Subversion Repositories Kolibri OS

Rev

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