WL_MAIN.C (31907B)
1 // WL_MAIN.C 2 3 #include <conio.h> 4 #include "WL_DEF.H" 5 #pragma hdrstop 6 7 8 /* 9 ============================================================================= 10 11 WOLFENSTEIN 3-D 12 13 An Id Software production 14 15 by John Carmack 16 17 ============================================================================= 18 */ 19 20 /* 21 ============================================================================= 22 23 LOCAL CONSTANTS 24 25 ============================================================================= 26 */ 27 28 29 #define FOCALLENGTH (0x5700l) // in global coordinates 30 #define VIEWGLOBAL 0x10000 // globals visable flush to wall 31 32 #define VIEWWIDTH 256 // size of view window 33 #define VIEWHEIGHT 144 34 35 /* 36 ============================================================================= 37 38 GLOBAL VARIABLES 39 40 ============================================================================= 41 */ 42 43 char str[80],str2[20]; 44 int tedlevelnum; 45 boolean tedlevel; 46 boolean nospr; 47 boolean IsA386; 48 int dirangle[9] = {0,ANGLES/8,2*ANGLES/8,3*ANGLES/8,4*ANGLES/8, 49 5*ANGLES/8,6*ANGLES/8,7*ANGLES/8,ANGLES}; 50 51 // 52 // proejection variables 53 // 54 fixed focallength; 55 unsigned screenofs; 56 int viewwidth; 57 int viewheight; 58 int centerx; 59 int shootdelta; // pixels away from centerx a target can be 60 fixed scale,maxslope; 61 long heightnumerator; 62 int minheightdiv; 63 64 65 void Quit (char *error); 66 67 boolean startgame,loadedgame,virtualreality; 68 int mouseadjustment; 69 70 char configname[13]="CONFIG."; 71 72 73 /* 74 ============================================================================= 75 76 LOCAL VARIABLES 77 78 ============================================================================= 79 */ 80 81 82 /* 83 ==================== 84 = 85 = ReadConfig 86 = 87 ==================== 88 */ 89 90 void ReadConfig(void) 91 { 92 int file; 93 SDMode sd; 94 SMMode sm; 95 SDSMode sds; 96 97 98 if ( (file = open(configname,O_BINARY | O_RDONLY)) != -1) 99 { 100 // 101 // valid config file 102 // 103 read(file,Scores,sizeof(HighScore) * MaxScores); 104 105 read(file,&sd,sizeof(sd)); 106 read(file,&sm,sizeof(sm)); 107 read(file,&sds,sizeof(sds)); 108 109 read(file,&mouseenabled,sizeof(mouseenabled)); 110 read(file,&joystickenabled,sizeof(joystickenabled)); 111 read(file,&joypadenabled,sizeof(joypadenabled)); 112 read(file,&joystickprogressive,sizeof(joystickprogressive)); 113 read(file,&joystickport,sizeof(joystickport)); 114 115 read(file,&dirscan,sizeof(dirscan)); 116 read(file,&buttonscan,sizeof(buttonscan)); 117 read(file,&buttonmouse,sizeof(buttonmouse)); 118 read(file,&buttonjoy,sizeof(buttonjoy)); 119 120 read(file,&viewsize,sizeof(viewsize)); 121 read(file,&mouseadjustment,sizeof(mouseadjustment)); 122 123 close(file); 124 125 if (sd == sdm_AdLib && !AdLibPresent && !SoundBlasterPresent) 126 { 127 sd = sdm_PC; 128 sd = smm_Off; 129 } 130 131 if ((sds == sds_SoundBlaster && !SoundBlasterPresent) || 132 (sds == sds_SoundSource && !SoundSourcePresent)) 133 sds = sds_Off; 134 135 if (!MousePresent) 136 mouseenabled = false; 137 if (!JoysPresent[joystickport]) 138 joystickenabled = false; 139 140 MainMenu[6].active=1; 141 MainItems.curpos=0; 142 } 143 else 144 { 145 // 146 // no config file, so select by hardware 147 // 148 if (SoundBlasterPresent || AdLibPresent) 149 { 150 sd = sdm_AdLib; 151 sm = smm_AdLib; 152 } 153 else 154 { 155 sd = sdm_PC; 156 sm = smm_Off; 157 } 158 159 if (SoundBlasterPresent) 160 sds = sds_SoundBlaster; 161 else if (SoundSourcePresent) 162 sds = sds_SoundSource; 163 else 164 sds = sds_Off; 165 166 if (MousePresent) 167 mouseenabled = true; 168 169 joystickenabled = false; 170 joypadenabled = false; 171 joystickport = 0; 172 joystickprogressive = false; 173 174 viewsize = 15; 175 mouseadjustment=5; 176 } 177 178 SD_SetMusicMode (sm); 179 SD_SetSoundMode (sd); 180 SD_SetDigiDevice (sds); 181 182 } 183 184 185 /* 186 ==================== 187 = 188 = WriteConfig 189 = 190 ==================== 191 */ 192 193 void WriteConfig(void) 194 { 195 int file; 196 197 file = open(configname,O_CREAT | O_BINARY | O_WRONLY, 198 S_IREAD | S_IWRITE | S_IFREG); 199 200 if (file != -1) 201 { 202 write(file,Scores,sizeof(HighScore) * MaxScores); 203 204 write(file,&SoundMode,sizeof(SoundMode)); 205 write(file,&MusicMode,sizeof(MusicMode)); 206 write(file,&DigiMode,sizeof(DigiMode)); 207 208 write(file,&mouseenabled,sizeof(mouseenabled)); 209 write(file,&joystickenabled,sizeof(joystickenabled)); 210 write(file,&joypadenabled,sizeof(joypadenabled)); 211 write(file,&joystickprogressive,sizeof(joystickprogressive)); 212 write(file,&joystickport,sizeof(joystickport)); 213 214 write(file,&dirscan,sizeof(dirscan)); 215 write(file,&buttonscan,sizeof(buttonscan)); 216 write(file,&buttonmouse,sizeof(buttonmouse)); 217 write(file,&buttonjoy,sizeof(buttonjoy)); 218 219 write(file,&viewsize,sizeof(viewsize)); 220 write(file,&mouseadjustment,sizeof(mouseadjustment)); 221 222 close(file); 223 } 224 } 225 226 227 //=========================================================================== 228 229 230 /* 231 ======================== 232 = 233 = Patch386 234 = 235 = Patch ldiv to use 32 bit instructions 236 = 237 ======================== 238 */ 239 240 char *JHParmStrings[] = {"no386",nil}; 241 void Patch386 (void) 242 { 243 extern void far jabhack2(void); 244 extern int far CheckIs386(void); 245 246 int i; 247 248 for (i = 1;i < _argc;i++) 249 if (US_CheckParm(_argv[i],JHParmStrings) == 0) 250 { 251 IsA386 = false; 252 return; 253 } 254 255 if (CheckIs386()) 256 { 257 IsA386 = true; 258 jabhack2(); 259 } 260 else 261 IsA386 = false; 262 } 263 264 //=========================================================================== 265 266 /* 267 ===================== 268 = 269 = NewGame 270 = 271 = Set up new game to start from the beginning 272 = 273 ===================== 274 */ 275 276 void NewGame (int difficulty,int episode) 277 { 278 memset (&gamestate,0,sizeof(gamestate)); 279 gamestate.difficulty = difficulty; 280 gamestate.weapon = gamestate.bestweapon 281 = gamestate.chosenweapon = wp_pistol; 282 gamestate.health = 100; 283 gamestate.ammo = STARTAMMO; 284 gamestate.lives = 3; 285 gamestate.nextextra = EXTRAPOINTS; 286 gamestate.episode=episode; 287 288 startgame = true; 289 } 290 291 //=========================================================================== 292 293 void DiskFlopAnim(int x,int y) 294 { 295 static char which=0; 296 if (!x && !y) 297 return; 298 VWB_DrawPic(x,y,C_DISKLOADING1PIC+which); 299 VW_UpdateScreen(); 300 which^=1; 301 } 302 303 304 long DoChecksum(byte far *source,unsigned size,long checksum) 305 { 306 unsigned i; 307 308 for (i=0;i<size-1;i++) 309 checksum += source[i]^source[i+1]; 310 311 return checksum; 312 } 313 314 315 /* 316 ================== 317 = 318 = SaveTheGame 319 = 320 ================== 321 */ 322 323 boolean SaveTheGame(int file,int x,int y) 324 { 325 struct diskfree_t dfree; 326 long avail,size,checksum; 327 objtype *ob,nullobj; 328 329 330 if (_dos_getdiskfree(0,&dfree)) 331 Quit("Error in _dos_getdiskfree call"); 332 333 avail = (long)dfree.avail_clusters * 334 dfree.bytes_per_sector * 335 dfree.sectors_per_cluster; 336 337 size = 0; 338 for (ob = player; ob ; ob=ob->next) 339 size += sizeof(*ob); 340 size += sizeof(nullobj); 341 342 size += sizeof(gamestate) + 343 sizeof(LRstruct)*8 + 344 sizeof(tilemap) + 345 sizeof(actorat) + 346 sizeof(laststatobj) + 347 sizeof(statobjlist) + 348 sizeof(doorposition) + 349 sizeof(pwallstate) + 350 sizeof(pwallx) + 351 sizeof(pwally) + 352 sizeof(pwalldir) + 353 sizeof(pwallpos); 354 355 if (avail < size) 356 { 357 Message(STR_NOSPACE1"\n" 358 STR_NOSPACE2); 359 return false; 360 } 361 362 checksum = 0; 363 364 365 DiskFlopAnim(x,y); 366 CA_FarWrite (file,(void far *)&gamestate,sizeof(gamestate)); 367 checksum = DoChecksum((byte far *)&gamestate,sizeof(gamestate),checksum); 368 369 DiskFlopAnim(x,y); 370 #ifdef SPEAR 371 CA_FarWrite (file,(void far *)&LevelRatios[0],sizeof(LRstruct)*20); 372 checksum = DoChecksum((byte far *)&LevelRatios[0],sizeof(LRstruct)*20,checksum); 373 #else 374 CA_FarWrite (file,(void far *)&LevelRatios[0],sizeof(LRstruct)*8); 375 checksum = DoChecksum((byte far *)&LevelRatios[0],sizeof(LRstruct)*8,checksum); 376 #endif 377 378 DiskFlopAnim(x,y); 379 CA_FarWrite (file,(void far *)tilemap,sizeof(tilemap)); 380 checksum = DoChecksum((byte far *)tilemap,sizeof(tilemap),checksum); 381 DiskFlopAnim(x,y); 382 CA_FarWrite (file,(void far *)actorat,sizeof(actorat)); 383 checksum = DoChecksum((byte far *)actorat,sizeof(actorat),checksum); 384 385 CA_FarWrite (file,(void far *)areaconnect,sizeof(areaconnect)); 386 CA_FarWrite (file,(void far *)areabyplayer,sizeof(areabyplayer)); 387 388 for (ob = player ; ob ; ob=ob->next) 389 { 390 DiskFlopAnim(x,y); 391 CA_FarWrite (file,(void far *)ob,sizeof(*ob)); 392 } 393 nullobj.active = ac_badobject; // end of file marker 394 DiskFlopAnim(x,y); 395 CA_FarWrite (file,(void far *)&nullobj,sizeof(nullobj)); 396 397 398 399 DiskFlopAnim(x,y); 400 CA_FarWrite (file,(void far *)&laststatobj,sizeof(laststatobj)); 401 checksum = DoChecksum((byte far *)&laststatobj,sizeof(laststatobj),checksum); 402 DiskFlopAnim(x,y); 403 CA_FarWrite (file,(void far *)statobjlist,sizeof(statobjlist)); 404 checksum = DoChecksum((byte far *)statobjlist,sizeof(statobjlist),checksum); 405 406 DiskFlopAnim(x,y); 407 CA_FarWrite (file,(void far *)doorposition,sizeof(doorposition)); 408 checksum = DoChecksum((byte far *)doorposition,sizeof(doorposition),checksum); 409 DiskFlopAnim(x,y); 410 CA_FarWrite (file,(void far *)doorobjlist,sizeof(doorobjlist)); 411 checksum = DoChecksum((byte far *)doorobjlist,sizeof(doorobjlist),checksum); 412 413 DiskFlopAnim(x,y); 414 CA_FarWrite (file,(void far *)&pwallstate,sizeof(pwallstate)); 415 checksum = DoChecksum((byte far *)&pwallstate,sizeof(pwallstate),checksum); 416 CA_FarWrite (file,(void far *)&pwallx,sizeof(pwallx)); 417 checksum = DoChecksum((byte far *)&pwallx,sizeof(pwallx),checksum); 418 CA_FarWrite (file,(void far *)&pwally,sizeof(pwally)); 419 checksum = DoChecksum((byte far *)&pwally,sizeof(pwally),checksum); 420 CA_FarWrite (file,(void far *)&pwalldir,sizeof(pwalldir)); 421 checksum = DoChecksum((byte far *)&pwalldir,sizeof(pwalldir),checksum); 422 CA_FarWrite (file,(void far *)&pwallpos,sizeof(pwallpos)); 423 checksum = DoChecksum((byte far *)&pwallpos,sizeof(pwallpos),checksum); 424 425 // 426 // WRITE OUT CHECKSUM 427 // 428 CA_FarWrite (file,(void far *)&checksum,sizeof(checksum)); 429 430 return(true); 431 } 432 433 //=========================================================================== 434 435 /* 436 ================== 437 = 438 = LoadTheGame 439 = 440 ================== 441 */ 442 443 boolean LoadTheGame(int file,int x,int y) 444 { 445 long checksum,oldchecksum; 446 objtype *ob,nullobj; 447 448 449 checksum = 0; 450 451 DiskFlopAnim(x,y); 452 CA_FarRead (file,(void far *)&gamestate,sizeof(gamestate)); 453 checksum = DoChecksum((byte far *)&gamestate,sizeof(gamestate),checksum); 454 455 DiskFlopAnim(x,y); 456 #ifdef SPEAR 457 CA_FarRead (file,(void far *)&LevelRatios[0],sizeof(LRstruct)*20); 458 checksum = DoChecksum((byte far *)&LevelRatios[0],sizeof(LRstruct)*20,checksum); 459 #else 460 CA_FarRead (file,(void far *)&LevelRatios[0],sizeof(LRstruct)*8); 461 checksum = DoChecksum((byte far *)&LevelRatios[0],sizeof(LRstruct)*8,checksum); 462 #endif 463 464 DiskFlopAnim(x,y); 465 SetupGameLevel (); 466 467 DiskFlopAnim(x,y); 468 CA_FarRead (file,(void far *)tilemap,sizeof(tilemap)); 469 checksum = DoChecksum((byte far *)tilemap,sizeof(tilemap),checksum); 470 DiskFlopAnim(x,y); 471 CA_FarRead (file,(void far *)actorat,sizeof(actorat)); 472 checksum = DoChecksum((byte far *)actorat,sizeof(actorat),checksum); 473 474 CA_FarRead (file,(void far *)areaconnect,sizeof(areaconnect)); 475 CA_FarRead (file,(void far *)areabyplayer,sizeof(areabyplayer)); 476 477 478 479 InitActorList (); 480 DiskFlopAnim(x,y); 481 CA_FarRead (file,(void far *)player,sizeof(*player)); 482 483 while (1) 484 { 485 DiskFlopAnim(x,y); 486 CA_FarRead (file,(void far *)&nullobj,sizeof(nullobj)); 487 if (nullobj.active == ac_badobject) 488 break; 489 GetNewActor (); 490 // don't copy over the links 491 memcpy (new,&nullobj,sizeof(nullobj)-4); 492 } 493 494 495 496 DiskFlopAnim(x,y); 497 CA_FarRead (file,(void far *)&laststatobj,sizeof(laststatobj)); 498 checksum = DoChecksum((byte far *)&laststatobj,sizeof(laststatobj),checksum); 499 DiskFlopAnim(x,y); 500 CA_FarRead (file,(void far *)statobjlist,sizeof(statobjlist)); 501 checksum = DoChecksum((byte far *)statobjlist,sizeof(statobjlist),checksum); 502 503 DiskFlopAnim(x,y); 504 CA_FarRead (file,(void far *)doorposition,sizeof(doorposition)); 505 checksum = DoChecksum((byte far *)doorposition,sizeof(doorposition),checksum); 506 DiskFlopAnim(x,y); 507 CA_FarRead (file,(void far *)doorobjlist,sizeof(doorobjlist)); 508 checksum = DoChecksum((byte far *)doorobjlist,sizeof(doorobjlist),checksum); 509 510 DiskFlopAnim(x,y); 511 CA_FarRead (file,(void far *)&pwallstate,sizeof(pwallstate)); 512 checksum = DoChecksum((byte far *)&pwallstate,sizeof(pwallstate),checksum); 513 CA_FarRead (file,(void far *)&pwallx,sizeof(pwallx)); 514 checksum = DoChecksum((byte far *)&pwallx,sizeof(pwallx),checksum); 515 CA_FarRead (file,(void far *)&pwally,sizeof(pwally)); 516 checksum = DoChecksum((byte far *)&pwally,sizeof(pwally),checksum); 517 CA_FarRead (file,(void far *)&pwalldir,sizeof(pwalldir)); 518 checksum = DoChecksum((byte far *)&pwalldir,sizeof(pwalldir),checksum); 519 CA_FarRead (file,(void far *)&pwallpos,sizeof(pwallpos)); 520 checksum = DoChecksum((byte far *)&pwallpos,sizeof(pwallpos),checksum); 521 522 CA_FarRead (file,(void far *)&oldchecksum,sizeof(oldchecksum)); 523 524 if (oldchecksum != checksum) 525 { 526 Message(STR_SAVECHT1"\n" 527 STR_SAVECHT2"\n" 528 STR_SAVECHT3"\n" 529 STR_SAVECHT4); 530 531 IN_ClearKeysDown(); 532 IN_Ack(); 533 534 gamestate.score = 0; 535 gamestate.lives = 1; 536 gamestate.weapon = 537 gamestate.chosenweapon = 538 gamestate.bestweapon = wp_pistol; 539 gamestate.ammo = 8; 540 } 541 542 return true; 543 } 544 545 //=========================================================================== 546 547 /* 548 ========================== 549 = 550 = ShutdownId 551 = 552 = Shuts down all ID_?? managers 553 = 554 ========================== 555 */ 556 557 void ShutdownId (void) 558 { 559 US_Shutdown (); 560 SD_Shutdown (); 561 PM_Shutdown (); 562 IN_Shutdown (); 563 VW_Shutdown (); 564 CA_Shutdown (); 565 MM_Shutdown (); 566 } 567 568 569 //=========================================================================== 570 571 /* 572 ================== 573 = 574 = BuildTables 575 = 576 = Calculates: 577 = 578 = scale projection constant 579 = sintable/costable overlapping fractional tables 580 = 581 ================== 582 */ 583 584 const float radtoint = (float)FINEANGLES/2/PI; 585 586 void BuildTables (void) 587 { 588 int i; 589 float angle,anglestep; 590 double tang; 591 fixed value; 592 593 594 // 595 // calculate fine tangents 596 // 597 598 for (i=0;i<FINEANGLES/8;i++) 599 { 600 tang = tan( (i+0.5)/radtoint); 601 finetangent[i] = tang*TILEGLOBAL; 602 finetangent[FINEANGLES/4-1-i] = 1/tang*TILEGLOBAL; 603 } 604 605 // 606 // costable overlays sintable with a quarter phase shift 607 // ANGLES is assumed to be divisable by four 608 // 609 // The low word of the value is the fraction, the high bit is the sign bit, 610 // bits 16-30 should be 0 611 // 612 613 angle = 0; 614 anglestep = PI/2/ANGLEQUAD; 615 for (i=0;i<=ANGLEQUAD;i++) 616 { 617 value=GLOBAL1*sin(angle); 618 sintable[i]= 619 sintable[i+ANGLES]= 620 sintable[ANGLES/2-i] = value; 621 sintable[ANGLES-i]= 622 sintable[ANGLES/2+i] = value | 0x80000000l; 623 angle += anglestep; 624 } 625 626 } 627 628 //=========================================================================== 629 630 631 /* 632 ==================== 633 = 634 = CalcProjection 635 = 636 = Uses focallength 637 = 638 ==================== 639 */ 640 641 void CalcProjection (long focal) 642 { 643 int i; 644 long intang; 645 float angle; 646 double tang; 647 double planedist; 648 double globinhalf; 649 int halfview; 650 double halfangle,facedist; 651 652 653 focallength = focal; 654 facedist = focal+MINDIST; 655 halfview = viewwidth/2; // half view in pixels 656 657 // 658 // calculate scale value for vertical height calculations 659 // and sprite x calculations 660 // 661 scale = halfview*facedist/(VIEWGLOBAL/2); 662 663 // 664 // divide heightnumerator by a posts distance to get the posts height for 665 // the heightbuffer. The pixel height is height>>2 666 // 667 heightnumerator = (TILEGLOBAL*scale)>>6; 668 minheightdiv = heightnumerator/0x7fff +1; 669 670 // 671 // calculate the angle offset from view angle of each pixel's ray 672 // 673 674 for (i=0;i<halfview;i++) 675 { 676 // start 1/2 pixel over, so viewangle bisects two middle pixels 677 tang = (long)i*VIEWGLOBAL/viewwidth/facedist; 678 angle = atan(tang); 679 intang = angle*radtoint; 680 pixelangle[halfview-1-i] = intang; 681 pixelangle[halfview+i] = -intang; 682 } 683 684 // 685 // if a point's abs(y/x) is greater than maxslope, the point is outside 686 // the view area 687 // 688 maxslope = finetangent[pixelangle[0]]; 689 maxslope >>= 8; 690 } 691 692 693 694 //=========================================================================== 695 696 /* 697 =================== 698 = 699 = SetupWalls 700 = 701 = Map tile values to scaled pics 702 = 703 =================== 704 */ 705 706 void SetupWalls (void) 707 { 708 int i; 709 710 for (i=1;i<MAXWALLTILES;i++) 711 { 712 horizwall[i]=(i-1)*2; 713 vertwall[i]=(i-1)*2+1; 714 } 715 } 716 717 //=========================================================================== 718 719 /* 720 ========================== 721 = 722 = SignonScreen 723 = 724 ========================== 725 */ 726 727 void SignonScreen (void) // VGA version 728 { 729 unsigned segstart,seglength; 730 731 VL_SetVGAPlaneMode (); 732 VL_TestPaletteSet (); 733 VL_SetPalette (&gamepal); 734 735 if (!virtualreality) 736 { 737 VW_SetScreen(0x8000,0); 738 VL_MungePic (&introscn,320,200); 739 VL_MemToScreen (&introscn,320,200,0,0); 740 VW_SetScreen(0,0); 741 } 742 743 // 744 // reclaim the memory from the linked in signon screen 745 // 746 segstart = FP_SEG(&introscn); 747 seglength = 64000/16; 748 if (FP_OFF(&introscn)) 749 { 750 segstart++; 751 seglength--; 752 } 753 MML_UseSpace (segstart,seglength); 754 } 755 756 757 /* 758 ========================== 759 = 760 = FinishSignon 761 = 762 ========================== 763 */ 764 765 void FinishSignon (void) 766 { 767 768 #ifndef SPEAR 769 VW_Bar (0,189,300,11,peekb(0xa000,0)); 770 WindowX = 0; 771 WindowW = 320; 772 PrintY = 190; 773 774 #ifndef JAPAN 775 SETFONTCOLOR(14,4); 776 777 #ifdef SPANISH 778 US_CPrint ("Oprima una tecla"); 779 #else 780 US_CPrint ("Press a key"); 781 #endif 782 783 #endif 784 785 if (!NoWait) 786 IN_Ack (); 787 788 #ifndef JAPAN 789 VW_Bar (0,189,300,11,peekb(0xa000,0)); 790 791 PrintY = 190; 792 SETFONTCOLOR(10,4); 793 794 #ifdef SPANISH 795 US_CPrint ("pensando..."); 796 #else 797 US_CPrint ("Working..."); 798 #endif 799 800 #endif 801 802 SETFONTCOLOR(0,15); 803 #else 804 if (!NoWait) 805 VW_WaitVBL(3*70); 806 #endif 807 } 808 809 //=========================================================================== 810 811 /* 812 ================= 813 = 814 = MS_CheckParm 815 = 816 ================= 817 */ 818 819 boolean MS_CheckParm (char far *check) 820 { 821 int i; 822 char *parm; 823 824 for (i = 1;i<_argc;i++) 825 { 826 parm = _argv[i]; 827 828 while ( !isalpha(*parm) ) // skip - / \ etc.. in front of parm 829 if (!*parm++) 830 break; // hit end of string without an alphanum 831 832 if ( !_fstricmp(check,parm) ) 833 return true; 834 } 835 836 return false; 837 } 838 839 //=========================================================================== 840 841 /* 842 ===================== 843 = 844 = InitDigiMap 845 = 846 ===================== 847 */ 848 849 static int wolfdigimap[] = 850 { 851 // These first sounds are in the upload version 852 #ifndef SPEAR 853 HALTSND, 0, 854 DOGBARKSND, 1, 855 CLOSEDOORSND, 2, 856 OPENDOORSND, 3, 857 ATKMACHINEGUNSND, 4, 858 ATKPISTOLSND, 5, 859 ATKGATLINGSND, 6, 860 SCHUTZADSND, 7, 861 GUTENTAGSND, 8, 862 MUTTISND, 9, 863 BOSSFIRESND, 10, 864 SSFIRESND, 11, 865 DEATHSCREAM1SND, 12, 866 DEATHSCREAM2SND, 13, 867 DEATHSCREAM3SND, 13, 868 TAKEDAMAGESND, 14, 869 PUSHWALLSND, 15, 870 871 LEBENSND, 20, 872 NAZIFIRESND, 21, 873 SLURPIESND, 22, 874 875 YEAHSND, 32, 876 877 #ifndef UPLOAD 878 // These are in all other episodes 879 DOGDEATHSND, 16, 880 AHHHGSND, 17, 881 DIESND, 18, 882 EVASND, 19, 883 884 TOT_HUNDSND, 23, 885 MEINGOTTSND, 24, 886 SCHABBSHASND, 25, 887 HITLERHASND, 26, 888 SPIONSND, 27, 889 NEINSOVASSND, 28, 890 DOGATTACKSND, 29, 891 LEVELDONESND, 30, 892 MECHSTEPSND, 31, 893 894 SCHEISTSND, 33, 895 DEATHSCREAM4SND, 34, // AIIEEE 896 DEATHSCREAM5SND, 35, // DEE-DEE 897 DONNERSND, 36, // EPISODE 4 BOSS DIE 898 EINESND, 37, // EPISODE 4 BOSS SIGHTING 899 ERLAUBENSND, 38, // EPISODE 6 BOSS SIGHTING 900 DEATHSCREAM6SND, 39, // FART 901 DEATHSCREAM7SND, 40, // GASP 902 DEATHSCREAM8SND, 41, // GUH-BOY! 903 DEATHSCREAM9SND, 42, // AH GEEZ! 904 KEINSND, 43, // EPISODE 5 BOSS SIGHTING 905 MEINSND, 44, // EPISODE 6 BOSS DIE 906 ROSESND, 45, // EPISODE 5 BOSS DIE 907 908 #endif 909 #else 910 // 911 // SPEAR OF DESTINY DIGISOUNDS 912 // 913 HALTSND, 0, 914 CLOSEDOORSND, 2, 915 OPENDOORSND, 3, 916 ATKMACHINEGUNSND, 4, 917 ATKPISTOLSND, 5, 918 ATKGATLINGSND, 6, 919 SCHUTZADSND, 7, 920 BOSSFIRESND, 8, 921 SSFIRESND, 9, 922 DEATHSCREAM1SND, 10, 923 DEATHSCREAM2SND, 11, 924 TAKEDAMAGESND, 12, 925 PUSHWALLSND, 13, 926 AHHHGSND, 15, 927 LEBENSND, 16, 928 NAZIFIRESND, 17, 929 SLURPIESND, 18, 930 LEVELDONESND, 22, 931 DEATHSCREAM4SND, 23, // AIIEEE 932 DEATHSCREAM3SND, 23, // DOUBLY-MAPPED!!! 933 DEATHSCREAM5SND, 24, // DEE-DEE 934 DEATHSCREAM6SND, 25, // FART 935 DEATHSCREAM7SND, 26, // GASP 936 DEATHSCREAM8SND, 27, // GUH-BOY! 937 DEATHSCREAM9SND, 28, // AH GEEZ! 938 GETGATLINGSND, 38, // Got Gat replacement 939 940 #ifndef SPEARDEMO 941 DOGBARKSND, 1, 942 DOGDEATHSND, 14, 943 SPIONSND, 19, 944 NEINSOVASSND, 20, 945 DOGATTACKSND, 21, 946 TRANSSIGHTSND, 29, // Trans Sight 947 TRANSDEATHSND, 30, // Trans Death 948 WILHELMSIGHTSND, 31, // Wilhelm Sight 949 WILHELMDEATHSND, 32, // Wilhelm Death 950 UBERDEATHSND, 33, // Uber Death 951 KNIGHTSIGHTSND, 34, // Death Knight Sight 952 KNIGHTDEATHSND, 35, // Death Knight Death 953 ANGELSIGHTSND, 36, // Angel Sight 954 ANGELDEATHSND, 37, // Angel Death 955 GETSPEARSND, 39, // Got Spear replacement 956 #endif 957 #endif 958 LASTSOUND 959 }; 960 961 962 void InitDigiMap (void) 963 { 964 int *map; 965 966 for (map = wolfdigimap;*map != LASTSOUND;map += 2) 967 DigiMap[map[0]] = map[1]; 968 969 970 } 971 972 973 #ifndef SPEAR 974 CP_iteminfo MusicItems={CTL_X,CTL_Y,6,0,32}; 975 CP_itemtype far MusicMenu[]= 976 { 977 {1,"Get Them!",0}, 978 {1,"Searching",0}, 979 {1,"P.O.W.",0}, 980 {1,"Suspense",0}, 981 {1,"War March",0}, 982 {1,"Around The Corner!",0}, 983 984 {1,"Nazi Anthem",0}, 985 {1,"Lurking...",0}, 986 {1,"Going After Hitler",0}, 987 {1,"Pounding Headache",0}, 988 {1,"Into the Dungeons",0}, 989 {1,"Ultimate Conquest",0}, 990 991 {1,"Kill the S.O.B.",0}, 992 {1,"The Nazi Rap",0}, 993 {1,"Twelfth Hour",0}, 994 {1,"Zero Hour",0}, 995 {1,"Ultimate Conquest",0}, 996 {1,"Wolfpack",0} 997 }; 998 #else 999 CP_iteminfo MusicItems={CTL_X,CTL_Y-20,9,0,32}; 1000 CP_itemtype far MusicMenu[]= 1001 { 1002 {1,"Funky Colonel Bill",0}, 1003 {1,"Death To The Nazis",0}, 1004 {1,"Tiptoeing Around",0}, 1005 {1,"Is This THE END?",0}, 1006 {1,"Evil Incarnate",0}, 1007 {1,"Jazzin' Them Nazis",0}, 1008 {1,"Puttin' It To The Enemy",0}, 1009 {1,"The SS Gonna Get You",0}, 1010 {1,"Towering Above",0} 1011 }; 1012 #endif 1013 1014 #ifndef SPEARDEMO 1015 void DoJukebox(void) 1016 { 1017 int which,lastsong=-1; 1018 unsigned start,songs[]= 1019 { 1020 #ifndef SPEAR 1021 GETTHEM_MUS, 1022 SEARCHN_MUS, 1023 POW_MUS, 1024 SUSPENSE_MUS, 1025 WARMARCH_MUS, 1026 CORNER_MUS, 1027 1028 NAZI_OMI_MUS, 1029 PREGNANT_MUS, 1030 GOINGAFT_MUS, 1031 HEADACHE_MUS, 1032 DUNGEON_MUS, 1033 ULTIMATE_MUS, 1034 1035 INTROCW3_MUS, 1036 NAZI_RAP_MUS, 1037 TWELFTH_MUS, 1038 ZEROHOUR_MUS, 1039 ULTIMATE_MUS, 1040 PACMAN_MUS 1041 #else 1042 XFUNKIE_MUS, // 0 1043 XDEATH_MUS, // 2 1044 XTIPTOE_MUS, // 4 1045 XTHEEND_MUS, // 7 1046 XEVIL_MUS, // 17 1047 XJAZNAZI_MUS, // 18 1048 XPUTIT_MUS, // 21 1049 XGETYOU_MUS, // 22 1050 XTOWER2_MUS // 23 1051 #endif 1052 }; 1053 struct dostime_t time; 1054 1055 1056 1057 IN_ClearKeysDown(); 1058 if (!AdLibPresent && !SoundBlasterPresent) 1059 return; 1060 1061 1062 MenuFadeOut(); 1063 1064 #ifndef SPEAR 1065 #ifndef UPLOAD 1066 _dos_gettime(&time); 1067 start = (time.hsecond%3)*6; 1068 #else 1069 start = 0; 1070 #endif 1071 #else 1072 start = 0; 1073 #endif 1074 1075 1076 CA_CacheGrChunk (STARTFONT+1); 1077 #ifdef SPEAR 1078 CacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END); 1079 #else 1080 CacheLump (CONTROLS_LUMP_START,CONTROLS_LUMP_END); 1081 #endif 1082 CA_LoadAllSounds (); 1083 1084 fontnumber=1; 1085 ClearMScreen (); 1086 VWB_DrawPic(112,184,C_MOUSELBACKPIC); 1087 DrawStripes (10); 1088 SETFONTCOLOR (TEXTCOLOR,BKGDCOLOR); 1089 1090 #ifndef SPEAR 1091 DrawWindow (CTL_X-2,CTL_Y-6,280,13*7,BKGDCOLOR); 1092 #else 1093 DrawWindow (CTL_X-2,CTL_Y-26,280,13*10,BKGDCOLOR); 1094 #endif 1095 1096 DrawMenu (&MusicItems,&MusicMenu[start]); 1097 1098 SETFONTCOLOR (READHCOLOR,BKGDCOLOR); 1099 PrintY=15; 1100 WindowX = 0; 1101 WindowY = 320; 1102 US_CPrint ("Robert's Jukebox"); 1103 1104 SETFONTCOLOR (TEXTCOLOR,BKGDCOLOR); 1105 VW_UpdateScreen(); 1106 MenuFadeIn(); 1107 1108 do 1109 { 1110 which = HandleMenu(&MusicItems,&MusicMenu[start],NULL); 1111 if (which>=0) 1112 { 1113 if (lastsong >= 0) 1114 MusicMenu[start+lastsong].active = 1; 1115 1116 StartCPMusic(songs[start + which]); 1117 MusicMenu[start+which].active = 2; 1118 DrawMenu (&MusicItems,&MusicMenu[start]); 1119 VW_UpdateScreen(); 1120 lastsong = which; 1121 } 1122 } while(which>=0); 1123 1124 MenuFadeOut(); 1125 IN_ClearKeysDown(); 1126 #ifdef SPEAR 1127 UnCacheLump (BACKDROP_LUMP_START,BACKDROP_LUMP_END); 1128 #else 1129 UnCacheLump (CONTROLS_LUMP_START,CONTROLS_LUMP_END); 1130 #endif 1131 } 1132 #endif 1133 1134 1135 /* 1136 ========================== 1137 = 1138 = InitGame 1139 = 1140 = Load a few things right away 1141 = 1142 ========================== 1143 */ 1144 1145 void InitGame (void) 1146 { 1147 int i,x,y; 1148 unsigned *blockstart; 1149 1150 if (MS_CheckParm ("virtual")) 1151 virtualreality = true; 1152 else 1153 virtualreality = false; 1154 1155 MM_Startup (); // so the signon screen can be freed 1156 1157 SignonScreen (); 1158 1159 VW_Startup (); 1160 IN_Startup (); 1161 PM_Startup (); 1162 PM_UnlockMainMem (); 1163 SD_Startup (); 1164 CA_Startup (); 1165 US_Startup (); 1166 1167 1168 #ifndef SPEAR 1169 if (mminfo.mainmem < 235000L) 1170 #else 1171 if (mminfo.mainmem < 257000L && !MS_CheckParm("debugmode")) 1172 #endif 1173 { 1174 memptr screen; 1175 1176 CA_CacheGrChunk (ERRORSCREEN); 1177 screen = grsegs[ERRORSCREEN]; 1178 ShutdownId(); 1179 movedata ((unsigned)screen,7+7*160,0xb800,0,17*160); 1180 gotoxy (1,23); 1181 exit(1); 1182 } 1183 1184 1185 // 1186 // build some tables 1187 // 1188 InitDigiMap (); 1189 1190 for (i=0;i<MAPSIZE;i++) 1191 { 1192 nearmapylookup[i] = &tilemap[0][0]+MAPSIZE*i; 1193 farmapylookup[i] = i*64; 1194 } 1195 1196 for (i=0;i<PORTTILESHIGH;i++) 1197 uwidthtable[i] = UPDATEWIDE*i; 1198 1199 blockstart = &blockstarts[0]; 1200 for (y=0;y<UPDATEHIGH;y++) 1201 for (x=0;x<UPDATEWIDE;x++) 1202 *blockstart++ = SCREENWIDTH*16*y+x*TILEWIDTH; 1203 1204 updateptr = &update[0]; 1205 1206 bufferofs = 0; 1207 displayofs = 0; 1208 ReadConfig (); 1209 1210 1211 // 1212 // HOLDING DOWN 'M' KEY? 1213 // 1214 #ifndef SPEARDEMO 1215 if (Keyboard[sc_M]) 1216 DoJukebox(); 1217 else 1218 #endif 1219 // 1220 // draw intro screen stuff 1221 // 1222 if (!virtualreality) 1223 IntroScreen (); 1224 1225 // 1226 // load in and lock down some basic chunks 1227 // 1228 1229 CA_CacheGrChunk(STARTFONT); 1230 MM_SetLock (&grsegs[STARTFONT],true); 1231 1232 LoadLatchMem (); 1233 BuildTables (); // trig tables 1234 SetupWalls (); 1235 1236 #if 0 1237 { 1238 int temp,i; 1239 temp = viewsize; 1240 profilehandle = open("SCALERS.TXT", O_CREAT | O_WRONLY | O_TEXT); 1241 for (i=1;i<20;i++) 1242 NewViewSize(i); 1243 viewsize = temp; 1244 close(profilehandle); 1245 } 1246 #endif 1247 1248 NewViewSize (viewsize); 1249 1250 1251 // 1252 // initialize variables 1253 // 1254 InitRedShifts (); 1255 if (!virtualreality) 1256 FinishSignon(); 1257 1258 displayofs = PAGE1START; 1259 bufferofs = PAGE2START; 1260 1261 if (virtualreality) 1262 { 1263 NoWait = true; 1264 geninterrupt(0x60); 1265 } 1266 } 1267 1268 //=========================================================================== 1269 1270 /* 1271 ========================== 1272 = 1273 = SetViewSize 1274 = 1275 ========================== 1276 */ 1277 1278 boolean SetViewSize (unsigned width, unsigned height) 1279 { 1280 viewwidth = width&~15; // must be divisable by 16 1281 viewheight = height&~1; // must be even 1282 centerx = viewwidth/2-1; 1283 shootdelta = viewwidth/10; 1284 screenofs = ((200-STATUSLINES-viewheight)/2*SCREENWIDTH+(320-viewwidth)/8); 1285 1286 // 1287 // calculate trace angles and projection constants 1288 // 1289 CalcProjection (FOCALLENGTH); 1290 1291 // 1292 // build all needed compiled scalers 1293 // 1294 // MM_BombOnError (false); 1295 SetupScaling (viewwidth*1.5); 1296 #if 0 1297 MM_BombOnError (true); 1298 if (mmerror) 1299 { 1300 Quit ("Can't build scalers!"); 1301 mmerror = false; 1302 return false; 1303 } 1304 #endif 1305 return true; 1306 } 1307 1308 1309 void ShowViewSize (int width) 1310 { 1311 int oldwidth,oldheight; 1312 1313 oldwidth = viewwidth; 1314 oldheight = viewheight; 1315 1316 viewwidth = width*16; 1317 viewheight = width*16*HEIGHTRATIO; 1318 DrawPlayBorder (); 1319 1320 viewheight = oldheight; 1321 viewwidth = oldwidth; 1322 } 1323 1324 1325 void NewViewSize (int width) 1326 { 1327 CA_UpLevel (); 1328 MM_SortMem (); 1329 viewsize = width; 1330 SetViewSize (width*16,width*16*HEIGHTRATIO); 1331 CA_DownLevel (); 1332 } 1333 1334 1335 1336 //=========================================================================== 1337 1338 /* 1339 ========================== 1340 = 1341 = Quit 1342 = 1343 ========================== 1344 */ 1345 1346 void Quit (char *error) 1347 { 1348 unsigned finscreen; 1349 memptr screen; 1350 1351 if (virtualreality) 1352 geninterrupt(0x61); 1353 1354 ClearMemory (); 1355 if (!*error) 1356 { 1357 #ifndef JAPAN 1358 CA_CacheGrChunk (ORDERSCREEN); 1359 screen = grsegs[ORDERSCREEN]; 1360 #endif 1361 WriteConfig (); 1362 } 1363 else 1364 { 1365 CA_CacheGrChunk (ERRORSCREEN); 1366 screen = grsegs[ERRORSCREEN]; 1367 } 1368 1369 ShutdownId (); 1370 1371 if (error && *error) 1372 { 1373 movedata ((unsigned)screen,7,0xb800,0,7*160); 1374 gotoxy (10,4); 1375 puts(error); 1376 gotoxy (1,8); 1377 exit(1); 1378 } 1379 else 1380 if (!error || !(*error)) 1381 { 1382 clrscr(); 1383 #ifndef JAPAN 1384 movedata ((unsigned)screen,7,0xb800,0,4000); 1385 gotoxy(1,24); 1386 #endif 1387 //asm mov bh,0 1388 //asm mov dh,23 // row 1389 //asm mov dl,0 // collumn 1390 //asm mov ah,2 1391 //asm int 0x10 1392 } 1393 1394 exit(0); 1395 } 1396 1397 //=========================================================================== 1398 1399 1400 1401 /* 1402 ===================== 1403 = 1404 = DemoLoop 1405 = 1406 ===================== 1407 */ 1408 1409 static char *ParmStrings[] = {"baby","easy","normal","hard",""}; 1410 1411 void DemoLoop (void) 1412 { 1413 static int LastDemo; 1414 int i,level; 1415 long nsize; 1416 memptr nullblock; 1417 1418 // 1419 // check for launch from ted 1420 // 1421 if (tedlevel) 1422 { 1423 NoWait = true; 1424 NewGame(1,0); 1425 1426 for (i = 1;i < _argc;i++) 1427 { 1428 if ( (level = US_CheckParm(_argv[i],ParmStrings)) != -1) 1429 { 1430 gamestate.difficulty=level; 1431 break; 1432 } 1433 } 1434 1435 #ifndef SPEAR 1436 gamestate.episode = tedlevelnum/10; 1437 gamestate.mapon = tedlevelnum%10; 1438 #else 1439 gamestate.episode = 0; 1440 gamestate.mapon = tedlevelnum; 1441 #endif 1442 GameLoop(); 1443 Quit (NULL); 1444 } 1445 1446 1447 // 1448 // main game cycle 1449 // 1450 1451 1452 // nsize = (long)40*1024; 1453 // MM_GetPtr(&nullblock,nsize); 1454 1455 #ifndef DEMOTEST 1456 1457 #ifndef UPLOAD 1458 1459 #ifndef GOODTIMES 1460 #ifndef SPEAR 1461 #ifndef JAPAN 1462 if (!NoWait) 1463 NonShareware(); 1464 #endif 1465 #else 1466 1467 #ifndef GOODTIMES 1468 #ifndef SPEARDEMO 1469 CopyProtection(); 1470 #endif 1471 #endif 1472 1473 #endif 1474 #endif 1475 #endif 1476 1477 StartCPMusic(INTROSONG); 1478 1479 #ifndef JAPAN 1480 if (!NoWait) 1481 PG13 (); 1482 #endif 1483 1484 #endif 1485 1486 while (1) 1487 { 1488 while (!NoWait) 1489 { 1490 // 1491 // title page 1492 // 1493 MM_SortMem (); 1494 #ifndef DEMOTEST 1495 1496 #ifdef SPEAR 1497 CA_CacheGrChunk (TITLEPALETTE); 1498 1499 CA_CacheGrChunk (TITLE1PIC); 1500 VWB_DrawPic (0,0,TITLE1PIC); 1501 UNCACHEGRCHUNK (TITLE1PIC); 1502 1503 CA_CacheGrChunk (TITLE2PIC); 1504 VWB_DrawPic (0,80,TITLE2PIC); 1505 UNCACHEGRCHUNK (TITLE2PIC); 1506 VW_UpdateScreen (); 1507 VL_FadeIn(0,255,grsegs[TITLEPALETTE],30); 1508 1509 UNCACHEGRCHUNK (TITLEPALETTE); 1510 #else 1511 CA_CacheScreen (TITLEPIC); 1512 VW_UpdateScreen (); 1513 VW_FadeIn(); 1514 #endif 1515 if (IN_UserInput(TickBase*15)) 1516 break; 1517 VW_FadeOut(); 1518 // 1519 // credits page 1520 // 1521 CA_CacheScreen (CREDITSPIC); 1522 VW_UpdateScreen(); 1523 VW_FadeIn (); 1524 if (IN_UserInput(TickBase*10)) 1525 break; 1526 VW_FadeOut (); 1527 // 1528 // high scores 1529 // 1530 DrawHighScores (); 1531 VW_UpdateScreen (); 1532 VW_FadeIn (); 1533 1534 if (IN_UserInput(TickBase*10)) 1535 break; 1536 #endif 1537 // 1538 // demo 1539 // 1540 1541 #ifndef SPEARDEMO 1542 PlayDemo (LastDemo++%4); 1543 #else 1544 PlayDemo (0); 1545 #endif 1546 1547 if (playstate == ex_abort) 1548 break; 1549 StartCPMusic(INTROSONG); 1550 } 1551 1552 VW_FadeOut (); 1553 1554 #ifndef SPEAR 1555 if (Keyboard[sc_Tab] && MS_CheckParm("goobers")) 1556 #else 1557 if (Keyboard[sc_Tab] && MS_CheckParm("debugmode")) 1558 #endif 1559 RecordDemo (); 1560 else 1561 US_ControlPanel (0); 1562 1563 if (startgame || loadedgame) 1564 { 1565 GameLoop (); 1566 VW_FadeOut(); 1567 StartCPMusic(INTROSONG); 1568 } 1569 } 1570 } 1571 1572 1573 //=========================================================================== 1574 1575 1576 /* 1577 ========================== 1578 = 1579 = main 1580 = 1581 ========================== 1582 */ 1583 1584 char *nosprtxt[] = {"nospr",nil}; 1585 1586 void main (void) 1587 { 1588 int i; 1589 1590 1591 #ifdef BETA 1592 // 1593 // THIS IS FOR BETA ONLY! 1594 // 1595 struct dosdate_t d; 1596 1597 _dos_getdate(&d); 1598 if (d.year > YEAR || 1599 (d.month >= MONTH && d.day >= DAY)) 1600 { 1601 printf("Sorry, BETA-TESTING is over. Thanks for you help.\n"); 1602 exit(1); 1603 } 1604 #endif 1605 1606 CheckForEpisodes(); 1607 1608 Patch386 (); 1609 1610 InitGame (); 1611 1612 DemoLoop(); 1613 1614 Quit("Demo loop exited???"); 1615 } 1616