1 #include "build.h"
2 #include "names.h"
3 #include "pragmas.h"
4 #include "cache1d.h"
5 #include "baselayer.h"
6 #include "renderlayer.h"
7 #include "common.h"
8 #include "mmulti.h"
9 #include "keyboard.h"
10 #include "control.h"
11 #include "config.h"
12 #include "tekwar.h"
13 #include "tekver.cpp"
14 #include "grpscan.h"
15 #include "osdcmds.h"
16 #include "common_game.h"
17
18 #ifdef _WIN32
19 # include "winbits.h"
20 #endif /* _WIN32 */
21
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 extern const char* s_buildRev;
26 extern const char* s_buildTimestamp;
27 #ifdef __cplusplus
28 }
29 #endif
30
31 const char* AppProperName = APPNAME;
32 const char* AppTechnicalName = APPBASENAME;
33
34 static char g_rootDir[BMAX_PATH];
35
36 int mouseaiming, aimmode, mouseflip;
37 int runkey_mode, auto_run;
38
39
40 #if defined GEKKO
41 # define FPS_YOFFSET 16
42 #else
43 # define FPS_YOFFSET 0
44 #endif
45
46 void shutdown();
47
M32RunScript(const char * s)48 void M32RunScript(const char* s) { UNREFERENCED_PARAMETER(s); }
app_crashhandler(void)49 void app_crashhandler(void)
50 {
51 shutdown();
52 }
53
54
55 #define SECT_LOTAG_CLIMB 5060
56
57 #ifdef TEKWAR
58 FILE *dbgfp;
59 int dbgfilen;
60 char dbgfname[16];
61 int dbgflag;
62 int dbgcolumn;
63 short mousebias=1;
64 short biasthreshhold=72;
65 char biasthreshholdon=0;
66 short lastmousy;
67 char keyedhorizon;
68 //** Les START - 09/26/95
69 char jstickenabled=0;
70 int jlowx,jlowy,
71 jhighx,jhighy;
72 char oldjoyb;
73 //** Les END - 09/26/95
74 short yaw,pitch,roll,vrangle,vrpitch;
75
76 #endif
77
78 int vel, svel, angvel;
79 int vel2, svel2, angvel2;
80
81 int recording = -2;
82
83 #ifdef TEKWAR
84 int xdimgame = 640, ydimgame = 480, bppgame = 8;
85 int forcesetup = 1;
86
87 #define MAXMOREOPTIONS 21
88 #define MAXTOGGLES 16
89 #define MAXGAMESTUFF 16
90 unsigned char option[NUMOPTIONS] = {
91 1, // 0 VIDEO MODE CHAINED OR NO
92 0, // 1 SOUND CHOICE
93 0, // 2 MUSIC CHOICE
94 1, // 3 MOUSE ON/OFF
95 0, // 4 MULTIPLAYER COUNT
96 0, // 5 MULTIPLYER SETTING
97 2, // 6 VIDEO RES CHOICE
98 0 // 7 SOUND FREQ
99 };
100 unsigned char keys[NUMGAMEKEYS] = {
101 200, // 0 FWD
102 208, // 1 BKWD
103 203, // 2 RIGHT
104 205, // 3 LEFT
105 42, // 4 RUN / AMPLIFY
106 56, // 5 STRAFE
107 29, // 6 SHOOT
108 57, // 7 USE
109 45, // 8 JUMP
110 46, // 9 CROUCH
111 201, // 10 LOOK UP
112 209, // 11 LOOK DOWN
113 51, // 12 SLIDE LEFT
114 52, // 13 SLIDE RIGHT
115 15, // 14 MAP MODE
116 156, // 15 SWITCH PLAYER
117 13, // 16 EXPAND VIEW
118 12, // 17 SHRINK VIEW
119 50, // 18 MESSAGE MODE
120 199, // 19 AUTOCENTER
121 19, // 20 TOGGLE REARVIEW
122 18, // 21 TOGGLE PREPARED ITEM
123 35, // 22 TOGGLE HEALTH METER
124 34, // 23 TOGGLE CROSSHAIRS
125 20, // 24 TOGGLE ELAPSED TIME
126 31, // 25 TOGGLE SCORE
127 23, // 26 TOGGLE INVENTORY
128 53, // 27 CONCEAL WEAPON
129 58, // 28 MOUSE LOOKUP/DOWN
130 26, // 29 N/U
131 26, // 30 N/U
132 26 // 31 N/U
133 };
134 unsigned char moreoptions[MAXMOREOPTIONS] = {
135 1, // 0 MOUSE ON/OFF
136 29, // 1 MOUSE BUTTON 1 MAP
137 200, // 2 MOUSE BUTTON 2 MAP
138 0, // 3 JOYSTICK ON/OFF
139 4, // 4 JOYSTICK BUTTON 1 MAP
140 6, // 5 JOYSTICK BUTTON 2 MAP
141 10, // 6 JOYSTICK BUTTON 3 MAP
142 11, // 7 JOYSTICK BUTTON 4 MAP
143 1, // 8 DIFFICULTY LEVEL
144 16, // 9 SOUND VOLUME
145 16, // 10 MUSIC VOLUME
146 8, // 11 MOUSE SENSITIVITY
147 1, // 12 HEAD BOB
148 0, // 13 N/U
149 0, // 14 N/U
150 0 // 15 N/U
151 };
152 char toggles[MAXTOGGLES] = { 1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0 };
153 int gamestuff[MAXGAMESTUFF] = {
154 -1, // 0 joyxcenter
155 -1, // 1 joyycenter
156 0, // 2 screensize
157 0, // 3 brightness
158 100, // 4 biasthreshhold
159 0, // 5 warpretang
160 0, // 6 warpretsect
161 0, // 7
162 0, // 8
163 0, // 9
164 0, // 10
165 0, // 11
166 0, // 12
167 0, // 13
168 0, // 14
169 0 // 15
170 };
171 #endif
172
173 char frame2draw[MAXPLAYERS];
174 int frameskipcnt[MAXPLAYERS];
175
176 char gundmost[320];
177
178 //Shared player variables
179 int posx[MAXPLAYERS], posy[MAXPLAYERS], posz[MAXPLAYERS];
180 int horiz[MAXPLAYERS], zoom[MAXPLAYERS], hvel[MAXPLAYERS];
181 short ang[MAXPLAYERS], cursectnum[MAXPLAYERS], ocursectnum[MAXPLAYERS];
182 short playersprite[MAXPLAYERS], deaths[MAXPLAYERS];
183 int lastchaingun[MAXPLAYERS];
184 int health[MAXPLAYERS], score[MAXPLAYERS], saywatchit[MAXPLAYERS];
185 short numbombs[MAXPLAYERS], oflags[MAXPLAYERS];
186 char dimensionmode[MAXPLAYERS];
187 char revolvedoorstat[MAXPLAYERS];
188 short revolvedoorang[MAXPLAYERS], revolvedoorrotang[MAXPLAYERS];
189 int revolvedoorx[MAXPLAYERS], revolvedoory[MAXPLAYERS];
190
191 //Local multiplayer variables
192 int locselectedgun;
193 signed char locvel, olocvel;
194 short locsvel, olocsvel; // Les 09/27/95
195 short locangvel, olocangvel; // Les 09/27/95
196 short locbits, olocbits;
197
198 //Local multiplayer variables for second player
199 int locselectedgun2;
200 signed char locvel2, olocvel2;
201 short locsvel2, olocsvel2; // Les 09/27/95
202 short locangvel2, olocangvel2; // Les 09/27/95
203 short locbits2, olocbits2;
204
205 //Multiplayer syncing variables
206 signed char fsyncvel[MAXPLAYERS], osyncvel[MAXPLAYERS], syncvel[MAXPLAYERS];
207 short fsyncsvel[MAXPLAYERS], osyncsvel[MAXPLAYERS], syncsvel[MAXPLAYERS]; // Les 09/27/95
208 short fsyncangvel[MAXPLAYERS], osyncangvel[MAXPLAYERS], syncangvel[MAXPLAYERS]; // Les 09/27/95
209 unsigned short fsyncbits[MAXPLAYERS], osyncbits[MAXPLAYERS], syncbits[MAXPLAYERS];
210
211 char frameinterpolate = 1, detailmode = 0, ready2send = 0;
212 int ototalclock = 0, gotlastpacketclock = 0, smoothratio;
213 int oposx[MAXPLAYERS], oposy[MAXPLAYERS], oposz[MAXPLAYERS];
214 int ohoriz[MAXPLAYERS], ozoom[MAXPLAYERS];
215 short oang[MAXPLAYERS];
216
217 point3d osprite[MAXSPRITESONSCREEN];
218
219 int movefifoplc, movefifoend;
220 signed char baksyncvel[MOVEFIFOSIZ][MAXPLAYERS];
221 short baksyncsvel[MOVEFIFOSIZ][MAXPLAYERS]; // Les 09/27/95
222 short baksyncangvel[MOVEFIFOSIZ][MAXPLAYERS]; // Les 09/27/95
223 short baksyncbits[MOVEFIFOSIZ][MAXPLAYERS];
224
225 //GAME.C sync state variables
226 short syncstat = 0;
227 int syncvalplc, othersyncvalplc;
228 int syncvalend, othersyncvalend;
229 int syncvalcnt, othersyncvalcnt;
230 short syncval[MOVEFIFOSIZ], othersyncval[MOVEFIFOSIZ];
231
232 extern int crctable[256];
233 char playerreadyflag[MAXPLAYERS];
234
235 //Game recording variables
236 int reccnt, recstat = 1;
237 signed char recsyncvel[16384][2];
238 short recsyncsvel[16384][2]; // Les 09/27/95
239 short recsyncangvel[16384][2]; // Les 09/27/95
240 short recsyncbits[16384][2];
241
242 //Miscellaneous variables
243 char tempbuf[256];
244 uint8_t packetbuf[MAXXDIM];
245 char boardfilename[80];
246 short screenpeek = 0, oldmousebstatus = 0, brightness = 0;
247 short screensize, screensizeflag = 0;
248 short neartagsector, neartagwall, neartagsprite;
249 int lockclock, neartagdist, neartaghitdist;
250 int masterslavetexttime;
251 int globhiz, globloz, globhihit, globlohit;
252
253 //Board animation variables
254 short rotatespritelist[16], rotatespritecnt;
255 short warpsectorlist[64], warpsectorcnt;
256 short xpanningsectorlist[16], xpanningsectorcnt;
257 short ypanningwalllist[64], ypanningwallcnt;
258 short floorpanninglist[64], floorpanningcnt;
259 short dragsectorlist[16], dragxdir[16], dragydir[16], dragsectorcnt;
260 int dragx1[16], dragy1[16], dragx2[16], dragy2[16], dragfloorz[16];
261 short swingcnt, swingwall[32][5], swingsector[32];
262 short swingangopen[32], swingangclosed[32], swingangopendir[32];
263 short swingang[32], swinganginc[32];
264 int swingx[32][8], swingy[32][8];
265 short revolvesector[4], revolveang[4], revolvecnt;
266 int revolvex[4][16], revolvey[4][16];
267 int revolvepivotx[4], revolvepivoty[4];
268 short subwaytracksector[4][128], subwaynumsectors[4], subwaytrackcnt;
269 int subwaystop[4][8], subwaystopcnt[4];
270 int subwaytrackx1[4], subwaytracky1[4];
271 int subwaytrackx2[4], subwaytracky2[4];
272 int subwayx[4], subwaygoalstop[4], subwayvel[4], subwaypausetime[4];
273 short waterfountainwall[MAXPLAYERS], waterfountaincnt[MAXPLAYERS];
274 short slimesoundcnt[MAXPLAYERS];
275
276 //Variables that let you type messages to other player
277 char getmessage[162], getmessageleng;
278 int getmessagetimeoff;
279 char typemessage[162];
280 int typemessageleng = 0, typemode = 0;
281 char scantoasc[128] =
282 {
283 0,0,'1','2','3','4','5','6','7','8','9','0','-','=',0,0,
284 'q','w','e','r','t','y','u','i','o','p','[',']',0,0,'a','s',
285 'd','f','g','h','j','k','l',';',39,'`',0,92,'z','x','c','v',
286 'b','n','m',',','.','/',0,'*',0,32,0,0,0,0,0,0,
287 0,0,0,0,0,0,0,'7','8','9','-','4','5','6','+','1',
288 '2','3','0','.',0,0,0,0,0,0,0,0,0,0,0,0,
289 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
290 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
291 };
292 char scantoascwithshift[128] =
293 {
294 0,0,'!','@','#','$','%','^','&','*','(',')','_','+',0,0,
295 'Q','W','E','R','T','Y','U','I','O','P','{','}',0,0,'A','S',
296 'D','F','G','H','J','K','L',':',34,'~',0,'|','Z','X','C','V',
297 'B','N','M','<','>','?',0,'*',0,32,0,0,0,0,0,0,
298 0,0,0,0,0,0,0,'7','8','9','-','4','5','6','+','1',
299 '2','3','0','.',0,0,0,0,0,0,0,0,0,0,0,0,
300 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
301 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
302 };
303
304 //These variables are for animating x, y, or z-coordinates of sectors,
305 //walls, or sprites (They are NOT to be used for changing the [].picnum's)
306 //See the setanimation(), and getanimategoal() functions for more details.
307 int *animateptr[MAXANIMATES], animategoal[MAXANIMATES];
308 int animatevel[MAXANIMATES], animateacc[MAXANIMATES], animatecnt = 0;
309
310 int32_t g_commandSetup = 0;
311 int32_t g_noSetup = 0;
312 int32_t g_noAutoLoad = 0;
313
314 //////////
315
316 enum gametokens
317 {
318 T_INCLUDE = 0,
319 T_INTERFACE = 0,
320 T_LOADGRP = 1,
321 T_MODE = 1,
322 T_CACHESIZE = 2,
323 T_ALLOW = 2,
324 T_NOAUTOLOAD,
325 T_INCLUDEDEFAULT,
326 T_MUSIC,
327 T_SOUND,
328 T_FILE,
329 T_CUTSCENE,
330 T_ANIMSOUNDS,
331 T_NOFLOORPALRANGE,
332 T_ID,
333 T_MINPITCH,
334 T_MAXPITCH,
335 T_PRIORITY,
336 T_TYPE,
337 T_DISTANCE,
338 T_VOLUME,
339 T_DELAY,
340 T_RENAMEFILE,
341 T_GLOBALGAMEFLAGS,
342 T_ASPECT,
343 T_FORCEFILTER,
344 T_FORCENOFILTER,
345 T_TEXTUREFILTER,
346 T_NEWGAMECHOICES,
347 T_CHOICE,
348 T_NAME,
349 T_LOCKED,
350 T_HIDDEN,
351 T_USERCONTENT,
352 };
353
354 int tekwar_globalflags;
355
356 static int parsedefinitions_game(scriptfile*, int);
357
parsedefinitions_game_include(const char * fileName,scriptfile * pScript,const char * cmdtokptr,int const firstPass)358 static void parsedefinitions_game_include(const char* fileName, scriptfile* pScript, const char* cmdtokptr, int const firstPass)
359 {
360 scriptfile* included = scriptfile_fromfile(fileName);
361
362 if (!included)
363 {
364 if (!Bstrcasecmp(cmdtokptr, "null") || pScript == NULL) // this is a bit overboard to prevent unused parameter warnings
365 {
366 // initprintf("Warning: Failed including %s as module\n", fn);
367 }
368 /*
369 else
370 {
371 initprintf("Warning: Failed including %s on line %s:%d\n",
372 fn, script->filename,scriptfile_getlinum(script,cmdtokptr));
373 }
374 */
375 }
376 else
377 {
378 parsedefinitions_game(included, firstPass);
379 scriptfile_close(included);
380 }
381 }
382
parsedefinitions_game(scriptfile * pScript,int firstPass)383 static int parsedefinitions_game(scriptfile* pScript, int firstPass)
384 {
385 int token;
386 char* pToken;
387
388 static const tokenlist tokens[] =
389 {
390 { "include", T_INCLUDE },
391 { "#include", T_INCLUDE },
392 { "includedefault", T_INCLUDEDEFAULT },
393 { "#includedefault", T_INCLUDEDEFAULT },
394 { "loadgrp", T_LOADGRP },
395 { "cachesize", T_CACHESIZE },
396 { "noautoload", T_NOAUTOLOAD },
397 { "renamefile", T_RENAMEFILE },
398 { "globalgameflags", T_GLOBALGAMEFLAGS },
399 };
400
401 do
402 {
403 token = getatoken(pScript, tokens, ARRAY_SIZE(tokens));
404 pToken = pScript->ltextptr;
405
406 switch (token)
407 {
408 case T_LOADGRP:
409 {
410 char* fileName;
411
412 pathsearchmode = 1;
413 if (!scriptfile_getstring(pScript, &fileName) && firstPass)
414 {
415 if (initgroupfile(fileName) == -1)
416 initprintf("Could not find file \"%s\".\n", fileName);
417 else
418 {
419 initprintf("Using file \"%s\" as game data.\n", fileName);
420 if (!g_noAutoLoad && !gSetup.noautoload)
421 G_DoAutoload(fileName);
422 }
423 }
424
425 pathsearchmode = 0;
426 }
427 break;
428 case T_CACHESIZE:
429 {
430 int32_t cacheSize;
431
432 if (scriptfile_getnumber(pScript, &cacheSize) || !firstPass)
433 break;
434
435 if (cacheSize > 0)
436 MAXCACHE1DSIZE = cacheSize << 10;
437 }
438 break;
439 case T_INCLUDE:
440 {
441 char* fileName;
442
443 if (!scriptfile_getstring(pScript, &fileName))
444 parsedefinitions_game_include(fileName, pScript, pToken, firstPass);
445
446 break;
447 }
448 case T_INCLUDEDEFAULT:
449 {
450 parsedefinitions_game_include(G_DefaultDefFile(), pScript, pToken, firstPass);
451 break;
452 }
453 case T_NOAUTOLOAD:
454 if (firstPass)
455 g_noAutoLoad = 1;
456 break;
457 case T_GLOBALGAMEFLAGS: scriptfile_getnumber(pScript, &tekwar_globalflags); break;
458 case T_EOF: return 0;
459 default: break;
460 }
461 } while (1);
462
463 return 0;
464 }
465
loaddefinitions_game(const char * fileName,int32_t firstPass)466 int loaddefinitions_game(const char* fileName, int32_t firstPass)
467 {
468 scriptfile* pScript = scriptfile_fromfile(fileName);
469
470 if (pScript)
471 parsedefinitions_game(pScript, firstPass);
472
473 for (char const* m : g_defModules)
474 parsedefinitions_game_include(m, NULL, "null", firstPass);
475
476 if (pScript)
477 scriptfile_close(pScript);
478
479 scriptfile_clearsymbols();
480
481 return 0;
482 }
483
484 #define FPS_COLOR(x) ((x) ? COLOR_RED : COLOR_WHITE)
485
486 #define COLOR_RED redcol
487 #define COLOR_WHITE whitecol
488
489 #define LOW_FPS ((videoGetRenderMode() == REND_CLASSIC) ? 35 : 50)
490 #define SLOW_FRAME_TIME 20
491
G_PrintFPS(void)492 static void G_PrintFPS(void)
493 {
494 static char tempbuf[256];
495 static int32_t frameCount;
496 static double cumulativeFrameDelay;
497 static double lastFrameTime;
498 static float lastFPS; // , minFPS = std::numeric_limits<float>::max(), maxFPS;
499 //static double minGameUpdate = std::numeric_limits<double>::max(), maxGameUpdate;
500
501 double frameTime = timerGetHiTicks();
502 double frameDelay = frameTime - lastFrameTime;
503 cumulativeFrameDelay += frameDelay;
504
505 if (frameDelay >= 0)
506 {
507 int32_t x = (xdim <= 640);
508
509 if (r_showfps)
510 {
511 int32_t chars = Bsprintf(tempbuf, "%.1f ms, %5.1f fps", frameDelay, lastFPS);
512
513 printext256(windowxy2.x - (chars << (3 - x)) + 1, windowxy1.y + 2 + FPS_YOFFSET, blackcol, -1, tempbuf, x);
514 printext256(windowxy2.x - (chars << (3 - x)), windowxy1.y + 1 + FPS_YOFFSET,
515 FPS_COLOR(lastFPS < LOW_FPS), -1, tempbuf, x);
516 }
517
518 if (cumulativeFrameDelay >= 1000.0)
519 {
520 lastFPS = 1000.f * frameCount / cumulativeFrameDelay;
521 // g_frameRate = Blrintf(lastFPS);
522 frameCount = 0;
523 cumulativeFrameDelay = 0.0;
524 }
525 frameCount++;
526 }
527 lastFrameTime = frameTime;
528 }
529
530 void shutdown();
531
debugout(short p)532 void debugout(short p)
533 {
534 static int dbglines;
535
536 if (dbgcolumn != 0) {
537 fprintf(dbgfp,"\n");
538 }
539 fprintf(dbgfp,"%2d %6d %3d %04X %04d %06d %06d %06d %06d %d\n",
540 p,lockclock,movefifoplc,syncbits[p],ang[p],posx[p],posy[p],posz[p],
541 health[p],randomseed);
542 dbglines++;
543 dbgcolumn=0;
544 if (dbglines > 2000) {
545 dbglines=0;
546 fclose(dbgfp);
547 sprintf(dbgfname,"DEBUG.%03d",dbgfilen++);
548 dbgfp=fopen(dbgfname,"wt");
549 fprintf(dbgfp," P CLOCK PLC BITS ANG X Y Z HEALTH RSEED\n");
550 fprintf(dbgfp,"== ====== === ==== ==== ===== ===== ===== ====== =========\n");
551 }
552 }
553
554
555 char localname[MAXNAMESIZE];
556 char netnames[MAXPLAYERS][MAXNAMESIZE];
557
558 extern int startwin_run(void);
559
InstallEngine()560 void InstallEngine()
561 {
562 lm("initgroupfile");
563 // initgroupfile("stuff.dat");
564
565 char* cwd;
566
567 if (g_modDir[0] != '/' && (cwd = buildvfs_getcwd(NULL, 0)))
568 {
569 buildvfs_chdir(g_modDir);
570 if (artLoadFiles("tiles%03i.art", MAXCACHE1DSIZE) < 0)
571 {
572 buildvfs_chdir(cwd);
573 if (artLoadFiles("tiles%03i.art", MAXCACHE1DSIZE) < 0)
574 crash("Failed loading art.");
575 }
576 buildvfs_chdir(cwd);
577 #ifndef __ANDROID__ //This crashes on *some* Android devices. Small onetime memory leak. TODO fix above function
578 Xfree(cwd);
579 #endif
580 }
581 else if (artLoadFiles("tiles%03i.art", MAXCACHE1DSIZE) < 0)
582 crash("Failed loading art.");
583
584 if (engineInit())
585 {
586 wm_msgbox("Fatal Engine Initialization Error",
587 "There was a problem initializing the engine: %s\n\nThe application will now close.", engineerrstr);
588 //TODO:
589 //G_Cleanup();
590 ERRprintf("G_Startup: There was a problem initializing the engine: %s\n", engineerrstr);
591 exit(6);
592 }
593 if (videoSetGameMode(gSetup.fullscreen, gSetup.xdim, gSetup.ydim, gSetup.bpp, 0) < 0)
594 {
595 initprintf("Failure setting video mode %dx%dx%d %s! Trying next mode...\n", gSetup.xdim, gSetup.ydim,
596 gSetup.bpp, gSetup.fullscreen?"fullscreen":"windowed");
597
598 int resIdx = 0;
599
600 for (int i = 0; i < validmodecnt; i++)
601 {
602 if (validmode[i].xdim == gSetup.xdim && validmode[i].ydim == gSetup.ydim)
603 {
604 resIdx = i;
605 break;
606 }
607 }
608
609 int const savedIdx = resIdx;
610 int bpp = gSetup.bpp;
611
612 while (videoSetGameMode(0, validmode[resIdx].xdim, validmode[resIdx].ydim, bpp, 0) < 0)
613 {
614 initprintf("Failure setting video mode %dx%dx%d windowed! Trying next mode...\n",
615 validmode[resIdx].xdim, validmode[resIdx].ydim, bpp);
616
617 if (++resIdx == validmodecnt)
618 {
619 if (bpp == 8)
620 crash("Fatal error: unable to set any video mode!");
621
622 resIdx = savedIdx;
623 bpp = 8;
624 }
625 }
626
627 gSetup.xdim = validmode[resIdx].xdim;
628 gSetup.ydim = validmode[resIdx].ydim;
629 gSetup.bpp = bpp;
630 }
631
632 // build.obj is dated 9th July 1995
633 enginecompatibilitymode = ENGINE_19950829;
634 }
635
shutdown()636 void shutdown()
637 {
638 CONFIG_WriteSetup(0);
639
640 // TODO SND_Shutdown();
641
642 engineUnInit();
643
644 uninitgroupfile();
645
646 exit(EXIT_SUCCESS);
647 }
648
app_main(int argc,char const * const argv[])649 int app_main(int argc, char const * const argv[])
650 {
651 int i, waitplayers;
652 int other;
653
654 sprintf(tektempbuf, TITLE, VERS);
655 initputs(tektempbuf);
656 initputs("\n\n");
657 // wm_setapptitle(tektempbuf);
658
659 #ifdef _WIN32
660 #ifndef DEBUGGINGAIDS
661 if (!G_CheckCmdSwitch(argc, argv, "-noinstancechecking") && !windowsCheckAlreadyRunning())
662 {
663 #ifdef EDUKE32_STANDALONE
664 if (!wm_ynbox(APPNAME, "It looks like " APPNAME " is already running.\n\n"
665 #else
666 if (!wm_ynbox(APPNAME, "It looks like the game is already running.\n\n"
667 #endif
668 "Are you sure you want to start another copy?"))
669 return 3;
670 }
671 #endif
672 #endif
673
674 tekargv(argc, argv);
675
676 G_ExtPreInit(argc, argv);
677
678 OSD_SetLogFile(APPBASENAME ".log");
679
680 OSD_SetFunctions(NULL,
681 NULL,
682 NULL,
683 NULL,
684 NULL,
685 GAME_clearbackground,
686 BGetTime,
687 GAME_onshowosd);
688
689 wm_setapptitle(APPNAME);
690
691 initprintf("TekWar %s\n", s_buildRev);
692 PrintBuildInfo();
693
694 // This needs to happen afterwards, as G_CheckCommandLine() is where we set
695 // up the command-line-provided search paths (duh).
696 G_ExtInit();
697
698 #if defined(RENDERTYPEWIN) && defined(USE_OPENGL)
699 if (forcegl) initprintf("GL driver blacklist disabled.\n");
700 #endif
701
702 // used with binds for fast function lookup
703 hash_init(&h_gamefuncs);
704 for (bssize_t i = kMaxGameFunctions - 1; i >= 0; i--)
705 {
706 if (gamefunctions[i][0] == '\0')
707 continue;
708
709 hash_add(&h_gamefuncs, gamefunctions[i], i, 0);
710 }
711
712 #ifdef STARTUP_SETUP_WINDOW
713 int const readSetup =
714 #endif
715 CONFIG_ReadSetup();
716
717 if (enginePreInit()) {
718 wm_msgbox("Build Engine Initialisation Error",
719 "There was a problem initialising the Build engine: %s", engineerrstr);
720 exit(1);
721 }
722
723 if (Bstrcmp(setupfilename, kSetupFilename))
724 initprintf("Using config file \"%s\".\n", setupfilename);
725
726 G_ScanGroups();
727
728 // REVERT wm_msgbox("Pre-Release Software Warning", "%s is not ready for public use. Proceed with caution!", AppProperName);
729
730 #ifdef STARTUP_SETUP_WINDOW
731 if (readSetup < 0 || (!g_noSetup && gSetup.forcesetup) || g_commandSetup)
732 {
733 if (quitevent || !startwin_run())
734 {
735 engineUnInit();
736 Bexit(0);
737 }
738 }
739 #endif
740
741 G_LoadGroups(!g_noAutoLoad && !gSetup.noautoload);
742
743 CONFIG_WriteSetup(1);
744 CONFIG_ReadSetup();
745
746 Bsprintf(tempbuf, "TekWar %s", s_buildRev);
747 OSD_SetVersion(tempbuf, 10, 0);
748 OSD_SetParameters(0, 0, 0, 0, 0, 0, OSD_ERROR, OSDTEXT_RED, gamefunctions[gamefunc_Show_Console][0] == '\0'?OSD_PROTECTED:0);
749 registerosdcommands();
750
751 lm("tekloadsetup");
752 tekloadsetup();
753
754 SetupInput();
755
756 /*
757 char* const setupFileName = Xstrdup(setupfilename);
758 char* const p = strtok(setupFileName, ".");
759
760 if (!p || !Bstrcmp(setupfilename, kSetupFilename))
761 Bsprintf(tempbuf, "settings.cfg");
762 else
763 Bsprintf(tempbuf, "%s_settings.cfg", p);
764
765 Xfree(setupFileName);
766 */
767 OSD_Exec("etekwar_cvars.cfg");
768 OSD_Exec("etekwar_autoexec.cfg");
769
770 CONFIG_SetDefaultKeys(keydefaults, true);
771
772 system_getcvars();
773
774 InstallEngine();
775
776 lm("inittimer");
777 timerInit(CLKIPS);
778 // TODO timerSetCallback(timerhandler);
779 lm("tekinitmultiplayers");
780 tekinitmultiplayers(0, NULL);
781 lm("initsb");
782 initsb(option[1],option[2],0,0,0,0,0);
783 lm("tekpreinit");
784 tekpreinit();
785 lm("tekgamestarted");
786 tekgamestarted();
787 lm("initinput");
788 initinput();
789 lm("initmouse");
790 // TODO if( option[3] != 0 ) initmouse();
791
792 if (dbgflag) {
793 lm("debug mode: ON");
794 sprintf(dbgfname,"DEBUG.%03d",dbgfilen++);
795 dbgfp=fopen(dbgfname,"wt");
796 fprintf(dbgfp," P CLOCK PLC BITS ANG X Y Z HEALTH RSEED\n");
797 fprintf(dbgfp,"== ====== === ==== ==== ===== ===== ===== ====== =========\n");
798 dbgcolumn=0;
799 }
800
801 const char* defsfile = G_DefFile();
802 uint32_t stime = timerGetTicks();
803 if (!loaddefinitionsfile(defsfile))
804 {
805 uint32_t etime = timerGetTicks();
806 initprintf("Definitions file \"%s\" loaded in %d ms.\n", defsfile, etime - stime);
807 }
808 loaddefinitions_game(defsfile, FALSE);
809
810 if (enginePostInit())
811 shutdown();
812
813 KB_Startup();
814 // TODO SND_Startup();
815
816 if (option[4] > 0)
817 {
818 lm("multiplayer init");
819 teknetpickmap();
820 sendlogon();
821
822 if (option[4] < 5) {
823 waitplayers = 2;
824 }
825 else {
826 waitplayers = option[4] - 3;
827 }
828
829 while (numplayers < waitplayers)
830 {
831 videoClearViewableArea(0);
832 overwritesprite((xdim >> 1) - 160, 0, 408, 0, 0, 0);
833 sprintf(tempbuf, " MULTIPLAYER MODE ");
834 printext((xdim >> 1) - 80, (ydim >> 1) - 24, tempbuf, ALPHABET2, 0);
835 sprintf(tempbuf, "%2d OF %2d PLAYERS IN", numplayers, waitplayers);
836 printext((xdim >> 1) - 80, ydim >> 1, tempbuf, ALPHABET2, 0);
837 videoNextPage();
838 if (getpacket(&other, packetbuf) > 0)
839 {
840 if (packetbuf[0] == 255) {
841 keystatus[1] = 1;
842 }
843 }
844 if (keystatus[1] > 0) {
845 goto gameends;
846 }
847 }
848 screenpeek = myconnectindex;
849 videoClearViewableArea(0);
850 }
851 for (i = connecthead; i >= 0; i = connectpoint2[i]) {
852 initplayersprite((short)i);
853 }
854
855 if (option[4] == 0) {
856 smkplayseq("INTRO");
857 }
858
859 missionselection:
860 if (option[4] == 0)
861 {
862 if (choosemission() == 0) {
863 goto gameends;
864 }
865 }
866
867 reccnt=0;
868 movefifoplc = 0; movefifoend = 0;
869 syncvalplc = 0; othersyncvalplc = 0;
870 syncvalend = 0; othersyncvalend = 0;
871 syncvalcnt = 0L; othersyncvalcnt = 0L;
872 olocvel = 0; olocvel2 = 0;
873 olocsvel = 0; olocsvel2 = 0;
874 olocangvel = 0; olocangvel2 = 0;
875 olocbits = 0; olocbits2 = 0;
876 lockclock = 0;
877 ototalclock = 0;
878 gotlastpacketclock = 0;
879 masterslavetexttime = 0;
880 for (i = 0; i < MAXPLAYERS; i++)
881 {
882 fsyncvel[i] = syncvel[i] = osyncvel[i] = 0;
883 fsyncsvel[i] = syncsvel[i] = osyncsvel[i] = 0;
884 fsyncangvel[i] = syncangvel[i] = osyncangvel[i] = 0;
885 fsyncbits[i] = syncbits[i] = osyncbits[i] = 0;
886 }
887 resettiming();
888
889 ready2send = 1;
890 #ifdef NETNAMES
891 if (option[4] != 0)
892 {
893 packetbuf[0] = 8;
894 packetbuf[1] = myconnectindex;
895 memcpy(&packetbuf[2], localname, 10);
896 packetbuf[12] = 0;
897 for (i = connecthead; i >= 0; i = connectpoint2[i])
898 {
899 if (i != myconnectindex)
900 {
901 sendpacket(i, packetbuf, 12);
902 }
903 }
904 memcpy(netnames[myconnectindex], localname, 10);
905 netnames[myconnectindex][10] = 0;
906 }
907 #endif
908 screenpeek=myconnectindex;
909 while (!gameover)
910 {
911 handleevents();
912 while (movefifoplc != movefifoend) {
913 domovethings();
914 }
915 drawscreen(screenpeek, (((int)totalclock) - gotlastpacketclock) * (65536 / TICSPERFRAME));
916 }
917 ready2send = 0;
918
919 if (option[4] == 0)
920 {
921 debrief = 1;
922 goto missionselection;
923 }
924
925 gameends:
926
927 CONFIG_WriteSetup(0);
928
929 copyrightscreen();
930
931 sendlogoff();
932 uninitmultiplayers();
933 uninitsb();
934 cduninit();
935 //uninittimer();
936 uninitinput();
937 engineUnInit();
938 uninitgroupfile();
939
940 teksavesetup();
941
942 if (dbgflag) {
943 fclose(dbgfp);
944 }
945
946 exit(0);
947 }
948
949 void
processinput(short snum)950 processinput(short snum)
951 {
952 int nexti;
953 int i,j, doubvel, xvect, yvect, goalz;
954 int dax, day;
955 char *ptr;
956 vec3_t pos;
957
958 // move player snum
959 if (snum < 0 || snum >= MAXPLAYERS) {
960 crash("game712: Invalid player number (%d)",snum);
961 }
962
963 if (cursectnum[snum] < 0 || cursectnum[snum] >= numsectors) {
964 crash("game718: Invalid sector for player %d @ %ld,%ld (%d)",snum,
965 posx[snum],posy[snum],cursectnum[snum]);
966 }
967
968 if( (syncvel[snum]|syncsvel[snum]) != 0 ) {
969 // no run while crouching
970 if( ((syncbits[snum]&2) != 0) && (mission != 7) ) {
971 doubvel = 1+((syncbits[snum]&256) == 0);
972 }
973 else {
974 doubvel = (TICSPERFRAME<<((syncbits[snum]&256)>0));
975 doubvel<<=1;
976 }
977 xvect = 0, yvect = 0;
978 if( syncvel[snum] != 0 ) {
979 xvect += ((((int)syncvel[snum])*doubvel*(int)sintable[(ang[snum]+2560)&2047])>>3);
980 yvect += ((((int)syncvel[snum])*doubvel*(int)sintable[(ang[snum]+2048)&2047])>>3);
981 }
982 if( syncsvel[snum] != 0 ) {
983 xvect += ((((int)syncsvel[snum])*doubvel*(int)sintable[(ang[snum]+2048)&2047])>>3);
984 yvect += ((((int)syncsvel[snum])*doubvel*(int)sintable[(ang[snum]+1536)&2047])>>3);
985 }
986
987 pos.x = posx[snum]; pos.y = posy[snum]; pos.z = posz[snum];
988 clipmove(&pos,&cursectnum[snum],xvect,yvect,128L,4<<8,4<<8,CLIPMASK0);
989
990 posx[snum] = pos.x; posy[snum] = pos.y; posz[snum] = pos.z;
991
992 frameinterpolate = 1;
993 revolvedoorstat[snum] = 1;
994 if( option[4] == 0 ) {
995 tekheadbob();
996 }
997 }
998 else {
999 revolvedoorstat[snum] = 0;
1000 headbob=0;
1001 }
1002
1003 // push player away from walls if clipmove doesn't work
1004 pos.x = posx[snum]; pos.y = posy[snum]; pos.z = posz[snum];
1005
1006 if( pushmove(&pos,&cursectnum[snum],128L,4<<8,4<<8,CLIPMASK0) < 0 ) {
1007 changehealth(snum,-1000); // if this fails then instant death
1008 changescore(snum,-5);
1009 }
1010
1011 posx[snum] = pos.x; posy[snum] = pos.y; posz[snum] = pos.z;
1012
1013 if (cursectnum[snum] < 0 || cursectnum[snum] >= numsectors) {
1014 crash("game748: Invalid sector for player %d @ %ld,%ld (%d)",snum,
1015 posx[snum],posy[snum],cursectnum[snum]);
1016 }
1017 if (playersprite[snum] < 0 || playersprite[snum] >= MAXSPRITES) {
1018 crash("game751: Invalid sprite for player %d (%d)",snum,playersprite[snum]);
1019 }
1020
1021 // getzrange returns the highest and lowest z's for an entire box,
1022 // NOT just a point. This prevents you from falling off cliffs
1023 // when you step only slightly over the cliff.
1024 sprite[playersprite[snum]].cstat ^= 1;
1025
1026 pos.x = posx[snum]; pos.y = posy[snum]; pos.z = posz[snum];
1027 getzrange(&pos,cursectnum[snum],&globhiz,&globhihit,&globloz,&globlohit,128L,CLIPMASK0);
1028 sprite[playersprite[snum]].cstat ^= 1;
1029
1030 if( cursectnum[snum] != ocursectnum[snum] ) {
1031 teknewsector(snum);
1032 }
1033
1034 // ang += angvel*constant, engine calculates angvel
1035 if( syncangvel[snum] != 0 ) {
1036 doubvel = TICSPERFRAME;
1037 // if run key then turn faster
1038 if( (syncbits[snum]&256) > 0 ) {
1039 doubvel += (TICSPERFRAME>>1);
1040 }
1041 ang[snum] += ((((int)syncangvel[snum])*doubvel)>>4);
1042 ang[snum] = (ang[snum]+2048)&2047;
1043 }
1044
1045 if( health[snum] < 0 ) {
1046 health[snum] -= (TICSPERFRAME<<1);
1047 if( health[snum] <= -160 ) {
1048 hvel[snum] = 0;
1049 if( snum == myconnectindex ) {
1050 vel = 0, svel = 0, angvel = 0, keystatus[3] = 1;
1051 }
1052 deaths[snum]++;
1053 if( (option[4] == 0) && (numplayers == 1) ) {
1054 fadeout(0,255,32,0,0,100);
1055 }
1056 if( option[4] != 0 ) {
1057 netstartspot(&posx[snum],&posy[snum],&cursectnum[snum]);
1058 if (cursectnum[snum] < 0 || cursectnum[snum] >= numsectors) {
1059 crash("game818: Invalid sector for player %d (%d)",snum,cursectnum[snum]);
1060 }
1061 placerandompic(KLIPPIC);
1062 placerandompic(MEDICKITPIC);
1063 posz[snum] = sector[cursectnum[snum]].floorz-(1<<8);
1064 ang[snum] = (krand_intercept("GAME 802")&2047);
1065 }
1066 else {
1067 posx[snum]=startx;
1068 posy[snum]=starty;
1069 posz[snum]=startz;
1070 ang[snum]=starta;
1071 cursectnum[snum]=starts;
1072 }
1073
1074 tekrestoreplayer(snum);
1075
1076 if( (option[4] == 0) && (missionfailed() == 0) ) {
1077 newgame(boardfilename);
1078 keystatus[2]=1;
1079 dofadein=32;
1080 }
1081 else {
1082 // some sort of die anim here for multiplayer ?
1083 }
1084 }
1085 #if 0 // Les 10/01/95
1086 else {
1087 sprite[playersprite[snum]].xrepeat = max(((128+health[snum])>>1),0);
1088 sprite[playersprite[snum]].yrepeat = max(((128+health[snum])>>1),0);
1089
1090 hvel[snum] += (TICSPERFRAME<<2);
1091 horiz[snum] = max(horiz[snum]-4,0);
1092 posz[snum] += hvel[snum];
1093 if( posz[snum] > globloz-(4<<8) ) {
1094 posz[snum] = globloz-(4<<8);
1095 horiz[snum] = min(horiz[snum]+5,200);
1096 hvel[snum] = 0;
1097 }
1098 }
1099 #endif // Les 10/01/95
1100 }
1101 if( (syncbits[snum]&64) != 0 ) {
1102 autocenter[snum]=1;
1103 }
1104 if( autocenter[snum] ) {
1105 if( horiz[snum] > 100 ) {
1106 horiz[snum]-=4;
1107 if( horiz[snum] < 100 ) {
1108 horiz[snum]=100;
1109 }
1110 }
1111 else if( horiz[snum] < 100 ) {
1112 horiz[snum]+=4;
1113 if( horiz[snum] > 100 ) {
1114 horiz[snum]=100;
1115 }
1116 }
1117 if( horiz[snum] == 100 ) {
1118 autocenter[snum]=0;
1119 }
1120 }
1121
1122 if (((syncbits[snum]&8) > 0) && (horiz[snum] > 100-(200>>1))) horiz[snum] -= 4; //-
1123 if (((syncbits[snum]&4) > 0) && (horiz[snum] < 100+(200>>1))) horiz[snum] += 4; //+
1124
1125 // 32 pixels above floor is where player should be
1126 goalz = globloz-(KENSPLAYERHEIGHT<<8);
1127
1128 // kens slime sector
1129 if( sector[cursectnum[snum]].lotag == 4 ) {
1130 // if not on a sprite
1131 if( (globlohit&0xc000) != 49152 ) {
1132 goalz = globloz-(8<<8);
1133 if( posz[snum] >= goalz-(2<<8) )
1134 {
1135 pos.x = posx[snum]; pos.y = posy[snum]; pos.z = posz[snum];
1136 clipmove(&pos,&cursectnum[snum],-TICSPERFRAME<<14,-TICSPERFRAME<<14,128L,4<<8,4<<8,CLIPMASK0);
1137 posx[snum] = pos.x; posy[snum] = pos.y; posz[snum] = pos.z;
1138
1139 frameinterpolate = 0;
1140 if( slimesoundcnt[snum] >= 0 ) {
1141 slimesoundcnt[snum] -= TICSPERFRAME;
1142 while( slimesoundcnt[snum] < 0 ) {
1143 slimesoundcnt[snum] += 120;
1144 }
1145 }
1146 }
1147 }
1148 }
1149
1150 // case where ceiling & floor are too close
1151 if( goalz < globhiz+(16<<8) ) {
1152 goalz = ((globloz+globhiz)>>1);
1153 }
1154
1155 // climb ladder or regular z movement
1156 if( (mission == 7) || sector[cursectnum[snum]].lotag == SECT_LOTAG_CLIMB ) {
1157 if( (syncbits[snum]&1) > 0 ) {
1158 if( posz[snum] > (sector[cursectnum[snum]].ceilingz+2048) ) {
1159 posz[snum]-=64;
1160 if( (syncbits[snum]&256) > 0 ) {
1161 posz[snum]-=128;
1162 }
1163 if( mission == 7 ) {
1164 posz[snum]-=256;
1165 }
1166 }
1167 }
1168 else if( (syncbits[snum]&2) > 0 ) {
1169 if( posz[snum] < (sector[cursectnum[snum]].floorz-2048) ) {
1170 posz[snum]+=64;
1171 if( (syncbits[snum]&256) > 0 ) {
1172 posz[snum]+=128;
1173 }
1174 if( mission == 7 ) {
1175 posz[snum]+=256;
1176 }
1177 }
1178 }
1179 }
1180 else {
1181 if( health[snum] >= 0 ) {
1182 // jump key
1183 if( (syncbits[snum]&1) > 0 ) {
1184 if( posz[snum] >= globloz-(KENSPLAYERHEIGHT<<8) ) {
1185 goalz -= (16<<8);
1186 // if( (syncbits[snum]&256) > 0 ) {
1187 goalz -= (24<<8);
1188 // }
1189 }
1190 }
1191 // crouch key
1192 if( (syncbits[snum]&2) > 0 ) {
1193 goalz += (12<<8);
1194 // if( (syncbits[snum]&256) > 0 ) {
1195 goalz += (12<<8);
1196 // }
1197 }
1198 }
1199 // player is on a groudraw area
1200 /*jonof: groudraw became slopes
1201 if( (sector[cursectnum[snum]].floorstat&2) > 0 ) {
1202 if( waloff[sector[cursectnum[snum]].floorheinum] == 0 ) {
1203 loadtile(sector[cursectnum[snum]].floorheinum);
1204 }
1205 ptr = (char *)(waloff[sector[cursectnum[snum]].floorheinum]+(((posx[snum]>>4)&63)<<6)+((posy[snum]>>4)&63));
1206 goalz -= ((*ptr)<<8);
1207 }
1208 */
1209 // gravity, plus check for if on an elevator
1210 if( posz[snum] < goalz ) {
1211 hvel[snum] += (TICSPERFRAME<<5)+1;
1212 }
1213 else {
1214 if( (globlohit&0xC000) == 0xC000 ) { // on a sprite
1215 if ((globlohit-49152) < 0 || (globlohit-49152) >= MAXSPRITES) {
1216 crash("game961: Invalid sprite index (%d)",globlohit-49152);
1217 }
1218 if( sprite[globlohit-49152].lotag >= 1500 ) {
1219 onelev[snum]=1;
1220 }
1221 }
1222 else if( sector[cursectnum[snum]].lotag == 1004 ||
1223 sector[cursectnum[snum]].lotag == 1005 ) {
1224 onelev[snum]=1;
1225 }
1226 else {
1227 onelev[snum]=0;
1228 }
1229 if (onelev[snum] != 0 && (syncbits[snum]&2) == 0) {
1230 hvel[snum]=0;
1231 posz[snum]=globloz-(KENSPLAYERHEIGHT<<8);
1232 }
1233 else {
1234 hvel[snum] = (((goalz-posz[snum])*TICSPERFRAME)>>5);
1235 }
1236 }
1237 tekchangefallz(snum,globloz,globhiz);
1238 }
1239
1240 // overhead maps zoom in/out
1241 if( dimensionmode[snum] != 3 ) {
1242 if (((syncbits[snum]&32) > 0) && (zoom[snum] > 48)) zoom[snum] -= (zoom[snum]>>4);
1243 if (((syncbits[snum]&16) > 0) && (zoom[snum] < 4096)) zoom[snum] += (zoom[snum]>>4);
1244 }
1245
1246 // update sprite representation of player
1247 // should be after movement, but before shooting code
1248 pos.x = posx[snum]; pos.y = posy[snum]; pos.z = posz[snum] + (KENSPLAYERHEIGHT << 8);
1249 setsprite(playersprite[snum],&pos);
1250 sprite[playersprite[snum]].ang = ang[snum];
1251
1252 // in wrong sector or is ceiling/floor smooshing player
1253 if( (cursectnum[snum] < 0) || (cursectnum[snum] >= numsectors) ) {
1254 changehealth(snum,-200);
1255 changescore(snum,-5);
1256 }
1257 else if( globhiz+(8<<8) > globloz ) {
1258 changehealth(snum,-200);
1259 changescore(snum,-5);
1260 }
1261
1262 // kens waterfountain
1263 if( (waterfountainwall[snum] >= 0) && (health[snum] >= 0) ) {
1264 if (neartagwall < 0 || neartagwall >= numwalls) {
1265 crash("game1009: Invalid wall (%d)",neartagwall);
1266 }
1267 if( (wall[neartagwall].lotag != 7) || ((syncbits[snum]&1024) == 0) ) {
1268 i = waterfountainwall[snum];
1269 if (i < 0 || i >= numwalls) {
1270 crash("game1014: Invalid wall index (%d)",i);
1271 }
1272 if( wall[i].overpicnum == USEWATERFOUNTAIN ) {
1273 wall[i].overpicnum = WATERFOUNTAIN;
1274 }
1275 else if( wall[i].picnum == USEWATERFOUNTAIN ) {
1276 wall[i].picnum = WATERFOUNTAIN;
1277 }
1278 waterfountainwall[snum] = -1;
1279 }
1280 }
1281
1282 // enter throw
1283 if( (option[4] == 0 ) && (pickup.picnum != 0) && (keystatus[28] != 0) ) {
1284 toss(snum);
1285 keystatus[28]=0;
1286 }
1287
1288 // space bar (use) code
1289 if( ((syncbits[snum]&1024) > 0) && (sector[cursectnum[snum]].lotag == 4444) ) {
1290 depositsymbol(snum);
1291 }
1292 else if( (syncbits[snum]&1024) > 0 ) {
1293 // continuous triggers
1294 neartag(posx[snum],posy[snum],(posz[snum]+(8<<8)),cursectnum[snum],ang[snum],&neartagsector,&neartagwall,&neartagsprite,&neartaghitdist,1024L,3,nullptr);
1295 if( neartagsector == -1 ) {
1296 i = cursectnum[snum];
1297 if( (sector[i].lotag|sector[i].hitag) != 0 ) {
1298 neartagsector = i;
1299 }
1300 }
1301 // kens water fountain
1302 if( neartagwall >= 0 ) {
1303 if (neartagwall >= numwalls) {
1304 crash("game1053: Invalid wall index (%d)",neartagwall);
1305 }
1306 if ( wall[neartagwall].lotag == 7 ) {
1307 if( wall[neartagwall].overpicnum == WATERFOUNTAIN ) {
1308 wall[neartagwall].overpicnum = USEWATERFOUNTAIN;
1309 waterfountainwall[snum] = neartagwall;
1310 }
1311 else if( wall[neartagwall].picnum == WATERFOUNTAIN ) {
1312 wall[neartagwall].picnum = USEWATERFOUNTAIN;
1313 waterfountainwall[snum] = neartagwall;
1314 }
1315 if( waterfountainwall[snum] >= 0 ) {
1316 waterfountaincnt[snum] -= TICSPERFRAME;
1317 while( waterfountaincnt[snum] < 0 ) {
1318 waterfountaincnt[snum] += 120;
1319 changehealth(snum,2);
1320 }
1321 }
1322 }
1323 }
1324 // 1-time triggers
1325 if( (oflags[snum]&1024) == 0 ) {
1326 if( neartagsector >= 0 ) {
1327 if (neartagsector >= numsectors) {
1328 crash("game1070: Invalid sector index (%d)",neartagsector);
1329 }
1330 if( sector[neartagsector].hitag == 0 ) {
1331 operatesector(neartagsector);
1332 }
1333 }
1334 if( neartagwall >= 0 ) {
1335 if (neartagwall >= numwalls) {
1336 crash("game1078: Invalid wall index (%d)",neartagwall);
1337 }
1338 if( wall[neartagwall].lotag == 2 ) {
1339 for( i=0; i<numsectors; i++ ) {
1340 if( sector[i].hitag == wall[neartagwall].hitag ) {
1341 if( sector[i].lotag != 1 ) {
1342 operatesector(i);
1343 }
1344 }
1345 }
1346 i = headspritestat[0];
1347 while( i != -1 ) {
1348 nexti = nextspritestat[i];
1349 if( sprite[i].hitag == wall[neartagwall].hitag ) {
1350 operatesprite(i);
1351 }
1352 i = nexti;
1353 }
1354 j = wall[neartagwall].overpicnum;
1355 if( j == SWITCH1ON ) {
1356 wall[neartagwall].overpicnum = GIFTBOX;
1357 wall[neartagwall].lotag = 0;
1358 wall[neartagwall].hitag = 0;
1359 }
1360 if( j == GIFTBOX ) {
1361 wall[neartagwall].overpicnum = SWITCH1ON;
1362 wall[neartagwall].lotag = 0;
1363 wall[neartagwall].hitag = 0;
1364 }
1365 if (j == SWITCH2ON) wall[neartagwall].overpicnum = SWITCH2OFF;
1366 if (j == SWITCH2OFF) wall[neartagwall].overpicnum = SWITCH2ON;
1367 if (j == SWITCH3ON) wall[neartagwall].overpicnum = SWITCH3OFF;
1368 if (j == SWITCH3OFF) wall[neartagwall].overpicnum = SWITCH3ON;
1369 i = wall[neartagwall].point2;
1370 dax = ((wall[neartagwall].x+wall[i].x)>>1);
1371 day = ((wall[neartagwall].y+wall[i].y)>>1);
1372 }
1373 }
1374 if( neartagsprite >= 0 ) {
1375 if (neartagsprite >= MAXSPRITES) {
1376 crash("game1118: Invalid sprite index (%d)",neartagsprite);
1377 }
1378 if( sprite[neartagsprite].lotag == 4 ) {
1379 tekswitchtrigger(snum);
1380 }
1381 else {
1382 operatesprite(neartagsprite);
1383 }
1384 }
1385 }
1386 }
1387
1388 // fire weapon
1389 if( (syncbits[snum]&2048) > 0 ) {
1390 tekfiregun((syncbits[snum]>>13)&15,snum);
1391 }
1392
1393 // map mode
1394 if( (syncbits[snum]&4096) > (oflags[snum]&4096) ) {
1395 if (dimensionmode[snum] == 3) {
1396 dimensionmode[snum]=1;
1397 }
1398 else {
1399 dimensionmode[snum]=3;
1400 }
1401 #if 0 // eliminate map mode 2
1402 dimensionmode[snum]++;
1403 if( dimensionmode[snum] > 3 ) {
1404 dimensionmode[snum] = 1;
1405 }
1406 #endif
1407 if( snum == screenpeek ) {
1408 if (dimensionmode[snum] == 2) videoSetViewableArea(0L,0L,xdim-1,(ydim-1)>>detailmode);
1409 if (dimensionmode[snum] == 3) setup3dscreen();
1410 }
1411 }
1412
1413 oflags[snum] = syncbits[snum];
1414 }
1415
1416 void
drawscreen(short snum,int dasmoothratio)1417 drawscreen(short snum, int dasmoothratio)
1418 {
1419 int i, j, charsperline, tempint;
1420 int x1, y1, x2, y2, ox1, oy1, ox2, oy2;
1421 int cposx, cposy, cposz, choriz, czoom;
1422 short cang;
1423
1424 smoothratio = max(min(dasmoothratio,65536),0);
1425
1426 cposx = oposx[snum]+mulscale(posx[snum]-oposx[snum],smoothratio,16);
1427 cposy = oposy[snum]+mulscale(posy[snum]-oposy[snum],smoothratio,16);
1428 cposz = oposz[snum]+mulscale(posz[snum]-oposz[snum],smoothratio,16);
1429 if( frameinterpolate == 0 ) {
1430 cposx = posx[snum]; cposy = posy[snum]; cposz = posz[snum];
1431 }
1432 cposz+=headbob;
1433 choriz = ohoriz[snum]+mulscale(horiz[snum]-ohoriz[snum],smoothratio,16);
1434 czoom = ozoom[snum]+mulscale(zoom[snum]-ozoom[snum],smoothratio,16);
1435 cang = oang[snum]+mulscale(((ang[snum]+1024-oang[snum])&2047)-1024,smoothratio,16);
1436
1437 if( dimensionmode[snum] != 2 ) {
1438 if( (numplayers > 1) && (option[4] == 0) ) {
1439 for( i=connecthead; i>=0; i=connectpoint2[i] ) {
1440 frame2draw[i] = 1;
1441 }
1442 redrawbackfx();
1443 for( i=connecthead,j=0; i>=0; i=connectpoint2[i],j++ ) {
1444 if( frame2draw[i] != 0 ) {
1445 if( numplayers <= 4 ) {
1446 switch( j ) {
1447 case 0: videoSetViewableArea(0,0,(xdim>>1)-1,(ydim>>1)-1); break;
1448 case 1: videoSetViewableArea((xdim>>1),0,xdim-1,(ydim>>1)-1); break;
1449 case 2: videoSetViewableArea(0,(ydim>>1),(xdim>>1)-1,ydim-1); break;
1450 case 3: videoSetViewableArea((xdim>>1),(ydim>>1),xdim-1,ydim-1); break;
1451 }
1452 }
1453 else {
1454 switch( j ) {
1455 case 0: videoSetViewableArea(0,0,(xdim>>2)-1,(ydim>>2)-1); break;
1456 case 1: videoSetViewableArea(xdim>>2,0,(xdim>>1)-1,(ydim>>2)-1); break;
1457 case 2: videoSetViewableArea(xdim>>1,0,xdim-(xdim>>2)-1,(ydim>>2)-1); break;
1458 case 3: videoSetViewableArea(xdim-(xdim>>2),0,xdim-1,(ydim>>2)-1); break;
1459 case 4: videoSetViewableArea(0,ydim>>2,(xdim>>2)-1,(ydim>>1)-1); break;
1460 case 5: videoSetViewableArea(xdim>>2,ydim>>2,(xdim>>1)-1,(ydim>>1)-1); break;
1461 case 6: videoSetViewableArea(xdim>>1,ydim>>2,xdim-(xdim>>2)-1,(ydim>>1)-1); break;
1462 case 7: videoSetViewableArea(xdim-(xdim>>2),ydim>>2,xdim-1,(ydim>>1)-1); break;
1463 case 8: videoSetViewableArea(0,ydim>>1,(xdim>>2)-1,ydim-(ydim>>2)-1); break;
1464 case 9: videoSetViewableArea(xdim>>2,ydim>>1,(xdim>>1)-1,ydim-(ydim>>2)-1); break;
1465 case 10: videoSetViewableArea(xdim>>1,ydim>>1,xdim-(xdim>>2)-1,ydim-(ydim>>2)-1); break;
1466 case 11: videoSetViewableArea(xdim-(xdim>>2),ydim>>1,xdim-1,ydim-(ydim>>2)-1); break;
1467 case 12: videoSetViewableArea(0,ydim-(ydim>>2),(xdim>>2)-1,ydim-1); break;
1468 case 13: videoSetViewableArea(xdim>>2,ydim-(ydim>>2),(xdim>>1)-1,ydim-1); break;
1469 case 14: videoSetViewableArea(xdim>>1,ydim-(ydim>>2),xdim-(xdim>>2)-1,ydim-1); break;
1470 case 15: videoSetViewableArea(xdim-(xdim>>2),ydim-(ydim>>2),xdim-1,ydim-1); break;
1471 }
1472 }
1473 if( i == snum ) {
1474 drawrooms(cposx,cposy,cposz,cang,choriz,cursectnum[i]);
1475 }
1476 else {
1477 drawrooms(posx[i],posy[i],posz[i],ang[i],horiz[i],cursectnum[i]);
1478 }
1479 analyzesprites(posx[i],posy[i]);
1480 renderDrawMasks();
1481 tekdrawgun((syncbits[i]>>13)&15,i);
1482 }
1483 }
1484 }
1485 else {
1486 redrawbackfx();
1487 drawrooms(cposx,cposy,cposz,cang,choriz,cursectnum[snum]);
1488 analyzesprites(posx[snum],posy[snum]);
1489 renderDrawMasks();
1490 tekdrawgun((syncbits[screenpeek]>>13)&15,screenpeek);
1491 }
1492 }
1493
1494 // move back pivot point for map
1495 if( dimensionmode[snum] != 3 ) {
1496 cposx += (sintable[(cang+512)&2047]<<6) / czoom;
1497 cposy += (sintable[cang&2047]<<6) / czoom;
1498 if( dimensionmode[snum] == 2 ) {
1499 videoClearViewableArea(0L); //Clear screen to specified color
1500 // TODO drawmapview(cposx,cposy,czoom,cang);
1501 }
1502 drawoverheadmap(cposx,cposy,czoom,cang);
1503 }
1504
1505 if( typemode != 0 ) {
1506 charsperline = 40;
1507 for( i=0; i<=typemessageleng; i+=charsperline ) {
1508 for( j=0; j<charsperline; j++ ) {
1509 tempbuf[j] = typemessage[i+j];
1510 }
1511 if( typemessageleng < i+charsperline ) {
1512 tempbuf[(typemessageleng-i)] = '_';
1513 tempbuf[(typemessageleng-i)+1] = 0;
1514 }
1515 else {
1516 tempbuf[charsperline] = 0;
1517 }
1518 }
1519 }
1520 else {
1521 if( dimensionmode[myconnectindex] == 3 ) {
1522 tempint = screensize;
1523 if( ((locbits&32) > (screensizeflag&32)) && (screensize > 64) ) {
1524 ox1 = (xdim>>1)-(screensize>>1);
1525 ox2 = ox1+screensize-1;
1526 oy1 = ((ydim-32)>>1)-(((screensize*(ydim-32))/xdim)>>1);
1527 oy2 = oy1+((screensize*(ydim-32))/xdim)-1;
1528 tekview(&ox1,&oy1, &ox2,&oy2);
1529 screensize -= (screensize>>3);
1530 if( tempint > xdim ) {
1531 screensize = xdim;
1532 permanentwritesprite((xdim-320)>>1,ydim-32,STATUSBAR,0,0,0,xdim-1,ydim-1,0);
1533 i = ((xdim-320)>>1);
1534 while( i >= 8 ) {
1535 i -= 8, permanentwritesprite(i,ydim-32,STATUSBARFILL8,0,0,0,xdim-1,ydim-1,0);
1536 }
1537 if( i >= 4 ) {
1538 i -= 4, permanentwritesprite(i,ydim-32,STATUSBARFILL4,0,0,0,xdim-1,ydim-1,0);
1539 }
1540 i = ((xdim-320)>>1)+320;
1541 while( i <= xdim-8 ) {
1542 permanentwritesprite(i,ydim-32,STATUSBARFILL8,0,0,0,xdim-1,ydim-1,0), i += 8;
1543 }
1544 if( i <= xdim-4 ) {
1545 permanentwritesprite(i,ydim-32,STATUSBARFILL4,0,0,0,xdim-1,ydim-1,0), i += 4;
1546 }
1547 }
1548 x1 = (xdim>>1)-(screensize>>1);
1549 x2 = x1+screensize-1;
1550 y1 = ((ydim-32)>>1)-(((screensize*(ydim-32))/xdim)>>1);
1551 y2 = y1+((screensize*(ydim-32))/xdim)-1;
1552 tekview(&x1,&y1,&x2,&y2);
1553 videoSetViewableArea(x1,y1>>detailmode,x2,y2>>detailmode);
1554 permanentwritespritetile(0L,0L,BACKGROUND,0,ox1,oy1,x1-1,oy2,0);
1555 permanentwritespritetile(0L,0L,BACKGROUND,0,x2+1,oy1,ox2,oy2,0);
1556 permanentwritespritetile(0L,0L,BACKGROUND,0,x1,oy1,x2,y1-1,0);
1557 permanentwritespritetile(0L,0L,BACKGROUND,0,x1,y2+1,x2,oy2,0);
1558 }
1559 if( ((locbits&16) > (screensizeflag&16)) && (screensize <= xdim) ) {
1560 screensize += (screensize>>3);
1561 if( (screensize > xdim) && (tempint == xdim) ) {
1562 screensize = xdim+1;
1563 x1 = 0; y1 = 0;
1564 x2 = xdim-1; y2 = ydim-1;
1565 }
1566 else {
1567 if (screensize > xdim) screensize = xdim;
1568 x1 = (xdim>>1)-(screensize>>1);
1569 x2 = x1+screensize-1;
1570 y1 = ((ydim-32)>>1)-(((screensize*(ydim-32))/xdim)>>1);
1571 y2 = y1+((screensize*(ydim-32))/xdim)-1;
1572 }
1573 tekview(&x1,&y1,&x2,&y2);
1574 videoSetViewableArea(x1,y1>>detailmode,x2,y2>>detailmode);
1575 }
1576 screensizeflag = locbits;
1577 }
1578 }
1579
1580 if( getmessageleng > 0 ) {
1581 charsperline = 40;
1582 for( i=0; i<=getmessageleng; i+=charsperline ) {
1583 for( j=0; j<charsperline; j++ ) {
1584 tempbuf[j] = getmessage[i+j];
1585 }
1586 if( getmessageleng < i+charsperline ) {
1587 tempbuf[(getmessageleng-i)] = 0;
1588 }
1589 else {
1590 tempbuf[charsperline] = 0;
1591 }
1592 printext256(0L,((i/charsperline)<<3)+(200-32-8)-(((getmessageleng-1)/charsperline)<<3),151,-1,tempbuf,0);
1593 }
1594 if( ((int)totalclock) > getmessagetimeoff ) {
1595 getmessageleng = 0;
1596 }
1597 }
1598
1599 // you are looking thru an opponent plaeyer's eyes
1600 if( (numplayers >= 2) && (screenpeek != myconnectindex) ) {
1601 strcpy(tempbuf,"Other");
1602 }
1603
1604 #ifdef OUTOFSYNCMESSAGE
1605 if( syncstat != 0 ) {
1606 printext256(68L,84L,31,0,"OUT OF SYNC!",0);
1607 }
1608 if( syncstate != 0 ) {
1609 printext256(68L,92L,31,0,"Missed Network packet!",0);
1610 }
1611 #endif
1612
1613 tekscreenfx();
1614
1615 #ifdef NETWORKDIAGNOSTICS
1616 if( (option[4] > 0) ) {
1617 for( i=connecthead ; i >= 0 ; i=connectpoint2[i] ) {
1618 sprintf(tektempbuf,"%2d %5d %5d %5d %5d %3d %4d", i,posx[i],posy[i],posz[i],ang[i],horiz[i],health[i]);
1619 printext(2,i*8+2,tektempbuf,ALPHABET,255);
1620 }
1621 if( myconnectindex == connecthead ) {
1622 sprintf(tektempbuf,"%2d %s",myconnectindex,"M");
1623 }
1624 else {
1625 sprintf(tektempbuf,"%2d %s",myconnectindex,"S");
1626 }
1627 printext(windowx2-48,windowy2-64,tektempbuf,ALPHABET2,255);
1628 }
1629 #endif
1630
1631 videoNextPage();
1632 if( dofadein != 0 ) {
1633 fadein(0,255,dofadein);
1634 }
1635
1636 #ifdef OOGIE
1637 // F5 key
1638 if( keystatus[0x3f] > 0 ) {
1639 keystatus[0x3f] = 0;
1640 detailmode ^= 1;
1641 if( detailmode == 0 ) {
1642 setview(windowx1,windowy1<<1,windowx2,(windowy2<<1)+1);
1643 outp(0x3d4,0x9); outp(0x3d5,(inp(0x3d5)&~31)|1);
1644 }
1645 else {
1646 setview(windowx1,windowy1>>detailmode,windowx2,windowy2>>detailmode);
1647 setaspect(yxaspect>>1);
1648 outp(0x3d4,0x9); outp(0x3d5,(inp(0x3d5)&~31)|3);
1649 }
1650 }
1651 #endif
1652
1653 // F12 key
1654 if( keystatus[0x58] > 0 ) {
1655 keystatus[0x58] = 0;
1656 // TODO screencapture("captxxxx.pcx",keystatus[0x2a]|keystatus[0x36]);
1657 }
1658
1659 #ifdef STEREOMODE_ADJUSTMENT_ACTIVE
1660 if( stereofps != 0 ) {
1661 if( (keystatus[0x2a]|keystatus[0x36]) > 0 ) {
1662 if (keystatus[0x1a] > 0) stereopixelwidth--; //Shift [
1663 if (keystatus[0x1b] > 0) stereopixelwidth++; //Shift ]
1664 }
1665 else {
1666 if (keystatus[0x1a] > 0) stereowidth -= 512; //[
1667 if (keystatus[0x1b] > 0) stereowidth += 512; //]
1668 }
1669 }
1670 #endif
1671
1672 #ifdef FAKEMULTIPLAYER_ACTIVE
1673 if( option[4] == 0 ) {
1674 if( keystatus[0xd2] > 0 ) {
1675 keystatus[0xd2] = 0;
1676 if( numplayers < MAXPLAYERS ) {
1677 connectpoint2[numplayers-1] = numplayers;
1678 connectpoint2[numplayers] = -1;
1679 initplayersprite(numplayers);
1680 clearallviews(0L);
1681 numplayers++;
1682 }
1683 }
1684 if( keystatus[0xd3] > 0 ) {
1685 keystatus[0xd3] = 0;
1686 if( numplayers > 1 ) {
1687 numplayers--;
1688 connectpoint2[numplayers-1] = -1;
1689 deletesprite(playersprite[numplayers]);
1690 playersprite[numplayers] = -1;
1691 if( myconnectindex >= numplayers ) {
1692 myconnectindex = 0;
1693 }
1694 if( screenpeek >= numplayers ) {
1695 screenpeek = 0;
1696 }
1697 if( numplayers < 2 ) {
1698 setup3dscreen();
1699 }
1700 else {
1701 clearallviews(0L);
1702 }
1703 }
1704 }
1705 // scroll lock
1706 if( keystatus[0x46] > 0 ) {
1707 keystatus[0x46] = 0;
1708 myconnectindex = connectpoint2[myconnectindex];
1709 if( myconnectindex < 0 ) {
1710 myconnectindex = connecthead;
1711 }
1712 screenpeek = myconnectindex;
1713 }
1714 }
1715 #endif
1716 }
1717
1718 void
movethings()1719 movethings()
1720 {
1721 int i;
1722
1723 gotlastpacketclock = (int)totalclock;
1724 for( i=connecthead; i>=0; i=connectpoint2[i] ) {
1725 baksyncvel[movefifoend][i] = fsyncvel[i];
1726 baksyncsvel[movefifoend][i] = fsyncsvel[i];
1727 baksyncangvel[movefifoend][i] = fsyncangvel[i];
1728 baksyncbits[movefifoend][i] = fsyncbits[i];
1729 }
1730 movefifoend = ((movefifoend+1)&(MOVEFIFOSIZ-1));
1731
1732 // do this for Master/Slave switching
1733 for( i=connectpoint2[connecthead]; i>=0; i=connectpoint2[i] ) {
1734 if( syncbits[i]&512 ) {
1735 ready2send = 0;
1736 }
1737 }
1738
1739 tektime();
1740 }
1741
1742 void
domovethings()1743 domovethings()
1744 {
1745 short i, j, startwall, endwall;
1746 walltype *wal;
1747
1748 for( i=connecthead; i>=0; i=connectpoint2[i] ) {
1749 if (dbgflag) {
1750 debugout(i);
1751 }
1752 syncvel[i] = baksyncvel[movefifoplc][i];
1753 syncsvel[i] = baksyncsvel[movefifoplc][i];
1754 syncangvel[i] = baksyncangvel[movefifoplc][i];
1755 syncbits[i] = baksyncbits[movefifoplc][i];
1756 }
1757 movefifoplc = ((movefifoplc+1)&(MOVEFIFOSIZ-1));
1758 #if 0
1759 syncval[syncvalend] = getsyncstat();
1760 syncvalend = ((syncvalend+1)&(MOVEFIFOSIZ-1));
1761 #endif
1762 for( i=connecthead; i>=0; i=connectpoint2[i] ) {
1763 oposx[i] = posx[i];
1764 oposy[i] = posy[i];
1765 oposz[i] = posz[i];
1766 ohoriz[i] = horiz[i];
1767 ozoom[i] = zoom[i];
1768 oang[i] = ang[i];
1769 }
1770
1771 for( i=1; i<=8; i++ ) {
1772 if( i != 2 ) {
1773 for( j=headspritestat[i]; j>=0; j=nextspritestat[j] ) {
1774 copybuf(&sprite[j].x,&osprite[j].x,3);
1775 }
1776 }
1777 }
1778
1779 for( i=connecthead; i>=0; i=connectpoint2[i] ) {
1780 ocursectnum[i] = cursectnum[i];
1781 }
1782
1783 if( (numplayers <= 2) && (recstat == 1) ) {
1784 j = 0;
1785 for( i=connecthead; i>=0; i=connectpoint2[i] ) {
1786 recsyncvel[reccnt][j] = syncvel[i];
1787 recsyncsvel[reccnt][j] = syncsvel[i];
1788 recsyncangvel[reccnt][j] = syncangvel[i];
1789 recsyncbits[reccnt][j] = syncbits[i];
1790 j++;
1791 }
1792 reccnt++;
1793 if( reccnt > 16383 ) {
1794 reccnt = 16383;
1795 }
1796 }
1797
1798 lockclock += TICSPERFRAME;
1799
1800 for( i=connecthead; i>=0; i=connectpoint2[i] ) {
1801 processinput(i);
1802 checktouchsprite(i,cursectnum[i]);
1803 startwall = sector[cursectnum[i]].wallptr;
1804 endwall = startwall + sector[cursectnum[i]].wallnum;
1805 for( j=startwall,wal=&wall[j]; j<endwall; j++,wal++ ) {
1806 if( wal->nextsector >= 0 ) {
1807 checktouchsprite(i,wal->nextsector);
1808 }
1809 }
1810 }
1811
1812 doanimations();
1813
1814 tagcode();
1815 statuslistcode();
1816
1817 checkmasterslaveswitch();
1818 }
1819
1820 void
adjustbiasthreshhold(short mousy)1821 adjustbiasthreshhold(short mousy)
1822 {
1823 biasthreshhold-=mousy;
1824 if( biasthreshhold < 8 )
1825 biasthreshhold=8;
1826 if( biasthreshhold > 512 )
1827 biasthreshhold=512;
1828 }
1829
1830 //** Les START - 09/27/95
1831 short moreoptionbits[]={
1832 -1, // 0 move forward
1833 -1, // 1 move backward
1834 -1, // 2 turn right
1835 -1, // 3 turn left
1836 8, // 4 run
1837 -1, // 5 strafe
1838 11, // 6 shoot
1839 10, // 7 use
1840 0, // 8 jump
1841 1, // 9 crouch
1842 2, // 10 look up
1843 3, // 11 look down
1844 -1, // 12 slide left
1845 -1, // 13 slide right
1846 12, // 14 map
1847 -1, // 15 switch player
1848 4, // 16 zoom in
1849 5, // 17 zoom out
1850 -1, // 18 message
1851 6, // 19 autocenter
1852 -1, // 20 rearview
1853 -1, // 21 current item
1854 -1, // 22 health
1855 -1, // 23 crosshairs
1856 -1, // 24 elapsed time
1857 -1, // 25 score
1858 -1, // 26 inventory
1859 7, // 27 conceal weapon
1860 -1 // 28 mouse look mode
1861 };
1862 //** Les END - 09/27/95
1863
getinput()1864 void getinput()
1865 {
1866 int ch, keystate;
1867 int i, j;
1868 int mousx, mousy, bstatus;
1869 short moving,strafing,turning;
1870
1871 if( activemenu != 0 ) {
1872 domenuinput();
1873 }
1874
1875 // normal game keys active
1876 if( typemode == 0 ) {
1877 // shift+shift+R
1878 if( (keystatus[0x2a]&keystatus[0x36]&keystatus[0x13]) > 0 ) {
1879 keystatus[0x13] = 0;
1880 playback();
1881 }
1882 #ifdef SWITCHINGACTIVE
1883 if( keystatus[keys[15]] > 0 ) {
1884 keystatus[keys[15]] = 0;
1885 screenpeek = connectpoint2[screenpeek];
1886 if( screenpeek < 0 ) {
1887 screenpeek = connecthead;
1888 }
1889 }
1890 #endif
1891 for( i=7; i>=0; i-- ) {
1892 if( (keystatus[i+2] > 0) && tekhasweapon(i,screenpeek) ) {
1893 keystatus[i+2] = 0;
1894 locselectedgun = i;
1895 break;
1896 }
1897 }
1898 }
1899
1900 //** Les - moved from below to apply button movements to vel, svel and angvel
1901 //** if needed
1902
1903 mousx=mousy=bstatus=0;
1904 #if 0 // TODO
1905 if( moreoptions[0] != 0 ) {
1906 getmousevalues(&mousx,&mousy,&bstatus);
1907 if( biasthreshholdon && (bstatus&6) ) {
1908 adjustbiasthreshhold(mousy);
1909 bstatus=0;
1910 }
1911 // if horizon key down
1912 if( keystatus[58] == 0 ) {
1913 if( mousy > (biasthreshhold) ) {
1914 mousebias=-1;
1915 }
1916 else if( mousy < -(biasthreshhold) ) {
1917 mousebias=+1;
1918 }
1919 }
1920 }
1921 #endif
1922
1923 //** Les START - 09/26/95
1924 locbits=(locselectedgun<<13); // Les 09/28/95 moved from below
1925
1926 #if 0 // TODO
1927 if (jstickenabled) {
1928 // showmessage("X: %05d Y: %05d B:%04X",joyx,joyy,joyb);
1929 if (joyaxis[0] < jlowx) {
1930 angvel=max(min(angvel-joyaxis[0],127),-128);
1931 }
1932 else if (joyaxis[0] > jhighx) {
1933 angvel=min(max(angvel+joyaxis[0],-128),127);
1934 }
1935 if (joyaxis[1] < jlowy) {
1936 vel=min(max(vel+joyaxis[1],-128),127);
1937 }
1938 else if (joyaxis[1] > jhighy) {
1939 vel=max(min(vel-joyaxis[1],127),-128);
1940 }
1941 for (i=0 ; i < 4 ; i++) {
1942 if ((joyb&(0x10<<i)) == 0) {
1943 if (moreoptions[i+4] == 0) {
1944 moving=1;
1945 }
1946 else if (moreoptions[i+4] == 1) {
1947 moving=-1;
1948 }
1949 else if (moreoptions[i+4] == 2) {
1950 turning=1;
1951 }
1952 else if (moreoptions[i+4] == 3) {
1953 turning=-1;
1954 }
1955 else if (moreoptions[i+4] == 5) {
1956 strafing=2;
1957 }
1958 else if (moreoptions[i+4] == 12) {
1959 strafing=-1;
1960 }
1961 else if (moreoptions[i+4] == 13) {
1962 strafing=1;
1963 }
1964 else if (moreoptionbits[moreoptions[i+4]] >= 0) {
1965 locbits|=(1<<moreoptionbits[moreoptions[i+4]]);
1966 }
1967 }
1968 }
1969 oldjoyb=joyb;
1970 }
1971 #endif
1972
1973 //** Les END - 09/26/95
1974
1975 //** Les START - 09/28/95
1976 moving=strafing=turning=0;
1977 if (moreoptions[0] != 0) {
1978 for (i=0 ; i < 3 ; i++) {
1979 if (bstatus&(1<<i)) {
1980 switch (i) {
1981 case 0:
1982 j=1;
1983 break;
1984 case 1:
1985 j=20;
1986 break;
1987 case 2:
1988 j=2;
1989 break;
1990 }
1991 if (moreoptions[j] == 0) {
1992 moving=1;
1993 }
1994 else if (moreoptions[j] == 1) {
1995 moving=-1;
1996 }
1997 else if (moreoptions[j] == 2) {
1998 turning=1;
1999 }
2000 else if (moreoptions[j] == 3) {
2001 turning=-1;
2002 }
2003 else if (moreoptions[j] == 5) {
2004 strafing=2;
2005 }
2006 else if (moreoptions[j] == 12) {
2007 strafing=-1;
2008 }
2009 else if (moreoptions[j] == 13) {
2010 strafing=1;
2011 }
2012 else {
2013 locbits|=(1<<moreoptionbits[moreoptions[j]]);
2014 }
2015 }
2016 }
2017 }
2018 //** Les END - 09/28/95
2019
2020 // keyboard survey - use to be keytimerstuff() called from keyhandler
2021 if( keystatus[keys[5]] == 0 && strafing == 0 ) { // Les 09/28/95
2022 if( keystatus[keys[2]] > 0 || turning == 1) angvel = max(angvel-16*TICSPERFRAME,-128); // Les 09/28/95
2023 if( keystatus[keys[3]] > 0 || turning == -1) angvel = min(angvel+16*TICSPERFRAME,127); // Les 09/28/95
2024 }
2025 else {
2026 if (strafing == 0) { // Les 09/28/95
2027 strafing=2; // Les 09/28/95
2028 } // Les 09/28/95
2029 if( keystatus[keys[2]] > 0 || turning == 1 ) svel = min(svel+8*TICSPERFRAME,127); // Les 09/28/95
2030 if( keystatus[keys[3]] > 0 || turning == -1 ) svel = max(svel-8*TICSPERFRAME,-128); // Les 09/28/95
2031 }
2032 if( keystatus[keys[0]] > 0 || moving == 1 ) vel = min(vel+8*TICSPERFRAME,127); // Les 09/28/95
2033 if( keystatus[keys[1]] > 0 || moving == -1 ) vel = max(vel-8*TICSPERFRAME,-128); // Les 09/28/95
2034 if( keystatus[keys[12]] > 0 || strafing == 1 ) svel = min(svel+8*TICSPERFRAME,127); // Les 09/28/95
2035 if( keystatus[keys[13]] > 0 || strafing == -1 ) svel = max(svel-8*TICSPERFRAME,-128); // Les 09/28/95
2036 if( angvel < 0 ) angvel = min(angvel+12*TICSPERFRAME,0);
2037 if( angvel > 0 ) angvel = max(angvel-12*TICSPERFRAME,0);
2038 if( svel < 0 ) svel = min(svel+2*TICSPERFRAME,0);
2039 if( svel > 0 ) svel = max(svel-2*TICSPERFRAME,0);
2040 if( vel < 0 ) vel = min(vel+2*TICSPERFRAME,0);
2041 if( vel > 0 ) vel = max(vel-2*TICSPERFRAME,0);
2042
2043 if( (option[4] == 0) && (numplayers == 2) ) {
2044 if( keystatus[0x4f] == 0 ) {
2045 if( keystatus[0x4b] > 0 ) angvel2 = max(angvel2-16*TICSPERFRAME,-128);
2046 if( keystatus[0x4d] > 0 ) angvel2 = min(angvel2+16*TICSPERFRAME,127);
2047 }
2048 else {
2049 if( keystatus[0x4b] > 0 ) svel2 = min(svel2+8*TICSPERFRAME,127);
2050 if( keystatus[0x4d] > 0 ) svel2 = max(svel2-8*TICSPERFRAME,-128);
2051 }
2052 if( keystatus[0x48] > 0 ) vel2 = min(vel2+8*TICSPERFRAME,127);
2053 if( keystatus[0x4c] > 0 ) vel2 = max(vel2-8*TICSPERFRAME,-128);
2054 if( angvel2 < 0 ) angvel2 = min(angvel2+12*TICSPERFRAME,0);
2055 if( angvel2 > 0 ) angvel2 = max(angvel2-12*TICSPERFRAME,0);
2056 if( svel2 < 0 ) svel2 = min(svel2+2*TICSPERFRAME,0);
2057 if( svel2 > 0 ) svel2 = max(svel2-2*TICSPERFRAME,0);
2058 if( vel2 < 0 ) vel2 = min(vel2+2*TICSPERFRAME,0);
2059 if( vel2 > 0 ) vel2 = max(vel2-2*TICSPERFRAME,0);
2060 }
2061 if( keystatus[keys[28]] ) {
2062 i=horiz[myconnectindex]+((( int)mousy)>>3);
2063 if( i > 200 ) i=200;
2064 if( i < 0 ) i=0;
2065 horiz[myconnectindex]=i;
2066 keyedhorizon=1;
2067 mousy=0;
2068 }
2069 else {
2070 if( (keyedhorizon) && (horiz[myconnectindex] != 100) )
2071 autocenter[myconnectindex]=1;
2072 keyedhorizon=0;
2073 mousx*=mousesensitivity;
2074 }
2075 // if( (bstatus&6) != 0 ) {
2076 // vel=min(vel+(1<<(8+mousesensitivity)),127);
2077 // vel*=mousebias;
2078 // }
2079 locvel = min(max(vel,-128+8),127-8);
2080 locsvel = min(max(svel,-128+8),127-8);
2081 locangvel = min(max(angvel,-512+16),511-16); // Les 09/27/95
2082
2083 if (strafing == 2) { // Les 09/28/95
2084 locsvel=max(min(svel-mousx,511-16),-512+16); // Les 09/28/95
2085 } // Les 09/28/95
2086 else { // Les 09/28/95
2087 locangvel=min(max(locangvel+mousx,-512),511); // Les 09/27/95
2088 } // Les 09/28/95
2089 //** Les START - 09/28/95
2090 if (mousy < 0) {
2091 mousy-=(1<<mousesensitivity);
2092 }
2093 else if (mousy > 0) {
2094 mousy+=(1<<mousesensitivity);
2095 }
2096 //** Les END - 09/28/95
2097
2098 locvel=min(max(locvel-mousy,-128),127);
2099 // locbits = (locselectedgun<<13); moved up to joystick section
2100
2101
2102 if( typemode == 0 ) {
2103 #ifdef MASTERSWITCHING
2104 locbits |= (keystatus[0x32]<<9); //M (be master)
2105 #endif
2106 locbits |= ((keystatus[keys[14]]==1)<<12); //Map mode
2107 }
2108 locbits |= keystatus[keys[8]]; //Stand high
2109 locbits |= (keystatus[keys[9]] <<1); //Stand low
2110 locbits |= (keystatus[keys[10]]<<2); //Look up
2111 locbits |= (keystatus[keys[11]]<<3); //Look down
2112 locbits |= (keystatus[keys[16]]<<4); //Zoom in
2113 locbits |= (keystatus[keys[17]]<<5); //Zoom out
2114 locbits |= (keystatus[keys[19]]<<6); //AutoCenter TekWar
2115 locbits |= (keystatus[keys[27]]<<7); //Conceal Weapin TekWar
2116 locbits |= (keystatus[keys[4]]<<8); //Run
2117 locbits |= ((keystatus[keys[7]]==1)<<10); //Space
2118 locbits |= ((keystatus[keys[6]]==1)<<11); //Shoot Kbd
2119 // locbits |= (((bstatus&6)>(oldmousebstatus&6))<<10); //Space
2120 // locbits |= (((bstatus&1)>(oldmousebstatus&1))<<11); //Shoot Mse
2121
2122 if( typemode != 0 ) {
2123 #ifdef MASTERSWITCHING
2124 locbits &= ~(keystatus[0x32]<<9);
2125 #endif
2126 locbits &= ~((keystatus[keys[14]]==1)<<12);
2127 }
2128
2129 #if 0 // TODO
2130 if( (joyb == 236) || (joyb == 220) || (joyb == 124) || (joyb == 188) ) {
2131 keystatus[keys[moreoptions[4]]]=0;
2132 keystatus[keys[moreoptions[5]]]=0;
2133 keystatus[keys[moreoptions[6]]]=0;
2134 keystatus[keys[moreoptions[7]]]=0;
2135 }
2136 #endif
2137
2138 oldmousebstatus = bstatus;
2139 if( (locbits&2048) > 0 ) {
2140 oldmousebstatus &= ~1;
2141 }
2142
2143 // trap print scrn key
2144 if( keystatus[0xb7] > 0 ) {
2145 keystatus[0xb7] = 0;
2146 //printscreeninterrupt();
2147 }
2148
2149 // F9 brightness
2150 if( keystatus[67] > 0 ) {
2151 keystatus[67] = 0;
2152 brightness++;
2153 if( brightness > 8 ) brightness = 0;
2154 setbrightness(brightness);
2155 }
2156
2157 #ifdef OOGIE
2158 // F10 adjust bias threshhold
2159 if (keystatus[68] != 0) {
2160 keystatus[68]=0;
2161 if (dimensionmode[screenpeek] != 3) {
2162 setup3dscreen();
2163 }
2164 else {
2165 dimensionmode[screenpeek]=2;
2166 setview(0L,0L,xdim-1,(ydim-1)>>detailmode);
2167 }
2168 }
2169 #endif
2170
2171 if( typemode == 0 ) {
2172 #ifdef PARALLAX_SETTING_ACTIVE
2173 if( keystatus[0x19] > 0 ) {
2174 keystatus[0x19] = 0;
2175 parallaxtype++;
2176 if (parallaxtype > 2) parallaxtype = 0;
2177 }
2178 #endif
2179 #ifdef VISIBILITY_SETTING_ACTIVE
2180 if( (keystatus[0x38]|keystatus[0xb8]) > 0 ) {
2181 if (keystatus[0x4a] > 0) // Keypad -
2182 visibility = min(visibility+(visibility>>3),16384);
2183 if (keystatus[0x4e] > 0) // Keypad +
2184 visibility = max(visibility-(visibility>>3),128);
2185 }
2186 #endif
2187 // if typing mode reset kbrd fifo
2188 if( (keystatus[keys[18]]) > 0 ) {
2189 keystatus[keys[18]] = 0;
2190 typemode = 1;
2191 // TODO keyfifoplc = keyfifoend;
2192 }
2193 }
2194 else {
2195
2196 #if 0 // TODO
2197 while( keyfifoplc != keyfifoend )
2198 {
2199 ch = keyfifo[keyfifoplc];
2200 keystate = keyfifo[(keyfifoplc+1)&(KEYFIFOSIZ-1)];
2201 keyfifoplc = ((keyfifoplc+2)&(KEYFIFOSIZ-1));
2202 if( keystate != 0 ) {
2203 // backspace key
2204 if( ch == 0xe ) {
2205 if( typemessageleng == 0 ) {
2206 typemode = 0;
2207 break;
2208 }
2209 typemessageleng--;
2210 }
2211 if( ch == 0xf ) {
2212 keystatus[0xf] = 0;
2213 typemode = 0;
2214 break;
2215 }
2216 // either enter key
2217 if( (ch == 0x1c) || (ch == 0x9c) ) {
2218 keystatus[0x1c] = 0; keystatus[0x9c] = 0;
2219 if( typemessageleng > 0 ) {
2220 tempbuf[0] = 2;
2221 // sending text is message type 4
2222 for( j=typemessageleng-1; j>=0; j-- ) {
2223 tempbuf[j+1] = typemessage[j];
2224 }
2225 for( i=connecthead; i>=0; i=connectpoint2[i] ) {
2226 if( i != myconnectindex ) {
2227 sendpacket(i,packetbuf,typemessageleng+1);
2228 }
2229 }
2230 typemessageleng = 0;
2231 }
2232 typemode = 0;
2233 break;
2234 }
2235 if( (typemessageleng < 159) && (ch < 128) ) {
2236 if( (keystatus[0x2a]|keystatus[0x36]) != 0 ) {
2237 ch = scantoascwithshift[ch];
2238 }
2239 else {
2240 ch = scantoasc[ch];
2241 }
2242 if( ch != 0 ) {
2243 typemessage[typemessageleng++] = ch;
2244 }
2245 }
2246 }
2247 }
2248 #endif
2249
2250 // here's a trick of making key repeat after a 1/2 second
2251 if( keystatus[0xe] > 0 ) {
2252 if( keystatus[0xe] < 30 ) {
2253 keystatus[0xe] += TICSPERFRAME;
2254 }
2255 else {
2256 if( typemessageleng == 0 ) {
2257 typemode = 0;
2258 }
2259 else {
2260 typemessageleng--;
2261 }
2262 }
2263 }
2264 }
2265
2266 tekprivatekeys();
2267 }
2268
2269 void
playback()2270 playback()
2271 {
2272 int i, j, k;
2273
2274 ready2send = 0;
2275 recstat = 0; i = reccnt;
2276 while (keystatus[1] == 0)
2277 {
2278 while (((int)totalclock) >= lockclock+TICSPERFRAME)
2279 {
2280 if (i >= reccnt)
2281 {
2282 prepareboard(boardfilename);
2283 for(i=connecthead;i>=0;i=connectpoint2[i])
2284 initplayersprite((short)i);
2285 resettiming(); ototalclock = 0; gotlastpacketclock = 0;
2286 i = 0;
2287 }
2288
2289 k = 0;
2290 for(j=connecthead;j>=0;j=connectpoint2[j])
2291 {
2292 fsyncvel[j] = recsyncvel[i][k];
2293 fsyncsvel[j] = recsyncsvel[i][k];
2294 fsyncangvel[j] = recsyncangvel[i][k];
2295 fsyncbits[j] = recsyncbits[i][k];
2296 k++;
2297 }
2298 movethings(); domovethings();
2299 i++;
2300 }
2301 drawscreen(screenpeek,(((int)totalclock)-lockclock)*(65536/TICSPERFRAME));
2302
2303 if (keystatus[keys[15]] > 0)
2304 {
2305 keystatus[keys[15]] = 0;
2306
2307 screenpeek = connectpoint2[screenpeek];
2308 if (screenpeek < 0) screenpeek = connecthead;
2309 }
2310 if (keystatus[keys[14]] > 0)
2311 {
2312 keystatus[keys[14]] = 0;
2313 dimensionmode[screenpeek]++;
2314 if (dimensionmode[screenpeek] > 3) dimensionmode[screenpeek] = 1;
2315 if (dimensionmode[screenpeek] == 2) videoSetViewableArea(0L,0L,xdim-1,(ydim-1)>>detailmode);
2316 if (dimensionmode[screenpeek] == 3) setup3dscreen();
2317 }
2318 }
2319
2320 musicoff();
2321
2322 uninitmultiplayers();
2323 //uninittimer();
2324 uninitinput();
2325 engineUnInit();
2326 uninitsb();
2327 uninitgroupfile();
2328 cduninit();
2329 exit(0);
2330 }
2331
2332 void
doanimations()2333 doanimations()
2334 {
2335 int i, j;
2336
2337 for(i=animatecnt-1;i>=0;i--)
2338 {
2339 j = *animateptr[i];
2340
2341 if (j < animategoal[i])
2342 j = min(j+animatevel[i]*TICSPERFRAME,animategoal[i]);
2343 else
2344 j = max(j-animatevel[i]*TICSPERFRAME,animategoal[i]);
2345 animatevel[i] += animateacc[i];
2346
2347 *animateptr[i] = j;
2348
2349 if (j == animategoal[i])
2350 {
2351 animatecnt--;
2352 if (i != animatecnt)
2353 {
2354 animateptr[i] = animateptr[animatecnt];
2355 animategoal[i] = animategoal[animatecnt];
2356 animatevel[i] = animatevel[animatecnt];
2357 animateacc[i] = animateacc[animatecnt];
2358 }
2359 }
2360 }
2361 }
2362
2363 int
getanimationgoal(int * animptr)2364 getanimationgoal(int *animptr)
2365 {
2366 int i;
2367
2368 for(i=animatecnt-1;i>=0;i--)
2369 if (animptr == animateptr[i]) return(i);
2370 return(-1);
2371 }
2372
2373 int
setanimation(int * animptr,int thegoal,int thevel,int theacc)2374 setanimation(int *animptr, int thegoal, int thevel, int theacc)
2375 {
2376 int i, j;
2377
2378 if (animatecnt >= MAXANIMATES) return(-1);
2379
2380 j = animatecnt;
2381 for(i=animatecnt-1;i>=0;i--)
2382 if (animptr == animateptr[i])
2383 { j = i; break; }
2384
2385 animateptr[j] = animptr;
2386 animategoal[j] = thegoal;
2387 animatevel[j] = thevel;
2388 animateacc[j] = theacc;
2389 if (j == animatecnt) animatecnt++;
2390 return(j);
2391 }
2392
2393 void
checkmasterslaveswitch()2394 checkmasterslaveswitch()
2395 {
2396 int i, j;
2397
2398 if (option[4] == 0) return;
2399
2400 i = connecthead; j = connectpoint2[i];
2401 while (j >= 0)
2402 {
2403 if ((syncbits[j]&512) > 0)
2404 {
2405 connectpoint2[i] = connectpoint2[j];
2406 connectpoint2[j] = connecthead;
2407 connecthead = (short)j;
2408
2409 olocvel = locvel+1; olocvel2 = locvel2+1;
2410 olocsvel = locsvel+1; olocsvel2 = locsvel2+1;
2411 olocangvel = locangvel+1; olocangvel2 = locangvel2+1;
2412 olocbits = locbits+1; olocbits2 = locbits2+1;
2413 for(i=0;i<MAXPLAYERS;i++)
2414 {
2415 osyncvel[i] = fsyncvel[i]+1;
2416 osyncsvel[i] = fsyncsvel[i]+1;
2417 osyncangvel[i] = fsyncangvel[i]+1;
2418 osyncbits[i] = fsyncbits[i]+1;
2419 }
2420
2421 syncvalplc = 0L; othersyncvalplc = 0L;
2422 syncvalend = 0L; othersyncvalend = 0L;
2423 syncvalcnt = 0L; othersyncvalcnt = 0L;
2424
2425 totalclock = lockclock;
2426 ototalclock = lockclock;
2427 gotlastpacketclock = lockclock;
2428 masterslavetexttime = lockclock;
2429 ready2send = 1;
2430 return;
2431 }
2432 i = j; j = connectpoint2[i];
2433 }
2434 }
2435
2436 void
faketimerhandler()2437 faketimerhandler()
2438 {
2439 short other;
2440 int i, j, k, l;
2441
2442 if (((int)totalclock) < ototalclock+TICSPERFRAME) return;
2443 if (ready2send == 0) return;
2444 ototalclock = (int)totalclock;
2445
2446 // I am the MASTER (or 1 player game)
2447 if ((myconnectindex == connecthead) || (option[4] == 0))
2448 {
2449 if (option[4] != 0)
2450 getpackets();
2451
2452 if (getoutputcirclesize() < 16)
2453 {
2454 getinput();
2455 fsyncvel[myconnectindex] = locvel;
2456 fsyncsvel[myconnectindex] = locsvel;
2457 fsyncangvel[myconnectindex] = locangvel;
2458 fsyncbits[myconnectindex] = locbits;
2459
2460 if (option[4] != 0)
2461 {
2462 packetbuf[0] = 0;
2463 j = ((numplayers+1)>>1)+1;
2464 for(k=1;k<j;k++) packetbuf[k] = 0;
2465 k = (1<<3);
2466 for(i=connecthead;i>=0;i=connectpoint2[i])
2467 {
2468 l = 0;
2469 if (fsyncvel[i] != osyncvel[i]) packetbuf[j++] = fsyncvel[i], l |= 1;
2470 //** Les START - 09/27/95
2471 if (fsyncsvel[i] != osyncsvel[i]) {
2472 packetbuf[j++]=(fsyncsvel[i]&0xFF);
2473 packetbuf[j++]=(fsyncsvel[i]>>8);
2474 l|=2;
2475 }
2476 if (fsyncangvel[i] != osyncangvel[i]) {
2477 packetbuf[j++]=(fsyncangvel[i]&0xFF);
2478 packetbuf[j++]=(fsyncangvel[i]>>8);
2479 l|=4;
2480 }
2481 //** Les END - 09/27/95
2482 if (fsyncbits[i] != osyncbits[i])
2483 {
2484 tempbuf[j++] = (fsyncbits[i]&255);
2485 tempbuf[j++] = ((fsyncbits[i]>>8)&255);
2486 l |= 8;
2487 }
2488 tempbuf[k>>3] |= (l<<(k&7));
2489 k += 4;
2490
2491 osyncvel[i] = fsyncvel[i];
2492 osyncsvel[i] = fsyncsvel[i];
2493 osyncangvel[i] = fsyncangvel[i];
2494 osyncbits[i] = fsyncbits[i];
2495 }
2496 #if 0
2497 while (syncvalplc != syncvalend)
2498 {
2499 tempbuf[j] = (unsigned char)(syncval[syncvalplc]&255);
2500 tempbuf[j+1] = (unsigned char)((syncval[syncvalplc]>>8)&255);
2501 j += 2;
2502 syncvalplc = ((syncvalplc+1)&(MOVEFIFOSIZ-1));
2503 }
2504 #endif
2505 for(i=connectpoint2[connecthead];i>=0;i=connectpoint2[i])
2506 sendpacket(i, packetbuf,j);
2507 }
2508 else if (numplayers == 2)
2509 {
2510 if (keystatus[0xb5] > 0)
2511 {
2512 keystatus[0xb5] = 0;
2513 locselectedgun2++;
2514 if (locselectedgun2 >= 3) locselectedgun2 = 0;
2515 }
2516
2517 // second player on 1 computer mode
2518 locvel2 = min(max(vel2,-128+8),127-8);
2519 locsvel2 = min(max(svel2,-128+8),127-8);
2520 locangvel2 = min(max(angvel2,-128+16),127-16);
2521 locbits2 = (locselectedgun2<<13);
2522 locbits2 |= keystatus[0x45]; //Stand high
2523 locbits2 |= (keystatus[0x47]<<1); //Stand low
2524 locbits2 |= (1<<8); //Run
2525 locbits2 |= (keystatus[0x49]<<2); //Look up
2526 locbits2 |= (keystatus[0x37]<<3); //Look down
2527 locbits2 |= (keystatus[0x50]<<10); //Space
2528 locbits2 |= (keystatus[0x52]<<11); //Shoot
2529
2530 other = connectpoint2[myconnectindex];
2531 if (other < 0) other = connecthead;
2532
2533 fsyncvel[other] = locvel2;
2534 fsyncsvel[other] = locsvel2;
2535 fsyncangvel[other] = locangvel2;
2536 fsyncbits[other] = locbits2;
2537 }
2538 movethings(); //Move EVERYTHING (you too!)
2539 }
2540 }
2541 else //I am a SLAVE
2542 {
2543 getpackets();
2544
2545 if (getoutputcirclesize() < 16)
2546 {
2547 getinput();
2548
2549 packetbuf[0] = 1; k = 0;
2550 j = 2;
2551
2552 if (locvel != olocvel) packetbuf[j++] = locvel, k |= 1;
2553 //** Les START - 09/27/95
2554 if (locsvel != olocsvel) {
2555 packetbuf[j++]=locsvel&0xFF;
2556 packetbuf[j++]=(locsvel>>8);
2557 k|=2;
2558 }
2559 if (locangvel != olocangvel) {
2560 packetbuf[j++]=locangvel&0xFF;
2561 packetbuf[j++]=(locangvel>>8);
2562 k|=4;
2563 }
2564 //** Les END - 09/27/95
2565 if ((locbits^olocbits)&0x00ff) packetbuf[j++] = (locbits&255), k |= 8;
2566 if ((locbits^olocbits)&0xff00) packetbuf[j++] = ((locbits>>8)&255), k |= 16;
2567
2568 packetbuf[1] = k;
2569
2570 olocvel = locvel;
2571 olocsvel = locsvel;
2572 olocangvel = locangvel;
2573 olocbits = locbits;
2574
2575 sendpacket(connecthead, packetbuf,j);
2576 }
2577 }
2578 }
2579
2580 void
getpackets()2581 getpackets()
2582 {
2583 int i, j, k, l;
2584 int other, tempbufleng;
2585
2586 if (option[4] == 0) return;
2587
2588 while ((tempbufleng = getpacket(&other, packetbuf)) > 0)
2589 {
2590 switch(packetbuf[0])
2591 {
2592 case 0: //[0] (receive master sync buffer)
2593 j = ((numplayers+1)>>1)+1; k = (1<<3);
2594 for(i=connecthead;i>=0;i=connectpoint2[i])
2595 {
2596 l = (packetbuf[k>>3]>>(k&7));
2597 if (l&1) fsyncvel[i] = packetbuf[j++];
2598 //** Les START - 09/27/95
2599 if (l&2) {
2600 fsyncsvel[i]= packetbuf[j++];
2601 fsyncsvel[i]|=(packetbuf[j++]<<8);
2602 }
2603 if (l&4) {
2604 fsyncangvel[i]= packetbuf[j++];
2605 fsyncangvel[i]|=(packetbuf[j++]<<8);
2606 }
2607 //** Les END - 09/27/95
2608 if (l&8)
2609 {
2610 fsyncbits[i] = ((short)packetbuf[j])+(((short)packetbuf[j+1])<<8);
2611 j += 2;
2612 }
2613 k += 4;
2614 }
2615 #if 0
2616 while (j != tempbufleng)
2617 {
2618 othersyncval[othersyncvalend] = ((int)tempbuf[j]);
2619 othersyncval[othersyncvalend] += (((int)tempbuf[j+1])<<8);
2620 j += 2;
2621 othersyncvalend = ((othersyncvalend+1)&(MOVEFIFOSIZ-1));
2622 }
2623
2624 i = 0;
2625 while (syncvalplc != syncvalend)
2626 {
2627 if (othersyncvalcnt > syncvalcnt)
2628 {
2629 if (i == 0) syncstat = 0, i = 1;
2630 syncstat |= (syncval[syncvalplc]^othersyncval[syncvalplc]);
2631 }
2632 syncvalplc = ((syncvalplc+1)&(MOVEFIFOSIZ-1));
2633 syncvalcnt++;
2634 }
2635 while (othersyncvalplc != othersyncvalend)
2636 {
2637 if (syncvalcnt > othersyncvalcnt)
2638 {
2639 if (i == 0) syncstat = 0, i = 1;
2640 syncstat |= (syncval[othersyncvalplc]^othersyncval[othersyncvalplc]);
2641 }
2642 othersyncvalplc = ((othersyncvalplc+1)&(MOVEFIFOSIZ-1));
2643 othersyncvalcnt++;
2644 }
2645 #endif
2646
2647 movethings(); //Move all players and sprites
2648 break;
2649 case 1: //[1] (receive slave sync buffer)
2650 j = 2; k = packetbuf[1];
2651 if (k&1) fsyncvel[other] = packetbuf[j++];
2652 //** Les START - 09/27/95
2653 if (k&2) {
2654 fsyncsvel[other]= packetbuf[j++];
2655 fsyncsvel[other]|=(packetbuf[j++]<<8);
2656 }
2657 if (k&4) {
2658 fsyncangvel[other]= packetbuf[j++];
2659 fsyncangvel[other]|=(packetbuf[j++]<<8);
2660 }
2661 //** Les END - 09/27/95
2662 if (k&8) fsyncbits[other] = ((fsyncbits[other]&0xff00)|((short)packetbuf[j++]));
2663 if (k&16) fsyncbits[other] = ((fsyncbits[other]&0x00ff)|(((short)packetbuf[j++])<<8));
2664 break;
2665 case 2:
2666 getmessageleng = tempbufleng-1;
2667 for(j=getmessageleng-1;j>=0;j--) getmessage[j] = packetbuf[j+1];
2668 getmessagetimeoff = ((int)totalclock)+360+(getmessageleng<<4);
2669 break;
2670 case 3:
2671 break;
2672 #ifdef NETNAMES
2673 case 8:
2674 memcpy(netnames[packetbuf[1]],&packetbuf[2],10);
2675 netnames[packetbuf[1]][10]=0;
2676 break;
2677 #endif
2678 case 5:
2679 playerreadyflag[other] = packetbuf[1];
2680 if ((other == connecthead) && (packetbuf[1] == 2))
2681 sendpacket(connecthead, packetbuf,2);
2682 break;
2683 case 255: //[255] (logout)
2684 deletesprite(playersprite[other]);
2685 sprintf(tektempbuf,"%2d %8s HAS QUIT", other,netnames[other]);
2686 showmessage(tektempbuf);
2687 break;
2688 }
2689 }
2690 }
2691
2692 void
waitforeverybody()2693 waitforeverybody()
2694 {
2695 int i, j, oldtotalclock;
2696
2697 if (numplayers < 2) return;
2698
2699 if (myconnectindex == connecthead)
2700 {
2701 for(j=1;j<=2;j++)
2702 {
2703 for(i=connectpoint2[connecthead];i>=0;i=connectpoint2[i])
2704 playerreadyflag[i] = 0;
2705 oldtotalclock = ((int)totalclock)-8;
2706 do
2707 {
2708 getpackets();
2709 if (((int)totalclock) >= oldtotalclock+8)
2710 {
2711 oldtotalclock = (int)totalclock;
2712 packetbuf[0] = 5;
2713 packetbuf[1] = j;
2714 for(i=connectpoint2[connecthead];i>=0;i=connectpoint2[i])
2715 if (playerreadyflag[i] != j) sendpacket(i, packetbuf,2);
2716 }
2717 for(i=connectpoint2[connecthead];i>=0;i=connectpoint2[i])
2718 if (playerreadyflag[i] != j) break;
2719 } while (i >= 0);
2720 }
2721 }
2722 else
2723 {
2724 playerreadyflag[connecthead] = 0;
2725 while (playerreadyflag[connecthead] != 2)
2726 {
2727 getpackets();
2728 if (playerreadyflag[connecthead] == 1)
2729 {
2730 playerreadyflag[connecthead] = 0;
2731 sendpacket(connecthead, packetbuf,2);
2732 }
2733 }
2734 }
2735 }
2736
2737 #if 0
2738 unsigned short
2739 getsyncstat()
2740 {
2741 int i, j;
2742 unsigned short crc;
2743 spritetype *spr;
2744
2745 crc = 0;
2746 updatecrc16(crc,randomseed); updatecrc16(crc,randomseed>>8);
2747 for(i=connecthead;i>=0;i=connectpoint2[i])
2748 {
2749 updatecrc16(crc,posx[i]);
2750 updatecrc16(crc,posy[i]);
2751 updatecrc16(crc,posz[i]);
2752 updatecrc16(crc,ang[i]);
2753 updatecrc16(crc,horiz[i]);
2754 updatecrc16(crc,health[i]);
2755 }
2756
2757 #if SPRITES_CRC_CHECK
2758 for( i=1000; i>=0; i-- ) {
2759 for( j=headspritestat[i]; j>=0; j=nextspritestat[j] ) {
2760 spr = &sprite[j];
2761 updatecrc16(crc,spr->x); //if (syncstat != 0) printf("%ld ",spr->x);
2762 updatecrc16(crc,spr->y); //if (syncstat != 0) printf("%ld ",spr->y);
2763 updatecrc16(crc,spr->z); //if (syncstat != 0) printf("%ld ",spr->z);
2764 updatecrc16(crc,spr->ang); //if (syncstat != 0) printf("%ld ",spr->ang);
2765 }
2766 }
2767 #endif
2768
2769 return(crc);
2770 }
2771 #endif
2772
2773