blob: 66ce4123bf9edc0657895446b70b8e901770837e [file] [log] [blame]
Franklin Weia855d622017-01-21 15:18:31 -05001//-------------------------------------------------------------------------
2/*
3 Copyright (C) 1996, 2003 - 3D Realms Entertainment
4
5 This file is part of Duke Nukem 3D version 1.5 - Atomic Edition
6
7 Duke Nukem 3D is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
16 See the GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 aint32_t with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22 Original Source: 1996 - Todd Replogle
23 Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
24*/
25//-------------------------------------------------------------------------
26
27#include "duke3d.h"
28#include "mouse.h"
29#include "animlib.h"
30#include "control.h"
31
32#include "../../Engine/src/filesystem.h"
33#include "SDL.h"
34#include "premap.h"
35#include "../../Engine/src/display.h"
36
37extern SDL_Surface *surface;
38extern short inputloc;
39extern int recfilep;
40extern uint8_t vgacompatible;
41short probey=0,lastprobey=0,last_menu,globalskillsound=-1;
42short sh,onbar,buttonstat,deletespot;
43short last_zero,last_fifty,last_threehundred = 0;
44static uint8_t fileselect = 1, menunamecnt;
45static char menuname[256][17];
46
47// File tree info
48//
49uint8_t szCurrentDirectory[1024] = {'\0'};
50
51#define FILETYPE_DIRECTORY 0
52#define FILETYPE_FILE 1
53
54typedef struct fileentry
55{
56 uint8_t filename[16];
57 int type;
58}FILEENTRY;
59
60typedef struct filelist
61{
62 FILEENTRY *files;
63}FILELIST;
64
65FILELIST m_Files;// = NULL;
66
67//
68//
69
70#define MENU_SELECT_EPISODE 100
71#define MENU_USER_MAP 101
72
73
74// CTW - REMOVED
75/* Error codes */
76/*
77 #define eTenBnNotInWindows 3801
78 #define eTenBnBadGameIni 3802
79 #define eTenBnBadTenIni 3803
80 #define eTenBnBrowseCancel 3804
81 #define eTenBnBadTenInst 3805
82
83 int tenBnStart(void);
84 void tenBnSetBrowseRtn(uint8_t *(*rtn)(uint8_t *str, int len));
85 void tenBnSetExitRtn(void (*rtn)(void));
86 void tenBnSetEndRtn(void (*rtn)(void));*/
87// CTW END - REMOVED
88
89void dummyfunc(void)
90{
91}
92
93void dummymess(int i,uint8_t *c)
94{
95}
96
97// CTW - REMOVED
98/*
99 void TENtext(void)
100 {
101 int32_t dacount,dalastcount;
102
103 puts("\nDuke Nukem 3D has been licensed exclusively to TEN (Total");
104 puts("Entertainment Network) for wide-area networked (WAN) multiplayer");
105 puts("games.\n");
106
107 puts("The multiplayer code within Duke Nukem 3D has been highly");
108 puts("customized to run best on TEN, where you'll experience fast and");
109 puts("stable performance, plus other special benefits.\n");
110
111 puts("We do not authorize or recommend the use of Duke Nukem 3D with");
112 puts("gaming services other than TEN.\n");
113
114 puts("Duke Nukem 3D is protected by United States copyright law and");
115 puts("international treaty.\n");
116
117 puts("For the best online multiplayer gaming experience, please call TEN");
118 puts("at 800-8040-TEN, or visit TEN's Web Site at www.ten.net.\n");
119
120 puts("Press any key to continue.\n");
121
122 _bios_timeofday(0,&dacount);
123
124 while( _bios_keybrd(1) == 0 )
125 {
126 _bios_timeofday(0,&dalastcount);
127 if( (dacount+240) < dalastcount ) break;
128 }
129 }
130*/
131// CTW END - REMOVED
132
133void cmenu(short cm)
134{
135 current_menu = cm;
136
137 if( (cm >= 1000 && cm <= 1010) )
138 return;
139
140 if( cm == 0 )
141 probey = last_zero;
142 else if(cm == 50)
143 probey = last_fifty;
144 else if(cm >= 300 && cm < 400)
145 probey = last_threehundred;
146 else if(cm == 110)
147 probey = 1;
148 else probey = 0;
149 lastprobey = -1;
150}
151
152
153void savetemp(char *fn,uint8_t* daptr,int32_t dasiz)
154{
155 int fp;
156
157 char full[256];
158 snprintf(full, "%s/%s", game_dir, fn);
159 fp = rb->open(full,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666);
160
161 write(fp,(uint8_t *)daptr,dasiz);
162
163 close(fp);
164}
165
166void getangplayers(short snum)
167{
168 short i,a;
169
170 for(i=connecthead;i>=0;i=connectpoint2[i])
171 {
172 if(i != snum)
173 {
174 a = ps[snum].ang+getangle(ps[i].posx-ps[snum].posx,ps[i].posy-ps[snum].posy);
175 a = a-1024;
176 rotatesprite(
177 (320<<15) + (((sintable[(a+512)&2047])>>7)<<15),
178 (320<<15) - (((sintable[a&2047])>>8)<<15),
179 klabs(sintable[((a>>1)+768)&2047]<<2),0,APLAYER,0,ps[i].palookup,0,0,0,xdim-1,ydim-1);
180 }
181 }
182}
183
184int loadpheader(uint8_t spot,int32 *vn,int32 *ln,int32 *psk,int32 *nump)
185{
186
187 char fn[] = "game0.sav";
188 int32_t fil;
189 int32_t bv;
190
191 fn[4] = spot+'0';
192
193 char fullfn[256];
194 sprintf(fullfn, "%s/%s", game_dir, fn);
195
196 if ((fil = TCkopen4load(fullfn,0)) == -1) return(-1);
197
198 tiles[MAXTILES-3].lock = 255;
199
200 kdfread(&bv,4,1,fil);
201 if(bv != BYTEVERSION)
202 {
203 FTA(114,&ps[myconnectindex],1);
204 kclose(fil);
205 return 1;
206 }
207
208 kdfread(nump,sizeof(int32),1,fil);
209
210 kdfread(tempbuf,19,1,fil);
211 kdfread(vn,sizeof(int32),1,fil);
212 kdfread(ln,sizeof(int32),1,fil);
213 kdfread(psk,sizeof(int32),1,fil);
214
215 if (tiles[MAXTILES-3].data == NULL)
216 allocache(&tiles[MAXTILES-3].data,160*100,&tiles[MAXTILES-3].lock);
217 tiles[MAXTILES-3].dim.width = 100;
218 tiles[MAXTILES-3].dim.height = 160;
219 kdfread(tiles[MAXTILES-3].data,160,100,fil);
220 kclose(fil);
221 return(0);
222}
223
224
225int loadplayer(int8_t spot)
226{
227 short k,music_changed;
228 char fn[] = "game0.sav";
229 char mpfn[] = "gameA_00.sav";
230 char *fnptr, scriptptrs[MAXSCRIPTSIZE];
231 int32_t fil, bv, i, j, x;
232 int32 nump;
233
234 if(spot < 0)
235 {
236 multiflag = 1;
237 multiwhat = 0;
238 multipos = -spot-1;
239 return -1;
240 }
241
242 if( multiflag == 2 && multiwho != myconnectindex )
243 {
244 fnptr = mpfn;
245 mpfn[4] = spot + 'A';
246
247 if(ud.multimode > 9)
248 {
249 mpfn[6] = (multiwho/10) + '0';
250 mpfn[7] = (multiwho%10) + '0';
251 }
252 else mpfn[7] = multiwho + '0';
253 }
254 else
255 {
256 fnptr = fn;
257 fn[4] = spot + '0';
258 }
259
260 char fullfn[256];
261 sprintf(fullfn, "%s/%s", game_dir, fnptr);
262
263 if ((fil = TCkopen4load(fullfn,0)) == -1) return(-1);
264
265 if(ud.recstat != 2)
266 ready2send = 0;
267
268 kdfread(&bv,4,1,fil);
269 if(bv != BYTEVERSION)
270 {
271 rb->splashf(HZ, "wrong version (%d != %d)", bv, BYTEVERSION);
272 FTA(114,&ps[myconnectindex],1);
273 kclose(fil);
274 if(ud.recstat != 2)
275 {
276 // FIX_00084: Various bugs in the load game (single player) option if ESC is hit or if wrong version
277 ototalclock = totalclock;
278 ready2send = 1;
279 }
280 return 1;
281 }
282
283 kdfread(&nump,sizeof(nump),1,fil);
284 if(nump != numplayers)
285 {
286 rb->splash(HZ, "wrong num players");
287 kclose(fil);
288 if(ud.recstat != 2)
289 {
290 // FIX_00084: Various bugs in the load game (single player) option if ESC is hit or if wrong version
291 ototalclock = totalclock;
292 ready2send = 1;
293 }
294 FTA(124,&ps[myconnectindex],1);
295 return 1;
296 }
297
298 if(numplayers > 1)
299 {
300 pub = NUMPAGES;
301 pus = NUMPAGES;
302 vscrn();
303 drawbackground();
304 menutext(160,100,0,0,"LOADING...");
305 nextpage();
306 }
307
308 waitforeverybody();
309
310 FX_StopAllSounds();
311 clearsoundlocks();
312 MUSIC_StopSong();
313
314 if(numplayers > 1)
315 kdfread(&buf,19,1,fil);
316 else
317 kdfread(&ud.savegame[spot][0],19,1,fil);
318
319 music_changed = (music_select != (ud.volume_number*11) + ud.level_number);
320
321 kdfread(&ud.volume_number,sizeof(ud.volume_number),1,fil);
322 kdfread(&ud.level_number,sizeof(ud.level_number),1,fil);
323 kdfread(&ud.player_skill,sizeof(ud.player_skill),1,fil);
324
325 ud.m_level_number = ud.level_number;
326 ud.m_volume_number = ud.volume_number;
327 ud.m_player_skill = ud.player_skill;
328
329 //Fake read because lseek won't work with compression
330 tiles[MAXTILES-3].lock = 1;
331
332 if (tiles[MAXTILES-3].data == NULL)
333 allocache(&tiles[MAXTILES-3].data,160*100,&tiles[MAXTILES-3].lock);
334
335 tiles[MAXTILES-3].dim.width = 100;
336 tiles[MAXTILES-3].dim.height = 160;
337
338 kdfread(tiles[MAXTILES-3].data,160,100,fil);
339
340 kdfread(&numwalls,2,1,fil);
341 kdfread(&wall[0],sizeof(walltype),MAXWALLS,fil);
342 kdfread(&numsectors,2,1,fil);
343 kdfread(&sector[0],sizeof(sectortype),MAXSECTORS,fil);
344 kdfread(&sprite[0],sizeof(spritetype),MAXSPRITES,fil);
345 kdfread(&headspritesect[0],2,MAXSECTORS+1,fil);
346 kdfread(&prevspritesect[0],2,MAXSPRITES,fil);
347 kdfread(&nextspritesect[0],2,MAXSPRITES,fil);
348 kdfread(&headspritestat[0],2,MAXSTATUS+1,fil);
349 kdfread(&prevspritestat[0],2,MAXSPRITES,fil);
350 kdfread(&nextspritestat[0],2,MAXSPRITES,fil);
351 kdfread(&numcyclers,sizeof(numcyclers),1,fil);
352 kdfread(&cyclers[0][0],12,MAXCYCLERS,fil);
353 kdfread(ps,sizeof(ps),1,fil);
354 kdfread(po,sizeof(po),1,fil);
355 kdfread(&numanimwalls,sizeof(numanimwalls),1,fil);
356 kdfread(&animwall,sizeof(animwall),1,fil);
357 kdfread(&msx[0],sizeof(int32_t),sizeof(msx)/sizeof(int32_t),fil);
358 kdfread(&msy[0],sizeof(int32_t),sizeof(msy)/sizeof(int32_t),fil);
359 kdfread((short *)&spriteqloc,sizeof(short),1,fil);
360 kdfread((short *)&spriteqamount,sizeof(short),1,fil);
361 kdfread((short *)&spriteq[0],sizeof(short),spriteqamount,fil);
362 kdfread(&mirrorcnt,sizeof(short),1,fil);
363 kdfread(&mirrorwall[0],sizeof(short),64,fil);
364 kdfread(&mirrorsector[0],sizeof(short),64,fil);
365 kdfread(&show2dsector[0],sizeof(uint8_t ),MAXSECTORS>>3,fil);
366 kdfread(&actortype[0],sizeof(uint8_t ),MAXTILES,fil);
367 kdfread(&boardfilename[0],sizeof(boardfilename),1,fil);
368
369 kdfread(&numclouds,sizeof(numclouds),1,fil);
370 kdfread(&clouds[0],sizeof(short)<<7,1,fil);
371 kdfread(&cloudx[0],sizeof(short)<<7,1,fil);
372 kdfread(&cloudy[0],sizeof(short)<<7,1,fil);
373
374 kdfread(&scriptptrs[0],1,MAXSCRIPTSIZE,fil);
375 kdfread(&script[0],4,MAXSCRIPTSIZE,fil);
376 for(i=0;i<MAXSCRIPTSIZE;i++)
377 if( scriptptrs[i] )
378 {
379 j = (int32_t)script[i]+(int32_t)&script[0];
380 script[i] = j;
381 }
382
383 kdfread(&actorscrptr[0],4,MAXTILES,fil);
384 for(i=0;i<MAXTILES;i++)
385 if(actorscrptr[i])
386 {
387 j = (int32_t)actorscrptr[i]+(int32_t)&script[0];
388 actorscrptr[i] = (int32_t *)j;
389 }
390
391 kdfread(&scriptptrs[0],1,MAXSPRITES,fil);
392 kdfread(&hittype[0],sizeof(struct weaponhit),MAXSPRITES,fil);
393
394 for(i=0;i<MAXSPRITES;i++)
395 {
396 j = (int32_t)(&script[0]);
397 if( scriptptrs[i]&1 ) T2 += j;
398 if( scriptptrs[i]&2 ) T5 += j;
399 if( scriptptrs[i]&4 ) T6 += j;
400 }
401
402 kdfread(&lockclock,sizeof(lockclock),1,fil);
403 kdfread(&pskybits,sizeof(pskybits),1,fil);
404 kdfread(&pskyoff[0],sizeof(pskyoff[0]),MAXPSKYTILES,fil);
405
406 kdfread(&animatecnt,sizeof(animatecnt),1,fil);
407 kdfread(&animatesect[0],2,MAXANIMATES,fil);
408 kdfread(&animateptr[0],4,MAXANIMATES,fil);
409 for(i = animatecnt-1;i>=0;i--) animateptr[i] = (int32_t *)((int32_t)animateptr[i]+(int32_t)(&sector[0]));
410 kdfread(&animategoal[0],4,MAXANIMATES,fil);
411 kdfread(&animatevel[0],4,MAXANIMATES,fil);
412
413 kdfread(&earthquaketime,sizeof(earthquaketime),1,fil);
414 kdfread(&ud.from_bonus,sizeof(ud.from_bonus),1,fil);
415 kdfread(&ud.secretlevel,sizeof(ud.secretlevel),1,fil);
416 kdfread(&ud.respawn_monsters,sizeof(ud.respawn_monsters),1,fil);
417 ud.m_respawn_monsters = ud.respawn_monsters;
418 kdfread(&ud.respawn_items,sizeof(ud.respawn_items),1,fil);
419 ud.m_respawn_items = ud.respawn_items;
420 kdfread(&ud.respawn_inventory,sizeof(ud.respawn_inventory),1,fil);
421 ud.m_respawn_inventory = ud.respawn_inventory;
422
423 kdfread(&ud.god,sizeof(ud.god),1,fil);
424 kdfread(&ud.auto_run,sizeof(ud.auto_run),1,fil);
425 kdfread(&ud.crosshair,sizeof(ud.crosshair),1,fil);
426 kdfread(&ud.monsters_off,sizeof(ud.monsters_off),1,fil);
427 ud.m_monsters_off = ud.monsters_off;
428 kdfread(&ud.last_level,sizeof(ud.last_level),1,fil);
429 kdfread(&ud.eog,sizeof(ud.eog),1,fil);
430
431 kdfread(&ud.coop,sizeof(ud.coop),1,fil);
432 ud.m_coop = ud.coop;
433 kdfread(&ud.marker,sizeof(ud.marker),1,fil);
434 ud.m_marker = ud.marker;
435 kdfread(&ud.ffire,sizeof(ud.ffire),1,fil);
436 ud.m_ffire = ud.ffire;
437
438 kdfread(&camsprite,sizeof(camsprite),1,fil);
439 kdfread(&connecthead,sizeof(connecthead),1,fil);
440 kdfread(connectpoint2,sizeof(connectpoint2),1,fil);
441 kdfread(&numplayersprites,sizeof(numplayersprites),1,fil);
442 kdfread((short *)&frags[0][0],sizeof(frags),1,fil);
443
444 kdfread(&randomseed,sizeof(randomseed),1,fil);
445 kdfread(&global_random,sizeof(global_random),1,fil);
446 kdfread(&parallaxyscale,sizeof(parallaxyscale),1,fil);
447
448 kclose(fil);
449
450 if(ps[myconnectindex].over_shoulder_on != 0)
451 {
452 cameradist = 0;
453 cameraclock = 0;
454 ps[myconnectindex].over_shoulder_on = 1;
455 }
456
457 screenpeek = myconnectindex;
458
459 clearbufbyte(gotpic,sizeof(gotpic),0L);
460 clearsoundlocks();
461 cacheit();
462 docacheit();
463
464 if(music_changed == 0)
465 music_select = (ud.volume_number*11) + ud.level_number;
466 playmusic(&music_fn[0][music_select][0]);
467
468 ps[myconnectindex].gm = MODE_GAME;
469 ud.recstat = 0;
470
471 if(ps[myconnectindex].jetpack_on)
472 spritesound(DUKE_JETPACK_IDLE,ps[myconnectindex].i);
473
474 restorepalette = 1;
475 setpal(&ps[myconnectindex]);
476 vscrn();
477
478 FX_SetReverb(0);
479
480 if(ud.lockout == 0)
481 {
482 for(x=0;x<numanimwalls;x++)
483 if( wall[animwall[x].wallnum].extra >= 0 )
484 wall[animwall[x].wallnum].picnum = wall[animwall[x].wallnum].extra;
485 }
486 else
487 {
488 for(x=0;x<numanimwalls;x++)
489 switch(wall[animwall[x].wallnum].picnum)
490 {
491 case FEMPIC1:
492 wall[animwall[x].wallnum].picnum = BLANKSCREEN;
493 break;
494 case FEMPIC2:
495 case FEMPIC3:
496 wall[animwall[x].wallnum].picnum = SCREENBREAK6;
497 break;
498 }
499 }
500
501 numinterpolations = 0;
502 startofdynamicinterpolations = 0;
503
504 k = headspritestat[3];
505 while(k >= 0)
506 {
507 switch(sprite[k].lotag)
508 {
509 case 31:
510 setinterpolation(&sector[sprite[k].sectnum].floorz);
511 break;
512 case 32:
513 setinterpolation(&sector[sprite[k].sectnum].ceilingz);
514 break;
515 case 25:
516 setinterpolation(&sector[sprite[k].sectnum].floorz);
517 setinterpolation(&sector[sprite[k].sectnum].ceilingz);
518 break;
519 case 17:
520 setinterpolation(&sector[sprite[k].sectnum].floorz);
521 setinterpolation(&sector[sprite[k].sectnum].ceilingz);
522 break;
523 case 0:
524 case 5:
525 case 6:
526 case 11:
527 case 14:
528 case 15:
529 case 16:
530 case 26:
531 case 30:
532 setsectinterpolate(k);
533 break;
534 }
535
536 k = nextspritestat[k];
537 }
538
539 for(i=numinterpolations-1;i>=0;i--) bakipos[i] = *curipos[i];
540 for(i = animatecnt-1;i>=0;i--)
541 setinterpolation(animateptr[i]);
542
543 show_shareware = 0;
544 everyothertime = 0;
545
546 clearbufbyte(playerquitflag,MAXPLAYERS,0x01010101);
547
548 resetmys();
549
550 ready2send = 1;
551
552 flushpackets();
553 clearfifo();
554 waitforeverybody();
555
556 resettimevars();
557
558 return(0);
559}
560
561int saveplayer(int8_t spot)
562{
563 int32_t i, j;
564 char fn[] = "game0.sav";
565 char mpfn[] = "gameA_00.sav";
566 char *fnptr,scriptptrs[MAXSCRIPTSIZE];
567 FILE *fil;
568 int32_t bv = BYTEVERSION;
569 char fullpathsavefilename[256];
570
571 if(spot < 0)
572 {
573 multiflag = 1;
574 multiwhat = 1;
575 multipos = -spot-1;
576 return -1;
577 }
578
579 waitforeverybody();
580
581 if( multiflag == 2 && multiwho != myconnectindex )
582 {
583 fnptr = mpfn;
584 mpfn[4] = spot + 'A';
585
586 if(ud.multimode > 9)
587 {
588 mpfn[6] = (multiwho/10) + '0';
589 mpfn[7] = multiwho + '0';
590 }
591 else mpfn[7] = multiwho + '0';
592 }
593 else
594 {
595 fnptr = fn;
596 fn[4] = spot + '0';
597 }
598
599
600 // Are we loading a TC?
601 if(getGameDir()[0] != '\0')
602 {
603 // Yes
604 sprintf(fullpathsavefilename, "%s/%s", getGameDir(), fnptr);
605 }
606 else
607 {
608 // No
609 sprintf(fullpathsavefilename, "%s", fnptr);
610 }
611
612 if ((fil = fopen(fullpathsavefilename,"wb")) == 0) return(-1);
613
614 ready2send = 0;
615
616 dfwrite(&bv,4,1,fil);
617 dfwrite(&ud.multimode,sizeof(ud.multimode),1,fil);
618
619 dfwrite(&ud.savegame[spot][0],19,1,fil);
620 dfwrite(&ud.volume_number,sizeof(ud.volume_number),1,fil);
621 dfwrite(&ud.level_number,sizeof(ud.level_number),1,fil);
622 dfwrite(&ud.player_skill,sizeof(ud.player_skill),1,fil);
623 dfwrite(tiles[MAXTILES-1].data,160,100,fil);
624
625 dfwrite(&numwalls,2,1,fil);
626 dfwrite(&wall[0],sizeof(walltype),MAXWALLS,fil);
627 dfwrite(&numsectors,2,1,fil);
628 dfwrite(&sector[0],sizeof(sectortype),MAXSECTORS,fil);
629 dfwrite(&sprite[0],sizeof(spritetype),MAXSPRITES,fil);
630 dfwrite(&headspritesect[0],2,MAXSECTORS+1,fil);
631 dfwrite(&prevspritesect[0],2,MAXSPRITES,fil);
632 dfwrite(&nextspritesect[0],2,MAXSPRITES,fil);
633 dfwrite(&headspritestat[0],2,MAXSTATUS+1,fil);
634 dfwrite(&prevspritestat[0],2,MAXSPRITES,fil);
635 dfwrite(&nextspritestat[0],2,MAXSPRITES,fil);
636 dfwrite(&numcyclers,sizeof(numcyclers),1,fil);
637 dfwrite(&cyclers[0][0],12,MAXCYCLERS,fil);
638 dfwrite(ps,sizeof(ps),1,fil);
639 dfwrite(po,sizeof(po),1,fil);
640 dfwrite(&numanimwalls,sizeof(numanimwalls),1,fil);
641 dfwrite(&animwall,sizeof(animwall),1,fil);
642 dfwrite(&msx[0],sizeof(int32_t),sizeof(msx)/sizeof(int32_t),fil);
643 dfwrite(&msy[0],sizeof(int32_t),sizeof(msy)/sizeof(int32_t),fil);
644 dfwrite(&spriteqloc,sizeof(short),1,fil);
645 dfwrite(&spriteqamount,sizeof(short),1,fil);
646 dfwrite(&spriteq[0],sizeof(short),spriteqamount,fil);
647 dfwrite(&mirrorcnt,sizeof(short),1,fil);
648 dfwrite(&mirrorwall[0],sizeof(short),64,fil);
649 dfwrite(&mirrorsector[0],sizeof(short),64,fil);
650 dfwrite(&show2dsector[0],sizeof(uint8_t ),MAXSECTORS>>3,fil);
651 dfwrite(&actortype[0],sizeof(uint8_t ),MAXTILES,fil);
652 dfwrite(&boardfilename[0],sizeof(boardfilename),1,fil);
653
654 dfwrite(&numclouds,sizeof(numclouds),1,fil);
655 dfwrite(&clouds[0],sizeof(short)<<7,1,fil);
656 dfwrite(&cloudx[0],sizeof(short)<<7,1,fil);
657 dfwrite(&cloudy[0],sizeof(short)<<7,1,fil);
658
659 for(i=0;i<MAXSCRIPTSIZE;i++)
660 {
661 if( (int32_t)script[i] >= (int32_t)(&script[0]) && (int32_t)script[i] < (int32_t)(&script[MAXSCRIPTSIZE]) )
662 {
663 scriptptrs[i] = 1;
664 j = (int32_t)script[i] - (int32_t)&script[0];
665 script[i] = j;
666 }
667 else scriptptrs[i] = 0;
668 }
669
670 dfwrite(&scriptptrs[0],1,MAXSCRIPTSIZE,fil);
671 dfwrite(&script[0],4,MAXSCRIPTSIZE,fil);
672
673 for(i=0;i<MAXSCRIPTSIZE;i++)
674 if( scriptptrs[i] )
675 {
676 j = script[i]+(int32_t)&script[0];
677 script[i] = j;
678 }
679
680 for(i=0;i<MAXTILES;i++)
681 if(actorscrptr[i])
682 {
683 j = (int32_t)actorscrptr[i]-(int32_t)&script[0];
684 actorscrptr[i] = (int32_t *)j;
685 }
686 dfwrite(&actorscrptr[0],4,MAXTILES,fil);
687 for(i=0;i<MAXTILES;i++)
688 if(actorscrptr[i])
689 {
690 j = (int32_t)actorscrptr[i]+(int32_t)&script[0];
691 actorscrptr[i] = (int32_t *)j;
692 }
693
694 for(i=0;i<MAXSPRITES;i++)
695 {
696 scriptptrs[i] = 0;
697
698 if(actorscrptr[PN] == 0) continue;
699
700 j = (int32_t)&script[0];
701
702 if(T2 >= j && T2 < (int32_t)(&script[MAXSCRIPTSIZE]) )
703 {
704 scriptptrs[i] |= 1;
705 T2 -= j;
706 }
707 if(T5 >= j && T5 < (int32_t)(&script[MAXSCRIPTSIZE]) )
708 {
709 scriptptrs[i] |= 2;
710 T5 -= j;
711 }
712 if(T6 >= j && T6 < (int32_t)(&script[MAXSCRIPTSIZE]) )
713 {
714 scriptptrs[i] |= 4;
715 T6 -= j;
716 }
717 }
718
719 dfwrite(&scriptptrs[0],1,MAXSPRITES,fil);
720 dfwrite(&hittype[0],sizeof(struct weaponhit),MAXSPRITES,fil);
721
722 for(i=0;i<MAXSPRITES;i++)
723 {
724 if(actorscrptr[PN] == 0) continue;
725 j = (int32_t)&script[0];
726
727 if(scriptptrs[i]&1)
728 T2 += j;
729 if(scriptptrs[i]&2)
730 T5 += j;
731 if(scriptptrs[i]&4)
732 T6 += j;
733 }
734
735 dfwrite(&lockclock,sizeof(lockclock),1,fil);
736 dfwrite(&pskybits,sizeof(pskybits),1,fil);
737 dfwrite(&pskyoff[0],sizeof(pskyoff[0]),MAXPSKYTILES,fil);
738 dfwrite(&animatecnt,sizeof(animatecnt),1,fil);
739 dfwrite(&animatesect[0],2,MAXANIMATES,fil);
740 for(i = animatecnt-1;i>=0;i--) animateptr[i] = (int32_t *)((int32_t)animateptr[i]-(int32_t)(&sector[0]));
741 dfwrite(&animateptr[0],4,MAXANIMATES,fil);
742 for(i = animatecnt-1;i>=0;i--) animateptr[i] = (int32_t *)((int32_t)animateptr[i]+(int32_t)(&sector[0]));
743 dfwrite(&animategoal[0],4,MAXANIMATES,fil);
744 dfwrite(&animatevel[0],4,MAXANIMATES,fil);
745
746 dfwrite(&earthquaketime,sizeof(earthquaketime),1,fil);
747 dfwrite(&ud.from_bonus,sizeof(ud.from_bonus),1,fil);
748 dfwrite(&ud.secretlevel,sizeof(ud.secretlevel),1,fil);
749 dfwrite(&ud.respawn_monsters,sizeof(ud.respawn_monsters),1,fil);
750 dfwrite(&ud.respawn_items,sizeof(ud.respawn_items),1,fil);
751 dfwrite(&ud.respawn_inventory,sizeof(ud.respawn_inventory),1,fil);
752 dfwrite(&ud.god,sizeof(ud.god),1,fil);
753 dfwrite(&ud.auto_run,sizeof(ud.auto_run),1,fil);
754 dfwrite(&ud.crosshair,sizeof(ud.crosshair),1,fil);
755 dfwrite(&ud.monsters_off,sizeof(ud.monsters_off),1,fil);
756 dfwrite(&ud.last_level,sizeof(ud.last_level),1,fil);
757 dfwrite(&ud.eog,sizeof(ud.eog),1,fil);
758 dfwrite(&ud.coop,sizeof(ud.coop),1,fil);
759 dfwrite(&ud.marker,sizeof(ud.marker),1,fil);
760 dfwrite(&ud.ffire,sizeof(ud.ffire),1,fil);
761 dfwrite(&camsprite,sizeof(camsprite),1,fil);
762 dfwrite(&connecthead,sizeof(connecthead),1,fil);
763 dfwrite(connectpoint2,sizeof(connectpoint2),1,fil);
764 dfwrite(&numplayersprites,sizeof(numplayersprites),1,fil);
765 dfwrite((short *)&frags[0][0],sizeof(frags),1,fil);
766
767 dfwrite(&randomseed,sizeof(randomseed),1,fil);
768 dfwrite(&global_random,sizeof(global_random),1,fil);
769 dfwrite(&parallaxyscale,sizeof(parallaxyscale),1,fil);
770
771 fclose(fil);
772
773 if(ud.multimode < 2)
774 {
775 strcpy(fta_quotes[122],"GAME SAVED");
776 FTA(122,&ps[myconnectindex],1);
777 }
778
779 ready2send = 1;
780
781 waitforeverybody();
782
783 ototalclock = totalclock;
784
785 return(0);
786}
787
788#define LMB (buttonstat&1)
789#define RMB (buttonstat&2)
790
791// FIX_00036: Mouse wheel can now be used in menu
792#define WHEELUP (buttonstat&8)
793#define WHEELDOWN (buttonstat&16)
794
795ControlInfo minfo;
796
797int probe(int x,int y,int i,int n)
798{
799 return( probeXduke(x, y, i, n, 65536L) );
800}
801
802int probeXduke(int x,int y,int i,int n, int32_t spriteSize)
803{
804 short centre;
805 int32 mouseSens;
806
807 static int32_t delay_counter_up = 0, delay_counter_down = 0, delay_up = 50, delay_down = 50;
808 static int32_t mi = 0;
809
810 // FIX_00075: Bad Sensitivity aint32_t Y axis when using mouse in menu (Thanks to Turrican)
811 mouseSens = CONTROL_GetMouseSensitivity_Y();
812 mouseSens = mouseSens ? mouseSens : 1;
813
814 if( ((ControllerType == controltype_keyboardandmouse)||
815 (ControllerType == controltype_joystickandmouse)) )
816 //&& CONTROL_MousePresent )
817 {
818 memset(&minfo, 0, sizeof(ControlInfo));
819
820 CONTROL_GetInput( &minfo );
821 //mouseY = CONTROL_GetMouseY();
822 //mi = mouseY;
823 mi += minfo.dz / mouseSens;
824 mi += minfo.dpitch / mouseSens;
825 }
826
827 else minfo.dz = minfo.dyaw = 0;
828
829 if( x == (320>>1) )
830 centre = 320>>2;
831 else centre = 0;
832
833 if( KB_KeyPressed( sc_UpArrow ) || KB_KeyPressed( sc_PgUp ) || KB_KeyPressed( sc_kpad_8 ) ||
834 (mi < -1024) || WHEELUP)
835 {
836 // FIX_00060: Repeat key function was not working in the menu
837 if(delay_counter_up==0 || (totalclock-delay_counter_up)>delay_up || (mi < -1024) || WHEELUP)
838 {
839 mi = 0;
840 sound(KICK_HIT);
841
842 probey--;
843 if(probey < 0) probey = n-1;
844 minfo.dz = 0;
845 minfo.dpitch = 0;
846 if (delay_counter_up && (totalclock-delay_counter_up)>delay_up)
847 delay_up = 10;
848 delay_counter_up = totalclock;
849 }
850 }
851 else
852 {
853 KB_ClearKeyDown( sc_UpArrow );
854 KB_ClearKeyDown( sc_kpad_8 );
855 KB_ClearKeyDown( sc_PgUp );
856 delay_counter_up = 0;
857 delay_up = 50;
858 }
859
860 if( KB_KeyPressed( sc_DownArrow ) || KB_KeyPressed( sc_PgDn ) || KB_KeyPressed( sc_kpad_2 )
861 || (mi > 1024) || WHEELDOWN )
862 {
863 if(delay_counter_down==0 || (totalclock-delay_counter_down)>delay_down || (mi > 1024) || WHEELDOWN)
864 {
865 mi = 0;
866 sound(KICK_HIT);
867 probey++;
868 minfo.dz = 0;
869 minfo.dpitch = 0;
870 if (delay_counter_down && (totalclock-delay_counter_down)>delay_down)
871 delay_down = 10;
872 delay_counter_down = totalclock;
873 }
874 }
875 else
876 {
877 KB_ClearKeyDown( sc_DownArrow );
878 KB_ClearKeyDown( sc_kpad_2 );
879 KB_ClearKeyDown( sc_PgDn );
880 delay_counter_down = 0;
881 delay_down = 50;
882 }
883
884 if(probey >= n)
885 probey = 0;
886
887 if(centre)
888 {
889// rotatesprite(((320>>1)+(centre)+54)<<16,(y+(probey*i)-4)<<16,65536L,0,SPINNINGNUKEICON+6-((6+(totalclock>>3))%7),sh,0,10,0,0,xdim-1,ydim-1);
890// rotatesprite(((320>>1)-(centre)-54)<<16,(y+(probey*i)-4)<<16,65536L,0,SPINNINGNUKEICON+((totalclock>>3)%7),sh,0,10,0,0,xdim-1,ydim-1);
891
892 rotatesprite(((320>>1)+(centre>>1)+70)<<16,(y+(probey*i)-4)<<16,spriteSize,0,SPINNINGNUKEICON+6-((6+(totalclock>>3))%7),sh,0,10,0,0,xdim-1,ydim-1);
893 rotatesprite(((320>>1)-(centre>>1)-70)<<16,(y+(probey*i)-4)<<16,spriteSize,0,SPINNINGNUKEICON+((totalclock>>3)%7),sh,0,10,0,0,xdim-1,ydim-1);
894 }
895 else
896 rotatesprite((x-tiles[BIGFNTCURSOR].dim.width-4)<<16,(y+(probey*i)-4)<<16,spriteSize,0,SPINNINGNUKEICON+(((totalclock>>3))%7),sh,0,10,0,0,xdim-1,ydim-1);
897
898 if( KB_KeyPressed(sc_Space) || KB_KeyPressed( sc_kpad_Enter ) || KB_KeyPressed( sc_Enter ) || (LMB))// && !onbar) )
899 {
900 if(current_menu != 110)
901 sound(PISTOL_BODYHIT);
902 KB_ClearKeyDown( sc_Enter );
903 KB_ClearKeyDown( sc_Space );
904 KB_ClearKeyDown( sc_kpad_Enter );
905 return(probey);
906 }
907 else if( KB_KeyPressed( sc_Escape ) || (RMB) )
908 {
909 onbar = 0;
910 KB_ClearKeyDown( sc_Escape );
911 sound(EXITMENUSOUND);
912 return(-1);
913 }
914 else
915 {
916 if(onbar == 0) return(-probey-2);
917 if ( KB_KeyPressed( sc_LeftArrow ) || KB_KeyPressed( sc_kpad_4 ) || ((buttonstat&1) && minfo.dyaw < -128 ) )
918 return(probey);
919 else if ( KB_KeyPressed( sc_RightArrow ) || KB_KeyPressed( sc_kpad_6 ) || ((buttonstat&1) && minfo.dyaw > 128 ) )
920 return(probey);
921 else return(-probey-2);
922 }
923}
924
925int menutext(int x,int y,short s,short p,char *t)
926{
927 short i, ac, centre;
928
929 y -= 12;
930
931 i = centre = 0;
932
933 if( x == (320>>1) )
934 {
935 while( *(t+i) )
936 {
937 if(*(t+i) == ' ')
938 {
939 centre += 5;
940 i++;
941 continue;
942 }
943 ac = 0;
944 if(*(t+i) >= '0' && *(t+i) <= '9')
945 ac = *(t+i) - '0' + BIGALPHANUM-10;
946 else if(*(t+i) >= 'a' && *(t+i) <= 'z')
947 ac = toupper(*(t+i)) - 'A' + BIGALPHANUM;
948 else if(*(t+i) >= 'A' && *(t+i) <= 'Z')
949 ac = *(t+i) - 'A' + BIGALPHANUM;
950 else switch(*(t+i))
951 {
952 case '-':
953 ac = BIGALPHANUM-11;
954 break;
955 case '.':
956 ac = BIGPERIOD;
957 break;
958 case '\'':
959 ac = BIGAPPOS;
960 break;
961 case ',':
962 ac = BIGCOMMA;
963 break;
964 case '!':
965 ac = BIGX;
966 break;
967 case '?':
968 ac = BIGQ;
969 break;
970 case ';':
971 ac = BIGSEMI;
972 break;
973 case ':':
974 ac = BIGSEMI;
975 break;
976 default:
977 centre += 5;
978 i++;
979 continue;
980 }
981
982 centre += tiles[ac].dim.width-1;
983 i++;
984 }
985 }
986
987 if(centre)
988 x = (320-centre-10)>>1;
989
990 while(*t)
991 {
992 if(*t == ' ') {x+=5;t++;continue;}
993 ac = 0;
994 if(*t >= '0' && *t <= '9')
995 ac = *t - '0' + BIGALPHANUM-10;
996 else if(*t >= 'a' && *t <= 'z')
997 ac = toupper(*t) - 'A' + BIGALPHANUM;
998 else if(*t >= 'A' && *t <= 'Z')
999 ac = *t - 'A' + BIGALPHANUM;
1000 else switch(*t)
1001 {
1002 case '-':
1003 ac = BIGALPHANUM-11;
1004 break;
1005 case '.':
1006 ac = BIGPERIOD;
1007 break;
1008 case ',':
1009 ac = BIGCOMMA;
1010 break;
1011 case '!':
1012 ac = BIGX;
1013 break;
1014 case '\'':
1015 ac = BIGAPPOS;
1016 break;
1017 case '?':
1018 ac = BIGQ;
1019 break;
1020 case ';':
1021 ac = BIGSEMI;
1022 break;
1023 case ':':
1024 ac = BIGCOLIN;
1025 break;
1026 default:
1027 x += 5;
1028 t++;
1029 continue;
1030 }
1031
1032 rotatesprite(x<<16,y<<16,65536L,0,ac,s,p,10+16,0,0,xdim-1,ydim-1);
1033
1034 x += tiles[ac].dim.width;
1035 t++;
1036 }
1037 return (x);
1038}
1039
1040int menutextc(int x,int y,short s,short p,char *t)
1041{
1042 short i, ac, centre;
1043
1044 s += 8;
1045 y -= 12;
1046
1047 i = centre = 0;
1048
1049// if( x == (320>>1) )
1050 {
1051 while( *(t+i) )
1052 {
1053 if(*(t+i) == ' ')
1054 {
1055 centre += 5;
1056 i++;
1057 continue;
1058 }
1059 ac = 0;
1060 if(*(t+i) >= '0' && *(t+i) <= '9')
1061 ac = *(t+i) - '0' + BIGALPHANUM+26+26;
1062 if(*(t+i) >= 'a' && *(t+i) <= 'z')
1063 ac = *(t+i) - 'a' + BIGALPHANUM+26;
1064 if(*(t+i) >= 'A' && *(t+i) <= 'Z')
1065 ac = *(t+i) - 'A' + BIGALPHANUM;
1066
1067 else switch(*t)
1068 {
1069 case '-':
1070 ac = BIGALPHANUM-11;
1071 break;
1072 case '.':
1073 ac = BIGPERIOD;
1074 break;
1075 case ',':
1076 ac = BIGCOMMA;
1077 break;
1078 case '!':
1079 ac = BIGX;
1080 break;
1081 case '?':
1082 ac = BIGQ;
1083 break;
1084 case ';':
1085 ac = BIGSEMI;
1086 break;
1087 case ':':
1088 ac = BIGCOLIN;
1089 break;
1090 }
1091
1092 centre += tiles[ac].dim.width-1;
1093 i++;
1094 }
1095 }
1096
1097 x -= centre>>1;
1098
1099 while(*t)
1100 {
1101 if(*t == ' ') {x+=5;t++;continue;}
1102 ac = 0;
1103 if(*t >= '0' && *t <= '9')
1104 ac = *t - '0' + BIGALPHANUM+26+26;
1105 if(*t >= 'a' && *t <= 'z')
1106 ac = *t - 'a' + BIGALPHANUM+26;
1107 if(*t >= 'A' && *t <= 'Z')
1108 ac = *t - 'A' + BIGALPHANUM;
1109 switch(*t)
1110 {
1111 case '-':
1112 ac = BIGALPHANUM-11;
1113 break;
1114 case '.':
1115 ac = BIGPERIOD;
1116 break;
1117 case ',':
1118 ac = BIGCOMMA;
1119 break;
1120 case '!':
1121 ac = BIGX;
1122 break;
1123 case '?':
1124 ac = BIGQ;
1125 break;
1126 case ';':
1127 ac = BIGSEMI;
1128 break;
1129 case ':':
1130 ac = BIGCOLIN;
1131 break;
1132 }
1133
1134 rotatesprite(x<<16,y<<16,65536L,0,ac,s,p,10+16,0,0,xdim-1,ydim-1);
1135
1136 x += tiles[ac].dim.width;
1137 t++;
1138 }
1139 return (x);
1140}
1141
1142
1143void bar(int x,int y,short *p,short dainc,uint8_t damodify,short s, short pa)
1144{
1145 short xloc;
1146 uint8_t rev;
1147
1148 if(dainc < 0) { dainc = -dainc; rev = 1; }
1149 else rev = 0;
1150 y-=2;
1151
1152 if(damodify)
1153 {
1154 if(rev == 0)
1155 {
1156 if( KB_KeyPressed( sc_LeftArrow ) || KB_KeyPressed( sc_kpad_4 ) || ((buttonstat&1) && minfo.dyaw < -256 ) ) // && onbar) )
1157 {
1158 KB_ClearKeyDown( sc_LeftArrow );
1159 KB_ClearKeyDown( sc_kpad_4 );
1160
1161 *p -= dainc;
1162 if(*p < 0)
1163 *p = 0;
1164 sound(KICK_HIT);
1165 }
1166 if( KB_KeyPressed( sc_RightArrow ) || KB_KeyPressed( sc_kpad_6 ) || ((buttonstat&1) && minfo.dyaw > 256 ) )//&& onbar) )
1167 {
1168 KB_ClearKeyDown( sc_RightArrow );
1169 KB_ClearKeyDown( sc_kpad_6 );
1170
1171 *p += dainc;
1172 if(*p > 63)
1173 *p = 63;
1174 sound(KICK_HIT);
1175 }
1176 }
1177 else
1178 {
1179 if( KB_KeyPressed( sc_RightArrow ) || KB_KeyPressed( sc_kpad_6 ) || ((buttonstat&1) && minfo.dyaw > 256 ))//&& onbar ))
1180 {
1181 KB_ClearKeyDown( sc_RightArrow );
1182 KB_ClearKeyDown( sc_kpad_6 );
1183
1184 *p -= dainc;
1185 if(*p < 0)
1186 *p = 0;
1187 sound(KICK_HIT);
1188 }
1189 if( KB_KeyPressed( sc_LeftArrow ) || KB_KeyPressed( sc_kpad_4 ) || ((buttonstat&1) && minfo.dyaw < -256 ))// && onbar) )
1190 {
1191 KB_ClearKeyDown( sc_LeftArrow );
1192 KB_ClearKeyDown( sc_kpad_4 );
1193
1194 *p += dainc;
1195 if(*p > 64)
1196 *p = 64;
1197 sound(KICK_HIT);
1198 }
1199 }
1200 }
1201
1202 xloc = *p;
1203
1204 rotatesprite( (x+22)<<16,(y-3)<<16,65536L,0,SLIDEBAR,s,pa,10,0,0,xdim-1,ydim-1);
1205 if(rev == 0)
1206 rotatesprite( (x+xloc+1)<<16,(y+1)<<16,65536L,0,SLIDEBAR+1,s,pa,10,0,0,xdim-1,ydim-1);
1207 else
1208 rotatesprite( (x+(65-xloc) )<<16,(y+1)<<16,65536L,0,SLIDEBAR+1,s,pa,10,0,0,xdim-1,ydim-1);
1209}
1210
1211#define SHX(X) 0
1212// ((x==X)*(-sh))
1213#define PHX(X) 0
1214// ((x==X)?1:2)
1215#define MWIN(X) rotatesprite( 320<<15,200<<15,X,0,MENUSCREEN,-16,0,10+64,0,0,xdim-1,ydim-1)
1216#define MWINXY(X,OX,OY) rotatesprite( ( 320+(OX) )<<15, ( 200+(OY) )<<15,X,0,MENUSCREEN,-16,0,10+64,0,0,xdim-1,ydim-1)
1217
1218
1219int32 volnum,levnum,plrskl,numplr;
1220short lastsavedpos = -1;
1221
1222void dispnames(void)
1223{
1224 short x, c = 160;
1225
1226 c += 64;
1227 for(x = 0;x <= 108;x += 12)
1228 rotatesprite((c+91-64)<<16,(x+56)<<16,65536L,0,TEXTBOX,24,0,10,0,0,xdim-1,ydim-1);
1229
1230 rotatesprite(22<<16,97<<16,65536L,0,WINDOWBORDER2,24,0,10,0,0,xdim-1,ydim-1);
1231 rotatesprite(180<<16,97<<16,65536L,1024,WINDOWBORDER2,24,0,10,0,0,xdim-1,ydim-1);
1232 rotatesprite(99<<16,50<<16,65536L,512,WINDOWBORDER1,24,0,10,0,0,xdim-1,ydim-1);
1233 rotatesprite(103<<16,144<<16,65536L,1024+512,WINDOWBORDER1,24,0,10,0,0,xdim-1,ydim-1);
1234
1235 minitext(c,48,ud.savegame[0],2,10+16);
1236 minitext(c,48+12,ud.savegame[1],2,10+16);
1237 minitext(c,48+12+12,ud.savegame[2],2,10+16);
1238 minitext(c,48+12+12+12,ud.savegame[3],2,10+16);
1239 minitext(c,48+12+12+12+12,ud.savegame[4],2,10+16);
1240 minitext(c,48+12+12+12+12+12,ud.savegame[5],2,10+16);
1241 minitext(c,48+12+12+12+12+12+12,ud.savegame[6],2,10+16);
1242 minitext(c,48+12+12+12+12+12+12+12,ud.savegame[7],2,10+16);
1243 minitext(c,48+12+12+12+12+12+12+12+12,ud.savegame[8],2,10+16);
1244 minitext(c,48+12+12+12+12+12+12+12+12+12,ud.savegame[9],2,10+16);
1245
1246}
1247
Franklin Weia855d622017-01-21 15:18:31 -05001248int getfilenames(char kind[6])
1249{
Franklin Weia855d622017-01-21 15:18:31 -05001250 DIR *dir;
1251 struct dirent *dent;
Franklin Weia855d622017-01-21 15:18:31 -05001252 int add_this;
1253 uint8_t *ptr = NULL;
1254 int len = 0;
1255 int subdirs = 0;
1256
1257 if (strcmp(kind,"SUBD") == 0)
1258 subdirs = 1;
1259
Vencislav Atanasov183e45e2019-07-28 23:31:50 +03001260 dir = opendir(getGameDir());
Franklin Weia855d622017-01-21 15:18:31 -05001261 if (dir == NULL)
1262 return(-1);
1263
1264 do
1265 {
1266 add_this = 0;
1267 dent = readdir(dir);
1268 if (dent != NULL)
1269 {
Vencislav Atanasov183e45e2019-07-28 23:31:50 +03001270 if (subdirs)
1271 {
1272 if (rb->dir_exists(dent->d_name))
1273 add_this = 1;
1274 } /* if */
1275 else
1276 {
1277 /* need to expand support if this assertion ever fails. */
1278 assert(stricmp(kind, "*.MAP") == 0);
1279 len = strlen(dent->d_name);
1280 if (len >= 5)
1281 {
1282 ptr = ((uint8_t *) dent->d_name) + len;
1283 ptr += strlen(ptr) - 4;
1284 if (stricmp(ptr, ".MAP") == 0)
1285 add_this = 1;
1286 } /* if */
1287 } /* else */
Franklin Weia855d622017-01-21 15:18:31 -05001288
Vencislav Atanasov183e45e2019-07-28 23:31:50 +03001289 if (add_this)
1290 {
1291 strcpy(menuname[menunamecnt],dent->d_name);
1292 menuname[menunamecnt][16] = subdirs;
1293 menunamecnt++;
1294 } /* if */
Franklin Weia855d622017-01-21 15:18:31 -05001295 } /* if */
1296 } while (dent != NULL);
1297
1298 closedir(dir);
1299
Franklin Weia855d622017-01-21 15:18:31 -05001300 return(0);
1301}
1302
Franklin Weia855d622017-01-21 15:18:31 -05001303void sortfilenames()
1304{
1305 uint8_t sortbuffer[17];
1306 int32_t i, j, k;
1307
1308 for(i=1;i<menunamecnt;i++)
1309 for(j=0;j<i;j++)
1310 {
1311 k = 0;
1312 while ((menuname[i][k] == menuname[j][k]) && (menuname[i][k] != 0) && (menuname[j][k] != 0))
1313 k++;
1314 if (menuname[i][k] < menuname[j][k])
1315 {
1316 memcpy(&sortbuffer[0],&menuname[i][0],sizeof(menuname[0]));
1317 memcpy(&menuname[i][0],&menuname[j][0],sizeof(menuname[0]));
1318 memcpy(&menuname[j][0],&sortbuffer[0],sizeof(menuname[0]));
1319 }
1320 }
1321}
1322
1323int32_t quittimer = 0;
1324
1325void gameexitanycase(void)
1326{
1327 KB_FlushKeyboardQueue();
1328
1329 if( gamequit == 0 && ( numplayers > 1 ) )
1330 {
1331 if(ps[myconnectindex].gm&MODE_GAME)
1332 {
1333 gamequit = 1;
1334 quittimer = totalclock+120;
1335 sound(SHORT_CIRCUIT);
1336 }
1337 else
1338 {
1339 sendlogoff();
1340 gameexit(" ");
1341 sound(NITEVISION_ONOFF);
1342 }
1343 }
1344 else if( numplayers < 2 )
1345 gameexit(" ");
1346
1347 if( ( totalclock > quittimer ) && ( gamequit == 1) )
1348 {
1349 gameexit("Timed out.");
1350 }
1351}
1352
1353
1354void menus(void)
1355{
1356 short c,x;
1357 volatile int32_t l;
1358 int i,j;
1359
1360 static int lastkeysetup = 0;
1361 static int waiting4key = false;
1362 static int current_resolution = 0;
1363 char text[512];
1364
1365 getpackets();
1366
1367 if(((ControllerType == controltype_keyboardandmouse)||
1368 (ControllerType == controltype_joystickandmouse))
1369 //&& CONTROL_MousePresent
1370 )
1371 {
1372
1373 if(buttonstat != 0 && !onbar) // anti-repeat
1374 {
1375 x = MOUSE_GetButtons()<<3;
1376 if( x )
1377 {
1378 buttonstat = x<<3;
1379 }
1380 else
1381 {
1382 buttonstat = 0;
1383 }
1384 }
1385 else
1386
1387 buttonstat = MOUSE_GetButtons();
1388 }
1389 else buttonstat = 0;
1390
1391 if( (ps[myconnectindex].gm&MODE_MENU) == 0 )
1392 {
1393 tiles[MAXTILES-3].lock = 1;
1394 return;
1395 }
1396
1397 ps[myconnectindex].gm &= (0xff-MODE_TYPE);
1398 ps[myconnectindex].fta = 0;
1399
1400 x = 0;
1401
1402 sh = 4-(sintable[(totalclock<<4)&2047]>>11);
1403
1404 if(!(current_menu >= 1000 && current_menu <= 2999 && current_menu >= 300 && current_menu <= 369))
1405 vscrn();
1406
1407 // printf("Current menu=%d, game mode=%d, last menu =%d\n", current_menu, ps[myconnectindex].gm, last_menu);
1408
1409 switch(current_menu)
1410 {
1411 case 25000:
1412 gametext(160,90,"SELECT A SAVE SPOT BEFORE",0,2+8+16);
1413 gametext(160,90+9,"YOU QUICK RESTORE.",0,2+8+16);
1414
1415 x = probe(186,124,0,0);
1416 if(x >= -1)
1417 {
1418 if(ud.multimode < 2 && ud.recstat != 2)
1419 {
1420 ready2send = 1;
1421 totalclock = ototalclock;
1422 }
1423 ps[myconnectindex].gm &= ~MODE_MENU;
1424 }
1425 break;
1426
1427 case 20000:
1428 x = probe(326,190,0,0);
1429 gametext(160,50-8,"YOU ARE PLAYING THE SHAREWARE",0,2+8+16);
1430 gametext(160,59-8,"VERSION OF DUKE NUKEM 3D. WHILE",0,2+8+16);
1431 gametext(160,68-8,"THIS VERSION IS REALLY COOL, YOU",0,2+8+16);
1432 gametext(160,77-8,"ARE MISSING OVER 75% OF THE TOTAL",0,2+8+16);
1433 gametext(160,86-8,"GAME, ALONG WITH OTHER GREAT EXTRAS",0,2+8+16);
1434 gametext(160,95-8,"AND GAMES, WHICH YOU'LL GET WHEN",0,2+8+16);
1435 gametext(160,104-8,"YOU ORDER THE COMPLETE VERSION AND",0,2+8+16);
1436 gametext(160,113-8,"GET THE FINAL TWO EPISODES.",0,2+8+16);
1437
1438 gametext(160,113+8,"PLEASE READ THE 'HOW TO ORDER' ITEM",0,2+8+16);
1439 gametext(160,122+8,"ON THE MAIN MENU IF YOU WISH TO",0,2+8+16);
1440 gametext(160,131+8,"UPGRADE TO THE FULL REGISTERED",0,2+8+16);
1441 gametext(160,140+8,"VERSION OF DUKE NUKEM 3D.",0,2+8+16);
1442 gametext(160,149+16,"PRESS ANY KEY...",0,2+8+16);
1443
1444 if( x >= -1 ) cmenu(100);
1445 break;
1446
1447
1448 case 15001:
1449 case 15000:
1450
1451 gametext(160,90,"LOAD last game:",0,2+8+16);
1452
1453 sprintf(text,"\"%s\"",ud.savegame[lastsavedpos]);
1454 gametext(160,99,text,0,2+8+16);
1455
1456 gametext(160,99+9,"(Y/N)",0,2+8+16);
1457
1458 _handle_events();
1459 if( KB_KeyPressed(sc_Escape) || KB_KeyPressed(sc_N) || RMB)
1460 {
1461 if(sprite[ps[myconnectindex].i].extra <= 0)
1462 {
1463 enterlevel(MODE_GAME);
1464 return;
1465 }
1466
1467 KB_ClearKeyDown(sc_N);
1468 KB_ClearKeyDown(sc_Escape);
1469
1470 ps[myconnectindex].gm &= ~MODE_MENU;
1471 if(ud.multimode < 2 && ud.recstat != 2)
1472 {
1473 ready2send = 1;
1474 totalclock = ototalclock;
1475 }
1476 }
1477
1478 if( KB_KeyPressed(sc_Space) || KB_KeyPressed(sc_Enter) || KB_KeyPressed(sc_kpad_Enter) || KB_KeyPressed(sc_Y) || LMB )
1479 {
1480 KB_FlushKeyboardQueue();
1481 FX_StopAllSounds();
1482
1483 if(ud.multimode > 1)
1484 {
1485 loadplayer(-1-lastsavedpos);
1486 ps[myconnectindex].gm = MODE_GAME;
1487 }
1488 else
1489 {
1490 c = loadplayer(lastsavedpos);
1491 if(c == 0)
1492 ps[myconnectindex].gm = MODE_GAME;
1493 }
1494 }
1495
1496 probe(186,124+9,0,0);
1497
1498 break;
1499
1500 case 10000: // parental
1501 case 10001:
1502
1503 c = (320>>1)-120;
1504 rotatesprite(320<<15,19<<16,65536L,0,MENUBAR,16,0,10,0,0,xdim-1,ydim-1);
1505 menutext(320>>1,24,0,0,"ADULT MODE");
1506
1507 x = probe(c+6,43,16,2);
1508
1509 if(x == -1)
1510 {
1511 cmenu(702);
1512 probey = 6;
1513 break;
1514 }
1515
1516 menutext(c,43,SHX(-2),PHX(-2),"ADULT MODE");
1517 menutext(c+160+40,43,0,0,ud.lockout?"OFF":"ON");
1518
1519 menutext(c,43+16,SHX(-3),PHX(-3),"ENTER PASSWORD");
1520
1521 if(current_menu == 10001)
1522 {
1523 gametext(160,43+16+16+16-12,"ENTER PASSWORD",0,2+8+16);
1524 x = strget((320>>1),43+16+16+16,buf,19, 998);
1525
1526 if(x == 1) // user hit enter key
1527 {
1528 if(ud.pwlockout[0] == 0 || ud.lockout == 0 ) // if already unlocked then we set pwd or reset pwd is there is already one
1529 strcpy(&ud.pwlockout[0],buf);
1530 else if( strcmp(buf,&ud.pwlockout[0]) == 0 ) // if (pwd was up AND lockout is true (locked) AND pwd is good)
1531 {
1532 ud.lockout = 0;
1533 buf[0] = 0;
1534
1535 for(x=0;x<numanimwalls;x++)
1536 if( wall[animwall[x].wallnum].picnum != W_SCREENBREAK &&
1537 wall[animwall[x].wallnum].picnum != W_SCREENBREAK+1 &&
1538 wall[animwall[x].wallnum].picnum != W_SCREENBREAK+2 )
1539 if( wall[animwall[x].wallnum].extra >= 0 )
1540 wall[animwall[x].wallnum].picnum = wall[animwall[x].wallnum].extra;
1541
1542 }
1543 current_menu = 10000;
1544 KB_ClearKeyDown(sc_Enter);
1545 KB_ClearKeyDown(sc_kpad_Enter);
1546 KB_FlushKeyboardQueue();
1547 }
1548 else if(x==-1) // pressed esc while typing. We discard the text.
1549 {
1550 *buf = 0;
1551 current_menu = 10000;
1552 KB_ClearKeyDown(sc_Escape);
1553 }
1554 }
1555 else
1556 {
1557 if(x == 0)
1558 {
1559 if( ud.lockout == 1 )
1560 {
1561 if(ud.pwlockout[0] == 0)
1562 {
1563 ud.lockout = 0;
1564 for(x=0;x<numanimwalls;x++)
1565 if( wall[animwall[x].wallnum].picnum != W_SCREENBREAK &&
1566 wall[animwall[x].wallnum].picnum != W_SCREENBREAK+1 &&
1567 wall[animwall[x].wallnum].picnum != W_SCREENBREAK+2 )
1568 if( wall[animwall[x].wallnum].extra >= 0 )
1569 wall[animwall[x].wallnum].picnum = wall[animwall[x].wallnum].extra;
1570 }
1571 else
1572 {
1573 buf[0] = 0;
1574 current_menu = 10001;
1575 inputloc = 0;
1576 KB_FlushKeyboardQueue();
1577 }
1578 }
1579 else
1580 {
1581 ud.lockout = 1;
1582
1583 for(x=0;x<numanimwalls;x++)
1584 switch(wall[animwall[x].wallnum].picnum)
1585 {
1586 case FEMPIC1:
1587 wall[animwall[x].wallnum].picnum = BLANKSCREEN;
1588 break;
1589 case FEMPIC2:
1590 case FEMPIC3:
1591 wall[animwall[x].wallnum].picnum = SCREENBREAK6;
1592 break;
1593 }
1594 }
1595 }
1596
1597 else if(x == 1)
1598 {
1599 current_menu = 10001; // ask for password change
1600 inputloc = 0;
1601 *buf = 0;
1602 KB_FlushKeyboardQueue();
1603 }
1604 }
1605
1606 break;
1607
1608 case 1000:
1609 case 1001:
1610 case 1002:
1611 case 1003:
1612 case 1004:
1613 case 1005:
1614 case 1006:
1615 case 1007:
1616 case 1008:
1617 case 1009:
1618
1619 rotatesprite(160<<16,200<<15,65536L,0,MENUSCREEN,16,0,10+64,0,0,xdim-1,ydim-1);
1620 rotatesprite(160<<16,19<<16,65536L,0,MENUBAR,16,0,10,0,0,xdim-1,ydim-1);
1621 menutext(160,24,0,0,"LOAD GAME");
1622 rotatesprite(101<<16,97<<16,65536,512,MAXTILES-3,-32,0,4+10+64,0,0,xdim-1,ydim-1);
1623
1624 dispnames();
1625
1626 sprintf((char*)tempbuf,"PLAYERS: %-2d ",numplr);
1627 gametext(160,158,(char*)tempbuf,0,2+8+16);
1628
1629 sprintf((char*)tempbuf,"EPISODE: %-2d / LEVEL: %-2d / SKILL: %-2d",1+volnum,1+levnum,plrskl);
1630 gametext(160,170,(char*)tempbuf,0,2+8+16);
1631
1632 gametext(160,90,"LOAD game:",0,2+8+16);
1633 sprintf((char*)tempbuf,"\"%s\"",ud.savegame[current_menu-1000]);
1634 gametext(160,99,(char*)tempbuf,0,2+8+16);
1635 gametext(160,99+9,"(Y/N)",0,2+8+16);
1636
1637 _handle_events();
1638 if( KB_KeyPressed(sc_Space) || KB_KeyPressed(sc_Enter) || KB_KeyPressed(sc_kpad_Enter) || KB_KeyPressed(sc_Y) || LMB )
1639 {
1640 lastsavedpos = current_menu-1000;
1641
1642 KB_FlushKeyboardQueue();
1643 //if(ud.multimode < 2 && ud.recstat != 2)
1644 //{
1645 // ready2send = 1;
1646 // totalclock = ototalclock;
1647 //}
1648
1649 if(ud.multimode > 1)
1650 {
1651 if( ps[myconnectindex].gm&MODE_GAME )
1652 {
1653 loadplayer(-1-lastsavedpos);
1654 ps[myconnectindex].gm = MODE_GAME;
1655 }
1656 else
1657 {
1658 tempbuf[0] = 126;
1659 tempbuf[1] = lastsavedpos;
1660 for(x=connecthead;x>=0;x=connectpoint2[x])
1661 if(x != myconnectindex)
1662 sendpacket(x,(uint8_t*)tempbuf,2);
1663
1664 getpackets();
1665
1666 loadplayer(lastsavedpos);
1667
1668 multiflag = 0;
1669 }
1670 }
1671 else
1672 {
1673 // FIX_00084: Various bugs in the load game (single player) option if ESC is hit or if wrong version
1674
1675 c = loadplayer(lastsavedpos);
1676 if(c == 0)
1677 {
1678 ps[myconnectindex].gm = MODE_GAME;
1679 if (ud.recstat != 2) // if not playing a demo then ..
1680 totalclock = ototalclock;
1681 }
1682 else
1683 cmenu(1010); // failed loading game
1684 }
1685
1686 break;
1687 }
1688
1689 if( KB_KeyPressed(sc_N) || KB_KeyPressed(sc_Escape) || RMB)
1690 {
1691 KB_ClearKeyDown(sc_N);
1692 KB_ClearKeyDown(sc_Escape);
1693 sound(EXITMENUSOUND);
1694 cmenu(300);
1695 // FIX_00084: Various bugs in the load game (single player) option if ESC is hit or if wrong version
1696 // simply get back w/o changing anything.
1697
1698 }
1699
1700 break;
1701
1702 case 1010: //loading a saved game failed
1703
1704 gametext(160,99,"YOU CAN'T LOAD THIS GAME",0,2+8+16);
1705 gametext(160,99+9,"EITHER A WONG VERSION",0,2+8+16);
1706 gametext(160,99+9+9,"OR BAD # OF PLAYERS OR...",0,2+8+16);
1707
1708 _handle_events();
1709 if( KB_KeyPressed(sc_Space) || KB_KeyPressed(sc_Escape) || KB_KeyPressed(sc_Enter)
1710 || RMB) {
1711 KB_ClearKeyDown(sc_Space);
1712 KB_ClearKeyDown(sc_Escape);
1713 KB_ClearKeyDown(sc_Enter);
1714 sound(EXITMENUSOUND);
1715 cmenu(300);
1716 }
1717
1718 break;
1719
1720 case 1500:
1721 _handle_events();
1722 if( KB_KeyPressed(sc_Space) || KB_KeyPressed(sc_Enter) || KB_KeyPressed(sc_kpad_Enter) || KB_KeyPressed(sc_Y) || LMB )
1723 {
1724 KB_FlushKeyboardQueue();
1725 cmenu(100);
1726 }
1727 if( KB_KeyPressed(sc_N) || KB_KeyPressed(sc_Escape) || RMB)
1728 {
1729 KB_ClearKeyDown(sc_N);
1730 KB_ClearKeyDown(sc_Escape);
1731 if(ud.multimode < 2 && ud.recstat != 2)
1732 {
1733 ready2send = 1;
1734 totalclock = ototalclock;
1735 }
1736 ps[myconnectindex].gm &= ~MODE_MENU;
1737 sound(EXITMENUSOUND);
1738 break;
1739 }
1740 probe(186,124,0,0);
1741 gametext(160,90,"ABORT this game?",0,2+8+16);
1742 gametext(160,90+9,"(Y/N)",0,2+8+16);
1743
1744 break;
1745
1746 case 2000:
1747 case 2001:
1748 case 2002:
1749 case 2003:
1750 case 2004:
1751 case 2005:
1752 case 2006:
1753 case 2007:
1754 case 2008:
1755 case 2009:
1756
1757 rotatesprite(160<<16,200<<15,65536L,0,MENUSCREEN,16,0,10+64,0,0,xdim-1,ydim-1);
1758 rotatesprite(160<<16,19<<16,65536L,0,MENUBAR,16,0,10,0,0,xdim-1,ydim-1);
1759 menutext(160,24,0,0,"SAVE GAME");
1760
1761 rotatesprite(101<<16,97<<16,65536L,512,MAXTILES-3,-32,0,4+10+64,0,0,xdim-1,ydim-1);
1762 sprintf(text,"PLAYERS: %-2d ",ud.multimode);
1763 gametext(160,158,text,0,2+8+16);
1764
1765 sprintf(text,"EPISODE: %-2d / LEVEL: %-2d / SKILL: %-2d",1+ud.volume_number,1+ud.level_number,ud.player_skill);
1766 gametext(160,170,text,0,2+8+16);
1767
1768 dispnames();
1769
1770 gametext(160,90,"OVERWRITE previous SAVED game?",0,2+8+16);
1771 gametext(160,90+9,"(Y/N)",0,2+8+16);
1772
1773 _handle_events();
1774 if( KB_KeyPressed(sc_Space) || KB_KeyPressed(sc_Enter) || KB_KeyPressed(sc_kpad_Enter) || KB_KeyPressed(sc_Y) || LMB )
1775 {
1776 KB_FlushKeyboardQueue();
1777 inputloc = strlen(&ud.savegame[current_menu-2000][0]);
1778
1779 cmenu(current_menu-2000+360);
1780
1781 KB_FlushKeyboardQueue();
1782 break;
1783 }
1784 if( KB_KeyPressed(sc_N) || KB_KeyPressed(sc_Escape) || RMB)
1785 {
1786 KB_ClearKeyDown(sc_N);
1787 KB_ClearKeyDown(sc_Escape);
1788 cmenu(351);
1789 sound(EXITMENUSOUND);
1790 }
1791
1792 probe(186,124,0,0);
1793
1794 break;
1795
1796 case 990: // credits
1797 case 991:
1798 case 992:
1799 case 993:
1800 case 994:
1801 case 995:
1802 case 996:
1803 case 997:
1804 c = 160;
1805 if (!PLUTOPAK) {
1806 //rotatesprite(c<<16,200<<15,65536L,0,MENUSCREEN,16,0,10+64,0,0,xdim-1,ydim-1);
1807 rotatesprite(c<<16,19<<16,65536L,0,MENUBAR,16,0,10,0,0,xdim-1,ydim-1);
1808 menutext(c,24,0,0,"CREDITS");
1809
1810 l = 7;
1811 } else {
1812 l = 2;
1813 }
1814
1815 if(KB_KeyPressed(sc_Escape)) { cmenu(0); break; }
1816
1817 if( KB_KeyPressed( sc_LeftArrow ) ||
1818 KB_KeyPressed( sc_kpad_4 ) ||
1819 KB_KeyPressed( sc_UpArrow ) ||
1820 KB_KeyPressed( sc_PgUp ) ||
1821 KB_KeyPressed( sc_kpad_8 ) )
1822 {
1823 KB_ClearKeyDown(sc_LeftArrow);
1824 KB_ClearKeyDown(sc_kpad_4);
1825 KB_ClearKeyDown(sc_UpArrow);
1826 KB_ClearKeyDown(sc_PgUp);
1827 KB_ClearKeyDown(sc_kpad_8);
1828
1829 sound(KICK_HIT);
1830 current_menu--;
1831 if(current_menu < 990) current_menu = 990+l;
1832 }
1833 else if(
1834 KB_KeyPressed( sc_PgDn ) ||
1835 KB_KeyPressed( sc_Enter ) ||
1836 KB_KeyPressed( sc_Space ) ||
1837 KB_KeyPressed( sc_kpad_Enter ) ||
1838 KB_KeyPressed( sc_RightArrow ) ||
1839 KB_KeyPressed( sc_DownArrow ) ||
1840 KB_KeyPressed( sc_kpad_2 ) ||
1841 KB_KeyPressed( sc_kpad_9 ) ||
1842 KB_KeyPressed( sc_kpad_6 ) )
1843 {
1844 KB_ClearKeyDown(sc_PgDn);
1845 KB_ClearKeyDown(sc_Enter);
1846 KB_ClearKeyDown(sc_RightArrow);
1847 KB_ClearKeyDown(sc_kpad_Enter);
1848 KB_ClearKeyDown(sc_kpad_6);
1849 KB_ClearKeyDown(sc_kpad_9);
1850 KB_ClearKeyDown(sc_kpad_2);
1851 KB_ClearKeyDown(sc_DownArrow);
1852 KB_ClearKeyDown(sc_Space);
1853 sound(KICK_HIT);
1854 current_menu++;
1855 if(current_menu > 990+l) current_menu = 990;
1856 }
1857
1858 if (!PLUTOPAK) { // This is Jonathon Fowler code. Text respects the true 1.3/1.3d --mk
1859 switch (current_menu) {
1860 case 990:
1861 gametext(c,40, "ORIGINAL CONCEPT",0,2+8+16);
1862 gametext(c,40+9, "TODD REPLOGLE",0,2+8+16);
1863 gametext(c,40+9+9, "ALLEN H. BLUM III",0,2+8+16);
1864
1865 gametext(c,40+9+9+9+9, "PRODUCED & DIRECTED BY",0,2+8+16);
1866 gametext(c,40+9+9+9+9+9, "GREG MALONE",0,2+8+16);
1867
1868 gametext(c,40+9+9+9+9+9+9+9, "EXECUTIVE PRODUCER",0,2+8+16);
1869 gametext(c,40+9+9+9+9+9+9+9+9, "GEORGE BROUSSARD",0,2+8+16);
1870
1871 gametext(c,40+9+9+9+9+9+9+9+9+9+9, "BUILD ENGINE",0,2+8+16);
1872 gametext(c,40+9+9+9+9+9+9+9+9+9+9+9,"KEN SILVERMAN",0,2+8+16);
1873 break;
1874 case 991:
1875 gametext(c,40, "GAME PROGRAMMING",0,2+8+16);
1876 gametext(c,40+9, "TODD REPLOGLE",0,2+8+16);
1877
1878 gametext(c,40+9+9+9, "3D ENGINE/TOOLS/NET",0,2+8+16);
1879 gametext(c,40+9+9+9+9, "KEN SILVERMAN",0,2+8+16);
1880
1881 gametext(c,40+9+9+9+9+9+9, "NETWORK LAYER/SETUP PROGRAM",0,2+8+16);
1882 gametext(c,40+9+9+9+9+9+9+9, "MARK DOCHTERMANN",0,2+8+16);
1883 break;
1884 case 992:
1885 gametext(c,40, "MAP DESIGN",0,2+8+16);
1886 gametext(c,40+9, "ALLEN H BLUM III",0,2+8+16);
1887 gametext(c,40+9+9, "RICHARD GRAY",0,2+8+16);
1888
1889 gametext(c,40+9+9+9+9, "3D MODELING",0,2+8+16);
1890 gametext(c,40+9+9+9+9+9, "CHUCK JONES",0,2+8+16);
1891 gametext(c,40+9+9+9+9+9+9, "SAPPHIRE CORPORATION",0,2+8+16);
1892
1893 gametext(c,40+9+9+9+9+9+9+9+9, "ARTWORK",0,2+8+16);
1894 gametext(c,40+9+9+9+9+9+9+9+9+9, "DIRK JONES, STEPHEN HORNBACK",0,2+8+16);
1895 gametext(c,40+9+9+9+9+9+9+9+9+9+9, "JAMES STOREY, DAVID DEMARET",0,2+8+16);
1896 gametext(c,40+9+9+9+9+9+9+9+9+9+9+9,"DOUGLAS R WOOD",0,2+8+16);
1897 break;
1898 case 993:
1899 gametext(c,40, "SOUND ENGINE",0,2+8+16);
1900 gametext(c,40+9, "JIM DOSE",0,2+8+16);
1901
1902 gametext(c,40+9+9+9, "SOUND & MUSIC DEVELOPMENT",0,2+8+16);
1903 gametext(c,40+9+9+9+9, "ROBERT PRINCE",0,2+8+16);
1904 gametext(c,40+9+9+9+9+9, "LEE JACKSON",0,2+8+16);
1905
1906 gametext(c,40+9+9+9+9+9+9+9, "VOICE TALENT",0,2+8+16);
1907 gametext(c,40+9+9+9+9+9+9+9+9, "LANI MINELLA - VOICE PRODUCER",0,2+8+16);
1908 gametext(c,40+9+9+9+9+9+9+9+9+9, "JON ST. JOHN AS \"DUKE NUKEM\"",0,2+8+16);
1909 break;
1910 case 994:
1911 gametext(c,60, "GRAPHIC DESIGN",0,2+8+16);
1912 gametext(c,60+9, "PACKAGING, MANUAL, ADS",0,2+8+16);
1913 gametext(c,60+9+9, "ROBERT M. ATKINS",0,2+8+16);
1914 gametext(c,60+9+9+9, "MICHAEL HADWIN",0,2+8+16);
1915
1916 gametext(c,60+9+9+9+9+9, "SPECIAL THANKS TO",0,2+8+16);
1917 gametext(c,60+9+9+9+9+9+9, "STEVEN BLACKBURN, TOM HALL",0,2+8+16);
1918 gametext(c,60+9+9+9+9+9+9+9, "SCOTT MILLER, JOE SIEGLER",0,2+8+16);
1919 gametext(c,60+9+9+9+9+9+9+9+9, "TERRY NAGY, COLLEEN COMPTON",0,2+8+16);
1920 gametext(c,60+9+9+9+9+9+9+9+9+9, "HASH INC., FORMGEN, INC.",0,2+8+16);
1921 break;
1922 case 995:
1923 gametext(c,49, "THE 3D REALMS BETA TESTERS",0,2+8+16);
1924
1925 gametext(c,49+9+9, "NATHAN ANDERSON, WAYNE BENNER",0,2+8+16);
1926 gametext(c,49+9+9+9, "GLENN BRENSINGER, ROB BROWN",0,2+8+16);
1927 gametext(c,49+9+9+9+9, "ERIK HARRIS, KEN HECKBERT",0,2+8+16);
1928 gametext(c,49+9+9+9+9+9, "TERRY HERRIN, GREG HIVELY",0,2+8+16);
1929 gametext(c,49+9+9+9+9+9+9, "HANK LEUKART, ERIC BAKER",0,2+8+16);
1930 gametext(c,49+9+9+9+9+9+9+9, "JEFF RAUSCH, KELLY ROGERS",0,2+8+16);
1931 gametext(c,49+9+9+9+9+9+9+9+9, "MIKE DUNCAN, DOUG HOWELL",0,2+8+16);
1932 gametext(c,49+9+9+9+9+9+9+9+9+9, "BILL BLAIR",0,2+8+16);
1933 break;
1934 case 996:
1935 gametext(c,32, "COMPANY PRODUCT SUPPORT",0,2+8+16);
1936
1937 gametext(c,32+9+9, "THE FOLLOWING COMPANIES WERE COOL",0,2+8+16);
1938 gametext(c,32+9+9+9, "ENOUGH TO GIVE US LOTS OF STUFF",0,2+8+16);
1939 gametext(c,32+9+9+9+9, "DURING THE MAKING OF DUKE NUKEM 3D.",0,2+8+16);
1940
1941 gametext(c,32+9+9+9+9+9+9, "ALTEC LANSING MULTIMEDIA",0,2+8+16);
1942 gametext(c,32+9+9+9+9+9+9+9, "FOR TONS OF SPEAKERS AND THE",0,2+8+16);
1943 gametext(c,32+9+9+9+9+9+9+9+9, "THX-LICENSED SOUND SYSTEM",0,2+8+16);
1944 gametext(c,32+9+9+9+9+9+9+9+9+9, "FOR INFO CALL 1-800-548-0620",0,2+8+16);
1945
1946 gametext(c,32+9+9+9+9+9+9+9+9+9+9+9,"CREATIVE LABS, INC.",0,2+8+16);
1947
1948 gametext(c,32+9+9+9+9+9+9+9+9+9+9+9+9+9,"THANKS FOR THE HARDWARE, GUYS.",0,2+8+16);
1949 break;
1950 case 997:
1951 gametext(c,50, "DUKE NUKEM IS A TRADEMARK OF",0,2+8+16);
1952 gametext(c,50+9, "3D REALMS ENTERTAINMENT",0,2+8+16);
1953
1954 gametext(c,50+9+9+9, "DUKE NUKEM",0,2+8+16);
1955 gametext(c,50+9+9+9+9, "(C) 1996 3D REALMS ENTERTAINMENT",0,2+8+16);
1956
1957 if (VOLUMEONE) {
1958 gametext(c,106, "PLEASE READ LICENSE.DOC FOR SHAREWARE",0,2+8+16);
1959 gametext(c,106+9, "DISTRIBUTION GRANTS AND RESTRICTIONS",0,2+8+16);
1960 }
1961
1962 gametext(c,VOLUMEONE?134:115, "MADE IN DALLAS, TEXAS USA",0,2+8+16);
1963 break;
1964 }
1965 }
1966
1967 switch(current_menu)
1968 {
1969 case 990:
1970 case 991:
1971 case 992:
1972 rotatesprite(160<<16,200<<15,65536L,0,2504+current_menu-990,0,0,10+64,0,0,xdim-1,ydim-1);
1973
1974 break;
1975
1976 }
1977 break;
1978
1979 case 0: // main menu
1980 c = (320>>1);
1981 rotatesprite(c<<16,28<<16,65536L,0,INGAMEDUKETHREEDEE,0,0,10,0,0,xdim-1,ydim-1);
1982 rotatesprite((c+100)<<16,36<<16,65536L,0,PLUTOPAKSPRITE+2,(sintable[(totalclock<<4)&2047]>>11),0,2+8,0,0,xdim-1,ydim-1);
1983
1984 x = probe(c,67,16,6);
1985
1986 if(x >= 0)
1987 {
1988 if( ud.multimode > 1 && x == 0 && ud.recstat != 2)
1989 {
1990 if( movesperpacket == 4 && myconnectindex != connecthead )
1991 break;
1992
1993 last_zero = 0;
1994 cmenu( 600 );
1995 }
1996 else
1997 {
1998 last_zero = x;
1999 switch(x)
2000 {
2001 case 0:
2002 cmenu(100);
2003 break;
2004 case 1: cmenu(200);break;
2005 case 2:
2006 if(movesperpacket == 4 && connecthead != myconnectindex)
2007 break;
2008 cmenu(300);
2009 break;
2010 case 3: KB_FlushKeyboardQueue();cmenu(400);break; // help
2011 case 4: cmenu(990);break; // credit
2012 case 5: cmenu(501);break; // quit
2013
2014 }
2015 }
2016 }
2017
2018 if(KB_KeyPressed(sc_Q)) cmenu(501);
2019
2020 if(x == -1)
2021 {
2022 // FIX_00069: Hitting Esc at the menu screen shows an empty green screen
2023 if(ud.recstat == 2) // playing demo
2024 ps[myconnectindex].gm &= ~MODE_MENU;
2025 }
2026
2027 if(movesperpacket == 4)
2028 {
2029 if( myconnectindex == connecthead )
2030 menutext(c,67,SHX(-2),PHX(-2),"NEW GAME");
2031 else
2032 menutext(c,67,SHX(-2),1,"NEW GAME");
2033 }
2034 else
2035 menutext(c,67,SHX(-2),PHX(-2),"NEW GAME");
2036
2037 menutext(c,67+16,SHX(-3),PHX(-3),"OPTIONS");
2038
2039 if(movesperpacket == 4 && connecthead != myconnectindex)
2040 menutext(c,67+16+16,SHX(-4),1,"LOAD GAME");
2041 else menutext(c,67+16+16,SHX(-4),PHX(-4),"LOAD GAME");
2042
2043 if(VOLUMEONE)
2044 menutext(c,67+16+16+16,SHX(-5),PHX(-5),"HOW TO ORDER");
2045 else
2046 menutext(c,67+16+16+16,SHX(-5),PHX(-5),"HELP");
2047
2048 menutext(c,67+16+16+16+16,SHX(-6),PHX(-6),"CREDITS");
2049
2050 menutext(c,67+16+16+16+16+16,SHX(-7),PHX(-7),"QUIT");
2051
2052 break;
2053// CTW END - MODIFICATION
2054
2055 case 50: // general menu as cmenu(0) but for multiplayer games
2056 c = (320>>1);
2057 rotatesprite(c<<16,32<<16,65536L,0,INGAMEDUKETHREEDEE,0,0,10,0,0,xdim-1,ydim-1);
2058 rotatesprite((c+100)<<16,36<<16,65536L,0,PLUTOPAKSPRITE+2,(sintable[(totalclock<<4)&2047]>>11),0,2+8,0,0,xdim-1,ydim-1);
2059 x = probe(c,67,16,7);
2060 switch(x)
2061 {
2062 case 0:
2063 if(movesperpacket == 4 && myconnectindex != connecthead)
2064 break;
2065 if(ud.multimode < 2 || ud.recstat == 2)
2066 cmenu(1500);
2067 else
2068 {
2069 cmenu(600);
2070 last_fifty = 0;
2071 }
2072 break;
2073 case 1:
2074 if(movesperpacket == 4 && connecthead != myconnectindex)
2075 break;
2076 if(ud.recstat != 2)
2077 {
2078 last_fifty = 1;
2079 cmenu(350);
2080 setview(0,0,xdim-1,ydim-1);
2081 }
2082 break;
2083 case 2:
2084 if(movesperpacket == 4 && connecthead != myconnectindex)
2085 break;
2086 last_fifty = 2;
2087 cmenu(300);
2088 break;
2089 case 3:
2090 last_fifty = 3;
2091 cmenu(200);
2092 break;
2093 case 4:
2094 last_fifty = 4;
2095 KB_FlushKeyboardQueue();
2096 cmenu(400);
2097 break;
2098 case 5:
2099 if(numplayers < 2)
2100 {
2101 last_fifty = 5;
2102 cmenu(503);
2103 }
2104 break;
2105 case 6:
2106 last_fifty = 6;
2107 cmenu(502);
2108 break;
2109 case -1:
2110 ps[myconnectindex].gm &= ~MODE_MENU;
2111 if(ud.multimode < 2 && ud.recstat != 2)
2112 {
2113 ready2send = 1;
2114 totalclock = ototalclock;
2115 }
2116 break;
2117 }
2118
2119 if( KB_KeyPressed(sc_Q) )
2120 cmenu(502);
2121
2122 if(movesperpacket == 4 && connecthead != myconnectindex)
2123 {
2124 menutext(c,67+16*0 ,SHX(-2),1,"NEW GAME");
2125 menutext(c,67+16*1 ,SHX(-3),1,"SAVE GAME");
2126 menutext(c,67+16*2 ,SHX(-4),1,"LOAD GAME");
2127 }
2128 else
2129 {
2130 menutext(c,67+16*0 ,SHX(-2),PHX(-2),"NEW GAME");
2131 menutext(c,67+16*1 ,SHX(-3),PHX(-3),"SAVE GAME");
2132 menutext(c,67+16*2 ,SHX(-4),PHX(-4),"LOAD GAME");
2133 }
2134
2135 menutext(c,67+16*3 ,SHX(-5),PHX(-5),"OPTIONS");
2136 if(VOLUMEONE)
2137 menutext(c,67+16*4 ,SHX(-6),PHX(-6),"HOW TO ORDER");
2138 else
2139 menutext(c,67+16*4 ,SHX(-6),PHX(-6)," HELP");
2140
2141 if(numplayers > 1)
2142 menutext(c,67+16*5 ,SHX(-7),1,"QUIT TO TITLE");
2143 else menutext(c,67+16*5 ,SHX(-7),PHX(-7),"QUIT TO TITLE");
2144 menutext(c,67+16*6,SHX(-8),PHX(-8),"QUIT GAME");
2145
2146 break;
2147
2148 case 100: // Title menu
2149 rotatesprite(160<<16,19<<16,65536L,0,MENUBAR,16,0,10,0,0,xdim-1,ydim-1);
2150 menutext(160,24,0,0,"SELECT AN EPISODE");
2151 if(PLUTOPAK)
2152 { //////if(boardfilename[0])
2153 //
2154 // uncomment this for user map
2155 //x = probe(160,60,20,5);
2156 x = probe(160,60,20,4);
2157
2158 //////else x = probe(160,60,20,4);
2159 }
2160 else
2161 {
2162 if(boardfilename[0])
2163 x = probe(160,60,20,4);
2164 else x = probe(160,60,20,3);
2165 }
2166 if(x >= 0)
2167 {
2168
2169 if (VOLUMEONE)
2170 {
2171 if(x > 0)
2172 cmenu(20000);
2173 else
2174 {
2175 ud.m_volume_number = x;
2176 ud.m_level_number = 0;
2177 cmenu(110);
2178 }
2179 }
2180
2181 else
2182 {
2183
2184 if((x == 3 && boardfilename[0])&&!PLUTOPAK)
2185 {
2186 ud.m_volume_number = 0;
2187 ud.m_level_number = 7;
2188 }
2189 else
2190
2191 /*
2192 if(x == 4 && boardfilename[0])
2193 {
2194 ud.m_volume_number = 0;
2195 ud.m_level_number = 7;
2196 }
2197 */
2198
2199 // USER MAP
2200 if((x == 4)&&PLUTOPAK)
2201 {
2202 //CONSOLE_Printf("MENU_USER_MAP");
2203 //
2204 //[Todo: generate file list starting from .\\maps]")
2205
2206 cmenu(MENU_USER_MAP); // cmenu(101)
2207 break;
2208 }
2209 else
2210 {
2211 ud.m_volume_number = x;
2212 ud.m_level_number = 0;
2213 }
2214 cmenu(110);
2215 }
2216 }
2217 else if(x == -1)
2218 {
2219 if(ps[myconnectindex].gm&MODE_GAME) cmenu(50);
2220 else cmenu(0);
2221 }
2222
2223 menutext(160,60,SHX(-2),PHX(-2),volume_names[0]);
2224
2225 c = 80;
2226 if (VOLUMEONE)
2227 {
2228 menutext(160,60+20,SHX(-3),1,volume_names[1]);
2229 menutext(160,60+20+20,SHX(-4),1,volume_names[2]);
2230 if(PLUTOPAK)
2231 menutext(160,60+20+20,SHX(-5),1,volume_names[3]);
2232 }
2233 else
2234 {
2235 menutext(160,60+20,SHX(-3),PHX(-3),volume_names[1]);
2236 menutext(160,60+20+20,SHX(-4),PHX(-4),volume_names[2]);
2237 if(PLUTOPAK)
2238 {
2239 menutext(160,60+20+20+20,SHX(-5),PHX(-5),volume_names[3]);
2240 //if(boardfilename[0])
2241 //{
2242
2243 // uncomment this for usermap
2244 //menutext(160,60+20+20+20+20,SHX(-6),PHX(-6),"USER MAP");
2245
2246 //gametextpal(160,60+20+20+20+20+3,boardfilename,16+(sintable[(totalclock<<4)&2047]>>11),2);
2247 //}
2248 }
2249 else
2250 { /*
2251 if(boardfilename[0])
2252 {
2253 menutext(160,60+20+20+20,SHX(-6),PHX(-6),"USER MAP");
2254 gametext(160,60+20+20+20+6,boardfilename,2,2+8+16);
2255 }
2256 */
2257 }
2258 }
2259 break;
2260
2261 case 101: // MENU_USER_MAP
2262 c = (320>>1);
2263 rotatesprite(c<<16,19<<16,65536L,0,MENUBAR,16,0,10,0,0,xdim-1,ydim-1);
2264 menutext(c,24,0,0,"USER MAP");
2265
2266 // Draw USER MAP background
2267 {
2268 int y, x1;
2269 int32_t xPos, xPos2;
2270 int32_t yPos; //yPos2;
2271
2272 xPos = ( xdim *32) / 320;
2273 yPos = ( ydim *30) / 200;
2274
2275 xPos2 = ( xdim *282) / 320;
2276 //yPos2 = ( ydim *130) / 200;
2277
2278 for(y=yPos; y < (ydim - (yPos*2)); y+=128)
2279 {
2280 for(x1=xPos; x1 < xPos2; x1+=128)
2281 {
2282 rotatesprite(x1<<16,y<<16,65536L,0,BIGHOLE,8,0,1+8+16+64+128,0,0, xdim - xPos, ydim - (yPos*2));
2283 }
2284 }
2285 }
2286
2287 c = (320>>1)-120;
2288 x = probe(c,70,19,4);
2289
2290 if(x == -1)
2291 {
2292 cmenu(MENU_SELECT_EPISODE);
2293 }
2294 break;
2295
2296 case 110:
2297 c = (320>>1);
2298 rotatesprite(c<<16,19<<16,65536L,0,MENUBAR,16,0,10,0,0,xdim-1,ydim-1);
2299 menutext(c,24,0,0,"SELECT SKILL");
2300 x = probe(c,70,19,4);
2301 if(x >= 0)
2302 {
2303 switch(x)
2304 {
2305 case 0: globalskillsound = JIBBED_ACTOR6;break;
2306 case 1: globalskillsound = BONUS_SPEECH1;break;
2307 case 2: globalskillsound = DUKE_GETWEAPON2;break;
2308 case 3: globalskillsound = JIBBED_ACTOR5;break;
2309 }
2310
2311 sound(globalskillsound);
2312
2313 ud.m_player_skill = x+1;
2314 if(x == 3) ud.m_respawn_monsters = 1;
2315 else ud.m_respawn_monsters = 0;
2316
2317 ud.m_monsters_off = ud.monsters_off = 0;
2318
2319 ud.m_respawn_items = 0;
2320 ud.m_respawn_inventory = 0;
2321
2322 ud.multimode = 1;
2323
2324 // if (ud.showcinematics)
2325 //if(ud.m_volume_number == 3) // not needed to play cinematics. Black screen not nice
2326 //{
2327 // flushperms();
2328 // setview(0,0,xdim-1,ydim-1);
2329 // clearview(0L);
2330 // nextpage();
2331 //}
2332
2333 newgame(ud.m_volume_number,ud.m_level_number,ud.m_player_skill);
2334 enterlevel(MODE_GAME);
2335 }
2336 else if(x == -1)
2337 {
2338 cmenu(100);
2339 KB_FlushKeyboardQueue();
2340 }
2341
2342 menutext(c,70,SHX(-2),PHX(-2),skill_names[0]);
2343 menutext(c,70+19,SHX(-3),PHX(-3),skill_names[1]);
2344 menutext(c,70+19+19,SHX(-4),PHX(-4),skill_names[2]);
2345 menutext(c,70+19+19+19,SHX(-5),PHX(-5),skill_names[3]);
2346 break;
2347
2348 case 200:
2349
2350 rotatesprite(320<<15,19<<16,65536L,0,MENUBAR,16,0,10,0,0,xdim-1,ydim-1);
2351 menutext(320>>1,24,0,0,"OPTIONS");
2352
2353 c = (320>>1)-120;
2354
2355 x = probe(c+6,43,16,6);
2356
2357 if(x == -1)
2358 { if(ps[myconnectindex].gm&MODE_GAME) cmenu(50);else cmenu(0); }
2359
2360 switch(x)
2361 {
2362 case 0:
2363 cmenu(702); // game options
2364 break;
2365
2366 case 1:
2367 cmenu(703); // keybaord setup
2368 probey = 7;
2369 break;
2370
2371 case 2:
2372 cmenu(701); // mouse setup
2373 break;
2374
2375 case 3:
2376 cmenu(700); // sound setup
2377 break;
2378
2379 case 4:
2380 cmenu(706); // Video setup
2381 lastkeysetup = 0;
2382 current_resolution = 0; // in case we don't find it
2383 for(i=0; i<validmodecnt; i++)
2384 {
2385 if(validmodexdim[i] == xdim && validmodeydim[i] == ydim)
2386 current_resolution = i;
2387 }
2388 break;
2389
2390 case 5: // record on/off
2391 if( (ps[myconnectindex].gm&MODE_GAME) )
2392 {
2393 closedemowrite();
2394 break;
2395 }
2396 ud.m_recstat = !ud.m_recstat;
2397 break;
2398
2399 //case -7:
2400 // gametext(320>>1,43+16*6,"*** DISABLED. WILL BE FIXED SOON***",0,2+8+16); // center-i
2401 // break;
2402
2403 }
2404
2405 menutext(c,43,SHX(-6),PHX(-6),"GAME OPTIONS");
2406
2407 menutext(c,43+16,SHX(-6),PHX(-6),"SETUP KEYBOARD");
2408
2409 menutext(c,43+16+16,SHX(-6),PHX(-6),"SETUP MOUSE");
2410
2411 menutext(c,43+16+16+16,SHX(-8),PHX(-8),"SETUP SOUND");
2412
2413 menutext(c,43+16+16+16+16,SHX(-8),PHX(-8),"SETUP VIDEO");
2414
2415 if( (ps[myconnectindex].gm&MODE_GAME) && ud.m_recstat != 1 )
2416 {
2417 menutext(c,43+16+16+16+16+16,SHX(-10),1,"RECORD");
2418 menutext(c+160+40,43+16+16+16+16+16,SHX(-10),1,"OFF");
2419 }
2420 else