1 /* Catacomb Armageddon Source Code
\r
2 * Copyright (C) 1993-2014 Flat Rock Software
\r
4 * This program is free software; you can redistribute it and/or modify
\r
5 * it under the terms of the GNU General Public License as published by
\r
6 * the Free Software Foundation; either version 2 of the License, or
\r
7 * (at your option) any later version.
\r
9 * This program is distributed in the hope that it will be useful,
\r
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
12 * GNU General Public License for more details.
\r
14 * You should have received a copy of the GNU General Public License along
\r
15 * with this program; if not, write to the Free Software Foundation, Inc.,
\r
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\r
33 =============================================================================
\r
37 =============================================================================
\r
42 #define SUCCUBUSLUMP 0
\r
43 #define FATDEMONLUMP 1
\r
46 #define POTIONLUMP 4
\r
51 //#define SCROLLLUMP 9
\r
52 #define CHESTLUMP 10
\r
53 #define PLAYERLUMP 11
\r
54 #define WALL1LUMP 12
\r
55 #define WALL2LUMP 13
\r
56 #define BDOORLUMP 14
\r
57 #define GODESSLUMP 15
\r
61 #define TOMBSTONESLUMP 19
\r
62 #define ZOMBIELUMP 20
\r
64 #define SKELETONLUMP 22
\r
70 //#define RKEY2LUMP 28
\r
71 #define DRAGONLUMP 29
\r
72 #define OBJ_WARPLUMP 30
\r
74 #define REDDEMONLUMP 32
\r
75 //#define PITLUMP 33
\r
76 #define FTIMELUMP 34
\r
77 #define WATERCHESTLUMP 35
\r
79 #define ARCH1LUMP 37
\r
80 #define BUNNYLUMP 38
\r
81 #define ANTHILLLUMP 39
\r
82 #define COLUMNLUMP 40
\r
83 #define SULPHURGASLUMP 41
\r
84 #define FIREPOTLUMP 42
\r
85 //#define WHIRLPOOLLUMP 43
\r
86 #define FOUNTAINLUMP 44
\r
87 #define FORCEFIELDLUMP 45
\r
88 #define ARCH2LUMP 46
\r
89 #define ARCH3LUMP 47
\r
90 #define ARCH4LUMP 48
\r
91 #define ARCH5LUMP 49
\r
92 #define ARCH6LUMP 50
\r
93 #define SKELHANGLUMP 51
\r
94 //#define SKELPILELUMP 52
\r
95 #define ARCH7LUMP 53
\r
96 #define ARCH8LUMP 54
\r
97 #define ARCH9LUMP 55
\r
98 #define ARCH10LUMP 56
\r
99 #define ARCH11LUMP 57
\r
100 #define ARCH12LUMP 58
\r
101 #define ARCH13LUMP 59
\r
103 int lumpstart[NUMLUMPS] = {
\r
104 SUCCUBUS_LUMP_START,
\r
105 FATDEMON_LUMP_START,
\r
114 //SCROLL_LUMP_START,
\r
117 //WALL1_LUMP_START,
\r
118 //WALL2_LUMP_START,
\r
119 //BDOOR_LUMP_START,
\r
125 TOMBSTONES_LUMP_START,
\r
128 SKELDUDE_LUMP_START,
\r
134 0, //RKEY2_LUMP_START,
\r
136 OBJ_WARP_LUMP_START,
\r
138 REDDEMON_LUMP_START,
\r
139 0, //PIT_LUMP_START,
\r
141 O_WATER_CHEST_LUMP_START,
\r
145 ANTHILL_LUMP_START,
\r
147 SULPHURGAS_LUMP_START,
\r
148 FIREPOT_LUMP_START,
\r
149 0, //WHIRLPOOL_LUMP_START,
\r
150 FOUNTAIN_LUMP_START,
\r
151 FORCEFIELD_LUMP_START,
\r
157 SKELHANG_LUMP_START,
\r
158 0, //SKELPILE_LUMP_START,
\r
169 int lumpend[NUMLUMPS] = {
\r
188 TOMBSTONES_LUMP_END,
\r
197 0, //RKEY2_LUMP_END,
\r
204 O_WATER_CHEST_LUMP_END,
\r
210 SULPHURGAS_LUMP_END,
\r
212 0, //WHIRLPOOL_LUMP_END,
\r
214 FORCEFIELD_LUMP_END,
\r
221 0, //SKELPILE_LUMP_END,
\r
232 //extern unsigned scolor,gcolor;
\r
236 =============================================================================
\r
240 =============================================================================
\r
243 unsigned latchpics[NUMLATCHPICS];
\r
244 unsigned tileoffsets[NUMTILE16];
\r
245 unsigned textstarts[27];
\r
247 boolean splitscreen=false;
\r
250 =============================================================================
\r
254 =============================================================================
\r
257 boolean lumpneeded[NUMLUMPS];
\r
260 //===========================================================================
\r
262 //==========================================================================
\r
265 // LOCAL PROTOTYPES
\r
268 //==========================================================================
\r
270 void CashPoints(void);
\r
275 ==========================
\r
279 = Spawn all actors and mark down special places
\r
281 ==========================
\r
284 void ScanInfoPlane (void)
\r
286 unsigned char hibyte;
\r
289 unsigned far *start;
\r
291 InitObjList(); // start spawning things with a clean slate
\r
293 scolor = gcolor = 0;
\r
294 skycolor = &scolor;
\r
295 groundcolor = &gcolor;
\r
298 memset (lumpneeded,0,sizeof(lumpneeded));
\r
300 start = mapsegs[2];
\r
301 for (y=0;y<mapheight;y++)
\r
302 for (x=0;x<mapwidth;x++)
\r
305 hibyte = tile >> 8;
\r
313 wall_anim_time = tile;
\r
317 case 0xfa: // sky/ground color
\r
318 case 0xf9: // sky/ground 'strip'
\r
325 case 0xfa: // sky / ground color
\r
326 scolor = ((hi)|(hi<<8));
\r
327 gcolor = ((tile)|(tile<<8));
\r
328 skycolor = &scolor;
\r
329 groundcolor = &gcolor;
\r
332 case 0xf9: // sky / ground 'strip'
\r
338 if ((!tile) || (hibyte))
\r
347 lumpneeded[PLAYERLUMP] = true;
\r
348 SpawnPlayer(x,y,NORTH+tile-1);
\r
358 lumpneeded[tile-5+BOLTLUMP] = true;
\r
359 SpawnBonus(x,y,tile-5);
\r
371 lumpneeded[SCROLLLUMP] = true;
\r
372 SpawnBonus(x,y,B_SCROLL1+tile-12);
\r
377 lumpneeded[REDDEMONLUMP] = true;
\r
378 SpawnRedDemon (x,y);
\r
383 lumpneeded[GOALLUMP] = true;
\r
384 SpawnBonus(x,y,B_GOAL);
\r
389 lumpneeded[GODESSLUMP] = true;
\r
394 lumpneeded[FATDEMONLUMP] = true;
\r
395 SpawnFatDemon (x,y);
\r
399 lumpneeded[SUCCUBUSLUMP] = true;
\r
400 SpawnSuccubus (x,y);
\r
404 lumpneeded[DRAGONLUMP] = true;
\r
409 lumpneeded[BATLUMP] = true;
\r
414 lumpneeded[EYELUMP] = true;
\r
419 lumpneeded[MAGELUMP] = true;
\r
424 lumpneeded[RKEYLUMP] = lumpneeded[GRELLUMP] = true;
\r
425 SpawnGrelminar (x,y);
\r
429 lumpneeded[ANTLUMP] = true;
\r
438 lumpneeded[OBJ_WARPLUMP] = true;
\r
439 SpawnWarp (x,y,tile-30);
\r
443 lumpneeded[ZOMBIELUMP] = true;
\r
448 lumpneeded[SKELETONLUMP] = true;
\r
449 SpawnSkeleton(x,y);
\r
453 lumpneeded[SKELETONLUMP] = true;
\r
454 SpawnWallSkeleton(x,y);
\r
458 lumpneeded[FTIMELUMP] = true;
\r
467 lumpneeded[tile-40+RGEMLUMP] = true;
\r
468 SpawnBonus(x,y,tile-40+B_RGEM);
\r
474 lumpneeded[TOMBSTONESLUMP] = true;
\r
475 SpawnTombstone(x,y,tile-45);
\r
480 lumpneeded[PITLUMP] = true;
\r
485 if (gcolor == 0x0101)
\r
486 lumpneeded[WATERCHESTLUMP] = true;
\r
488 lumpneeded[CHESTLUMP] = true;
\r
489 SpawnBonus(x,y,B_CHEST);
\r
493 lumpneeded[TREELUMP] = true;
\r
498 lumpneeded[BUNNYLUMP] = true;
\r
503 lumpneeded[ARCH1LUMP] = true;
\r
508 lumpneeded[ANTHILLLUMP] = true;
\r
513 lumpneeded[COLUMNLUMP] = true;
\r
514 SpawnMiscObjects(x,y,1); //1=column,2=sulphur hole,3=fire pot,4=fountain
\r
518 lumpneeded[SULPHURGASLUMP] = true;
\r
519 SpawnMiscObjects(x,y,2);
\r
523 lumpneeded[FIREPOTLUMP] = true;
\r
524 SpawnMiscObjects(x,y,3);
\r
528 lumpneeded[ARCH13LUMP] = true;
\r
533 lumpneeded[FOUNTAINLUMP] = true;
\r
534 SpawnMiscObjects(x,y,4);
\r
538 lumpneeded[FORCEFIELDLUMP] = true;
\r
539 SpawnForceField(x,y);
\r
543 lumpneeded[ARCH2LUMP] = true;
\r
548 lumpneeded[ARCH3LUMP] = true;
\r
553 lumpneeded[ARCH4LUMP] = true;
\r
558 lumpneeded[ARCH5LUMP] = true;
\r
563 lumpneeded[ARCH6LUMP] = true;
\r
568 lumpneeded[SKELHANGLUMP] = true;
\r
569 lumpneeded[SKELETONLUMP] = true;
\r
570 SpawnSkeletonHanging(x,y);
\r
574 lumpneeded[ARCH12LUMP] = true;
\r
579 lumpneeded[ARCH7LUMP] = true;
\r
584 lumpneeded[ARCH8LUMP] = true;
\r
589 lumpneeded[ARCH9LUMP] = true;
\r
594 lumpneeded[ARCH10LUMP] = true;
\r
599 lumpneeded[ARCH11LUMP] = true;
\r
607 //==========================================================================
\r
617 void ScanText (void)
\r
622 text = (char _seg *)grsegs[LEVEL1TEXT+mapon];
\r
626 for (i=1;i<=26;i++)
\r
628 while (*text != '\n')
\r
635 textstarts[i] = FP_OFF(text);
\r
640 //==========================================================================
\r
650 static char *levelnames[] =
\r
652 "Programmers Test Map",
\r
653 "The Garden of Tears",
\r
654 "The Den of Zombies",
\r
655 "The Mausoleum Grounds",
\r
656 "The Main Floor of the Mausoleum",
\r
657 "Mike's Blastable Passage",
\r
658 "The Crypt of Nemesis the Undead",
\r
659 "The Subterranean Vault",
\r
660 "The Ancient Aqueduct",
\r
662 "The Lair of the Troll",
\r
663 "The Demon's Inferno",
\r
664 "The Battleground of the Titans",
\r
665 "The Coven of Mages",
\r
666 "The Inner Sanctum",
\r
667 "The Haunt of Nemesis",
\r
668 "The Passage to the Surface",
\r
669 "Big Jim's Domain",
\r
695 void DrawEnterScreen (void)
\r
699 bufferofs = displayofs = screenloc[screenpage];
\r
700 VW_Bar(0,0,VIEWWIDTH,VIEWHEIGHT,0);
\r
701 // width = strlen(levelnames[gamestate.mapon]);
\r
702 width = strlen("You enter a new area ...");
\r
705 CenterWindow(width,3);
\r
706 US_CPrint("\nYou enter a new area ...\n");
\r
707 // US_CPrint(levelnames[gamestate.mapon]);
\r
710 //==========================================================================
\r
712 boolean tileneeded[NUMFLOORS];
\r
723 void CacheScaleds (void)
\r
726 unsigned source,dest;
\r
729 CA_CacheGrChunk(LEVEL1TEXT+mapon);
\r
733 // make sure we are displaying screenpage 0
\r
737 source = screenloc[screenpage];
\r
738 dest = screenloc[0];
\r
739 VW_ScreenToScreen (source,dest,40,VIEWHEIGHT);
\r
741 VW_SetScreen (dest,0);
\r
746 // cache wall pictures
\r
748 for (i=1;i<NUMFLOORS;i++)
\r
751 SetupScaleWall (walllight1[i]);
\r
752 SetupScaleWall (walldark1[i]);
\r
756 // cache the actor pictures
\r
758 for (i=0;i<NUMLUMPS;i++)
\r
760 for (j=lumpstart[i];j<=lumpend[i];j++)
\r
763 source = screenloc[0];
\r
766 dest = screenloc[i];
\r
767 VW_ScreenToScreen (source,dest,40,VIEWHEIGHT);
\r
773 //==========================================================================
\r
784 void SetupGameLevel ()
\r
787 unsigned far *map,tile,far *spotptr,spot;
\r
788 unsigned search_tile;
\r
789 boolean exploding_walls_present = false;
\r
791 memset (tileneeded,0,sizeof(tileneeded));
\r
793 // randomize if not a demo
\r
798 US_InitRndT(false);
\r
799 gamestate.difficulty = gd_Normal;
\r
808 CA_CacheMap (gamestate.mapon);
\r
810 mapwidth = mapheaderseg[mapon]->width;
\r
811 mapheight = mapheaderseg[mapon]->height;
\r
814 // make a lookup table for the maps left edge
\r
817 for (y=0;y<mapheight;y++)
\r
819 farmapylookup[y] = spot;
\r
825 // copy the wall data to a data segment array
\r
827 memset (tilemap,0,sizeof(tilemap));
\r
828 memset (actorat,0,sizeof(actorat));
\r
830 spotptr = mapsegs[2];
\r
831 for (y=0;y<mapheight;y++)
\r
832 for (x=0;x<mapwidth;x++)
\r
836 if (((*spotptr)>>8) == EXP_WALL_CODE)
\r
838 exploding_walls_present = true;
\r
841 if (tile<NUMFLOORS)
\r
844 if (tile == WALL_SKELETON_CODE)
\r
846 tileneeded[tile+1] = tileneeded[tile+2] = true;
\r
847 tilemap[x][y] = tile;
\r
850 if ((tile == 66) || (tile == 67) || (tile == 68) || (tile == 69))
\r
852 if ((tile == 66) || (tile == 67))
\r
853 tileneeded[tile+2] = true;
\r
854 tileneeded[21] = tileneeded[tile] = true;
\r
855 tilemap[x][y] = tile;
\r
858 if (tile != INVISIBLEWALL)
\r
860 tileneeded[tile] = true;
\r
861 tilemap[x][y] = tile;
\r
862 if (ANIM_FLAGS(tile))
\r
864 search_tile = tile+(char signed)ANIM_FLAGS(tile);
\r
866 if (!tileneeded[search_tile])
\r
867 while (search_tile != tile)
\r
869 tileneeded[search_tile] = true;
\r
870 if (ANIM_FLAGS(search_tile))
\r
871 search_tile += (char signed)ANIM_FLAGS(search_tile);
\r
873 TrashProg("Unending Tile Animation!");
\r
879 (unsigned)actorat[x][y] = tile;
\r
886 // Mark any gfx chunks needed
\r
889 // CA_MarkGrChunk(NORTHICONSPR);
\r
890 // CA_CacheMarks(NULL);
\r
894 // decide which graphics are needed and spawn actors
\r
896 zombie_base_delay = 0; // (1*60) + random(1*60);
\r
898 _fmemset(wall_anim_pos,0,sizeof(wall_anim_pos));
\r
902 // mark which exploding walls are needed ---- the check for floor color
\r
903 // is preformed in ScanInfoPlane.
\r
906 if (exploding_walls_present)
\r
908 extern unsigned gnd_colors[];
\r
910 if (gcolor == 0x0101)
\r
911 tileneeded[WATEREXP] = tileneeded[WATEREXP+1] = tileneeded[WATEREXP+2] = true;
\r
913 tileneeded[WALLEXP] = tileneeded[WALLEXP+1] = tileneeded[WALLEXP+2] = true;
\r
919 // have the caching manager load and purge stuff to make sure all marks
\r
922 CA_LoadAllSounds ();
\r
925 //==========================================================================
\r
928 =====================
\r
932 =====================
\r
935 void LatchDrawPic (unsigned x, unsigned y, unsigned picnum)
\r
937 unsigned height, source, dest;
\r
940 wide = pictable[picnum-STARTPICS].width;
\r
941 height = pictable[picnum-STARTPICS].height;
\r
942 dest = bufferofs + ylookup[y]+x;
\r
943 source = latchpics[picnum-FIRSTLATCHPIC];
\r
948 asm mov bx,[linewidth]
\r
951 asm mov ax,[screenseg]
\r
955 asm mov si,[source]
\r
957 asm mov dx,[height] // scan lines to draw
\r
969 asm mov ds,ax // restore turbo's data segment
\r
976 //--------------------------------------------------------------------------
\r
977 // LatchDrawPicStrip() - srcoff is distance into source file (in PIXELS!)
\r
978 //--------------------------------------------------------------------------
\r
979 void LatchDrawPicStrip (unsigned x, unsigned y, unsigned picnum, unsigned srcoff)
\r
981 unsigned wide, height, source, dest, shift, srcmod;
\r
983 shift = (srcoff & 7) >> 1;
\r
985 wide = pictable[picnum-STARTPICS].width;
\r
986 srcmod = wide - linewidth + (shift != 3);
\r
987 if (wide > linewidth)
\r
989 height = pictable[picnum-STARTPICS].height;
\r
990 dest = bufferofs + ylookup[y]+x;
\r
992 picnum = ((picnum - (FIRSTSTRIPPIC+1)) >> 2) + (shift);
\r
993 source = latchpics[(FIRSTSTRIPPIC-FIRSTLATCHPIC+1)+picnum];
\r
998 asm mov bx,[linewidth]
\r
1001 asm mov ax,[screenseg]
\r
1005 asm mov si,[source]
\r
1006 asm add si,[srcoff]
\r
1008 asm mov dx,[height] // scan lines to draw
\r
1015 asm add si,[srcmod]
\r
1021 asm mov ds,ax // restore turbo's data segment
\r
1029 //==========================================================================
\r
1032 =====================
\r
1036 =====================
\r
1039 void Victory (boolean playsounds)
\r
1041 struct Shape shape;
\r
1045 SD_PlaySound (GETBOLTSND);
\r
1046 SD_WaitSoundDone ();
\r
1047 SD_PlaySound (GETNUKESND);
\r
1048 SD_WaitSoundDone ();
\r
1049 SD_PlaySound (GETPOTIONSND);
\r
1050 SD_WaitSoundDone ();
\r
1051 SD_PlaySound (GETKEYSND);
\r
1052 SD_WaitSoundDone ();
\r
1053 SD_PlaySound (GETSCROLLSND);
\r
1054 SD_WaitSoundDone ();
\r
1055 SD_PlaySound (GETPOINTSSND);
\r
1065 screenpage = bufferofs = 0;
\r
1067 CA_CacheGrChunk (FINALEPIC);
\r
1068 UNMARKGRCHUNK(FINALEPIC);
\r
1069 VW_DrawPic(0, 0, FINALEPIC);
\r
1074 //==========================================================================
\r
1078 ===================
\r
1082 ===================
\r
1087 unsigned page1,page2;
\r
1089 // fizzle fade screen to grey
\r
1092 SD_PlaySound (GAMEOVERSND);
\r
1093 bufferofs = screenloc[(screenpage+1)%3];
\r
1094 DisplayMsg("Though fallen, your Spirit ...",NULL);
\r
1095 // LatchDrawPic(0,0,DEADPIC);
\r
1096 // FizzleFade(bufferofs,displayofs,VIEWWIDTH,VIEWHEIGHT,false);
\r
1097 IN_ClearKeysDown();
\r
1098 while (!Keyboard[sc_Enter]);
\r
1100 VW_SetScreen (bufferofs,0);
\r
1101 VW_ColorBorder(0);
\r
1105 //==========================================================================
\r
1108 ===================
\r
1112 ===================
\r
1115 void NormalScreen (void)
\r
1117 VW_SetSplitScreen (200);
\r
1118 bufferofs = displayofs = SCREEN1START;
\r
1119 VW_Bar(0,0,320,200,0);
\r
1120 bufferofs = SCREEN2START;
\r
1121 VW_Bar(0,0,320,200,0);
\r
1122 VW_SetScreen (displayofs,0);
\r
1123 splitscreen = false;
\r
1126 //==========================================================================
\r
1129 ===================
\r
1133 ===================
\r
1136 void DrawPlayScreen (void)
\r
1143 VW_Bar (0,0,320,STATUSLINES,0);
\r
1146 bufferofs = screenloc[i];
\r
1147 VW_Bar (0,0,320,VIEWHEIGHT,0);
\r
1150 splitscreen = true;
\r
1151 VW_SetSplitScreen(120);
\r
1152 VW_SetScreen(screenloc[0],0);
\r
1154 CA_CacheGrChunk (STATUSPIC);
\r
1157 VW_DrawPic (0,0,STATUSPIC);
\r
1159 grneeded[STATUSPIC] &= ~ca_levelbit;
\r
1160 MM_SetPurge(&grsegs[STATUSPIC],3);
\r
1162 RedrawStatusWindow ();
\r
1163 bufferofs = displayofs = screenloc[0];
\r
1167 //==========================================================================
\r
1170 ===================
\r
1174 ===================
\r
1177 unsigned latchmemavail;
\r
1179 void LoadLatchMem (void)
\r
1181 static unsigned base_destoff=0;
\r
1182 static int base_numpics=0;
\r
1183 int i,j,p,m,numpics;
\r
1184 byte far *src, far *dest;
\r
1190 // draw some pics into latch memory
\r
1193 if (!base_numpics)
\r
1199 latchpics[0] = freelatch;
\r
1200 src = (byte _seg *)grsegs[STARTTILE8];
\r
1201 dest = MK_FP(0xa000,freelatch);
\r
1203 for (i=0;i<NUMTILE8;i++)
\r
1208 asm mov dx,SC_INDEX
\r
1209 asm mov al,SC_MAPMASK
\r
1210 asm mov ah,[BYTE PTR m]
\r
1221 src = (byte _seg *)grsegs[STARTTILE16];
\r
1223 for (i=0;i<NUMTILE16;i++)
\r
1225 CA_CacheGrChunk (STARTTILE16+i);
\r
1226 src = (byte _seg *)grsegs[STARTTILE16+i];
\r
1229 tileoffsets[i] = FP_OFF(dest);
\r
1233 asm mov dx,SC_INDEX
\r
1234 asm mov al,SC_MAPMASK
\r
1235 asm mov ah,[BYTE PTR m]
\r
1237 for (j=0;j<32;j++)
\r
1241 MM_FreePtr (&grsegs[STARTTILE16+i]);
\r
1242 UNMARKGRCHUNK(STARTTILE16+i);
\r
1245 tileoffsets[i] = 0;
\r
1253 destoff = FP_OFF(dest);
\r
1254 for (i=FIRSTLATCHPIC+1;i<FIRSTGROUNDPIC;i++)
\r
1256 latchpics[numpics++] = destoff;
\r
1257 CA_CacheGrChunk (i);
\r
1258 j = pictable[i-STARTPICS].width * pictable[i-STARTPICS].height;
\r
1259 VW_MemToScreen (grsegs[i],destoff,j,1);
\r
1261 MM_FreePtr (&grsegs[i]);
\r
1265 base_numpics = numpics;
\r
1266 base_destoff = destoff;
\r
1270 numpics = base_numpics;
\r
1271 destoff = base_destoff;
\r
1278 for (i=FIRSTGROUNDPIC+1;i<FIRSTSTRIPPIC;i++)
\r
1280 int shape = (*groundcolor & 0xf0) - 16;
\r
1282 // Is current shape needed?
\r
1284 if (shape != (i-(FIRSTGROUNDPIC+1)))
\r
1290 latchpics[numpics++] = destoff;
\r
1291 CA_CacheGrChunk (i);
\r
1292 j = pictable[i-STARTPICS].width * pictable[i-STARTPICS].height;
\r
1293 VW_MemToScreen (grsegs[i],destoff,j,1);
\r
1295 MM_FreePtr (&grsegs[i]);
\r
1301 // 'parallax' strips - used in place of a sky color
\r
1303 // Under current setup, each strip takes about 7k in latch memory.
\r
1304 // To create 2 pixel scrolling, 4 strips are needed, that's 28k of
\r
1305 // latch memory needed to produce this effect.
\r
1308 for (i=FIRSTSTRIPPIC+1;i<FIRSTSCALEPIC;i++)
\r
1311 unsigned workdest,stripsize,planesize;
\r
1312 short loop,pic=i-STARTPICS;
\r
1313 int shape = (*skycolor & 0xf0) - 16;
\r
1315 // Is current shape needed?
\r
1317 if (shape != (i-(FIRSTSTRIPPIC+1)))
\r
1323 // CAL_ShiftSprite() works with the SRC and DST in the same
\r
1324 // segment. So we must allocate memory for two strips, and
\r
1325 // move the base strip into that segment. Then we can use the
\r
1326 // 2nd half of that memory for each shifted strip.
\r
1328 CA_CacheGrChunk (i);
\r
1329 planesize = (pictable[pic].width+1) * pictable[pic].height;
\r
1330 stripsize = planesize * 4;
\r
1331 // MM_GetPtr(&work,(stripsize*2)+0000);
\r
1332 MM_GetPtr(&work,65536);
\r
1333 movedata((unsigned)grsegs[i],0,(unsigned)work,0,stripsize);
\r
1334 workdest = 32768; //(stripsize+15) & 0xFFF0;
\r
1336 // Free base strip
\r
1338 MM_FreePtr (&grsegs[i]);
\r
1341 // Create three shifted strips and move 'em to latch!
\r
1343 for (loop=3; loop; loop--)
\r
1345 // Produce current shift for this strip
\r
1347 latchpics[numpics++] = destoff;
\r
1348 CAL_ShiftSprite ((unsigned)work,0,workdest,pictable[pic].width,
\r
1349 pictable[pic].height,loop*2,false);
\r
1351 // Copy this shift to latch memory
\r
1353 VW_MemToScreen ((memptr)((unsigned)work+(workdest>>4)),destoff,planesize,1);
\r
1354 destoff+=planesize;
\r
1357 // Copy unshifted strip to latch
\r
1359 latchpics[numpics++] = destoff;
\r
1360 planesize = pictable[pic].width * pictable[pic].height;
\r
1361 VW_MemToScreen (work,destoff,planesize,1);
\r
1362 destoff+=planesize;
\r
1364 // Free work buffer
\r
1366 MM_FreePtr(&work);
\r
1370 // Keep track of how much latch memory we have...
\r
1372 latchmemavail = 65535-destoff;
\r
1377 //==========================================================================
\r
1380 ===================
\r
1384 ===================
\r
1387 void FizzleOut (int showlevel)
\r
1389 unsigned page1,page2;
\r
1391 // fizzle fade screen to grey
\r
1393 bufferofs = screenloc[(screenpage+1)%3];
\r
1395 DrawEnterScreen ();
\r
1396 FizzleFade(bufferofs,displayofs,VIEWWIDTH,VIEWHEIGHT,false);
\r
1399 //==========================================================================
\r
1402 ====================
\r
1406 ====================
\r
1409 void FreeUpMemory (void)
\r
1413 for (i=0;i<NUMSCALEPICS;i++)
\r
1414 if (shapedirectory[i])
\r
1415 MM_SetPurge (&(memptr)shapedirectory[i],3);
\r
1417 for (i=0;i<NUMSCALEWALLS;i++)
\r
1418 if (walldirectory[i])
\r
1419 MM_SetPurge (&(memptr)walldirectory[i],3);
\r
1422 //==========================================================================
\r
1427 ==================
\r
1431 ==================
\r
1434 void DrawHighScores(void)
\r
1436 char buffer[16],*str;
\r
1443 CA_CacheGrChunk (HIGHSCORESPIC);
\r
1444 VWB_DrawPic (0,0,HIGHSCORESPIC);
\r
1445 MM_SetPurge (&grsegs[HIGHSCORESPIC],3);
\r
1446 UNMARKGRCHUNK(HIGHSCORESPIC);
\r
1448 for (i = 0,s = Scores;i < MaxScores;i++,s++)
\r
1450 PrintY = 68 + (16 * i);
\r
1456 US_Print(s->name);
\r
1461 ultoa(s->completed,buffer,10);
\r
1462 for (str = buffer;*str;str++)
\r
1463 *str = *str + (129 - '0'); // Used fixed-width numbers (129...)
\r
1464 USL_MeasureString(buffer,&w,&h);
\r
1465 PrintX = (25 * 8) - 8 - w;
\r
1471 ultoa(s->score,buffer,10);
\r
1472 for (str = buffer;*str;str++)
\r
1473 *str = *str + (129 - '0'); // Used fixed-width numbers (129...)
\r
1474 USL_MeasureString(buffer,&w,&h);
\r
1475 PrintX = (34 * 8) - 8 - w;
\r
1479 fontcolor = F_BLACK;
\r
1485 =======================
\r
1489 =======================
\r
1492 void CheckHighScore (long score,word other)
\r
1496 HighScore myscore;
\r
1498 strcpy(myscore.name,"");
\r
1499 myscore.score = score;
\r
1500 myscore.completed = other;
\r
1502 for (i = 0,n = -1;i < MaxScores;i++)
\r
1506 (myscore.score > Scores[i].score)
\r
1508 (myscore.score == Scores[i].score)
\r
1509 && (myscore.completed > Scores[i].completed)
\r
1513 for (j = MaxScores;--j > i;)
\r
1514 Scores[j] = Scores[j - 1];
\r
1515 Scores[i] = myscore;
\r
1517 HighScoresDirty = true;
\r
1525 // got a high score
\r
1527 DrawHighScores ();
\r
1528 PrintY = 68 + (16 * n);
\r
1530 US_LineInput(PrintX,PrintY,Scores[n].name,nil,true,MaxHighName,100);
\r
1537 //==========================================================================
\r
1540 ===================
\r
1544 ===================
\r
1547 void GameLoop (void)
\r
1549 boolean wait = false;
\r
1550 int i,xl,yl,xh,yh;
\r
1553 clock_t start,end;
\r
1556 DrawPlayScreen ();
\r
1557 IN_ClearKeysDown();
\r
1562 gamestate.difficulty = restartgame;
\r
1563 restartgame = gd_Continue;
\r
1564 DrawEnterScreen ();
\r
1565 if (gamestate.mapon != 8)
\r
1572 playstate = gd_Continue;
\r
1574 SetupGameLevel ();
\r
1576 loadedgame = false;
\r
1583 DisplaySMsg("*** NOVICE ***", NULL);
\r
1585 DisplaySMsg("*** WARRIOR ***", NULL);
\r
1587 status_delay = 250;
\r
1589 RedrawStatusWindow();
\r
1598 while (start == clock());
\r
1606 itoa(end-start,str,10);
\r
1611 switch (playstate)
\r
1616 case ex_resetgame:
\r
1618 case ex_loadedgame:
\r
1621 if (playstate != ex_resetgame)
\r
1622 DisplayMsg(" ", NULL);
\r
1623 DisplaySMsg(" ", NULL);
\r
1625 case ex_victorious:
\r
1639 // make wall pictures purgable
\r
1641 for (i=0;i<NUMSCALEWALLS;i++)
\r
1642 if (walldirectory[i])
\r
1643 MM_SetPurge (&(memptr)walldirectory[i],3);
\r
1647 // cache wall pictures back in
\r
1649 for (i=1;i<NUMFLOORS;i++)
\r
1650 if (tileneeded[i])
\r
1652 SetupScaleWall (walllight1[i]);
\r
1653 SetupScaleWall (walllight2[i]);
\r
1654 SetupScaleWall (walldark1[i]);
\r
1655 SetupScaleWall (walldark2[i]);
\r