1 /* Catacomb Apocalypse 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 EYESTALKLUMP 0
\r
46 #define POTIONLUMP 4
\r
56 #define CHESTLUMP 14
\r
57 #define PLAYERLUMP 15
\r
58 #define FTIMELUMP 16
\r
59 #define PORTALLUMP 17
\r
60 #define COLUMN1LUMP 18
\r
61 #define FIREPOTLUMP 19
\r
62 #define COLUMN2LUMP 20
\r
64 #define FUTUREMAGELUMP 22
\r
65 #define FORCEFIELDLUMP 23
\r
66 #define ROBOTANKLUMP 24
\r
67 #define RAMBONELUMP 25
\r
68 #define STOMPYLUMP 26
\r
69 #define TROLLLUMP 27
\r
70 #define WIZARDLUMP 28
\r
72 #define INVISDUDELUMP 30
\r
74 #define CYBORGLUMP 32
\r
75 #define WATERCHESTLUMP 33
\r
78 #define COLUMN3LUMP 36
\r
79 #define OLDCHESTLUMP 37
\r
80 #define OLDFIREPOTLUMP 38
\r
81 #define COLUMN4LUMP 39
\r
82 #define TOMB1LUMP 40
\r
83 #define TOMB2LUMP 41
\r
84 #define DEMONLUMP 42
\r
85 #define COLUMN5LUMP 43
\r
87 int lumpstart[NUMLUMPS] = {
\r
88 EYESTALK_LUMP_START,
\r
106 COLUMN1_LUMP_START,
\r
107 FFIREPOT_LUMP_START,
\r
108 COLUMN2_LUMP_START,
\r
110 FUTUREMAGE_LUMP_START,
\r
111 FORCEFIELD_LUMP_START,
\r
112 ROBOTANK_LUMP_START,
\r
113 RAMBONE_LUMP_START,
\r
118 INVISDUDE_LUMP_START,
\r
121 O_WATER_CHEST_LUMP_START,
\r
124 COLUMN3_LUMP_START,
\r
125 OLD_CHEST_LUMP_START,
\r
126 OFIREPOT_LUMP_START,
\r
127 COLUMN4_LUMP_START,
\r
131 COLUMN5_LUMP_START,
\r
135 int lumpend[NUMLUMPS] = {
\r
158 FUTUREMAGE_LUMP_END,
\r
159 FORCEFIELD_LUMP_END,
\r
166 INVISDUDE_LUMP_END,
\r
169 O_WATER_CHEST_LUMP_END,
\r
173 OLD_CHEST_LUMP_END,
\r
185 =============================================================================
\r
189 =============================================================================
\r
192 unsigned latchpics[NUMLATCHPICS];
\r
193 unsigned tileoffsets[NUMTILE16];
\r
194 unsigned textstarts[27];
\r
196 boolean splitscreen=false;
\r
198 =============================================================================
\r
202 =============================================================================
\r
205 boolean lumpneeded[NUMLUMPS];
\r
208 //===========================================================================
\r
213 ==========================
\r
217 = Spawn all actors and mark down special places
\r
219 ==========================
\r
222 void ScanInfoPlane (void)
\r
224 unsigned char hibyte;
\r
227 unsigned far *start;
\r
229 InitObjList(); // start spawning things with a clean slate
\r
231 scolor = gcolor = 0;
\r
232 skycolor = &scolor;
\r
233 groundcolor = &gcolor;
\r
236 memset (lumpneeded,0,sizeof(lumpneeded));
\r
238 start = mapsegs[2];
\r
239 for (y=0;y<mapheight;y++)
\r
240 for (x=0;x<mapwidth;x++)
\r
243 hibyte = tile >> 8;
\r
251 wall_anim_time = tile;
\r
255 case 0xfa: // sky/ground color
\r
262 case 0xfa: // sky / ground color
\r
263 scolor = ((hi)|(hi<<8));
\r
264 gcolor = ((tile)|(tile<<8));
\r
265 skycolor = &scolor;
\r
266 groundcolor = &gcolor;
\r
273 if ((!tile) || (hibyte))
\r
282 lumpneeded[PLAYERLUMP] = true;
\r
283 SpawnPlayer(x,y,NORTH+tile-1);
\r
293 lumpneeded[tile-5+BOLTLUMP] = true;
\r
294 SpawnBonus(x,y,tile-5);
\r
298 lumpneeded[EYESTALKLUMP] = true;
\r
299 SpawnAquaMan(x, y);
\r
304 lumpneeded[BLOBLUMP] = true;
\r
310 lumpneeded[BUGLUMP] = true;
\r
315 lumpneeded[CYBORGLUMP] = true;
\r
316 SpawnCyborgDemon(x, y);
\r
320 lumpneeded[EYELUMP] = true;
\r
321 SpawnShooterEye(x, y);
\r
325 lumpneeded[FUTUREMAGELUMP] = true;
\r
326 SpawnFutureMage(x, y);
\r
330 lumpneeded[INVISDUDELUMP] = true;
\r
331 SpawnInvisDude(x, y);
\r
335 lumpneeded[ROBOTANKLUMP] = true;
\r
336 SpawnRoboTank(x, y);
\r
340 lumpneeded[RAMBONELUMP] = true;
\r
341 SpawnRamBone(x, y);
\r
345 lumpneeded[STOMPYLUMP] = true;
\r
350 lumpneeded[TROLLLUMP] = true;
\r
355 lumpneeded[WIZARDLUMP] = true;
\r
360 SpawnBounce(x, y, 0);
\r
364 SpawnBounce(x, y, 1);
\r
368 lumpneeded[RKEYLUMP] = lumpneeded[GRELLUMP] = true;
\r
369 SpawnGrelminar (x,y);
\r
373 lumpneeded[EYELUMP] = true;
\r
374 SpawnRunningEye(x,y);
\r
378 lumpneeded[RAYLUMP] = true;
\r
383 lumpneeded[HEADLUMP] = true;
\r
384 SpawnEgyptianHead(x, y);
\r
388 lumpneeded[DEMONLUMP] = true;
\r
393 lumpneeded[COLUMN5LUMP] = true;
\r
394 SpawnMiscObjects(x, y, 9);
\r
398 SpawnInvisWallCntroller(x, y);
\r
411 lumpneeded[COLUMN1LUMP] = true;
\r
412 SpawnMiscObjects(x, y, 1);
\r
416 lumpneeded[FIREPOTLUMP] = true;
\r
417 SpawnMiscObjects(x, y, 4);
\r
421 lumpneeded[PORTALLUMP] = true;
\r
426 lumpneeded[FTIMELUMP] = true;
\r
436 lumpneeded[tile-40+RGEMLUMP] = true;
\r
437 SpawnBonus(x,y,tile-40+B_RGEM);
\r
441 lumpneeded[COLUMN2LUMP] = true;
\r
442 SpawnMiscObjects(x, y, 2);
\r
446 lumpneeded[COLUMN3LUMP] = true;
\r
447 SpawnMiscObjects(x, y, 3);
\r
451 lumpneeded[FORCEFIELDLUMP] = true;
\r
452 SpawnForceField(x, y);
\r
456 lumpneeded[OLDCHESTLUMP] = true;
\r
457 SpawnBonus(x, y, B_OLDCHEST);
\r
461 if (gcolor == 0x0101)
\r
462 lumpneeded[WATERCHESTLUMP] = true;
\r
464 lumpneeded[CHESTLUMP] = true;
\r
465 SpawnBonus(x,y,B_CHEST);
\r
469 lumpneeded[COLUMN4LUMP] = true;
\r
470 SpawnMiscObjects(x, y, 5);
\r
474 lumpneeded[OLDFIREPOTLUMP] = true;
\r
475 SpawnMiscObjects(x, y, 6);
\r
479 lumpneeded[TOMB1LUMP] = true;
\r
480 SpawnMiscObjects(x, y, 7);
\r
484 lumpneeded[TOMB2LUMP] = true;
\r
485 SpawnMiscObjects(x, y, 8);
\r
547 //==========================================================================
\r
557 void ScanText (void)
\r
562 text = (char _seg *)grsegs[LEVEL1TEXT+mapon];
\r
566 for (i=1;i<=26;i++)
\r
568 while (*text != '\n')
\r
575 textstarts[i] = FP_OFF(text);
\r
580 //==========================================================================
\r
590 static char *levelnames[] =
\r
592 "Programmers Test Map",
\r
593 "The Garden of Tears",
\r
594 "The Den of Zombies",
\r
595 "The Mausoleum Grounds",
\r
596 "The Main Floor of the Mausoleum",
\r
597 "Mike's Blastable Passage",
\r
598 "The Crypt of Nemesis the Undead",
\r
599 "The Subterranean Vault",
\r
600 "The Ancient Aqueduct",
\r
602 "The Lair of the Troll",
\r
603 "The Demon's Inferno",
\r
604 "The Battleground of the Titans",
\r
605 "The Coven of Mages",
\r
606 "The Inner Sanctum",
\r
607 "The Haunt of Nemesis",
\r
608 "The Passage to the Surface",
\r
609 "Big Jim's Domain",
\r
635 void DrawEnterScreen ()
\r
639 bufferofs = displayofs = screenloc[screenpage];
\r
640 VW_Bar(0,0,VIEWWIDTH,VIEWHEIGHT,0);
\r
642 // width = strlen(levelnames[gamestate.mapon]);
\r
643 width = strlen("A new challenge awaits you.");
\r
646 CenterWindow(width,3);
\r
647 US_CPrint("\nA new challenge awaits you.\n");
\r
648 // US_CPrint(levelnames[gamestate.mapon]);
\r
651 //==========================================================================
\r
653 boolean tileneeded[NUMFLOORS];
\r
664 void CacheScaleds (void)
\r
667 unsigned source,dest;
\r
670 CA_CacheGrChunk(LEVEL1TEXT+mapon);
\r
674 // make sure we are displaying screenpage 0
\r
678 source = screenloc[screenpage];
\r
679 dest = screenloc[0];
\r
680 VW_ScreenToScreen (source,dest,40,VIEWHEIGHT);
\r
682 VW_SetScreen (dest,0);
\r
687 // cache wall pictures
\r
689 for (i=1;i<NUMFLOORS;i++)
\r
692 SetupScaleWall (walllight1[i]);
\r
693 SetupScaleWall (walldark1[i]);
\r
697 // cache the actor pictures
\r
699 for (i=0;i<NUMLUMPS;i++)
\r
701 for (j=lumpstart[i];j<=lumpend[i];j++)
\r
704 source = screenloc[0];
\r
707 dest = screenloc[i];
\r
708 VW_ScreenToScreen (source,dest,40,VIEWHEIGHT);
\r
714 //==========================================================================
\r
725 void SetupGameLevel ()
\r
728 unsigned far *map,tile,far *spotptr,spot;
\r
729 unsigned search_tile;
\r
730 boolean exploding_walls_present = false;
\r
732 memset (tileneeded,0,sizeof(tileneeded));
\r
734 // randomize if not a demo
\r
739 US_InitRndT(false);
\r
740 gamestate.difficulty = gd_Normal;
\r
749 CA_CacheMap (gamestate.mapon);
\r
751 mapwidth = mapheaderseg[mapon]->width;
\r
752 mapheight = mapheaderseg[mapon]->height;
\r
755 // make a lookup table for the maps left edge
\r
758 for (y=0;y<mapheight;y++)
\r
760 farmapylookup[y] = spot;
\r
766 // copy the wall data to a data segment array
\r
768 memset (tilemap,0,sizeof(tilemap));
\r
769 memset (actorat,0,sizeof(actorat));
\r
771 spotptr = mapsegs[2];
\r
772 for (y=0;y<mapheight;y++)
\r
773 for (x=0;x<mapwidth;x++)
\r
777 if (((*spotptr)>>8) == EXP_WALL_CODE)
\r
779 exploding_walls_present = true;
\r
782 if (tile<NUMFLOORS)
\r
785 if (tile == WALL_SKELETON_CODE)
\r
787 tileneeded[tile+1] = tileneeded[tile+2] = true;
\r
788 tilemap[x][y] = tile;
\r
791 if ((tile == 66) || (tile == 67) || (tile == 68) || (tile == 69))
\r
793 if ((tile == 66) || (tile == 67))
\r
794 tileneeded[tile+2] = true;
\r
795 tileneeded[21] = tileneeded[tile] = true;
\r
796 tilemap[x][y] = tile;
\r
799 if (tile != INVISIBLEWALL)
\r
801 tileneeded[tile] = true;
\r
802 tilemap[x][y] = tile;
\r
803 if (ANIM_FLAGS(tile))
\r
805 search_tile = tile+(char signed)ANIM_FLAGS(tile);
\r
807 if (!tileneeded[search_tile])
\r
808 while (search_tile != tile)
\r
810 tileneeded[search_tile] = true;
\r
811 if (ANIM_FLAGS(search_tile))
\r
812 search_tile += (char signed)ANIM_FLAGS(search_tile);
\r
814 TrashProg("Unending Tile Animation!");
\r
820 (unsigned)actorat[x][y] = tile;
\r
827 // Mark any gfx chunks needed
\r
830 // CA_MarkGrChunk(NORTHICONSPR);
\r
831 // CA_CacheMarks(NULL);
\r
835 // decide which graphics are needed and spawn actors
\r
837 head_base_delay = 0; // (1*60) + random(1*60);
\r
839 _fmemset(wall_anim_pos,0,sizeof(wall_anim_pos));
\r
843 // mark which exploding walls are needed ---- the check for floor color
\r
844 // is preformed in ScanInfoPlane.
\r
847 if (exploding_walls_present)
\r
849 extern unsigned gnd_colors[];
\r
851 if (gcolor == 0x0101)
\r
852 tileneeded[WATEREXP] = tileneeded[WATEREXP+1] = tileneeded[WATEREXP+2] = true;
\r
854 tileneeded[WALLEXP] = tileneeded[WALLEXP+1] = tileneeded[WALLEXP+2] = true;
\r
860 // have the caching manager load and purge stuff to make sure all marks
\r
863 CA_LoadAllSounds ();
\r
866 //==========================================================================
\r
869 =====================
\r
873 =====================
\r
876 void LatchDrawPic (unsigned x, unsigned y, unsigned picnum)
\r
878 unsigned height, source, dest;
\r
881 wide = pictable[picnum-STARTPICS].width;
\r
882 height = pictable[picnum-STARTPICS].height;
\r
883 dest = bufferofs + ylookup[y]+x;
\r
884 source = latchpics[picnum-FIRSTLATCHPIC];
\r
889 asm mov bx,[linewidth]
\r
892 asm mov ax,[screenseg]
\r
896 asm mov si,[source]
\r
898 asm mov dx,[height] // scan lines to draw
\r
910 asm mov ds,ax // restore turbo's data segment
\r
917 //--------------------------------------------------------------------------
\r
918 // LatchDrawPicStrip() - srcoff is distance into source file (in PIXELS!)
\r
919 //--------------------------------------------------------------------------
\r
920 void LatchDrawPicStrip (unsigned x, unsigned y, unsigned picnum, unsigned srcoff)
\r
922 unsigned wide, height, source, dest, shift, srcmod;
\r
924 shift = (srcoff & 7) >> 1;
\r
926 wide = pictable[picnum-STARTPICS].width;
\r
927 srcmod = wide - linewidth + (shift != 3);
\r
928 if (wide > linewidth)
\r
930 height = pictable[picnum-STARTPICS].height;
\r
931 dest = bufferofs + ylookup[y]+x;
\r
933 picnum = ((picnum - (FIRSTSTRIPPIC+1)) >> 2) + (shift);
\r
934 source = latchpics[(FIRSTSTRIPPIC-FIRSTLATCHPIC+1)+picnum];
\r
939 asm mov bx,[linewidth]
\r
942 asm mov ax,[screenseg]
\r
946 asm mov si,[source]
\r
947 asm add si,[srcoff]
\r
949 asm mov dx,[height] // scan lines to draw
\r
956 asm add si,[srcmod]
\r
962 asm mov ds,ax // restore turbo's data segment
\r
970 //==========================================================================
\r
973 =====================
\r
977 =====================
\r
980 void Victory (boolean playsounds)
\r
982 struct Shape shape;
\r
986 SD_PlaySound (GETBOLTSND);
\r
987 SD_WaitSoundDone ();
\r
988 SD_PlaySound (GETNUKESND);
\r
989 SD_WaitSoundDone ();
\r
990 SD_PlaySound (GETPOTIONSND);
\r
991 SD_WaitSoundDone ();
\r
992 SD_PlaySound (GETKEYSND);
\r
993 SD_WaitSoundDone ();
\r
994 // SD_PlaySound (GETSCROLLSND);
\r
995 // SD_WaitSoundDone ();
\r
996 SD_PlaySound (GETPOINTSSND);
\r
1006 screenpage = bufferofs = 0;
\r
1008 CA_CacheGrChunk (FINALEPIC);
\r
1009 UNMARKGRCHUNK(FINALEPIC);
\r
1010 VW_DrawPic(0, 0, FINALEPIC);
\r
1016 //==========================================================================
\r
1020 ===================
\r
1024 ===================
\r
1029 unsigned page1,page2;
\r
1031 // fizzle fade screen to grey
\r
1034 SD_PlaySound (GAMEOVERSND);
\r
1035 bufferofs = screenloc[(screenpage+1)%3];
\r
1036 DisplayMsg("Though fallen, your Spirit ...",NULL);
\r
1037 // LatchDrawPic(0,0,DEADPIC);
\r
1038 // FizzleFade(bufferofs,displayofs,VIEWWIDTH,VIEWHEIGHT,false);
\r
1039 IN_ClearKeysDown();
\r
1040 while (!Keyboard[sc_Enter]);
\r
1042 VW_SetScreen (bufferofs,0);
\r
1043 VW_ColorBorder(0);
\r
1047 //==========================================================================
\r
1050 ===================
\r
1054 ===================
\r
1057 void NormalScreen (void)
\r
1059 VW_SetSplitScreen (200);
\r
1060 bufferofs = displayofs = SCREEN1START;
\r
1061 VW_Bar(0,0,320,200,0);
\r
1062 bufferofs = SCREEN2START;
\r
1063 VW_Bar(0,0,320,200,0);
\r
1064 VW_SetScreen (displayofs,0);
\r
1065 splitscreen = false;
\r
1068 //==========================================================================
\r
1071 ===================
\r
1075 ===================
\r
1078 void DrawPlayScreen (void)
\r
1085 VW_Bar (0,0,320,STATUSLINES,0);
\r
1088 bufferofs = screenloc[i];
\r
1089 VW_Bar (0,0,320,VIEWHEIGHT,0);
\r
1092 splitscreen = true;
\r
1093 VW_SetSplitScreen(120);
\r
1094 VW_SetScreen(screenloc[0],0);
\r
1096 CA_CacheGrChunk (STATUSPIC);
\r
1099 VW_DrawPic (0,0,STATUSPIC);
\r
1101 grneeded[STATUSPIC] &= ~ca_levelbit;
\r
1102 MM_SetPurge(&grsegs[STATUSPIC],3);
\r
1104 // RedrawStatusWindow ();
\r
1105 bufferofs = displayofs = screenloc[0];
\r
1109 //==========================================================================
\r
1112 ===================
\r
1116 ===================
\r
1119 unsigned latchmemavail;
\r
1121 void LoadLatchMem (void)
\r
1123 static unsigned base_destoff=0;
\r
1124 static int base_numpics=0;
\r
1125 int i,j,p,m,numpics;
\r
1126 byte far *src, far *dest;
\r
1132 // draw some pics into latch memory
\r
1135 if (!base_numpics)
\r
1141 latchpics[0] = freelatch;
\r
1142 src = (byte _seg *)grsegs[STARTTILE8];
\r
1143 dest = MK_FP(0xa000,freelatch);
\r
1145 for (i=0;i<NUMTILE8;i++)
\r
1150 asm mov dx,SC_INDEX
\r
1151 asm mov al,SC_MAPMASK
\r
1152 asm mov ah,[BYTE PTR m]
\r
1163 src = (byte _seg *)grsegs[STARTTILE16];
\r
1165 for (i=0;i<NUMTILE16;i++)
\r
1167 CA_CacheGrChunk (STARTTILE16+i);
\r
1168 src = (byte _seg *)grsegs[STARTTILE16+i];
\r
1171 tileoffsets[i] = FP_OFF(dest);
\r
1175 asm mov dx,SC_INDEX
\r
1176 asm mov al,SC_MAPMASK
\r
1177 asm mov ah,[BYTE PTR m]
\r
1179 for (j=0;j<32;j++)
\r
1183 MM_FreePtr (&grsegs[STARTTILE16+i]);
\r
1184 UNMARKGRCHUNK(STARTTILE16+i);
\r
1187 tileoffsets[i] = 0;
\r
1195 destoff = FP_OFF(dest);
\r
1196 for (i=FIRSTLATCHPIC+1;i<FIRSTGROUNDPIC;i++)
\r
1198 latchpics[numpics++] = destoff;
\r
1199 CA_CacheGrChunk (i);
\r
1200 j = pictable[i-STARTPICS].width * pictable[i-STARTPICS].height;
\r
1201 VW_MemToScreen (grsegs[i],destoff,j,1);
\r
1203 MM_FreePtr (&grsegs[i]);
\r
1207 base_numpics = numpics;
\r
1208 base_destoff = destoff;
\r
1212 numpics = base_numpics;
\r
1213 destoff = base_destoff;
\r
1220 for (i=FIRSTGROUNDPIC+1;i<FIRSTSTRIPPIC;i++)
\r
1222 int shape = (*groundcolor & 0xf0) - 16;
\r
1224 // Is current shape needed?
\r
1226 if (shape != (i-(FIRSTGROUNDPIC+1)))
\r
1232 latchpics[numpics++] = destoff;
\r
1233 CA_CacheGrChunk (i);
\r
1234 j = pictable[i-STARTPICS].width * pictable[i-STARTPICS].height;
\r
1235 VW_MemToScreen (grsegs[i],destoff,j,1);
\r
1237 MM_FreePtr (&grsegs[i]);
\r
1243 // 'parallax' strips - used in place of a sky color
\r
1245 // Under current setup, each strip takes about 7k in latch memory.
\r
1246 // To create 2 pixel scrolling, 4 strips are needed, that's 28k of
\r
1247 // latch memory needed to produce this effect.
\r
1250 for (i=FIRSTSTRIPPIC+1;i<FIRSTSCALEPIC;i++)
\r
1253 unsigned workdest,stripsize,planesize;
\r
1254 short loop,pic=i-STARTPICS;
\r
1255 int shape = (*skycolor & 0xf0) - 16;
\r
1257 // Is current shape needed?
\r
1259 if (shape != (i-(FIRSTSTRIPPIC+1)))
\r
1265 // CAL_ShiftSprite() works with the SRC and DST in the same
\r
1266 // segment. So we must allocate memory for two strips, and
\r
1267 // move the base strip into that segment. Then we can use the
\r
1268 // 2nd half of that memory for each shifted strip.
\r
1270 CA_CacheGrChunk (i);
\r
1271 planesize = (pictable[pic].width+1) * pictable[pic].height;
\r
1272 stripsize = planesize * 4;
\r
1273 // MM_GetPtr(&work,(stripsize*2)+0000);
\r
1274 MM_GetPtr(&work,65536);
\r
1275 movedata((unsigned)grsegs[i],0,(unsigned)work,0,stripsize);
\r
1276 workdest = 32768; //(stripsize+15) & 0xFFF0;
\r
1278 // Free base strip
\r
1280 MM_FreePtr (&grsegs[i]);
\r
1283 // Create three shifted strips and move 'em to latch!
\r
1285 for (loop=3; loop; loop--)
\r
1287 // Produce current shift for this strip
\r
1289 latchpics[numpics++] = destoff;
\r
1290 CAL_ShiftSprite ((unsigned)work,0,workdest,pictable[pic].width,
\r
1291 pictable[pic].height,loop*2,false);
\r
1293 // Copy this shift to latch memory
\r
1295 VW_MemToScreen ((memptr)((unsigned)work+(workdest>>4)),destoff,planesize,1);
\r
1296 destoff+=planesize;
\r
1299 // Copy unshifted strip to latch
\r
1301 latchpics[numpics++] = destoff;
\r
1302 planesize = pictable[pic].width * pictable[pic].height;
\r
1303 VW_MemToScreen (work,destoff,planesize,1);
\r
1304 destoff+=planesize;
\r
1306 // Free work buffer
\r
1308 MM_FreePtr(&work);
\r
1312 // Keep track of how much latch memory we have...
\r
1314 latchmemavail = 65535-destoff;
\r
1319 //==========================================================================
\r
1322 ===================
\r
1326 ===================
\r
1329 void FizzleOut (int showlevel)
\r
1331 unsigned page1,page2;
\r
1333 // fizzle fade screen to grey
\r
1335 bufferofs = screenloc[(screenpage+1)%3];
\r
1337 DrawEnterScreen ();
\r
1338 FizzleFade(bufferofs,displayofs,VIEWWIDTH,VIEWHEIGHT,false);
\r
1341 //==========================================================================
\r
1344 ====================
\r
1348 ====================
\r
1351 void FreeUpMemory (void)
\r
1355 for (i=0;i<NUMSCALEPICS;i++)
\r
1356 if (shapedirectory[i])
\r
1357 MM_SetPurge (&(memptr)shapedirectory[i],3);
\r
1359 for (i=0;i<NUMSCALEWALLS;i++)
\r
1360 if (walldirectory[i])
\r
1361 MM_SetPurge (&(memptr)walldirectory[i],3);
\r
1364 //==========================================================================
\r
1369 ==================
\r
1373 ==================
\r
1376 void DrawHighScores(void)
\r
1378 char buffer[16],*str;
\r
1385 CA_CacheGrChunk (HIGHSCORESPIC);
\r
1386 VWB_DrawPic (0,0,HIGHSCORESPIC);
\r
1387 MM_SetPurge (&grsegs[HIGHSCORESPIC],3);
\r
1388 UNMARKGRCHUNK(HIGHSCORESPIC);
\r
1390 for (i = 0,s = Scores;i < MaxScores;i++,s++)
\r
1392 PrintY = 68 + (16 * i);
\r
1398 US_Print(s->name);
\r
1403 ultoa(s->completed,buffer,10);
\r
1404 for (str = buffer;*str;str++)
\r
1405 *str = *str + (129 - '0'); // Used fixed-width numbers (129...)
\r
1406 USL_MeasureString(buffer,&w,&h);
\r
1407 PrintX = (25 * 8) - 8 - w;
\r
1413 ultoa(s->score,buffer,10);
\r
1414 for (str = buffer;*str;str++)
\r
1415 *str = *str + (129 - '0'); // Used fixed-width numbers (129...)
\r
1416 USL_MeasureString(buffer,&w,&h);
\r
1417 PrintX = (34 * 8) - 8 - w;
\r
1421 fontcolor = F_BLACK;
\r
1427 =======================
\r
1431 =======================
\r
1434 void CheckHighScore (long score,word other)
\r
1438 HighScore myscore;
\r
1440 strcpy(myscore.name,"");
\r
1441 myscore.score = score;
\r
1442 myscore.completed = other;
\r
1444 for (i = 0,n = -1;i < MaxScores;i++)
\r
1448 (myscore.score > Scores[i].score)
\r
1450 (myscore.score == Scores[i].score)
\r
1451 && (myscore.completed > Scores[i].completed)
\r
1455 for (j = MaxScores;--j > i;)
\r
1456 Scores[j] = Scores[j - 1];
\r
1457 Scores[i] = myscore;
\r
1459 HighScoresDirty = true;
\r
1467 // got a high score
\r
1469 DrawHighScores ();
\r
1470 PrintY = 68 + (16 * n);
\r
1472 US_LineInput(PrintX,PrintY,Scores[n].name,nil,true,MaxHighName,100);
\r
1479 //==========================================================================
\r
1482 ===================
\r
1486 ===================
\r
1489 void GameLoop (void)
\r
1491 boolean wait = false;
\r
1492 int i,xl,yl,xh,yh;
\r
1495 clock_t start,end;
\r
1498 DrawPlayScreen ();
\r
1499 IN_ClearKeysDown();
\r
1504 gamestate.difficulty = restartgame;
\r
1505 restartgame = gd_Continue;
\r
1506 DrawEnterScreen ();
\r
1507 if (gamestate.mapon != 8)
\r
1514 playstate = gd_Continue;
\r
1516 SetupGameLevel ();
\r
1518 loadedgame = false;
\r
1525 DisplaySMsg("*** NOVICE ***", NULL);
\r
1527 DisplaySMsg("*** WARRIOR ***", NULL);
\r
1529 status_delay = 250;
\r
1531 RedrawStatusWindow();
\r
1540 while (start == clock());
\r
1548 itoa(end-start,str,10);
\r
1553 switch (playstate)
\r
1558 case ex_resetgame:
\r
1560 case ex_loadedgame:
\r
1563 if (playstate != ex_resetgame)
\r
1564 DisplayMsg(" ", NULL);
\r
1565 DisplaySMsg(" ", NULL);
\r
1567 case ex_victorious:
\r
1581 // make wall pictures purgable
\r
1583 for (i=0;i<NUMSCALEWALLS;i++)
\r
1584 if (walldirectory[i])
\r
1585 MM_SetPurge (&(memptr)walldirectory[i],3);
\r
1589 // cache wall pictures back in
\r
1591 for (i=1;i<NUMFLOORS;i++)
\r
1592 if (tileneeded[i])
\r
1594 SetupScaleWall (walllight1[i]);
\r
1595 SetupScaleWall (walllight2[i]);
\r
1596 SetupScaleWall (walldark1[i]);
\r
1597 SetupScaleWall (walldark2[i]);
\r