C6_GAME.C 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600
  1. /* Catacomb Apocalypse Source Code
  2. * Copyright (C) 1993-2014 Flat Rock Software
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. */
  18. // C3_GAME.C
  19. #include <stdlib.h>
  20. #include "DEF.H"
  21. #include "gelib.h"
  22. #pragma hdrstop
  23. #ifdef PROFILE
  24. #include "TIME.H"
  25. #endif
  26. /*
  27. =============================================================================
  28. LOCAL CONSTANTS
  29. =============================================================================
  30. */
  31. #define NUMLUMPS 45
  32. #define EYESTALKLUMP 0
  33. #define BLOBLUMP 1
  34. #define BOLTLUMP 2
  35. #define NUKELUMP 3
  36. #define POTIONLUMP 4
  37. #define RKEYLUMP 5
  38. #define YKEYLUMP 6
  39. #define GKEYLUMP 7
  40. #define BKEYLUMP 8
  41. #define RGEMLUMP 9
  42. #define GGEMLUMP 10
  43. #define BGEMLUMP 11
  44. #define YGEMLUMP 12
  45. #define PGEMLUMP 13
  46. #define CHESTLUMP 14
  47. #define PLAYERLUMP 15
  48. #define FTIMELUMP 16
  49. #define PORTALLUMP 17
  50. #define COLUMN1LUMP 18
  51. #define FIREPOTLUMP 19
  52. #define COLUMN2LUMP 20
  53. #define EYELUMP 21
  54. #define FUTUREMAGELUMP 22
  55. #define FORCEFIELDLUMP 23
  56. #define ROBOTANKLUMP 24
  57. #define RAMBONELUMP 25
  58. #define STOMPYLUMP 26
  59. #define TROLLLUMP 27
  60. #define WIZARDLUMP 28
  61. #define HEADLUMP 29
  62. #define INVISDUDELUMP 30
  63. #define BUGLUMP 31
  64. #define CYBORGLUMP 32
  65. #define WATERCHESTLUMP 33
  66. #define GRELLUMP 34
  67. #define RAYLUMP 35
  68. #define COLUMN3LUMP 36
  69. #define OLDCHESTLUMP 37
  70. #define OLDFIREPOTLUMP 38
  71. #define COLUMN4LUMP 39
  72. #define TOMB1LUMP 40
  73. #define TOMB2LUMP 41
  74. #define DEMONLUMP 42
  75. #define COLUMN5LUMP 43
  76. int lumpstart[NUMLUMPS] = {
  77. EYESTALK_LUMP_START,
  78. BLOB_LUMP_START,
  79. BOLT_LUMP_START,
  80. NUKE_LUMP_START,
  81. POTION_LUMP_START,
  82. RKEY_LUMP_START,
  83. YKEY_LUMP_START,
  84. GKEY_LUMP_START,
  85. BKEY_LUMP_START,
  86. RGEM_LUMP_START,
  87. GGEM_LUMP_START,
  88. BGEM_LUMP_START,
  89. YGEM_LUMP_START,
  90. PGEM_LUMP_START,
  91. CHEST_LUMP_START,
  92. PLAYER_LUMP_START,
  93. TIME_LUMP_START,
  94. PORTAL_LUMP_START,
  95. COLUMN1_LUMP_START,
  96. FFIREPOT_LUMP_START,
  97. COLUMN2_LUMP_START,
  98. EYE_LUMP_START,
  99. FUTUREMAGE_LUMP_START,
  100. FORCEFIELD_LUMP_START,
  101. ROBOTANK_LUMP_START,
  102. RAMBONE_LUMP_START,
  103. STOMPY_LUMP_START,
  104. TROLL_LUMP_START,
  105. WIZARD_LUMP_START,
  106. HEAD_LUMP_START,
  107. INVISDUDE_LUMP_START,
  108. BUG_LUMP_START,
  109. CYBORG_LUMP_START,
  110. O_WATER_CHEST_LUMP_START,
  111. GREL_LUMP_START,
  112. RAY_LUMP_START,
  113. COLUMN3_LUMP_START,
  114. OLD_CHEST_LUMP_START,
  115. OFIREPOT_LUMP_START,
  116. COLUMN4_LUMP_START,
  117. TOMB1_LUMP_START,
  118. TOMB2_LUMP_START,
  119. DEMON_LUMP_START,
  120. COLUMN5_LUMP_START,
  121. };
  122. int lumpend[NUMLUMPS] = {
  123. EYESTALK_LUMP_END,
  124. BLOB_LUMP_END,
  125. BOLT_LUMP_END,
  126. NUKE_LUMP_END,
  127. POTION_LUMP_END,
  128. RKEY_LUMP_END,
  129. YKEY_LUMP_END,
  130. GKEY_LUMP_END,
  131. BKEY_LUMP_END,
  132. RGEM_LUMP_END,
  133. GGEM_LUMP_END,
  134. BGEM_LUMP_END,
  135. YGEM_LUMP_END,
  136. PGEM_LUMP_END,
  137. CHEST_LUMP_END,
  138. PLAYER_LUMP_END,
  139. TIME_LUMP_END,
  140. PORTAL_LUMP_END,
  141. COLUMN1_LUMP_END,
  142. FFIREPOT_LUMP_END,
  143. COLUMN2_LUMP_END,
  144. EYE_LUMP_END,
  145. FUTUREMAGE_LUMP_END,
  146. FORCEFIELD_LUMP_END,
  147. ROBOTANK_LUMP_END,
  148. RAMBONE_LUMP_END,
  149. STOMPY_LUMP_END,
  150. TROLL_LUMP_END,
  151. WIZARD_LUMP_END,
  152. HEAD_LUMP_END,
  153. INVISDUDE_LUMP_END,
  154. BUG_LUMP_END,
  155. CYBORG_LUMP_END,
  156. O_WATER_CHEST_LUMP_END,
  157. GREL_LUMP_END,
  158. RAY_LUMP_END,
  159. COLUMN3_LUMP_END,
  160. OLD_CHEST_LUMP_END,
  161. OFIREPOT_LUMP_END,
  162. COLUMN4_LUMP_END,
  163. TOMB1_LUMP_END,
  164. TOMB2_LUMP_END,
  165. DEMON_LUMP_END,
  166. COLUMN5_LUMP_END,
  167. };
  168. /*
  169. =============================================================================
  170. GLOBAL VARIABLES
  171. =============================================================================
  172. */
  173. unsigned latchpics[NUMLATCHPICS];
  174. unsigned tileoffsets[NUMTILE16];
  175. unsigned textstarts[27];
  176. boolean splitscreen=false;
  177. /*
  178. =============================================================================
  179. LOCAL VARIABLES
  180. =============================================================================
  181. */
  182. boolean lumpneeded[NUMLUMPS];
  183. //===========================================================================
  184. /*
  185. ==========================
  186. =
  187. = ScanInfoPlane
  188. =
  189. = Spawn all actors and mark down special places
  190. =
  191. ==========================
  192. */
  193. void ScanInfoPlane (void)
  194. {
  195. unsigned char hibyte;
  196. unsigned x,y,i,j;
  197. unsigned int tile;
  198. unsigned far *start;
  199. InitObjList(); // start spawning things with a clean slate
  200. scolor = gcolor = 0;
  201. skycolor = &scolor;
  202. groundcolor = &gcolor;
  203. memset (lumpneeded,0,sizeof(lumpneeded));
  204. start = mapsegs[2];
  205. for (y=0;y<mapheight;y++)
  206. for (x=0;x<mapwidth;x++)
  207. {
  208. tile = *start++;
  209. hibyte = tile >> 8;
  210. tile &= 0xff;
  211. switch (hibyte)
  212. {
  213. char hi;
  214. case 0xFB:
  215. wall_anim_time = tile;
  216. tile = 0;
  217. break;
  218. case 0xfa: // sky/ground color
  219. x++;
  220. tile = *start++;
  221. hi = tile >> 8;
  222. tile &= 0xff;
  223. switch (hibyte)
  224. {
  225. case 0xfa: // sky / ground color
  226. scolor = ((hi)|(hi<<8));
  227. gcolor = ((tile)|(tile<<8));
  228. skycolor = &scolor;
  229. groundcolor = &gcolor;
  230. break;
  231. }
  232. break;
  233. }
  234. if ((!tile) || (hibyte))
  235. continue;
  236. switch (tile)
  237. {
  238. case 1:
  239. case 2:
  240. case 3:
  241. case 4:
  242. lumpneeded[PLAYERLUMP] = true;
  243. SpawnPlayer(x,y,NORTH+tile-1);
  244. break;
  245. case 5:
  246. case 6:
  247. case 7:
  248. case 8:
  249. case 9:
  250. case 10:
  251. case 11:
  252. lumpneeded[tile-5+BOLTLUMP] = true;
  253. SpawnBonus(x,y,tile-5);
  254. break;
  255. case 12:
  256. lumpneeded[EYESTALKLUMP] = true;
  257. SpawnAquaMan(x, y);
  258. break;
  259. case 13:
  260. lumpneeded[BLOBLUMP] = true;
  261. SpawnBlob(x, y);
  262. break;
  263. case 14:
  264. lumpneeded[BUGLUMP] = true;
  265. SpawnBug(x, y);
  266. break;
  267. case 15:
  268. lumpneeded[CYBORGLUMP] = true;
  269. SpawnCyborgDemon(x, y);
  270. break;
  271. case 16:
  272. lumpneeded[EYELUMP] = true;
  273. SpawnShooterEye(x, y);
  274. break;
  275. case 17:
  276. lumpneeded[FUTUREMAGELUMP] = true;
  277. SpawnFutureMage(x, y);
  278. break;
  279. case 18:
  280. lumpneeded[INVISDUDELUMP] = true;
  281. SpawnInvisDude(x, y);
  282. break;
  283. case 19:
  284. lumpneeded[ROBOTANKLUMP] = true;
  285. SpawnRoboTank(x, y);
  286. break;
  287. case 20:
  288. lumpneeded[RAMBONELUMP] = true;
  289. SpawnRamBone(x, y);
  290. break;
  291. case 21:
  292. lumpneeded[STOMPYLUMP] = true;
  293. SpawnStompy(x, y);
  294. break;
  295. case 22:
  296. lumpneeded[TROLLLUMP] = true;
  297. SpawnTroll(x, y);
  298. break;
  299. case 23:
  300. lumpneeded[WIZARDLUMP] = true;
  301. SpawnWizard(x, y);
  302. break;
  303. case 24:
  304. SpawnBounce(x, y, 0);
  305. break;
  306. case 25:
  307. SpawnBounce(x, y, 1);
  308. break;
  309. case 26:
  310. lumpneeded[RKEYLUMP] = lumpneeded[GRELLUMP] = true;
  311. SpawnGrelminar (x,y);
  312. break;
  313. case 27:
  314. lumpneeded[EYELUMP] = true;
  315. SpawnRunningEye(x,y);
  316. break;
  317. case 28:
  318. lumpneeded[RAYLUMP] = true;
  319. SpawnRay(x, y);
  320. break;
  321. case 29:
  322. lumpneeded[HEADLUMP] = true;
  323. SpawnEgyptianHead(x, y);
  324. break;
  325. case 30:
  326. lumpneeded[DEMONLUMP] = true;
  327. SpawnDemon(x, y);
  328. break;
  329. case 31:
  330. lumpneeded[COLUMN5LUMP] = true;
  331. SpawnMiscObjects(x, y, 9);
  332. break;
  333. case 32:
  334. SpawnInvisWallCntroller(x, y);
  335. break;
  336. case 33:
  337. break;
  338. case 34:
  339. break;
  340. case 35:
  341. break;
  342. case 36:
  343. lumpneeded[COLUMN1LUMP] = true;
  344. SpawnMiscObjects(x, y, 1);
  345. break;
  346. case 37:
  347. lumpneeded[FIREPOTLUMP] = true;
  348. SpawnMiscObjects(x, y, 4);
  349. break;
  350. case 38:
  351. lumpneeded[PORTALLUMP] = true;
  352. SpawnWarp(x, y);
  353. break;
  354. case 39:
  355. lumpneeded[FTIMELUMP] = true;
  356. SpawnFTime(x,y);
  357. break;
  358. case 40:
  359. case 41:
  360. case 42:
  361. case 43:
  362. case 44:
  363. lumpneeded[tile-40+RGEMLUMP] = true;
  364. SpawnBonus(x,y,tile-40+B_RGEM);
  365. break;
  366. case 45:
  367. lumpneeded[COLUMN2LUMP] = true;
  368. SpawnMiscObjects(x, y, 2);
  369. break;
  370. case 46:
  371. lumpneeded[COLUMN3LUMP] = true;
  372. SpawnMiscObjects(x, y, 3);
  373. break;
  374. case 47:
  375. lumpneeded[FORCEFIELDLUMP] = true;
  376. SpawnForceField(x, y);
  377. break;
  378. case 48:
  379. lumpneeded[OLDCHESTLUMP] = true;
  380. SpawnBonus(x, y, B_OLDCHEST);
  381. break;
  382. case 49: // chest
  383. if (gcolor == 0x0101)
  384. lumpneeded[WATERCHESTLUMP] = true;
  385. else
  386. lumpneeded[CHESTLUMP] = true;
  387. SpawnBonus(x,y,B_CHEST);
  388. break;
  389. case 50:
  390. lumpneeded[COLUMN4LUMP] = true;
  391. SpawnMiscObjects(x, y, 5);
  392. break;
  393. case 51:
  394. lumpneeded[OLDFIREPOTLUMP] = true;
  395. SpawnMiscObjects(x, y, 6);
  396. break;
  397. case 52:
  398. lumpneeded[TOMB1LUMP] = true;
  399. SpawnMiscObjects(x, y, 7);
  400. break;
  401. case 53:
  402. lumpneeded[TOMB2LUMP] = true;
  403. SpawnMiscObjects(x, y, 8);
  404. break;
  405. case 54:
  406. break;
  407. case 55:
  408. break;
  409. case 56:
  410. break;
  411. case 57:
  412. break;
  413. case 58:
  414. break;
  415. case 59:
  416. break;
  417. case 60:
  418. break;
  419. case 61:
  420. break;
  421. case 62:
  422. break;
  423. case 63:
  424. break;
  425. case 64:
  426. break;
  427. case 65:
  428. break;
  429. case 66:
  430. break;
  431. case 67:
  432. break;
  433. case 68:
  434. break;
  435. case 69:
  436. break;
  437. case 70:
  438. break;
  439. case 71:
  440. break;
  441. }
  442. }
  443. }
  444. //==========================================================================
  445. /*
  446. ==================
  447. =
  448. = ScanText
  449. =
  450. ==================
  451. */
  452. void ScanText (void)
  453. {
  454. int i;
  455. char far *text;
  456. text = (char _seg *)grsegs[LEVEL1TEXT+mapon];
  457. textstarts[0] = 0;
  458. for (i=1;i<=26;i++)
  459. {
  460. while (*text != '\n')
  461. {
  462. if (*text == '\r')
  463. *text = 0;
  464. text++;
  465. }
  466. text++;
  467. textstarts[i] = FP_OFF(text);
  468. }
  469. }
  470. //==========================================================================
  471. /*
  472. ==================
  473. =
  474. = DrawEnterScreen
  475. =
  476. ==================
  477. */
  478. #if 0
  479. static char *levelnames[] =
  480. {
  481. "Programmers Test Map",
  482. "The Garden of Tears",
  483. "The Den of Zombies",
  484. "The Mausoleum Grounds",
  485. "The Main Floor of the Mausoleum",
  486. "Mike's Blastable Passage",
  487. "The Crypt of Nemesis the Undead",
  488. "The Subterranean Vault",
  489. "The Ancient Aqueduct",
  490. "The Orc Mines",
  491. "The Lair of the Troll",
  492. "The Demon's Inferno",
  493. "The Battleground of the Titans",
  494. "The Coven of Mages",
  495. "The Inner Sanctum",
  496. "The Haunt of Nemesis",
  497. "The Passage to the Surface",
  498. "Big Jim's Domain",
  499. "Nolan",
  500. "19",
  501. "20",
  502. "21",
  503. "22",
  504. "23",
  505. "24",
  506. "25",
  507. "26",
  508. "27",
  509. "28",
  510. "29",
  511. "30",
  512. "31",
  513. "32",
  514. "33",
  515. "34",
  516. "35",
  517. "36",
  518. "37",
  519. "38",
  520. "39",
  521. };
  522. #endif
  523. void DrawEnterScreen ()
  524. {
  525. int width;
  526. bufferofs = displayofs = screenloc[screenpage];
  527. VW_Bar(0,0,VIEWWIDTH,VIEWHEIGHT,0);
  528. // width = strlen(levelnames[gamestate.mapon]);
  529. width = strlen("A new challenge awaits you.");
  530. if (width < 20)
  531. width = 20;
  532. CenterWindow(width,3);
  533. US_CPrint("\nA new challenge awaits you.\n");
  534. // US_CPrint(levelnames[gamestate.mapon]);
  535. }
  536. //==========================================================================
  537. boolean tileneeded[NUMFLOORS];
  538. /*
  539. ==================
  540. =
  541. = CacheScaleds
  542. =
  543. ==================
  544. */
  545. void CacheScaleds (void)
  546. {
  547. int i,j;
  548. unsigned source,dest;
  549. FreeUpMemory ();
  550. CA_CacheGrChunk(LEVEL1TEXT+mapon);
  551. ScanText ();
  552. //
  553. // make sure we are displaying screenpage 0
  554. //
  555. if (screenpage)
  556. {
  557. source = screenloc[screenpage];
  558. dest = screenloc[0];
  559. VW_ScreenToScreen (source,dest,40,VIEWHEIGHT);
  560. screenpage = 0;
  561. VW_SetScreen (dest,0);
  562. displayofs = dest;
  563. }
  564. //
  565. // cache wall pictures
  566. //
  567. for (i=1;i<NUMFLOORS;i++)
  568. if (tileneeded[i])
  569. {
  570. SetupScaleWall (walllight1[i]);
  571. SetupScaleWall (walldark1[i]);
  572. }
  573. //
  574. // cache the actor pictures
  575. //
  576. for (i=0;i<NUMLUMPS;i++)
  577. if (lumpneeded[i])
  578. for (j=lumpstart[i];j<=lumpend[i];j++)
  579. SetupScalePic(j);
  580. source = screenloc[0];
  581. for (i=1;i<=2;i++)
  582. {
  583. dest = screenloc[i];
  584. VW_ScreenToScreen (source,dest,40,VIEWHEIGHT);
  585. }
  586. screenpage = 1;
  587. }
  588. //==========================================================================
  589. /*
  590. ==================
  591. =
  592. = SetupGameLevel
  593. =
  594. ==================
  595. */
  596. void SetupGameLevel ()
  597. {
  598. int x,y,i,loop;
  599. unsigned far *map,tile,far *spotptr,spot;
  600. unsigned search_tile;
  601. boolean exploding_walls_present = false;
  602. memset (tileneeded,0,sizeof(tileneeded));
  603. //
  604. // randomize if not a demo
  605. //
  606. #if 0
  607. if (DemoMode)
  608. {
  609. US_InitRndT(false);
  610. gamestate.difficulty = gd_Normal;
  611. }
  612. else
  613. #endif
  614. US_InitRndT(true);
  615. //
  616. // load the level
  617. //
  618. CA_CacheMap (gamestate.mapon);
  619. mapwidth = mapheaderseg[mapon]->width;
  620. mapheight = mapheaderseg[mapon]->height;
  621. //
  622. // make a lookup table for the maps left edge
  623. //
  624. spot = 0;
  625. for (y=0;y<mapheight;y++)
  626. {
  627. farmapylookup[y] = spot;
  628. spot += mapwidth;
  629. }
  630. //
  631. // copy the wall data to a data segment array
  632. //
  633. memset (tilemap,0,sizeof(tilemap));
  634. memset (actorat,0,sizeof(actorat));
  635. map = mapsegs[0];
  636. spotptr = mapsegs[2];
  637. for (y=0;y<mapheight;y++)
  638. for (x=0;x<mapwidth;x++)
  639. {
  640. tile = *map++;
  641. if (((*spotptr)>>8) == EXP_WALL_CODE)
  642. {
  643. exploding_walls_present = true;
  644. }
  645. if (tile<NUMFLOORS)
  646. {
  647. #if 0
  648. if (tile == WALL_SKELETON_CODE)
  649. {
  650. tileneeded[tile+1] = tileneeded[tile+2] = true;
  651. tilemap[x][y] = tile;
  652. }
  653. #endif
  654. if ((tile == 66) || (tile == 67) || (tile == 68) || (tile == 69))
  655. {
  656. if ((tile == 66) || (tile == 67))
  657. tileneeded[tile+2] = true;
  658. tileneeded[21] = tileneeded[tile] = true;
  659. tilemap[x][y] = tile;
  660. }
  661. else
  662. if (tile != INVISIBLEWALL)
  663. {
  664. tileneeded[tile] = true;
  665. tilemap[x][y] = tile;
  666. if (ANIM_FLAGS(tile))
  667. {
  668. search_tile = tile+(char signed)ANIM_FLAGS(tile);
  669. if (!tileneeded[search_tile])
  670. while (search_tile != tile)
  671. {
  672. tileneeded[search_tile] = true;
  673. if (ANIM_FLAGS(search_tile))
  674. search_tile += (char signed)ANIM_FLAGS(search_tile);
  675. else
  676. TrashProg("Unending Tile Animation!");
  677. }
  678. }
  679. }
  680. if (tile>0)
  681. (unsigned)actorat[x][y] = tile;
  682. }
  683. spotptr++;
  684. }
  685. //
  686. // Mark any gfx chunks needed
  687. //
  688. // CA_MarkGrChunk(NORTHICONSPR);
  689. // CA_CacheMarks(NULL);
  690. //
  691. // decide which graphics are needed and spawn actors
  692. //
  693. head_base_delay = 0; // (1*60) + random(1*60);
  694. ScanInfoPlane ();
  695. _fmemset(wall_anim_pos,0,sizeof(wall_anim_pos));
  696. //
  697. // mark which exploding walls are needed ---- the check for floor color
  698. // is preformed in ScanInfoPlane.
  699. //
  700. if (exploding_walls_present)
  701. {
  702. extern unsigned gnd_colors[];
  703. if (gcolor == 0x0101)
  704. tileneeded[WATEREXP] = tileneeded[WATEREXP+1] = tileneeded[WATEREXP+2] = true;
  705. else
  706. tileneeded[WALLEXP] = tileneeded[WALLEXP+1] = tileneeded[WALLEXP+2] = true;
  707. }
  708. //
  709. // have the caching manager load and purge stuff to make sure all marks
  710. // are in memory
  711. //
  712. CA_LoadAllSounds ();
  713. }
  714. //==========================================================================
  715. /*
  716. =====================
  717. =
  718. = LatchDrawPic
  719. =
  720. =====================
  721. */
  722. void LatchDrawPic (unsigned x, unsigned y, unsigned picnum)
  723. {
  724. unsigned height, source, dest;
  725. unsigned wide;
  726. wide = pictable[picnum-STARTPICS].width;
  727. height = pictable[picnum-STARTPICS].height;
  728. dest = bufferofs + ylookup[y]+x;
  729. source = latchpics[picnum-FIRSTLATCHPIC];
  730. EGAWRITEMODE(1);
  731. EGAMAPMASK(15);
  732. asm mov bx,[linewidth]
  733. asm sub bx,[wide]
  734. asm mov ax,[screenseg]
  735. asm mov es,ax
  736. asm mov ds,ax
  737. asm mov si,[source]
  738. asm mov di,[dest]
  739. asm mov dx,[height] // scan lines to draw
  740. asm mov ax,[wide]
  741. lineloop:
  742. asm mov cx,ax
  743. asm rep movsb
  744. asm add di,bx
  745. asm dec dx
  746. asm jnz lineloop
  747. asm mov ax,ss
  748. asm mov ds,ax // restore turbo's data segment
  749. EGAWRITEMODE(0);
  750. }
  751. #if USE_STRIPS
  752. //--------------------------------------------------------------------------
  753. // LatchDrawPicStrip() - srcoff is distance into source file (in PIXELS!)
  754. //--------------------------------------------------------------------------
  755. void LatchDrawPicStrip (unsigned x, unsigned y, unsigned picnum, unsigned srcoff)
  756. {
  757. unsigned wide, height, source, dest, shift, srcmod;
  758. shift = (srcoff & 7) >> 1;
  759. srcoff >>= 3;
  760. wide = pictable[picnum-STARTPICS].width;
  761. srcmod = wide - linewidth + (shift != 3);
  762. if (wide > linewidth)
  763. wide = linewidth;
  764. height = pictable[picnum-STARTPICS].height;
  765. dest = bufferofs + ylookup[y]+x;
  766. picnum = ((picnum - (FIRSTSTRIPPIC+1)) >> 2) + (shift);
  767. source = latchpics[(FIRSTSTRIPPIC-FIRSTLATCHPIC+1)+picnum];
  768. EGAWRITEMODE(1);
  769. EGAMAPMASK(15);
  770. asm mov bx,[linewidth]
  771. asm sub bx,[wide]
  772. asm mov ax,[screenseg]
  773. asm mov es,ax
  774. asm mov ds,ax
  775. asm mov si,[source]
  776. asm add si,[srcoff]
  777. asm mov di,[dest]
  778. asm mov dx,[height] // scan lines to draw
  779. asm mov ax,[wide]
  780. lineloop:
  781. asm mov cx,ax
  782. asm rep movsb
  783. asm add di,bx
  784. asm add si,[srcmod]
  785. asm dec dx
  786. asm jnz lineloop
  787. asm mov ax,ss
  788. asm mov ds,ax // restore turbo's data segment
  789. EGAWRITEMODE(0);
  790. }
  791. #endif
  792. //==========================================================================
  793. /*
  794. =====================
  795. =
  796. = Victory
  797. =
  798. =====================
  799. */
  800. void Victory (boolean playsounds)
  801. {
  802. struct Shape shape;
  803. if (playsounds)
  804. {
  805. SD_PlaySound (GETBOLTSND);
  806. SD_WaitSoundDone ();
  807. SD_PlaySound (GETNUKESND);
  808. SD_WaitSoundDone ();
  809. SD_PlaySound (GETPOTIONSND);
  810. SD_WaitSoundDone ();
  811. SD_PlaySound (GETKEYSND);
  812. SD_WaitSoundDone ();
  813. // SD_PlaySound (GETSCROLLSND);
  814. // SD_WaitSoundDone ();
  815. SD_PlaySound (GETPOINTSSND);
  816. }
  817. FreeUpMemory();
  818. if (!screenfaded)
  819. VW_FadeOut();
  820. NormalScreen ();
  821. screenpage = bufferofs = 0;
  822. CA_CacheGrChunk (FINALEPIC);
  823. UNMARKGRCHUNK(FINALEPIC);
  824. VW_DrawPic(0, 0, FINALEPIC);
  825. VW_FadeIn();
  826. }
  827. //==========================================================================
  828. #if 0
  829. /*
  830. ===================
  831. =
  832. = Died
  833. =
  834. ===================
  835. */
  836. void Died (void)
  837. {
  838. unsigned page1,page2;
  839. //
  840. // fizzle fade screen to grey
  841. //
  842. FreeUpMemory ();
  843. SD_PlaySound (GAMEOVERSND);
  844. bufferofs = screenloc[(screenpage+1)%3];
  845. DisplayMsg("Though fallen, your Spirit ...",NULL);
  846. // LatchDrawPic(0,0,DEADPIC);
  847. // FizzleFade(bufferofs,displayofs,VIEWWIDTH,VIEWHEIGHT,false);
  848. IN_ClearKeysDown();
  849. while (!Keyboard[sc_Enter]);
  850. // IN_Ack();
  851. VW_SetScreen (bufferofs,0);
  852. VW_ColorBorder(0);
  853. }
  854. #endif
  855. //==========================================================================
  856. /*
  857. ===================
  858. =
  859. = NormalScreen
  860. =
  861. ===================
  862. */
  863. void NormalScreen (void)
  864. {
  865. VW_SetSplitScreen (200);
  866. bufferofs = displayofs = SCREEN1START;
  867. VW_Bar(0,0,320,200,0);
  868. bufferofs = SCREEN2START;
  869. VW_Bar(0,0,320,200,0);
  870. VW_SetScreen (displayofs,0);
  871. splitscreen = false;
  872. }
  873. //==========================================================================
  874. /*
  875. ===================
  876. =
  877. = DrawPlayScreen
  878. =
  879. ===================
  880. */
  881. void DrawPlayScreen (void)
  882. {
  883. int i,j,p,m;
  884. screenpage = 0;
  885. bufferofs = 0;
  886. VW_Bar (0,0,320,STATUSLINES,0);
  887. for (i=0;i<3;i++)
  888. {
  889. bufferofs = screenloc[i];
  890. VW_Bar (0,0,320,VIEWHEIGHT,0);
  891. }
  892. splitscreen = true;
  893. VW_SetSplitScreen(120);
  894. VW_SetScreen(screenloc[0],0);
  895. CA_CacheGrChunk (STATUSPIC);
  896. bufferofs = 0;
  897. VW_DrawPic (0,0,STATUSPIC);
  898. grneeded[STATUSPIC] &= ~ca_levelbit;
  899. MM_SetPurge(&grsegs[STATUSPIC],3);
  900. // RedrawStatusWindow ();
  901. bufferofs = displayofs = screenloc[0];
  902. }
  903. //==========================================================================
  904. /*
  905. ===================
  906. =
  907. = LoadLatchMem
  908. =
  909. ===================
  910. */
  911. unsigned latchmemavail;
  912. void LoadLatchMem (void)
  913. {
  914. static unsigned base_destoff=0;
  915. static int base_numpics=0;
  916. int i,j,p,m,numpics;
  917. byte far *src, far *dest;
  918. unsigned destoff;
  919. EGAWRITEMODE(0);
  920. //
  921. // draw some pics into latch memory
  922. //
  923. if (!base_numpics)
  924. {
  925. //
  926. // tile 8s
  927. //
  928. latchpics[0] = freelatch;
  929. src = (byte _seg *)grsegs[STARTTILE8];
  930. dest = MK_FP(0xa000,freelatch);
  931. for (i=0;i<NUMTILE8;i++)
  932. {
  933. for (p=0;p<4;p++)
  934. {
  935. m = 1<<p;
  936. asm mov dx,SC_INDEX
  937. asm mov al,SC_MAPMASK
  938. asm mov ah,[BYTE PTR m]
  939. asm out dx,ax
  940. for (j=0;j<8;j++)
  941. *(dest+j)=*src++;
  942. }
  943. dest+=8;
  944. }
  945. //
  946. // tile 16s
  947. //
  948. src = (byte _seg *)grsegs[STARTTILE16];
  949. for (i=0;i<NUMTILE16;i++)
  950. {
  951. CA_CacheGrChunk (STARTTILE16+i);
  952. src = (byte _seg *)grsegs[STARTTILE16+i];
  953. if (src)
  954. {
  955. tileoffsets[i] = FP_OFF(dest);
  956. for (p=0;p<4;p++)
  957. {
  958. m = 1<<p;
  959. asm mov dx,SC_INDEX
  960. asm mov al,SC_MAPMASK
  961. asm mov ah,[BYTE PTR m]
  962. asm out dx,ax
  963. for (j=0;j<32;j++)
  964. *(dest+j)=*src++;
  965. }
  966. dest+=32;
  967. MM_FreePtr (&grsegs[STARTTILE16+i]);
  968. UNMARKGRCHUNK(STARTTILE16+i);
  969. }
  970. else
  971. tileoffsets[i] = 0;
  972. }
  973. //
  974. // pics
  975. //
  976. numpics=1;
  977. destoff = FP_OFF(dest);
  978. for (i=FIRSTLATCHPIC+1;i<FIRSTGROUNDPIC;i++)
  979. {
  980. latchpics[numpics++] = destoff;
  981. CA_CacheGrChunk (i);
  982. j = pictable[i-STARTPICS].width * pictable[i-STARTPICS].height;
  983. VW_MemToScreen (grsegs[i],destoff,j,1);
  984. destoff+=j;
  985. MM_FreePtr (&grsegs[i]);
  986. UNMARKGRCHUNK(i);
  987. }
  988. base_numpics = numpics;
  989. base_destoff = destoff;
  990. }
  991. numpics = base_numpics;
  992. destoff = base_destoff;
  993. #if USE_STRIPS
  994. //
  995. // ground pics
  996. //
  997. numpics++;
  998. for (i=FIRSTGROUNDPIC+1;i<FIRSTSTRIPPIC;i++)
  999. {
  1000. int shape = (*groundcolor & 0xf0) - 16;
  1001. // Is current shape needed?
  1002. //
  1003. if (shape != (i-(FIRSTGROUNDPIC+1)))
  1004. {
  1005. numpics++;
  1006. continue;
  1007. }
  1008. latchpics[numpics++] = destoff;
  1009. CA_CacheGrChunk (i);
  1010. j = pictable[i-STARTPICS].width * pictable[i-STARTPICS].height;
  1011. VW_MemToScreen (grsegs[i],destoff,j,1);
  1012. destoff+=j;
  1013. MM_FreePtr (&grsegs[i]);
  1014. UNMARKGRCHUNK(i);
  1015. }
  1016. //
  1017. // 'parallax' strips - used in place of a sky color
  1018. //
  1019. // Under current setup, each strip takes about 7k in latch memory.
  1020. // To create 2 pixel scrolling, 4 strips are needed, that's 28k of
  1021. // latch memory needed to produce this effect.
  1022. //
  1023. numpics++;
  1024. for (i=FIRSTSTRIPPIC+1;i<FIRSTSCALEPIC;i++)
  1025. {
  1026. memptr work;
  1027. unsigned workdest,stripsize,planesize;
  1028. short loop,pic=i-STARTPICS;
  1029. int shape = (*skycolor & 0xf0) - 16;
  1030. // Is current shape needed?
  1031. //
  1032. if (shape != (i-(FIRSTSTRIPPIC+1)))
  1033. {
  1034. numpics++;
  1035. continue;
  1036. }
  1037. // CAL_ShiftSprite() works with the SRC and DST in the same
  1038. // segment. So we must allocate memory for two strips, and
  1039. // move the base strip into that segment. Then we can use the
  1040. // 2nd half of that memory for each shifted strip.
  1041. //
  1042. CA_CacheGrChunk (i);
  1043. planesize = (pictable[pic].width+1) * pictable[pic].height;
  1044. stripsize = planesize * 4;
  1045. // MM_GetPtr(&work,(stripsize*2)+0000);
  1046. MM_GetPtr(&work,65536);
  1047. movedata((unsigned)grsegs[i],0,(unsigned)work,0,stripsize);
  1048. workdest = 32768; //(stripsize+15) & 0xFFF0;
  1049. // Free base strip
  1050. //
  1051. MM_FreePtr (&grsegs[i]);
  1052. UNMARKGRCHUNK(i);
  1053. // Create three shifted strips and move 'em to latch!
  1054. //
  1055. for (loop=3; loop; loop--)
  1056. {
  1057. // Produce current shift for this strip
  1058. //
  1059. latchpics[numpics++] = destoff;
  1060. CAL_ShiftSprite ((unsigned)work,0,workdest,pictable[pic].width,
  1061. pictable[pic].height,loop*2,false);
  1062. // Copy this shift to latch memory
  1063. //
  1064. VW_MemToScreen ((memptr)((unsigned)work+(workdest>>4)),destoff,planesize,1);
  1065. destoff+=planesize;
  1066. }
  1067. // Copy unshifted strip to latch
  1068. //
  1069. latchpics[numpics++] = destoff;
  1070. planesize = pictable[pic].width * pictable[pic].height;
  1071. VW_MemToScreen (work,destoff,planesize,1);
  1072. destoff+=planesize;
  1073. // Free work buffer
  1074. //
  1075. MM_FreePtr(&work);
  1076. }
  1077. #endif
  1078. // Keep track of how much latch memory we have...
  1079. //
  1080. latchmemavail = 65535-destoff;
  1081. EGAMAPMASK(15);
  1082. }
  1083. //==========================================================================
  1084. /*
  1085. ===================
  1086. =
  1087. = FizzleOut
  1088. =
  1089. ===================
  1090. */
  1091. void FizzleOut (int showlevel)
  1092. {
  1093. unsigned page1,page2;
  1094. //
  1095. // fizzle fade screen to grey
  1096. //
  1097. bufferofs = screenloc[(screenpage+1)%3];
  1098. if (showlevel)
  1099. DrawEnterScreen ();
  1100. FizzleFade(bufferofs,displayofs,VIEWWIDTH,VIEWHEIGHT,false);
  1101. }
  1102. //==========================================================================
  1103. /*
  1104. ====================
  1105. =
  1106. = FreeUpMemory
  1107. =
  1108. ====================
  1109. */
  1110. void FreeUpMemory (void)
  1111. {
  1112. int i;
  1113. for (i=0;i<NUMSCALEPICS;i++)
  1114. if (shapedirectory[i])
  1115. MM_SetPurge (&(memptr)shapedirectory[i],3);
  1116. for (i=0;i<NUMSCALEWALLS;i++)
  1117. if (walldirectory[i])
  1118. MM_SetPurge (&(memptr)walldirectory[i],3);
  1119. }
  1120. //==========================================================================
  1121. #if 0
  1122. /*
  1123. ==================
  1124. =
  1125. = DrawHighScores
  1126. =
  1127. ==================
  1128. */
  1129. void DrawHighScores(void)
  1130. {
  1131. char buffer[16],*str;
  1132. word i,j,
  1133. w,h,
  1134. x,y;
  1135. HighScore *s;
  1136. CA_CacheGrChunk (HIGHSCORESPIC);
  1137. VWB_DrawPic (0,0,HIGHSCORESPIC);
  1138. MM_SetPurge (&grsegs[HIGHSCORESPIC],3);
  1139. UNMARKGRCHUNK(HIGHSCORESPIC);
  1140. for (i = 0,s = Scores;i < MaxScores;i++,s++)
  1141. {
  1142. PrintY = 68 + (16 * i);
  1143. //
  1144. // name
  1145. //
  1146. PrintX = 60;
  1147. US_Print(s->name);
  1148. //
  1149. // level
  1150. //
  1151. ultoa(s->completed,buffer,10);
  1152. for (str = buffer;*str;str++)
  1153. *str = *str + (129 - '0'); // Used fixed-width numbers (129...)
  1154. USL_MeasureString(buffer,&w,&h);
  1155. PrintX = (25 * 8) - 8 - w;
  1156. US_Print(buffer);
  1157. //
  1158. // score
  1159. //
  1160. ultoa(s->score,buffer,10);
  1161. for (str = buffer;*str;str++)
  1162. *str = *str + (129 - '0'); // Used fixed-width numbers (129...)
  1163. USL_MeasureString(buffer,&w,&h);
  1164. PrintX = (34 * 8) - 8 - w;
  1165. US_Print(buffer);
  1166. }
  1167. fontcolor = F_BLACK;
  1168. }
  1169. /*
  1170. =======================
  1171. =
  1172. = CheckHighScore
  1173. =
  1174. =======================
  1175. */
  1176. void CheckHighScore (long score,word other)
  1177. {
  1178. word i,j;
  1179. int n;
  1180. HighScore myscore;
  1181. strcpy(myscore.name,"");
  1182. myscore.score = score;
  1183. myscore.completed = other;
  1184. for (i = 0,n = -1;i < MaxScores;i++)
  1185. {
  1186. if
  1187. (
  1188. (myscore.score > Scores[i].score)
  1189. || (
  1190. (myscore.score == Scores[i].score)
  1191. && (myscore.completed > Scores[i].completed)
  1192. )
  1193. )
  1194. {
  1195. for (j = MaxScores;--j > i;)
  1196. Scores[j] = Scores[j - 1];
  1197. Scores[i] = myscore;
  1198. n = i;
  1199. HighScoresDirty = true;
  1200. break;
  1201. }
  1202. }
  1203. if (n != -1)
  1204. {
  1205. //
  1206. // got a high score
  1207. //
  1208. DrawHighScores ();
  1209. PrintY = 68 + (16 * n);
  1210. PrintX = 60;
  1211. US_LineInput(PrintX,PrintY,Scores[n].name,nil,true,MaxHighName,100);
  1212. }
  1213. }
  1214. #endif
  1215. //==========================================================================
  1216. /*
  1217. ===================
  1218. =
  1219. = GameLoop
  1220. =
  1221. ===================
  1222. */
  1223. void GameLoop (void)
  1224. {
  1225. boolean wait = false;
  1226. int i,xl,yl,xh,yh;
  1227. char num[20];
  1228. #ifdef PROFILE
  1229. clock_t start,end;
  1230. #endif
  1231. DrawPlayScreen ();
  1232. IN_ClearKeysDown();
  1233. restart:
  1234. if (!loadedgame)
  1235. {
  1236. gamestate.difficulty = restartgame;
  1237. restartgame = gd_Continue;
  1238. DrawEnterScreen ();
  1239. if (gamestate.mapon != 8)
  1240. fizzlein = true;
  1241. wait = true;
  1242. }
  1243. do
  1244. {
  1245. playstate = gd_Continue;
  1246. if (!loadedgame)
  1247. SetupGameLevel ();
  1248. else
  1249. loadedgame = false;
  1250. FreeUpMemory();
  1251. LoadLatchMem();
  1252. CacheScaleds ();
  1253. if (EASYMODEON)
  1254. DisplaySMsg("*** NOVICE ***", NULL);
  1255. else
  1256. DisplaySMsg("*** WARRIOR ***", NULL);
  1257. status_delay = 250;
  1258. RedrawStatusWindow();
  1259. if (wait)
  1260. {
  1261. VW_WaitVBL(120);
  1262. wait = false;
  1263. }
  1264. #ifdef PROFILE
  1265. start = clock();
  1266. while (start == clock());
  1267. start++;
  1268. #endif
  1269. PlayLoop ();
  1270. #ifdef PROFILE
  1271. end = clock();
  1272. itoa(end-start,str,10);
  1273. Quit (str);
  1274. #endif
  1275. switch (playstate)
  1276. {
  1277. case ex_abort:
  1278. FreeUpMemory ();
  1279. return;
  1280. case ex_resetgame:
  1281. NewGame();
  1282. case ex_loadedgame:
  1283. case ex_warped:
  1284. FreeUpMemory();
  1285. if (playstate != ex_resetgame)
  1286. DisplayMsg(" ", NULL);
  1287. DisplaySMsg(" ", NULL);
  1288. goto restart;
  1289. case ex_victorious:
  1290. screenpage = 0;
  1291. bufferofs = 0;
  1292. status_flag = 0;
  1293. return;
  1294. }
  1295. } while (1);
  1296. }
  1297. #if 0
  1298. //
  1299. // make wall pictures purgable
  1300. //
  1301. for (i=0;i<NUMSCALEWALLS;i++)
  1302. if (walldirectory[i])
  1303. MM_SetPurge (&(memptr)walldirectory[i],3);
  1304. //
  1305. // cache wall pictures back in
  1306. //
  1307. for (i=1;i<NUMFLOORS;i++)
  1308. if (tileneeded[i])
  1309. {
  1310. SetupScaleWall (walllight1[i]);
  1311. SetupScaleWall (walllight2[i]);
  1312. SetupScaleWall (walldark1[i]);
  1313. SetupScaleWall (walldark2[i]);
  1314. }
  1315. #endif