QUEUE.CPP 186 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561
  1. //
  2. // Copyright 2020 Electronic Arts Inc.
  3. //
  4. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
  5. // software: you can redistribute it and/or modify it under the terms of
  6. // the GNU General Public License as published by the Free Software Foundation,
  7. // either version 3 of the License, or (at your option) any later version.
  8. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
  9. // in the hope that it will be useful, but with permitted additional restrictions
  10. // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  11. // distributed with this program. You should have received a copy of the
  12. // GNU General Public License along with permitted additional restrictions
  13. // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
  14. /* $Header: /counterstrike/QUEUE.CPP 6 3/14/97 5:12p Steve_tall $ */
  15. /***************************************************************************
  16. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  17. * *
  18. * Project Name : Command & Conquer *
  19. * *
  20. * File Name : QUEUE.CPP *
  21. * *
  22. * Programmer : Bill R. Randolph *
  23. * *
  24. * Start Date : 11/28/95 *
  25. * *
  26. * Last Update : October 14, 1996 [BRR] *
  27. * *
  28. *-------------------------------------------------------------------------*
  29. * Functions for Queueing Events: *
  30. * Queue_Mission -- Queue a mega mission event. *
  31. * Queue_Options -- Queue the options event. *
  32. * Queue_Exit -- Add the exit game event to the queue. *
  33. * *
  34. * Functions for processing Queued Events: *
  35. * Queue_AI -- Process all queued events. *
  36. * Queue_AI_Normal -- Process all queued events. *
  37. * Queue_AI_Multiplayer -- Process all queued events. *
  38. * *
  39. * Main Multiplayer Queue Logic: *
  40. * Wait_For_Players -- Waits for other systems to come on-line *
  41. * Generate_Timing_Event -- computes & queues a RESPONSE_TIME event *
  42. * Process_Send_Period -- timing for sending packets every 'n' frames *
  43. * Send_Packets -- sends out events from the OutList *
  44. * Send_FrameSync -- Sends a FRAMESYNC packet *
  45. * Process_Receive_Packet -- processes an incoming packet *
  46. * Process_Serial_Packet -- Handles an incoming serial packet *
  47. * Can_Advance -- determines if it's OK to advance to the next frame *
  48. * Process_Reconnect_Dialog -- processes the reconnection dialog *
  49. * Handle_Timeout -- attempts to reconnect; if fails, bails. *
  50. * Stop_Game -- stops the game *
  51. * *
  52. * Packet Compression / Decompression: *
  53. * Build_Send_Packet -- Builds a big packet from a bunch of little ones. *
  54. * Add_Uncompressed_Events -- adds uncompressed events to a packet *
  55. * Add_Compressed_Events -- adds compressed events to a packet *
  56. * Breakup_Receive_Packet -- Splits a big packet into little ones. *
  57. * Extract_Uncompressed_Events -- extracts events from a packet *
  58. * Extract_Compressed_Events -- extracts events from a packet *
  59. * *
  60. * DoList Management: *
  61. * Execute_DoList -- Executes commands from the DoList *
  62. * Clean_DoList -- Cleans out old events from the DoList *
  63. * Queue_Record -- Records the DoList to disk *
  64. * Queue_Playback -- plays back queue entries from a record file *
  65. * *
  66. * Debugging: *
  67. * Compute_Game_CRC -- Computes a CRC value of the entire game. *
  68. * Add_CRC -- Adds a value to a CRC *
  69. * Print_CRCs -- Prints a data file for finding Sync Bugs *
  70. * Init_Queue_Mono -- inits mono display *
  71. * Update_Queue_Mono -- updates mono display *
  72. * Print_Framesync_Values -- displays frame-sync variables *
  73. * Check_Mirror -- Checks mirror memory *
  74. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  75. #include "function.h"
  76. #ifdef WOLAPI_INTEGRATION
  77. //#include "WolDebug.h"
  78. #include "WolapiOb.h"
  79. extern WolapiObject* pWolapi;
  80. bool bReconnectDialogCancelled;
  81. #endif
  82. /********************************** Defines *********************************/
  83. #define SHOW_MONO 0
  84. /********************************** Globals *********************************/
  85. //---------------------------------------------------------------------------
  86. // GameCRC is the current computed CRC value for this frame.
  87. // CRC[] is a record of our last 32 game CRC's.
  88. // ColorNames is for debug output in Print_CRCs
  89. //---------------------------------------------------------------------------
  90. static unsigned long GameCRC;
  91. static unsigned long CRC[32] =
  92. {0,0,0,0,0,0,0,0,0,0,
  93. 0,0,0,0,0,0,0,0,0,0,
  94. 0,0,0,0,0,0,0,0,0,0,
  95. 0,0};
  96. static char *ColorNames[8] = {
  97. "Yellow",
  98. "LtBlue",
  99. "Red",
  100. "Green",
  101. "Orange",
  102. "Grey",
  103. "Blue",
  104. "Brown"
  105. };
  106. //...........................................................................
  107. // Mono debugging variables:
  108. // NetMonoMode: 0 = show connection output, 1 = flowcount output
  109. // NewMonoMode: set by anything that toggles NetMonoMode; re-inits screen
  110. // IsMono: used for taking control of Mono screen away from the engine
  111. //...........................................................................
  112. int NetMonoMode = 1;
  113. int NewMonoMode = 1;
  114. static int IsMono = 0;
  115. //---------------------------------------------------------------------------
  116. // Several routines return various codes; here's an enum for all of them.
  117. //---------------------------------------------------------------------------
  118. typedef enum RetcodeEnum {
  119. RC_NORMAL, // no news is good news
  120. RC_PLAYER_READY, // a new player has been heard from
  121. RC_SCENARIO_MISMATCH, // scenario mismatch
  122. RC_DOLIST_FULL, // DoList is full
  123. RC_SERIAL_PROCESSED, // modem: SERIAL packet was processed
  124. RC_PLAYER_LEFT, // modem: other player left the game
  125. RC_HUNG_UP, // modem has hung up
  126. RC_NOT_RESPONDING, // other player not responding (timeout/hung up)
  127. RC_CANCEL, // user cancelled
  128. } RetcodeType;
  129. #ifdef FIXIT_CSII // checked - ajw 9/28/98
  130. extern void Enable_Secret_Units(void);
  131. #endif
  132. /********************************* Prototypes *******************************/
  133. //...........................................................................
  134. // Main multiplayer queue logic
  135. //...........................................................................
  136. static void Queue_AI_Normal(void);
  137. static void Queue_AI_Multiplayer(void);
  138. static RetcodeType Wait_For_Players(int first_time, ConnManClass *net,
  139. int resend_delta, int dialog_time, int timeout, char *multi_packet_buf,
  140. int my_sent, long *their_frame, unsigned short *their_sent,
  141. unsigned short *their_recv);
  142. static void Generate_Timing_Event(ConnManClass *net, int my_sent);
  143. static void Generate_Real_Timing_Event(ConnManClass *net, int my_sent);
  144. static void Generate_Process_Time_Event(ConnManClass *net);
  145. static int Process_Send_Period(ConnManClass *net); //, int init);
  146. static int Send_Packets(ConnManClass *net, char *multi_packet_buf,
  147. int multi_packet_max, int max_ahead, int my_sent);
  148. static void Send_FrameSync(ConnManClass *net, int cmd_count);
  149. static RetcodeType Process_Receive_Packet(ConnManClass *net,
  150. char *multi_packet_buf, int id, int packetlen, long *their_frame,
  151. unsigned short *their_sent, unsigned short *their_recv);
  152. static RetcodeType Process_Serial_Packet(char *multi_packet_buf,
  153. int first_time);
  154. static int Can_Advance(ConnManClass *net, int max_ahead, long *their_frame,
  155. unsigned short *their_sent, unsigned short *their_recv);
  156. static int Process_Reconnect_Dialog(CDTimerClass<SystemTimerClass> *timeout_timer,
  157. long *their_frame, int num_conn, int reconn, int fresh);
  158. static int Handle_Timeout(ConnManClass *net, long *their_frame,
  159. unsigned short *their_sent, unsigned short *their_recv);
  160. static void Stop_Game(void);
  161. //...........................................................................
  162. // Packet compression/decompression:
  163. //...........................................................................
  164. static int Build_Send_Packet(void *buf, int bufsize, int frame_delay,
  165. int num_cmds, int cap);
  166. int Add_Uncompressed_Events(void *buf, int bufsize, int frame_delay, int size,
  167. int cap);
  168. int Add_Compressed_Events(void *buf, int bufsize, int frame_delay, int size,
  169. int cap);
  170. static int Breakup_Receive_Packet(void *buf, int bufsize );
  171. int Extract_Uncompressed_Events(void *buf, int bufsize);
  172. int Extract_Compressed_Events(void *buf, int bufsize);
  173. //...........................................................................
  174. // DoList management:
  175. //...........................................................................
  176. static int Execute_DoList(int max_houses, HousesType base_house,
  177. ConnManClass *net, CDTimerClass<FrameTimerClass> *skip_crc,
  178. // ConnManClass *net, TCountDownTimerClass *skip_crc,
  179. long *their_frame, unsigned short *their_sent, unsigned short *their_recv);
  180. static void Clean_DoList(ConnManClass *net);
  181. static void Queue_Record(void);
  182. static void Queue_Playback(void);
  183. //...........................................................................
  184. // Debugging:
  185. //...........................................................................
  186. static void Compute_Game_CRC(void);
  187. void Add_CRC(unsigned long *crc, unsigned long val);
  188. static void Print_CRCs(EventClass *ev);
  189. static void Init_Queue_Mono(ConnManClass *net);
  190. static void Update_Queue_Mono(ConnManClass *net, int flow_index);
  191. static void Print_Framesync_Values(long curframe, unsigned long max_ahead,
  192. int num_connections, unsigned short *their_recv,
  193. unsigned short *their_sent, unsigned short my_sent);
  194. extern void Keyboard_Process(KeyNumType &input);
  195. void Dump_Packet_Too_Late_Stuff(EventClass *event, ConnManClass *net,
  196. long *their_frame, unsigned short *their_sent, unsigned short *their_recv);
  197. void Check_Mirror(void);
  198. /***************************************************************************
  199. * Queue_Mission -- Queue a mega mission event. *
  200. * *
  201. * This routine is called when the player causes a change to a game unit. *
  202. * The event that initiates the change is queued to as a result of a call *
  203. * to this routine. *
  204. * *
  205. * INPUT: *
  206. * whom Whom this mission request applies to (a friendly unit). *
  207. * mission The mission to assign to this object. *
  208. * target The target of this mission (if any). *
  209. * dest The movement destination for this mission (if any). *
  210. * *
  211. * OUTPUT: *
  212. * Was the mission request queued successfully? *
  213. * *
  214. * WARNINGS: *
  215. * none. *
  216. * *
  217. * HISTORY: *
  218. * 09/21/1995 JLB : Created. *
  219. *=========================================================================*/
  220. bool Queue_Mission(TargetClass whom, MissionType mission, TARGET target, TARGET destination)
  221. {
  222. if (! OutList.Add(EventClass(whom, mission, TargetClass(target), TargetClass(destination)))) {
  223. return(false);
  224. } else {
  225. return(true);
  226. }
  227. }
  228. /***********************************************************************************************
  229. * Queue_Mission -- Queue a mega mission event, formation override for common speed. *
  230. * *
  231. * This routine is called when the player causes a change to a game unit. The event that *
  232. * initiates the change is queued to as a result of a call to this routine. *
  233. * *
  234. * INPUT: whom -- Whom this mission request applies to (a friendly unit). *
  235. * *
  236. * mission -- The mission to assign to this object. *
  237. * *
  238. * target -- The target of this mission (if any). *
  239. * *
  240. * dest -- The movement destination for this mission (if any). *
  241. * *
  242. * speed -- The override speed for this unit. *
  243. * *
  244. * maxspeed -- The override maximum speed for this unit. *
  245. * *
  246. * OUTPUT: Was the mission request queued successfully? *
  247. * *
  248. * WARNINGS: none *
  249. * *
  250. * HISTORY: *
  251. * 09/21/1995 JLB : Created. *
  252. *=============================================================================================*/
  253. bool Queue_Mission(TargetClass whom, MissionType mission, TARGET target, TARGET destination, SpeedType speed, MPHType maxspeed)
  254. {
  255. if (! OutList.Add(EventClass(whom, mission, TargetClass(target), TargetClass(destination), speed, maxspeed))) {
  256. return(false);
  257. } else {
  258. return(true);
  259. }
  260. }
  261. /***************************************************************************
  262. * Queue_Options -- Queue the options event. *
  263. * *
  264. * INPUT: *
  265. * none. *
  266. * *
  267. * OUTPUT: *
  268. * Was the options screen event queued successfully? *
  269. * *
  270. * WARNINGS: *
  271. * none. *
  272. * *
  273. * HISTORY: *
  274. * 09/21/1995 JLB : Created. *
  275. *=========================================================================*/
  276. bool Queue_Options(void)
  277. {
  278. if (! OutList.Add(EventClass(EventClass::OPTIONS))) {
  279. return(false);
  280. }
  281. else {
  282. return(true);
  283. }
  284. } /* end of Queue_Options */
  285. /***************************************************************************
  286. * Queue_Exit -- Add the exit game event to the queue. *
  287. * *
  288. * INPUT: *
  289. * none. *
  290. * *
  291. * OUTPUT: *
  292. * Was the exit event queued successfully? *
  293. * *
  294. * WARNINGS: *
  295. * none. *
  296. * *
  297. * HISTORY: *
  298. * 09/21/1995 JLB : Created. *
  299. *=========================================================================*/
  300. bool Queue_Exit(void)
  301. {
  302. if (! OutList.Add(EventClass(EventClass::EXIT))) {
  303. return(false);
  304. }
  305. else {
  306. return(true);
  307. }
  308. } /* end of Queue_Exit */
  309. /***************************************************************************
  310. * Queue_AI -- Process all queued events. *
  311. * *
  312. * INPUT: *
  313. * none. *
  314. * *
  315. * OUTPUT: *
  316. * none. *
  317. * *
  318. * WARNINGS: *
  319. * none. *
  320. * *
  321. * HISTORY: *
  322. * 09/21/1995 JLB : Created. *
  323. *=========================================================================*/
  324. void Queue_AI(void)
  325. {
  326. if (Session.Play) {
  327. Queue_Playback();
  328. }
  329. else {
  330. switch (Session.Type) {
  331. case GAME_SKIRMISH:
  332. case GAME_NORMAL:
  333. Queue_AI_Normal();
  334. break;
  335. case GAME_MODEM:
  336. case GAME_NULL_MODEM:
  337. case GAME_IPX:
  338. case GAME_INTERNET:
  339. case GAME_TEN:
  340. case GAME_MPATH:
  341. Queue_AI_Multiplayer();
  342. break;
  343. }
  344. }
  345. } /* end of Queue_AI */
  346. /***************************************************************************
  347. * Queue_AI_Normal -- Process all queued events. *
  348. * *
  349. * This is the "normal" version of the queue management routine. It does *
  350. * the following: *
  351. * - Transfers items in the OutList to the DoList *
  352. * - Executes any commands in the DoList that are supposed to be done on *
  353. * this frame # *
  354. * - Cleans out the DoList *
  355. * *
  356. * INPUT: *
  357. * none. *
  358. * *
  359. * OUTPUT: *
  360. * none. *
  361. * *
  362. * WARNINGS: *
  363. * none. *
  364. * *
  365. * HISTORY: *
  366. * 09/21/1995 JLB : Created. *
  367. *=========================================================================*/
  368. static void Queue_AI_Normal(void)
  369. {
  370. //------------------------------------------------------------------------
  371. // Move events from the OutList (events generated by this player) into the
  372. // DoList (the list of events to execute).
  373. //------------------------------------------------------------------------
  374. while (OutList.Count) {
  375. OutList.First().IsExecuted = false;
  376. if (!DoList.Add(OutList.First())) {
  377. ;
  378. }
  379. #ifdef MIRROR_QUEUE
  380. MirrorList.Add(OutList.First());
  381. #endif
  382. OutList.Next();
  383. }
  384. //------------------------------------------------------------------------
  385. // Save the DoList to disk, if we're in "Record" mode
  386. //------------------------------------------------------------------------
  387. if (Session.Record) {
  388. Queue_Record();
  389. }
  390. //------------------------------------------------------------------------
  391. // Execute the DoList; if an error occurs, bail out.
  392. //------------------------------------------------------------------------
  393. if (!Execute_DoList(1, PlayerPtr->Class->House, NULL, NULL, NULL,
  394. NULL, NULL)) {
  395. GameActive = 0;
  396. return;
  397. }
  398. //------------------------------------------------------------------------
  399. // Clean out the DoList
  400. //------------------------------------------------------------------------
  401. Clean_DoList(NULL);
  402. } /* end of Queue_AI_Normal */
  403. /***************************************************************************
  404. * Queue_AI_Multiplayer -- Process all queued events. *
  405. * *
  406. * This is the network version of the queue management routine. It does *
  407. * the following: *
  408. * - If this is the 1st frame, waits for other systems to signal ready *
  409. * - Generates a timing event, to allow the connection time to be dynamic *
  410. * - Handles timing related to sending packets every 'n' frames *
  411. * - Sends outgoing events *
  412. * - Frame-syncs to the other systems (see below) *
  413. * - Executes & cleans out the DoList *
  414. * *
  415. * The Frame-Sync'ing logic is the heart & soul of network play. It works *
  416. * by ensuring that any system won't out-run the other system by more than *
  417. * 'Session.MaxAhead' frames; this in turn ensures that a packet's *
  418. * execution frame # won't have been passed by the time that packet is *
  419. * received by all systems. *
  420. * *
  421. * To achieve this, the system must keep track of all other system's *
  422. * current frame #'s; these are stored in an array called 'their_frame[]'. *
  423. * However, because current frame #'s are sent in FRAMEINFO packets, which *
  424. * don't require an ACK, and command packets are sent in packets requiring *
  425. * an ACK, it's possible for a command packet to get lost, and the next *
  426. * frame's FRAMEINFO packet to not get lost; the other system may then *
  427. * advance past the frame # the command is to execute on! So, to prevent *
  428. * this, all FRAMEINFO packets include a CommandCount field. This value *
  429. * tells the other system how many events it should have received by this *
  430. * time. This system can therefore keep track of how many commands it's *
  431. * actually received, and compare it to the CommandCount field, to see if *
  432. * it's missed an event packet. The # of events we've received from each *
  433. * system is stored in 'their_recv[]', and the # events they say they've *
  434. * sent is stored in 'their_sent[]'. *
  435. * *
  436. * Thus, two conditions must be met in order to advance to the next frame: *
  437. * - Our current frame # must be < their_frame + Session.MaxAhead *
  438. * - their_recv[i] must be >= their_sent[i] *
  439. * *
  440. * 'their_frame[] is updated by Process_Receive_Packet() *
  441. * 'their_recv[] is updated by Process_Receive_Packet() *
  442. * 'their_sent[] is updated by Process_Receive_Packet() *
  443. * 'my_sent' is updated by this routine. *
  444. * *
  445. * The order of the arrays their_frame[] etc is the same order the *
  446. * connections are created in. The Sender's ID is passed to *
  447. * Connection_Index() to obtain the array index. *
  448. * *
  449. * The only routines allowed to pop up dialogs are: *
  450. * Wait_For_Players() (only pops up the reconnect dialog) *
  451. * Execute_DoList() (tells if out of sync, or packet recv'd too late) *
  452. * *
  453. * Sign-off's are detected by: *
  454. * - Timing out while waiting for a packet *
  455. * - Detecting that the other player is now at the score screen or *
  456. * connection dialog (serial) *
  457. * - If we see an EventClass::EXIT event on the private channel *
  458. * *
  459. * The current communications protocol, COMM_PROTOCOL_MULTI_E_COMP, has *
  460. * the following properties: *
  461. * - It compresses packets, so that the minimum number of bytes are *
  462. * transmitted. Packets are compressed by extracting all info common to *
  463. * the events into the packet header, and then sending only the bytes *
  464. * relevant to each type of event. For instance, if 100 infantry guys *
  465. * are told to move to the same location, the command itself & the *
  466. * location will be included in the 1st movement command only; after *
  467. * that, there will be a rep count then 99 infantry TARGET numbers, *
  468. * identifying all the infantry told to move. *
  469. * - The protocol also only sends packets out every 'n' frames. This cuts *
  470. * the data rate dramatically. It means that 'Session.MaxAhead' must be *
  471. * divisible by 'n'; also, the minimum value for 'Session.MaxAhead' is *
  472. * 'n * 2', to give both sides some "breathing" room in case a FRAMEINFO *
  473. * packet gets missed. *
  474. * *
  475. * Note: For synchronization-waiting loops (like waiting to hear from all *
  476. * other players, waiting to advance to the next frame, etc), use *
  477. * Net.Num_Connections() rather than Session.NumPlayers; this reflects the *
  478. * actual # of connections, and can be "faked" into playing even when *
  479. * there aren't any other players actually there. A typical example of *
  480. * this is playing back a recorded game. For command-execution loops, use *
  481. * Session.NumPlayers. This ensures all commands get executed, even if *
  482. * there isn't a human generating those commands. *
  483. * *
  484. * The modem works a little differently from the network in this respect: *
  485. * - The connection has to stay "alive" even if the other player exits to *
  486. * the join dialog. This prevents each system from timing out & hanging *
  487. * the modem up. Thus, packets are sent back & forth & just thrown away,*
  488. * but each system knows the other is still there. Messages may be sent *
  489. * between systems, though. *
  490. * - Destroy_Null_Connection doesn't hang up the modem, so *
  491. * Num_Connections() still reports a value of 1 even though the other *
  492. * player has left. *
  493. * - Any waits on Num_Connections() must also check for *
  494. * Session.NumPlayers > 1, to keep from waiting forever if the other *
  495. * guy has left *
  496. * - Packets sent to a player who's left require no ACK *
  497. * *
  498. * INPUT: *
  499. * none. *
  500. * *
  501. * OUTPUT: *
  502. * none. *
  503. * *
  504. * WARNINGS: *
  505. * none. *
  506. * *
  507. * HISTORY: *
  508. * 11/21/1995 BRR : Created. *
  509. *=========================================================================*/
  510. static void Queue_AI_Multiplayer(void)
  511. {
  512. if(Session.Type == GAME_SKIRMISH) return;
  513. return;
  514. #if (0)//PG
  515. //........................................................................
  516. // Enums:
  517. //........................................................................
  518. enum {
  519. MIXFILE_RESEND_DELTA = 120, // ticks b/w resends
  520. MIXFILE_TIMEOUT = 3600*2, // timeout waiting for mixfiles.
  521. FRAMESYNC_DLG_TIME = (3*60), // time until displaying reconnect dialog
  522. FRAMESYNC_TIMEOUT = (15*60), // timeout waiting for frame sync packet
  523. };
  524. int timeout_factor = (Session.Type == GAME_INTERNET) ? 6 : 1;
  525. //........................................................................
  526. // Variables for sending, receiving & parsing packets:
  527. //........................................................................
  528. ConnManClass *net; // ptr to access all multiplayer functions
  529. EventClass packet; // for sending single frame-sync's
  530. char *multi_packet_buf; // buffer for sending/receiving
  531. int multi_packet_max; // max length of multi_packet_buf
  532. //........................................................................
  533. // Frame-sync'ing variables
  534. //........................................................................
  535. static long
  536. their_frame[MAX_PLAYERS - 1]; // other players' frame #'s
  537. static unsigned short
  538. their_sent[MAX_PLAYERS - 1]; // # cmds other player claims to have sent
  539. static unsigned short
  540. their_recv[MAX_PLAYERS - 1]; // # cmds actually received from others
  541. static unsigned short
  542. my_sent; // # cmds I've sent out
  543. //........................................................................
  544. // Timing variables
  545. //........................................................................
  546. static CDTimerClass<FrameTimerClass> skip_crc; // to delay the CRC check
  547. // static TCountDownTimerClass skip_crc; // to delay the CRC check
  548. //........................................................................
  549. // Other misc variables
  550. //........................................................................
  551. int i;
  552. RetcodeType rc;
  553. int reconnect_dlg = 0; // 1 = the reconnect dialog is displayed
  554. //------------------------------------------------------------------------
  555. // Initialize the packet buffer pointer & its max size
  556. //------------------------------------------------------------------------
  557. #if (0)//PG
  558. if (Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) {
  559. multi_packet_buf = NullModem.BuildBuf;
  560. multi_packet_max = NullModem.MaxLen - sizeof (CommHeaderType);
  561. net = &NullModem;
  562. } else if (Session.Type == GAME_IPX || Session.Type == GAME_INTERNET) {
  563. multi_packet_buf = Session.MetaPacket;
  564. multi_packet_max = Session.MetaSize;
  565. net = &Ipx;
  566. }
  567. #endif
  568. #if(TEN)
  569. else if (Session.Type == GAME_TEN) {
  570. multi_packet_buf = Session.TenPacket;
  571. multi_packet_max = Session.TenSize;
  572. net = Ten;
  573. }
  574. #endif
  575. #if(MPATH)
  576. else if (Session.Type == GAME_MPATH) {
  577. multi_packet_buf = Session.MPathPacket;
  578. multi_packet_max = Session.MPathSize;
  579. net = MPath;
  580. }
  581. #endif
  582. //------------------------------------------------------------------------
  583. // Debug stuff
  584. //------------------------------------------------------------------------
  585. Init_Queue_Mono(net);
  586. Update_Queue_Mono (net, 0);
  587. //------------------------------------------------------------------------
  588. // Compute the Game's CRC
  589. //------------------------------------------------------------------------
  590. Compute_Game_CRC();
  591. CRC[Frame & 0x001f] = GameCRC;
  592. //------------------------------------------------------------------------
  593. // If we've just started a game, or loaded a multiplayer game, we must
  594. // wait for all other systems to signal ready.
  595. //------------------------------------------------------------------------
  596. if (Frame==0 || Session.LoadGame) {
  597. //.....................................................................
  598. // Initialize static locals
  599. //.....................................................................
  600. for (i = 0; i < MAX_PLAYERS - 1; i++) {
  601. their_frame[i] = -1;
  602. their_sent[i] = 0;
  603. their_recv[i] = 0;
  604. }
  605. my_sent = 0;
  606. #ifdef FIXIT_MULTI_SAVE
  607. skip_crc = 32;
  608. #else
  609. skip_crc = Frame + 32;
  610. #endif // FIXIT_MULTI_SAVE
  611. for (i = 0; i < 32; i++)
  612. CRC[i] = 0;
  613. //.....................................................................
  614. // If we've loaded a saved game:
  615. // - If this game was saved as the result of a lost connection, clear
  616. // the CRC value so it will always match the other system's
  617. // - Otherwise, use the GameCRC value, so we'll compare save-game files
  618. // rather than scenario INI files
  619. //.....................................................................
  620. if (Session.LoadGame) {
  621. if (Session.EmergencySave)
  622. ScenarioCRC = 0;
  623. else
  624. ScenarioCRC = GameCRC;
  625. }
  626. //.....................................................................
  627. // Send our initial FRAMESYNC packet
  628. //.....................................................................
  629. Send_FrameSync(net, my_sent);
  630. //.....................................................................
  631. // Wait for the other guys
  632. //.....................................................................
  633. rc = Wait_For_Players (1, net, MIXFILE_RESEND_DELTA, FRAMESYNC_DLG_TIME*timeout_factor,
  634. MIXFILE_TIMEOUT, multi_packet_buf, my_sent, their_frame,
  635. their_sent, their_recv);
  636. if (rc != RC_NORMAL) {
  637. #ifdef WIN32
  638. if (Session.Type == GAME_INTERNET){
  639. Register_Game_End_Time();
  640. }
  641. #endif //WIN32
  642. if (rc == RC_NOT_RESPONDING) {
  643. WWMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);
  644. }
  645. else if (rc == RC_SCENARIO_MISMATCH) {
  646. WWMessageBox().Process (TXT_SCENARIOS_DO_NOT_MATCH);
  647. }
  648. else if (rc == RC_DOLIST_FULL) {
  649. WWMessageBox().Process(TXT_QUEUE_FULL);
  650. }
  651. Stop_Game();
  652. return;
  653. }
  654. //.....................................................................
  655. // Re-initialize frame numbers (in case somebody signed off while I was
  656. // waiting for MIX files to load; we would have fallen through, but
  657. // their frame # would still be -1).
  658. //.....................................................................
  659. for (i = 0; i < MAX_PLAYERS - 1; i++)
  660. their_frame[i] = 0;
  661. //.....................................................................
  662. // Reset the network response time computation, now that we're both
  663. // sending data again (loading MIX files will have introduced
  664. // deceptively large values).
  665. //.....................................................................
  666. net->Reset_Response_Time();
  667. //.....................................................................
  668. // Initialize the frame timers
  669. //.....................................................................
  670. if (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {
  671. Process_Send_Period(net);//, 1);
  672. }
  673. //.....................................................................
  674. // Turn off our special load-game flags
  675. //.....................................................................
  676. if (Session.LoadGame) {
  677. Session.EmergencySave = false;
  678. Session.LoadGame = false;
  679. }
  680. } // end of Frame 0 wait
  681. //------------------------------------------------------------------------
  682. // Adjust connection timing parameters every 128 frames.
  683. //------------------------------------------------------------------------
  684. else if ( (Frame & 0x007f) == 0) {
  685. //
  686. // If we're using the new spiffy protocol, do proper timing handling.
  687. // If we're the net "master", compute our desired frame rate & new
  688. // 'MaxAhead' value.
  689. //
  690. if (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {
  691. //
  692. // All systems will transmit their required process time.
  693. //
  694. Generate_Process_Time_Event(net);
  695. //
  696. // The game "host" will transmit timing adjustment events.
  697. //
  698. if (Session.Am_I_Master()) {
  699. Generate_Real_Timing_Event(net, my_sent);
  700. }
  701. } else {
  702. //
  703. // For the older protocols, do the old broken timing handling.
  704. //
  705. Generate_Timing_Event(net, my_sent);
  706. }
  707. }
  708. //------------------------------------------------------------------------
  709. // Only process every 'FrameSendRate' frames
  710. //------------------------------------------------------------------------
  711. if (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {
  712. if (!Process_Send_Period(net)) { //, 0)) {
  713. if (IsMono) {
  714. MonoClass::Disable();
  715. }
  716. return;
  717. }
  718. }
  719. //------------------------------------------------------------------------
  720. // Send our data packet(s); update my command-sent counter
  721. //------------------------------------------------------------------------
  722. my_sent += Send_Packets(net, multi_packet_buf, multi_packet_max,
  723. Session.MaxAhead, my_sent);
  724. //------------------------------------------------------------------------
  725. // If this is our first time through, we're done.
  726. //------------------------------------------------------------------------
  727. if (Frame==0) {
  728. if (IsMono) {
  729. MonoClass::Disable();
  730. }
  731. return;
  732. }
  733. //------------------------------------------------------------------------
  734. // Frame-sync'ing: wait until it's OK to advance to the next frame.
  735. //------------------------------------------------------------------------
  736. #ifdef FIXIT_VERSION_3
  737. int iFramesyncTimeout;
  738. if( Session.Type == GAME_INTERNET && pWolapi && pWolapi->GameInfoCurrent.iPlayerCount > 2 )
  739. // Shortened resync timeout for non-2 player games.
  740. iFramesyncTimeout = 5 * 60; // One minute.
  741. else
  742. iFramesyncTimeout = FRAMESYNC_TIMEOUT;
  743. rc = Wait_For_Players (0, net,
  744. (Session.MaxAhead << 3),
  745. MAX ( net->Response_Time() * 3, FRAMESYNC_DLG_TIME*timeout_factor ),
  746. iFramesyncTimeout * (2*timeout_factor),
  747. multi_packet_buf, my_sent, their_frame,
  748. their_sent, their_recv);
  749. #else
  750. rc = Wait_For_Players (0, net,
  751. (Session.MaxAhead << 3),
  752. MAX ( net->Response_Time() * 3, FRAMESYNC_DLG_TIME*timeout_factor ),
  753. FRAMESYNC_TIMEOUT* (2*timeout_factor),
  754. multi_packet_buf, my_sent, their_frame,
  755. their_sent, their_recv);
  756. #endif
  757. if (rc != RC_NORMAL) {
  758. #ifdef WIN32
  759. if (Session.Type == GAME_INTERNET){
  760. Register_Game_End_Time();
  761. #ifdef WOLAPI_INTEGRATION
  762. // New rule - if you cancel a waiting to reconnect dialog, you lose.
  763. bReconnectDialogCancelled = ( rc == RC_CANCEL );
  764. #endif
  765. }
  766. #endif //WIN32
  767. if (rc == RC_NOT_RESPONDING) {
  768. WWMessageBox().Process (TXT_SYSTEM_NOT_RESPONDING);
  769. }
  770. else if (rc == RC_SCENARIO_MISMATCH) {
  771. WWMessageBox().Process (TXT_SCENARIOS_DO_NOT_MATCH);
  772. }
  773. else if (rc == RC_DOLIST_FULL) {
  774. WWMessageBox().Process(TXT_QUEUE_FULL);
  775. }
  776. Stop_Game();
  777. return;
  778. }
  779. //------------------------------------------------------------------------
  780. // Save the DoList to disk, if we're in "Record" mode
  781. //------------------------------------------------------------------------
  782. if (Session.Record) {
  783. Queue_Record();
  784. }
  785. //------------------------------------------------------------------------
  786. // Execute the DoList; if an error occurs, bail out.
  787. //------------------------------------------------------------------------
  788. if (!Execute_DoList(Session.MaxPlayers, HOUSE_MULTI1, net, &skip_crc,
  789. their_frame, their_sent, their_recv)) {
  790. #ifdef WIN32
  791. if (Session.Type == GAME_INTERNET){
  792. Register_Game_End_Time();
  793. }
  794. #endif //WIN32
  795. Stop_Game();
  796. return;
  797. }
  798. //------------------------------------------------------------------------
  799. // Clean out the DoList
  800. //------------------------------------------------------------------------
  801. Clean_DoList(net);
  802. if (IsMono) {
  803. MonoClass::Disable();
  804. }
  805. #endif
  806. } // end of Queue_AI_Multiplayer
  807. /***************************************************************************
  808. * Wait_For_Players -- Waits for other systems to come on-line *
  809. * *
  810. * This routine performs the most critical logic in multiplayer; that of *
  811. * synchronizing my frame number with those of the other systems. *
  812. * *
  813. * INPUT: *
  814. * first_time 1 = 1st time this routine is called *
  815. * net ptr to connection manager *
  816. * resend_delta time (ticks) between FRAMESYNC resends *
  817. * dialog_time time (ticks) until pop up a reconnect dialog *
  818. * timeout time (ticks) until we give up the ghost *
  819. * multi_packet_buf buffer to store packets in *
  820. * my_sent # commands I've sent so far *
  821. * their_frame array of their frame #'s *
  822. * their_sent array of their CommandCount values *
  823. * their_recv array of # cmds I've received from them *
  824. * *
  825. * OUTPUT: *
  826. * RC_NORMAL OK to advance to the next frame *
  827. * RC_CANCEL user hit 'Cancel' at the timeout countdown dlg *
  828. * RC_NOT_RESPONDING other player(s) not responding *
  829. * RC_SCENARIO_MISMATCH scenario's don't match (first_time only) *
  830. * RC_DOLIST_FULL DoList was full *
  831. * *
  832. * WARNINGS: *
  833. * none. *
  834. * *
  835. * HISTORY: *
  836. * 11/21/1995 BRR : Created. *
  837. *=========================================================================*/
  838. static RetcodeType Wait_For_Players(int first_time, ConnManClass *net,
  839. int resend_delta, int dialog_time, int timeout, char *multi_packet_buf,
  840. int my_sent, long *their_frame, unsigned short *their_sent,
  841. unsigned short *their_recv)
  842. {
  843. //........................................................................
  844. // Variables for sending, receiving & parsing packets:
  845. //........................................................................
  846. EventClass *event; // event ptr for parsing incoming packets
  847. int packetlen; // size of meta-packet sent, & received
  848. int id; // id of other player
  849. int messages_this_loop; // to limit # messages processed each loop
  850. int message_limit; // max # messages we'll read each frame
  851. //........................................................................
  852. // Variables used only if 'first_time':
  853. //........................................................................
  854. int num_ready; // # players signalling ready
  855. //........................................................................
  856. // Timing variables
  857. //........................................................................
  858. CDTimerClass<SystemTimerClass> retry_timer; // time between FRAMESYNC packet resends
  859. CDTimerClass<SystemTimerClass> dialog_timer; // time to pop up a dialog
  860. CDTimerClass<SystemTimerClass> timeout_timer; // general-purpose timeout
  861. //........................................................................
  862. // Dialog variables
  863. //........................................................................
  864. int reconnect_dlg = 0; // 1 = the reconnect dialog is displayed
  865. //........................................................................
  866. // Other misc variables
  867. //........................................................................
  868. KeyNumType input; // for user input
  869. int x,y; // for map input
  870. RetcodeType rc;
  871. //------------------------------------------------------------------------
  872. // Wait to hear from all other players
  873. //------------------------------------------------------------------------
  874. num_ready = 0;
  875. retry_timer = resend_delta; // time to retry
  876. dialog_timer = dialog_time; // time to show dlg
  877. timeout_timer = timeout; // time to bail out
  878. while (1) {
  879. Keyboard->Check();
  880. Update_Queue_Mono (net, 2);
  881. //---------------------------------------------------------------------
  882. // Resend a frame-sync packet if longer than one propagation delay goes
  883. // by; this prevents a "deadlock". If he's waiting for me to advance,
  884. // but has missed my last few FRAMEINFO packets, I may be waiting for
  885. // him to advance. Resending a FRAMESYNC ensures he knows what frame
  886. // number I'm on.
  887. //---------------------------------------------------------------------
  888. if (!retry_timer) {
  889. retry_timer = resend_delta; // time to retry
  890. Update_Queue_Mono (net, 3);
  891. Send_FrameSync(net, my_sent);
  892. }
  893. //---------------------------------------------------------------------
  894. // Service the connections
  895. //---------------------------------------------------------------------
  896. net->Service();
  897. //---------------------------------------------------------------------
  898. // Pop up a reconnect dialog if enough time goes by
  899. //---------------------------------------------------------------------
  900. if (!dialog_timer && SpecialDialog==SDLG_NONE) {
  901. if (reconnect_dlg == 0 && first_time == 0) {
  902. FILE *fp;
  903. int i;
  904. HouseClass *housep;
  905. fp = fopen("recon.txt","wt");
  906. if (fp) {
  907. fprintf(fp,"# Connections: %d\n",net->Num_Connections());
  908. fprintf(fp," My Frame #: %d\n",Frame);
  909. for (i = 0; i < net->Num_Connections(); i++) {
  910. housep = HouseClass::As_Pointer((HousesType)(net->Connection_ID(i)));
  911. fprintf(fp,"%15s: Their Sent:%d Their Recv:%d Their Frame:%d\n",
  912. housep->IniName, their_sent[i], their_recv[i], their_frame[i]);
  913. }
  914. fclose(fp);
  915. }
  916. #ifdef WOLAPI_INTEGRATION
  917. // "Reconnecting" dialog is about to be shown.
  918. // At this point, begin wolapi "disconnect pinging", if appropriate.
  919. if( Session.Type == GAME_INTERNET && pWolapi && pWolapi->GameInfoCurrent.bTournament )
  920. pWolapi->Init_DisconnectPinging();
  921. #endif
  922. }
  923. if (Process_Reconnect_Dialog(&timeout_timer, their_frame, // (Returns immediately.)
  924. net->Num_Connections(), (first_time==0), (reconnect_dlg==0))) {
  925. return (RC_CANCEL);
  926. }
  927. reconnect_dlg = 1;
  928. #ifdef WOLAPI_INTEGRATION
  929. // Continue wolapi "disconnect pinging", if appropriate.
  930. if( Session.Type == GAME_INTERNET && pWolapi && pWolapi->bDoingDisconnectPinging )
  931. pWolapi->Pump_DisconnectPinging();
  932. #endif
  933. }
  934. //---------------------------------------------------------------------
  935. // Exit if too much time goes by (the other system has crashed or
  936. // bailed)
  937. //---------------------------------------------------------------------
  938. if (!timeout_timer) {
  939. //..................................................................
  940. // For the first-time run, just give up; something's wrong.
  941. //..................................................................
  942. if (first_time) {
  943. return (RC_NOT_RESPONDING);
  944. }
  945. //..................................................................
  946. // Otherwise, we're in the middle of a game; so, the modem &
  947. // network must deal with a timeout differently.
  948. //..................................................................
  949. else {
  950. Update_Queue_Mono (net, 4);
  951. if (Handle_Timeout(net, their_frame, their_sent, their_recv)) {
  952. Map.Flag_To_Redraw(true); // erase modem reconnect dialog
  953. Map.Render();
  954. retry_timer = resend_delta;
  955. dialog_timer = dialog_time;
  956. timeout_timer = timeout;
  957. }
  958. #ifdef FIXIT_MULTI_SAVE
  959. #ifdef FIXIT_VERSION_3
  960. else if ((Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) ) {
  961. #else
  962. else if ((Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) &&
  963. PlayingAgainstVersion != VERSION_RED_ALERT_104) {
  964. #endif
  965. if (WWMessageBox().Process (TXT_ASK_EMERGENCY_SAVE_NOT_RESPONDING,
  966. TXT_YES, TXT_NO, TXT_NONE) == 0) {
  967. Session.EmergencySave = 1;
  968. //printf("Saving emergency game; frame:%d, CRC:%d\n",Frame,GameCRC);
  969. //Print_CRCs(NULL);
  970. //printf("Before Save: Count1:%d, Count2:%d, Seed:%d\n",
  971. // Scen.RandomNumber.Count1,
  972. // Scen.RandomNumber.Count2,
  973. // Scen.RandomNumber.Seed);
  974. Save_Game(-1, (char *)Text_String(TXT_MULTIPLAYER_GAME));
  975. //printf("After Save: Count1:%d, Count2:%d, Seed:%d\n",
  976. // Scen.RandomNumber.Count1,
  977. // Scen.RandomNumber.Count2,
  978. // Scen.RandomNumber.Seed);
  979. Session.EmergencySave = 0;
  980. }
  981. return (RC_CANCEL);
  982. }
  983. #endif // FIXIT_MULTI_SAVE
  984. else {
  985. return (RC_NOT_RESPONDING);
  986. }
  987. }
  988. }
  989. //---------------------------------------------------------------------
  990. // Check for an incoming message. We must still process commands
  991. // even if 'first_time' is set, in case the other system got my 1st
  992. // FRAMESYNC, but I didn't get his; he'll be at the next frame, and
  993. // may be sending commands.
  994. // We have to limit the number of incoming messages we handle; it's
  995. // possible to go into an infinite loop processing modem messages.
  996. // (This feature is disabled for Ten; we need to keep the TCP buffers
  997. // clear, so we read all the packets we can every time.)
  998. //---------------------------------------------------------------------
  999. messages_this_loop = 0;
  1000. message_limit = 5;
  1001. if (Session.Type == GAME_TEN || Session.Type == GAME_MPATH) {
  1002. message_limit = 9999;
  1003. }
  1004. while ( (messages_this_loop++ < message_limit) &&
  1005. net->Get_Private_Message (multi_packet_buf, &packetlen, &id) ) {
  1006. Keyboard->Check();
  1007. Update_Queue_Mono (net, 5);
  1008. /*..................................................................
  1009. Get an event ptr to the incoming message
  1010. ..................................................................*/
  1011. event = (EventClass *)multi_packet_buf;
  1012. //------------------------------------------------------------------
  1013. // Special processing for a modem game: process SERIAL packets
  1014. //------------------------------------------------------------------
  1015. if (Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) {
  1016. rc = Process_Serial_Packet(multi_packet_buf, first_time);
  1017. //...............................................................
  1018. // SERIAL packet received & processed
  1019. //...............................................................
  1020. if (rc == RC_SERIAL_PROCESSED) {
  1021. net->Service();
  1022. retry_timer = resend_delta;
  1023. dialog_timer = dialog_time;
  1024. timeout_timer = timeout;
  1025. continue;
  1026. }
  1027. //...............................................................
  1028. // other player has left the game
  1029. //...............................................................
  1030. else if (rc == RC_PLAYER_LEFT) {
  1031. if (first_time) {
  1032. num_ready++;
  1033. }
  1034. break;
  1035. }
  1036. //...............................................................
  1037. // Connection was lost
  1038. //...............................................................
  1039. else if (rc == RC_HUNG_UP) {
  1040. #ifdef FIXIT_MULTI_SAVE
  1041. #ifndef FIXIT_VERSION_3
  1042. if (PlayingAgainstVersion != VERSION_RED_ALERT_104){
  1043. #endif
  1044. if (WWMessageBox().Process (TXT_ASK_EMERGENCY_SAVE_HUNG_UP,
  1045. TXT_YES, TXT_NO, TXT_NONE) == 0) {
  1046. Session.EmergencySave = 1;
  1047. //printf("Saving emergency game; frame:%d, CRC:%d\n",Frame,GameCRC);
  1048. //Print_CRCs(NULL);
  1049. //printf("Before Save: Count1:%d, Count2:%d, Seed:%d\n",
  1050. // Scen.RandomNumber.Count1,
  1051. // Scen.RandomNumber.Count2,
  1052. // Scen.RandomNumber.Seed);
  1053. Save_Game (-1, (char *)Text_String(TXT_MULTIPLAYER_GAME));
  1054. //printf("After Save: Count1:%d, Count2:%d, Seed:%d\n",
  1055. // Scen.RandomNumber.Count1,
  1056. // Scen.RandomNumber.Count2,
  1057. // Scen.RandomNumber.Seed);
  1058. Session.EmergencySave = 0;
  1059. }
  1060. return (RC_CANCEL);
  1061. #ifndef FIXIT_VERSION_3
  1062. }else{
  1063. return (RC_NOT_RESPONDING);
  1064. }
  1065. #endif
  1066. #else
  1067. return (RC_NOT_RESPONDING);
  1068. #endif // FIXIT_MULTI_SAVE
  1069. }
  1070. //...............................................................
  1071. // If it was any other type of serial packet, break
  1072. //...............................................................
  1073. else if (rc != RC_NORMAL) {
  1074. break;
  1075. }
  1076. }
  1077. //------------------------------------------------------------------
  1078. // Process the incoming packet
  1079. //------------------------------------------------------------------
  1080. rc = Process_Receive_Packet(net, multi_packet_buf, id, packetlen,
  1081. their_frame, their_sent, their_recv);
  1082. //..................................................................
  1083. // New player heard from
  1084. //..................................................................
  1085. if (rc == RC_PLAYER_READY) {
  1086. num_ready++;
  1087. }
  1088. //..................................................................
  1089. // Scenario's don't match
  1090. //..................................................................
  1091. else if (rc == RC_SCENARIO_MISMATCH) {
  1092. return (RC_SCENARIO_MISMATCH);
  1093. }
  1094. //..................................................................
  1095. // DoList was full
  1096. //..................................................................
  1097. else if (rc == RC_DOLIST_FULL) {
  1098. return (RC_DOLIST_FULL);
  1099. }
  1100. //..................................................................
  1101. // Service the connection, to clean out the receive queues
  1102. //..................................................................
  1103. net->Service();
  1104. }
  1105. //---------------------------------------------------------------------
  1106. // Debug output
  1107. //---------------------------------------------------------------------
  1108. Print_Framesync_Values(Frame, Session.MaxAhead, net->Num_Connections(),
  1109. their_recv, their_sent, my_sent);
  1110. //---------------------------------------------------------------------
  1111. // Attempt to advance to the next frame.
  1112. //---------------------------------------------------------------------
  1113. //.....................................................................
  1114. // For the first-time run, just check to see if we've heard from
  1115. // everyone.
  1116. //.....................................................................
  1117. if (first_time) {
  1118. if (num_ready >= net->Num_Connections()) {
  1119. break;
  1120. }
  1121. }
  1122. //.....................................................................
  1123. // For in-game processing, we have to check their_sent, their_recv,
  1124. // their_frame, etc.
  1125. //.....................................................................
  1126. else {
  1127. if (Can_Advance(net, Session.MaxAhead, their_frame, their_sent,
  1128. their_recv)) {
  1129. break;
  1130. }
  1131. }
  1132. //---------------------------------------------------------------------
  1133. // Service game stuff. Servicing the map's input, and rendering the
  1134. // map, allows the map to scroll even though we're hung up waiting for
  1135. // packets. Don't do this if 'first_time' is set, since users could be
  1136. // waiting a very long time for all systems to load the scenario, and
  1137. // it gets frustrating being able to scroll around without doing
  1138. // anything.
  1139. //---------------------------------------------------------------------
  1140. Call_Back();
  1141. if (!first_time && SpecialDialog == SDLG_NONE && reconnect_dlg==0) {
  1142. #ifdef WIN32
  1143. WWMouse->Erase_Mouse(&HidPage, TRUE);
  1144. #endif //WIN32
  1145. Map.Input(input, x, y);
  1146. if (input)
  1147. Keyboard_Process(input);
  1148. Map.Render();
  1149. }
  1150. } /* end of while */
  1151. //------------------------------------------------------------------------
  1152. // If the reconnect dialog was shown, force the map to redraw.
  1153. //------------------------------------------------------------------------
  1154. if (reconnect_dlg) {
  1155. Map.Flag_To_Redraw(true);
  1156. Map.Render();
  1157. }
  1158. return (RC_NORMAL);
  1159. } // end of Wait_For_Players
  1160. /***************************************************************************
  1161. * Generate_Timing_Event -- computes & queues a RESPONSE_TIME event *
  1162. * *
  1163. * This routine adjusts the connection timing on the local system; it also *
  1164. * optionally generates a RESPONSE_TIME event, to tell all systems to *
  1165. * dynamically adjust the current MaxAhead value. This allows both the *
  1166. * MaxAhead & the connection retry logic to have dynamic timing, to adjust *
  1167. * to varying line conditions. *
  1168. * *
  1169. * INPUT: *
  1170. * net ptr to connection manager *
  1171. * my_sent # commands I've sent out so far *
  1172. * *
  1173. * OUTPUT: *
  1174. * none. *
  1175. * *
  1176. * WARNINGS: *
  1177. * none. *
  1178. * *
  1179. * HISTORY: *
  1180. * 11/21/1995 BRR : Created. *
  1181. *=========================================================================*/
  1182. static void Generate_Timing_Event(ConnManClass *net, int my_sent)
  1183. {
  1184. unsigned long resp_time; // connection response time, in ticks
  1185. EventClass ev;
  1186. //
  1187. // For now, TEN & MPATH don't measure the net's response time, so there's
  1188. // no point in adjusting our timing. Do nothing.
  1189. //
  1190. if (Session.Type == GAME_TEN || Session.Type == GAME_MPATH) {
  1191. return;
  1192. }
  1193. //------------------------------------------------------------------------
  1194. // Measure the current connection response time. This time will be in
  1195. // 60ths of a second, and represents full round-trip time of a packet.
  1196. // To convert to one-way packet time, divide by 2; to convert to game
  1197. // frames, divide again by 4, assuming a game rate of 15 fps.
  1198. //------------------------------------------------------------------------
  1199. resp_time = net->Response_Time();
  1200. //------------------------------------------------------------------------
  1201. // Adjust my connection retry timing; only do this if I've sent out more
  1202. // than 5 commands, so I know I have a measure of the response time.
  1203. //------------------------------------------------------------------------
  1204. if (my_sent > 5) {
  1205. net->Set_Timing (resp_time + 10, -1, (resp_time * 4)+15);
  1206. //.....................................................................
  1207. // If I'm the network "master", I'm also responsible for updating the
  1208. // MaxAhead value on all systems, so do that here too.
  1209. //.....................................................................
  1210. if (Session.Am_I_Master()) {
  1211. ev.Type = EventClass::RESPONSE_TIME;
  1212. //..................................................................
  1213. // For multi-frame compressed events, the MaxAhead must be an even
  1214. // multiple of the FrameSendRate.
  1215. //..................................................................
  1216. if (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {
  1217. ev.Data.FrameInfo.Delay = max( ((((resp_time / 8) +
  1218. (Session.FrameSendRate - 1)) / Session.FrameSendRate) *
  1219. Session.FrameSendRate), (Session.FrameSendRate * 2) );
  1220. }
  1221. //..................................................................
  1222. // For sending packets every frame, just use the 1-way connection
  1223. // response time.
  1224. //..................................................................
  1225. else {
  1226. if (Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) {
  1227. ev.Data.FrameInfo.Delay = max( (resp_time / 8),
  1228. MODEM_MIN_MAX_AHEAD );
  1229. } else if (Session.Type == GAME_IPX || Session.Type == GAME_INTERNET) {
  1230. ev.Data.FrameInfo.Delay = max( (resp_time / 8),
  1231. NETWORK_MIN_MAX_AHEAD );
  1232. }
  1233. else if (Session.Type == GAME_TEN || Session.Type == GAME_MPATH) {
  1234. ev.Data.FrameInfo.Delay = max( (resp_time / 8),
  1235. MODEM_MIN_MAX_AHEAD );
  1236. }
  1237. }
  1238. OutList.Add(ev);
  1239. }
  1240. }
  1241. } // end of Generate_Timing_Event
  1242. /***************************************************************************
  1243. * Generate_Real_Timing_Event -- Generates a TIMING event *
  1244. * *
  1245. * INPUT: *
  1246. * net ptr to connection manager *
  1247. * my_sent # commands I've sent out so far *
  1248. * *
  1249. * OUTPUT: *
  1250. * none. *
  1251. * *
  1252. * WARNINGS: *
  1253. * none. *
  1254. * *
  1255. * HISTORY: *
  1256. * 07/02/1996 BRR : Created. *
  1257. *=========================================================================*/
  1258. static void Generate_Real_Timing_Event(ConnManClass *net, int my_sent)
  1259. {
  1260. unsigned long resp_time; // connection response time, in ticks
  1261. EventClass ev;
  1262. int highest_ticks;
  1263. int i;
  1264. int specified_frame_rate;
  1265. int maxahead;
  1266. //
  1267. // If we haven't sent out at least 5 guaranteed-delivery packets, don't
  1268. // bother trying to measure our connection response time; just return.
  1269. //
  1270. if (my_sent < 5) {
  1271. return;
  1272. }
  1273. //
  1274. // Find the highest processing time we have stored
  1275. //
  1276. highest_ticks = 0;
  1277. for (i = 0; i < Session.Players.Count(); i++) {
  1278. //
  1279. // If we haven't heard from all systems yet, bail out.
  1280. //
  1281. if (Session.Players[i]->Player.ProcessTime == -1) {
  1282. return;
  1283. }
  1284. if (Session.Players[i]->Player.ProcessTime > highest_ticks) {
  1285. highest_ticks = Session.Players[i]->Player.ProcessTime;
  1286. }
  1287. }
  1288. //
  1289. // Compute our "desired" frame rate as the lower of:
  1290. // - What the user has dialed into the options screen
  1291. // - What we're really able to run at
  1292. //
  1293. if (highest_ticks == 0) {
  1294. Session.DesiredFrameRate = 60;
  1295. } else {
  1296. Session.DesiredFrameRate = 60 / highest_ticks;
  1297. }
  1298. if (Options.GameSpeed == 0) {
  1299. specified_frame_rate = 60;
  1300. } else {
  1301. specified_frame_rate = 60 / Options.GameSpeed;
  1302. }
  1303. Session.DesiredFrameRate = MIN (Session.DesiredFrameRate, specified_frame_rate);
  1304. //
  1305. // Measure the current connection response time. This time will be in
  1306. // 60ths of a second, and represents full round-trip time of a packet.
  1307. // To convert to one-way packet time, divide by 2; to convert to game
  1308. // frames, ....uh....
  1309. //
  1310. resp_time = net->Response_Time();
  1311. //
  1312. // Compute our new 'MaxAhead' value, based upon the response time of our
  1313. // connection and our desired frame rate.
  1314. // 'MaxAhead' in frames is:
  1315. //
  1316. // (resp_time / 2 ticks) * (1 sec/60 ticks) * (n Frames / sec)
  1317. //
  1318. // resp_time is divided by 2 because, as reported, it represents a round-
  1319. // trip, and we only want to use a one-way trip.
  1320. //
  1321. maxahead = (resp_time * Session.DesiredFrameRate) / (2 * 60);
  1322. //
  1323. // Now, we have to round 'maxahead' so it's an even multiple of our
  1324. // send rate. It also must be at least thrice the FrameSendRate.
  1325. // (Isn't "thrice" a cool word?)
  1326. //
  1327. maxahead = ((maxahead + Session.FrameSendRate - 1) / Session.FrameSendRate) * Session.FrameSendRate;
  1328. maxahead = MAX (maxahead, (int)Session.FrameSendRate * 3);
  1329. ev.Type = EventClass::TIMING;
  1330. ev.Data.Timing.DesiredFrameRate = Session.DesiredFrameRate;
  1331. ev.Data.Timing.MaxAhead = maxahead;
  1332. OutList.Add(ev);
  1333. //
  1334. // Adjust my connection retry timing. These values set the retry timeout
  1335. // to just over one round-trip time, the 'maxretries' to -1, and the
  1336. // connection timeout to allow for about 4 retries.
  1337. //
  1338. //net->Set_Timing (resp_time + 10, -1, (resp_time * 4)+15);
  1339. if (Session.Type == GAME_INTERNET) {
  1340. net->Set_Timing (resp_time + 10, -1, ((resp_time + 10)* 8)+15);
  1341. }else{
  1342. net->Set_Timing (resp_time + 10, -1, (resp_time * 4)+15);
  1343. }
  1344. }
  1345. /***************************************************************************
  1346. * Generate_Process_Time_Event -- Generates a PROCESS_TIME event *
  1347. * *
  1348. * INPUT: *
  1349. * net ptr to connection manager *
  1350. * *
  1351. * OUTPUT: *
  1352. * none. *
  1353. * *
  1354. * WARNINGS: *
  1355. * none. *
  1356. * *
  1357. * HISTORY: *
  1358. * 07/02/1996 BRR : Created. *
  1359. *=========================================================================*/
  1360. static void Generate_Process_Time_Event(ConnManClass *net)
  1361. {
  1362. EventClass ev;
  1363. int avgticks;
  1364. unsigned long resp_time; // connection response time, in ticks
  1365. //
  1366. // Measure the current connection response time. This time will be in
  1367. // 60ths of a second, and represents full round-trip time of a packet.
  1368. // To convert to one-way packet time, divide by 2; to convert to game
  1369. // frames, ....uh....
  1370. //
  1371. resp_time = net->Response_Time();
  1372. //
  1373. // Adjust my connection retry timing. These values set the retry timeout
  1374. // to just over one round-trip time, the 'maxretries' to -1, and the
  1375. // connection timeout to allow for about 4 retries.
  1376. //
  1377. //net->Set_Timing (resp_time + 10, -1, (resp_time * 4)+15);
  1378. if (Session.Type == GAME_INTERNET) {
  1379. net->Set_Timing (resp_time + 10, -1, ((resp_time + 10)* 8)+15);
  1380. }else{
  1381. net->Set_Timing (resp_time + 10, -1, (resp_time * 4)+15);
  1382. }
  1383. if (IsMono) {
  1384. MonoClass::Enable();
  1385. Mono_Set_Cursor(0,23);
  1386. Mono_Printf("Processing Ticks:%03d Frames:%03d\n", Session.ProcessTicks,Session.ProcessFrames);
  1387. MonoClass::Disable();
  1388. }
  1389. avgticks = Session.ProcessTicks / Session.ProcessFrames;
  1390. ev.Type = EventClass::PROCESS_TIME;
  1391. ev.Data.ProcessTime.AverageTicks = avgticks;
  1392. OutList.Add(ev);
  1393. Session.ProcessTicks = 0;
  1394. Session.ProcessFrames = 0;
  1395. }
  1396. /***************************************************************************
  1397. * Process_Send_Period -- timing for sending packets every 'n' frames *
  1398. * *
  1399. * This function is for a CommProtocol of COMM_PROTOCOL_MULTI_E_COMP only. *
  1400. * It determines if it's time to send a packet or not. *
  1401. * *
  1402. * INPUT: *
  1403. * net ptr to connection manager *
  1404. * *
  1405. * OUTPUT: *
  1406. * 1 = it's time to send a packet; 0 = don't send a packet this frame. *
  1407. * *
  1408. * WARNINGS: *
  1409. * *
  1410. * HISTORY: *
  1411. * 11/21/1995 BRR : Created. *
  1412. *=========================================================================*/
  1413. static int Process_Send_Period(ConnManClass *net) //, int init)
  1414. {
  1415. //------------------------------------------------------------------------
  1416. // If the current frame # is not an even multiple of 'FrameSendRate', then
  1417. // it's not time to send a packet; just return.
  1418. //------------------------------------------------------------------------
  1419. if (Frame != (((Frame + (Session.FrameSendRate - 1)) /
  1420. Session.FrameSendRate) * Session.FrameSendRate) ) {
  1421. net->Service();
  1422. if (IsMono) {
  1423. MonoClass::Disable();
  1424. }
  1425. return (0);
  1426. }
  1427. return (1);
  1428. } // end of Process_Send_Period
  1429. /***************************************************************************
  1430. * Send_Packets -- sends out events from the OutList *
  1431. * *
  1432. * This routine computes how many events can be sent this frame, and then *
  1433. * builds the "meta-packet" & sends it. *
  1434. * *
  1435. * The 'cap' value is the max # of events we can send. Ideally, it should *
  1436. * be based upon the bandwidth of our connection. Currently, it's just *
  1437. * hardcoded to prevent the modem from having to resend "too much" data, *
  1438. * which is about 200 bytes per frame. *
  1439. * *
  1440. * INPUT: *
  1441. * net ptr to connection manager *
  1442. * multi_packet_buf buffer to store packets in *
  1443. * multi_packet_max max size of multi_packet_buf *
  1444. * max_ahead current game MaxAhead value *
  1445. * my_sent # commands I've sent this game *
  1446. * *
  1447. * OUTPUT: *
  1448. * # events sent, NOT including the FRAMEINFO event *
  1449. * *
  1450. * WARNINGS: *
  1451. * *
  1452. * HISTORY: *
  1453. * 11/21/1995 BRR : Created. *
  1454. *=========================================================================*/
  1455. static int Send_Packets(ConnManClass *net, char *multi_packet_buf,
  1456. int multi_packet_max, int max_ahead, int my_sent)
  1457. {
  1458. int cap; // max # events to send, NOT including FRAMEINFO event
  1459. int do_once; // true: only go through packet loop once
  1460. int ack_req; // 0 = no ack required on outgoing packet
  1461. int packetlen; // size of meta-packet sent
  1462. //------------------------------------------------------------------------
  1463. // Determine how many events it's OK to send this frame.
  1464. //------------------------------------------------------------------------
  1465. //........................................................................
  1466. // If we have 4 or more packets queued for sending, don't add any more
  1467. // this frame.
  1468. //........................................................................
  1469. if (net->Private_Num_Send() >= 4) {
  1470. cap = 0;
  1471. do_once = 1;
  1472. }
  1473. //........................................................................
  1474. // If there are 2 or more packets queued, the entire packet we send must
  1475. // fit within a single ComQueue buffer, so limit # events to 5.
  1476. // (The Modem connection manager has a max buffer size of 200 bytes, which
  1477. // is large enough for 6 uncompressed events, which leaves room for 5
  1478. // events plus a FRAMEINFO.)
  1479. //........................................................................
  1480. else if (net->Private_Num_Send() >= 2) {
  1481. cap = 5;
  1482. do_once = 1;
  1483. }
  1484. //........................................................................
  1485. // Otherwise, just send all events in the OutList
  1486. //........................................................................
  1487. else {
  1488. cap = OutList.Count;
  1489. do_once = 0;
  1490. }
  1491. //........................................................................
  1492. // Make sure we aren't sending more events than are in the OutList
  1493. //........................................................................
  1494. if (cap > OutList.Count) {
  1495. cap = OutList.Count;
  1496. }
  1497. //........................................................................
  1498. // Make sure we don't send so many events that our DoList fills up
  1499. //........................................................................
  1500. if (cap > (MAX_EVENTS * 64) - DoList.Count) {
  1501. cap = (MAX_EVENTS * 64) - DoList.Count;
  1502. }
  1503. //
  1504. // 10/21/96 5:12PM - ST
  1505. //
  1506. if (Session.Type == GAME_INTERNET || Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM){
  1507. cap = OutList.Count;
  1508. do_once = 0;
  1509. }
  1510. //------------------------------------------------------------------------
  1511. // Build our meta-packet & transmit it.
  1512. //------------------------------------------------------------------------
  1513. while (1) {
  1514. Keyboard->Check();
  1515. Update_Queue_Mono (net, 1);
  1516. //.....................................................................
  1517. // If there are no commands this frame, we'll just be sending a FRAMEINFO
  1518. // packet; no ack is required. For the modem's sake, check
  1519. // Session.NumPlayers; no ACK is needed if we're just sending to someone
  1520. // who's left the game.
  1521. //.....................................................................
  1522. if (cap == 0 || OutList.Count == 0 || Session.NumPlayers == 1) {
  1523. ack_req = 0;
  1524. }
  1525. else {
  1526. ack_req = 1;
  1527. }
  1528. //.....................................................................
  1529. // Build & send out our message
  1530. //.....................................................................
  1531. packetlen = Build_Send_Packet (multi_packet_buf, multi_packet_max,
  1532. max_ahead, my_sent, cap);
  1533. net->Send_Private_Message (multi_packet_buf, packetlen, ack_req);
  1534. //.....................................................................
  1535. // Call Service() to actually send the packet
  1536. //.....................................................................
  1537. net->Service();
  1538. //.....................................................................
  1539. // Stop if there's no more data to send, or if our send queue is
  1540. // filling up.
  1541. //.....................................................................
  1542. if (OutList.Count == 0 || do_once) {
  1543. break;
  1544. }
  1545. }
  1546. return (cap);
  1547. } // end of Send_Packets
  1548. /***************************************************************************
  1549. * Send_FrameSync -- Sends a FRAMESYNC packet *
  1550. * *
  1551. * This routine is used to periodically remind the other systems that *
  1552. * we're still here, and to tell them what frame # we're on, in case *
  1553. * they've missed my FRAMEINFO packets. *
  1554. * *
  1555. * INPUT: *
  1556. * net ptr to connection manager *
  1557. * cmd_count # commands I've sent so far *
  1558. * *
  1559. * OUTPUT: *
  1560. * none. *
  1561. * *
  1562. * WARNINGS: *
  1563. * none. *
  1564. * *
  1565. * HISTORY: *
  1566. * 11/21/1995 BRR : Created. *
  1567. *=========================================================================*/
  1568. static void Send_FrameSync(ConnManClass *net, int cmd_count)
  1569. {
  1570. EventClass packet;
  1571. //------------------------------------------------------------------------
  1572. // Build a frame-sync event to send. FRAMESYNC packets contain a
  1573. // scenario-based CRC rather than a game-state-based CRC, to let the
  1574. // games compare scenario CRC's on startup.
  1575. //------------------------------------------------------------------------
  1576. memset (&packet, 0, sizeof(EventClass));
  1577. packet.Type = EventClass::FRAMESYNC;
  1578. if (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {
  1579. packet.Frame = ((Frame + Session.MaxAhead + (Session.FrameSendRate - 1)) /
  1580. Session.FrameSendRate) * Session.FrameSendRate;
  1581. }
  1582. else {
  1583. packet.Frame = Frame + Session.MaxAhead;
  1584. }
  1585. packet.ID = PlayerPtr->ID;
  1586. packet.Data.FrameInfo.CRC = ScenarioCRC;
  1587. packet.Data.FrameInfo.CommandCount = cmd_count;
  1588. packet.Data.FrameInfo.Delay = Session.MaxAhead;
  1589. //------------------------------------------------------------------------
  1590. // Send the event. For modem, this just sends to the other player;
  1591. // for network, it sends to everyone we're connected to.
  1592. //------------------------------------------------------------------------
  1593. net->Send_Private_Message (&packet, (offsetof(EventClass, Data) +
  1594. size_of(EventClass, Data.FrameInfo)), 0 );
  1595. return;
  1596. } // end of Send_FrameSync
  1597. /***************************************************************************
  1598. * Process_Receive_Packet -- processes an incoming packet *
  1599. * *
  1600. * This routine receives a packet from another system, adds it to our *
  1601. * execution queue (the DoList), and updates my arrays of their frame #, *
  1602. * their commands-sent, and their commands-received. *
  1603. * *
  1604. * INPUT: *
  1605. * net ptr to connection manager *
  1606. * multi_packet_buf buffer containing packet(s) to parse *
  1607. * id id of sender *
  1608. * their_frame array containing frame #'s of other players *
  1609. * their_sent array containing command count of other players *
  1610. * their_recv array containing # recv'd cmds from other players *
  1611. * *
  1612. * OUTPUT: *
  1613. * RC_NORMAL: nothing unusual happened, although *
  1614. * their_sent or their_recv may have been *
  1615. * altered *
  1616. * RC_PLAYER_READY: player has been heard from for the 1st time; *
  1617. * this presumes that his original *
  1618. * 'their_frame[]' value was -1 when this *
  1619. * routine was called *
  1620. * RC_SCENARIO_MISMATCH: FRAMEINFO scenario CRC doesn't match; *
  1621. * normally only applies after loading a new *
  1622. * scenario or save-game *
  1623. * RC_DOLIST_FULL: fatal error; unable to add events to DoList *
  1624. * *
  1625. * WARNINGS: *
  1626. * none. *
  1627. * *
  1628. * HISTORY: *
  1629. * 11/21/1995 BRR : Created. *
  1630. *=========================================================================*/
  1631. static RetcodeType Process_Receive_Packet(ConnManClass *net,
  1632. char *multi_packet_buf, int id, int packetlen, long *their_frame,
  1633. unsigned short *their_sent, unsigned short *their_recv)
  1634. {
  1635. EventClass *event;
  1636. int index;
  1637. RetcodeType retcode = RC_NORMAL;
  1638. int i;
  1639. //------------------------------------------------------------------------
  1640. // Get an event ptr to the incoming message
  1641. //------------------------------------------------------------------------
  1642. event = (EventClass *)multi_packet_buf;
  1643. //------------------------------------------------------------------------
  1644. // Get the index of the sender
  1645. //------------------------------------------------------------------------
  1646. index = net->Connection_Index(id);
  1647. //------------------------------------------------------------------------
  1648. // Compute the other player's frame # (at the time this packet was sent)
  1649. //------------------------------------------------------------------------
  1650. if (their_frame[index] <
  1651. (int)(event->Frame - event->Data.FrameInfo.Delay)) {
  1652. //.....................................................................
  1653. // If the original frame # for this player is -1, it means we've heard
  1654. // from this player for the 1st time; return the appropriate value.
  1655. //.....................................................................
  1656. if (their_frame[index]==-1) {
  1657. retcode = RC_PLAYER_READY;
  1658. }
  1659. their_frame[index] = event->Frame - event->Data.FrameInfo.Delay;
  1660. }
  1661. //------------------------------------------------------------------------
  1662. // Extract the other player's CommandCount. This count will include
  1663. // the commands in this packet, if there are any.
  1664. //------------------------------------------------------------------------
  1665. if (event->Data.FrameInfo.CommandCount > their_sent[index]) {
  1666. if ( abs(their_sent[index] - event->Data.FrameInfo.CommandCount) > 500) {
  1667. FILE *fp;
  1668. fp = fopen("badcount.txt","wt");
  1669. if (fp) {
  1670. fprintf(fp,"Event Type:%s\n",EventClass::EventNames[event->Type]);
  1671. fprintf(fp,"Frame:%d ID:%d IsExec:%d\n",
  1672. event->Frame,
  1673. event->ID,
  1674. event->IsExecuted);
  1675. if (event->Type != EventClass::FRAMEINFO) {
  1676. fprintf(fp,"Wrong Event Type!\n");
  1677. } else {
  1678. fprintf(fp,"CRC:%x CommandCount:%d Delay:%d\n",
  1679. event->Data.FrameInfo.CRC,
  1680. event->Data.FrameInfo.CommandCount,
  1681. event->Data.FrameInfo.Delay);
  1682. }
  1683. }
  1684. }
  1685. their_sent[index] = event->Data.FrameInfo.CommandCount;
  1686. }
  1687. if (Debug_Print_Events) {
  1688. if (event->Type == EventClass::FRAMESYNC) {
  1689. printf("(%d) Received FRAMESYNC: ", Frame);
  1690. } else {
  1691. printf("(%d) Received FRAMEINFO: ", Frame);
  1692. }
  1693. printf("EvFrame:%d ID:%d CRC:%x CmdCount:%d Delay:%d\n",
  1694. event->Frame,
  1695. event->ID,
  1696. event->Data.FrameInfo.CRC,
  1697. event->Data.FrameInfo.CommandCount,
  1698. event->Data.FrameInfo.Delay);
  1699. }
  1700. //------------------------------------------------------------------------
  1701. // If this packet was not a FRAMESYNC packet:
  1702. // - Add the events in it to our DoList
  1703. // - Increment our commands-received counter by the number of non-
  1704. // FRAMEINFO packets received
  1705. //------------------------------------------------------------------------
  1706. if (event->Type != EventClass::FRAMESYNC) {
  1707. //.....................................................................
  1708. // Break up the packet into its component events. A returned packet
  1709. // count of -1 indicates a fatal queue-full error.
  1710. //.....................................................................
  1711. i = Breakup_Receive_Packet( multi_packet_buf, packetlen);
  1712. if (i==-1) {
  1713. return (RC_DOLIST_FULL);
  1714. }
  1715. //.....................................................................
  1716. // Compute the actual # commands in the packet by subtracting off the
  1717. // FRAMEINFO event
  1718. //.....................................................................
  1719. if ( (event->Type==EventClass::FRAMEINFO) && (i > 0)) {
  1720. i--;
  1721. }
  1722. their_recv[index] += i;
  1723. }
  1724. //------------------------------------------------------------------------
  1725. // If the event was a FRAMESYNC packet, there will be no commands to add,
  1726. // but we must check the ScenarioCRC value.
  1727. //------------------------------------------------------------------------
  1728. else if (event->Data.FrameInfo.CRC != ScenarioCRC) {
  1729. return (RC_SCENARIO_MISMATCH);
  1730. }
  1731. return (retcode);
  1732. } // end of Process_Receive_Packet
  1733. /***************************************************************************
  1734. * Process_Serial_Packet -- Handles an incoming serial packet *
  1735. * *
  1736. * This routine is needed because the modem classes don't support a *
  1737. * "global channel" like the network classes do, but that functionality is *
  1738. * still needed for modem communications. Specifically, the modem dialogs *
  1739. * transmit their own special packets back & forth, and messages are sent *
  1740. * using a special packet type. Thus, we have to call this routine when *
  1741. * we receive a modem packet, to allow it to process messages & dialog *
  1742. * packets. *
  1743. * *
  1744. * INPUT: *
  1745. * multi_packet_buf packet buffer to process *
  1746. * first_time 1 = this is the 1st game frame *
  1747. * *
  1748. * OUTPUT: *
  1749. * RC_NORMAL: this wasn't a SERIAL-type packet *
  1750. * RC_SERIAL_PROCESSED: this was a SERIAL-type packet, and was *
  1751. * processed; the other player is still connected, *
  1752. * even if he's not in the game. *
  1753. * RC_PLAYER_LEFT: other player has left the game *
  1754. * RC_HUNG_UP: we're getting our own packets back; thus, the *
  1755. * modem is mirroring our packets, which means the *
  1756. * modem hung up! *
  1757. * *
  1758. * WARNINGS: *
  1759. * none. *
  1760. * *
  1761. * HISTORY: *
  1762. * 11/21/1995 BRR : Created. *
  1763. *=========================================================================*/
  1764. static RetcodeType Process_Serial_Packet(char *multi_packet_buf,
  1765. int first_time)
  1766. {
  1767. multi_packet_buf;
  1768. first_time;
  1769. return (RC_NORMAL);
  1770. #if (0) // ST - 5/13/2019
  1771. SerialPacketType *serial_packet; // for parsing serial packets
  1772. int player_gone;
  1773. EventClass *event;
  1774. //------------------------------------------------------------------------
  1775. // Determine if this packet means that the other player has left the game
  1776. //------------------------------------------------------------------------
  1777. serial_packet = (SerialPacketType *)multi_packet_buf;
  1778. player_gone = 0;
  1779. //........................................................................
  1780. // On Frame 0, only a SIGN_OFF means the other player left; the other
  1781. // packet types may be left over from a previous session.
  1782. //........................................................................
  1783. if (first_time) {
  1784. if (serial_packet->Command == SERIAL_SIGN_OFF) {
  1785. player_gone = 1;
  1786. }
  1787. }
  1788. //........................................................................
  1789. // On subsequent frames, any of SIGN_OFF, TIMING, or SCORE_SCREEN means
  1790. // the other player is gone.
  1791. //........................................................................
  1792. else {
  1793. if (serial_packet->Command == SERIAL_SIGN_OFF ||
  1794. serial_packet->Command == SERIAL_TIMING ||
  1795. serial_packet->Command == SERIAL_SCORE_SCREEN ) {
  1796. player_gone = 1;
  1797. }
  1798. }
  1799. if (player_gone) {
  1800. Destroy_Null_Connection(serial_packet->ScenarioInfo.Color, 0);
  1801. return (RC_PLAYER_LEFT);
  1802. }
  1803. //------------------------------------------------------------------------
  1804. // Process an incoming message
  1805. //------------------------------------------------------------------------
  1806. if (serial_packet->Command == SERIAL_MESSAGE) {
  1807. if (!Session.Messages.Concat_Message(serial_packet->Name,
  1808. serial_packet->ID, serial_packet->Message.Message, Rule.MessageDelay * TICKS_PER_MINUTE)) {
  1809. #ifdef FIXIT_CSII // checked - ajw 9/28/98 - Appears to do nothing
  1810. char *ptr = &serial_packet->Message.Message[0];
  1811. if (!strncmp(ptr,"SECRET UNITS ON ",15) && NewUnitsEnabled) {
  1812. Enable_Secret_Units();
  1813. }
  1814. #endif
  1815. Session.Messages.Add_Message (serial_packet->Name,
  1816. serial_packet->ID, serial_packet->Message.Message,
  1817. (PlayerColorType)serial_packet->ID,
  1818. TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_FULLSHADOW, Rule.MessageDelay * TICKS_PER_MINUTE);
  1819. Sound_Effect(VOC_INCOMING_MESSAGE);
  1820. }
  1821. //.....................................................................
  1822. // Save this message in our last-message buffer
  1823. //.....................................................................
  1824. if (strlen (serial_packet->Message.Message)) {
  1825. strcpy (Session.LastMessage, serial_packet->Message.Message);
  1826. }
  1827. //.....................................................................
  1828. // Tell the map to do a partial update (just to force the
  1829. // messages to redraw).
  1830. //.....................................................................
  1831. //Map.Flag_To_Redraw(false);
  1832. Map.Flag_To_Redraw(true);
  1833. return (RC_SERIAL_PROCESSED);
  1834. }
  1835. //------------------------------------------------------------------------
  1836. // Any other SERIAL-type packet means the other player is still there;
  1837. // throw them away, but let the caller know the connection is OK.
  1838. //------------------------------------------------------------------------
  1839. if ( (serial_packet->Command >= SERIAL_CONNECT &&
  1840. serial_packet->Command < SERIAL_LAST_COMMAND) ||
  1841. (serial_packet->Command >= SERIAL_REQ_SCENARIO &&
  1842. serial_packet->Command <= SERIAL_NO_SCENARIO) ||
  1843. Session.NumPlayers == 1) {
  1844. return (RC_SERIAL_PROCESSED);
  1845. }
  1846. //........................................................................
  1847. // are we getting our own packets back??
  1848. //........................................................................
  1849. event = (EventClass *)multi_packet_buf;
  1850. if (event->Type <= EventClass::EMPTY || event->Type >= EventClass::LAST_EVENT) return (RC_SERIAL_PROCESSED);
  1851. if (event->ID == PlayerPtr->ID) {
  1852. return (RC_HUNG_UP);
  1853. }
  1854. return (RC_NORMAL);
  1855. #endif
  1856. } // end of Process_Serial_Packet
  1857. /***************************************************************************
  1858. * Can_Advance -- determines if it's OK to advance to the next frame *
  1859. * *
  1860. * This routine uses the current values stored in their_frame[], *
  1861. * their_send[], and their_recv[] to see if it's OK to advance to the next *
  1862. * game frame. We must not advance if: *
  1863. * - If our frame # would be too far ahead of the slowest player (the *
  1864. * lowest their_frame[] value). "Too far" means *
  1865. * (Frame >= their_frame + MaxAhead). *
  1866. * - our current command count doesn't match the sent command count of one *
  1867. * other player (meaning that we've missed a command packet from that *
  1868. * player, and thus the frame # we're receiving from him may be due to a *
  1869. * FRAMEINFO packet sent later than the command, so we shouldn't use *
  1870. * this frame # to see if we should advance; we should wait until we *
  1871. * have all the commands before we advance. *
  1872. * *
  1873. * Of course, this routine assumes the values in their_frame[] etc are *
  1874. * kept current by the caller. *
  1875. * *
  1876. * INPUT: *
  1877. * net ptr to connection manager *
  1878. * max_ahead max frames ahead *
  1879. * their_frame array of their frame #'s *
  1880. * their_sent array of their sent command count *
  1881. * their_recv array of their # received commands *
  1882. * *
  1883. * OUTPUT: *
  1884. * 1 = OK to advance; 0 = not OK *
  1885. * *
  1886. * WARNINGS: *
  1887. * none. *
  1888. * *
  1889. * HISTORY: *
  1890. * 11/21/1995 BRR : Created. *
  1891. *=========================================================================*/
  1892. static int Can_Advance(ConnManClass *net, int max_ahead, long *their_frame,
  1893. unsigned short *their_sent, unsigned short *their_recv)
  1894. {
  1895. long their_oldest_frame; // other players' oldest frame #
  1896. int count_ok; // true = my cmd count matches theirs
  1897. int i;
  1898. //------------------------------------------------------------------------
  1899. // Special case for modem: if the other player has left, go ahead and
  1900. // advance to the next frame; don't wait on him.
  1901. //------------------------------------------------------------------------
  1902. if (Session.NumPlayers == 1) {
  1903. return (1);
  1904. }
  1905. //------------------------------------------------------------------------
  1906. // Find the oldest frame # in 'their_frame'
  1907. //------------------------------------------------------------------------
  1908. their_oldest_frame = Frame + 1000;
  1909. for (i = 0; i < net->Num_Connections(); i++) {
  1910. if (their_frame[i] < their_oldest_frame)
  1911. their_oldest_frame = their_frame[i];
  1912. }
  1913. //------------------------------------------------------------------------
  1914. // I can advance to the next frame IF:
  1915. // 1) I'm less than a one-way propagation delay ahead of the other
  1916. // players' frame numbers, AND
  1917. // 2) their_recv[i] >= their_sent[i] (ie I've received all the commands
  1918. // the other players have sent so far).
  1919. //------------------------------------------------------------------------
  1920. count_ok = 1;
  1921. for (i = 0; i < net->Num_Connections(); i++) {
  1922. if (their_recv[i] < their_sent[i]) {
  1923. count_ok = 0;
  1924. break;
  1925. }
  1926. }
  1927. if (count_ok && (Frame < (their_oldest_frame + max_ahead))) {
  1928. return (1);
  1929. }
  1930. return (0);
  1931. } // end of Can_Advance
  1932. /***************************************************************************
  1933. * Process_Reconnect_Dialog -- processes the reconnection dialog *
  1934. * *
  1935. * This routine [re]draws the reconnection dialog; if 'reconn' is set, *
  1936. * it tells the user who we're trying to reconnect to; otherwise, is just *
  1937. * says something generic like "Waiting for connections". *
  1938. * *
  1939. * INPUT: *
  1940. * timeout_timer ptr to count down timer, showing time remaining *
  1941. * their_frame array of other players' frame #'s *
  1942. * num_conn # connections in 'their_frame' *
  1943. * reconn 1 = reconnect, 0 = waiting for first-time connection *
  1944. * fresh 1 = draw from scratch, 0 = only update time counter *
  1945. * *
  1946. * OUTPUT: *
  1947. * 1 = user wants to cancel, 0 = not *
  1948. * *
  1949. * WARNINGS: *
  1950. * *
  1951. * HISTORY: *
  1952. * 11/21/1995 BRR : Created. *
  1953. *=========================================================================*/
  1954. static int Process_Reconnect_Dialog(CDTimerClass<SystemTimerClass> *timeout_timer,
  1955. long *their_frame, int num_conn, int reconn, int fresh)
  1956. {
  1957. static int displayed_time = 0; // time value currently displayed
  1958. int new_time;
  1959. int oldest_index; // index of person requiring a reconnect
  1960. int i,j;
  1961. //------------------------------------------------------------------------
  1962. // Convert the timer to seconds
  1963. //------------------------------------------------------------------------
  1964. new_time = *timeout_timer / 60;
  1965. //------------------------------------------------------------------------
  1966. // If the timer has changed, or 'fresh' is set, redraw the dialog
  1967. //------------------------------------------------------------------------
  1968. if (fresh || (new_time != displayed_time)) {
  1969. //.....................................................................
  1970. // Find the index of the person we're trying to reconnect to
  1971. //.....................................................................
  1972. if (reconn) {
  1973. j = 0x7fffffff;
  1974. oldest_index = 0;
  1975. for (i = 0; i < num_conn; i++) {
  1976. if (their_frame[i] < j) {
  1977. j = their_frame[i];
  1978. oldest_index = i;
  1979. }
  1980. }
  1981. }
  1982. Net_Reconnect_Dialog(reconn, fresh, oldest_index, new_time);
  1983. }
  1984. displayed_time = new_time;
  1985. //........................................................................
  1986. // If user hits ESC, bail out
  1987. //........................................................................
  1988. if (Keyboard->Check()) {
  1989. if (Keyboard->Get() == KN_ESC) {
  1990. return (1);
  1991. }
  1992. }
  1993. return (0);
  1994. } // end of Process_Reconnect_Dialog
  1995. /***************************************************************************
  1996. * Handle_Timeout -- handles a timeout in the wait-for-players loop *
  1997. * *
  1998. * This routine "gracefully" handles a timeout in the frame-sync loop. *
  1999. * The timeout must be handled differently by a modem game or network *
  2000. * game. *
  2001. * *
  2002. * The modem game must detect if the other player is still connected *
  2003. * physically, even if he's not playing the game any more; if so, this *
  2004. * routine returns an OK status. If the other player isn't even *
  2005. * physically connected, an error is returned. *
  2006. * *
  2007. * The network game must find the connection that's causing the timeout, *
  2008. * and destroy it. The game continues, even if there are no more human *
  2009. * players left. *
  2010. * *
  2011. * INPUT: *
  2012. * net ptr to connection manager *
  2013. * their_frame array containing frame #'s of other players *
  2014. * their_sent array containing command count of other players *
  2015. * their_recv array containing # recv'd cmds from other players *
  2016. * *
  2017. * OUTPUT: *
  2018. * 1 = it's OK; reset timeout timers & keep processing *
  2019. * 0 = game over, man *
  2020. * *
  2021. * WARNINGS: *
  2022. * *
  2023. * HISTORY: *
  2024. * 11/21/1995 BRR : Created. *
  2025. *=========================================================================*/
  2026. static int Handle_Timeout(ConnManClass *net, long *their_frame,
  2027. unsigned short *their_sent, unsigned short *their_recv)
  2028. {
  2029. int oldest_index; // index of person requiring a reconnect
  2030. int i,j;
  2031. int id;
  2032. //------------------------------------------------------------------------
  2033. // For modem, attempt to reconnect; if that fails, save the game & bail.
  2034. //------------------------------------------------------------------------
  2035. if (Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) {
  2036. if ( net->Num_Connections() ) {
  2037. if (!Reconnect_Modem()) {
  2038. #ifndef FIXIT_MULTI_SAVE
  2039. //...............................................................
  2040. // Set 'Session.EmergencySave', so when this game is loaded, we
  2041. // won't check the CRC of the game state (this system & the
  2042. // other may be on different frames, in which case the CRC
  2043. // won't match).
  2044. //...............................................................
  2045. Session.EmergencySave = 1;
  2046. //Save_Game (-1, (char *)Text_String(TXT_MULTIPLAYER_GAME));
  2047. Session.EmergencySave = 0;
  2048. #endif // FIXIT_MULTI_SAVE
  2049. return (0);
  2050. } else {
  2051. return (1);
  2052. }
  2053. }
  2054. }
  2055. //------------------------------------------------------------------------
  2056. // For network, destroy the oldest connection
  2057. //------------------------------------------------------------------------
  2058. else if (Session.Type == GAME_IPX || Session.Type == GAME_INTERNET ||
  2059. Session.Type == GAME_TEN || Session.Type == GAME_MPATH) {
  2060. j = 0x7fffffff;
  2061. oldest_index = 0;
  2062. for (i = 0; i < net->Num_Connections(); i++) {
  2063. if (their_frame[i] < j) {
  2064. j = their_frame[i];
  2065. oldest_index = i;
  2066. }
  2067. }
  2068. id = net->Connection_ID(oldest_index);
  2069. #ifdef WIN32
  2070. /*
  2071. ** Send the game statistics packet now if the game is effectivly over
  2072. */
  2073. if (Session.Players.Count() == 2 &&
  2074. Session.Type == GAME_INTERNET &&
  2075. !GameStatisticsPacketSent) {
  2076. Register_Game_End_Time();
  2077. ConnectionLost = true;
  2078. Send_Statistics_Packet(); // Disconnect, and I'll be the only one left.
  2079. }
  2080. #endif //WIN32
  2081. if (id != ConnManClass::CONNECTION_NONE) {
  2082. for (i = oldest_index; i < net->Num_Connections() - 1; i++) {
  2083. their_frame[i] = their_frame[i+1];
  2084. their_sent[i] = their_sent[i+1];
  2085. their_recv[i] = their_recv[i+1];
  2086. }
  2087. if (Session.Type == GAME_IPX || Session.Type == GAME_INTERNET) {
  2088. Destroy_Connection(id,1);
  2089. }
  2090. #if(TEN)
  2091. else if (Session.Type == GAME_TEN) {
  2092. Destroy_TEN_Connection(id,1);
  2093. }
  2094. #endif
  2095. #if(MPATH)
  2096. else if (Session.Type == GAME_MPATH) {
  2097. Destroy_MPATH_Connection(id,1);
  2098. }
  2099. #endif
  2100. }
  2101. }
  2102. return (1);
  2103. } // end of Handle_Timeout
  2104. /***************************************************************************
  2105. * Stop_Game -- stops the game *
  2106. * *
  2107. * This routine clears any global flags that need it, in preparation for *
  2108. * halting the game prematurely. *
  2109. * *
  2110. * INPUT: *
  2111. * none. *
  2112. * *
  2113. * OUTPUT: *
  2114. * none. *
  2115. * *
  2116. * WARNINGS: *
  2117. * none. *
  2118. * *
  2119. * HISTORY: *
  2120. * 11/22/1995 BRR : Created. *
  2121. *=========================================================================*/
  2122. static void Stop_Game(void)
  2123. {
  2124. Session.LoadGame = false;
  2125. Session.EmergencySave = false;
  2126. GameActive = 0;
  2127. if (IsMono) {
  2128. MonoClass::Disable();
  2129. }
  2130. #ifdef WIN32
  2131. if (Session.Type == GAME_INTERNET){
  2132. ConnectionLost = true;
  2133. Send_Statistics_Packet(); // Stop_Game()
  2134. }
  2135. #endif //WIN32
  2136. return;
  2137. } // end of Stop_Game
  2138. /***************************************************************************
  2139. * Build_Send_Packet -- Builds a big packet from a bunch of little ones. *
  2140. * *
  2141. * This routine takes events from the OutList, and puts them into a *
  2142. * "meta-packet", which is transmitted to all systems we're connected to. *
  2143. * Also, these events are added to our own DoList. *
  2144. * *
  2145. * Every Meta-Packet we send uses a FRAMEINFO packet as a header; this *
  2146. * tells the other systems what frame we're on, as well as serving as a *
  2147. * standard packet header. *
  2148. * *
  2149. * INPUT: *
  2150. * buf buffer to store packet in *
  2151. * bufsize max size of buffer *
  2152. * frame_delay desired frame delay to attach to all outgoing packets *
  2153. * num_cmds value to use for the CommandCount field *
  2154. * cap max # events to send *
  2155. * *
  2156. * OUTPUT: *
  2157. * new size of packet *
  2158. * *
  2159. * WARNINGS: *
  2160. * 'num_cmds' should be the total of of commands, including all those sent *
  2161. * this frame! *
  2162. * *
  2163. * HISTORY: *
  2164. * 11/21/1995 BRR : Created. *
  2165. *=========================================================================*/
  2166. static int Build_Send_Packet(void *buf, int bufsize, int frame_delay,
  2167. int num_cmds, int cap)
  2168. {
  2169. int size = 0;
  2170. EventClass *finfo;
  2171. //------------------------------------------------------------------------
  2172. // All events start with a FRAMEINFO event; fill this part in.
  2173. //------------------------------------------------------------------------
  2174. //........................................................................
  2175. // Set the event type
  2176. //........................................................................
  2177. finfo = (EventClass *)buf;
  2178. finfo->Type = EventClass::FRAMEINFO;
  2179. //........................................................................
  2180. // Set the frame to execute this event on; this is protocol-specific
  2181. //........................................................................
  2182. if (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {
  2183. finfo->Frame = ((Frame + frame_delay + (Session.FrameSendRate - 1)) /
  2184. Session.FrameSendRate) * Session.FrameSendRate;
  2185. }
  2186. else {
  2187. finfo->Frame = Frame + frame_delay;
  2188. }
  2189. //........................................................................
  2190. // Fill in the rest of the event
  2191. //........................................................................
  2192. finfo->ID = PlayerPtr->ID;
  2193. finfo->Data.FrameInfo.CRC = GameCRC;
  2194. finfo->Data.FrameInfo.CommandCount = num_cmds;
  2195. finfo->Data.FrameInfo.Delay = frame_delay;
  2196. //------------------------------------------------------------------------
  2197. // Initialize the # of bytes processed; this is protocol-specific
  2198. //------------------------------------------------------------------------
  2199. if (Session.CommProtocol==COMM_PROTOCOL_SINGLE_NO_COMP) {
  2200. size += sizeof(EventClass);
  2201. }
  2202. else {
  2203. size += (offsetof(EventClass, Data) +
  2204. size_of(EventClass, Data.FrameInfo));
  2205. }
  2206. //------------------------------------------------------------------------
  2207. // Transfer all events from the OutList into the DoList, building our
  2208. // packet while we go.
  2209. //------------------------------------------------------------------------
  2210. switch (Session.CommProtocol) {
  2211. //.....................................................................
  2212. // COMM_PROTOCOL_SINGLE_NO_COMP:
  2213. // We'll send at least a FRAMEINFO every single frame, no compression
  2214. //.....................................................................
  2215. case (COMM_PROTOCOL_SINGLE_NO_COMP):
  2216. size = Add_Uncompressed_Events(buf, bufsize, frame_delay, size, cap);
  2217. break;
  2218. //.....................................................................
  2219. // COMM_PROTOCOL_SINGLE_E_COMP:
  2220. // Compress a group of packets into our send buffer; send out
  2221. // compressed packets every frame.
  2222. // COMM_PROTOCOL_MULTI_E_COMP:
  2223. // Compress a group of packets into our send buffer; send out
  2224. // compressed packets every 'n' frames.
  2225. //.....................................................................
  2226. case (COMM_PROTOCOL_SINGLE_E_COMP):
  2227. case (COMM_PROTOCOL_MULTI_E_COMP):
  2228. size = Add_Compressed_Events(buf, bufsize, frame_delay, size, cap);
  2229. break;
  2230. //.....................................................................
  2231. // Default: We have no idea what to do, so do nothing.
  2232. //.....................................................................
  2233. default:
  2234. size = 0;
  2235. break;
  2236. }
  2237. return( size );
  2238. } /* end of Build_Send_Packet */
  2239. /***************************************************************************
  2240. * Add_Uncompressed_Events -- adds uncompressed events to a packet *
  2241. * *
  2242. * INPUT: *
  2243. * buf buffer to store packet in *
  2244. * bufsize max size of buffer *
  2245. * frame_delay desired frame delay to attach to all outgoing packets *
  2246. * size current packet size *
  2247. * cap max # events to process *
  2248. * *
  2249. * OUTPUT: *
  2250. * new size value *
  2251. * *
  2252. * WARNINGS: *
  2253. * This routine MUST check to be sure it doesn't overflow the buffer. *
  2254. * *
  2255. * HISTORY: *
  2256. * 11/21/1995 DRD : Created. *
  2257. *=========================================================================*/
  2258. static int Add_Uncompressed_Events(void *buf, int bufsize, int frame_delay,
  2259. int size, int cap)
  2260. {
  2261. int num = 0; // # of events processed
  2262. int ev_size; // size of event we're adding
  2263. //------------------------------------------------------------------------
  2264. // Loop until there are no more events, or we've processed our max # of
  2265. // events, or the buffer is full.
  2266. //------------------------------------------------------------------------
  2267. while (OutList.Count && (num < cap)) {
  2268. Keyboard->Check();
  2269. if (OutList.First().Type==EventClass::ADDPLAYER) {
  2270. ev_size = sizeof(EventClass) + OutList.First().Data.Variable.Size;
  2271. }
  2272. else {
  2273. ev_size = sizeof(EventClass);
  2274. }
  2275. //.....................................................................
  2276. // Will the next event exceed the size of the buffer? If so, break.
  2277. //.....................................................................
  2278. if ( (size + ev_size) > bufsize ) {
  2279. return (size);
  2280. }
  2281. //.....................................................................
  2282. // Set the event's frame delay
  2283. //.....................................................................
  2284. OutList.First().Frame = Frame + frame_delay;
  2285. //.....................................................................
  2286. // Set the event's ID
  2287. //.....................................................................
  2288. OutList.First().ID = PlayerPtr->ID;
  2289. //.....................................................................
  2290. // Transfer the event in OutList to DoList, un-queue the OutList
  2291. // event. If the DoList is full, stop transferring immediately.
  2292. //.....................................................................
  2293. OutList.First().IsExecuted = 0;
  2294. if (!DoList.Add(OutList.First())) {
  2295. return (size);
  2296. }
  2297. #ifdef MIRROR_QUEUE
  2298. MirrorList.Add(OutList.First());
  2299. #endif
  2300. //.....................................................................
  2301. // Add event to the send packet
  2302. //.....................................................................
  2303. if (OutList.First().Type==EventClass::ADDPLAYER) {
  2304. memcpy ( ((char *)buf) + size, &OutList.First(), sizeof(EventClass) );
  2305. size += sizeof(EventClass);
  2306. memcpy ( ((char *)buf) + size,
  2307. OutList.First().Data.Variable.Pointer,
  2308. OutList.First().Data.Variable.Size);
  2309. size += OutList.First().Data.Variable.Size;
  2310. }
  2311. else {
  2312. memcpy ( ((char *)buf) + size, &OutList.First(), sizeof(EventClass) );
  2313. size += sizeof(EventClass);
  2314. }
  2315. //.....................................................................
  2316. // Increment our event counter; delete the last event from the queue
  2317. //.....................................................................
  2318. num++;
  2319. OutList.Next();
  2320. }
  2321. return (size);
  2322. } // end of Add_Uncompressed_Events
  2323. /***************************************************************************
  2324. * Add_Compressed_Events -- adds an compressed events to a packet *
  2325. * *
  2326. * INPUT: *
  2327. * buf buffer to store packet in *
  2328. * bufsize max size of buffer *
  2329. * frame_delay desired frame delay to attach to all outgoing packets *
  2330. * size reference to current packet size *
  2331. * cap max # events to process *
  2332. * *
  2333. * OUTPUT: *
  2334. * new size value *
  2335. * *
  2336. * WARNINGS: *
  2337. * This routine MUST check to be sure it doesn't overflow the buffer. *
  2338. * *
  2339. * HISTORY: *
  2340. * 11/21/1995 DRD : Created. *
  2341. *=========================================================================*/
  2342. static int Add_Compressed_Events(void *buf, int bufsize, int frame_delay,
  2343. int size, int cap)
  2344. {
  2345. int num = 0; // # of events processed
  2346. EventClass::EventType eventtype; // type of event being compressed
  2347. EventClass prevevent; // last event processed
  2348. int datasize; // size of element plucked from event union
  2349. int storedsize; // actual # bytes stored from event
  2350. unsigned char *unitsptr = NULL; // ptr to buffer pos to store mega. rep count
  2351. unsigned char numunits = 0; // megamission rep count value
  2352. bool missiondup = false; // flag: is this event a megamission repeat?
  2353. //------------------------------------------------------------------------
  2354. // clear previous event
  2355. //------------------------------------------------------------------------
  2356. memset (&prevevent, 0, sizeof(EventClass));
  2357. if (Debug_Print_Events) {
  2358. printf("\n(%d) Building Send Packet\n", Frame);
  2359. }
  2360. //------------------------------------------------------------------------
  2361. // Loop until there are no more events, we've processed our max # of
  2362. // events, or the buffer is full.
  2363. //------------------------------------------------------------------------
  2364. while (OutList.Count && (num < cap)) {
  2365. Keyboard->Check();
  2366. eventtype = OutList.First().Type;
  2367. datasize = EventClass::EventLength[ eventtype ];
  2368. //.....................................................................
  2369. // For a variable-sized event, pull the size from the event; otherwise,
  2370. // the size will be the data element size plus the event type value.
  2371. // (The other data elements in the event, Frame, ID, etc, are stored
  2372. // in the packet header.)
  2373. //.....................................................................
  2374. if (eventtype==EventClass::ADDPLAYER) {
  2375. storedsize = datasize + sizeof (EventClass::EventType) +
  2376. OutList.First().Data.Variable.Size;
  2377. }
  2378. else {
  2379. storedsize = datasize + sizeof (EventClass::EventType);
  2380. }
  2381. //.....................................................................
  2382. // MegaMission compression: MegaMissions are stored as:
  2383. // EventType
  2384. // Rep Count
  2385. // MegaMission structure (event # 1 only)
  2386. // Whom #2
  2387. // Whom #3
  2388. // Whom #4
  2389. // ...
  2390. // Whom #n
  2391. //.....................................................................
  2392. if (prevevent.Type == EventClass::MEGAMISSION) {
  2393. //..................................................................
  2394. // If previous & current events are both MegaMissions:
  2395. //..................................................................
  2396. if (eventtype == EventClass::MEGAMISSION) {
  2397. //...............................................................
  2398. // If the Mission, Target, & Destination are the same, compress
  2399. // the events into one:
  2400. // - Change datasize to the size of the 'Whom' field only
  2401. // - set total # bytes to store to the size of the 'Whom' only
  2402. // - increment the MegaMission rep count
  2403. // - set the MegaMission rep flag
  2404. //...............................................................
  2405. if (OutList.First().Data.MegaMission.Mission ==
  2406. prevevent.Data.MegaMission.Mission &&
  2407. OutList.First().Data.MegaMission.Target ==
  2408. prevevent.Data.MegaMission.Target &&
  2409. OutList.First().Data.MegaMission.Destination ==
  2410. prevevent.Data.MegaMission.Destination) {
  2411. #if (0)//PG
  2412. if (Debug_Print_Events) {
  2413. printf(" adding Whom:%x (%x) Mission:%s Target:%x (%x) Dest:%x (%x)\n",
  2414. OutList.First().Data.MegaMission.Whom.As_TARGET(),
  2415. OutList.First().Data.MegaMission.Whom,
  2416. MissionClass::Mission_Name(OutList.First().Data.MegaMission.Mission),
  2417. OutList.First().Data.MegaMission.Target.As_TARGET(),
  2418. OutList.First().Data.MegaMission.Target,
  2419. OutList.First().Data.MegaMission.Destination.As_TARGET(),
  2420. OutList.First().Data.MegaMission.Destination);
  2421. }
  2422. #endif
  2423. datasize = sizeof(prevevent.Data.MegaMission.Whom);
  2424. storedsize = datasize;
  2425. numunits++;
  2426. missiondup = true;
  2427. }
  2428. //...............................................................
  2429. // Data doesn't match; start a new run of MegaMissions:
  2430. // - Store previous MegaMission rep count
  2431. // - Init 'unitsptr' to buffer pos after next EventType
  2432. // - set total # bytes to store to 'datasize' + sizeof(EventType) +
  2433. // sizeof (numunits)
  2434. // - init the MegaMission rep count to 1
  2435. // - clear the MegaMission rep flag
  2436. //...............................................................
  2437. else {
  2438. if (Debug_Print_Events) {
  2439. printf(" New MEGAMISSION run:\n");
  2440. }
  2441. *unitsptr = numunits;
  2442. unitsptr = ((unsigned char *)buf) + size +
  2443. sizeof(EventClass::EventType);
  2444. storedsize += sizeof(numunits);
  2445. numunits = 1;
  2446. missiondup = false;
  2447. }
  2448. }
  2449. //..................................................................
  2450. // Previous event was a MegaMission, but this one isn't: end the
  2451. // run of MegaMissions:
  2452. // - Store previous MegaMission rep count
  2453. // - Clear variables
  2454. //..................................................................
  2455. else {
  2456. *unitsptr = numunits; // save # events in our run
  2457. unitsptr = NULL; // init other values
  2458. numunits = 0;
  2459. missiondup = false;
  2460. }
  2461. }
  2462. //.....................................................................
  2463. // The previous event is not a MEGAMISSION but the current event is:
  2464. // Set up a new run of MegaMissions:
  2465. // - Init 'unitsptr' to buffer pos after next EventType
  2466. // - set total # bytes to store to 'datasize' + sizeof(EventType) +
  2467. // sizeof (numunits)
  2468. // - init the MegaMission rep count to 1
  2469. // - clear the MegaMission rep flag
  2470. //.....................................................................
  2471. else if (eventtype == EventClass::MEGAMISSION) {
  2472. if (Debug_Print_Events) {
  2473. printf(" New MEGAMISSION run:\n");
  2474. }
  2475. unitsptr = ((unsigned char *)buf) + size +
  2476. sizeof(EventClass::EventType);
  2477. storedsize += sizeof(numunits);
  2478. numunits = 1;
  2479. missiondup = false;
  2480. }
  2481. //.....................................................................
  2482. // Will the next event exceed the size of the buffer? If so,
  2483. // stop compressing.
  2484. //.....................................................................
  2485. if ( (size + storedsize) > bufsize )
  2486. break;
  2487. //.....................................................................
  2488. // Set the event's frame delay (this is protocol-dependent)
  2489. //.....................................................................
  2490. if (Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {
  2491. OutList.First().Frame = ((Frame + frame_delay +
  2492. (Session.FrameSendRate - 1)) / Session.FrameSendRate) *
  2493. Session.FrameSendRate;
  2494. }
  2495. else {
  2496. OutList.First().Frame = Frame + frame_delay;
  2497. }
  2498. //.....................................................................
  2499. // Set the event's ID
  2500. //.....................................................................
  2501. OutList.First().ID = PlayerPtr->ID;
  2502. //.....................................................................
  2503. // Transfer the event in OutList to DoList, un-queue the OutList event.
  2504. // If the DoList is full, stop transferring immediately.
  2505. //.....................................................................
  2506. OutList.First().IsExecuted = 0;
  2507. if ( !DoList.Add( OutList.First() ) ) {
  2508. break;
  2509. }
  2510. #ifdef MIRROR_QUEUE
  2511. MirrorList.Add(OutList.First());
  2512. #endif
  2513. //---------------------------------------------------------------------
  2514. // Compress the event into the send packet buffer
  2515. //---------------------------------------------------------------------
  2516. switch ( eventtype ) {
  2517. //..................................................................
  2518. // RESPONSE_TIME: just use the Delay field of the FrameInfo union
  2519. //..................................................................
  2520. case (EventClass::RESPONSE_TIME):
  2521. *(EventClass::EventType *)( ((char *)buf) + size) = eventtype;
  2522. memcpy ( ((char *)buf) + size + sizeof(EventClass::EventType),
  2523. &OutList.First().Data.FrameInfo.Delay, datasize );
  2524. size += (datasize + sizeof(EventClass::EventType));
  2525. break;
  2526. //..................................................................
  2527. // MEGAMISSION:
  2528. //..................................................................
  2529. case (EventClass::MEGAMISSION):
  2530. //...............................................................
  2531. // Repeated mission in a run:
  2532. // - Update the rep count (in case we break out)
  2533. // - Copy the Whom field only
  2534. //...............................................................
  2535. if (missiondup) {
  2536. *unitsptr = numunits;
  2537. memcpy ( ((char *)buf) + size,
  2538. &OutList.First().Data.MegaMission.Whom, datasize );
  2539. size += datasize;
  2540. }
  2541. //...............................................................
  2542. // 1st mission in a run:
  2543. // - Init the rep count (in case we break out)
  2544. // - Set the EventType
  2545. // - Copy the MegaMission structure, leaving room for 'numunits'
  2546. //...............................................................
  2547. else {
  2548. *unitsptr = numunits;
  2549. *(EventClass::EventType *)( ((char *)buf) + size) = eventtype;
  2550. memcpy ( ((char *)buf) + size +
  2551. sizeof(EventClass::EventType) + sizeof(numunits),
  2552. &OutList.First().Data.MegaMission, datasize );
  2553. size += (datasize + sizeof(EventClass::EventType) + sizeof(numunits));
  2554. }
  2555. break;
  2556. //..................................................................
  2557. // Variable-sized packets: Copy the packet Size & the buffer
  2558. //..................................................................
  2559. case (EventClass::ADDPLAYER):
  2560. *(EventClass::EventType *)( ((char *)buf) + size) = eventtype;
  2561. memcpy ( ((char *)buf) + size + sizeof(EventClass::EventType),
  2562. &OutList.First().Data.Variable.Size, datasize );
  2563. size += (datasize + sizeof(EventClass::EventType));
  2564. memcpy ( ((char *)buf) + size,
  2565. OutList.First().Data.Variable.Pointer,
  2566. OutList.First().Data.Variable.Size);
  2567. size += OutList.First().Data.Variable.Size;
  2568. break;
  2569. //..................................................................
  2570. // Default case: Just copy over the data field from the union
  2571. //..................................................................
  2572. default:
  2573. *(EventClass::EventType *)( ((char *)buf) + size) = eventtype;
  2574. memcpy ( ((char *)buf) + size + sizeof(EventClass::EventType),
  2575. &OutList.First().Data, datasize );
  2576. size += (datasize + sizeof(EventClass::EventType));
  2577. break;
  2578. }
  2579. //---------------------------------------------------------------------
  2580. // update # events processed
  2581. //---------------------------------------------------------------------
  2582. num++;
  2583. //---------------------------------------------------------------------
  2584. // Update 'prevevent'
  2585. //---------------------------------------------------------------------
  2586. memcpy ( &prevevent, &OutList.First(), sizeof(EventClass) );
  2587. //---------------------------------------------------------------------
  2588. // Go to the next event to process
  2589. //---------------------------------------------------------------------
  2590. OutList.Next();
  2591. }
  2592. if (Debug_Print_Events) {
  2593. printf("\n");
  2594. }
  2595. return (size);
  2596. } // end of Add_Compressed_Events
  2597. /***************************************************************************
  2598. * Breakup_Receive_Packet -- Splits a big packet into little ones. *
  2599. * *
  2600. * INPUT: *
  2601. * buf buffer to break up *
  2602. * bufsize length of buffer *
  2603. * *
  2604. * OUTPUT: *
  2605. * # events added to queue, -1 if fatal error (queue is full) *
  2606. * (return value includes any FRAMEINFO packets encountered; *
  2607. * FRAMESYNC's are ignored) *
  2608. * *
  2609. * WARNINGS: *
  2610. * none. *
  2611. * *
  2612. * HISTORY: *
  2613. * 11/21/1995 BRR : Created. *
  2614. *=========================================================================*/
  2615. static int Breakup_Receive_Packet(void *buf, int bufsize )
  2616. {
  2617. int count = 0;
  2618. /*
  2619. ** is there enough leftover for another record
  2620. */
  2621. switch (Session.CommProtocol) {
  2622. case (COMM_PROTOCOL_SINGLE_NO_COMP):
  2623. count = Extract_Uncompressed_Events(buf, bufsize);
  2624. break;
  2625. default:
  2626. count = Extract_Compressed_Events(buf, bufsize);
  2627. break;
  2628. }
  2629. return (count);
  2630. } /* end of Breakup_Receive_Packet */
  2631. /***************************************************************************
  2632. * Extract_Uncompressed_Events -- extracts events from a packet *
  2633. * *
  2634. * INPUT: *
  2635. * buf buffer containing events to extract *
  2636. * bufsize length of 'buf' *
  2637. * *
  2638. * OUTPUT: *
  2639. * # events extracted *
  2640. * *
  2641. * WARNINGS: *
  2642. * none. *
  2643. * *
  2644. * HISTORY: *
  2645. * 11/21/1995 DRD : Created. *
  2646. *=========================================================================*/
  2647. static int Extract_Uncompressed_Events(void *buf, int bufsize)
  2648. {
  2649. int count = 0;
  2650. int pos = 0;
  2651. int leftover = bufsize;
  2652. EventClass *event;
  2653. //------------------------------------------------------------------------
  2654. // Loop until there are no more events in the packet
  2655. //------------------------------------------------------------------------
  2656. while (leftover >= sizeof(EventClass) ) {
  2657. Keyboard->Check();
  2658. event = (EventClass *)(((char *)buf) + pos);
  2659. //.....................................................................
  2660. // add event to the DoList, only if it's not a FRAMESYNC
  2661. // (but FRAMEINFO's do get added.)
  2662. //.....................................................................
  2663. if (event->Type != EventClass::FRAMESYNC) {
  2664. event->IsExecuted = 0;
  2665. //..................................................................
  2666. // Special processing for variable-sized events
  2667. //..................................................................
  2668. if (event->Type == EventClass::ADDPLAYER) {
  2669. event->Data.Variable.Pointer = new char[event->Data.Variable.Size];
  2670. memcpy (event->Data.Variable.Pointer,
  2671. ((char *)buf) + sizeof(EventClass),
  2672. event->Data.Variable.Size);
  2673. pos += event->Data.Variable.Size;
  2674. leftover -= event->Data.Variable.Size;
  2675. }
  2676. if (!DoList.Add( *event )) {
  2677. if (event->Type == EventClass::ADDPLAYER) {
  2678. delete [] event->Data.Variable.Pointer;
  2679. }
  2680. return (-1);
  2681. }
  2682. #ifdef MIRROR_QUEUE
  2683. MirrorList.Add(*event);
  2684. #endif
  2685. //..................................................................
  2686. // Keep count of how many events we add to the queue
  2687. //..................................................................
  2688. count++;
  2689. }
  2690. //.....................................................................
  2691. // Point to the next position in the buffer; decrement our 'leftover'
  2692. //.....................................................................
  2693. pos += sizeof(EventClass);
  2694. leftover -= sizeof(EventClass);
  2695. }
  2696. return (count);
  2697. } // end of Extract_Uncompressed_Events
  2698. /***************************************************************************
  2699. * Extract_Compressed_Events -- extracts events from a packet *
  2700. * *
  2701. * INPUT: *
  2702. * buf buffer containing events to extract *
  2703. * bufsize length of 'buf' *
  2704. * *
  2705. * OUTPUT: *
  2706. * # events extracted *
  2707. * *
  2708. * WARNINGS: *
  2709. * none. *
  2710. * *
  2711. * HISTORY: *
  2712. * 11/21/1995 DRD : Created. *
  2713. *=========================================================================*/
  2714. static int Extract_Compressed_Events(void *buf, int bufsize)
  2715. {
  2716. int pos = 0; // current buffer parsing position
  2717. int leftover = bufsize; // # bytes left to process
  2718. EventClass *event; // event ptr for parsing buffer
  2719. int count = 0; // # events processed
  2720. int datasize = 0; // size of data to copy
  2721. EventClass eventdata; // stores Frame, ID, etc
  2722. unsigned char numunits = 0; // # units stored in compressed MegaMissions
  2723. //------------------------------------------------------------------------
  2724. // Clear work event structure
  2725. //------------------------------------------------------------------------
  2726. memset (&eventdata, 0, sizeof(EventClass));
  2727. //------------------------------------------------------------------------
  2728. // Assume the first event is a FRAMEINFO event
  2729. // Init 'datasize' to the amount of data to copy, minus the EventType value
  2730. // For the 1st packet only, this will include all info before the Data
  2731. // union, plus the size of the FrameInfo structure, minus the EventType size.
  2732. //------------------------------------------------------------------------
  2733. datasize = (offsetof(EventClass, Data) +
  2734. size_of(EventClass, Data.FrameInfo)) - sizeof(EventClass::EventType);
  2735. event = (EventClass *)(((char *)buf) + pos);
  2736. while (leftover >= (datasize + (int)sizeof(EventClass::EventType)) ) {
  2737. Keyboard->Check();
  2738. //.....................................................................
  2739. // add event to the DoList, only if it's not a FRAMESYNC
  2740. // (but FRAMEINFO's do get added.)
  2741. //.....................................................................
  2742. if (event->Type != EventClass::FRAMESYNC) {
  2743. //..................................................................
  2744. // initialize the common data from the FRAMEINFO event
  2745. // keeping IsExecuted 0
  2746. //..................................................................
  2747. if (event->Type == EventClass::FRAMEINFO) {
  2748. eventdata.Frame = event->Frame;
  2749. eventdata.ID = event->ID;
  2750. //...............................................................
  2751. // Adjust position past the common data
  2752. //...............................................................
  2753. pos += (offsetof(EventClass, Data) -
  2754. sizeof(EventClass::EventType));
  2755. leftover -= (offsetof(EventClass, Data) -
  2756. sizeof(EventClass::EventType));
  2757. }
  2758. //..................................................................
  2759. // if MEGAMISSION event get the number of units (events to generate)
  2760. //..................................................................
  2761. else if (event->Type == EventClass::MEGAMISSION) {
  2762. numunits = *(((unsigned char *)buf) + pos + sizeof(eventdata.Type));
  2763. pos += sizeof(numunits);
  2764. leftover -= sizeof(numunits);
  2765. }
  2766. //..................................................................
  2767. // clear the union data portion of the event
  2768. //..................................................................
  2769. memset (&eventdata.Data, 0, sizeof(eventdata.Data));
  2770. eventdata.Type = event->Type;
  2771. datasize = EventClass::EventLength[ eventdata.Type ];
  2772. switch (eventdata.Type) {
  2773. case (EventClass::RESPONSE_TIME):
  2774. memcpy ( &eventdata.Data.FrameInfo.Delay,
  2775. ((char *)buf) + pos + sizeof(EventClass::EventType),
  2776. datasize );
  2777. break;
  2778. case (EventClass::ADDPLAYER):
  2779. memcpy ( &eventdata.Data.Variable.Size,
  2780. ((char *)buf) + pos + sizeof(EventClass::EventType),
  2781. datasize );
  2782. eventdata.Data.Variable.Pointer =
  2783. new char[eventdata.Data.Variable.Size];
  2784. memcpy (eventdata.Data.Variable.Pointer,
  2785. ((char *)buf) + pos + sizeof(EventClass::EventType) + datasize,
  2786. eventdata.Data.Variable.Size);
  2787. pos += eventdata.Data.Variable.Size;
  2788. leftover -= eventdata.Data.Variable.Size;
  2789. break;
  2790. case (EventClass::MEGAMISSION):
  2791. memcpy ( &eventdata.Data.MegaMission,
  2792. ((char *)buf) + pos + sizeof(EventClass::EventType),
  2793. datasize );
  2794. if (numunits > 1) {
  2795. pos += (datasize + sizeof(EventClass::EventType));
  2796. leftover -= (datasize + sizeof(EventClass::EventType));
  2797. datasize = sizeof(eventdata.Data.MegaMission.Whom);
  2798. while (numunits) {
  2799. Keyboard->Check();
  2800. if ( !DoList.Add( eventdata ) ) {
  2801. return (-1);
  2802. }
  2803. #ifdef MIRROR_QUEUE
  2804. MirrorList.Add( eventdata );
  2805. #endif
  2806. //......................................................
  2807. // Keep count of how many events we add to the queue
  2808. //......................................................
  2809. count++;
  2810. numunits--;
  2811. memcpy ( &eventdata.Data.MegaMission.Whom,
  2812. ((char *)buf) + pos, datasize );
  2813. //......................................................
  2814. // if one unit left fall thru to normal code
  2815. //......................................................
  2816. if (numunits == 1) {
  2817. datasize -= sizeof(EventClass::EventType);
  2818. break;
  2819. }
  2820. else {
  2821. pos += datasize;
  2822. leftover -= datasize;
  2823. }
  2824. }
  2825. }
  2826. break;
  2827. default:
  2828. memcpy ( &eventdata.Data,
  2829. ((char *)buf) + pos + sizeof(EventClass::EventType),
  2830. datasize );
  2831. break;
  2832. }
  2833. if ( !DoList.Add( eventdata ) ) {
  2834. if (eventdata.Type == EventClass::ADDPLAYER) {
  2835. delete [] eventdata.Data.Variable.Pointer;
  2836. }
  2837. return (-1);
  2838. }
  2839. #ifdef MIRROR_QUEUE
  2840. MirrorList.Add( eventdata );
  2841. #endif
  2842. //..................................................................
  2843. // Keep count of how many events we add to the queue
  2844. //..................................................................
  2845. count++;
  2846. pos += (datasize + sizeof(EventClass::EventType));
  2847. leftover -= (datasize + sizeof(EventClass::EventType));
  2848. if (leftover) {
  2849. event = (EventClass *)(((char *)buf) + pos);
  2850. datasize = EventClass::EventLength[ event->Type ];
  2851. if (event->Type == EventClass::MEGAMISSION) {
  2852. datasize += sizeof(numunits);
  2853. }
  2854. }
  2855. }
  2856. //.....................................................................
  2857. // FRAMESYNC event: This >should< be the only event in the buffer,
  2858. // and it will be uncompressed.
  2859. //.....................................................................
  2860. else {
  2861. pos += (datasize + sizeof(EventClass::EventType));
  2862. leftover -= (datasize + sizeof(EventClass::EventType));
  2863. event = (EventClass *)(((char *)buf) + pos);
  2864. //..................................................................
  2865. // size of FRAMESYNC event - EventType size
  2866. //..................................................................
  2867. datasize = (offsetof(EventClass, Data) +
  2868. size_of(EventClass, Data.FrameInfo)) -
  2869. sizeof(EventClass::EventType);
  2870. }
  2871. }
  2872. return (count);
  2873. } // end of Extract_Compressed_Events
  2874. /***************************************************************************
  2875. * Execute_DoList -- Executes commands from the DoList *
  2876. * *
  2877. * This routine executes any events in the DoList that need to be executed *
  2878. * on the current game frame. The events must be executed in a special *
  2879. * order, so that all systems execute all events in exactly the same *
  2880. * order. *
  2881. * *
  2882. * This routine also handles checking the Game CRC sent by other systems *
  2883. * against my own, to be sure we're still in sync. *
  2884. * *
  2885. * INPUT: *
  2886. * max_houses # houses to execute commands for *
  2887. * base_house HousesType to start with *
  2888. * net ptr to connection manager; NULL if none *
  2889. * skip_crc a frame-based countdown timer; if it's non-zero, the *
  2890. * CRC check will be skipped. Ignored if NULL. *
  2891. * their_frame array of their frame #'s *
  2892. * their_sent array of # commands they've sent *
  2893. * their_recv array of # commands I've received from them *
  2894. * *
  2895. * (their_xxx are ignored if 'net' is NULL.) *
  2896. * *
  2897. * OUTPUT: *
  2898. * 1 = OK, 0 = some error occurred (CRC error, packet rcv'd too late.) *
  2899. * *
  2900. * WARNINGS: *
  2901. * *
  2902. * HISTORY: *
  2903. * 11/21/1995 BRR : Created. *
  2904. *=========================================================================*/
  2905. static int Execute_DoList(int max_houses, HousesType base_house,
  2906. ConnManClass *net, CDTimerClass<FrameTimerClass> *skip_crc,
  2907. long *their_frame, unsigned short *their_sent, unsigned short *their_recv)
  2908. {
  2909. HousesType house;
  2910. HouseClass *hptr;
  2911. int i,j,k;
  2912. int index;
  2913. int check_crc;
  2914. Check_Mirror();
  2915. #if(TIMING_FIX)
  2916. //
  2917. // If MPlayerMaxAhead is recomputed such that it increases, the systems
  2918. // may try to free-run to the new MaxAhead value. If so, they may miss
  2919. // an event that was generated after the TIMING event was created, but
  2920. // before it executed; this event will be scheduled with the older,
  2921. // shorter MaxAhead value. If a system doesn't receive this event, it
  2922. // may execute past the frame it's scheduled to execute on, creating
  2923. // a Packet-Recieved-Too-Late error. To prevent this, find any events
  2924. // that are scheduled to execute during this "period of vulnerability",
  2925. // and re-schedule for the end of that period.
  2926. //
  2927. for (j = 0; j < DoList.Count; j++) {
  2928. if (DoList[j].Type != EventClass::FRAMEINFO &&
  2929. DoList[j].Frame > (unsigned)NewMaxAheadFrame1 &&
  2930. DoList[j].Frame < (unsigned)NewMaxAheadFrame2) {
  2931. DoList[j].Frame = (unsigned)NewMaxAheadFrame2;
  2932. #ifdef MIRROR_QUEUE
  2933. MirrorList[j].Frame = NewMaxAheadFrame2;
  2934. #endif
  2935. }
  2936. }
  2937. #endif
  2938. //------------------------------------------------------------------------
  2939. // Execute the DoList. Events must be executed in the same order on all
  2940. // systems; so, execute them in the order of the HouseClass array. This
  2941. // array is stored in the same order on all systems.
  2942. //------------------------------------------------------------------------
  2943. for (i = 0; i < max_houses; i++) {
  2944. //.....................................................................
  2945. // Convert our index into a HousesType value
  2946. //.....................................................................
  2947. house = (HousesType)(i + base_house);
  2948. hptr = HouseClass::As_Pointer(house);
  2949. //.....................................................................
  2950. // If for some reason this house doesn't exist, skip it.
  2951. // Also, if this house has exited the game, skip it. (The user can
  2952. // generate events after he exits, because the exit event is scheduled
  2953. // at least FrameSendRate*3 frames ahead. If one system gets these
  2954. // packets & another system doesn't, they'll go out of sync because
  2955. // they aren't checking the CommandCount for that house, since that
  2956. // house isn't connected any more.)
  2957. //.....................................................................
  2958. if (!hptr) {
  2959. continue;
  2960. }
  2961. if (!hptr->IsHuman) {
  2962. continue;
  2963. }
  2964. //.....................................................................
  2965. // Loop through all events
  2966. //.....................................................................
  2967. for (j = 0; j < DoList.Count; j++) {
  2968. if (net)
  2969. Update_Queue_Mono (net, 6);
  2970. //..................................................................
  2971. // If this event was from the currently-executing player ID, and it's
  2972. // time to execute it, execute it.
  2973. //..................................................................
  2974. if (DoList[j].ID == hptr->ID && (unsigned) Frame >= DoList[j].Frame &&
  2975. !DoList[j].IsExecuted) {
  2976. //...............................................................
  2977. // Error if it's too late to execute this packet!
  2978. // (Hack: disable this check for solo or skirmish mode.)
  2979. //...............................................................
  2980. if ((unsigned)Frame > DoList[j].Frame && DoList[j].Type !=
  2981. EventClass::FRAMEINFO && Session.Type != GAME_NORMAL &&
  2982. Session.Type != GAME_SKIRMISH) {
  2983. #if(TEN)
  2984. Send_TEN_Packet_Too_Late();
  2985. #endif // TEN
  2986. #if(MPATH)
  2987. //Send_MPATH_Packet_Too_Late();
  2988. #endif // MPATH
  2989. Dump_Packet_Too_Late_Stuff(&DoList[j], net, their_frame,
  2990. their_sent, their_recv);
  2991. WWMessageBox().Process (TXT_PACKET_TOO_LATE);
  2992. return (0);
  2993. }
  2994. //...............................................................
  2995. // Only execute EXIT & OPTIONS commands if they're from myself.
  2996. //...............................................................
  2997. if (DoList[j].Type==EventClass::EXIT ||
  2998. DoList[j].Type==EventClass::OPTIONS) {
  2999. #ifdef WIN32
  3000. if (DoList[j].Type==EventClass::EXIT) {
  3001. /*
  3002. ** Flag that this house lost because it quit.
  3003. */
  3004. HousesType quithouse;
  3005. HouseClass *quithptr;
  3006. for (int player = 0; player < max_houses ; player++) {
  3007. quithouse = (HousesType)(player + base_house);
  3008. quithptr = HouseClass::As_Pointer(quithouse);
  3009. if (!quithptr) {
  3010. continue;
  3011. }
  3012. if (quithptr->ID == DoList[j].ID) {
  3013. quithptr->IsGiverUpper = true;
  3014. break;
  3015. }
  3016. }
  3017. /*
  3018. ** Send the game statistics packet now since the game is effectivly over
  3019. */
  3020. if (Session.Players.Count() == 2 &&
  3021. Session.Type == GAME_INTERNET &&
  3022. !GameStatisticsPacketSent) {
  3023. Register_Game_End_Time();
  3024. Send_Statistics_Packet(); // Event - player aborted, and there were only 2 left.
  3025. }
  3026. }
  3027. #endif //WIN32
  3028. if (Debug_Print_Events) {
  3029. if (DoList[j].Type==EventClass::EXIT) {
  3030. printf("(%d) Executing EXIT, ID:%d (%s), EvFrame:%d\n",
  3031. Frame,
  3032. DoList[j].ID,
  3033. (HouseClass::As_Pointer((HousesType)(DoList[j].ID)))->IniName,
  3034. DoList[j].Frame);
  3035. }
  3036. }
  3037. if (DoList[j].ID == PlayerPtr->ID) {
  3038. DoList[j].Execute();
  3039. } else if (DoList[j].Type==EventClass::EXIT) {
  3040. //............................................................
  3041. // If this EXIT event isn't from myself, destroy the connection
  3042. // for that player. The HousesType for this event is the
  3043. // connection ID.
  3044. //............................................................
  3045. if (Session.Type == GAME_MODEM ||
  3046. Session.Type == GAME_NULL_MODEM) {
  3047. //PG Destroy_Null_Connection( house, 0 );
  3048. } else if ((Session.Type == GAME_IPX ||
  3049. Session.Type == GAME_INTERNET ||
  3050. Session.Type == GAME_TEN ||
  3051. Session.Type == GAME_MPATH) && net) {
  3052. index = net->Connection_Index (house);
  3053. if (index != -1) {
  3054. for (k = index; k < net->Num_Connections() - 1; k++) {
  3055. their_frame[k] = their_frame[k+1];
  3056. their_sent[k] = their_sent[k+1];
  3057. their_recv[k] = their_recv[k+1];
  3058. }
  3059. if (Session.Type == GAME_IPX ||
  3060. Session.Type == GAME_INTERNET) {
  3061. Destroy_Connection(house,0);
  3062. }
  3063. #if(TEN)
  3064. else if (Session.Type == GAME_TEN) {
  3065. Destroy_TEN_Connection(house,0);
  3066. }
  3067. #endif // TEN
  3068. #if(MPATH)
  3069. else if (Session.Type == GAME_MPATH) {
  3070. Destroy_MPATH_Connection(house,0);
  3071. }
  3072. #endif // MPATH
  3073. }
  3074. }
  3075. //
  3076. // Special case for recording playback: turn the house over
  3077. // to the computer.
  3078. //
  3079. if (Session.Play && DoList[j].Type==EventClass::EXIT) {
  3080. hptr->IsHuman = false;
  3081. hptr->IQ = Rule.MaxIQ;
  3082. hptr->Computer_Paranoid();
  3083. strcpy (hptr->IniName,Text_String(TXT_COMPUTER));
  3084. Session.NumPlayers--;
  3085. }
  3086. }
  3087. }
  3088. //...............................................................
  3089. // For a FRAMEINFO event, check the CRC value.
  3090. //...............................................................
  3091. else if (DoList[j].Type == EventClass::FRAMEINFO) {
  3092. //............................................................
  3093. // Skip the CRC check if we're less than 32 frames into the game;
  3094. // this will prevent a newly-loaded modem game from instantly
  3095. // going out of sync, if the games were saved at different
  3096. // frame numbers.
  3097. //............................................................
  3098. if (!skip_crc || *skip_crc == 0) {
  3099. check_crc = 1;
  3100. }
  3101. else {
  3102. check_crc = 0;
  3103. }
  3104. if (check_crc
  3105. && DoList[j].Frame == Frame
  3106. && DoList[j].Data.FrameInfo.Delay < 32) {
  3107. index = ((DoList[j].Frame - DoList[j].Data.FrameInfo.Delay) &
  3108. 0x001f);
  3109. if (CRC[index] != DoList[j].Data.FrameInfo.CRC) {
  3110. Print_CRCs(&DoList[j]);
  3111. #if(TEN)
  3112. Send_TEN_Out_Of_Sync();
  3113. #endif // TEN
  3114. #if(MPATH)
  3115. //Send_MPATH_Out_Of_Sync();
  3116. #endif // MPATH
  3117. #if (0)//PG
  3118. if (WWMessageBox().Process (TXT_OUT_OF_SYNC,
  3119. TXT_CONTINUE, TXT_STOP) == 0) {
  3120. if (Session.Type == GAME_MODEM ||
  3121. Session.Type == GAME_NULL_MODEM) {
  3122. //PG Destroy_Null_Connection( house, -1 );
  3123. Shutdown_Modem();
  3124. Session.Type = GAME_NORMAL;
  3125. }
  3126. else if ((Session.Type == GAME_IPX ||
  3127. Session.Type == GAME_INTERNET) && net) {
  3128. while (net->Num_Connections()) {
  3129. Keyboard->Check();
  3130. Destroy_Connection (net->Connection_ID(0), -1);
  3131. }
  3132. }
  3133. #if(TEN)
  3134. else if (Session.Type == GAME_TEN && net) {
  3135. while (net->Num_Connections()) {
  3136. Destroy_TEN_Connection (net->Connection_ID(0), -1);
  3137. }
  3138. }
  3139. #endif
  3140. #if(MPATH)
  3141. else if (Session.Type == GAME_MPATH && net) {
  3142. while (net->Num_Connections()) {
  3143. Destroy_MPATH_Connection (net->Connection_ID(0), -1);
  3144. }
  3145. }
  3146. #endif
  3147. Map.Flag_To_Redraw(true);
  3148. }
  3149. else {
  3150. return (0);
  3151. }
  3152. #endif
  3153. return (1);
  3154. }
  3155. }
  3156. }
  3157. //...............................................................
  3158. // Execute other commands
  3159. //...............................................................
  3160. else {
  3161. DoList[j].Execute();
  3162. }
  3163. //...............................................................
  3164. // Mark this event as executed.
  3165. //...............................................................
  3166. DoList[j].IsExecuted = 1;
  3167. #ifdef MIRROR_QUEUE
  3168. MirrorList[j].IsExecuted = 1;
  3169. #endif
  3170. }
  3171. }
  3172. }
  3173. return (1);
  3174. } // end of Execute_DoList
  3175. /***************************************************************************
  3176. * Clean_DoList -- Cleans out old events from the DoList *
  3177. * *
  3178. * Currently, an event can only be removed from the DoList if it's at the *
  3179. * head of the list; and event can't be removed from the middle. So, *
  3180. * this routine loops as long as the next event in the DoList has been *
  3181. * executed, it's removed. *
  3182. * *
  3183. * INPUT: *
  3184. * net ptr to connection manager; ignored if NULL *
  3185. * *
  3186. * OUTPUT: *
  3187. * none. *
  3188. * *
  3189. * WARNINGS: *
  3190. * none. *
  3191. * *
  3192. * HISTORY: *
  3193. * 11/21/1995 BRR : Created. *
  3194. *=========================================================================*/
  3195. static void Clean_DoList(ConnManClass *net)
  3196. {
  3197. while (DoList.Count) {
  3198. Keyboard->Check();
  3199. if (net)
  3200. Update_Queue_Mono (net, 7);
  3201. //.....................................................................
  3202. // Discard events that have been executed, OR it's too late to execute.
  3203. // (This happens if another player exits the game; he'll leave FRAMEINFO
  3204. // events lying around in my queue. They won't have been "executed",
  3205. // because his IPX connection was destroyed.)
  3206. //.....................................................................
  3207. if ( (DoList.First().IsExecuted) || ((unsigned)Frame > DoList.First().Frame) ) {
  3208. DoList.Next();
  3209. #ifdef MIRROR_QUEUE
  3210. MirrorList.Next();
  3211. #endif
  3212. }
  3213. else {
  3214. break;
  3215. }
  3216. }
  3217. } // end of Clean_DoList
  3218. /***************************************************************************
  3219. * Queue_Record -- Records the DoList to disk *
  3220. * *
  3221. * This routine just saves any events in the DoList to disk; we can later *
  3222. * "play back" the recording just be pulling events from disk rather than *
  3223. * from the network! *
  3224. * *
  3225. * INPUT: *
  3226. * none. *
  3227. * *
  3228. * OUTPUT: *
  3229. * none. *
  3230. * *
  3231. * WARNINGS: *
  3232. * none. *
  3233. * *
  3234. * HISTORY: *
  3235. * 08/14/1995 BRR : Created. *
  3236. *=========================================================================*/
  3237. static void Queue_Record(void)
  3238. {
  3239. int i,j;
  3240. //------------------------------------------------------------------------
  3241. // Compute # of events to save this frame
  3242. //------------------------------------------------------------------------
  3243. j = 0;
  3244. for (i = 0; i < DoList.Count; i++) {
  3245. if (Frame == DoList[i].Frame && !DoList[i].IsExecuted) {
  3246. j++;
  3247. }
  3248. }
  3249. //------------------------------------------------------------------------
  3250. // Save the # of events, then all events.
  3251. //------------------------------------------------------------------------
  3252. Session.RecordFile.Write (&j,sizeof(j));
  3253. for (i = 0; i < DoList.Count; i++) {
  3254. if (Frame == DoList[i].Frame && !DoList[i].IsExecuted) {
  3255. Session.RecordFile.Write (&DoList[i],sizeof (EventClass));
  3256. j--;
  3257. }
  3258. }
  3259. } /* end of Queue_Record */
  3260. /***************************************************************************
  3261. * Queue_Playback -- plays back queue entries from a record file *
  3262. * *
  3263. * This routine reads events from disk, putting them into the DoList; *
  3264. * it then executes the DoList just like the network version does. The *
  3265. * result is that the game "plays back" like a recording. *
  3266. * *
  3267. * This routine detects mouse motion and stops playback, so it can work *
  3268. * like an "attract" mode, showing a demo of the game itself. *
  3269. * *
  3270. * INPUT: *
  3271. * none. *
  3272. * *
  3273. * OUTPUT: *
  3274. * none. *
  3275. * *
  3276. * WARNINGS: *
  3277. * none. *
  3278. * *
  3279. * HISTORY: *
  3280. * 05/15/1995 BRR : Created. *
  3281. *=========================================================================*/
  3282. static void Queue_Playback(void)
  3283. {
  3284. int numevents;
  3285. EventClass event;
  3286. int i;
  3287. int ok;
  3288. static int mx,my;
  3289. int max_houses;
  3290. HousesType base_house;
  3291. int key;
  3292. int testframe;
  3293. //------------------------------------------------------------------------
  3294. // If the user hits ESC, stop the playback
  3295. //------------------------------------------------------------------------
  3296. if (Keyboard->Check()) {
  3297. key = Keyboard->Get();
  3298. if (key == KA_ESC || Session.Attract) {
  3299. GameActive = 0;
  3300. return;
  3301. }
  3302. }
  3303. //------------------------------------------------------------------------
  3304. // If we're in "Attract" mode, and the user moves the mouse, stop the
  3305. // playback.
  3306. //------------------------------------------------------------------------
  3307. if (Session.Attract && Frame > 0 &&
  3308. (mx != Get_Mouse_X() || my != Get_Mouse_Y())) {
  3309. GameActive = 0;
  3310. return;
  3311. }
  3312. mx = Get_Mouse_X();
  3313. my = Get_Mouse_Y();
  3314. //------------------------------------------------------------------------
  3315. // Compute the Game's CRC
  3316. //------------------------------------------------------------------------
  3317. Compute_Game_CRC();
  3318. CRC[Frame & 0x001f] = GameCRC;
  3319. //------------------------------------------------------------------------
  3320. // If we've reached the CRC print frame, do so & exit
  3321. //------------------------------------------------------------------------
  3322. if (Frame >= Session.TrapPrintCRC) {
  3323. Print_CRCs(NULL);
  3324. Prog_End("Queue_Playback reached CRC print frame", true);
  3325. Emergency_Exit(0);
  3326. }
  3327. //------------------------------------------------------------------------
  3328. // Don't read anything the first time through (since the Queue_AI_Network
  3329. // routine didn't write anything the first time through); do this after the
  3330. // CRC is computed, since we'll still need a CRC for Frame 0.
  3331. //------------------------------------------------------------------------
  3332. if (Frame==0 && Session.Type!=GAME_NORMAL) {
  3333. return;
  3334. }
  3335. //------------------------------------------------------------------------
  3336. // Only process every 'FrameSendRate' frames
  3337. //------------------------------------------------------------------------
  3338. testframe = ((Frame + (Session.FrameSendRate - 1)) /
  3339. Session.FrameSendRate) * Session.FrameSendRate;
  3340. if ( (Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH) &&
  3341. Session.CommProtocol == COMM_PROTOCOL_MULTI_E_COMP) {
  3342. if (Frame != testframe) {
  3343. return;
  3344. }
  3345. }
  3346. //------------------------------------------------------------------------
  3347. // Read the DoList from disk
  3348. //------------------------------------------------------------------------
  3349. ok = 1;
  3350. if (Session.RecordFile.Read (&numevents, sizeof(numevents)) ==
  3351. sizeof(numevents)) {
  3352. for (i = 0; i < numevents; i++) {
  3353. if (Session.RecordFile.Read (&event, sizeof(EventClass)) ==
  3354. sizeof(EventClass)) {
  3355. event.IsExecuted = 0;
  3356. DoList.Add (event);
  3357. #ifdef MIRROR_QUEUE
  3358. MirrorList.Add(event);
  3359. #endif
  3360. }
  3361. else {
  3362. ok = 0;
  3363. break;
  3364. }
  3365. }
  3366. }
  3367. else {
  3368. ok = 0;
  3369. }
  3370. if (!ok) {
  3371. GameActive = 0;
  3372. return;
  3373. }
  3374. //------------------------------------------------------------------------
  3375. // Execute the DoList; if an error occurs, bail out.
  3376. //------------------------------------------------------------------------
  3377. if (Session.Type == GAME_NORMAL) {
  3378. max_houses = 1;
  3379. base_house = PlayerPtr->Class->House;
  3380. }
  3381. else {
  3382. max_houses = Session.MaxPlayers;
  3383. base_house = HOUSE_MULTI1;
  3384. }
  3385. if (!Execute_DoList(max_houses, base_house, NULL, NULL, NULL, NULL, NULL)) {
  3386. GameActive = 0;
  3387. return;
  3388. }
  3389. //------------------------------------------------------------------------
  3390. // Clean out the DoList
  3391. //------------------------------------------------------------------------
  3392. Clean_DoList(NULL);
  3393. } /* end of Queue_Playback */
  3394. /***************************************************************************
  3395. * Compute_Game_CRC -- Computes a CRC value of the entire game. *
  3396. * *
  3397. * INPUT: *
  3398. * none. *
  3399. * *
  3400. * OUTPUT: *
  3401. * none. *
  3402. * *
  3403. * WARNINGS: *
  3404. * none. *
  3405. * *
  3406. * HISTORY: *
  3407. * 05/09/1995 BRR : Created. *
  3408. *=========================================================================*/
  3409. static void Compute_Game_CRC(void)
  3410. {
  3411. int i,j;
  3412. VesselClass *vessp;
  3413. InfantryClass *infp;
  3414. UnitClass *unitp;
  3415. BuildingClass *bldgp;
  3416. ObjectClass *objp;
  3417. HouseClass *housep;
  3418. GameCRC = 0;
  3419. //------------------------------------------------------------------------
  3420. // Infantry
  3421. //------------------------------------------------------------------------
  3422. for (i = 0; i < Infantry.Count(); i++) {
  3423. infp = (InfantryClass *)Infantry.Active_Ptr(i);
  3424. Add_CRC (&GameCRC, (int)infp->Coord + (int)infp->PrimaryFacing);
  3425. Add_CRC (&GameCRC, (int)infp->Speed + (int)infp->NavCom);
  3426. Add_CRC (&GameCRC, (int)infp->Mission + (int)infp->TarCom);
  3427. }
  3428. //------------------------------------------------------------------------
  3429. // Units
  3430. //------------------------------------------------------------------------
  3431. for (i = 0; i < Units.Count(); i++) {
  3432. unitp = (UnitClass *)Units.Active_Ptr(i);
  3433. Add_CRC (&GameCRC, (int)unitp->Coord + (int)unitp->PrimaryFacing +
  3434. (int)unitp->SecondaryFacing);
  3435. }
  3436. //------------------------------------------------------------------------
  3437. // Shippies
  3438. //------------------------------------------------------------------------
  3439. for (i = 0; i < Vessels.Count(); i++) {
  3440. vessp = (VesselClass *)Vessels.Active_Ptr(i);
  3441. Add_CRC (&GameCRC, (int)vessp->Coord + (int)vessp->PrimaryFacing);
  3442. Add_CRC (&GameCRC, (int)vessp->Speed + (int)vessp->NavCom);
  3443. Add_CRC (&GameCRC, (int)vessp->Strength);
  3444. Add_CRC (&GameCRC, (int)vessp->Mission + (int)vessp->TarCom);
  3445. }
  3446. //------------------------------------------------------------------------
  3447. // Buildings
  3448. //------------------------------------------------------------------------
  3449. for (i = 0; i < Buildings.Count(); i++) {
  3450. bldgp = (BuildingClass *)Buildings.Active_Ptr(i);
  3451. Add_CRC (&GameCRC, (int)bldgp->Coord + (int)bldgp->PrimaryFacing);
  3452. }
  3453. //------------------------------------------------------------------------
  3454. // Houses
  3455. //------------------------------------------------------------------------
  3456. for (i = 0; i < Houses.Count(); i++) {
  3457. housep = (HouseClass *)Houses.Active_Ptr(i);
  3458. Add_CRC (&GameCRC, (int)housep->Credits + (int)housep->Power +
  3459. (int)housep->Drain);
  3460. }
  3461. //------------------------------------------------------------------------
  3462. // Map Layers
  3463. //------------------------------------------------------------------------
  3464. for (i = 0; i < LAYER_COUNT; i++) {
  3465. for (j = 0; j < Map.Layer[i].Count(); j++) {
  3466. objp = Map.Layer[i][j];
  3467. Add_CRC (&GameCRC, (int)objp->Coord + (int)objp->What_Am_I());
  3468. }
  3469. }
  3470. //------------------------------------------------------------------------
  3471. // Logic Layers
  3472. //------------------------------------------------------------------------
  3473. for (i = 0; i < Logic.Count(); i++) {
  3474. objp = Logic[i];
  3475. Add_CRC (&GameCRC, (int)objp->Coord + (int)objp->What_Am_I());
  3476. }
  3477. //------------------------------------------------------------------------
  3478. // A random #
  3479. //------------------------------------------------------------------------
  3480. // Add_CRC(&GameCRC, Scen.RandomNumber.Seed);
  3481. Add_CRC(&GameCRC, Scen.RandomNumber);
  3482. } /* end of Compute_Game_CRC */
  3483. /***************************************************************************
  3484. * Add_CRC -- Adds a value to a CRC *
  3485. * *
  3486. * INPUT: *
  3487. * crc ptr to crc *
  3488. * val value to add *
  3489. * *
  3490. * OUTPUT: *
  3491. * none *
  3492. * *
  3493. * WARNINGS: *
  3494. * none *
  3495. * *
  3496. * HISTORY: *
  3497. * 05/09/1995 BRR : Created. *
  3498. *=========================================================================*/
  3499. void Add_CRC(unsigned long *crc, unsigned long val)
  3500. {
  3501. int hibit;
  3502. if ( (*crc) & 0x80000000) {
  3503. hibit = 1;
  3504. }
  3505. else {
  3506. hibit = 0;
  3507. }
  3508. (*crc) <<= 1;
  3509. (*crc) += val;
  3510. (*crc) += hibit;
  3511. } /* end of Add_CRC */
  3512. /***************************************************************************
  3513. * Print_CRCs -- Prints a data file for finding Sync Bugs *
  3514. * *
  3515. * INPUT: *
  3516. * ev -- event to display *
  3517. * *
  3518. * OUTPUT: *
  3519. * none *
  3520. * *
  3521. * WARNINGS: *
  3522. * none *
  3523. * *
  3524. * HISTORY: *
  3525. * 05/09/1995 BRR : Created. *
  3526. *=========================================================================*/
  3527. static void Print_CRCs(EventClass *ev)
  3528. {
  3529. int i,j;
  3530. InfantryClass *infp;
  3531. UnitClass *unitp;
  3532. VesselClass *vesselp;
  3533. BuildingClass *bldgp;
  3534. ObjectClass *objp;
  3535. FILE *fp;
  3536. HouseClass *housep;
  3537. HousesType house;
  3538. int color;
  3539. Mono_Clear_Screen();
  3540. Mono_Set_Cursor (0,0);
  3541. fp = fopen("OUT.TXT","wt");
  3542. if (fp==NULL) {
  3543. return;
  3544. }
  3545. for (i = 0; i < 32; i++) {
  3546. fprintf(fp,"CRC[%d]=%x\n",i,CRC[i]);
  3547. }
  3548. //
  3549. // Houses
  3550. //
  3551. for (house = HOUSE_MULTI1; house <= HOUSE_MULTI8; house++) {
  3552. GameCRC = 0;
  3553. housep = HouseClass::As_Pointer (house);
  3554. if (housep) {
  3555. HousesType actlike = housep->ActLike;
  3556. color = housep->RemapColor;
  3557. fprintf(fp,"%s: IsHuman:%d Color:%s ID:%d ActLike:%s\n",
  3558. housep->IniName,
  3559. housep->IsHuman,
  3560. ColorNames[color],
  3561. housep->ID,
  3562. HouseClass::As_Pointer(actlike)->Class->Name());
  3563. Add_CRC (&GameCRC, (int)housep->Credits + (int)housep->Power +
  3564. (int)housep->Drain);
  3565. Mono_Printf("House %s:%x\n",housep->Class->Name(),GameCRC);
  3566. }
  3567. }
  3568. //
  3569. // Infantry
  3570. //
  3571. for (house = HOUSE_MULTI1; house <= HOUSE_MULTI8; house++) {
  3572. housep = HouseClass::As_Pointer (house);
  3573. if (housep) {
  3574. GameCRC = 0;
  3575. fprintf(fp,"-------------------- %s Infantry -------------------\n",
  3576. housep->Class->Name());
  3577. for (i = 0; i < Infantry.Count(); i++) {
  3578. infp = (InfantryClass *)Infantry.Active_Ptr(i);
  3579. if (infp->Owner()==house) {
  3580. Add_CRC (&GameCRC, (int)infp->Coord + (int)infp->PrimaryFacing);
  3581. Add_CRC (&GameCRC, (int)infp->Speed + (int)infp->NavCom);
  3582. Add_CRC (&GameCRC, (int)infp->Mission + (int)infp->TarCom);
  3583. fprintf(fp,"COORD:%x Facing:%d Mission:%d Type:%d Tgt:%x Speed:%d NavCom:%x\n",
  3584. infp->Coord,(int)infp->PrimaryFacing,infp->Get_Mission(),
  3585. infp->Class->Type, infp->As_Target(), infp->Speed, infp->NavCom);
  3586. }
  3587. }
  3588. Mono_Printf("%s Infantry:%x\n",housep->Class->Name(),GameCRC);
  3589. }
  3590. }
  3591. //
  3592. // Units
  3593. //
  3594. for (house = HOUSE_MULTI1; house <= HOUSE_MULTI8; house++) {
  3595. housep = HouseClass::As_Pointer (house);
  3596. if (housep) {
  3597. GameCRC = 0;
  3598. fprintf(fp,"-------------------- %s Units -------------------\n",
  3599. housep->Class->Name());
  3600. for (i = 0; i < Units.Count(); i++) {
  3601. unitp = (UnitClass *)Units.Active_Ptr(i);
  3602. if (unitp->Owner()==house) {
  3603. Add_CRC (&GameCRC, (int)unitp->Coord + (int)unitp->PrimaryFacing +
  3604. (int)unitp->SecondaryFacing);
  3605. fprintf(fp,
  3606. "COORD:%x Facing:%d Facing2:%d Mission:%d Type:%d Tgt:%x\n",
  3607. unitp->Coord,(int)unitp->PrimaryFacing,
  3608. (int)unitp->SecondaryFacing,unitp->Get_Mission(),
  3609. unitp->Class->Type, unitp->As_Target());
  3610. }
  3611. }
  3612. Mono_Printf("%s Units:%x\n",housep->Class->Name(),GameCRC);
  3613. }
  3614. }
  3615. //
  3616. // Vessels
  3617. //
  3618. for (house = HOUSE_MULTI1; house <= HOUSE_MULTI8; house++) {
  3619. housep = HouseClass::As_Pointer (house);
  3620. if (housep) {
  3621. GameCRC = 0;
  3622. fprintf(fp,"-------------------- %s Vessels -------------------\n",
  3623. housep->Class->Name());
  3624. for (i = 0; i < Vessels.Count(); i++) {
  3625. vesselp = (VesselClass *)Vessels.Active_Ptr(i);
  3626. if (vesselp->Owner()==house) {
  3627. Add_CRC (&GameCRC, (int)vesselp->Coord + (int)vesselp->PrimaryFacing);
  3628. Add_CRC (&GameCRC, (int)vesselp->Speed + (int)vesselp->NavCom);
  3629. Add_CRC (&GameCRC, (int)vesselp->Strength);
  3630. Add_CRC (&GameCRC, (int)vesselp->Mission + (int)vesselp->TarCom);
  3631. fprintf(fp,
  3632. "COORD:%x Facing:%d Mission:%d Strength:%d Type:%d Tgt:%x\n",
  3633. vesselp->Coord,(int)vesselp->PrimaryFacing,
  3634. vesselp->Get_Mission(), vesselp->Strength,
  3635. vesselp->Class->Type, vesselp->As_Target());
  3636. }
  3637. }
  3638. Mono_Printf("%s Vessels:%x\n",housep->Class->Name(),GameCRC);
  3639. }
  3640. }
  3641. //
  3642. // Buildings
  3643. //
  3644. for (house = HOUSE_MULTI1; house <= HOUSE_MULTI8; house++) {
  3645. housep = HouseClass::As_Pointer (house);
  3646. if (housep) {
  3647. GameCRC = 0;
  3648. fprintf(fp,"-------------------- %s Buildings -------------------\n",
  3649. housep->Class->Name());
  3650. for (i = 0; i < Buildings.Count(); i++) {
  3651. bldgp = (BuildingClass *)Buildings.Active_Ptr(i);
  3652. if (bldgp->Owner()==house) {
  3653. Add_CRC (&GameCRC, (int)bldgp->Coord + (int)bldgp->PrimaryFacing);
  3654. fprintf(fp,"COORD:%x Facing:%d Mission:%d Type:%d Tgt:%x\n",
  3655. bldgp->Coord,(int)bldgp->PrimaryFacing,bldgp->Get_Mission(),
  3656. bldgp->Class->Type, bldgp->As_Target());
  3657. }
  3658. }
  3659. Mono_Printf("%s Buildings:%x\n",housep->Class->Name(),GameCRC);
  3660. }
  3661. }
  3662. //
  3663. // Animations
  3664. //
  3665. AnimClass *animp;
  3666. fprintf(fp,"-------------------- Animations -------------------\n");
  3667. for (i = 0; i < Anims.Count(); i++) {
  3668. animp = (AnimClass *)Anims.Active_Ptr(i);
  3669. fprintf(fp,"Target:%x OwnerHouse:%d Loops:%d\n",
  3670. animp->xObject,
  3671. animp->OwnerHouse,
  3672. animp->Loops);
  3673. }
  3674. //------------------------------------------------------------------------
  3675. // Map Layers
  3676. //------------------------------------------------------------------------
  3677. GameCRC = 0;
  3678. for (i = 0; i < LAYER_COUNT; i++) {
  3679. fprintf(fp,">>>> MAP LAYER %d <<<<\n",i);
  3680. for (j = 0; j < Map.Layer[i].Count(); j++) {
  3681. objp = Map.Layer[i][j];
  3682. Add_CRC (&GameCRC, (int)objp->Coord + (int)objp->What_Am_I());
  3683. fprintf(fp,"Object %d: %x ",j,objp->Coord);
  3684. if (objp->What_Am_I() == RTTI_AIRCRAFT)
  3685. fprintf(fp,"Aircraft (Type:%d) ",
  3686. (AircraftType)(*((AircraftClass *)objp)));
  3687. else if (objp->What_Am_I() == RTTI_ANIM)
  3688. fprintf(fp,"Anim (Type:%d) ",
  3689. (AnimType)(*((AnimClass *)objp)));
  3690. else if (objp->What_Am_I() == RTTI_BUILDING)
  3691. fprintf(fp,"Building (Type:%d) ",
  3692. (StructType)(*((BuildingClass *)objp)));
  3693. else if (objp->What_Am_I() == RTTI_BULLET)
  3694. fprintf(fp,"Bullet (Type:%d) ",
  3695. (BulletType)(*((BulletClass *)objp)));
  3696. else if (objp->What_Am_I() == RTTI_INFANTRY)
  3697. fprintf(fp,"Infantry (Type:%d) ",
  3698. (InfantryType)(*((InfantryClass *)objp)));
  3699. else if (objp->What_Am_I() == RTTI_OVERLAY)
  3700. fprintf(fp,"Overlay (Type:%d) ",
  3701. (OverlayType)(*((OverlayClass *)objp)));
  3702. else if (objp->What_Am_I() == RTTI_SMUDGE)
  3703. fprintf(fp,"Smudge (Type:%d) ",
  3704. (SmudgeType)(*((SmudgeClass *)objp)));
  3705. else if (objp->What_Am_I() == RTTI_TEMPLATE)
  3706. fprintf(fp,"Template (Type:%d) ",
  3707. (TemplateType)(*((TemplateClass *)objp)));
  3708. else if (objp->What_Am_I() == RTTI_TERRAIN)
  3709. fprintf(fp,"Terrain (Type:%d) ",
  3710. (TerrainType)(*((TerrainClass *)objp)));
  3711. else if (objp->What_Am_I() == RTTI_UNIT)
  3712. fprintf(fp,"Unit (Type:%d) ",
  3713. (UnitType)(*((UnitClass *)objp)));
  3714. else if (objp->What_Am_I() == RTTI_VESSEL)
  3715. fprintf(fp,"Vessel (Type:%d) ",
  3716. (VesselType)(*((VesselClass *)objp)));
  3717. house = objp->Owner();
  3718. if (house!=HOUSE_NONE) {
  3719. housep = HouseClass::As_Pointer (house);
  3720. fprintf(fp,"Owner: %s\n",housep->Class->IniName);
  3721. }
  3722. else {
  3723. fprintf(fp,"Owner: NONE\n");
  3724. }
  3725. }
  3726. }
  3727. Mono_Printf("Map Layers:%x \n",GameCRC);
  3728. //------------------------------------------------------------------------
  3729. // Logic Layers
  3730. //------------------------------------------------------------------------
  3731. GameCRC = 0;
  3732. fprintf(fp,">>>> LOGIC LAYER <<<<\n");
  3733. for (i = 0; i < Logic.Count(); i++) {
  3734. objp = Logic[i];
  3735. Add_CRC (&GameCRC, (int)objp->Coord + (int)objp->What_Am_I());
  3736. fprintf(fp,"Object %d: %x ",i,objp->Coord);
  3737. if (objp->What_Am_I() == RTTI_AIRCRAFT)
  3738. fprintf(fp,"Aircraft (Type:%d) ",
  3739. (AircraftType)(*((AircraftClass *)objp)));
  3740. else if (objp->What_Am_I() == RTTI_ANIM)
  3741. fprintf(fp,"Anim (Type:%d) ",
  3742. (AnimType)(*((AnimClass *)objp)));
  3743. else if (objp->What_Am_I() == RTTI_BUILDING)
  3744. fprintf(fp,"Building (Type:%d) ",
  3745. (StructType)(*((BuildingClass *)objp)));
  3746. else if (objp->What_Am_I() == RTTI_BULLET)
  3747. fprintf(fp,"Bullet (Type:%d) ",
  3748. (BulletType)(*((BulletClass *)objp)));
  3749. else if (objp->What_Am_I() == RTTI_INFANTRY)
  3750. fprintf(fp,"Infantry (Type:%d) ",
  3751. (InfantryType)(*((InfantryClass *)objp)));
  3752. else if (objp->What_Am_I() == RTTI_OVERLAY)
  3753. fprintf(fp,"Overlay (Type:%d) ",
  3754. (OverlayType)(*((OverlayClass *)objp)));
  3755. else if (objp->What_Am_I() == RTTI_SMUDGE)
  3756. fprintf(fp,"Smudge (Type:%d) ",
  3757. (SmudgeType)(*((SmudgeClass *)objp)));
  3758. else if (objp->What_Am_I() == RTTI_TEMPLATE)
  3759. fprintf(fp,"Template (Type:%d) ",
  3760. (TemplateType)(*((TemplateClass *)objp)));
  3761. else if (objp->What_Am_I() == RTTI_TERRAIN)
  3762. fprintf(fp,"Terrain (Type:%d) ",
  3763. (TerrainType)(*((TerrainClass *)objp)));
  3764. else if (objp->What_Am_I() == RTTI_UNIT)
  3765. fprintf(fp,"Unit (Type:%d) ",
  3766. (UnitType)(*((UnitClass *)objp)));
  3767. house = objp->Owner();
  3768. if (house!=HOUSE_NONE) {
  3769. housep = HouseClass::As_Pointer (house);
  3770. fprintf(fp,"Owner: %s\n",housep->Class->IniName);
  3771. }
  3772. else {
  3773. fprintf(fp,"Owner: NONE\n");
  3774. }
  3775. }
  3776. Mono_Printf("Logic:%x \n",GameCRC);
  3777. //------------------------------------------------------------------------
  3778. // Random # generator, frame #
  3779. //------------------------------------------------------------------------
  3780. Mono_Printf("Random Number:%x \n",Scen.RandomNumber.Seed);
  3781. #ifdef RANDOM_COUNT
  3782. fprintf(fp,"\nRandom Number:%x (Count1:%d, Count2:%d)\n",
  3783. Scen.RandomNumber.Seed,
  3784. Scen.RandomNumber.Count1,
  3785. Scen.RandomNumber.Count2);
  3786. #else
  3787. fprintf(fp,"\nRandom Number:%x\n",Scen.RandomNumber.Seed);
  3788. #endif
  3789. Mono_Printf("My Frame:%d \n",Frame);
  3790. fprintf(fp,"My Frame:%d\n",Frame);
  3791. if (ev) {
  3792. fprintf(fp,"\n");
  3793. fprintf(fp,"Offending event:\n");
  3794. fprintf(fp," Type: %d\n",ev->Type);
  3795. fprintf(fp," Frame: %d\n",ev->Frame);
  3796. fprintf(fp," ID: %x\n",ev->ID);
  3797. fprintf(fp," CRC: %x\n",ev->Data.FrameInfo.CRC);
  3798. fprintf(fp," CommandCount: %d\n",ev->Data.FrameInfo.CommandCount);
  3799. fprintf(fp," Delay: %d\n",ev->Data.FrameInfo.Delay);
  3800. }
  3801. fclose(fp);
  3802. } /* end of Print_CRCs */
  3803. /***************************************************************************
  3804. * Init_Queue_Mono -- inits mono display *
  3805. * *
  3806. * This routine steals control of the mono screen away from the rest of *
  3807. * the engine, by setting the global IsMono; if IsMono is set, the other *
  3808. * routines in this module turn off the Mono display when they're done *
  3809. * with it, so the rest of the engine won't over-write what we're writing. *
  3810. * *
  3811. * INPUT: *
  3812. * net ptr to connection manager *
  3813. * *
  3814. * OUTPUT: *
  3815. * none. *
  3816. * *
  3817. * WARNINGS: *
  3818. * none. *
  3819. * *
  3820. * HISTORY: *
  3821. * 11/21/1995 BRR : Created. *
  3822. *=========================================================================*/
  3823. static void Init_Queue_Mono(ConnManClass *net)
  3824. {
  3825. #if(SHOW_MONO)
  3826. //------------------------------------------------------------------------
  3827. // Set 'IsMono' so we can steal the mono screen from the engine
  3828. //------------------------------------------------------------------------
  3829. if ((Frame==0 || Session.LoadGame) && MonoClass::Is_Enabled()) {
  3830. IsMono = true;
  3831. }
  3832. //------------------------------------------------------------------------
  3833. // Enable mono output for our stuff; we must Disable it before we return
  3834. // control to the engine.
  3835. //------------------------------------------------------------------------
  3836. if (IsMono)
  3837. MonoClass::Enable();
  3838. if (net->Num_Connections() > 0) {
  3839. //.....................................................................
  3840. // Network mono debugging screen
  3841. //.....................................................................
  3842. if (NetMonoMode==0) {
  3843. if (Frame==0 || Session.LoadGame || NewMonoMode) {
  3844. net->Configure_Debug (0, sizeof (CommHeaderType),
  3845. sizeof(EventClass::EventType), EventClass::EventNames, 0, 27);
  3846. net->Mono_Debug_Print (0,1);
  3847. NewMonoMode = 0;
  3848. }
  3849. else {
  3850. net->Mono_Debug_Print (0,0);
  3851. }
  3852. }
  3853. //.....................................................................
  3854. // Flow control debugging output
  3855. //.....................................................................
  3856. else {
  3857. if (NewMonoMode) {
  3858. Mono_Clear_Screen();
  3859. Mono_Printf(" Queue AI:\n"); // flowcount[0]
  3860. Mono_Printf(" Build Packet Loop:\n"); // flowcount[1]
  3861. Mono_Printf(" Frame Sync:\n"); // flowcount[2]
  3862. Mono_Printf(" Frame Sync Resend:\n"); // flowcount[3]
  3863. Mono_Printf(" Frame Sync Timeout:\n"); // flowcount[4]
  3864. Mono_Printf(" Frame Sync New Message:\n"); // flowcount[5]
  3865. Mono_Printf(" DoList Execution:\n"); // flowcount[6]
  3866. Mono_Printf(" DoList Cleaning:\n"); // flowcount[7]
  3867. Mono_Printf("\n");
  3868. Mono_Printf(" Frame:\n");
  3869. Mono_Printf(" Session.MaxAhead:\n");
  3870. Mono_Printf(" their_recv:\n");
  3871. Mono_Printf(" their_sent:\n");
  3872. Mono_Printf(" my_sent:\n");
  3873. NewMonoMode = 0;
  3874. }
  3875. }
  3876. }
  3877. #else
  3878. net = net;
  3879. #endif
  3880. } // end of Init_Queue_Mono
  3881. /***************************************************************************
  3882. * Update_Queue_Mono -- updates mono display *
  3883. * *
  3884. * INPUT: *
  3885. * net ptr to connection manager *
  3886. * flow_index index # for flow-count updates *
  3887. * -1: display *
  3888. * *
  3889. * OUTPUT: *
  3890. * none. *
  3891. * *
  3892. * WARNINGS: *
  3893. * none. *
  3894. * *
  3895. * HISTORY: *
  3896. * 11/21/1995 BRR : Created. *
  3897. *=========================================================================*/
  3898. static void Update_Queue_Mono(ConnManClass *net, int flow_index)
  3899. {
  3900. #if(SHOW_MONO)
  3901. static int flowcount[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  3902. //------------------------------------------------------------------------
  3903. // If 'NetMonoMode' is 1, display flowcount info
  3904. //------------------------------------------------------------------------
  3905. if (NetMonoMode==1) {
  3906. if (flow_index >= 0 && flow_index < 20) {
  3907. Mono_Set_Cursor(35,flow_index);
  3908. flowcount[flow_index]++;
  3909. Mono_Printf("%d",flowcount[flow_index]);
  3910. }
  3911. }
  3912. //------------------------------------------------------------------------
  3913. // Otherwise, display the connection debug screen
  3914. //------------------------------------------------------------------------
  3915. else {
  3916. net->Mono_Debug_Print (0,0);
  3917. }
  3918. #else
  3919. flow_index = flow_index;
  3920. net = net;
  3921. #endif
  3922. } // end of Update_Queue_Mono
  3923. /***************************************************************************
  3924. * Print_Framesync_Values -- displays frame-sync variables *
  3925. * *
  3926. * INPUT: *
  3927. * curframe current game Frame # *
  3928. * max_ahead max-ahead value *
  3929. * num_connections # connections *
  3930. * their_recv # commands I've received from my connections *
  3931. * their_sent # commands each connection claims to have sent *
  3932. * my_sent # commands I've sent *
  3933. * *
  3934. * OUTPUT: *
  3935. * none. *
  3936. * *
  3937. * WARNINGS: *
  3938. * none. *
  3939. * *
  3940. * HISTORY: *
  3941. * 11/21/1995 BRR : Created. *
  3942. *=========================================================================*/
  3943. static void Print_Framesync_Values(long curframe, unsigned long max_ahead,
  3944. int num_connections, unsigned short *their_recv,
  3945. unsigned short *their_sent, unsigned short my_sent)
  3946. {
  3947. #if(SHOW_MONO)
  3948. int i;
  3949. if (NetMonoMode==1) {
  3950. Mono_Set_Cursor(35,9);
  3951. Mono_Printf("%d",curframe);
  3952. Mono_Set_Cursor(35,10);
  3953. Mono_Printf("%d",max_ahead);
  3954. for (i = 0; i < num_connections; i++) {
  3955. Mono_Set_Cursor(35 + i*5,11);
  3956. Mono_Printf("%4d",(int)their_recv[i]);
  3957. }
  3958. for (i = 0; i < num_connections; i++) {
  3959. Mono_Set_Cursor(35 + i*5,12);
  3960. Mono_Printf("%4d",(int)their_sent[i]);
  3961. }
  3962. Mono_Set_Cursor(35,13);
  3963. Mono_Printf("%4d",(int)my_sent);
  3964. }
  3965. #else
  3966. curframe = curframe;
  3967. max_ahead = max_ahead;
  3968. num_connections = num_connections;
  3969. their_recv = their_recv;
  3970. their_sent = their_sent;
  3971. my_sent = my_sent;
  3972. #endif
  3973. } // end of Print_Framesync_Values
  3974. /***************************************************************************
  3975. * Dump_Packet_Too_Late_Stuff -- Dumps a debug file to disk *
  3976. * *
  3977. * INPUT: *
  3978. * event ptr to event to print *
  3979. * *
  3980. * OUTPUT: *
  3981. * none. *
  3982. * *
  3983. * WARNINGS: *
  3984. * none. *
  3985. * *
  3986. * HISTORY: *
  3987. * 06/28/1996 BRR : Created. *
  3988. *=========================================================================*/
  3989. void Dump_Packet_Too_Late_Stuff(EventClass *event, ConnManClass *net,
  3990. long *their_frame, unsigned short *their_sent, unsigned short *their_recv)
  3991. {
  3992. FILE *fp;
  3993. int i;
  3994. HousesType house;
  3995. fp = fopen("toolate.txt", "wt");
  3996. if (!fp) {
  3997. return;
  3998. }
  3999. fprintf(fp,"----------------- Event data: ----------------------\n");
  4000. fprintf(fp,"Type: %s\n",EventClass::EventNames[event->Type]);
  4001. fprintf(fp,"Frame: %d\n",event->Frame);
  4002. fprintf(fp,"ID: %d\n",event->ID);
  4003. for (i = 0; i < Session.Players.Count(); i++) {
  4004. if (event->ID == Session.Players[i]->Player.ID) {
  4005. fprintf(fp,"Player's Name: %s",Session.Players[i]->Name);
  4006. }
  4007. }
  4008. fprintf(fp,"\n");
  4009. fprintf(fp,"--------------------- My data: ---------------------\n");
  4010. fprintf(fp,"My Frame:%d\n",Frame);
  4011. fprintf(fp,"My MaxAhead:%d\n",Session.MaxAhead);
  4012. if (net) {
  4013. fprintf(fp,"-------------------- Frame Stats: ------------------\n");
  4014. fprintf(fp,"Name ID TheirFrame TheirSent TheirRecv\n");
  4015. for (i = 0; i < net->Num_Connections(); i++) {
  4016. house = (HousesType)(net->Connection_ID(i));
  4017. fprintf(fp,"%12s %2d %6d %6d %6d\n",
  4018. (HouseClass::As_Pointer(house))->IniName,
  4019. net->Connection_ID(i),
  4020. their_frame[i],
  4021. their_sent[i],
  4022. their_recv[i]);
  4023. }
  4024. }
  4025. fclose(fp);
  4026. }
  4027. /***************************************************************************
  4028. * Check_Mirror -- Checks mirror memory *
  4029. * *
  4030. * INPUT: *
  4031. * none. *
  4032. * *
  4033. * OUTPUT: *
  4034. * none. *
  4035. * *
  4036. * WARNINGS: *
  4037. * none. *
  4038. * *
  4039. * HISTORY: *
  4040. * 10/14/1996 BRR : Created. *
  4041. *=========================================================================*/
  4042. void Check_Mirror(void)
  4043. {
  4044. #ifdef MIRROR_QUEUE
  4045. int i;
  4046. char txt[80];
  4047. unsigned long *ptr;
  4048. int found_5s = 0;
  4049. ptr = (unsigned long *)(DoList.Get_Array());
  4050. for (i = 0; i < (MAX_EVENTS * 64 * sizeof(EventClass)) /
  4051. sizeof(unsigned long); i++) {
  4052. if (ptr[i] == 0x55555555) {
  4053. sprintf(txt,"55555555 found in DoList! Addr:%p", &(ptr[i]));
  4054. WWMessageBox().Process (txt);
  4055. found_5s = 1;
  4056. }
  4057. }
  4058. ptr = (unsigned long *)(MirrorList.Get_Array());
  4059. for (i = 0; i < (MAX_EVENTS * 64 * sizeof(EventClass)) /
  4060. sizeof(unsigned long); i++) {
  4061. if (ptr[i] == 0x55555555) {
  4062. sprintf(txt,"55555555 found in MirrorList! Addr:%p", &(ptr[i]));
  4063. WWMessageBox().Process (txt);
  4064. found_5s = 1;
  4065. }
  4066. }
  4067. ptr = (unsigned long *)(DoList.Get_Array());
  4068. for (i = 0; i < (MAX_EVENTS * 64 * sizeof(EventClass)) /
  4069. sizeof(unsigned long); i++) {
  4070. if (ptr[i] == 0xAAAAAAAA) {
  4071. sprintf(txt,"AAAAAAAA found in DoList! Addr:%p", &(ptr[i]));
  4072. WWMessageBox().Process (txt);
  4073. found_5s = 1;
  4074. }
  4075. }
  4076. ptr = (unsigned long *)(MirrorList.Get_Array());
  4077. for (i = 0; i < (MAX_EVENTS * 64 * sizeof(EventClass)) /
  4078. sizeof(unsigned long); i++) {
  4079. if (ptr[i] == 0xAAAAAAAA) {
  4080. sprintf(txt,"AAAAAAAA found in MirrorList! Addr:%p", &(ptr[i]));
  4081. WWMessageBox().Process (txt);
  4082. found_5s = 1;
  4083. }
  4084. }
  4085. for (i = 0; i < DoList.Count; i++) {
  4086. if (memcmp(&DoList[i], &MirrorList[i], sizeof(EventClass)) != 0) {
  4087. sprintf(txt,"Queue Memory Trashed! Head:%d Tail:%d, Addr:%p or %p",
  4088. DoList.Get_Head(),
  4089. DoList.Get_Tail(),
  4090. DoList.Get_Array() + i,
  4091. MirrorList.Get_Array() + i);
  4092. WWMessageBox().Process (txt);
  4093. Prog_End("Check_Mirror", true);
  4094. Emergency_Exit(0);
  4095. }
  4096. }
  4097. if (found_5s) {
  4098. //Prog_End();
  4099. Emergency_Exit(0);
  4100. }
  4101. #endif
  4102. } // end of Check_Mirror
  4103. /*************************** end of queue.cpp ******************************/