D_NETBAK.C 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. // I_pcnet.m
  2. //
  3. // Modified 12-21-94 by Chris Rhinehart for use with multiple ticdups
  4. // actually, it wasn't modified, but rather we are currently using this
  5. // older version of D_NET.C, since the new one doesn't seem to work with
  6. // ticdup set to greater than one.
  7. #include "DoomDef.h"
  8. #include "P_local.h"
  9. #include "soundst.h"
  10. #define NCMD_EXIT 0x80000000
  11. #define NCMD_RETRANSMIT 0x40000000
  12. #define NCMD_SETUP 0x20000000
  13. #define NCMD_CHECKSUM 0x0fffffff
  14. /*
  15. if more space needs to be crunched out of the protocol...
  16. 1 drone
  17. 2 player
  18. 8 tic
  19. 5 numtics
  20. #define NCMD_EXIT 0x80000000
  21. #define NCMD_RETRANSMIT 0x40000000 // a retransmit will have 0 tics
  22. #define NCMD_DRONE 0x20000000
  23. #define NCMD_PLAYER 0x18000000
  24. #define NCMD_PLAYERSHIFT 27
  25. #define NCMD_TIC 0x00ff0000
  26. #define NCMD_TICSHIFT 16
  27. #define NCMD_NUMTICS 0x0000ff00
  28. #define NCMD_NUMTICSSHIFT 8
  29. #define NCMD_CHECKSUM 0x000000ff
  30. */
  31. doomcom_t *doomcom;
  32. doomdata_t *netbuffer; // points inside doomcom
  33. /*
  34. ==============================================================================
  35. NETWORKING
  36. gametic is the tic about to (or currently being) run
  37. maketic is the tick that hasn't had control made for it yet
  38. nettics[] has the maketics for all players
  39. a gametic cannot be run until nettics[] > gametic for all players
  40. ==============================================================================
  41. */
  42. #define RESENDCOUNT 10
  43. #define PL_DRONE 0x80 // bit flag in doomdata->player
  44. ticcmd_t localcmds[BACKUPTICS];
  45. ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
  46. int nettics[MAXNETNODES];
  47. boolean nodeingame[MAXNETNODES]; // set false as nodes leave game
  48. boolean remoteresend[MAXNETNODES]; // set when local needs tics
  49. int resendto[MAXNETNODES]; // set when remote needs tics
  50. int resendcount[MAXNETNODES];
  51. int nodeforplayer[MAXPLAYERS];
  52. int gametime;
  53. int maketic;
  54. int lastnettic, skiptics;
  55. int ticdup;
  56. void D_ProcessEvents (void);
  57. void G_BuildTiccmd (ticcmd_t *cmd);
  58. void D_DoAdvanceDemo (void);
  59. boolean reboundpacket;
  60. doomdata_t reboundstore;
  61. int NetbufferSize (void)
  62. {
  63. return (int)&(((doomdata_t *)0)->cmds[netbuffer->numtics]);
  64. }
  65. unsigned NetbufferChecksum (void)
  66. {
  67. unsigned c;
  68. int i,l;
  69. c = 0x1234567;
  70. l = (NetbufferSize () - (int)&(((doomdata_t *)0)->retransmitfrom))/4;
  71. for (i=0 ; i<l ; i++)
  72. c += ((unsigned *)&netbuffer->retransmitfrom)[i] * (i+1);
  73. return c & NCMD_CHECKSUM;
  74. }
  75. int ExpandTics (int low)
  76. {
  77. int delta;
  78. delta = low - (maketic&0xff);
  79. if (delta >= -64 && delta <= 64)
  80. return (maketic&~0xff) + low;
  81. if (delta > 64)
  82. return (maketic&~0xff) - 256 + low;
  83. if (delta < -64)
  84. return (maketic&~0xff) + 256 + low;
  85. I_Error ("ExpandTics: strange value %i at maketic %i",low,maketic);
  86. return 0;
  87. }
  88. //============================================================================
  89. /*
  90. ==============
  91. =
  92. = HSendPacket
  93. =
  94. ==============
  95. */
  96. void HSendPacket (int node, int flags)
  97. {
  98. netbuffer->checksum = NetbufferChecksum () | flags;
  99. if (!node)
  100. {
  101. reboundstore = *netbuffer;
  102. reboundpacket = true;
  103. return;
  104. }
  105. if (!netgame)
  106. I_Error ("Tried to transmit to another node");
  107. doomcom->command = CMD_SEND;
  108. doomcom->remotenode = node;
  109. doomcom->datalength = NetbufferSize ();
  110. if (debugfile)
  111. {
  112. int i;
  113. int realretrans;
  114. if (netbuffer->checksum & NCMD_RETRANSMIT)
  115. realretrans = ExpandTics (netbuffer->retransmitfrom);
  116. else
  117. realretrans = -1;
  118. fprintf (debugfile,"send (%i + %i, R %i) [%i] "
  119. ,ExpandTics(netbuffer->starttic),netbuffer->numtics, realretrans, doomcom->datalength);
  120. for (i=0 ; i<doomcom->datalength ; i++)
  121. fprintf (debugfile,"%i ",((byte *)netbuffer)[i]);
  122. fprintf (debugfile,"\n");
  123. }
  124. I_NetCmd ();
  125. }
  126. /*
  127. ==============
  128. =
  129. = HGetPacket
  130. =
  131. = Returns false if no packet is waiting
  132. =
  133. ==============
  134. */
  135. boolean HGetPacket (void)
  136. {
  137. if (reboundpacket)
  138. {
  139. *netbuffer = reboundstore;
  140. doomcom->remotenode = 0;
  141. reboundpacket = false;
  142. return true;
  143. }
  144. if (!netgame)
  145. return false;
  146. doomcom->command = CMD_GET;
  147. I_NetCmd ();
  148. if (doomcom->remotenode == -1)
  149. return false;
  150. if (doomcom->datalength != NetbufferSize ())
  151. {
  152. if (debugfile)
  153. fprintf (debugfile,"bad packet length %i\n",doomcom->datalength);
  154. return false;
  155. }
  156. if (NetbufferChecksum () != (netbuffer->checksum&NCMD_CHECKSUM) )
  157. {
  158. if (debugfile)
  159. fprintf (debugfile,"bad packet checksum\n");
  160. return false;
  161. }
  162. if (debugfile)
  163. {
  164. int realretrans;
  165. int i;
  166. if (netbuffer->checksum & NCMD_SETUP)
  167. fprintf (debugfile,"setup packet\n");
  168. else
  169. {
  170. if (netbuffer->checksum & NCMD_RETRANSMIT)
  171. realretrans = ExpandTics (netbuffer->retransmitfrom);
  172. else
  173. realretrans = -1;
  174. fprintf (debugfile,"get %i = (%i + %i, R %i)[%i] ",doomcom->remotenode,
  175. ExpandTics(netbuffer->starttic),netbuffer->numtics, realretrans, doomcom->datalength);
  176. for (i=0 ; i<doomcom->datalength ; i++)
  177. fprintf (debugfile,"%i ",((byte *)netbuffer)[i]);
  178. fprintf (debugfile,"\n");
  179. }
  180. }
  181. return true;
  182. }
  183. /*
  184. ===================
  185. =
  186. = GetPackets
  187. =
  188. ===================
  189. */
  190. char exitmsg[80];
  191. void GetPackets (void)
  192. {
  193. int netconsole;
  194. int netnode;
  195. int netdrone;
  196. int j;
  197. ticcmd_t *src, *dest;
  198. int dupedstart, dupedend;
  199. int skiptics;
  200. int realstart;
  201. while (HGetPacket ())
  202. {
  203. if (netbuffer->checksum & NCMD_SETUP)
  204. continue; // extra setup packet
  205. netdrone = netbuffer->player & PL_DRONE;
  206. netconsole = netbuffer->player & ~PL_DRONE;
  207. netnode = doomcom->remotenode;
  208. //
  209. // to save bytes, only the low byte of tic numbers are sent
  210. // Figure out what the rest of the bytes are
  211. //
  212. realstart = ExpandTics (netbuffer->starttic);
  213. dupedstart = realstart*doomcom->ticdup;
  214. dupedend = (realstart+netbuffer->numtics)*doomcom->ticdup;
  215. //
  216. // check for exiting the game
  217. //
  218. if (netbuffer->checksum & NCMD_EXIT)
  219. {
  220. if (!nodeingame[netnode])
  221. continue;
  222. nodeingame[netnode] = false;
  223. if (!netdrone)
  224. {
  225. playeringame[netconsole] = false;
  226. strcpy (exitmsg, "PLAYER 1 HAS LEFT THE GAME");
  227. exitmsg[7] += netconsole;
  228. P_SetMessage(&players[consoleplayer], exitmsg, true);
  229. UpdateState |= I_MESSAGES;
  230. S_StartSound(NULL, sfx_chat);
  231. }
  232. continue;
  233. }
  234. //
  235. // drone packets are just notifications
  236. //
  237. if (netdrone)
  238. {
  239. nettics[netnode] = dupedend;
  240. continue;
  241. }
  242. nodeforplayer[netconsole] = netnode;
  243. //
  244. // check for retransmit request
  245. //
  246. if ( resendcount[netnode] <= 0
  247. && (netbuffer->checksum & NCMD_RETRANSMIT) )
  248. {
  249. resendto[netnode] = ExpandTics(netbuffer->retransmitfrom);
  250. if (debugfile)
  251. fprintf (debugfile,"retransmit from %i\n", resendto[netnode]);
  252. resendcount[netnode] = RESENDCOUNT;
  253. }
  254. else
  255. resendcount[netnode]--;
  256. //
  257. // check for out of order / duplicated packet
  258. //
  259. if (dupedend == nettics[netnode])
  260. continue;
  261. if (dupedend < nettics[netnode])
  262. {
  263. if (debugfile)
  264. fprintf (debugfile,"out of order packet (%i + %i)\n" ,realstart,netbuffer->numtics);
  265. continue;
  266. }
  267. //
  268. // check for a missed packet
  269. //
  270. if (dupedstart > nettics[netnode])
  271. {
  272. // stop processing until the other system resends the missed tics
  273. if (debugfile)
  274. fprintf (debugfile,"missed tics from %i (%i - %i)\n", netnode, dupedstart, nettics[netnode]);
  275. remoteresend[netnode] = true;
  276. continue;
  277. }
  278. //
  279. // update command store from the packet
  280. //
  281. remoteresend[netnode] = false;
  282. skiptics = nettics[netnode]/doomcom->ticdup - realstart;
  283. src = &netbuffer->cmds[skiptics];
  284. while (nettics[netnode] < dupedend)
  285. {
  286. for (j=0 ; j<doomcom->ticdup ; j++)
  287. {
  288. dest = &netcmds[netconsole][nettics[netnode]%BACKUPTICS];
  289. nettics[netnode]++;
  290. *dest = *src;
  291. src->chatchar = 0;
  292. if (src->buttons & BT_SPECIAL)
  293. src->buttons = 0;
  294. }
  295. src++;
  296. }
  297. }
  298. }
  299. /*
  300. =============
  301. =
  302. = NetUpdate
  303. =
  304. = Builds ticcmds for console player
  305. = sends out a packet
  306. =============
  307. */
  308. void NetUpdate (void)
  309. {
  310. int nowtime;
  311. int newtics;
  312. int i,j;
  313. int gameticdiv;
  314. int realstart;
  315. if (singletics)
  316. return; // singletic update is syncronous
  317. //
  318. // check time
  319. //
  320. nowtime = I_GetTime ()/doomcom->ticdup;
  321. newtics = nowtime - gametime;
  322. gametime = nowtime;
  323. if (newtics <= 0) // nothing new to update
  324. goto listen;
  325. if (skiptics <= newtics)
  326. {
  327. newtics -= skiptics;
  328. skiptics = 0;
  329. }
  330. else
  331. {
  332. skiptics -= newtics;
  333. newtics = 0;
  334. }
  335. netbuffer->player = consoleplayer;
  336. if (doomcom->drone)
  337. netbuffer->player |= PL_DRONE;
  338. //
  339. // drone packets
  340. //
  341. if (doomcom->drone)
  342. {
  343. I_StartTic ();
  344. D_ProcessEvents ();
  345. goto sendit;
  346. }
  347. //
  348. // build new ticcmds for console player
  349. //
  350. gameticdiv = (gametic+doomcom->ticdup-1)/doomcom->ticdup;
  351. for (i=0 ; i<newtics ; i++)
  352. {
  353. I_StartTic ();
  354. D_ProcessEvents ();
  355. if (maketic - gameticdiv >= BACKUPTICS/2 /* /doomcom->ticdup */- 1)
  356. {
  357. newtics = i;
  358. break; // can't hold any more
  359. }
  360. //printf ("mk:%i ",maketic);
  361. G_BuildTiccmd (&localcmds[maketic%BACKUPTICS]);
  362. maketic++;
  363. }
  364. //
  365. // send the packet to the other nodes
  366. //
  367. sendit:
  368. for (i=0 ; i<doomcom->numnodes ; i++)
  369. if (nodeingame[i])
  370. {
  371. if (doomcom->drone)
  372. {
  373. netbuffer->starttic = realstart = maketic + BACKUPTICS/2;
  374. netbuffer->numtics = 0;
  375. }
  376. else
  377. {
  378. netbuffer->starttic = realstart = resendto[i];
  379. netbuffer->numtics = maketic - realstart;
  380. resendto[i] = maketic - doomcom->extratics;
  381. }
  382. if (netbuffer->numtics > BACKUPTICS)
  383. I_Error ("NetUpdate: netbuffer->numtics > BACKUPTICS");
  384. for (j=0 ; j< netbuffer->numtics ; j++)
  385. netbuffer->cmds[j] =
  386. localcmds[(realstart+j)%BACKUPTICS];
  387. if (remoteresend[i])
  388. {
  389. netbuffer->retransmitfrom = nettics[i]/doomcom->ticdup;
  390. HSendPacket (i, NCMD_RETRANSMIT);
  391. }
  392. else
  393. {
  394. netbuffer->retransmitfrom = 0;
  395. HSendPacket (i, 0);
  396. }
  397. }
  398. //
  399. // listen for other packets
  400. //
  401. listen:
  402. GetPackets ();
  403. }
  404. /*
  405. =====================
  406. =
  407. = CheckAbort
  408. =
  409. =====================
  410. */
  411. void CheckAbort (void)
  412. {
  413. event_t *ev;
  414. I_WaitVBL(2);
  415. I_StartTic ();
  416. for ( ; eventtail != eventhead
  417. ; eventtail = (++eventtail)&(MAXEVENTS-1) )
  418. {
  419. ev = &events[eventtail];
  420. if (ev->type == ev_keydown && ev->data1 == KEY_ESCAPE)
  421. I_Error ("Network game synchronization aborted.");
  422. }
  423. }
  424. /*
  425. =====================
  426. =
  427. = D_ArbitrateNetStart
  428. =
  429. =====================
  430. */
  431. void D_ArbitrateNetStart (void)
  432. {
  433. int i;
  434. boolean gotinfo[MAXNETNODES];
  435. autostart = true;
  436. memset (gotinfo,0,sizeof(gotinfo));
  437. if (doomcom->consoleplayer)
  438. { // listen for setup info from key player
  439. //printf ("listening for network start info...\n");
  440. while (1)
  441. {
  442. CheckAbort ();
  443. if (!HGetPacket ())
  444. continue;
  445. if (netbuffer->checksum & NCMD_SETUP)
  446. {
  447. if (netbuffer->player != VERSION)
  448. I_Error ("Different HERETIC versions cannot play a net game!");
  449. startskill = netbuffer->retransmitfrom & 15;
  450. deathmatch = (netbuffer->retransmitfrom & 0x80) > 0;
  451. startmap = netbuffer->starttic & 15;
  452. startepisode = netbuffer->starttic >> 4;
  453. return;
  454. }
  455. }
  456. }
  457. else
  458. { // key player, send the setup info
  459. // printf ("sending network start info...\n");
  460. do
  461. {
  462. CheckAbort ();
  463. for (i=0 ; i<doomcom->numnodes ; i++)
  464. {
  465. netbuffer->retransmitfrom = startskill;
  466. if (deathmatch)
  467. netbuffer->retransmitfrom |= 0x80;
  468. netbuffer->starttic = startepisode * 16 + startmap;
  469. netbuffer->player = VERSION;
  470. netbuffer->numtics = 0;
  471. HSendPacket (i, NCMD_SETUP);
  472. }
  473. while (HGetPacket ())
  474. {
  475. //printf ("got packet\n");
  476. gotinfo[netbuffer->player&0x7f] = true;
  477. }
  478. for (i=1 ; i<doomcom->numnodes ; i++)
  479. if (!gotinfo[i])
  480. break;
  481. } while (i < doomcom->numnodes);
  482. }
  483. }
  484. /*
  485. ===================
  486. =
  487. = D_CheckNetGame
  488. =
  489. = Works out player numbers among the net participants
  490. ===================
  491. */
  492. extern int viewangleoffset;
  493. void D_CheckNetGame (void)
  494. {
  495. int i;
  496. for (i=0 ; i<MAXNETNODES ; i++)
  497. {
  498. nodeingame[i] = false;
  499. nettics[i] = 0;
  500. remoteresend[i] = false; // set when local needs tics
  501. resendto[i] = 0; // which tic to start sending
  502. }
  503. // I_InitNetwork sets doomcom and netgame
  504. I_InitNetwork ();
  505. if (doomcom->id != DOOMCOM_ID)
  506. I_Error ("Doomcom buffer invalid!");
  507. netbuffer = &doomcom->data;
  508. consoleplayer = displayplayer = doomcom->consoleplayer;
  509. if (netgame)
  510. D_ArbitrateNetStart ();
  511. //printf ("startskill %i deathmatch: %i startmap: %i startepisode: %i\n", startskill, deathmatch, startmap, startepisode);
  512. // read values out of doomcom
  513. ticdup = doomcom->ticdup;
  514. for (i=0 ; i<doomcom->numplayers ; i++)
  515. playeringame[i] = true;
  516. for (i=0 ; i<doomcom->numnodes ; i++)
  517. nodeingame[i] = true;
  518. //printf ("player %i of %i (%i nodes)\n", consoleplayer+1, doomcom->numplayers, doomcom->numnodes);
  519. }
  520. /*
  521. ==================
  522. =
  523. = D_QuitNetGame
  524. =
  525. = Called before quitting to leave a net game without hanging the
  526. = other players
  527. =
  528. ==================
  529. */
  530. void D_QuitNetGame (void)
  531. {
  532. int i, j;
  533. if (debugfile)
  534. fclose (debugfile);
  535. if (!netgame || !usergame || consoleplayer == -1)
  536. return;
  537. // send a bunch of packets for security
  538. netbuffer->player = consoleplayer;
  539. if (doomcom->drone)
  540. netbuffer->player |= PL_DRONE;
  541. netbuffer->numtics = 0;
  542. for (i=0 ; i<4 ; i++)
  543. {
  544. for (j=1 ; j<doomcom->numnodes ; j++)
  545. if (nodeingame[j])
  546. HSendPacket (j, NCMD_EXIT);
  547. I_WaitVBL (1);
  548. }
  549. }
  550. /*
  551. ===============
  552. =
  553. = TryRunTics
  554. =
  555. ===============
  556. */
  557. int frametics[4], frameon;
  558. int frameskip[4];
  559. int oldnettics;
  560. extern boolean advancedemo;
  561. void TryRunTics (void)
  562. {
  563. int i;
  564. int lowtic, nextlowest;
  565. int entertic;
  566. int static oldentertics;
  567. int realtics, availabletics;
  568. int counts;
  569. int numplaying;
  570. //
  571. // get real tics
  572. //
  573. entertic = I_GetTime ();
  574. realtics = entertic - oldentertics;
  575. oldentertics = entertic;
  576. //
  577. // get available tics
  578. //
  579. NetUpdate ();
  580. lowtic = nextlowest = MAXINT;
  581. numplaying = 0;
  582. for (i=0 ; i<doomcom->numnodes ; i++)
  583. if (nodeingame[i])
  584. {
  585. numplaying++;
  586. if (nettics[i] < lowtic)
  587. {
  588. nextlowest = lowtic;
  589. lowtic = nettics[i];
  590. }
  591. else if (nettics[i] < nextlowest)
  592. nextlowest = nettics[i];
  593. }
  594. availabletics = lowtic - gametic;
  595. //
  596. // decide how many tics to run
  597. //
  598. if (realtics < availabletics-1)
  599. counts = realtics+1;
  600. else if (realtics < availabletics)
  601. counts = realtics;
  602. else
  603. counts = availabletics;
  604. if (counts < 1)
  605. counts = 1;
  606. frameon++;
  607. if (debugfile)
  608. fprintf (debugfile,"=======real: %i avail: %i game: %i\n",realtics, availabletics,counts);
  609. //=============================================================================
  610. //
  611. // ideally nettics[0] should be 1 - 3 tics above lowtic
  612. // if we are consistantly slower, speed up time
  613. // drones should never hold up the other players
  614. //
  615. for (i=0 ; i<MAXPLAYERS ; i++)
  616. if (playeringame[i])
  617. break;
  618. if (consoleplayer == i)
  619. { // the key player does not adapt
  620. }
  621. else
  622. {
  623. if (nettics[0] <= nettics[nodeforplayer[i]])
  624. {
  625. gametime--;
  626. // printf ("-");
  627. }
  628. frameskip[frameon&3] = (oldnettics > nettics[nodeforplayer[i]]);
  629. oldnettics = nettics[0];
  630. if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
  631. {
  632. skiptics = 1;
  633. // printf ("+");
  634. }
  635. }
  636. //=============================================================================
  637. //
  638. // wait for new tics if needed
  639. //
  640. while (lowtic < gametic + counts)
  641. {
  642. NetUpdate ();
  643. lowtic = MAXINT;
  644. for (i=0 ; i<doomcom->numnodes ; i++)
  645. if (nodeingame[i] && nettics[i] < lowtic)
  646. lowtic = nettics[i];
  647. if (lowtic < gametic)
  648. I_Error ("TryRunTics: lowtic < gametic");
  649. // don't stay in here forever -- give the menu a chance to work
  650. if (I_GetTime () - entertic >= 20)
  651. {
  652. MN_Ticker ();
  653. return;
  654. }
  655. }
  656. //
  657. // run the tics
  658. //
  659. while (counts--)
  660. {
  661. if (advancedemo)
  662. D_DoAdvanceDemo ();
  663. MN_Ticker ();
  664. G_Ticker ();
  665. NetUpdate (); // check for new console commands
  666. gametic++;
  667. }
  668. }