Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. // WL_GAME.C
  2.  
  3. #include <math.h>
  4. #include "wl_def.h"
  5. //#include <SDL_mixer.h>
  6. #pragma hdrstop
  7.  
  8. #ifdef MYPROFILE
  9. #include <TIME.H>
  10. #endif
  11.  
  12.  
  13. /*
  14. =============================================================================
  15.  
  16.                              LOCAL CONSTANTS
  17.  
  18. =============================================================================
  19. */
  20.  
  21.  
  22. /*
  23. =============================================================================
  24.  
  25.                              GLOBAL VARIABLES
  26.  
  27. =============================================================================
  28. */
  29.  
  30. boolean         ingame,fizzlein;
  31. gametype        gamestate;
  32. byte            bordercol=VIEWCOLOR;        // color of the Change View/Ingame border
  33.  
  34. #ifdef SPEAR
  35. int32_t         spearx,speary;
  36. unsigned        spearangle;
  37. boolean         spearflag;
  38. #endif
  39.  
  40. #ifdef USE_FEATUREFLAGS
  41. int ffDataTopLeft, ffDataTopRight, ffDataBottomLeft, ffDataBottomRight;
  42. #endif
  43.  
  44. //
  45. // ELEVATOR BACK MAPS - REMEMBER (-1)!!
  46. //
  47. int ElevatorBackTo[]={1,1,7,3,5,3};
  48.  
  49. void SetupGameLevel (void);
  50. void DrawPlayScreen (void);
  51. void LoadLatchMem (void);
  52. void GameLoop (void);
  53.  
  54. /*
  55. =============================================================================
  56.  
  57.                              LOCAL VARIABLES
  58.  
  59. =============================================================================
  60. */
  61.  
  62.  
  63.  
  64. //===========================================================================
  65. //===========================================================================
  66.  
  67.  
  68. /*
  69. ==========================
  70. =
  71. = SetSoundLoc - Given the location of an object (in terms of global
  72. =       coordinates, held in globalsoundx and globalsoundy), munges the values
  73. =       for an approximate distance from the left and right ear, and puts
  74. =       those values into leftchannel and rightchannel.
  75. =
  76. = JAB
  77. =
  78. ==========================
  79. */
  80.  
  81. int leftchannel, rightchannel;
  82. #define ATABLEMAX 15
  83. byte righttable[ATABLEMAX][ATABLEMAX * 2] = {
  84. { 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 0, 0, 0, 0, 0, 1, 3, 5, 8, 8, 8, 8, 8, 8, 8, 8},
  85. { 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 4, 0, 0, 0, 0, 0, 2, 4, 6, 8, 8, 8, 8, 8, 8, 8, 8},
  86. { 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 4, 1, 0, 0, 0, 1, 2, 4, 6, 8, 8, 8, 8, 8, 8, 8, 8},
  87. { 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 6, 5, 4, 2, 1, 0, 1, 2, 3, 5, 7, 8, 8, 8, 8, 8, 8, 8, 8},
  88. { 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 5, 4, 3, 2, 2, 3, 3, 5, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  89. { 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 4, 4, 4, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  90. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 5, 5, 6, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  91. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  92. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  93. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  94. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  95. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  96. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  97. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  98. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}
  99. };
  100. byte lefttable[ATABLEMAX][ATABLEMAX * 2] = {
  101. { 8, 8, 8, 8, 8, 8, 8, 8, 5, 3, 1, 0, 0, 0, 0, 0, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8},
  102. { 8, 8, 8, 8, 8, 8, 8, 8, 6, 4, 2, 0, 0, 0, 0, 0, 4, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8},
  103. { 8, 8, 8, 8, 8, 8, 8, 8, 6, 4, 2, 1, 0, 0, 0, 1, 4, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8},
  104. { 8, 8, 8, 8, 8, 8, 8, 8, 7, 5, 3, 2, 1, 0, 1, 2, 4, 5, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8},
  105. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 6, 5, 3, 3, 2, 2, 3, 4, 5, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8},
  106. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 6, 5, 4, 4, 4, 4, 5, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8},
  107. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 6, 6, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  108. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  109. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  110. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  111. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  112. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  113. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  114. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
  115. { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}
  116. };
  117.  
  118. void
  119. SetSoundLoc(fixed gx,fixed gy)
  120. {
  121.     fixed   xt,yt;
  122.     int     x,y;
  123.  
  124. //
  125. // translate point to view centered coordinates
  126. //
  127.     gx -= viewx;
  128.     gy -= viewy;
  129.  
  130. //
  131. // calculate newx
  132. //
  133.     xt = FixedMul(gx,viewcos);
  134.     yt = FixedMul(gy,viewsin);
  135.     x = (xt - yt) >> TILESHIFT;
  136.  
  137. //
  138. // calculate newy
  139. //
  140.     xt = FixedMul(gx,viewsin);
  141.     yt = FixedMul(gy,viewcos);
  142.     y = (yt + xt) >> TILESHIFT;
  143.  
  144.     if (y >= ATABLEMAX)
  145.         y = ATABLEMAX - 1;
  146.     else if (y <= -ATABLEMAX)
  147.         y = -ATABLEMAX;
  148.     if (x < 0)
  149.         x = -x;
  150.     if (x >= ATABLEMAX)
  151.         x = ATABLEMAX - 1;
  152.     leftchannel  =  lefttable[x][y + ATABLEMAX];
  153.     rightchannel = righttable[x][y + ATABLEMAX];
  154.  
  155. #if 0
  156.     CenterWindow(8,1);
  157.     US_PrintSigned(leftchannel);
  158.     US_Print(",");
  159.     US_PrintSigned(rightchannel);
  160.     VW_UpdateScreen();
  161. #endif
  162. }
  163.  
  164. /*
  165. ==========================
  166. =
  167. = SetSoundLocGlobal - Sets up globalsoundx & globalsoundy and then calls
  168. =       UpdateSoundLoc() to transform that into relative channel volumes. Those
  169. =       values are then passed to the Sound Manager so that they'll be used for
  170. =       the next sound played (if possible).
  171. =
  172. = JAB
  173. =
  174. ==========================
  175. */
  176. void PlaySoundLocGlobal(word s,fixed gx,fixed gy)
  177. {
  178.     SetSoundLoc(gx, gy);
  179.     SD_PositionSound(leftchannel, rightchannel);
  180.  
  181.     int channel = SD_PlaySound((soundnames) s);
  182.     if(channel)
  183.     {
  184. /*        channelSoundPos[channel - 1].globalsoundx = gx;
  185.         channelSoundPos[channel - 1].globalsoundy = gy;
  186.         channelSoundPos[channel - 1].valid = 1;*/
  187.     }
  188. }
  189.  
  190. void UpdateSoundLoc(void)
  191. {
  192. /*    if (SoundPositioned)
  193.     {
  194.         SetSoundLoc(globalsoundx,globalsoundy);
  195.         SD_SetPosition(leftchannel,rightchannel);
  196.     }*/
  197. /*
  198.     for(int i = 0; i < MIX_CHANNELS; i++)
  199.     {
  200.         if(channelSoundPos[i].valid)
  201.         {
  202.             SetSoundLoc(channelSoundPos[i].globalsoundx,
  203.                 channelSoundPos[i].globalsoundy);
  204.             SD_SetPosition(i, leftchannel, rightchannel);
  205.         }
  206.     }*/
  207. }
  208.  
  209. /*
  210. **      JAB End
  211. */
  212.  
  213. /*
  214. ==========================
  215. =
  216. = ScanInfoPlane
  217. =
  218. = Spawn all actors and mark down special places
  219. =
  220. ==========================
  221. */
  222.  
  223. static void ScanInfoPlane(void)
  224. {
  225.     unsigned x,y;
  226.     int      tile;
  227.     word     *start;
  228.  
  229.     start = mapsegs[1];
  230.     for (y=0;y<mapheight;y++)
  231.     {
  232.         for (x=0;x<mapwidth;x++)
  233.         {
  234.             tile = *start++;
  235.             if (!tile)
  236.                 continue;
  237.  
  238.             switch (tile)
  239.             {
  240.                 case 19:
  241.                 case 20:
  242.                 case 21:
  243.                 case 22:
  244.                     SpawnPlayer(x,y,NORTH+tile-19);
  245.                     break;
  246.  
  247.                 case 23:
  248.                 case 24:
  249.                 case 25:
  250.                 case 26:
  251.                 case 27:
  252.                 case 28:
  253.                 case 29:
  254.                 case 30:
  255.  
  256.                 case 31:
  257.                 case 32:
  258.                 case 33:
  259.                 case 34:
  260.                 case 35:
  261.                 case 36:
  262.                 case 37:
  263.                 case 38:
  264.  
  265.                 case 39:
  266.                 case 40:
  267.                 case 41:
  268.                 case 42:
  269.                 case 43:
  270.                 case 44:
  271.                 case 45:
  272.                 case 46:
  273.  
  274.                 case 47:
  275.                 case 48:
  276.                 case 49:
  277.                 case 50:
  278.                 case 51:
  279.                 case 52:
  280.                 case 53:
  281.                 case 54:
  282.  
  283.                 case 55:
  284.                 case 56:
  285.                 case 57:
  286.                 case 58:
  287.                 case 59:
  288.                 case 60:
  289.                 case 61:
  290.                 case 62:
  291.  
  292.                 case 63:
  293.                 case 64:
  294.                 case 65:
  295.                 case 66:
  296.                 case 67:
  297.                 case 68:
  298.                 case 69:
  299.                 case 70:
  300.                 case 71:
  301.                 case 72:
  302. #ifdef SPEAR
  303.                 case 73:                        // TRUCK AND SPEAR!
  304.                 case 74:
  305. #elif defined(USE_DIR3DSPR)                     // just for the example
  306.                 case 73:
  307. #endif
  308.                     SpawnStatic(x,y,tile-23);
  309.                     break;
  310.  
  311. //
  312. // P wall
  313. //
  314.                 case 98:
  315.                     if (!loadedgame)
  316.                         gamestate.secrettotal++;
  317.                     break;
  318.  
  319. //
  320. // guard
  321. //
  322.                 case 180:
  323.                 case 181:
  324.                 case 182:
  325.                 case 183:
  326.                     if (gamestate.difficulty<gd_hard)
  327.                         break;
  328.                     tile -= 36;
  329.                 case 144:
  330.                 case 145:
  331.                 case 146:
  332.                 case 147:
  333.                     if (gamestate.difficulty<gd_medium)
  334.                         break;
  335.                     tile -= 36;
  336.                 case 108:
  337.                 case 109:
  338.                 case 110:
  339.                 case 111:
  340.                     SpawnStand(en_guard,x,y,tile-108);
  341.                     break;
  342.  
  343.  
  344.                 case 184:
  345.                 case 185:
  346.                 case 186:
  347.                 case 187:
  348.                     if (gamestate.difficulty<gd_hard)
  349.                         break;
  350.                     tile -= 36;
  351.                 case 148:
  352.                 case 149:
  353.                 case 150:
  354.                 case 151:
  355.                     if (gamestate.difficulty<gd_medium)
  356.                         break;
  357.                     tile -= 36;
  358.                 case 112:
  359.                 case 113:
  360.                 case 114:
  361.                 case 115:
  362.                     SpawnPatrol(en_guard,x,y,tile-112);
  363.                     break;
  364.  
  365.                 case 124:
  366.                     SpawnDeadGuard (x,y);
  367.                     break;
  368. //
  369. // officer
  370. //
  371.                 case 188:
  372.                 case 189:
  373.                 case 190:
  374.                 case 191:
  375.                     if (gamestate.difficulty<gd_hard)
  376.                         break;
  377.                     tile -= 36;
  378.                 case 152:
  379.                 case 153:
  380.                 case 154:
  381.                 case 155:
  382.                     if (gamestate.difficulty<gd_medium)
  383.                         break;
  384.                     tile -= 36;
  385.                 case 116:
  386.                 case 117:
  387.                 case 118:
  388.                 case 119:
  389.                     SpawnStand(en_officer,x,y,tile-116);
  390.                     break;
  391.  
  392.  
  393.                 case 192:
  394.                 case 193:
  395.                 case 194:
  396.                 case 195:
  397.                     if (gamestate.difficulty<gd_hard)
  398.                         break;
  399.                     tile -= 36;
  400.                 case 156:
  401.                 case 157:
  402.                 case 158:
  403.                 case 159:
  404.                     if (gamestate.difficulty<gd_medium)
  405.                         break;
  406.                     tile -= 36;
  407.                 case 120:
  408.                 case 121:
  409.                 case 122:
  410.                 case 123:
  411.                     SpawnPatrol(en_officer,x,y,tile-120);
  412.                     break;
  413.  
  414.  
  415. //
  416. // ss
  417. //
  418.                 case 198:
  419.                 case 199:
  420.                 case 200:
  421.                 case 201:
  422.                     if (gamestate.difficulty<gd_hard)
  423.                         break;
  424.                     tile -= 36;
  425.                 case 162:
  426.                 case 163:
  427.                 case 164:
  428.                 case 165:
  429.                     if (gamestate.difficulty<gd_medium)
  430.                         break;
  431.                     tile -= 36;
  432.                 case 126:
  433.                 case 127:
  434.                 case 128:
  435.                 case 129:
  436.                     SpawnStand(en_ss,x,y,tile-126);
  437.                     break;
  438.  
  439.  
  440.                 case 202:
  441.                 case 203:
  442.                 case 204:
  443.                 case 205:
  444.                     if (gamestate.difficulty<gd_hard)
  445.                         break;
  446.                     tile -= 36;
  447.                 case 166:
  448.                 case 167:
  449.                 case 168:
  450.                 case 169:
  451.                     if (gamestate.difficulty<gd_medium)
  452.                         break;
  453.                     tile -= 36;
  454.                 case 130:
  455.                 case 131:
  456.                 case 132:
  457.                 case 133:
  458.                     SpawnPatrol(en_ss,x,y,tile-130);
  459.                     break;
  460.  
  461. //
  462. // dogs
  463. //
  464.                 case 206:
  465.                 case 207:
  466.                 case 208:
  467.                 case 209:
  468.                     if (gamestate.difficulty<gd_hard)
  469.                         break;
  470.                     tile -= 36;
  471.                 case 170:
  472.                 case 171:
  473.                 case 172:
  474.                 case 173:
  475.                     if (gamestate.difficulty<gd_medium)
  476.                         break;
  477.                     tile -= 36;
  478.                 case 134:
  479.                 case 135:
  480.                 case 136:
  481.                 case 137:
  482.                     SpawnStand(en_dog,x,y,tile-134);
  483.                     break;
  484.  
  485.  
  486.                 case 210:
  487.                 case 211:
  488.                 case 212:
  489.                 case 213:
  490.                     if (gamestate.difficulty<gd_hard)
  491.                         break;
  492.                     tile -= 36;
  493.                 case 174:
  494.                 case 175:
  495.                 case 176:
  496.                 case 177:
  497.                     if (gamestate.difficulty<gd_medium)
  498.                         break;
  499.                     tile -= 36;
  500.                 case 138:
  501.                 case 139:
  502.                 case 140:
  503.                 case 141:
  504.                     SpawnPatrol(en_dog,x,y,tile-138);
  505.                     break;
  506.  
  507. //
  508. // boss
  509. //
  510. #ifndef SPEAR
  511.                 case 214:
  512.                     SpawnBoss (x,y);
  513.                     break;
  514.                 case 197:
  515.                     SpawnGretel (x,y);
  516.                     break;
  517.                 case 215:
  518.                     SpawnGift (x,y);
  519.                     break;
  520.                 case 179:
  521.                     SpawnFat (x,y);
  522.                     break;
  523.                 case 196:
  524.                     SpawnSchabbs (x,y);
  525.                     break;
  526.                 case 160:
  527.                     SpawnFakeHitler (x,y);
  528.                     break;
  529.                 case 178:
  530.                     SpawnHitler (x,y);
  531.                     break;
  532. #else
  533.                 case 106:
  534.                     SpawnSpectre (x,y);
  535.                     break;
  536.                 case 107:
  537.                     SpawnAngel (x,y);
  538.                     break;
  539.                 case 125:
  540.                     SpawnTrans (x,y);
  541.                     break;
  542.                 case 142:
  543.                     SpawnUber (x,y);
  544.                     break;
  545.                 case 143:
  546.                     SpawnWill (x,y);
  547.                     break;
  548.                 case 161:
  549.                     SpawnDeath (x,y);
  550.                     break;
  551.  
  552. #endif
  553.  
  554. //
  555. // mutants
  556. //
  557.                 case 252:
  558.                 case 253:
  559.                 case 254:
  560.                 case 255:
  561.                     if (gamestate.difficulty<gd_hard)
  562.                         break;
  563.                     tile -= 18;
  564.                 case 234:
  565.                 case 235:
  566.                 case 236:
  567.                 case 237:
  568.                     if (gamestate.difficulty<gd_medium)
  569.                         break;
  570.                     tile -= 18;
  571.                 case 216:
  572.                 case 217:
  573.                 case 218:
  574.                 case 219:
  575.                     SpawnStand(en_mutant,x,y,tile-216);
  576.                     break;
  577.  
  578.                 case 256:
  579.                 case 257:
  580.                 case 258:
  581.                 case 259:
  582.                     if (gamestate.difficulty<gd_hard)
  583.                         break;
  584.                     tile -= 18;
  585.                 case 238:
  586.                 case 239:
  587.                 case 240:
  588.                 case 241:
  589.                     if (gamestate.difficulty<gd_medium)
  590.                         break;
  591.                     tile -= 18;
  592.                 case 220:
  593.                 case 221:
  594.                 case 222:
  595.                 case 223:
  596.                     SpawnPatrol(en_mutant,x,y,tile-220);
  597.                     break;
  598.  
  599. //
  600. // ghosts
  601. //
  602. #ifndef SPEAR
  603.                 case 224:
  604.                     SpawnGhosts (en_blinky,x,y);
  605.                     break;
  606.                 case 225:
  607.                     SpawnGhosts (en_clyde,x,y);
  608.                     break;
  609.                 case 226:
  610.                     SpawnGhosts (en_pinky,x,y);
  611.                     break;
  612.                 case 227:
  613.                     SpawnGhosts (en_inky,x,y);
  614.                     break;
  615. #endif
  616.             }
  617.         }
  618.     }
  619. }
  620.  
  621. //==========================================================================
  622.  
  623. /*
  624. ==================
  625. =
  626. = SetupGameLevel
  627. =
  628. ==================
  629. */
  630.  
  631. void SetupGameLevel (void)
  632. {
  633.     int  x,y;
  634.     word *map;
  635.     word tile;
  636.  
  637.  
  638.     if (!loadedgame)
  639.     {
  640.         gamestate.TimeCount
  641.             = gamestate.secrettotal
  642.             = gamestate.killtotal
  643.             = gamestate.treasuretotal
  644.             = gamestate.secretcount
  645.             = gamestate.killcount
  646.             = gamestate.treasurecount
  647.             = pwallstate = pwallpos = facetimes = 0;
  648.         LastAttacker = NULL;
  649.         killerobj = NULL;
  650.     }
  651.  
  652.     if (demoplayback || demorecord)
  653.         US_InitRndT (false);
  654.     else
  655.         US_InitRndT (true);
  656.  
  657. //
  658. // load the level
  659. //
  660.     CA_CacheMap (gamestate.mapon+10*gamestate.episode);
  661.     mapon-=gamestate.episode*10;
  662.  
  663. #ifdef USE_FEATUREFLAGS
  664.     // Temporary definition to make things clearer
  665.     #define MXX MAPSIZE - 1
  666.  
  667.     // Read feature flags data from map corners and overwrite corners with adjacent tiles
  668.     ffDataTopLeft     = MAPSPOT(0,   0,   0); MAPSPOT(0,   0,   0) = MAPSPOT(1,       0,       0);
  669.     ffDataTopRight    = MAPSPOT(MXX, 0,   0); MAPSPOT(MXX, 0,   0) = MAPSPOT(MXX,     1,       0);
  670.     ffDataBottomRight = MAPSPOT(MXX, MXX, 0); MAPSPOT(MXX, MXX, 0) = MAPSPOT(MXX - 1, MXX,     0);
  671.     ffDataBottomLeft  = MAPSPOT(0,   MXX, 0); MAPSPOT(0,   MXX, 0) = MAPSPOT(0,       MXX - 1, 0);
  672.  
  673.     #undef MXX
  674. #endif
  675.  
  676. //
  677. // copy the wall data to a data segment array
  678. //
  679.     memset (tilemap,0,sizeof(tilemap));
  680.     memset (actorat,0,sizeof(actorat));
  681.     map = mapsegs[0];
  682.     for (y=0;y<mapheight;y++)
  683.     {
  684.         for (x=0;x<mapwidth;x++)
  685.         {
  686.             tile = *map++;
  687.             if (tile<AREATILE)
  688.             {
  689.                 // solid wall
  690.                 tilemap[x][y] = (byte) tile;
  691.                 actorat[x][y] = (objtype *)(uintptr_t) tile;
  692.             }
  693.             else
  694.             {
  695.                 // area floor
  696.                 tilemap[x][y] = 0;
  697.                 actorat[x][y] = 0;
  698.             }
  699.         }
  700.     }
  701.  
  702. //
  703. // spawn doors
  704. //
  705.     InitActorList ();                       // start spawning things with a clean slate
  706.     InitDoorList ();
  707.     InitStaticList ();
  708.  
  709.     map = mapsegs[0];
  710.     for (y=0;y<mapheight;y++)
  711.     {
  712.         for (x=0;x<mapwidth;x++)
  713.         {
  714.             tile = *map++;
  715.             if (tile >= 90 && tile <= 101)
  716.             {
  717.                 // door
  718.                 switch (tile)
  719.                 {
  720.                     case 90:
  721.                     case 92:
  722.                     case 94:
  723.                     case 96:
  724.                     case 98:
  725.                     case 100:
  726.                         SpawnDoor (x,y,1,(tile-90)/2);
  727.                         break;
  728.                     case 91:
  729.                     case 93:
  730.                     case 95:
  731.                     case 97:
  732.                     case 99:
  733.                     case 101:
  734.                         SpawnDoor (x,y,0,(tile-91)/2);
  735.                         break;
  736.                 }
  737.             }
  738.         }
  739.     }
  740.  
  741. //
  742. // spawn actors
  743. //
  744.     ScanInfoPlane ();
  745.  
  746.  
  747. //
  748. // take out the ambush markers
  749. //
  750.     map = mapsegs[0];
  751.     for (y=0;y<mapheight;y++)
  752.     {
  753.         for (x=0;x<mapwidth;x++)
  754.         {
  755.             tile = *map++;
  756.             if (tile == AMBUSHTILE)
  757.             {
  758.                 tilemap[x][y] = 0;
  759.                 if ( (unsigned)(uintptr_t)actorat[x][y] == AMBUSHTILE)
  760.                     actorat[x][y] = NULL;
  761.  
  762.                 if (*map >= AREATILE)
  763.                     tile = *map;
  764.                 if (*(map-1-mapwidth) >= AREATILE)
  765.                     tile = *(map-1-mapwidth);
  766.                 if (*(map-1+mapwidth) >= AREATILE)
  767.                     tile = *(map-1+mapwidth);
  768.                 if ( *(map-2) >= AREATILE)
  769.                     tile = *(map-2);
  770.  
  771.                 *(map-1) = tile;
  772.             }
  773.         }
  774.     }
  775.  
  776.  
  777. //
  778. // have the caching manager load and purge stuff to make sure all marks
  779. // are in memory
  780. //
  781.     CA_LoadAllSounds ();
  782. }
  783.  
  784.  
  785. //==========================================================================
  786.  
  787.  
  788. /*
  789. ===================
  790. =
  791. = DrawPlayBorderSides
  792. =
  793. = To fix window overwrites
  794. =
  795. ===================
  796. */
  797. void DrawPlayBorderSides(void)
  798. {
  799.     if(viewsize == 21) return;
  800.  
  801.         const int sw = screenWidth;
  802.         const int sh = screenHeight;
  803.         const int vw = viewwidth;
  804.         const int vh = viewheight;
  805.         const int px = scaleFactor; // size of one "pixel"
  806.  
  807.         const int h  = sh - px * STATUSLINES;
  808.         const int xl = sw / 2 - vw / 2;
  809.         const int yl = (h - vh) / 2;
  810.  
  811.     if(xl != 0)
  812.     {
  813.             VWB_BarScaledCoord(0,            0, xl - px,     h, bordercol);                 // left side
  814.             VWB_BarScaledCoord(xl + vw + px, 0, xl - px * 2, h, bordercol);                 // right side
  815.     }
  816.  
  817.     if(yl != 0)
  818.     {
  819.             VWB_BarScaledCoord(0, 0,            sw, yl - px, bordercol);                    // upper side
  820.             VWB_BarScaledCoord(0, yl + vh + px, sw, yl - px, bordercol);                    // lower side
  821.     }
  822.  
  823.     if(xl != 0)
  824.     {
  825.         // Paint game view border lines
  826.             VWB_BarScaledCoord(xl - px, yl - px, vw + px, px,          0);                      // upper border
  827.             VWB_BarScaledCoord(xl,      yl + vh, vw + px, px,          bordercol - 2);          // lower border
  828.             VWB_BarScaledCoord(xl - px, yl - px, px,      vh + px,     0);                      // left border
  829.             VWB_BarScaledCoord(xl + vw, yl - px, px,      vh + px * 2, bordercol - 2);          // right border
  830.             VWB_BarScaledCoord(xl - px, yl + vh, px,      px,          bordercol - 3);          // lower left highlight
  831.     }
  832.     else
  833.     {
  834.         // Just paint a lower border line
  835.         VWB_BarScaledCoord(0, yl+vh, vw, px, bordercol-2);       // lower border
  836.     }
  837. }
  838.  
  839.  
  840. /*
  841. ===================
  842. =
  843. = DrawStatusBorder
  844. =
  845. ===================
  846. */
  847.  
  848. void DrawStatusBorder (byte color)
  849. {
  850.     int statusborderw = (screenWidth-scaleFactor*320)/2;
  851.  
  852.     VWB_BarScaledCoord (0,0,screenWidth,screenHeight-scaleFactor*(STATUSLINES-3),color);
  853.     VWB_BarScaledCoord (0,screenHeight-scaleFactor*(STATUSLINES-3),
  854.         statusborderw+scaleFactor*8,scaleFactor*(STATUSLINES-4),color);
  855.     VWB_BarScaledCoord (0,screenHeight-scaleFactor*2,screenWidth,scaleFactor*2,color);
  856.     VWB_BarScaledCoord (screenWidth-statusborderw-scaleFactor*8, screenHeight-scaleFactor*(STATUSLINES-3),
  857.         statusborderw+scaleFactor*8,scaleFactor*(STATUSLINES-4),color);
  858.  
  859.     VWB_BarScaledCoord (statusborderw+scaleFactor*9, screenHeight-scaleFactor*3,
  860.         scaleFactor*97, scaleFactor*1, color-1);
  861.     VWB_BarScaledCoord (statusborderw+scaleFactor*106, screenHeight-scaleFactor*3,
  862.         scaleFactor*161, scaleFactor*1, color-2);
  863.     VWB_BarScaledCoord (statusborderw+scaleFactor*267, screenHeight-scaleFactor*3,
  864.         scaleFactor*44, scaleFactor*1, color-3);
  865.     VWB_BarScaledCoord (screenWidth-statusborderw-scaleFactor*9, screenHeight-scaleFactor*(STATUSLINES-4),
  866.         scaleFactor*1, scaleFactor*20, color-2);
  867.     VWB_BarScaledCoord (screenWidth-statusborderw-scaleFactor*9, screenHeight-scaleFactor*(STATUSLINES/2-4),
  868.         scaleFactor*1, scaleFactor*14, color-3);
  869. }
  870.  
  871.  
  872. /*
  873. ===================
  874. =
  875. = DrawPlayBorder
  876. =
  877. ===================
  878. */
  879.  
  880. void DrawPlayBorder (void)
  881. {
  882.         const int px = scaleFactor; // size of one "pixel"
  883.  
  884.     if (bordercol != VIEWCOLOR)
  885.         DrawStatusBorder(bordercol);
  886.     else
  887.     {
  888.         const int statusborderw = (screenWidth-px*320)/2;
  889.         VWB_BarScaledCoord (0, screenHeight-px*STATUSLINES,
  890.             statusborderw+px*8, px*STATUSLINES, bordercol);
  891.         VWB_BarScaledCoord (screenWidth-statusborderw-px*8, screenHeight-px*STATUSLINES,
  892.             statusborderw+px*8, px*STATUSLINES, bordercol);
  893.     }
  894.  
  895.     if((unsigned) viewheight == screenHeight) return;
  896.  
  897.     VWB_BarScaledCoord (0,0,screenWidth,screenHeight-px*STATUSLINES,bordercol);
  898.  
  899.     const int xl = screenWidth/2-viewwidth/2;
  900.     const int yl = (screenHeight-px*STATUSLINES-viewheight)/2;
  901.     VWB_BarScaledCoord (xl,yl,viewwidth,viewheight,0);
  902.  
  903.     if(xl != 0)
  904.     {
  905.         // Paint game view border lines
  906.         VWB_BarScaledCoord(xl-px, yl-px, viewwidth+px, px, 0);                      // upper border
  907.         VWB_BarScaledCoord(xl, yl+viewheight, viewwidth+px, px, bordercol-2);       // lower border
  908.         VWB_BarScaledCoord(xl-px, yl-px, px, viewheight+px, 0);                     // left border
  909.         VWB_BarScaledCoord(xl+viewwidth, yl-px, px, viewheight+2*px, bordercol-2);  // right border
  910.         VWB_BarScaledCoord(xl-px, yl+viewheight, px, px, bordercol-3);              // lower left highlight
  911.     }
  912.     else
  913.     {
  914.         // Just paint a lower border line
  915.         VWB_BarScaledCoord(0, yl+viewheight, viewwidth, px, bordercol-2);       // lower border
  916.     }
  917. }
  918.  
  919.  
  920. /*
  921. ===================
  922. =
  923. = DrawPlayScreen
  924. =
  925. ===================
  926. */
  927.  
  928. void DrawPlayScreen (void)
  929. {
  930.     VWB_DrawPicScaledCoord ((screenWidth-scaleFactor*320)/2,screenHeight-scaleFactor*STATUSLINES,STATUSBARPIC);
  931.     DrawPlayBorder ();
  932.  
  933.     DrawFace ();
  934.     DrawHealth ();
  935.     DrawLives ();
  936.     DrawLevel ();
  937.     DrawAmmo ();
  938.     DrawKeys ();
  939.     DrawWeapon ();
  940.     DrawScore ();
  941. }
  942.  
  943. // Uses LatchDrawPic instead of StatusDrawPic
  944. void LatchNumberHERE (int x, int y, unsigned width, int32_t number)
  945. {
  946.     unsigned length,c;
  947.     char str[20];
  948.  
  949.     ltoa (number,str,10);
  950.  
  951.     length = (unsigned) strlen (str);
  952.  
  953.     while (length<width)
  954.     {
  955.         LatchDrawPic (x,y,N_BLANKPIC);
  956.         x++;
  957.         width--;
  958.     }
  959.  
  960.     c = length <= width ? 0 : length-width;
  961.  
  962.     while (c<length)
  963.     {
  964.         LatchDrawPic (x,y,str[c]-'0'+ N_0PIC);
  965.         x++;
  966.         c++;
  967.     }
  968. }
  969.  
  970. void ShowActStatus()
  971. {
  972.     // Draw status bar without borders
  973.     byte *source = grsegs[STATUSBARPIC];
  974.     int picnum = STATUSBARPIC - STARTPICS;
  975.     int width = pictable[picnum].width;
  976.     int height = pictable[picnum].height;
  977.     int destx = (screenWidth-scaleFactor*320)/2 + 9 * scaleFactor;
  978.     int desty = screenHeight - (height - 4) * scaleFactor;
  979.     VL_MemToScreenScaledCoord(source, width, height, 9, 4, destx, desty, width - 18, height - 7);
  980.  
  981.     ingame = false;
  982.     DrawFace ();
  983.     DrawHealth ();
  984.     DrawLives ();
  985.     DrawLevel ();
  986.     DrawAmmo ();
  987.     DrawKeys ();
  988.     DrawWeapon ();
  989.     DrawScore ();
  990.     ingame = true;
  991. }
  992.  
  993.  
  994. //==========================================================================
  995.  
  996. /*
  997. ==================
  998. =
  999. = StartDemoRecord
  1000. =
  1001. ==================
  1002. */
  1003.  
  1004. char    demoname[13] = "DEMO?.";
  1005.  
  1006. #ifndef REMDEBUG
  1007. #define MAXDEMOSIZE     8192
  1008.  
  1009. void StartDemoRecord (int levelnumber)
  1010. {
  1011.     demobuffer=malloc(MAXDEMOSIZE);
  1012.     CHECKMALLOCRESULT(demobuffer);
  1013.     demoptr = (int8_t *) demobuffer;
  1014.     lastdemoptr = demoptr+MAXDEMOSIZE;
  1015.  
  1016.     *demoptr = levelnumber;
  1017.     demoptr += 4;                           // leave space for length
  1018.     demorecord = true;
  1019. }
  1020.  
  1021.  
  1022. /*
  1023. ==================
  1024. =
  1025. = FinishDemoRecord
  1026. =
  1027. ==================
  1028. */
  1029.  
  1030. void FinishDemoRecord (void)
  1031. {
  1032.     int32_t    length,level;
  1033.  
  1034.     demorecord = false;
  1035.  
  1036.     length = (int32_t) (demoptr - (int8_t *)demobuffer);
  1037.  
  1038.     demoptr = ((int8_t *)demobuffer)+1;
  1039.     demoptr[0] = (int8_t) length;
  1040.     demoptr[1] = (int8_t) (length >> 8);
  1041.     demoptr[2] = 0;
  1042.  
  1043.     VW_FadeIn();
  1044.     CenterWindow(24,3);
  1045.     PrintY+=6;
  1046.     fontnumber=0;
  1047.     SETFONTCOLOR(0,15);
  1048.     US_Print(" Demo number (0-9): ");
  1049.     VW_UpdateScreen();
  1050.  
  1051.     if (US_LineInput (px,py,str,NULL,true,1,0))
  1052.     {
  1053.         level = atoi (str);
  1054.         if (level>=0 && level<=9)
  1055.         {
  1056.             demoname[4] = (char)('0'+level);
  1057.             CA_WriteFile (demoname,demobuffer,length);
  1058.         }
  1059.     }
  1060.  
  1061.     free(demobuffer);
  1062. }
  1063.  
  1064. //==========================================================================
  1065.  
  1066. /*
  1067. ==================
  1068. =
  1069. = RecordDemo
  1070. =
  1071. = Fades the screen out, then starts a demo.  Exits with the screen faded
  1072. =
  1073. ==================
  1074. */
  1075.  
  1076. void RecordDemo (void)
  1077. {
  1078.     int level,esc,maps;
  1079.  
  1080.     CenterWindow(26,3);
  1081.     PrintY+=6;
  1082.     CA_CacheGrChunk(STARTFONT);
  1083.     fontnumber=0;
  1084.     SETFONTCOLOR(0,15);
  1085. #ifndef SPEAR
  1086. #ifdef UPLOAD
  1087.     US_Print("  Demo which level(1-10): "); maps = 10;
  1088. #else
  1089.     US_Print("  Demo which level(1-60): "); maps = 60;
  1090. #endif
  1091. #else
  1092.     US_Print("  Demo which level(1-21): "); maps = 21;
  1093. #endif
  1094.     VW_UpdateScreen();
  1095.     VW_FadeIn ();
  1096.     esc = !US_LineInput (px,py,str,NULL,true,2,0);
  1097.     if (esc)
  1098.         return;
  1099.  
  1100.     level = atoi (str);
  1101.     level--;
  1102.  
  1103.     if (level >= maps || level < 0)
  1104.         return;
  1105.  
  1106.     VW_FadeOut ();
  1107.  
  1108. #ifndef SPEAR
  1109.     NewGame (gd_hard,level/10);
  1110.     gamestate.mapon = level%10;
  1111. #else
  1112.     NewGame (gd_hard,0);
  1113.     gamestate.mapon = level;
  1114. #endif
  1115.  
  1116.     StartDemoRecord (level);
  1117.  
  1118.     DrawPlayScreen ();
  1119.     VW_FadeIn ();
  1120.  
  1121.     startgame = false;
  1122.     demorecord = true;
  1123.  
  1124.     SetupGameLevel ();
  1125.     StartMusic ();
  1126.  
  1127.     if(usedoublebuffering) VH_UpdateScreen();
  1128.     fizzlein = true;
  1129.  
  1130.     PlayLoop ();
  1131.  
  1132.     demoplayback = false;
  1133.  
  1134.     StopMusic ();
  1135.     VW_FadeOut ();
  1136.     ClearMemory ();
  1137.  
  1138.     FinishDemoRecord ();
  1139. }
  1140. #else
  1141. void FinishDemoRecord (void) {return;}
  1142. void RecordDemo (void) {return;}
  1143. #endif
  1144.  
  1145.  
  1146.  
  1147. //==========================================================================
  1148.  
  1149. /*
  1150. ==================
  1151. =
  1152. = PlayDemo
  1153. =
  1154. = Fades the screen out, then starts a demo.  Exits with the screen unfaded
  1155. =
  1156. ==================
  1157. */
  1158.  
  1159. void PlayDemo (int demonumber)
  1160. {
  1161.     int length;
  1162. #ifdef DEMOSEXTERN
  1163. // debug: load chunk
  1164. #ifndef SPEARDEMO
  1165.     int dems[4]={T_DEMO0,T_DEMO1,T_DEMO2,T_DEMO3};
  1166. #else
  1167.     int dems[1]={T_DEMO0};
  1168. #endif
  1169.  
  1170.     CA_CacheGrChunk(dems[demonumber]);
  1171.     demoptr = (int8_t *) grsegs[dems[demonumber]];
  1172. #else
  1173.     demoname[4] = '0'+demonumber;
  1174.     CA_LoadFile (demoname,&demobuffer);
  1175.     demoptr = (int8_t *)demobuffer;
  1176. #endif
  1177.  
  1178.     NewGame (1,0);
  1179.     gamestate.mapon = *demoptr++;
  1180.     gamestate.difficulty = gd_hard;
  1181.     length = READWORD(*(uint8_t **)&demoptr);
  1182.     // TODO: Seems like the original demo format supports 16 MB demos
  1183.     //       But T_DEM00 and T_DEM01 of Wolf have a 0xd8 as third length size...
  1184.     demoptr++;
  1185.     lastdemoptr = demoptr-4+length;
  1186.  
  1187.     VW_FadeOut ();
  1188.  
  1189.     SETFONTCOLOR(0,15);
  1190.     DrawPlayScreen ();
  1191.  
  1192.     startgame = false;
  1193.     demoplayback = true;
  1194.  
  1195.     SetupGameLevel ();
  1196.     StartMusic ();
  1197.  
  1198.     PlayLoop ();
  1199.  
  1200. #ifdef DEMOSEXTERN
  1201.     UNCACHEGRCHUNK(dems[demonumber]);
  1202. #else
  1203.     MM_FreePtr (&demobuffer);
  1204. #endif
  1205.  
  1206.     demoplayback = false;
  1207.  
  1208.     StopMusic ();
  1209.     ClearMemory ();
  1210. }
  1211.  
  1212. //==========================================================================
  1213.  
  1214. /*
  1215. ==================
  1216. =
  1217. = Died
  1218. =
  1219. ==================
  1220. */
  1221.  
  1222. #define DEATHROTATE 2
  1223.  
  1224. void Died (void)
  1225. {
  1226.     float   fangle;
  1227.     int32_t dx,dy;
  1228.     int     iangle,curangle,clockwise,counter,change;
  1229.  
  1230.     if (screenfaded)
  1231.     {
  1232.         ThreeDRefresh ();
  1233.         VW_FadeIn ();
  1234.     }
  1235.  
  1236.     gamestate.weapon = (weapontype) -1;                     // take away weapon
  1237.     SD_PlaySound (PLAYERDEATHSND);
  1238.  
  1239.     //
  1240.     // swing around to face attacker
  1241.     //
  1242.     if(killerobj)
  1243.     {
  1244.         dx = killerobj->x - player->x;
  1245.         dy = player->y - killerobj->y;
  1246.  
  1247.         fangle = (float) atan2((float) dy, (float) dx);     // returns -pi to pi
  1248.         if (fangle<0)
  1249.             fangle = (float) (M_PI*2+fangle);
  1250.  
  1251.         iangle = (int) (fangle/(M_PI*2)*ANGLES);
  1252.     }
  1253.     else
  1254.     {
  1255.         iangle = player->angle + ANGLES / 2;
  1256.         if(iangle >= ANGLES) iangle -= ANGLES;
  1257.     }
  1258.  
  1259.     if (player->angle > iangle)
  1260.     {
  1261.         counter = player->angle - iangle;
  1262.         clockwise = ANGLES-player->angle + iangle;
  1263.     }
  1264.     else
  1265.     {
  1266.         clockwise = iangle - player->angle;
  1267.         counter = player->angle + ANGLES-iangle;
  1268.     }
  1269.  
  1270.     curangle = player->angle;
  1271.  
  1272.     if (clockwise<counter)
  1273.     {
  1274.         //
  1275.         // rotate clockwise
  1276.         //
  1277.         if (curangle>iangle)
  1278.             curangle -= ANGLES;
  1279.         do
  1280.         {
  1281.             change = tics*DEATHROTATE;
  1282.             if (curangle + change > iangle)
  1283.                 change = iangle-curangle;
  1284.  
  1285.             curangle += change;
  1286.             player->angle += change;
  1287.             if (player->angle >= ANGLES)
  1288.                 player->angle -= ANGLES;
  1289.  
  1290.             ThreeDRefresh ();
  1291.             CalcTics ();
  1292.         } while (curangle != iangle);
  1293.     }
  1294.     else
  1295.     {
  1296.         //
  1297.         // rotate counterclockwise
  1298.         //
  1299.         if (curangle<iangle)
  1300.             curangle += ANGLES;
  1301.         do
  1302.         {
  1303.             change = -(int)tics*DEATHROTATE;
  1304.             if (curangle + change < iangle)
  1305.                 change = iangle-curangle;
  1306.  
  1307.             curangle += change;
  1308.             player->angle += change;
  1309.             if (player->angle < 0)
  1310.                 player->angle += ANGLES;
  1311.  
  1312.             ThreeDRefresh ();
  1313.             CalcTics ();
  1314.         } while (curangle != iangle);
  1315.     }
  1316.  
  1317.     //
  1318.     // fade to red
  1319.     //
  1320.     FinishPaletteShifts ();
  1321.  
  1322.     if(usedoublebuffering) VH_UpdateScreen();
  1323.  
  1324.     VL_BarScaledCoord (viewscreenx,viewscreeny,viewwidth,viewheight,4);
  1325.  
  1326.     IN_ClearKeysDown ();
  1327.  
  1328.     FizzleFade(screenBuffer,viewscreenx,viewscreeny,viewwidth,viewheight,70,false);
  1329.  
  1330.     IN_UserInput(100);
  1331.     SD_WaitSoundDone ();
  1332.     ClearMemory();
  1333.  
  1334.     gamestate.lives--;
  1335.  
  1336.     if (gamestate.lives > -1)
  1337.     {
  1338.         gamestate.health = 100;
  1339.         gamestate.weapon = gamestate.bestweapon
  1340.             = gamestate.chosenweapon = wp_pistol;
  1341.         gamestate.ammo = STARTAMMO;
  1342.         gamestate.keys = 0;
  1343.         pwallstate = pwallpos = 0;
  1344.         gamestate.attackframe = gamestate.attackcount =
  1345.             gamestate.weaponframe = 0;
  1346.  
  1347.         if(viewsize != 21)
  1348.         {
  1349.             DrawKeys ();
  1350.             DrawWeapon ();
  1351.             DrawAmmo ();
  1352.             DrawHealth ();
  1353.             DrawFace ();
  1354.             DrawLives ();
  1355.         }
  1356.     }
  1357. }
  1358.  
  1359. //==========================================================================
  1360.  
  1361. /*
  1362. ===================
  1363. =
  1364. = GameLoop
  1365. =
  1366. ===================
  1367. */
  1368.  
  1369. void GameLoop (void)
  1370. {
  1371.     boolean died;
  1372. #ifdef MYPROFILE
  1373.     clock_t start,end;
  1374. #endif
  1375.  
  1376. restartgame:
  1377.     ClearMemory ();
  1378.     SETFONTCOLOR(0,15);
  1379.     VW_FadeOut();
  1380.     DrawPlayScreen ();
  1381.     died = false;
  1382.     do
  1383.     {
  1384.         if (!loadedgame)
  1385.             gamestate.score = gamestate.oldscore;
  1386.         if(!died || viewsize != 21) DrawScore();
  1387.  
  1388.         startgame = false;
  1389.         if (!loadedgame)
  1390.             SetupGameLevel ();
  1391.  
  1392. #ifdef SPEAR
  1393.         if (gamestate.mapon == 20)      // give them the key allways
  1394.         {
  1395.             gamestate.keys |= 1;
  1396.             DrawKeys ();
  1397.         }
  1398. #endif
  1399.  
  1400.         ingame = true;
  1401.         if(loadedgame)
  1402.         {
  1403.             ContinueMusic(lastgamemusicoffset);
  1404.             loadedgame = false;
  1405.         }
  1406.         else StartMusic ();
  1407.  
  1408.         if (!died)
  1409.             PreloadGraphics ();             // TODO: Let this do something useful!
  1410.         else
  1411.         {
  1412.             died = false;
  1413.             fizzlein = true;
  1414.         }
  1415.  
  1416.         DrawLevel ();
  1417.  
  1418. #ifdef SPEAR
  1419. startplayloop:
  1420. #endif
  1421.         PlayLoop ();
  1422.  
  1423. #ifdef SPEAR
  1424.         if (spearflag)
  1425.         {
  1426.             SD_StopSound();
  1427.             SD_PlaySound(GETSPEARSND);
  1428.             if (DigiMode != sds_Off)
  1429.             {
  1430.                 Delay(150);
  1431.             }
  1432.             else
  1433.                 SD_WaitSoundDone();
  1434.  
  1435.             ClearMemory ();
  1436.             gamestate.oldscore = gamestate.score;
  1437.             gamestate.mapon = 20;
  1438.             SetupGameLevel ();
  1439.             StartMusic ();
  1440.             player->x = spearx;
  1441.             player->y = speary;
  1442.             player->angle = (short)spearangle;
  1443.             spearflag = false;
  1444.             Thrust (0,0);
  1445.             goto startplayloop;
  1446.         }
  1447. #endif
  1448.  
  1449.         StopMusic ();
  1450.         ingame = false;
  1451.  
  1452.         if (demorecord && playstate != ex_warped)
  1453.             FinishDemoRecord ();
  1454.  
  1455.         if (startgame || loadedgame)
  1456.             goto restartgame;
  1457.  
  1458.         switch (playstate)
  1459.         {
  1460.             case ex_completed:
  1461.             case ex_secretlevel:
  1462.                 if(viewsize == 21) DrawPlayScreen();
  1463.                 gamestate.keys = 0;
  1464.                 DrawKeys ();
  1465.                 VW_FadeOut ();
  1466.  
  1467.                 ClearMemory ();
  1468.  
  1469.                 LevelCompleted ();              // do the intermission
  1470.                 if(viewsize == 21) DrawPlayScreen();
  1471.  
  1472. #ifdef SPEARDEMO
  1473.                 if (gamestate.mapon == 1)
  1474.                 {
  1475.                     died = true;                    // don't "get psyched!"
  1476.  
  1477.                     VW_FadeOut ();
  1478.  
  1479.                     ClearMemory ();
  1480.  
  1481.                     CheckHighScore (gamestate.score,gamestate.mapon+1);
  1482. #ifndef JAPAN
  1483.                     strcpy(MainMenu[viewscores].string,STR_VS);
  1484. #endif
  1485.                     MainMenu[viewscores].routine = CP_ViewScores;
  1486.                     return;
  1487.                 }
  1488. #endif
  1489.  
  1490. #ifdef JAPDEMO
  1491.                 if (gamestate.mapon == 3)
  1492.                 {
  1493.                     died = true;                    // don't "get psyched!"
  1494.  
  1495.                     VW_FadeOut ();
  1496.  
  1497.                     ClearMemory ();
  1498.  
  1499.                     CheckHighScore (gamestate.score,gamestate.mapon+1);
  1500. #ifndef JAPAN
  1501.                     strcpy(MainMenu[viewscores].string,STR_VS);
  1502. #endif
  1503.                     MainMenu[viewscores].routine = CP_ViewScores;
  1504.                     return;
  1505.                 }
  1506. #endif
  1507.  
  1508.                 gamestate.oldscore = gamestate.score;
  1509.  
  1510. #ifndef SPEAR
  1511.                 //
  1512.                 // COMING BACK FROM SECRET LEVEL
  1513.                 //
  1514.                 if (gamestate.mapon == 9)
  1515.                     gamestate.mapon = ElevatorBackTo[gamestate.episode];    // back from secret
  1516.                 else
  1517.                     //
  1518.                     // GOING TO SECRET LEVEL
  1519.                     //
  1520.                     if (playstate == ex_secretlevel)
  1521.                         gamestate.mapon = 9;
  1522. #else
  1523.  
  1524. #define FROMSECRET1             3
  1525. #define FROMSECRET2             11
  1526.  
  1527.                 //
  1528.                 // GOING TO SECRET LEVEL
  1529.                 //
  1530.                 if (playstate == ex_secretlevel)
  1531.                     switch(gamestate.mapon)
  1532.                 {
  1533.                     case FROMSECRET1: gamestate.mapon = 18; break;
  1534.                     case FROMSECRET2: gamestate.mapon = 19; break;
  1535.                 }
  1536.                 else
  1537.                     //
  1538.                     // COMING BACK FROM SECRET LEVEL
  1539.                     //
  1540.                     if (gamestate.mapon == 18 || gamestate.mapon == 19)
  1541.                         switch(gamestate.mapon)
  1542.                     {
  1543.                         case 18: gamestate.mapon = FROMSECRET1+1; break;
  1544.                         case 19: gamestate.mapon = FROMSECRET2+1; break;
  1545.                     }
  1546. #endif
  1547.                     else
  1548.                         //
  1549.                         // GOING TO NEXT LEVEL
  1550.                         //
  1551.                         gamestate.mapon++;
  1552.                 break;
  1553.  
  1554.             case ex_died:
  1555.                 Died ();
  1556.                 died = true;                    // don't "get psyched!"
  1557.  
  1558.                 if (gamestate.lives > -1)
  1559.                     break;                          // more lives left
  1560.  
  1561.                 VW_FadeOut ();
  1562.                 if(screenHeight % 200 != 0)
  1563.                     VL_ClearScreen(0);
  1564.  
  1565. #ifdef _arch_dreamcast
  1566.                 DC_StatusClearLCD();
  1567. #endif
  1568.  
  1569.                 ClearMemory ();
  1570.  
  1571.                 CheckHighScore (gamestate.score,gamestate.mapon+1);
  1572. #ifndef JAPAN
  1573.                 strcpy(MainMenu[viewscores].string,STR_VS);
  1574. #endif
  1575.                 MainMenu[viewscores].routine = CP_ViewScores;
  1576.                 return;
  1577.  
  1578.             case ex_victorious:
  1579.                 if(viewsize == 21) DrawPlayScreen();
  1580. #ifndef SPEAR
  1581.                 VW_FadeOut ();
  1582. #else
  1583.                 VL_FadeOut (0,255,0,17,17,300);
  1584. #endif
  1585.                 ClearMemory ();
  1586.  
  1587.                 Victory ();
  1588.  
  1589.                 ClearMemory ();
  1590.  
  1591.                 CheckHighScore (gamestate.score,gamestate.mapon+1);
  1592. #ifndef JAPAN
  1593.                 strcpy(MainMenu[viewscores].string,STR_VS);
  1594. #endif
  1595.                 MainMenu[viewscores].routine = CP_ViewScores;
  1596.                 return;
  1597.  
  1598.             default:
  1599.                 if(viewsize == 21) DrawPlayScreen();
  1600.                 ClearMemory ();
  1601.                 break;
  1602.         }
  1603.     } while (1);
  1604. }
  1605.