Subversion Repositories Kolibri OS

Rev

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