blob: 8808cd08838362da12f88bb968125e3aae8768cd [file] [log] [blame]
Franklin Wei3f59fc82019-07-07 22:00:20 -04001// WL_MAIN.C
2
3#include "wl_def.h"
4#pragma hdrstop
5#include "wl_atmos.h"
6#include <SDL_syswm.h>
7
8
9/*
10=============================================================================
11
12 WOLFENSTEIN 3-D
13
14 An Id Software production
15
16 by John Carmack
17
18=============================================================================
19*/
20
21extern byte signon[];
22
23/*
24=============================================================================
25
26 LOCAL CONSTANTS
27
28=============================================================================
29*/
30
31
32#define FOCALLENGTH (0x5700l) // in global coordinates
33#define VIEWGLOBAL 0x10000 // globals visable flush to wall
34
35#define VIEWWIDTH 256 // size of view window
36#define VIEWHEIGHT 144
37
38/*
39=============================================================================
40
41 GLOBAL VARIABLES
42
43=============================================================================
44*/
45
46char str[80];
47int dirangle[9] = {0,ANGLES/8,2*ANGLES/8,3*ANGLES/8,4*ANGLES/8,
48 5*ANGLES/8,6*ANGLES/8,7*ANGLES/8,ANGLES};
49
50//
51// proejection variables
52//
53fixed focallength;
54unsigned screenofs;
55int viewscreenx, viewscreeny;
56int viewwidth;
57int viewheight;
58short centerx;
59int shootdelta; // pixels away from centerx a target can be
60fixed scale;
61int32_t heightnumerator;
62
63
64void Quit (const char *error,...);
65
66boolean startgame;
67boolean loadedgame;
68int mouseadjustment;
69
70char configdir[256] = "";
71char configname[13] = "config.";
72
73//
74// Command line parameter variables
75//
76boolean param_debugmode = false;
77boolean param_nowait = false;
78int param_difficulty = 1; // default is "normal"
79int param_tedlevel = -1; // default is not to start a level
80int param_joystickindex = 0;
81
82#if defined(_arch_dreamcast)
83int param_joystickhat = 0;
84int param_samplerate = 11025; // higher samplerates result in "out of memory"
85int param_audiobuffer = 4096 / (44100 / param_samplerate);
86#elif defined(GP2X_940)
87int param_joystickhat = -1;
88int param_samplerate = 11025; // higher samplerates result in "out of memory"
89int param_audiobuffer = 128;
90#else
91int param_joystickhat = -1;
92int param_samplerate = RB_SAMPR;
93int param_audiobuffer = 2048 / (44100 / RB_SAMPR);
94#endif
95
96int param_mission = 0;
97boolean param_goodtimes = false;
98boolean param_ignorenumchunks = false;
99
100/*
101=============================================================================
102
103 LOCAL VARIABLES
104
105=============================================================================
106*/
107
108
109/*
110====================
111=
112= ReadConfig
113=
114====================
115*/
116
117void ReadConfig(void)
118{
119 SDMode sd;
120 SMMode sm;
121 SDSMode sds;
122
123 char configpath[300];
124
125#ifdef _arch_dreamcast
126 DC_LoadFromVMU(configname);
127#endif
128
129 if(configdir[0])
130 snprintf(configpath, sizeof(configpath), "%s/%s", configdir, configname);
131 else
132 strcpy(configpath, configname);
133
134 const int file = open(configpath, O_RDONLY | O_BINARY);
135 if (file >= 0)
136 {
137 //
138 // valid config file
139 //
140 word tmp;
141 read(file,&tmp,sizeof(tmp));
142 if(tmp!=0xfefa)
143 {
144 close(file);
145 goto noconfig;
146 }
147 read(file,Scores,sizeof(HighScore) * MaxScores);
148
149 read(file,&sd,sizeof(sd));
150 read(file,&sm,sizeof(sm));
151 read(file,&sds,sizeof(sds));
152
153 read(file,&mouseenabled,sizeof(mouseenabled));
154 read(file,&joystickenabled,sizeof(joystickenabled));
155 boolean dummyJoypadEnabled;
156 read(file,&dummyJoypadEnabled,sizeof(dummyJoypadEnabled));
157 boolean dummyJoystickProgressive;
158 read(file,&dummyJoystickProgressive,sizeof(dummyJoystickProgressive));
159 int dummyJoystickPort = 0;
160 read(file,&dummyJoystickPort,sizeof(dummyJoystickPort));
161
162 read(file,dirscan,sizeof(dirscan));
163 read(file,buttonscan,sizeof(buttonscan));
164 read(file,buttonmouse,sizeof(buttonmouse));
165 read(file,buttonjoy,sizeof(buttonjoy));
166
167 read(file,&viewsize,sizeof(viewsize));
168 read(file,&mouseadjustment,sizeof(mouseadjustment));
169
170 close(file);
171
172 /* hack to always enable sound */
173 sd = sdm_AdLib;
174 sm = smm_AdLib;
175
176 sds = sds_SoundBlaster;
177
178 // make sure values are correct
179
180 if(mouseenabled) mouseenabled=true;
181 if(joystickenabled) joystickenabled=true;
182
183 if (!MousePresent)
184 mouseenabled = false;
185 if (!IN_JoyPresent())
186 joystickenabled = false;
187
188 if(mouseadjustment<0) mouseadjustment=0;
189 else if(mouseadjustment>9) mouseadjustment=9;
190
191 if(viewsize<4) viewsize=4;
192 else if(viewsize>21) viewsize=21;
193
194 MainMenu[6].active=1;
195 MainItems.curpos=0;
196 }
197 else
198 {
199 //
200 // no config file, so select by hardware
201 //
202noconfig:
203 // always -FW19
204 sd = sdm_AdLib;
205 sm = smm_AdLib;
206
207 sds = sds_SoundBlaster;
208
209 if (MousePresent)
210 mouseenabled = true;
211
212 if (IN_JoyPresent())
213 joystickenabled = true;
214
Franklin Wei42240f62019-07-10 16:59:02 -0400215 viewsize = 20; // start with a good size
Franklin Wei3f59fc82019-07-07 22:00:20 -0400216 mouseadjustment=5;
217 }
218
219 SD_SetMusicMode (sm);
220 SD_SetSoundMode (sd);
221 SD_SetDigiDevice (sds);
222}
223
224/*
225====================
226=
227= WriteConfig
228=
229====================
230*/
231
232void WriteConfig(void)
233{
234 char configpath[300];
235
236#ifdef _arch_dreamcast
237 fs_unlink(configname);
238#endif
239
240 if(configdir[0])
241 snprintf(configpath, sizeof(configpath), "%s/%s", configdir, configname);
242 else
243 strcpy(configpath, configname);
244
245 const int file = open(configpath, O_CREAT | O_WRONLY | O_BINARY, 0644);
246 if (file != -1)
247 {
248 word tmp=0xfefa;
249 write(file,&tmp,sizeof(tmp));
250 write(file,Scores,sizeof(HighScore) * MaxScores);
251
252 write(file,&SoundMode,sizeof(SoundMode));
253 write(file,&MusicMode,sizeof(MusicMode));
254 write(file,&DigiMode,sizeof(DigiMode));
255
256 write(file,&mouseenabled,sizeof(mouseenabled));
257 write(file,&joystickenabled,sizeof(joystickenabled));
258 boolean dummyJoypadEnabled = false;
259 write(file,&dummyJoypadEnabled,sizeof(dummyJoypadEnabled));
260 boolean dummyJoystickProgressive = false;
261 write(file,&dummyJoystickProgressive,sizeof(dummyJoystickProgressive));
262 int dummyJoystickPort = 0;
263 write(file,&dummyJoystickPort,sizeof(dummyJoystickPort));
264
265 write(file,dirscan,sizeof(dirscan));
266 write(file,buttonscan,sizeof(buttonscan));
267 write(file,buttonmouse,sizeof(buttonmouse));
268 write(file,buttonjoy,sizeof(buttonjoy));
269
270 write(file,&viewsize,sizeof(viewsize));
271 write(file,&mouseadjustment,sizeof(mouseadjustment));
272
273 close(file);
274 }
275#ifdef _arch_dreamcast
276 DC_SaveToVMU(configname, NULL);
277#endif
278}
279
280
281//===========================================================================
282
283/*
284=====================
285=
286= NewGame
287=
288= Set up new game to start from the beginning
289=
290=====================
291*/
292
293void NewGame (int difficulty,int episode)
294{
295 memset (&gamestate,0,sizeof(gamestate));
296 gamestate.difficulty = difficulty;
297 gamestate.weapon = gamestate.bestweapon
298 = gamestate.chosenweapon = wp_pistol;
299 gamestate.health = 100;
300 gamestate.ammo = STARTAMMO;
301 gamestate.lives = 3;
302 gamestate.nextextra = EXTRAPOINTS;
303 gamestate.episode=episode;
304
305 startgame = true;
306}
307
308//===========================================================================
309
310void DiskFlopAnim(int x,int y)
311{
312 static int8_t which=0;
313 if (!x && !y)
314 return;
315 VWB_DrawPic(x,y,C_DISKLOADING1PIC+which);
316 VW_UpdateScreen();
317 which^=1;
318}
319
320
321int32_t DoChecksum(byte *source,unsigned size,int32_t checksum)
322{
323 unsigned i;
324
325 for (i=0;i<size-1;i++)
326 checksum += source[i]^source[i+1];
327
328 return checksum;
329}
330
331
332/*
333==================
334=
335= SaveTheGame
336=
337==================
338*/
339
340extern statetype s_grdstand;
341extern statetype s_player;
342
343boolean SaveTheGame(FILE *file,int x,int y)
344{
345// struct diskfree_t dfree;
346// int32_t avail,size,checksum;
347 int checksum;
348 objtype *ob;
349 objtype nullobj;
350 statobj_t nullstat;
351
352/* if (_dos_getdiskfree(0,&dfree))
353 Quit("Error in _dos_getdiskfree call");
354
355 avail = (int32_t)dfree.avail_clusters *
356 dfree.bytes_per_sector *
357 dfree.sectors_per_cluster;
358
359 size = 0;
360 for (ob = player; ob ; ob=ob->next)
361 size += sizeof(*ob);
362 size += sizeof(nullobj);
363
364 size += sizeof(gamestate) +
365 sizeof(LRstruct)*LRpack +
366 sizeof(tilemap) +
367 sizeof(actorat) +
368 sizeof(laststatobj) +
369 sizeof(statobjlist) +
370 sizeof(doorposition) +
371 sizeof(pwallstate) +
372 sizeof(pwalltile) +
373 sizeof(pwallx) +
374 sizeof(pwally) +
375 sizeof(pwalldir) +
376 sizeof(pwallpos);
377
378 if (avail < size)
379 {
380 Message(STR_NOSPACE1"\n"STR_NOSPACE2);
381 return false;
382 }*/
383
384 checksum = 0;
385
386 DiskFlopAnim(x,y);
387 fwrite(&gamestate,sizeof(gamestate),1,file);
388 checksum = DoChecksum((byte *)&gamestate,sizeof(gamestate),checksum);
389
390 DiskFlopAnim(x,y);
391 fwrite(&LevelRatios[0],sizeof(LRstruct)*LRpack,1,file);
392 checksum = DoChecksum((byte *)&LevelRatios[0],sizeof(LRstruct)*LRpack,checksum);
393
394 DiskFlopAnim(x,y);
395 fwrite(tilemap,sizeof(tilemap),1,file);
396 checksum = DoChecksum((byte *)tilemap,sizeof(tilemap),checksum);
397 DiskFlopAnim(x,y);
398
399 int i;
400 for(i=0;i<MAPSIZE;i++)
401 {
402 for(int j=0;j<MAPSIZE;j++)
403 {
404 word actnum;
405 objtype *objptr=actorat[i][j];
406 if(ISPOINTER(objptr))
407 actnum=0x8000 | (word)(objptr-objlist);
408 else
409 actnum=(word)(uintptr_t)objptr;
410 fwrite(&actnum,sizeof(actnum),1,file);
411 checksum = DoChecksum((byte *)&actnum,sizeof(actnum),checksum);
412 }
413 }
414
415 fwrite (areaconnect,sizeof(areaconnect),1,file);
416 fwrite (areabyplayer,sizeof(areabyplayer),1,file);
417
418 // player object needs special treatment as it's in WL_AGENT.CPP and not in
419 // WL_ACT2.CPP which could cause problems for the relative addressing
420
421 ob = player;
422 DiskFlopAnim(x,y);
423 memcpy(&nullobj,ob,sizeof(nullobj));
424 nullobj.state=(statetype *) ((uintptr_t)nullobj.state-(uintptr_t)&s_player);
425 fwrite(&nullobj,sizeof(nullobj),1,file);
426 ob = ob->next;
427
428 DiskFlopAnim(x,y);
429 for (; ob ; ob=ob->next)
430 {
431 memcpy(&nullobj,ob,sizeof(nullobj));
432 nullobj.state=(statetype *) ((uintptr_t)nullobj.state-(uintptr_t)&s_grdstand);
433 fwrite(&nullobj,sizeof(nullobj),1,file);
434 }
435 nullobj.active = ac_badobject; // end of file marker
436 DiskFlopAnim(x,y);
437 fwrite(&nullobj,sizeof(nullobj),1,file);
438
439 DiskFlopAnim(x,y);
440 word laststatobjnum=(word) (laststatobj-statobjlist);
441 fwrite(&laststatobjnum,sizeof(laststatobjnum),1,file);
442 checksum = DoChecksum((byte *)&laststatobjnum,sizeof(laststatobjnum),checksum);
443
444 DiskFlopAnim(x,y);
445 for(i=0;i<MAXSTATS;i++)
446 {
447 memcpy(&nullstat,statobjlist+i,sizeof(nullstat));
448 nullstat.visspot=(byte *) ((uintptr_t) nullstat.visspot-(uintptr_t)spotvis);
449 fwrite(&nullstat,sizeof(nullstat),1,file);
450 checksum = DoChecksum((byte *)&nullstat,sizeof(nullstat),checksum);
451 }
452
453 DiskFlopAnim(x,y);
454 fwrite (doorposition,sizeof(doorposition),1,file);
455 checksum = DoChecksum((byte *)doorposition,sizeof(doorposition),checksum);
456 DiskFlopAnim(x,y);
457 fwrite (doorobjlist,sizeof(doorobjlist),1,file);
458 checksum = DoChecksum((byte *)doorobjlist,sizeof(doorobjlist),checksum);
459
460 DiskFlopAnim(x,y);
461 fwrite (&pwallstate,sizeof(pwallstate),1,file);
462 checksum = DoChecksum((byte *)&pwallstate,sizeof(pwallstate),checksum);
463 fwrite (&pwalltile,sizeof(pwalltile),1,file);
464 checksum = DoChecksum((byte *)&pwalltile,sizeof(pwalltile),checksum);
465 fwrite (&pwallx,sizeof(pwallx),1,file);
466 checksum = DoChecksum((byte *)&pwallx,sizeof(pwallx),checksum);
467 fwrite (&pwally,sizeof(pwally),1,file);
468 checksum = DoChecksum((byte *)&pwally,sizeof(pwally),checksum);
469 fwrite (&pwalldir,sizeof(pwalldir),1,file);
470 checksum = DoChecksum((byte *)&pwalldir,sizeof(pwalldir),checksum);
471 fwrite (&pwallpos,sizeof(pwallpos),1,file);
472 checksum = DoChecksum((byte *)&pwallpos,sizeof(pwallpos),checksum);
473
474 //
475 // WRITE OUT CHECKSUM
476 //
477 fwrite (&checksum,sizeof(checksum),1,file);
478
479 fwrite (&lastgamemusicoffset,sizeof(lastgamemusicoffset),1,file);
480
481 return(true);
482}
483
484//===========================================================================
485
486/*
487==================
488=
489= LoadTheGame
490=
491==================
492*/
493
494boolean LoadTheGame(FILE *file,int x,int y)
495{
496 int32_t checksum,oldchecksum;
497 objtype nullobj;
498 statobj_t nullstat;
499
500 checksum = 0;
501
502 DiskFlopAnim(x,y);
503 fread (&gamestate,sizeof(gamestate),1,file);
504 checksum = DoChecksum((byte *)&gamestate,sizeof(gamestate),checksum);
505
506 DiskFlopAnim(x,y);
507 fread (&LevelRatios[0],sizeof(LRstruct)*LRpack,1,file);
508 checksum = DoChecksum((byte *)&LevelRatios[0],sizeof(LRstruct)*LRpack,checksum);
509
510 DiskFlopAnim(x,y);
511 SetupGameLevel ();
512
513 DiskFlopAnim(x,y);
514 fread (tilemap,sizeof(tilemap),1,file);
515 checksum = DoChecksum((byte *)tilemap,sizeof(tilemap),checksum);
516
517 DiskFlopAnim(x,y);
518
519 int actnum=0, i;
520 for(i=0;i<MAPSIZE;i++)
521 {
522 for(int j=0;j<MAPSIZE;j++)
523 {
524 fread (&actnum,sizeof(word),1,file);
525 checksum = DoChecksum((byte *) &actnum,sizeof(word),checksum);
526 if(actnum&0x8000)
527 actorat[i][j]=objlist+(actnum&0x7fff);
528 else
529 actorat[i][j]=(objtype *)(uintptr_t) actnum;
530 }
531 }
532
533 fread (areaconnect,sizeof(areaconnect),1,file);
534 fread (areabyplayer,sizeof(areabyplayer),1,file);
535
536 InitActorList ();
537 DiskFlopAnim(x,y);
538 fread (player,sizeof(*player),1,file);
539 player->state=(statetype *) ((uintptr_t)player->state+(uintptr_t)&s_player);
540
541 while (1)
542 {
543 DiskFlopAnim(x,y);
544 fread (&nullobj,sizeof(nullobj),1,file);
545 if (nullobj.active == ac_badobject)
546 break;
547 GetNewActor ();
548 nullobj.state=(statetype *) ((uintptr_t)nullobj.state+(uintptr_t)&s_grdstand);
549 // don't copy over the links
550 memcpy (newobj,&nullobj,sizeof(nullobj)-8);
551 }
552
553 DiskFlopAnim(x,y);
554 word laststatobjnum;
555 fread (&laststatobjnum,sizeof(laststatobjnum),1,file);
556 laststatobj=statobjlist+laststatobjnum;
557 checksum = DoChecksum((byte *)&laststatobjnum,sizeof(laststatobjnum),checksum);
558
559 DiskFlopAnim(x,y);
560 for(i=0;i<MAXSTATS;i++)
561 {
562 fread(&nullstat,sizeof(nullstat),1,file);
563 checksum = DoChecksum((byte *)&nullstat,sizeof(nullstat),checksum);
564 nullstat.visspot=(byte *) ((uintptr_t)nullstat.visspot+(uintptr_t)spotvis);
565 memcpy(statobjlist+i,&nullstat,sizeof(nullstat));
566 }
567
568 DiskFlopAnim(x,y);
569 fread (doorposition,sizeof(doorposition),1,file);
570 checksum = DoChecksum((byte *)doorposition,sizeof(doorposition),checksum);
571 DiskFlopAnim(x,y);
572 fread (doorobjlist,sizeof(doorobjlist),1,file);
573 checksum = DoChecksum((byte *)doorobjlist,sizeof(doorobjlist),checksum);
574
575 DiskFlopAnim(x,y);
576 fread (&pwallstate,sizeof(pwallstate),1,file);
577 checksum = DoChecksum((byte *)&pwallstate,sizeof(pwallstate),checksum);
578 fread (&pwalltile,sizeof(pwalltile),1,file);
579 checksum = DoChecksum((byte *)&pwalltile,sizeof(pwalltile),checksum);
580 fread (&pwallx,sizeof(pwallx),1,file);
581 checksum = DoChecksum((byte *)&pwallx,sizeof(pwallx),checksum);
582 fread (&pwally,sizeof(pwally),1,file);
583 checksum = DoChecksum((byte *)&pwally,sizeof(pwally),checksum);
584 fread (&pwalldir,sizeof(pwalldir),1,file);
585 checksum = DoChecksum((byte *)&pwalldir,sizeof(pwalldir),checksum);
586 fread (&pwallpos,sizeof(pwallpos),1,file);
587 checksum = DoChecksum((byte *)&pwallpos,sizeof(pwallpos),checksum);
588
589 if (gamestate.secretcount) // assign valid floorcodes under moved pushwalls
590 {
591 word *map, *obj; word tile, sprite;
592 map = mapsegs[0]; obj = mapsegs[1];
593 for (y=0;y<mapheight;y++)
594 for (x=0;x<mapwidth;x++)
595 {
596 tile = *map++; sprite = *obj++;
597 if (sprite == PUSHABLETILE && !tilemap[x][y]
598 && (tile < AREATILE || tile >= (AREATILE+NUMMAPS)))
599 {
600 if (*map >= AREATILE)
601 tile = *map;
602 if (*(map-1-mapwidth) >= AREATILE)
603 tile = *(map-1-mapwidth);
604 if (*(map-1+mapwidth) >= AREATILE)
605 tile = *(map-1+mapwidth);
606 if ( *(map-2) >= AREATILE)
607 tile = *(map-2);
608
609 *(map-1) = tile; *(obj-1) = 0;
610 }
611 }
612 }
613
614 Thrust(0,0); // set player->areanumber to the floortile you're standing on
615
616 fread (&oldchecksum,sizeof(oldchecksum),1,file);
617
618 fread (&lastgamemusicoffset,sizeof(lastgamemusicoffset),1,file);
619 if(lastgamemusicoffset<0) lastgamemusicoffset=0;
620
621
622 if (oldchecksum != checksum)
623 {
624 Message(STR_SAVECHT1"\n"
625 STR_SAVECHT2"\n"
626 STR_SAVECHT3"\n"
627 STR_SAVECHT4);
628
629 IN_ClearKeysDown();
630 IN_Ack();
631
632 gamestate.oldscore = gamestate.score = 0;
633 gamestate.lives = 1;
634 gamestate.weapon =
635 gamestate.chosenweapon =
636 gamestate.bestweapon = wp_pistol;
637 gamestate.ammo = 8;
638 }
639
640 return true;
641}
642
643//===========================================================================
644
645/*
646==========================
647=
648= ShutdownId
649=
650= Shuts down all ID_?? managers
651=
652==========================
653*/
654
655void ShutdownId (void)
656{
657 US_Shutdown (); // This line is completely useless...
658 SD_Shutdown ();
659 PM_Shutdown ();
660 IN_Shutdown ();
661 VW_Shutdown ();
662 CA_Shutdown ();
663#if defined(GP2X_940)
664 GP2X_Shutdown();
665#endif
666}
667
668
669//===========================================================================
670
671/*
672==================
673=
674= BuildTables
675=
676= Calculates:
677=
678= scale projection constant
679= sintable/costable overlapping fractional tables
680=
681==================
682*/
683
684const float radtoint = (float)(FINEANGLES/2/PI);
685
686void BuildTables (void)
687{
688 //
689 // calculate fine tangents
690 //
691
692 int i;
693 for(i=0;i<FINEANGLES/8;i++)
694 {
695 double tang=tan((i+0.5)/radtoint);
696 finetangent[i]=(int32_t)(tang*GLOBAL1);
697 finetangent[FINEANGLES/4-1-i]=(int32_t)((1/tang)*GLOBAL1);
698 }
699
700 //
701 // costable overlays sintable with a quarter phase shift
702 // ANGLES is assumed to be divisable by four
703 //
704
705 float angle=0;
706 float anglestep=(float)(PI/2/ANGLEQUAD);
707 for(i=0; i<ANGLEQUAD; i++)
708 {
709 fixed value=(int32_t)(GLOBAL1*sin(angle));
710 sintable[i]=sintable[i+ANGLES]=sintable[ANGLES/2-i]=value;
711 sintable[ANGLES-i]=sintable[ANGLES/2+i]=-value;
712 angle+=anglestep;
713 }
714 sintable[ANGLEQUAD] = 65536;
715 sintable[3*ANGLEQUAD] = -65536;
716
717#if defined(USE_STARSKY) || defined(USE_RAIN) || defined(USE_SNOW)
718 Init3DPoints();
719#endif
720}
721
722//===========================================================================
723
724
725/*
726====================
727=
728= CalcProjection
729=
730= Uses focallength
731=
732====================
733*/
734
735void CalcProjection (int32_t focal)
736{
737 int i;
738 int intang;
739 float angle;
740 double tang;
741 int halfview;
742 double facedist;
743
744 focallength = focal;
745 facedist = focal+MINDIST;
746 halfview = viewwidth/2; // half view in pixels
747
748 //
749 // calculate scale value for vertical height calculations
750 // and sprite x calculations
751 //
752 scale = (fixed) (halfview*facedist/(VIEWGLOBAL/2));
753
754 //
755 // divide heightnumerator by a posts distance to get the posts height for
756 // the heightbuffer. The pixel height is height>>2
757 //
758 heightnumerator = (TILEGLOBAL*scale)>>6;
759
760 //
761 // calculate the angle offset from view angle of each pixel's ray
762 //
763
764 for (i=0;i<halfview;i++)
765 {
766 // start 1/2 pixel over, so viewangle bisects two middle pixels
767 tang = (int32_t)i*VIEWGLOBAL/viewwidth/facedist;
768 angle = (float) atan(tang);
769 intang = (int) (angle*radtoint);
770 pixelangle[halfview-1-i] = intang;
771 pixelangle[halfview+i] = -intang;
772 }
773}
774
775
776
777//===========================================================================
778
779/*
780===================
781=
782= SetupWalls
783=
784= Map tile values to scaled pics
785=
786===================
787*/
788
789void SetupWalls (void)
790{
791 int i;
792
793 horizwall[0]=0;
794 vertwall[0]=0;
795
796 for (i=1;i<MAXWALLTILES;i++)
797 {
798 horizwall[i]=(i-1)*2;
799 vertwall[i]=(i-1)*2+1;
800 }
801}
802
803//===========================================================================
804
805/*
806==========================
807=
808= SignonScreen
809=
810==========================
811*/
812
813void SignonScreen (void) // VGA version
814{
815 VL_SetVGAPlaneMode ();
816
817 VL_MungePic (signon,320,200);
818 VL_MemToScreen (signon,320,200,0,0);
819}
820
821
822/*
823==========================
824=
825= FinishSignon
826=
827==========================
828*/
829
830void FinishSignon (void)
831{
832#ifndef SPEAR
833 VW_Bar (0,189,300,11,VL_GetPixel(0,0));
834 WindowX = 0;
835 WindowW = 320;
836 PrintY = 190;
837
838 #ifndef JAPAN
839 SETFONTCOLOR(14,4);
840
841 #ifdef SPANISH
842 US_CPrint ("Oprima una tecla");
843 #else
844 US_CPrint ("Press a key");
845 #endif
846
847 #endif
848
849 VH_UpdateScreen();
850
851 if (!param_nowait)
852 IN_Ack ();
853
854 #ifndef JAPAN
855 VW_Bar (0,189,300,11,VL_GetPixel(0,0));
856
857 PrintY = 190;
858 SETFONTCOLOR(10,4);
859
860 #ifdef SPANISH
861 US_CPrint ("pensando...");
862 #else
863 US_CPrint ("Working...");
864 #endif
865
866 VH_UpdateScreen();
867 #endif
868
869 SETFONTCOLOR(0,15);
870#else
871 VH_UpdateScreen();
872
873 if (!param_nowait)
874 VW_WaitVBL(3*70);
875#endif
876}
877
878//===========================================================================
879
880/*
881=====================
882=
883= InitDigiMap
884=
885=====================
886*/
887
888// channel mapping:
889// -1: any non reserved channel
890// 0: player weapons
891// 1: boss weapons
892
893static int wolfdigimap[] =
894 {
895 // These first sounds are in the upload version
896#ifndef SPEAR
897 HALTSND, 0, -1,
898 DOGBARKSND, 1, -1,
899 CLOSEDOORSND, 2, -1,
900 OPENDOORSND, 3, -1,
901 ATKMACHINEGUNSND, 4, 0,
902 ATKPISTOLSND, 5, 0,
903 ATKGATLINGSND, 6, 0,
904 SCHUTZADSND, 7, -1,
905 GUTENTAGSND, 8, -1,
906 MUTTISND, 9, -1,
907 BOSSFIRESND, 10, 1,
908 SSFIRESND, 11, -1,
909 DEATHSCREAM1SND, 12, -1,
910 DEATHSCREAM2SND, 13, -1,
911 DEATHSCREAM3SND, 13, -1,
912 TAKEDAMAGESND, 14, -1,
913 PUSHWALLSND, 15, -1,
914
915 LEBENSND, 20, -1,
916 NAZIFIRESND, 21, -1,
917 SLURPIESND, 22, -1,
918
919 YEAHSND, 32, -1,
920
921#ifndef UPLOAD
922 // These are in all other episodes
923 DOGDEATHSND, 16, -1,
924 AHHHGSND, 17, -1,
925 DIESND, 18, -1,
926 EVASND, 19, -1,
927
928 TOT_HUNDSND, 23, -1,
929 MEINGOTTSND, 24, -1,
930 SCHABBSHASND, 25, -1,
931 HITLERHASND, 26, -1,
932 SPIONSND, 27, -1,
933 NEINSOVASSND, 28, -1,
934 DOGATTACKSND, 29, -1,
935 LEVELDONESND, 30, -1,
936 MECHSTEPSND, 31, -1,
937
938 SCHEISTSND, 33, -1,
939 DEATHSCREAM4SND, 34, -1, // AIIEEE
940 DEATHSCREAM5SND, 35, -1, // DEE-DEE
941 DONNERSND, 36, -1, // EPISODE 4 BOSS DIE
942 EINESND, 37, -1, // EPISODE 4 BOSS SIGHTING
943 ERLAUBENSND, 38, -1, // EPISODE 6 BOSS SIGHTING
944 DEATHSCREAM6SND, 39, -1, // FART
945 DEATHSCREAM7SND, 40, -1, // GASP
946 DEATHSCREAM8SND, 41, -1, // GUH-BOY!
947 DEATHSCREAM9SND, 42, -1, // AH GEEZ!
948 KEINSND, 43, -1, // EPISODE 5 BOSS SIGHTING
949 MEINSND, 44, -1, // EPISODE 6 BOSS DIE
950 ROSESND, 45, -1, // EPISODE 5 BOSS DIE
951
952#endif
953#else
954//
955// SPEAR OF DESTINY DIGISOUNDS
956//
957 HALTSND, 0, -1,
958 CLOSEDOORSND, 2, -1,
959 OPENDOORSND, 3, -1,
960 ATKMACHINEGUNSND, 4, 0,
961 ATKPISTOLSND, 5, 0,
962 ATKGATLINGSND, 6, 0,
963 SCHUTZADSND, 7, -1,
964 BOSSFIRESND, 8, 1,
965 SSFIRESND, 9, -1,
966 DEATHSCREAM1SND, 10, -1,
967 DEATHSCREAM2SND, 11, -1,
968 TAKEDAMAGESND, 12, -1,
969 PUSHWALLSND, 13, -1,
970 AHHHGSND, 15, -1,
971 LEBENSND, 16, -1,
972 NAZIFIRESND, 17, -1,
973 SLURPIESND, 18, -1,
974 LEVELDONESND, 22, -1,
975 DEATHSCREAM4SND, 23, -1, // AIIEEE
976 DEATHSCREAM3SND, 23, -1, // DOUBLY-MAPPED!!!
977 DEATHSCREAM5SND, 24, -1, // DEE-DEE
978 DEATHSCREAM6SND, 25, -1, // FART
979 DEATHSCREAM7SND, 26, -1, // GASP
980 DEATHSCREAM8SND, 27, -1, // GUH-BOY!
981 DEATHSCREAM9SND, 28, -1, // AH GEEZ!
982 GETGATLINGSND, 38, -1, // Got Gat replacement
983
984#ifndef SPEARDEMO
985 DOGBARKSND, 1, -1,
986 DOGDEATHSND, 14, -1,
987 SPIONSND, 19, -1,
988 NEINSOVASSND, 20, -1,
989 DOGATTACKSND, 21, -1,
990 TRANSSIGHTSND, 29, -1, // Trans Sight
991 TRANSDEATHSND, 30, -1, // Trans Death
992 WILHELMSIGHTSND, 31, -1, // Wilhelm Sight
993 WILHELMDEATHSND, 32, -1, // Wilhelm Death
994 UBERDEATHSND, 33, -1, // Uber Death
995 KNIGHTSIGHTSND, 34, -1, // Death Knight Sight
996 KNIGHTDEATHSND, 35, -1, // Death Knight Death
997 ANGELSIGHTSND, 36, -1, // Angel Sight
998 ANGELDEATHSND, 37, -1, // Angel Death
999 GETSPEARSND, 39, -1, // Got Spear replacement
1000#endif
1001#endif
1002 LASTSOUND
1003 };
1004
1005
1006void InitDigiMap (void)
1007{
1008 int *map;
1009
1010 int i = 0;
1011 for (map = wolfdigimap; *map != LASTSOUND; map += 3)
1012 {
1013 rb->splashf(0, "Preparing sounds (%d/%d)", ++i, ARRAYLEN(wolfdigimap)/3);
1014 DigiMap[map[0]] = map[1];
1015 DigiChannel[map[1]] = map[2];
1016 SD_PrepareSound(map[1]);
1017 rb->yield();
1018 }
1019}
1020
1021#ifndef SPEAR
1022CP_iteminfo MusicItems={CTL_X,CTL_Y,6,0,32};
1023CP_itemtype MusicMenu[]=
1024 {
1025 {1,"Get Them!",0},
1026 {1,"Searching",0},
1027 {1,"P.O.W.",0},
1028 {1,"Suspense",0},
1029 {1,"War March",0},
1030 {1,"Around The Corner!",0},
1031
1032 {1,"Nazi Anthem",0},
1033 {1,"Lurking...",0},
1034 {1,"Going After Hitler",0},
1035 {1,"Pounding Headache",0},
1036 {1,"Into the Dungeons",0},
1037 {1,"Ultimate Conquest",0},
1038
1039 {1,"Kill the S.O.B.",0},
1040 {1,"The Nazi Rap",0},
1041 {1,"Twelfth Hour",0},
1042 {1,"Zero Hour",0},
1043 {1,"Ultimate Conquest",0},
1044 {1,"Wolfpack",0}
1045 };
1046#else
1047CP_iteminfo MusicItems={CTL_X,CTL_Y-20,9,0,32};
1048CP_itemtype MusicMenu[]=
1049 {
1050 {1,"Funky Colonel Bill",0},
1051 {1,"Death To The Nazis",0},
1052 {1,"Tiptoeing Around",0},
1053 {1,"Is This THE END?",0},
1054 {1,"Evil Incarnate",0},
1055 {1,"Jazzin' Them Nazis",0},
1056 {1,"Puttin' It To The Enemy",0},
1057 {1,"The SS Gonna Get You",0},
1058 {1,"Towering Above",0}
1059 };
1060#endif
1061
1062#ifndef SPEARDEMO
1063void DoJukebox(void)
1064{
1065 int which,lastsong=-1;
1066 unsigned start;
1067 unsigned songs[]=
1068 {
1069#ifndef SPEAR
1070 GETTHEM_MUS,
1071 SEARCHN_MUS,
1072 POW_MUS,
1073 SUSPENSE_MUS,
1074 WARMARCH_MUS,
1075 CORNER_MUS,
1076
1077 NAZI_OMI_MUS,
1078 PREGNANT_MUS,
1079 GOINGAFT_MUS,
1080 HEADACHE_MUS,
1081 DUNGEON_MUS,
1082 ULTIMATE_MUS,
1083
1084 INTROCW3_MUS,
1085 NAZI_RAP_MUS,
1086 TWELFTH_MUS,
1087 ZEROHOUR_MUS,
1088 ULTIMATE_MUS,
1089 PACMAN_MUS
1090#else
1091 XFUNKIE_MUS, // 0
1092 XDEATH_MUS, // 2
1093 XTIPTOE_MUS, // 4
1094 XTHEEND_MUS, // 7
1095 XEVIL_MUS, // 17
1096 XJAZNAZI_MUS, // 18
1097 XPUTIT_MUS, // 21
1098 XGETYOU_MUS, // 22
1099 XTOWER2_MUS // 23
1100#endif
1101 };
1102
1103 IN_ClearKeysDown();
1104 if (!AdLibPresent && !SoundBlasterPresent)
1105 return;
1106
1107 MenuFadeOut();
1108
1109#ifndef SPEAR
1110#ifndef UPLOAD
1111 start = ((SDL_GetTicks()/10)%3)*6;
1112#else
1113 start = 0;
1114#endif
1115#else
1116 start = 0;
1117#endif
1118
1119 CA_CacheGrChunk (STARTFONT+1);
1120#ifdef SPEAR
1121 CacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END);
1122#else
1123 CacheLump (CONTROLS_LUMP_START,CONTROLS_LUMP_END);
1124#endif
1125 CA_LoadAllSounds ();
1126
1127 fontnumber=1;
1128 ClearMScreen ();
1129 VWB_DrawPic(112,184,C_MOUSELBACKPIC);
1130 DrawStripes (10);
1131 SETFONTCOLOR (TEXTCOLOR,BKGDCOLOR);
1132
1133#ifndef SPEAR
1134 DrawWindow (CTL_X-2,CTL_Y-6,280,13*7,BKGDCOLOR);
1135#else
1136 DrawWindow (CTL_X-2,CTL_Y-26,280,13*10,BKGDCOLOR);
1137#endif
1138
1139 DrawMenu (&MusicItems,&MusicMenu[start]);
1140
1141 SETFONTCOLOR (READHCOLOR,BKGDCOLOR);
1142 PrintY=15;
1143 WindowX = 0;
1144 WindowY = 320;
1145 US_CPrint ("Robert's Jukebox");
1146
1147 SETFONTCOLOR (TEXTCOLOR,BKGDCOLOR);
1148 VW_UpdateScreen();
1149 MenuFadeIn();
1150
1151 do
1152 {
1153 which = HandleMenu(&MusicItems,&MusicMenu[start],NULL);
1154 if (which>=0)
1155 {
1156 if (lastsong >= 0)
1157 MusicMenu[start+lastsong].active = 1;
1158
1159 StartCPMusic(songs[start + which]);
1160 MusicMenu[start+which].active = 2;
1161 DrawMenu (&MusicItems,&MusicMenu[start]);
1162 VW_UpdateScreen();
1163 lastsong = which;
1164 }
1165 } while(which>=0);
1166
1167 MenuFadeOut();
1168 IN_ClearKeysDown();
1169#ifdef SPEAR
1170 UnCacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END);
1171#else
1172 UnCacheLump (CONTROLS_LUMP_START,CONTROLS_LUMP_END);
1173#endif
1174}
1175#endif
1176
1177/*
1178==========================
1179=
1180= InitGame
1181=
1182= Load a few things right away
1183=
1184==========================
1185*/
1186
1187static void InitGame()
1188{
1189#ifndef SPEARDEMO
1190 boolean didjukebox=false;
1191#endif
1192
1193 // initialize SDL
Franklin Wei3f59fc82019-07-07 22:00:20 -04001194 if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
1195 {
1196 printf("Unable to init SDL: %s\n", SDL_GetError());
1197 exit(1);
1198 }
1199
1200 atexit(SDL_Quit);
1201
1202 int numJoysticks = SDL_NumJoysticks();
1203 if(param_joystickindex && (param_joystickindex < -1 || param_joystickindex >= numJoysticks))
1204 {
1205 if(!numJoysticks)
1206 printf("No joysticks are available to SDL!\n");
1207 else
1208 printf("The joystick index must be between -1 and %i!\n", numJoysticks - 1);
1209 exit(1);
1210 }
1211
1212#if defined(GP2X_940)
1213 GP2X_MemoryInit();
1214#endif
1215
1216 SignonScreen ();
Vencislav Atanasov183e45e2019-07-28 23:31:50 +03001217
Franklin Wei3f59fc82019-07-07 22:00:20 -04001218 VH_Startup ();
1219 IN_Startup ();
1220 PM_Startup ();
1221 SD_Startup ();
1222 CA_Startup ();
1223 US_Startup ();
1224
1225 // TODO: Will any memory checking be needed someday??
1226#ifdef NOTYET
1227#ifndef SPEAR
1228 if (mminfo.mainmem < 235000L)
1229#else
1230 if (mminfo.mainmem < 257000L && !MS_CheckParm("debugmode"))
1231#endif
1232 {
1233 byte *screen;
1234
1235 CA_CacheGrChunk (ERRORSCREEN);
1236 screen = grsegs[ERRORSCREEN];
1237 ShutdownId();
1238/* memcpy((byte *)0xb8000,screen+7+7*160,17*160);
1239 gotoxy (1,23);*/
1240 exit(1);
1241 }
1242#endif
1243
1244//
1245// build some tables
1246//
1247 InitDigiMap ();
1248
1249 rb->splash(0, "Reading configuration...");
1250
1251 ReadConfig();
1252
1253 rb->splash(0, "Reading saved games...");
1254
1255 SetupSaveGames();
1256
1257//
1258// HOLDING DOWN 'M' KEY? (Fire for rockbox)
1259//
1260#ifndef SPEARDEMO
Franklin Wei7739ad62019-07-12 15:57:48 -04001261 /* allow entering jukebox */
1262
1263 rb->sleep(HZ / 10);
1264
1265 IN_ProcessEvents();
1266
1267 if (Keyboard[sc_Return])
Franklin Wei3f59fc82019-07-07 22:00:20 -04001268 {
1269 DoJukebox();
1270 didjukebox=true;
1271 }
1272 else
1273#endif
1274
1275//
1276// draw intro screen stuff
1277//
1278 IntroScreen ();
1279
1280#ifdef _arch_dreamcast
1281 //TODO: VMU Selection Screen
1282#endif
1283
1284//
1285// load in and lock down some basic chunks
1286//
1287
1288 rb->splash(0, "Loading...");
1289
1290 CA_CacheGrChunk(STARTFONT);
1291 CA_CacheGrChunk(STATUSBARPIC);
1292
1293 LoadLatchMem ();
1294 BuildTables (); // trig tables
1295 SetupWalls ();
1296
1297 rb->splash(0, "Loading (50%)...");
1298
1299 NewViewSize (viewsize);
1300
1301//
1302// initialize variables
1303//
1304 InitRedShifts ();
1305#ifndef SPEARDEMO
1306 if(!didjukebox)
1307#endif
1308 FinishSignon();
1309
1310#ifdef NOTYET
1311 vdisp = (byte *) (0xa0000+PAGE1START);
1312 vbuf = (byte *) (0xa0000+PAGE2START);
1313#endif
1314}
1315
1316//===========================================================================
1317
1318/*
1319==========================
1320=
1321= SetViewSize
1322=
1323==========================
1324*/
1325
1326boolean SetViewSize (unsigned width, unsigned height)
1327{
1328 viewwidth = width&~15; // must be divisable by 16
1329 viewheight = height&~1; // must be even
1330 centerx = viewwidth/2-1;
1331 shootdelta = viewwidth/10;
1332 if((unsigned) viewheight == screenHeight)
1333 viewscreenx = viewscreeny = screenofs = 0;
1334 else
1335 {
1336 viewscreenx = (screenWidth-viewwidth) / 2;
1337 viewscreeny = (screenHeight-scaleFactor*STATUSLINES-viewheight)/2;
1338 screenofs = viewscreeny*screenWidth+viewscreenx;
1339 }
1340
1341//
1342// calculate trace angles and projection constants
1343//
1344 CalcProjection (FOCALLENGTH);
1345
1346 return true;
1347}
1348
1349
1350void ShowViewSize (int width)
1351{
1352 int oldwidth,oldheight;
1353
1354 oldwidth = viewwidth;
1355 oldheight = viewheight;
1356
1357 if(width == 21)
1358 {
1359 viewwidth = screenWidth;
1360 viewheight = screenHeight;
1361 VWB_BarScaledCoord (0, 0, screenWidth, screenHeight, 0);
1362 }
1363 else if(width == 20)
1364 {
1365 viewwidth = screenWidth;
1366 viewheight = screenHeight - scaleFactor*STATUSLINES;
1367 DrawPlayBorder ();
1368 }
1369 else
1370 {
1371 viewwidth = width*16*screenWidth/320;
1372 viewheight = (int) (width*16*HEIGHTRATIO*screenHeight/200);
1373 DrawPlayBorder ();
1374 }
1375
1376 viewwidth = oldwidth;
1377 viewheight = oldheight;
1378}
1379
1380
1381void NewViewSize (int width)
1382{
1383 viewsize = width;
1384 if(viewsize == 21)
1385 SetViewSize(screenWidth, screenHeight);
1386 else if(viewsize == 20)
1387 SetViewSize(screenWidth, screenHeight - scaleFactor * STATUSLINES);
1388 else
1389 SetViewSize(width*16*screenWidth/320, (unsigned) (width*16*HEIGHTRATIO*screenHeight/200));
1390}
1391
1392
1393
1394//===========================================================================
1395
1396/*
1397==========================
1398=
1399= Quit
1400=
1401==========================
1402*/
1403
1404void Quit (const char *errorStr, ...)
1405{
1406#ifdef NOTYET
1407 byte *screen;
1408#endif
1409 char error[256];
1410 if(errorStr != NULL)
1411 {
1412 va_list vlist;
1413 va_start(vlist, errorStr);
1414 vsprintf(error, errorStr, vlist);
1415 va_end(vlist);
1416 rb->splashf(HZ * 4, "FATAL: %s", error);
1417 }
1418 else error[0] = 0;
1419
1420 if (!pictable) // don't try to display the red box before it's loaded
1421 {
1422 ShutdownId();
1423 if (error && *error)
1424 {
1425#ifdef NOTYET
1426 SetTextCursor(0,0);
1427#endif
1428 puts(error);
1429#ifdef NOTYET
1430 SetTextCursor(0,2);
1431#endif
1432 VW_WaitVBL(100);
1433 }
1434 exit(1);
1435 }
1436
1437 if (!error || !*error)
1438 {
1439#ifdef NOTYET
1440 #ifndef JAPAN
1441 CA_CacheGrChunk (ORDERSCREEN);
1442 screen = grsegs[ORDERSCREEN];
1443 #endif
1444#endif
1445 WriteConfig ();
1446 }
1447#ifdef NOTYET
1448 else
1449 {
1450 CA_CacheGrChunk (ERRORSCREEN);
1451 screen = grsegs[ERRORSCREEN];
1452 }
1453#endif
1454
1455 ShutdownId ();
1456
1457 if (error && *error)
1458 {
1459#ifdef NOTYET
1460 memcpy((byte *)0xb8000,screen+7,7*160);
1461 SetTextCursor(9,3);
1462#endif
1463 puts(error);
1464#ifdef NOTYET
1465 SetTextCursor(0,7);
1466#endif
1467 VW_WaitVBL(200);
1468 exit(1);
1469 }
1470 else
1471 if (!error || !(*error))
1472 {
1473#ifdef NOTYET
1474 #ifndef JAPAN
1475 memcpy((byte *)0xb8000,screen+7,24*160); // 24 for SPEAR/UPLOAD compatibility
1476 #endif
1477 SetTextCursor(0,23);
1478#endif
1479 }
1480
1481 exit(0);
1482}
1483
1484//===========================================================================
1485
1486
1487
1488/*
1489=====================
1490=
1491= DemoLoop
1492=
1493=====================
1494*/
1495
1496
1497static void DemoLoop()
1498{
1499 int LastDemo = 0;
1500
1501//
1502// check for launch from ted
1503//
1504 if (param_tedlevel != -1)
1505 {
1506 param_nowait = true;
1507 EnableEndGameMenuItem();
1508 NewGame(param_difficulty,0);
1509
1510#ifndef SPEAR
1511 gamestate.episode = param_tedlevel/10;
1512 gamestate.mapon = param_tedlevel%10;
1513#else
1514 gamestate.episode = 0;
1515 gamestate.mapon = param_tedlevel;
1516#endif
1517 GameLoop();
1518 Quit (NULL);
1519 }
1520
1521
1522//
1523// main game cycle
1524//
1525
1526#ifndef DEMOTEST
1527
1528 #ifndef UPLOAD
1529
1530 #ifndef GOODTIMES
1531 #ifndef SPEAR
1532 #ifndef JAPAN
1533 if (!param_nowait)
1534 NonShareware();
1535 #endif
1536 #else
1537 #ifndef GOODTIMES
1538 #ifndef SPEARDEMO
1539 extern void CopyProtection(void);
1540 if(!param_goodtimes)
1541 CopyProtection();
1542 #endif
1543 #endif
1544 #endif
1545 #endif
1546 #endif
1547
1548 StartCPMusic(INTROSONG);
1549
1550#ifndef JAPAN
1551 if (!param_nowait)
1552 PG13 ();
1553#endif
1554
1555#endif
1556
1557 while (1)
1558 {
1559 while (!param_nowait)
1560 {
1561//
1562// title page
1563//
1564#ifndef DEMOTEST
1565
1566#ifdef SPEAR
1567 SDL_Color pal[256];
1568 CA_CacheGrChunk (TITLEPALETTE);
1569 VL_ConvertPalette(grsegs[TITLEPALETTE], pal, 256);
1570
1571 CA_CacheGrChunk (TITLE1PIC);
1572 VWB_DrawPic (0,0,TITLE1PIC);
1573 UNCACHEGRCHUNK (TITLE1PIC);
1574
1575 CA_CacheGrChunk (TITLE2PIC);
1576 VWB_DrawPic (0,80,TITLE2PIC);
1577 UNCACHEGRCHUNK (TITLE2PIC);
1578 VW_UpdateScreen ();
1579 VL_FadeIn(0,255,pal,30);
1580
1581 UNCACHEGRCHUNK (TITLEPALETTE);
1582#else
1583 CA_CacheScreen (TITLEPIC);
1584 VW_UpdateScreen ();
1585 VW_FadeIn();
1586#endif
1587 if (IN_UserInput(TickBase*15))
1588 break;
1589 VW_FadeOut();
1590//
1591// credits page
1592//
1593 CA_CacheScreen (CREDITSPIC);
1594 VW_UpdateScreen();
1595 VW_FadeIn ();
1596 if (IN_UserInput(TickBase*10))
1597 break;
1598 VW_FadeOut ();
1599//
1600// high scores
1601//
1602 DrawHighScores ();
1603 VW_UpdateScreen ();
1604 VW_FadeIn ();
1605
1606 if (IN_UserInput(TickBase*10))
1607 break;
1608#endif
1609//
1610// demo
1611//
1612
1613 #ifndef SPEARDEMO
1614 PlayDemo (LastDemo++%4);
1615 #else
1616 PlayDemo (0);
1617 #endif
1618
1619 if (playstate == ex_abort)
1620 break;
1621 VW_FadeOut();
1622 if(screenHeight % 200 != 0)
1623 VL_ClearScreen(0);
1624 StartCPMusic(INTROSONG);
1625 }
1626
1627 VW_FadeOut ();
1628
1629#ifdef DEBUGKEYS
1630 if (Keyboard[sc_Tab] && param_debugmode)
1631 RecordDemo ();
1632 else
1633 US_ControlPanel (0);
1634#else
1635 US_ControlPanel (0);
1636#endif
1637
1638 if (startgame || loadedgame)
1639 {
1640 GameLoop ();
1641 if(!param_nowait)
1642 {
1643 VW_FadeOut();
1644 StartCPMusic(INTROSONG);
1645 }
1646 }
1647 }
1648}
1649
1650
1651//===========================================================================
1652
1653#define IFARG(str) if(!strcmp(arg, (str)))
1654
1655void CheckParameters(int argc, char *argv[])
1656{
1657 bool hasError = false, showHelp = false;
1658 bool sampleRateGiven = false, audioBufferGiven = false;
1659 int defaultSampleRate = param_samplerate;
1660
1661 for(int i = 1; i < argc; i++)
1662 {
1663 char *arg = argv[i];
1664#ifndef SPEAR
1665 IFARG("--goobers")
1666#else
1667 IFARG("--debugmode")
1668#endif
1669 param_debugmode = true;
1670 else IFARG("--baby")
1671 param_difficulty = 0;
1672 else IFARG("--easy")
1673 param_difficulty = 1;
1674 else IFARG("--normal")
1675 param_difficulty = 2;
1676 else IFARG("--hard")
1677 param_difficulty = 3;
1678 else IFARG("--nowait")
1679 param_nowait = true;
1680 else IFARG("--tedlevel")
1681 {
1682 if(++i >= argc)
1683 {
1684 printf("The tedlevel option is missing the level argument!\n");
1685 hasError = true;
1686 }
1687 else param_tedlevel = atoi(argv[i]);
1688 }
1689 else IFARG("--windowed")
1690 fullscreen = false;
1691 else IFARG("--windowed-mouse")
1692 {
1693 fullscreen = false;
1694 forcegrabmouse = true;
1695 }
1696 else IFARG("--res")
1697 {
1698 if(i + 2 >= argc)
1699 {
1700 printf("The res option needs the width and/or the height argument!\n");
1701 hasError = true;
1702 }
1703 else
1704 {
1705 screenWidth = atoi(argv[++i]);
1706 screenHeight = atoi(argv[++i]);
1707 unsigned factor = screenWidth / 320;
1708 if(screenWidth % 320 || screenHeight != 200 * factor && screenHeight != 240 * factor)
1709 printf("Screen size must be a multiple of 320x200 or 320x240!\n"), hasError = true;
1710 }
1711 }
1712 else IFARG("--resf")
1713 {
1714 if(i + 2 >= argc)
1715 {
1716 printf("The resf option needs the width and/or the height argument!\n");
1717 hasError = true;
1718 }
1719 else
1720 {
1721 screenWidth = atoi(argv[++i]);
1722 screenHeight = atoi(argv[++i]);
1723 if(screenWidth < 320)
1724 printf("Screen width must be at least 320!\n"), hasError = true;
1725 if(screenHeight < 200)
1726 printf("Screen height must be at least 200!\n"), hasError = true;
1727 }
1728 }
1729 else IFARG("--bits")
1730 {
1731 if(++i >= argc)
1732 {
1733 printf("The bits option is missing the color depth argument!\n");
1734 hasError = true;
1735 }
1736 else
1737 {
1738 screenBits = atoi(argv[i]);
1739 switch(screenBits)
1740 {
1741 case 8:
1742 case 16:
1743 case 24:
1744 case 32:
1745 break;
1746
1747 default:
1748 printf("Screen color depth must be 8, 16, 24, or 32!\n");
1749 hasError = true;
1750 break;
1751 }
1752 }
1753 }
1754 else IFARG("--nodblbuf")
1755 usedoublebuffering = false;
1756 else IFARG("--extravbls")
1757 {
1758 if(++i >= argc)
1759 {
1760 printf("The extravbls option is missing the vbls argument!\n");
1761 hasError = true;
1762 }
1763 else
1764 {
1765 extravbls = atoi(argv[i]);
1766 if(extravbls < 0)
1767 {
1768 printf("Extravbls must be positive!\n");
1769 hasError = true;
1770 }
1771 }
1772 }
1773 else IFARG("--joystick")
1774 {
1775 if(++i >= argc)
1776 {
1777 printf("The joystick option is missing the index argument!\n");
1778 hasError = true;
1779 }
1780 else param_joystickindex = atoi(argv[i]); // index is checked in InitGame
1781 }
1782 else IFARG("--joystickhat")
1783 {
1784 if(++i >= argc)
1785 {
1786 printf("The joystickhat option is missing the index argument!\n");
1787 hasError = true;
1788 }
1789 else param_joystickhat = atoi(argv[i]);
1790 }
1791 else IFARG("--samplerate")
1792 {
1793 if(++i >= argc)
1794 {
1795 printf("The samplerate option is missing the rate argument!\n");
1796 hasError = true;
1797 }
1798 else param_samplerate = atoi(argv[i]);
1799 sampleRateGiven = true;
1800 }
1801 else IFARG("--audiobuffer")
1802 {
1803 if(++i >= argc)
1804 {
1805 printf("The audiobuffer option is missing the size argument!\n");
1806 hasError = true;
1807 }
1808 else param_audiobuffer = atoi(argv[i]);
1809 audioBufferGiven = true;
1810 }
1811 else IFARG("--mission")
1812 {
1813 if(++i >= argc)
1814 {
1815 printf("The mission option is missing the mission argument!\n");
1816 hasError = true;
1817 }
1818 else
1819 {
1820 param_mission = atoi(argv[i]);
1821 if(param_mission < 0 || param_mission > 3)
1822 {
1823 printf("The mission option must be between 0 and 3!\n");
1824 hasError = true;
1825 }
1826 }
1827 }
1828 else IFARG("--configdir")
1829 {
1830 if(++i >= argc)
1831 {
1832 printf("The configdir option is missing the dir argument!\n");
1833 hasError = true;
1834 }
1835 else
1836 {
1837 size_t len = strlen(argv[i]);
1838 if(len + 2 > sizeof(configdir))
1839 {
1840 printf("The config directory is too long!\n");
1841 hasError = true;
1842 }
1843 else
1844 {
1845 strcpy(configdir, argv[i]);
1846 if(argv[i][len] != '/' && argv[i][len] != '\\')
1847 strcat(configdir, "/");
1848 }
1849 }
1850 }
1851 else IFARG("--goodtimes")
1852 param_goodtimes = true;
1853 else IFARG("--ignorenumchunks")
1854 param_ignorenumchunks = true;
1855 else IFARG("--help")
1856 showHelp = true;
1857 else hasError = true;
1858 }
1859 if(hasError || showHelp)
1860 {
1861 if(hasError) printf("\n");
1862 printf(
1863 "Wolf4SDL v1.7 ($Revision: 256 $)\n"
1864 "Ported by Chaos-Software (http://www.chaos-software.de.vu)\n"
1865 "Original Wolfenstein 3D by id Software\n\n"
1866 "Usage: Wolf4SDL [options]\n"
1867 "Options:\n"
1868 " --help This help page\n"
1869 " --tedlevel <level> Starts the game in the given level\n"
1870 " --baby Sets the difficulty to baby for tedlevel\n"
1871 " --easy Sets the difficulty to easy for tedlevel\n"
1872 " --normal Sets the difficulty to normal for tedlevel\n"
1873 " --hard Sets the difficulty to hard for tedlevel\n"
1874 " --nowait Skips intro screens\n"
1875 " --windowed[-mouse] Starts the game in a window [and grabs mouse]\n"
1876 " --res <width> <height> Sets the screen resolution\n"
1877 " (must be multiple of 320x200 or 320x240)\n"
1878 " --resf <w> <h> Sets any screen resolution >= 320x200\n"
1879 " (which may result in graphic errors)\n"
1880 " --bits <b> Sets the screen color depth\n"
1881 " (use this when you have palette/fading problems\n"
1882 " allowed: 8, 16, 24, 32, default: \"best\" depth)\n"
1883 " --nodblbuf Don't use SDL's double buffering\n"
1884 " --extravbls <vbls> Sets a delay after each frame, which may help to\n"
1885 " reduce flickering (unit is currently 8 ms, default: 0)\n"
1886 " --joystick <index> Use the index-th joystick if available\n"
1887 " (-1 to disable joystick, default: 0)\n"
1888 " --joystickhat <index> Enables movement with the given coolie hat\n"
1889 " --samplerate <rate> Sets the sound sample rate (given in Hz, default: %i)\n"
1890 " --audiobuffer <size> Sets the size of the audio buffer (-> sound latency)\n"
1891 " (given in bytes, default: 2048 / (44100 / samplerate))\n"
1892 " --ignorenumchunks Ignores the number of chunks in VGAHEAD.*\n"
1893 " (may be useful for some broken mods)\n"
1894 " --configdir <dir> Directory where config file and save games are stored\n"
Franklin Wei3f59fc82019-07-07 22:00:20 -04001895 " (default: $HOME/.wolf4sdl)\n"
Franklin Wei3f59fc82019-07-07 22:00:20 -04001896#if defined(SPEAR) && !defined(SPEARDEMO)
1897 " --mission <mission> Mission number to play (0-3)\n"
1898 " (default: 0 -> .sod, 1-3 -> .sd*)\n"
1899 " --goodtimes Disable copy protection quiz\n"
1900#endif
1901 , defaultSampleRate
1902 );
1903 exit(1);
1904 }
1905
1906 if(sampleRateGiven && !audioBufferGiven)
1907 param_audiobuffer = 2048 / (44100 / param_samplerate);
1908}
1909
1910/*
1911==========================
1912=
1913= main
1914=
1915==========================
1916*/
1917
1918#define main my_main
1919
1920int main (int argc, char *argv[])
1921{
1922#if defined(_arch_dreamcast)
1923 DC_Init();
1924#else
1925 CheckParameters(argc, argv);
1926#endif
1927
1928 CheckForEpisodes();
1929
1930 InitGame();
1931
1932 DemoLoop();
1933
1934 Quit("Demo loop exited???");
1935 return 1;
1936}