Subversion Repositories Kolibri OS

Rev

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