Subversion Repositories Kolibri OS

Rev

Rev 8596 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

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