--- /dev/null
+Subproject commit 374403ea47e9f6d69829c518c6ebee779b314703
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_US.c - User Manager\r
-// v1.0d1\r
-// By Jason Blochowiak\r
-//\r
-\r
-//\r
-// This module handles dealing with user input & feedback\r
-//\r
-// Depends on: Input Mgr, View Mgr, some variables from the Sound, Caching,\r
-// and Refresh Mgrs, Memory Mgr for background save/restore\r
-//\r
-// Globals:\r
-// ingame - Flag set by game indicating if a game is in progress\r
-// abortgame - Flag set if the current game should be aborted (if a load\r
-// game fails)\r
-// loadedgame - Flag set if a game was loaded\r
-// abortprogram - Normally nil, this points to a terminal error message\r
-// if the program needs to abort\r
-// restartgame - Normally set to gd_Continue, this is set to one of the\r
-// difficulty levels if a new game should be started\r
-// PrintX, PrintY - Where the User Mgr will print (global coords)\r
-// WindowX,WindowY,WindowW,WindowH - The dimensions of the current\r
-// window\r
-//\r
-\r
-// DEBUG - handle LPT3 for Sound Source\r
-\r
-#include "16_us.h"\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_CheckParm() - checks to see if a string matches one of a set of\r
-// strings. The check is case insensitive. The routine returns the\r
-// index of the string that matched, or -1 if no matches were found\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-int\r
-US_CheckParm(char *parm,char **strings)\r
-{\r
- char cp,cs,\r
- *p,*s;\r
- int i;\r
-\r
- while (!isalpha(*parm)) // Skip non-alphas\r
- parm++;\r
-\r
- for (i = 0;*strings && **strings;i++)\r
- {\r
- for (s = *strings++,p = parm,cs = cp = 0;cs == cp;)\r
- {\r
- cs = *s++;\r
- if (!cs)\r
- return(i);\r
- cp = *p++;\r
-\r
- if (isupper(cs))\r
- cs = tolower(cs);\r
- if (isupper(cp))\r
- cp = tolower(cp);\r
- }\r
- }\r
- return(-1);\r
-}\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-/////////////////////////////////////////////////\r
-//\r
-// MUSE Header for .ARM\r
-// Created Mon Jun 08 16:14:17 1992\r
-//\r
-/////////////////////////////////////////////////\r
-\r
-#define NUMSOUNDS 35\r
-#define NUMSNDCHUNKS 106\r
-\r
-//\r
-// Sound names & indexes\r
-//\r
-typedef enum {\r
- HITWALLSND, // 0\r
- WARPUPSND, // 1\r
- WARPDOWNSND, // 2\r
- GETBOLTSND, // 3\r
- GETNUKESND, // 4\r
- GETPOTIONSND, // 5\r
- GETKEYSND, // 6\r
- GETSCROLLSND, // 7\r
- GETPOINTSSND, // 8\r
- USEBOLTSND, // 9\r
- USENUKESND, // 10\r
- USEPOTIONSND, // 11\r
- USEKEYSND, // 12\r
- NOITEMSND, // 13\r
- WALK1SND, // 14\r
- WALK2SND, // 15\r
- TAKEDAMAGESND, // 16\r
- MONSTERMISSSND, // 17\r
- GAMEOVERSND, // 18\r
- SHOOTSND, // 19\r
- BIGSHOOTSND, // 20\r
- SHOOTWALLSND, // 21\r
- SHOOTMONSTERSND, // 22\r
- TAKEDMGHURTSND, // 23\r
- BALLBOUNCESND, // 24\r
- NOWAYSND, // 25\r
- WARPSND, // 26\r
- HIT_GATESND, // 27\r
- GETGEMSND, // 28\r
- BOOMSND, // 29\r
- GRELM_DEADSND, // 30\r
- FREEZETIMESND, // 31\r
- TIMERETURNSND, // 32\r
- TICKSND, // 33\r
- BODY_EXPLODESND, // 34\r
- LASTSOUND\r
- } soundnames;\r
-\r
-//\r
-// Base offsets\r
-//\r
-#define STARTPCSOUNDS 0\r
-#define STARTADLIBSOUNDS 35\r
-#define STARTDIGISOUNDS 70\r
-#define STARTMUSIC 105\r
-\r
-//\r
-// Music names & indexes\r
-//\r
-typedef enum {\r
- TOOHOT_MUS, // 0\r
- LASTMUSIC\r
- } musicnames;\r
-\r
-/////////////////////////////////////////////////\r
-//\r
-// Thanks for playing with MUSE!\r
-//\r
-/////////////////////////////////////////////////\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// C3_PLAY.C\r
-\r
-#include "DEF.H"\r
-#pragma hdrstop\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#if 0\r
-#define MSHOTDAMAGE 2\r
-#define MSHOTSPEED 10000\r
-\r
-#define ESHOTDAMAGE 1\r
-#define ESHOTSPEED 5000\r
-\r
-#define SSHOTDAMAGE 3\r
-#define SSHOTSPEED 6500\r
-\r
-#define RANDOM_ATTACK 20\r
-#endif\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-boolean ShootPlayer (objtype *ob, short obclass, short speed, statetype *state);\r
-void T_ShootPlayer(objtype *ob);\r
-\r
-short zombie_base_delay;\r
-\r
-short other_x[] = {0,39,39,0},\r
- other_y[] = {0,0,27,27};\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-dirtype dirtable[9] = {northwest,north,northeast,west,nodir,east,\r
- southwest,south,southeast};\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- BONUS ITEMS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern statetype s_boltbonus2;\r
-extern statetype s_nukebonus2;\r
-extern statetype s_boltbonus3;\r
-extern statetype s_nukebonus3;\r
-\r
-statetype s_boltbonus = {BOLTOBJPIC,8,NULL,&s_boltbonus2};\r
-statetype s_boltbonus2 = {BOLT2OBJPIC,8,NULL,&s_boltbonus3};\r
-statetype s_boltbonus3 = {BOLT3OBJPIC,8,NULL,&s_boltbonus};\r
-\r
-statetype s_nukebonus = {NUKEOBJPIC,8,NULL,&s_nukebonus2};\r
-statetype s_nukebonus2 = {NUKE2OBJPIC,8,NULL,&s_nukebonus3};\r
-statetype s_nukebonus3 = {NUKE3OBJPIC,8,NULL,&s_nukebonus};\r
-\r
-statetype s_potionbonus = {POTIONOBJPIC,0,NULL,&s_potionbonus};\r
-//statetype s_rkey2bonus = {RKEY2PIC,0,NULL,&s_rkey2bonus};\r
-statetype s_rkeybonus = {RKEYOBJPIC,0,NULL,&s_rkeybonus};\r
-statetype s_ykeybonus = {YKEYOBJPIC,0,NULL,&s_ykeybonus};\r
-statetype s_gkeybonus = {GKEYOBJPIC,0,NULL,&s_gkeybonus};\r
-statetype s_bkeybonus = {BKEYOBJPIC,0,NULL,&s_bkeybonus};\r
-//////////////////////////statetype s_scrollbonus = {SCROLLOBJPIC,0,NULL,&s_scrollbonus};\r
-statetype s_chestbonus = {CHESTOBJPIC,0,NULL,&s_chestbonus};\r
-//statetype s_goalbonus = {NEMESISPIC,0,NULL,&s_goalbonus};\r
-\r
-extern statetype s_waterchestbonus2;\r
-statetype s_waterchestbonus1 = {O_WATER_CHEST1PIC,8,NULL,&s_waterchestbonus2};\r
-statetype s_waterchestbonus2 = {O_WATER_CHEST2PIC,8,NULL,&s_waterchestbonus1};\r
-\r
-extern statetype s_rgem2bonus;\r
-extern statetype s_ygem2bonus;\r
-extern statetype s_ggem2bonus;\r
-extern statetype s_bgem2bonus;\r
-extern statetype s_pgem2bonus;\r
-\r
-statetype s_rgem1bonus = {RGEM1PIC,30,NULL,&s_rgem2bonus};\r
-statetype s_ygem1bonus = {YGEM1PIC,30,NULL,&s_ygem2bonus};\r
-statetype s_ggem1bonus = {GGEM1PIC,30,NULL,&s_ggem2bonus};\r
-statetype s_bgem1bonus = {BGEM1PIC,30,NULL,&s_bgem2bonus};\r
-statetype s_pgem1bonus = {PGEM1PIC,30,NULL,&s_pgem2bonus};\r
-\r
-statetype s_rgem2bonus = {RGEM2PIC,30,NULL,&s_rgem1bonus};\r
-statetype s_ygem2bonus = {YGEM2PIC,30,NULL,&s_ygem1bonus};\r
-statetype s_ggem2bonus = {GGEM2PIC,30,NULL,&s_ggem1bonus};\r
-statetype s_bgem2bonus = {BGEM2PIC,30,NULL,&s_bgem1bonus};\r
-statetype s_pgem2bonus = {PGEM2PIC,30,NULL,&s_pgem1bonus};\r
-\r
-statetype s_bonus_die = {0,8,NULL,NULL};\r
-\r
-/*\r
-===============\r
-=\r
-= SpawnBonus\r
-=\r
-===============\r
-*/\r
-\r
-void SpawnBonus (int tilex, int tiley, int number)\r
-{\r
- extern unsigned gcolor;\r
-\r
- statetype *state;\r
-\r
- switch (number)\r
- {\r
- case B_BOLT: state = &s_boltbonus; break;\r
- case B_NUKE: state = &s_nukebonus; break;\r
- case B_POTION: state = &s_potionbonus; break;\r
-\r
- case B_RKEY: state = &s_rkeybonus; break;\r
- case B_YKEY: state = &s_ykeybonus; break;\r
- case B_GKEY: state = &s_gkeybonus; break;\r
- case B_BKEY: state = &s_bkeybonus; break;\r
-\r
- case B_RGEM: state = &s_rgem1bonus; break;\r
- case B_YGEM: state = &s_ygem1bonus; break;\r
- case B_GGEM: state = &s_ggem1bonus; break;\r
- case B_BGEM: state = &s_bgem1bonus; break;\r
- case B_PGEM: state = &s_pgem1bonus; break;\r
-\r
- case B_CHEST:\r
- if (gcolor == 0x0101)\r
- state = &s_waterchestbonus1;\r
- else\r
- state = &s_chestbonus;\r
- break;\r
-\r
-#if 0\r
- case B_SCROLL1:\r
- case B_SCROLL2:\r
- case B_SCROLL3:\r
- case B_SCROLL4:\r
- case B_SCROLL5:\r
- case B_SCROLL6:\r
- case B_SCROLL7:\r
- case B_SCROLL8: state = &s_scrollbonus; break;\r
-#endif\r
-\r
-// case B_RKEY2: state = &s_rkey2bonus; break;\r
-\r
- default:\r
- Quit("SpawnBonus(): INVALID BONUS");\r
- break;\r
- }\r
-\r
- SpawnNewObj (tilex,tiley,state,TILEGLOBAL/2);\r
-// new->tileobject = true;\r
- new->temp1 = number;\r
- new->obclass = bonusobj;\r
-\r
- switch (number)\r
- {\r
- case B_POTION:\r
- case B_CHEST:\r
- case B_BOLT:\r
- case B_NUKE:\r
- new->flags |= of_shootable;\r
- break;\r
-\r
- default:\r
- new->flags &= ~of_shootable;\r
- break;\r
- }\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= SpawnTombstone\r
-=\r
-===============\r
-*/\r
-\r
-statetype s_tombs[3] = {{TOMB1PIC,8,NULL,&s_tombs[0]},\r
- {TOMB2PIC,8,NULL,&s_tombs[1]},\r
- {TOMB3PIC,8,NULL,&s_tombs[2]}};\r
-\r
-void SpawnTombstone (int tilex, int tiley, int shape)\r
-{\r
- statetype *state=&s_tombs[shape];\r
-\r
- SpawnNewObj (tilex,tiley,state,TILEGLOBAL/2);\r
-// new->tileobject = true;\r
- new->obclass = realsolidobj;\r
- new->flags |= of_shootable;\r
-}\r
-\r
-\r
-/*\r
-============================================================================\r
-\r
- FREEZE TIME OBJECT\r
-\r
-============================================================================\r
-*/\r
-\r
-extern statetype s_ftimebonus;\r
-extern statetype s_ftimebonus2;\r
-\r
-statetype s_ftimebonus = {TIMEOBJ1PIC,6,NULL,&s_ftimebonus2};\r
-statetype s_ftimebonus2 = {TIMEOBJ2PIC,6,NULL,&s_ftimebonus};\r
-\r
-/*\r
-===============\r
-=\r
-= SpawnFTime\r
-=\r
-===============\r
-*/\r
-void SpawnFTime(int tilex, int tiley)\r
-{\r
- SpawnNewObj(tilex,tiley,&s_ftimebonus,TILEGLOBAL/2);\r
-// new->tileobject = true;\r
- new->obclass = freezeobj;\r
- new->flags |= of_shootable;\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- EXPLODING WALL\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-void T_WallDie (objtype *ob);\r
-\r
-extern statetype s_walldie1;\r
-extern statetype s_walldie2;\r
-extern statetype s_walldie3;\r
-extern statetype s_walldie4;\r
-extern statetype s_walldie5;\r
-extern statetype s_walldie6;\r
-\r
-statetype s_walldie1 = {0,20,NULL,&s_walldie2};\r
-statetype s_walldie2 = {0,-1,T_WallDie,&s_walldie3};\r
-statetype s_walldie3 = {0,20,NULL,&s_walldie4};\r
-statetype s_walldie4 = {0,-1,T_WallDie,&s_walldie5};\r
-statetype s_walldie5 = {0,20,NULL,&s_walldie6};\r
-statetype s_walldie6 = {0,-1,T_WallDie,NULL};\r
-\r
-\r
-/*\r
-================\r
-=\r
-= ExplodeWall\r
-=\r
-================\r
-*/\r
-\r
-void ExplodeWall (int tilex, int tiley)\r
-{\r
- extern unsigned gcolor;\r
- unsigned tilenum;\r
-\r
- DSpawnNewObj (tilex,tiley,&s_walldie1,0);\r
- if (new == &dummyobj)\r
- return;\r
- new->obclass = inertobj;\r
- new->active = always;\r
- if (gcolor == 0x0101)\r
- tilenum = WATEREXP;\r
- else\r
- tilenum = WALLEXP;\r
- (unsigned)actorat[new->tilex][new->tiley] = tilemap[new->tilex][new->tiley] =\r
- *(mapsegs[0]+farmapylookup[new->tiley]+new->tilex) = tilenum;\r
- *(mapsegs[2]+farmapylookup[new->tiley]+new->tilex) &= 0xFF;\r
-}\r
-\r
-\r
-/*\r
-================\r
-=\r
-= T_WallDie\r
-=\r
-================\r
-*/\r
-\r
-void T_WallDie (objtype *ob)\r
-{\r
- extern unsigned gcolor;\r
- unsigned tile,other,spot,x,y;\r
-\r
- if (++ob->temp1 == 3)\r
- tile = 0;\r
- else\r
- if (gcolor == 0x0101)\r
- tile = WATEREXP-1 + ob->temp1;\r
- else\r
- tile = WALLEXP-1 + ob->temp1;\r
- x = ob->tilex;\r
- y = ob->tiley;\r
-\r
- (unsigned)actorat[x][y] = tilemap[x][y] = *(mapsegs[0]+farmapylookup[y]+x) = tile;\r
-\r
- if (ob->temp1 == 1)\r
- {\r
- //\r
- // blow up nearby walls\r
- //\r
- spot = (*(mapsegs[2]+farmapylookup[y]+(x-1))) >> 8;\r
- if (spot == EXP_WALL_CODE)\r
- ExplodeWall (x-1,y);\r
- spot = (*(mapsegs[2]+farmapylookup[y]+(x+1))) >> 8;\r
- if (spot == EXP_WALL_CODE)\r
- ExplodeWall (x+1,y);\r
- spot = (*(mapsegs[2]+farmapylookup[y-1]+x)) >> 8;\r
- if (spot == EXP_WALL_CODE)\r
- ExplodeWall (x,y-1);\r
- spot = (*(mapsegs[2]+farmapylookup[y+1]+x)) >> 8;\r
- if (spot == EXP_WALL_CODE)\r
- ExplodeWall (x,y+1);\r
- }\r
-}\r
-/*\r
-=============================================================================\r
-\r
- OBJ_WARP GATE\r
-\r
-=============================================================================\r
-*/\r
-\r
-void T_Gate (objtype *ob);\r
-\r
-extern statetype s_obj_gate1;\r
-extern statetype s_obj_gate2;\r
-extern statetype s_obj_gate3;\r
-extern statetype s_obj_gate4;\r
-\r
-statetype s_obj_gate1 = {OBJ_WARP1PIC,10,T_Gate,&s_obj_gate2};\r
-statetype s_obj_gate2 = {OBJ_WARP2PIC,10,T_Gate,&s_obj_gate3};\r
-statetype s_obj_gate3 = {OBJ_WARP3PIC,10,T_Gate,&s_obj_gate4};\r
-statetype s_obj_gate4 = {OBJ_WARP4PIC,10,T_Gate,&s_obj_gate1};\r
-\r
-extern statetype s_anthill;\r
-statetype s_anthill = {ANT_HILLPIC, 20, T_Gate, &s_anthill};\r
-\r
-//---------------------------------------------------------------------------\r
-// SpawnWarp()\r
-//\r
-// TYPE : Type param is the gate number (1-what ever) will link you to\r
-// gate of that type.\r
-//---------------------------------------------------------------------------\r
-void SpawnWarp (int tilex, int tiley, int type)\r
-{\r
-\r
- if (type)\r
- SpawnNewObj (tilex,tiley,&s_obj_gate1,TILEGLOBAL/3);\r
- else\r
- SpawnNewObj (tilex,tiley,&s_anthill,TILEGLOBAL/3);\r
- new->obclass = gateobj;\r
- new->temp1 = type;\r
-}\r
-\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= T_Gate\r
-=\r
-===============\r
-*/\r
-\r
-#define STATUSCOLOR 4\r
-\r
-void T_Gate (objtype *ob)\r
-{\r
- objtype *check;\r
- unsigned temp,spot;\r
-\r
- if (CheckHandAttack (ob) && !playstate)\r
- {\r
- // make\r
- //\r
-// spot = (*(mapsegs[2]+farmapylookup[ob->tiley+1]+ob->tilex)) >> 8;\r
-// if (spot--)\r
-// if (gamestate.keys[spot])\r
-// TakeKey(spot);\r
-// else\r
-// return;\r
-\r
- //\r
- // warp\r
- //\r
-\r
-// temp = bufferofs;\r
-// bufferofs = 0;\r
-// VW_Bar (26,4,232,9,STATUSCOLOR); // clear text description\r
-// bufferofs = temp;\r
-\r
-// IN_ClearKeysDown ();\r
- if (ob->temp1)\r
- {\r
- //\r
- // teleport inside level\r
- //\r
-\r
- for (check=player->next;check;check=check->next)\r
- if (check->obclass==gateobj && check->temp1==ob->temp1 &&\r
- check != ob)\r
- {\r
- player->x = check->x;\r
- player->y = check->y;\r
- Thrust (player->angle,TILEGLOBAL/2); // move forwards\r
- Thrust (player->angle,TILEGLOBAL/2); // move forwards\r
- Thrust (player->angle,TILEGLOBAL/2); // move forwards\r
- fizzlein=true;\r
- SD_PlaySound(WARPSND);\r
- }\r
- }\r
- else\r
- {\r
- //\r
- // teleport out of level\r
- //\r
-\r
- playstate = ex_warped;\r
- spot = (*(mapsegs[2]+farmapylookup[ob->tiley+1]+ob->tilex)) >> 8;\r
- gamestate.mapon=spot;\r
- SD_PlaySound(WARPUPSND);\r
- }\r
- }\r
-}\r
-\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- FAT DEMON\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define FATCLOUDDAMAGE 2\r
-\r
-void T_FatDemon (objtype *ob);\r
-void T_CheckCnt(objtype *ob);\r
-void ExplodeSound(objtype *ob);\r
-\r
-extern statetype s_fatdemon_pause;\r
-extern statetype s_fatdemon_walk1;\r
-extern statetype s_fatdemon_walk2;\r
-extern statetype s_fatdemon_walk3;\r
-extern statetype s_fatdemon_walk4;\r
-extern statetype s_fatdemon_attack1;\r
-extern statetype s_fatdemon_attack2;\r
-extern statetype s_fatdemon_blowup2;\r
-extern statetype s_fatdemon_blowup3;\r
-extern statetype s_fatdemon_blowup4;\r
-extern statetype s_fatdemon_blowup5;\r
-extern statetype s_fatdemon_blowup6;\r
-extern statetype s_fatdemon_blowup7;\r
-extern statetype s_fatdemon_explode;\r
-extern statetype s_fatdemon_feet;\r
-\r
-statetype s_fatdemon_pause = {FATDEMON_WALK1PIC,40,NULL,&s_fatdemon_walk2};\r
-\r
-statetype s_fatdemon_walk1 = {FATDEMON_WALK1PIC,13,T_FatDemon,&s_fatdemon_walk2};\r
-statetype s_fatdemon_walk2 = {FATDEMON_WALK2PIC,13,T_FatDemon,&s_fatdemon_walk3};\r
-statetype s_fatdemon_walk3 = {FATDEMON_WALK3PIC,13,T_FatDemon,&s_fatdemon_walk4};\r
-statetype s_fatdemon_walk4 = {FATDEMON_WALK4PIC,13,T_FatDemon,&s_fatdemon_walk1};\r
-\r
-statetype s_fatdemon_attack1 = {FATDEMON_ATTACK1PIC,20,NULL,&s_fatdemon_attack2};\r
-statetype s_fatdemon_attack2 = {FATDEMON_ATTACK2PIC,20,T_DoDamage,&s_fatdemon_pause};\r
-\r
-statetype s_fatdemon_ouch = {FATDEMON_OUCHPIC,14,NULL,&s_fatdemon_walk1};\r
-\r
-statetype s_fatdemon_blowup1 = {FATDEMON_BLOWUP1PIC,25,NULL,&s_fatdemon_blowup2};\r
-statetype s_fatdemon_blowup2 = {FATDEMON_BLOWUP2PIC,25,NULL,&s_fatdemon_blowup3};\r
-statetype s_fatdemon_blowup3 = {FATDEMON_BLOWUP1PIC,15,NULL,&s_fatdemon_blowup4};\r
-statetype s_fatdemon_blowup4 = {FATDEMON_BLOWUP2PIC,15,NULL,&s_fatdemon_blowup5};\r
-statetype s_fatdemon_blowup5 = {FATDEMON_BLOWUP1PIC,6,NULL,&s_fatdemon_blowup6};\r
-statetype s_fatdemon_blowup6 = {FATDEMON_BLOWUP2PIC,6,T_CheckCnt,&s_fatdemon_blowup5};\r
-statetype s_fatdemon_blowup7 = {FATDEMON_BLOWUP3PIC,30,NULL,&s_fatdemon_explode};\r
-\r
-\r
-statetype s_fatdemon_explode = {FATDEMON_EXPLODEPIC,40,ExplodeSound,&s_fatdemon_feet};\r
-statetype s_fatdemon_feet = {FATDEMON_FEETPIC,30,NULL,&s_fatdemon_feet};\r
-\r
-#define cnt ob->temp1\r
-#define cloud_delay ob->temp2\r
-\r
-/*\r
-===============\r
-=\r
-= SpawnFatDemon\r
-=\r
-===============\r
-*/\r
-\r
-void SpawnFatDemon (int tilex, int tiley)\r
-{\r
- SpawnNewObj(tilex,tiley,&s_fatdemon_walk1,35*PIXRADIUS);\r
- new->speed = 2500;\r
- new->obclass = fatdemonobj;\r
- new->flags |= of_shootable;\r
- new->hitpoints = EasyHitPoints(10);\r
- new->temp1 = 25; //used to "shake" the fat dude??????\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= T_FatDemon\r
-=\r
-===============\r
-*/\r
-\r
-void T_FatDemon (objtype *ob)\r
-{\r
- if (Chase(ob,true) || (random(1000)<RANDOM_ATTACK))\r
- {\r
- ob->state = &s_fatdemon_attack1;\r
- ob->ticcount = ob->state->tictime;\r
- return;\r
- }\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= T_DecCnt\r
-=\r
-===============\r
-*/\r
-\r
-void T_CheckCnt (objtype *ob)\r
-{\r
- ob->temp1--;\r
- if (!ob->temp1)\r
- {\r
- ob->state = &s_fatdemon_blowup7;\r
- ob->ticcount = ob->state->tictime;\r
- }\r
-}\r
-\r
-/*\r
-===============\r
-=\r
-= ExplodeSound\r
-=\r
-===============\r
-*/\r
-void ExplodeSound(objtype *ob)\r
-{\r
- if (ob->temp1 != 666) // Has this think been called already?\r
- {\r
- SD_PlaySound(BODY_EXPLODESND);\r
- ob->temp1 = 666; // Has now!\r
- }\r
-}\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- WATER DRAGON\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern statetype s_dragon_shot1;\r
-extern statetype s_dragon_shot2;\r
-\r
-\r
-void T_Dragon(objtype *ob);\r
-void T_DragonShoot(objtype *ob);\r
-\r
-\r
-statetype s_wet_bubbles1 = {DRAGON_BUBBLES1PIC,13,T_Dragon,&s_wet_bubbles2};\r
-statetype s_wet_bubbles2 = {DRAGON_BUBBLES2PIC,15,T_Dragon,&s_wet_bubbles1};\r
-statetype s_wet_bubbles3 = {0,35,T_Dragon,&s_wet_bubbles1};\r
-\r
-statetype s_wet_peek = {DRAGON_EYESPIC,45,NULL,&s_wet_bubbles1};\r
-\r
-statetype s_wet_rise1 = {DRAGON_BUBBLES2PIC,15,NULL,&s_wet_rise3};\r
-statetype s_wet_rise3 = {DRAGON_EYESPIC,20,NULL,&s_wet_rise4};\r
-statetype s_wet_rise4 = {DRAGON_RISE1PIC,20,NULL,&s_wet_rise5};\r
-statetype s_wet_rise5 = {DRAGON_RISE2PIC,20,NULL,&s_wet_walk1};\r
-\r
-statetype s_wet_sink1 = {DRAGON_RISE2PIC,20,NULL,&s_wet_sink2};\r
-statetype s_wet_sink2 = {DRAGON_RISE1PIC,20,NULL,&s_wet_sink3};\r
-statetype s_wet_sink3 = {DRAGON_EYESPIC,20,NULL,&s_wet_bubbles1};\r
-\r
-statetype s_wet_walk1 = {DRAGON_WALK1PIC,12,T_Dragon,&s_wet_walk2};\r
-statetype s_wet_walk2 = {DRAGON_WALK2PIC,12,T_Dragon,&s_wet_walk3};\r
-statetype s_wet_walk3 = {DRAGON_WALK3PIC,12,T_Dragon,&s_wet_walk4};\r
-statetype s_wet_walk4 = {DRAGON_WALK4PIC,12,T_Dragon,&s_wet_walk1};\r
-\r
-statetype s_wet_attack1 = {DRAGON_ATTACK1PIC,10,NULL,&s_wet_attack2};\r
-statetype s_wet_attack2 = {DRAGON_ATTACK2PIC,10,NULL,&s_wet_attack3};\r
-statetype s_wet_attack3 = {DRAGON_ATTACK2PIC,10,NULL,&s_wet_attack4};\r
-statetype s_wet_attack4 = {DRAGON_ATTACK3PIC,10,T_DragonShoot,&s_wet_walk1};\r
-\r
-statetype s_wet_ouch = {DRAGON_OUCHPIC,10,T_Dragon,&s_wet_walk1};\r
-\r
-statetype s_wet_die1 = {DRAGON_DEATH1PIC,27,NULL,&s_wet_die2};\r
-statetype s_wet_die2 = {DRAGON_DEATH2PIC,29,NULL,&s_wet_die3};\r
-statetype s_wet_die3 = {DRAGON_DEATH3PIC,44,NULL,&s_wet_die4};\r
-statetype s_wet_die4 = {DRAGON_BUBBLES2PIC,26,NULL,&s_wet_die5};\r
-statetype s_wet_die5 = {DRAGON_BUBBLES1PIC,23,NULL,NULL};\r
-\r
-statetype s_dragon_shot1 = {PSHOT1PIC,8,&T_ShootPlayer,&s_dragon_shot2};\r
-statetype s_dragon_shot2 = {PSHOT2PIC,8,&T_ShootPlayer,&s_dragon_shot1};\r
-\r
-\r
-typedef enum {wt_BUBBLES,wt_WALK,wt_CORNER1,wt_CORNER2,wt_CORNER3,wt_CORNER4} DragonTypes;\r
-\r
-\r
-#define WD_TIMEREMAIN (ob->temp1)\r
-#define WD_STAGE (ob->temp2)\r
-#define WATER_DRAGON_LEAVE 0x04\r
-\r
-/*\r
-===============\r
-=\r
-= SpawnDragon\r
-=\r
-===============\r
-*/\r
-void SpawnDragon(int tilex, int tiley)\r
-{\r
- objtype *ob;\r
- SpawnNewObj(tilex,tiley,&s_wet_bubbles1,PIXRADIUS*35);\r
- ob=new;\r
-\r
- WD_STAGE = wt_BUBBLES;\r
- WD_TIMEREMAIN = 80;\r
-\r
- new->obclass = wetobj;\r
- new->speed = 1000;\r
- new->flags &= ~of_shootable;\r
- new->hitpoints = EasyHitPoints(20);\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= T_Dragon\r
-=\r
-===============\r
-*/\r
-\r
-void T_Dragon(objtype *ob)\r
-{\r
- switch (WD_STAGE)\r
- {\r
- case wt_BUBBLES:\r
- ob->flags &= ~of_shootable;\r
- if (Chase(ob,true))\r
- {\r
- // RISE & GOTO WALK STAGE\r
- //\r
-\r
- WD_STAGE = wt_WALK;\r
- WD_TIMEREMAIN = 60*8+random(60*5);\r
- ob->state = &s_wet_rise1;\r
- ob->speed = 2200;\r
- ob->ticcount = ob->state->tictime;\r
- }\r
- else\r
- {\r
- // DEC COUNTER - And check for WALK\r
- //\r
- if ((WD_TIMEREMAIN-=realtics) < 0)\r
- {\r
- // RISE & GOTO WALK STAGE\r
- //\r
-\r
- WD_STAGE = wt_WALK;\r
- WD_TIMEREMAIN = 60*8+random(60*5);\r
- ob->state = &s_wet_rise1;\r
- ob->speed = 2200;\r
- ob->ticcount = ob->state->tictime;\r
- }\r
- else\r
- if (random(1000)<5)\r
- {\r
- // RANDOM PEEK UP OUT OF WATER\r
- //\r
-\r
- ob->state=&s_wet_peek;\r
- ob->ticcount = ob->state->tictime;\r
- }\r
- }\r
- break;\r
-\r
-\r
- case wt_WALK:\r
- ob->flags |= of_shootable;\r
-\r
- if (Chase(ob,true) || (CheckHandAttack(ob)))\r
-\r
- {\r
- ob->flags |= WATER_DRAGON_LEAVE;\r
- WD_STAGE = random(wt_CORNER3) + 2;\r
- WD_TIMEREMAIN = 60*2+(random(6)*60);\r
- ob->state = &s_wet_bubbles1;\r
- ob->ticcount = ob->state->tictime;\r
- }\r
- else\r
- if (AngleNearPlayer(ob) != -1)\r
- {\r
- ob->state = &s_wet_attack1;\r
- ob->ticcount = ob->state->tictime;\r
- }\r
-\r
- else\r
- {\r
- // DEC COUNTER - And check for SINK\r
- //\r
- if ((WD_TIMEREMAIN-=realtics) < 0)\r
- {\r
- // SINK & GOTO BUBBLE STAGE\r
- //\r
-\r
- WD_STAGE = wt_BUBBLES;\r
- WD_TIMEREMAIN = 60*2+random(60*2);\r
- ob->state = &s_wet_sink1;\r
- ob->speed = 1200;\r
- ob->ticcount = ob->state->tictime;\r
- ob->flags &= ~of_shootable;\r
- }\r
-\r
- }\r
- break;\r
- case wt_CORNER1:\r
- case wt_CORNER2:\r
- case wt_CORNER3:\r
- case wt_CORNER4:\r
- ob->flags &= ~of_shootable;\r
- if ((WD_TIMEREMAIN -= realtics) < 0)\r
- {\r
- WD_STAGE = wt_BUBBLES;\r
- ob->flags &= ~WATER_DRAGON_LEAVE;\r
- }\r
- else\r
- {\r
- fixed tempx,tempy;\r
- unsigned temp_tilex,temp_tiley;\r
-\r
- tempx = player->x;\r
- tempy = player->y;\r
- temp_tilex = player->tilex;\r
- temp_tiley = player->tiley;\r
-\r
- player->x = ((long)other_x[WD_STAGE-2]<<TILESHIFT)+TILEGLOBAL/2;\r
- player->y = ((long)other_y[WD_STAGE-2]<<TILESHIFT)+TILEGLOBAL/2;\r
- player->tilex = other_x[WD_STAGE-2];\r
- player->tiley = other_y[WD_STAGE-2];\r
-\r
-\r
- Chase(ob,true);\r
-\r
- player->x = tempx;\r
- player->y = tempy;\r
- player->tilex = temp_tilex;\r
- player->tiley = temp_tiley;\r
- }\r
- break;\r
- }\r
-}\r
-\r
-/*\r
-===============\r
-=\r
-= T_DragonShoot\r
-=\r
-===============\r
-*/\r
-void T_DragonShoot (objtype *ob)\r
-{\r
- ShootPlayer(ob,dshotobj,10000,&s_dragon_shot1);\r
-}\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// C3_PLAY.C\r
-\r
-#include "DEF.H"\r
-#pragma hdrstop\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-void SpawnSkeleton(int tilex, int tiley);\r
-\r
-#if 0\r
-#define MSHOTDAMAGE 2\r
-#define MSHOTSPEED 10000\r
-\r
-#define ESHOTDAMAGE 1\r
-#define ESHOTSPEED 5000\r
-\r
-#define SSHOTDAMAGE 3\r
-#define SSHOTSPEED 6500\r
-\r
-#define RANDOM_ATTACK 20\r
-#endif\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-boolean ShootPlayer (objtype *ob, short obclass, short speed, statetype *state);\r
-void T_ShootPlayer(objtype *ob);\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- SKELETON IN WALL\r
-\r
-=============================================================================\r
-*/\r
-\r
-void T_WallSkeleton(objtype *ob);\r
-\r
-statetype s_wallskel = {0,40,T_WallSkeleton,&s_wallskel};\r
-statetype s_wallskel2 = {0,1,NULL,NULL};\r
-\r
-\r
-enum wskel_modes {ws_wall1,ws_wall2,ws_wall3,ws_exit};\r
-//enum wskel_modes {ws_wall1,ws_exit};\r
-\r
-#define wskel_mode ob->temp1\r
-#define wskel_delay ob->temp2\r
-#define wskel_base ob->angle\r
-#define wskel_wallx ob->hitpoints\r
-#define wskel_wally ob->speed\r
-\r
-/*\r
-===============\r
-=\r
-= SpawnWallSkeleton\r
-=\r
-===============\r
-*/\r
-void SpawnWallSkeleton(int tilex, int tiley)\r
-{\r
- char xofs[] = {0,0,-1,+1};\r
- char yofs[] = {-1,+1,0,0};\r
-\r
- objtype *ob;\r
- int wallx=tilex,wally=tiley,wallbase,wallmode,loop;\r
- unsigned tile,current_delay;\r
-\r
- for (loop=0; loop<4; loop++)\r
- {\r
- tile = *(mapsegs[0]+farmapylookup[tiley+yofs[loop]]+tilex+xofs[loop]);\r
- switch (tile)\r
- {\r
-// case WALL_SKELETON_CODE:\r
-// case WALL_SKELETON_CODE+1:\r
-// case WALL_SKELETON_CODE+2:\r
-// wallmode = ws_wall1+(tile-WALL_SKELETON_CODE);\r
-// wallbase = WALL_SKELETON_CODE;\r
-// goto foundtile;\r
-// break;\r
-\r
- case 66:\r
- case 68:\r
-// case 21:\r
- wallmode = ws_wall1+(tile-66);\r
- wallbase = 66;\r
- goto foundtile;\r
-// break;\r
-\r
- case 67:\r
- case 69:\r
- wallmode = ws_wall1+(tile-67);\r
- wallbase = 67;\r
- goto foundtile;\r
-// break;\r
- }\r
- }\r
-\r
- return;\r
-foundtile:;\r
-\r
- wallx += xofs[loop];\r
- wally += yofs[loop];\r
-\r
- SpawnNewObj(tilex,tiley,&s_wallskel,PIXRADIUS*35);\r
- ob = new;\r
- new->obclass = wallskelobj;\r
- new->speed = 1900;\r
- new->flags &= ~of_shootable;\r
- new->hitpoints = 12;\r
-\r
-// new->tilex = wallx;\r
-// new->tiley = wally;\r
- wskel_wallx = wallx;\r
- wskel_wally = wally;\r
- wskel_base = wallbase;\r
- new->active = no;\r
-\r
- wskel_mode = wallmode;\r
-\r
- tile = *(mapsegs[2]+farmapylookup[wally]+wallx);\r
- if (tile)\r
- wskel_delay = (tile>>8)*30;\r
- else\r
- {\r
- current_delay = (2*60)+random(4*60);\r
- wskel_delay = zombie_base_delay+current_delay;\r
- zombie_base_delay += current_delay;\r
- if (zombie_base_delay > 8*60)\r
- zombie_base_delay = 0;\r
- }\r
-}\r
-\r
-/*\r
-===============\r
-=\r
-= T_WallSkeleton\r
-=\r
-===============\r
-*/\r
-void T_WallSkeleton(objtype *ob)\r
-{\r
- int x=wskel_wallx,y=wskel_wally;\r
-\r
- wskel_delay -= realtics;\r
- if (wskel_delay > 0)\r
- return;\r
-\r
- switch (wskel_mode)\r
- {\r
- case ws_wall2:\r
- if ((wskel_base == 66) || (wskel_base == 67))\r
- wskel_mode++;\r
- case ws_wall1:\r
- case ws_wall3:\r
- (unsigned)actorat[x][y]\r
- = tilemap[x][y]\r
- = *(mapsegs[0]+farmapylookup[y]+x)\r
- = wskel_base+(wskel_mode-ws_wall1);\r
-\r
- wskel_mode++;\r
- wskel_delay = (120);\r
- ob->active = always;\r
- break;\r
-\r
- case ws_exit:\r
- (unsigned)actorat[x][y]\r
- = tilemap[x][y]\r
- = *(mapsegs[0]+farmapylookup[y]+x)\r
- = 21;\r
-// = wskel_base;\r
- ob->tilex = ob->x >> TILESHIFT;\r
- ob->tiley = ob->y >> TILESHIFT;\r
-\r
- ob->obclass = skeletonobj;\r
- ob->speed = 2036;\r
- ob->flags |= of_shootable;\r
- ob->hitpoints = 12;\r
- ob->state = &s_skel_1;\r
- ob->ticcount = ob->state->tictime;\r
- break;\r
- }\r
-}\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- SKELETONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-void T_Skeleton(objtype *ob);\r
-\r
-\r
-\r
-\r
-statetype s_skel_pause = {SKELETON_1PIC,40,NULL,&s_skel_2};\r
-\r
-statetype s_skel_1 = {SKELETON_1PIC,10,T_Skeleton,&s_skel_2};\r
-statetype s_skel_2 = {SKELETON_2PIC,10,T_Skeleton,&s_skel_3};\r
-statetype s_skel_3 = {SKELETON_3PIC,10,T_Skeleton,&s_skel_4};\r
-statetype s_skel_4 = {SKELETON_4PIC,10,T_Skeleton,&s_skel_1};\r
-\r
-statetype s_skel_attack1 = {SKELETON_ATTACK_1PIC,12,NULL,&s_skel_attack2};\r
-statetype s_skel_attack2 = {SKELETON_ATTACK_2PIC,12,NULL,&s_skel_attack3};\r
-statetype s_skel_attack3 = {SKELETON_ATTACK_3PIC,12,T_DoDamage,&s_skel_pause};\r
-\r
-statetype s_skel_ouch = {SKELETON_OUCHPIC,8,NULL,&s_skel_1};\r
-\r
-statetype s_skel_die1 = {SKELETON_OUCHPIC,18,NULL,&s_skel_die2};\r
-statetype s_skel_die2 = {SKELETON_DEATH_1PIC,18,NULL,&s_skel_die3};\r
-statetype s_skel_die3 = {SKELETON_DEATH_2PIC,18,NULL,&s_skel_die3};\r
-\r
-/*\r
-===============\r
-=\r
-= SpawnSkeleton\r
-=\r
-===============\r
-*/\r
-void SpawnSkeleton(int tilex, int tiley)\r
-{\r
- SpawnNewObj(tilex,tiley,&s_skel_1,PIXRADIUS*35);\r
- new->obclass = skeletonobj;\r
- new->speed = 2036;\r
- new->flags |= of_shootable;\r
- new->hitpoints = EasyHitPoints(12);\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= T_Skeleton\r
-=\r
-===============\r
-*/\r
-\r
-void T_Skeleton(objtype *ob)\r
-{\r
- if (Chase (ob,true) || (random(1000)<RANDOM_ATTACK))\r
- {\r
- ob->state = &s_skel_attack1;\r
- ob->ticcount = ob->state->tictime;\r
- return;\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- EYE\r
-\r
-=============================================================================\r
-*/\r
-\r
-void T_EyeMage (objtype *ob);\r
-boolean T_EyeShoot (objtype *ob, boolean eyeshot);\r
-void T_EyeShootPlayer (objtype *ob);\r
-\r
-extern statetype s_eye_shootplayer_1;\r
-extern statetype s_eye_shootplayer_2;\r
-\r
-statetype s_eye_pause = {EYE_WALK1PIC,40,NULL,&s_eye_2};\r
-\r
-statetype s_eye_1 = {EYE_WALK1PIC,20,T_EyeMage,&s_eye_2};\r
-statetype s_eye_2 = {EYE_WALK2PIC,20,T_EyeMage,&s_eye_3};\r
-statetype s_eye_3 = {EYE_WALK3PIC,20,T_EyeMage,&s_eye_4};\r
-statetype s_eye_4 = {EYE_WALK2PIC,20,T_EyeMage,&s_eye_1};\r
-statetype s_eye_shootplayer_1 = {EYE_SCOWLPIC,1,T_EyeShootPlayer,&s_eye_shootplayer_2};\r
-statetype s_eye_shootplayer_2 = {EYE_SCOWLPIC,20,NULL,&s_eye_1};\r
-\r
-statetype s_eye_ouch = {EYE_OUCH1PIC,8,NULL,&s_eye_ouch2};\r
-statetype s_eye_ouch2 = {EYE_OUCH2PIC,8,NULL,&s_eye_1};\r
-\r
-statetype s_eye_die1 = {EYE_DEATH1PIC,22,NULL,&s_eye_die2};\r
-statetype s_eye_die2 = {EYE_DEATH2PIC,22,NULL,&s_eye_die3};\r
-statetype s_eye_die3 = {EYE_DEATH2PIC,22,NULL,NULL};\r
-\r
-extern statetype s_eshot2;\r
-\r
-statetype s_eshot1 = {EYE_SHOT1PIC,8,&T_ShootPlayer,&s_eshot2};\r
-statetype s_eshot2 = {EYE_SHOT2PIC,8,&T_ShootPlayer,&s_eshot1};\r
-\r
-#define eye_mode ob->temp1\r
-#define eye_delay ob->temp2\r
-\r
-\r
-//-------------------------------------------------------------------------\r
-// SpawnEye()\r
-//-------------------------------------------------------------------------\r
-void SpawnEye(int tilex, int tiley)\r
-{\r
- objtype *ob;\r
-\r
- SpawnNewObj(tilex,tiley,&s_eye_1,PIXRADIUS*35);\r
- ob = new;\r
- new->obclass = eyeobj;\r
- new->speed = 1200;\r
- new->flags |= of_shootable;\r
- new->hitpoints = EasyHitPoints(15);\r
- eye_mode = em_other1;\r
-}\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// T_EyeShootPlayer\r
-//---------------------------------------------------------------------------\r
-void T_EyeShootPlayer (objtype *ob)\r
-{\r
- ShootPlayer(ob,eshotobj,ESHOTSPEED,&s_eshot1);\r
-}\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- SUCCUBUS\r
-\r
-=============================================================================\r
-*/\r
-\r
-void T_Succubus (objtype *ob);\r
-void T_SuccubusShot (objtype *ob);\r
-\r
-extern statetype s_succubus_pause;\r
-extern statetype s_succubus_walk1;\r
-extern statetype s_succubus_walk2;\r
-extern statetype s_succubus_walk3;\r
-extern statetype s_succubus_walk4;\r
-extern statetype s_succubus_shot1;\r
-extern statetype s_succubus_attack1;\r
-extern statetype s_succubus_attack2;\r
-extern statetype s_succubus_attack3;\r
-extern statetype s_succubus_death1;\r
-extern statetype s_succubus_death2;\r
-\r
-statetype s_succubus_pause = {SUCCUBUS_WALK2PIC,10,NULL,&s_succubus_walk3};\r
-\r
-statetype s_succubus_walk1 = {SUCCUBUS_WALK1PIC,10,T_EyeMage,&s_succubus_walk2};\r
-statetype s_succubus_walk2 = {SUCCUBUS_WALK2PIC,10,T_EyeMage,&s_succubus_walk3};\r
-statetype s_succubus_walk3 = {SUCCUBUS_WALK3PIC,10,T_EyeMage,&s_succubus_walk4};\r
-statetype s_succubus_walk4 = {SUCCUBUS_WALK4PIC,10,T_EyeMage,&s_succubus_walk1};\r
-\r
-statetype s_succubus_attack1 = {SUCCUBUS_ATTACK1PIC,15,NULL,&s_succubus_attack2};\r
-statetype s_succubus_attack2 = {SUCCUBUS_ATTACK1PIC,-1,T_SuccubusShot,&s_succubus_attack3};\r
-statetype s_succubus_attack3 = {SUCCUBUS_ATTACK2PIC,15,NULL,&s_succubus_pause};\r
-\r
-statetype s_succubus_ouch = {SUCCUBUS_OUCHPIC,15,NULL,&s_succubus_walk1};\r
-\r
-statetype s_succubus_death1 = {SUCCUBUS_DEATH1PIC,55,NULL,&s_succubus_death2};\r
-statetype s_succubus_death2 = {SUCCUBUS_DEATH2PIC,20,NULL,&s_succubus_death2};\r
-\r
-statetype s_succubus_shot1 = {SUCCUBUS_SHOT1PIC,12,&T_ShootPlayer,&s_succubus_shot1};\r
-\r
-/*\r
-===============\r
-=\r
-= SpawnSuccubus\r
-=\r
-===============\r
-*/\r
-\r
-void SpawnSuccubus (int tilex, int tiley)\r
-{\r
- SpawnNewObj(tilex,tiley,&s_succubus_walk1,PIXRADIUS*30);\r
- new->obclass = succubusobj;\r
- new->speed = 2500;\r
- new->flags |= of_shootable;\r
- new->hitpoints = EasyHitPoints(12);\r
-}\r
-\r
-/*\r
-===============\r
-=\r
-= T_SuccubusShot\r
-=\r
-===============\r
-*/\r
-\r
-void T_SuccubusShot (objtype *ob)\r
-{\r
- ShootPlayer(ob,sshotobj,ob->temp1 ? MSHOTSPEED : SSHOTSPEED,&s_succubus_shot1);\r
-// ob->state = &s_succubus_attack3;\r
-// ob->ticcount = ob->temp1 ? 7 : ob->state->tictime;\r
-}\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- MAGE\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-void T_MageShoot (objtype *ob);\r
-\r
-extern statetype s_magepause;\r
-\r
-extern statetype s_mage1;\r
-extern statetype s_mage2;\r
-\r
-extern statetype s_mageattack1;\r
-extern statetype s_mageattack2;\r
-extern statetype s_mageattack3;\r
-\r
-extern statetype s_mageouch;\r
-\r
-extern statetype s_magedie1;\r
-extern statetype s_magedie2;\r
-\r
-\r
-statetype s_magepause = {MAGE1PIC,10,NULL,&s_mage2};\r
-\r
-statetype s_mage1 = {MAGE1PIC,20,T_EyeMage,&s_mage2};\r
-statetype s_mage2 = {MAGE2PIC,20,T_EyeMage,&s_mage1};\r
-\r
-//statetype s_mageattack1 = {MAGEATTACKPIC,20,NULL,&s_mageattack2};\r
-//statetype s_mageattack2 = {MAGEATTACKPIC,-1,T_MageShoot,&s_mageattack3};\r
-statetype s_mageattack3 = {MAGEATTACKPIC,30,NULL,&s_magepause};\r
-\r
-statetype s_mageouch = {MAGEOUCHPIC,10,NULL,&s_mage1};\r
-\r
-statetype s_magedie1 = {MAGEDIE1PIC,20,NULL,&s_magedie2};\r
-statetype s_magedie2 = {MAGEDIE2PIC,0,NULL,&s_magedie2};\r
-\r
-\r
-statetype s_mshot1 = {PSHOT1PIC,8,&T_ShootPlayer,&s_mshot2};\r
-statetype s_mshot2 = {PSHOT2PIC,8,&T_ShootPlayer,&s_mshot1};\r
-\r
-/*\r
-===============\r
-=\r
-= SpawnMage\r
-=\r
-===============\r
-*/\r
-\r
-void SpawnMage (int tilex, int tiley)\r
-{\r
- SpawnNewObj(tilex,tiley,&s_mage1,PIXRADIUS*35);\r
- new->obclass = mageobj;\r
- new->speed = 3072;\r
- new->flags |= of_shootable;\r
- new->hitpoints = EasyHitPoints(12);\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= T_EyeMage\r
-=\r
-= **********\r
-= ***NOTE*** This routine controls the thinks for the Eye, Mage, and Succubus.\r
-= **********\r
-=\r
-===============\r
-*/\r
-\r
-void T_EyeMage (objtype *ob)\r
-{\r
- fixed tempx,tempy;\r
- unsigned temp_tilex,temp_tiley;\r
- int angle;\r
-\r
- eye_delay -= realtics;\r
- if (eye_delay < 0)\r
- {\r
- eye_mode = random(em_dummy);\r
- eye_delay = (10*60);\r
- }\r
-\r
- tempx = player->x;\r
- tempy = player->y;\r
- temp_tilex = player->tilex;\r
- temp_tiley = player->tiley;\r
-\r
-\r
- switch (eye_mode)\r
- {\r
- case em_other1:\r
- case em_other2:\r
- case em_other3:\r
- case em_other4:\r
- player->x = ((long)other_x[eye_mode]<<TILESHIFT)+TILEGLOBAL/2;\r
- player->y = ((long)other_y[eye_mode]<<TILESHIFT)+TILEGLOBAL/2;\r
- player->tilex = other_x[eye_mode];\r
- player->tiley = other_y[eye_mode];\r
- break;\r
- }\r
-\r
- if (Chase(ob,true))\r
- eye_delay = 0;\r
-\r
- player->x = tempx;\r
- player->y = tempy;\r
- player->tilex = temp_tilex;\r
- player->tiley = temp_tiley;\r
-\r
-\r
- if (ob->obclass == mageobj) // do the mage shot\r
- {\r
- if (!random(10))\r
- if (ShootPlayer(ob,mshotobj,MSHOTSPEED,&s_mshot1))\r
- {\r
- ob->state = &s_mageattack3;\r
- ob->ticcount = ob->state->tictime;\r
- }\r
- }\r
- else\r
- if (ob->obclass == succubusobj) // do the succubus shot\r
- {\r
- angle = AngleNearPlayer(ob); // make sure angle is correct\r
- // - see AngleNearPlayer\r
- if (!random(5) && (angle != -1)) // if correct angle and random # attack\r
- {\r
- ob->state = &s_succubus_attack1; // change state to attack\r
- ob->ticcount = ob->state->tictime; // init ticcount - otherwise\r
- } // object may get hung in a\r
- } // endless state\r
-\r
- else\r
- {\r
- angle = AngleNearPlayer(ob); // do the eye shot\r
-\r
- if (!random(2) && (angle != -1))\r
- {\r
- ob->state = &s_eye_shootplayer_1;\r
- ob->ticcount = ob->state->tictime;\r
- }\r
- }\r
-\r
-}\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- BUNNY\r
-\r
-=============================================================================\r
-*/\r
-\r
-void T_HarmlessBunnyWalk(objtype *ob);\r
-void T_Bunny(objtype *ob);\r
-\r
-extern statetype s_bunny_left1;\r
-extern statetype s_bunny_left2;\r
-extern statetype s_bunny_left3;\r
-extern statetype s_bunny_right1;\r
-extern statetype s_bunny_right2;\r
-extern statetype s_bunny_right3;\r
-extern statetype s_bunny_meta1;\r
-extern statetype s_bunny_meta2;\r
-extern statetype s_bunny_walk1;\r
-extern statetype s_bunny_walk2;\r
-extern statetype s_bunny_attack1;\r
-extern statetype s_bunny_attack2;\r
-extern statetype s_bunny_pause;\r
-extern statetype s_bunny_death1;\r
-extern statetype s_bunny_death2;\r
-extern statetype s_bunny_death3;\r
-\r
-statetype s_bunny_left1 = {BUNNY_LEFT1PIC, 55, NULL, &s_bunny_left2};\r
-statetype s_bunny_left2 = {BUNNY_LEFT1PIC, 10, T_HarmlessBunnyWalk, &s_bunny_left1};\r
-statetype s_bunny_left3 = {BUNNY_LEFT2PIC, 30, NULL, &s_bunny_left1};\r
-\r
-statetype s_bunny_right1 = {BUNNY_RIGHT1PIC, 55, NULL, &s_bunny_right2};\r
-statetype s_bunny_right2 = {BUNNY_RIGHT1PIC, 10, T_HarmlessBunnyWalk, &s_bunny_right1};\r
-statetype s_bunny_right3 = {BUNNY_RIGHT2PIC, 30, NULL, &s_bunny_right1};\r
-\r
-statetype s_bunny_meta1 = {BUNNY_META1PIC, 30, NULL, &s_bunny_meta2};\r
-statetype s_bunny_meta2 = {BUNNY_META2PIC, 30, NULL, &s_bunny_walk1};\r
-\r
-statetype s_bunny_walk1 = {BUNNY_WALK1PIC, 25, T_Bunny, &s_bunny_walk2};\r
-statetype s_bunny_walk2 = {BUNNY_WALK2PIC, 25, T_Bunny, &s_bunny_walk1};\r
-\r
-statetype s_bunny_attack1 = {BUNNY_WALK1PIC, 25, NULL, &s_bunny_attack2};\r
-statetype s_bunny_attack2 = {BUNNY_WALK2PIC, 25, T_DoDamage, &s_bunny_walk1};\r
-\r
-statetype s_bunny_ouch = {BUNNY_OUCHPIC, 30, NULL, &s_bunny_pause};\r
-statetype s_bunny_pause = {BUNNY_WALK1PIC, 50, T_Bunny, &s_bunny_walk2};\r
-\r
-statetype s_bunny_death1 = {BUNNY_OUCHPIC, 40, NULL, &s_bunny_death2};\r
-statetype s_bunny_death2 = {BUNNY_DEATH1PIC, 50, NULL, &s_bunny_death3};\r
-statetype s_bunny_death3 = {BUNNY_DEATH2PIC, 20, NULL, &s_bunny_death3};\r
-\r
-\r
-#define bunny_dir_hop ob->temp1\r
-#define bunny_delay ob->temp2\r
-#define LEFTSIDE 0x8 // 1=left 0=right --side showing\r
-\r
-/*\r
-===============\r
-=\r
-= SpawnBunny\r
-=\r
-===============\r
-*/\r
-\r
-void SpawnBunny (int tilex, int tiley)\r
-{\r
- SpawnNewObj(tilex,tiley,&s_bunny_left1,PIXRADIUS*35);\r
- new->obclass = hbunnyobj;\r
- new->speed = 1947;\r
- new->temp1 = (random(3))+2;\r
- new->temp2 = random(30);\r
- new->flags &= ~of_shootable;\r
- new->flags |= LEFTSIDE; //left side showing}\r
-}\r
-\r
-/*\r
-===============\r
-=\r
-= T_HarmlessBunnyWalk\r
-=\r
-===============\r
-*/\r
-\r
-\r
-void T_HarmlessBunnyWalk(objtype *ob)\r
-{\r
- int valid_dir[8][2] = {{6,5}, {7,6}, {4,7}, {5,4}, {3,2}, {0,3}, {1,0}, {2,1}};\r
- long move;\r
- dirtype player_dir;\r
- fixed old_x, old_y;\r
- unsigned old_tilex, old_tiley;\r
- long old_distance;\r
-\r
-\r
- ob->temp2 -= realtics;\r
- if (ob->temp2 <= 0)\r
- {\r
- if (CheckHandAttack(ob))\r
- {\r
- ob->temp2 = -1;\r
- return;\r
- }\r
-\r
- actorat[ob->tilex][ob->tiley] = 0;\r
- ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
- ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
- ob->distance = TILEGLOBAL;\r
- ob->state = &s_bunny_meta1;\r
- ob->ticcount = ob->state->tictime;\r
- ob->obclass = bunnyobj;\r
- ob->flags |= of_shootable;\r
- ob->hitpoints = EasyHitPoints(10);\r
- ob->dir = nodir;\r
- ChaseThink(ob,true); // JTR - testing..\r
- return;\r
- }\r
-\r
- // The direction of the player isn't updated so it must be\r
- // calculated. This is done so the correct side (left/right)\r
- // of the bunny will be showed.\r
-\r
- if ((player->angle > 337) || (player->angle <= 22))\r
- player_dir = east;\r
- else\r
- if (player->angle <= 67)\r
- player_dir = northeast;\r
- else\r
- if (player->angle <= 112)\r
- player_dir = north;\r
- else\r
- if (player->angle <= 157)\r
- player_dir = northwest;\r
- else\r
- if (player->angle <= 202)\r
- player_dir = west;\r
- else\r
- if (player->angle <= 247)\r
- player_dir = southwest;\r
- else\r
- if (player->angle <= 292)\r
- player_dir = south;\r
- else\r
- if (player->angle <= 337)\r
- player_dir = southeast;\r
- if (ob->temp1)\r
- ob->temp1--;\r
- else\r
- ob->temp1 = (random(3))+2;\r
- if (ob->flags & LEFTSIDE)\r
- {\r
- if (ob->temp1)\r
- {\r
- if (valid_dir[player_dir][0] != ob->dir)\r
- {\r
- ob->dir = valid_dir[player_dir][0];\r
- }\r
- }\r
- else\r
- {\r
- ob->state = &s_bunny_right1;\r
- ob->ticcount = ob->state->tictime;\r
- ob->flags &= ~LEFTSIDE;\r
- ob->dir = valid_dir[player_dir][1];\r
- return;\r
- }\r
- }\r
- else\r
- {\r
- if (ob->temp1)\r
- {\r
- if (valid_dir[player_dir][1] != ob->dir)\r
- {\r
- ob->dir = valid_dir[player_dir][1];\r
- }\r
- }\r
- else\r
- {\r
- ob->state = &s_bunny_left1;\r
- ob->ticcount = ob->state->tictime;\r
- ob->flags |= LEFTSIDE;\r
- ob->dir = valid_dir[player_dir][2];\r
- return;\r
- }\r
- }\r
-\r
- move = ob->speed*tics;\r
-\r
- do\r
- {\r
- old_distance = ob->distance;\r
- old_x = ob->x;\r
- old_y = ob->y;\r
- old_tilex = ob->tilex;\r
- old_tiley = ob->tiley;\r
-\r
- MoveObj (ob, move);\r
-\r
- ob->tilex = ob->x >> TILESHIFT;\r
- ob->tiley = ob->y >> TILESHIFT;\r
-\r
- if (ob->tilex == old_tilex && ob->tiley == old_tiley)\r
- {\r
- break;\r
- }\r
- else\r
- if (actorat[ob->tilex][ob->tiley] == 0)\r
- {\r
- actorat[old_tilex][old_tiley] = 0;\r
- actorat[ob->tilex][ob->tiley] = ob;\r
- ob->distance = TILEGLOBAL;\r
- }\r
- else\r
- {\r
- ob->distance = old_distance;\r
- ob->x = old_x;\r
- ob->y = old_y;\r
- ob->tilex = old_tilex;\r
- ob->tiley = old_tiley;\r
- return;\r
- }\r
-\r
- } while (0);\r
-\r
- CalcBounds (ob);\r
-\r
- if (ob->flags & LEFTSIDE)\r
- ob->state = &s_bunny_left3;\r
- else\r
- ob->state = &s_bunny_right3;\r
- ob->ticcount = ob->state->tictime;\r
-}\r
-\r
-/*\r
-===============\r
-=\r
-= T_Bunny\r
-=\r
-===============\r
-*/\r
-\r
-void T_Bunny(objtype *ob)\r
-{\r
- if (Chase (ob, true) || (random(1000)<RANDOM_ATTACK))\r
- {\r
- ob->state = &s_bunny_attack1;\r
- ob->ticcount = ob->state->tictime;\r
- return;\r
- }\r
-}\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// C3_PLAY.C\r
-\r
-#include "DEF.H"\r
-#pragma hdrstop\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#if 0\r
-#define MSHOTDAMAGE 2\r
-#define MSHOTSPEED 10000\r
-\r
-#define ESHOTDAMAGE 1\r
-#define ESHOTSPEED 5000\r
-\r
-#define SSHOTDAMAGE 3\r
-#define SSHOTSPEED 6500\r
-\r
-#define RANDOM_ATTACK 20\r
-#endif\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-boolean ShootPlayer (objtype *ob, short obclass, short speed, statetype *state);\r
-void T_ShootPlayer(objtype *ob);\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-=============================================================================\r
-\r
- RED DEMON\r
-\r
-=============================================================================\r
-*/\r
-\r
-void T_RedDemon (objtype *ob);\r
-void T_RedDemonCheckCnt (objtype *ob);\r
-\r
-extern statetype s_red_demonpause;\r
-\r
-extern statetype s_red_demon1;\r
-extern statetype s_red_demon2;\r
-extern statetype s_red_demon3;\r
-extern statetype s_red_demon4;\r
-\r
-extern statetype s_red_demonattack1;\r
-extern statetype s_red_demonattack2;\r
-extern statetype s_red_demonattack3;\r
-\r
-extern statetype s_red_demonouch;\r
-\r
-extern statetype s_red_demondie1;\r
-extern statetype s_red_demondie2;\r
-extern statetype s_red_demondie3;\r
-extern statetype s_red_demondie4;\r
-\r
-statetype s_red_demonpause = {RED_DEMON1PIC,30,NULL,&s_red_demon2};\r
-\r
-statetype s_red_demon1 = {RED_DEMON1PIC,20,T_RedDemon,&s_red_demon2};\r
-statetype s_red_demon2 = {RED_DEMON2PIC,20,T_RedDemon,&s_red_demon3};\r
-statetype s_red_demon3 = {RED_DEMON3PIC,20,T_RedDemon,&s_red_demon4};\r
-statetype s_red_demon4 = {RED_DEMON4PIC,20,T_RedDemon,&s_red_demon1};\r
-\r
-statetype s_red_demonattack1 = {RED_DEMONATTACK1PIC,20,NULL,&s_red_demonattack2};\r
-statetype s_red_demonattack2 = {RED_DEMONATTACK2PIC,20,NULL,&s_red_demonattack3};\r
-statetype s_red_demonattack3 = {RED_DEMONATTACK3PIC,30,T_DoDamage,&s_red_demon2};\r
-\r
-statetype s_red_demonouch = {RED_DEMONOUCHPIC,30,NULL,&s_red_demon1};\r
-\r
-statetype s_red_demondie1 = {RED_DEMONOUCHPIC,9,NULL,&s_red_demondie2};\r
-statetype s_red_demondie2 = {RED_DEMONDIE1PIC,9,T_RedDemonCheckCnt,&s_red_demondie1};\r
-statetype s_red_demondie3 = {RED_DEMONDIE2PIC,20,NULL,&s_red_demondie4};\r
-statetype s_red_demondie4 = {RED_DEMONDIE3PIC,10,NULL,&s_red_demondie4};\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= SpawnRedDemon\r
-=\r
-===============\r
-*/\r
-\r
-void SpawnRedDemon (int tilex, int tiley)\r
-{\r
- SpawnNewObj(tilex,tiley,&s_red_demon1,PIXRADIUS*35);\r
- new->obclass = reddemonobj;\r
- new->speed = 2048;\r
- new->flags |= of_shootable;\r
- new->hitpoints = EasyHitPoints(50);\r
- new->temp1 = 25;\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= T_RedDemon\r
-=\r
-===============\r
-*/\r
-\r
-void T_RedDemon (objtype *ob)\r
-{\r
- if (Chase (ob,true) || (random(1000)<RANDOM_ATTACK))\r
- {\r
- ob->state = &s_red_demonattack1;\r
- ob->ticcount = ob->state->tictime;\r
- return;\r
- }\r
-}\r
-\r
-/*\r
-===============\r
-=\r
-= T_RedDemonCheckCnt\r
-=\r
-===============\r
-*/\r
-\r
-void T_RedDemonCheckCnt (objtype *ob)\r
-{\r
- ob->temp1--;\r
- if (!ob->temp1)\r
- {\r
- ob->state = &s_red_demondie3;\r
- ob->ticcount = ob->state->tictime;\r
- }\r
-}\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- GRELMINAR\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-void T_Grelminar (objtype *ob);\r
-void T_GrelminarShoot (objtype *ob);\r
-void T_Grelm_DropKey(objtype *ob);\r
-\r
-extern statetype s_grelpause;\r
-\r
-extern statetype s_grel1;\r
-extern statetype s_grel2;\r
-\r
-extern statetype s_grelattack1;\r
-extern statetype s_grelattack2;\r
-extern statetype s_grelattack3;\r
-\r
-extern statetype s_grelouch;\r
-\r
-extern statetype s_greldie1;\r
-extern statetype s_greldie2;\r
-extern statetype s_greldie3;\r
-extern statetype s_greldie4;\r
-extern statetype s_greldie5;\r
-extern statetype s_greldie5a;\r
-extern statetype s_greldie6;\r
-\r
-\r
-statetype s_grelpause = {GREL1PIC,50,NULL,&s_grel2};\r
-\r
-statetype s_grel1 = {GREL1PIC,20,T_Grelminar,&s_grel2};\r
-statetype s_grel2 = {GREL2PIC,20,T_Grelminar,&s_grel1};\r
-\r
-//statetype s_grelattack1 = {GRELATTACKPIC,20,NULL,&s_grelattack2};\r
-//statetype s_grelattack2 = {GRELATTACKPIC,-1,T_GrelminarShoot,&s_grelattack3};\r
-statetype s_grelattack3 = {GRELATTACKPIC,30,NULL,&s_grelpause};\r
-\r
-statetype s_grelouch = {GRELHITPIC,6,NULL,&s_grel1};\r
-\r
-statetype s_greldie1 = {GRELDIE1PIC,22,NULL,&s_greldie2};\r
-statetype s_greldie2 = {GRELDIE2PIC,22,NULL,&s_greldie3};\r
-statetype s_greldie3 = {GRELDIE3PIC,22,NULL,&s_greldie4};\r
-statetype s_greldie4 = {GRELDIE4PIC,22,NULL,&s_greldie5};\r
-statetype s_greldie5 = {GRELDIE5PIC,22,NULL,&s_greldie5a};\r
-statetype s_greldie5a = {GRELDIE5PIC,1,T_Grelm_DropKey,&s_greldie6};\r
-statetype s_greldie6 = {GRELDIE6PIC,0,NULL,&s_greldie6};\r
-\r
-\r
-extern statetype s_gshot1;\r
-\r
-statetype s_gshot1 = {SKULL_SHOTPIC,8,T_ShootPlayer,&s_gshot1};\r
-\r
-/*\r
-===============\r
-=\r
-= SpawnGrelminar\r
-=\r
-===============\r
-*/\r
-\r
-void SpawnGrelminar (int tilex, int tiley)\r
-{\r
- unsigned Grel_Hard;\r
- unsigned DropKey;\r
-\r
- SpawnNewObj(tilex,tiley,&s_grel1,PIXRADIUS*35);\r
- new->obclass = grelmobj;\r
- new->speed = 2048;\r
- new->flags |= of_shootable;\r
-\r
- //\r
- // if Grelminar is to drop a key the info-plane byte to the right\r
- // should have a 1 in the highbyte, else he will not drop the key.\r
- //\r
- DropKey = *(mapsegs[2]+farmapylookup[tiley]+tilex+1);\r
- if (DropKey)\r
- new->temp1 = DropKey>>8;\r
- else\r
- new->temp1 = 0;\r
-\r
- //\r
- // The info-plane byte below Grelminar will determine how powerful\r
- // Grelminar is. If nothing is there, he is the most powerful.\r
- // -- affected are the hit points and the shot damage.\r
- // The hit points are controlled here, the shot damage is controlled\r
- // within the spawning of the shot. See ShootPlayer for more info.\r
- //\r
- Grel_Hard = *(mapsegs[2]+farmapylookup[tiley+1]+tilex);\r
- if (Grel_Hard)\r
- {\r
- new->temp2 = Grel_Hard>>8;\r
- new->hitpoints = EasyHitPoints((new->temp2 * 10));\r
- }\r
- else\r
- new->hitpoints = EasyHitPoints(100);\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= T_Grelminar\r
-=\r
-===============\r
-*/\r
-\r
-void T_Grelminar (objtype *ob)\r
-{\r
- Chase (ob,false);\r
-\r
- if (!random(10))\r
- if (ShootPlayer(ob,gshotobj,ob->temp2,&s_gshot1))\r
- {\r
- ob->state = &s_grelattack3;\r
- ob->ticcount = ob->state->tictime;\r
- }\r
- if (CheckHandAttack(ob))\r
- TakeDamage (ob->temp2*3);\r
-\r
-}\r
-\r
-\r
-//=================================\r
-//\r
-// T_Grelm_DropKey\r
-//\r
-//=================================\r
-void T_Grelm_DropKey(objtype *ob)\r
-{\r
- if (!(ob->temp1))\r
- {\r
- ob->state = NULL;\r
- return;\r
- }\r
-\r
- SpawnBonus(ob->tilex,ob->tiley,B_RKEY);\r
- SD_PlaySound(GRELM_DEADSND);\r
- ob->temp1 = false;\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- BAT\r
-\r
-=============================================================================\r
-*/\r
-\r
-void T_Bat (objtype *ob);\r
-void T_BatPast (objtype *ob);\r
-\r
-extern statetype s_bat1;\r
-extern statetype s_bat2;\r
-extern statetype s_bat3;\r
-extern statetype s_bat4;\r
-\r
-extern statetype s_batdie1;\r
-extern statetype s_batdie2;\r
-\r
-\r
-statetype s_bat1 = {BAT1PIC,6,T_Bat,&s_bat2};\r
-statetype s_bat2 = {BAT2PIC,6,T_Bat,&s_bat3};\r
-statetype s_bat3 = {BAT3PIC,6,T_Bat,&s_bat4};\r
-statetype s_bat4 = {BAT4PIC,6,T_Bat,&s_bat1};\r
-\r
-statetype s_batpast = {BAT4PIC,80,T_BatPast,&s_bat1};\r
-\r
-statetype s_batdie1 = {BATDIE1PIC,18,NULL,&s_batdie2};\r
-statetype s_batdie2 = {BATDIE2PIC,18,NULL,NULL};\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= SpawnBat\r
-=\r
-===============\r
-*/\r
-\r
-void SpawnBat (int tilex, int tiley)\r
-{\r
- SpawnNewObj(tilex,tiley,&s_bat1,PIXRADIUS*35);\r
- new->obclass = batobj;\r
- new->flags |= of_shootable;\r
-\r
- new->hitpoints = 1;\r
- new->speed = 2000;\r
-}\r
-\r
-\r
-/*\r
-==================================\r
-=\r
-= BatChaseThink\r
-=\r
-==================================\r
-*/\r
-\r
-void BatChaseThink (objtype *obj)\r
-{\r
- int deltax,deltay;\r
-\r
- deltax=player->tilex - obj->tilex;\r
- deltay=player->tiley - obj->tiley;\r
-\r
- if (deltax>0)\r
- deltax = 2;\r
- else if (deltax<0)\r
- deltax = 0;\r
- else deltax = 1;\r
-\r
- if (deltay>0)\r
- deltay = 2;\r
- else if (deltay<0)\r
- deltay = 0;\r
- else deltay = 1;\r
-\r
- obj->dir = dirtable[deltay*3+deltax];\r
- if (Walk(obj))\r
- return;\r
-\r
- obj->dir = dirtable[3+deltax];\r
- if (Walk(obj))\r
- return;\r
-\r
- obj->dir = dirtable[deltay*3+1];\r
- if (Walk(obj))\r
- return;\r
-\r
- obj->dir = nodir;\r
-}\r
-\r
-\r
-void BatRunThink (objtype *obj)\r
-{\r
- int deltax,deltay;\r
-\r
- deltax=player->tilex - obj->tilex;\r
- deltay=player->tiley - obj->tiley;\r
-\r
- if (deltax>=0)\r
- deltax = 0;\r
- else\r
- deltax = 2;\r
-\r
- if (deltay>=0)\r
- deltay = 0;\r
- else\r
- deltay = 2;\r
-\r
- obj->dir = dirtable[deltay*3+deltax];\r
- if (Walk(obj))\r
- return;\r
-\r
- obj->dir = dirtable[3+deltax];\r
- if (Walk(obj))\r
- return;\r
-\r
- obj->dir = dirtable[deltay*3+1];\r
- Walk(obj);\r
-}\r
-\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= T_Bat\r
-=\r
-===============\r
-*/\r
-\r
-void T_Bat (objtype *ob)\r
-{\r
- long move;\r
- long deltax,deltay,size;\r
-\r
- move = ob->speed*tics;\r
- size = (long)ob->size + player->size + move;\r
-\r
-\r
- do\r
- {\r
- deltax = ob->x - player->x;\r
- deltay = ob->y - player->y;\r
-\r
- if (deltax <= size && deltax >= -size\r
- && deltay <= size && deltay >= -size && !ob->temp1)\r
- {\r
- TakeDamage (4);\r
- ob->temp1 = 2;\r
- }\r
-\r
- if (move < ob->distance)\r
- {\r
- MoveObj (ob,move);\r
- break;\r
- }\r
-\r
- actorat[ob->tilex][ob->tiley] = 0; // pick up marker from goal\r
- if (ob->dir == nodir)\r
- ob->dir = north;\r
-\r
- ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
- ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
- move -= ob->distance;\r
-\r
- if (ob->temp1)\r
- {\r
- Walk (ob); // go straight\r
- if (!--ob->temp1)\r
- {\r
- ob->state = &s_batpast;\r
- ob->ticcount = ob->state->tictime;\r
- }\r
- }\r
- else\r
- BatChaseThink (ob); // head towards player\r
-\r
- actorat[ob->tilex][ob->tiley] = ob; // set down a new goal marker\r
- } while (0); // just once\r
- CalcBounds (ob);\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= T_BatPast\r
-=\r
-===============\r
-*/\r
-\r
-void T_BatPast (objtype *ob)\r
-{\r
- long move;\r
- long deltax,deltay,size;\r
-\r
- move = ob->speed*tics;\r
-\r
- do\r
- {\r
- if (move < ob->distance)\r
- {\r
- MoveObj (ob,move);\r
- break;\r
- }\r
- actorat[ob->tilex][ob->tiley] = 0; // pick up marker from goal\r
-\r
- ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
- ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
- move -= ob->distance;\r
-\r
- BatRunThink (ob);\r
-\r
- actorat[ob->tilex][ob->tiley] = ob; // set down a new goal marker\r
- } while (0); //(move)\r
- CalcBounds (ob);\r
-}\r
-\r
-\r
-void T_ChaseThink(objtype *obj);\r
-void T_AwakeThink(objtype *obj);\r
-\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- GODESS\r
-\r
-=============================================================================\r
-*/\r
-\r
-void T_Godess (objtype *ob);\r
-\r
-\r
-extern statetype s_godesspause;\r
-\r
-extern statetype s_godess_statue1;\r
-extern statetype s_godess_statue2;\r
-\r
-extern statetype s_godess1;\r
-extern statetype s_godess2;\r
-extern statetype s_godess3;\r
-\r
-extern statetype s_godessattack1;\r
-extern statetype s_godessattack2;\r
-extern statetype s_godessattack3;\r
-\r
-extern statetype s_godessouch;\r
-\r
-extern statetype s_godessdie1;\r
-extern statetype s_godessdie2;\r
-extern statetype s_godessdie3;\r
-\r
-\r
-statetype s_godesspause = {GODESS_WALK1PIC,25,NULL,&s_godess2};\r
-\r
-statetype s_godess_statue1 = {GODESS_STATUEPIC,20,T_ChaseThink,&s_godess_statue1};\r
-statetype s_godess_statue2 = {GODESS_STATUEPIC,1,T_AwakeThink,&s_godess1};\r
-\r
-statetype s_godess1 = {GODESS_WALK1PIC,20,T_ChaseThink,&s_godess2};\r
-statetype s_godess2 = {GODESS_WALK2PIC,20,T_ChaseThink,&s_godess3};\r
-statetype s_godess3 = {GODESS_WALK3PIC,20,T_ChaseThink,&s_godess1};\r
-\r
-statetype s_godessattack1 = {GODESS_ATTACK1PIC,10,NULL,&s_godessattack2};//20\r
-statetype s_godessattack2 = {GODESS_ATTACK2PIC,8,NULL,&s_godessattack3};//20\r
-statetype s_godessattack3 = {GODESS_ATTACK3PIC,10,T_DoDamage,&s_godesspause};//30\r
-\r
-statetype s_godessouch = {GODESS_OUCHPIC,10,NULL,&s_godess1};\r
-\r
-statetype s_godessdie1 = {GODESS_DEATH1PIC,65,NULL,&s_godessdie2};\r
-statetype s_godessdie2 = {GODESS_DEATH2PIC,30,NULL,&s_godessdie2};\r
-\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= SpawnGodess\r
-=\r
-===============\r
-*/\r
-\r
-void SpawnGodess (int tilex, int tiley)\r
-{\r
- objtype *ob;\r
- short current_zombie_delay;\r
- unsigned tile;\r
-\r
- SpawnNewObj(tilex,tiley,&s_godess_statue1,PIXRADIUS*35);\r
- ob = new;\r
- zombie_mode = zm_wait_for_dark;\r
-\r
- tile = *(mapsegs[2]+farmapylookup[tiley+1]+tilex);\r
- if (tile)\r
- zombie_delay = (tile>>8)*30;\r
- else\r
- {\r
- current_zombie_delay = (2*60)+random(4*60);\r
- zombie_delay = zombie_base_delay+current_zombie_delay;\r
- zombie_base_delay += current_zombie_delay;\r
- if (zombie_base_delay > 8*60)\r
- zombie_base_delay = 0;\r
- }\r
-\r
- new->obclass = realsolidobj;//godessobj;\r
- new->speed = 3000;\r
- new->flags |= of_shootable;\r
- new->flags &= ~of_tree;\r
-// new->hitpoints = EasyHitPoints(10);\r
-}\r
-\r
-\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- ANT\r
-\r
-=============================================================================\r
-*/\r
-\r
-void T_Ant(objtype *ob);\r
-\r
-statetype s_ant_wait = {ANT_EGG1PIC,10,T_ChaseThink,&s_ant_wait};\r
-\r
-statetype s_ant_egg = {ANT_EGG2PIC,45,T_AwakeThink,&s_ant_walk1};\r
-\r
-statetype s_ant_walk1 = {ANT_WALK1PIC,20,T_ChaseThink,&s_ant_walk2};\r
-statetype s_ant_walk2 = {ANT_WALK2PIC,20,T_ChaseThink,&s_ant_walk3};\r
-statetype s_ant_walk3 = {ANT_WALK3PIC,20,T_ChaseThink,&s_ant_walk1};\r
-\r
-statetype s_ant_attack1 = {ANT_ATTACKPIC,20,NULL,&s_ant_pause};\r
-\r
-statetype s_ant_pause = {ANT_WALK2PIC,15,T_DoDamage,&s_ant_walk1};\r
-\r
-statetype s_ant_ouch = {ANT_WALK1PIC,15,NULL,&s_ant_walk1};\r
-\r
-statetype s_ant_die1 = {ANT_DEATH1PIC,40,NULL,&s_ant_die2};\r
-statetype s_ant_die2 = {ANT_DEATH2PIC,10,NULL,&s_ant_die3};\r
-statetype s_ant_die3 = {ANT_DEATH3PIC,10,NULL,&s_ant_die2};\r
-\r
-#define ant_mode ob->temp1\r
-#define ant_delay ob->temp2\r
-\r
-/*\r
-===============\r
-=\r
-= SpawnAnt\r
-=\r
-===============\r
-*/\r
-void SpawnAnt(int tilex, int tiley)\r
-{\r
- objtype *ob;\r
- unsigned tile;\r
- SpawnNewObj(tilex,tiley,&s_ant_wait,PIXRADIUS*35);\r
- ob = new;\r
-\r
- tile = *(mapsegs[2]+farmapylookup[tiley+1]+tilex);\r
- if (tile)\r
- ant_delay = (tile>>8)*30;\r
- else\r
- ant_delay = 2*60+random(5*60);\r
-\r
- ant_mode = zm_wait_for_dark;\r
-\r
- new->obclass = antobj;\r
- new->speed = 1900;\r
- new->flags &= ~of_shootable;\r
- new->hitpoints = EasyHitPoints(15);\r
-}\r
-\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- ZOMBIE\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern statetype s_zombie_rise1;\r
-extern statetype s_zombie_rise2;\r
-extern statetype s_zombie_rise3;\r
-extern statetype s_zombie_rise4;\r
-\r
-extern statetype s_zombie_alive1;\r
-extern statetype s_zombie_alive2;\r
-extern statetype s_zombie_alive3;\r
-\r
-//extern statetype s_zombie_attack1;\r
-\r
-extern statetype s_zombie_death1;\r
-extern statetype s_zombie_death2;\r
-extern statetype s_zombie_death3;\r
-\r
-void T_Zombie (objtype *ob);\r
-void T_ZombieRisen(objtype *obj);\r
-\r
-statetype s_zombie_risen = {ZOMB_WALK3PIC,1,T_AwakeThink,&s_zombie_alive1};\r
-\r
-statetype s_zombie_pause = {ZOMB_WALK1PIC,20,NULL,&s_zombie_alive1};\r
-\r
-statetype s_zombie_inground = {0,13,T_ChaseThink,&s_zombie_inground};\r
-\r
-statetype s_zombie_rise1 = {ZOMB_APPEAR1PIC,24,NULL,&s_zombie_rise2};\r
-statetype s_zombie_rise2 = {ZOMB_APPEAR2PIC,24,NULL,&s_zombie_rise3};\r
-statetype s_zombie_rise3 = {ZOMB_APPEAR3PIC,24,NULL,&s_zombie_rise4};\r
-statetype s_zombie_rise4 = {ZOMB_APPEAR4PIC,24,NULL,&s_zombie_risen};\r
-\r
-statetype s_zombie_alive1 = {ZOMB_WALK1PIC,13,T_ChaseThink,&s_zombie_alive2};\r
-statetype s_zombie_alive2 = {ZOMB_WALK2PIC,13,T_ChaseThink,&s_zombie_alive3};\r
-statetype s_zombie_alive3 = {ZOMB_WALK3PIC,13,T_ChaseThink,&s_zombie_alive1};\r
-\r
-statetype s_zombie_death1 = {ZOMB_DIE1PIC,16,NULL,&s_zombie_death2};\r
-statetype s_zombie_death2 = {ZOMB_DIE2PIC,16,NULL,&s_zombie_death3};\r
-statetype s_zombie_death3 = {ZOMB_DIE3PIC,16,NULL,&s_zombie_death3};\r
-\r
-statetype s_zombie_attack = {ZOMB_ATTACKPIC,15,T_DoDamage,&s_zombie_pause};\r
-//statetype s_zombie_attack1 = {ZOMB_ATTACKPIC,15,NULL,&s_zombie_pause};\r
-\r
-statetype s_zombie_ouch = {ZOMB_OUCHPIC,15,NULL,&s_zombie_alive1};\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-// SpawnZombie()\r
-//--------------------------------------------------------------------------\r
-void SpawnZombie (int tilex, int tiley)\r
-{\r
- objtype *ob;\r
- short current_zombie_delay;\r
- unsigned tile;\r
-\r
- SpawnNewObj(tilex,tiley,&s_zombie_inground,35*PIXRADIUS);\r
- ob = new;\r
- zombie_mode = zm_wait_for_dark;\r
-\r
- tile = *(mapsegs[2]+farmapylookup[tiley+1]+tilex);\r
- if (tile)\r
- zombie_delay = (tile>>8)*30;\r
- else\r
- {\r
- current_zombie_delay = (2*60)+random(4*60);\r
- zombie_delay = zombie_base_delay+current_zombie_delay;\r
- zombie_base_delay += current_zombie_delay;\r
- if (zombie_base_delay > 8*60)\r
- zombie_base_delay = 0;\r
- }\r
-\r
- new->speed = 2500;\r
- new->obclass = zombieobj;\r
- new->hitpoints = EasyHitPoints(8);\r
- new->active = yes;\r
- new->flags &= ~of_shootable;\r
-}\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- TREE\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern statetype s_tree_pause;\r
-extern statetype s_tree_idle;\r
-extern statetype s_tree_awakening1;\r
-extern statetype s_tree_awakening2;\r
-extern statetype s_tree_walk1;\r
-extern statetype s_tree_walk2;\r
-extern statetype s_tree_walk3;\r
-extern statetype s_tree_death1;\r
-extern statetype s_tree_death2;\r
-extern statetype s_tree_death3;\r
-extern statetype s_tree_death4;\r
-extern statetype s_tree_death5;\r
-extern statetype s_tree_attack1;\r
-extern statetype s_tree_attack2;\r
-extern statetype s_tree_attack3;\r
-extern statetype s_tree_ouch;\r
-\r
-void T_Tree (objtype *ob);\r
-void T_DeathThink(objtype *ob);\r
-\r
-statetype s_tree_pause = {TREE_WALK1PIC,25,NULL,&s_tree_walk2};\r
-\r
-statetype s_tree_idle = {TREE_IDLEPIC,13,T_ChaseThink,&s_tree_idle};\r
-\r
-statetype s_tree_awakening1 = {TREE_AWAKENINGPIC,1,T_AwakeThink,&s_tree_awakening2};\r
-statetype s_tree_awakening2 = {TREE_AWAKENINGPIC,50,NULL,&s_tree_walk1};\r
-\r
-statetype s_tree_walk1 = {TREE_WALK1PIC,13,T_ChaseThink,&s_tree_walk2};\r
-statetype s_tree_walk2 = {TREE_WALK2PIC,13,T_ChaseThink,&s_tree_walk1};\r
-\r
-statetype s_tree_death1 = {TREE_DEATH1PIC,45,NULL,&s_tree_death2};\r
-statetype s_tree_death2 = {TREE_DEATH2PIC,25,NULL,&s_tree_death3};\r
-statetype s_tree_death3 = {TREE_DEATH1PIC,15,T_DeathThink,&s_tree_death4};\r
-statetype s_tree_death4 = {TREE_DEATH2PIC,15,T_DeathThink,&s_tree_death5};\r
-statetype s_tree_death5 = {TREE_DEATH3PIC,15,T_DeathThink,&s_tree_death3};\r
-\r
-statetype s_tree_attack1 = {TREE_ATTACK1PIC,15,T_DoDamage,&s_tree_attack2};\r
-statetype s_tree_attack2 = {TREE_ATTACK2PIC,15,T_DoDamage,&s_tree_attack3};\r
-statetype s_tree_attack3 = {TREE_ATTACK3PIC,15,T_DoDamage,&s_tree_pause};\r
-\r
-statetype s_tree_ouch = {TREE_AWAKENINGPIC,15,NULL,&s_tree_walk1};\r
-\r
-\r
-#define zombie_mode ob->temp1\r
-#define zombie_delay ob->temp2\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-// SpawnTree()\r
-//--------------------------------------------------------------------------\r
-void SpawnTree(int tilex, int tiley)\r
-{\r
- objtype *ob;\r
- short current_zombie_delay;\r
- unsigned tile;\r
-\r
- SpawnNewObj(tilex,tiley,&s_tree_idle,35*PIXRADIUS);\r
- ob = new;\r
- zombie_mode = zm_wait_for_dark;\r
-\r
- tile = *(mapsegs[2]+farmapylookup[tiley+1]+tilex);\r
- if (tile)\r
- zombie_delay = (tile>>8)*30;\r
- else\r
- {\r
- current_zombie_delay = (2*60)+random(4*60);\r
- zombie_delay = zombie_base_delay+current_zombie_delay;\r
- zombie_base_delay += current_zombie_delay;\r
- if (zombie_base_delay > 8*60)\r
- zombie_base_delay = 0;\r
- }\r
-\r
- new->speed = 2500;\r
- new->obclass = realsolidobj;\r
-// new->hitpoints = EasyHitPoints(12);\r
- new->active = yes;\r
- new->flags |= of_shootable;\r
- new->flags |= of_tree;\r
-}\r
-\r
-//--------------------------------------------------------------------------\r
-// T_DeathThink()\r
-//--------------------------------------------------------------------------\r
-void T_DeathThink(objtype *ob)\r
-{\r
- char num;\r
-\r
- if ((ob->ticcount - realtics) <= 0)\r
- {\r
- num = random(2);\r
- switch (ob->temp1)\r
- {\r
- case 3:\r
- if (num)\r
- ob->state = &s_tree_death4;\r
- else\r
- ob->state = &s_tree_death5;\r
- ob->temp1++;\r
- break;\r
-\r
- case 4:\r
- if (num)\r
- ob->state = &s_tree_death3;\r
- else\r
- ob->state = &s_tree_death5;\r
- ob->temp1++;\r
- break;\r
-\r
- case 5:\r
- if (num)\r
- ob->state = &s_tree_death3;\r
- else\r
- ob->state = &s_tree_death4;\r
- ob->temp1 = 3;\r
- break;\r
- }\r
- ob->ticcount = ob->state->tictime;\r
- }\r
-\r
-\r
-\r
- if (CheckHandAttack(ob))\r
- TakeDamage (1);\r
-}\r
-\r
-\r
-//////////////////////////////////////////////////////////////////////////\r
-//\r
-// GENERAL THINK ROUTINES USED BY THE ZOMBIE, TREE, ANT, AND GODESS\r
-// ----trying to cut down on the code size----\r
-//\r
-//////////////////////////////////////////////////////////////////////////\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-// T_ChaseThink()\r
-//--------------------------------------------------------------------------\r
-void T_ChaseThink(objtype *ob)\r
-{\r
- switch (zombie_mode)\r
- {\r
- case zm_wait_for_dark:\r
-#if 0\r
- if (gamestate.mapon == 0)\r
- {\r
- if (BGFLAGS & BGF_NIGHT)\r
- zombie_mode = zm_wait_to_rise;\r
- }\r
- else\r
-#endif\r
- zombie_mode = zm_wait_to_rise;\r
- break;\r
-\r
- case zm_wait_to_rise:\r
- if (zombie_delay < 0)\r
- {\r
- if ((ob->tilex == player->tilex) && (ob->tiley == player->tiley))\r
- break;\r
- if (CheckHandAttack(ob))\r
- break;\r
-\r
- ob->active = always;\r
- switch (ob->obclass)\r
- {\r
- case zombieobj:\r
- ob->state = &s_zombie_rise1;\r
- break;\r
-\r
- case antobj:\r
- ob->state = &s_ant_egg;\r
- break;\r
-\r
- case realsolidobj: //tree and godess\r
- if (ob->flags & of_tree)\r
- ob->state = &s_tree_awakening1;\r
- else\r
- ob->state = &s_godess_statue2;\r
- break;\r
- }\r
- ob->ticcount = ob->state->tictime;\r
- zombie_mode = zm_active;\r
- }\r
- else\r
- zombie_delay -= tics;\r
-\r
- break;\r
-\r
- case zm_active:\r
- if (Chase (ob,true) || (random(1000)<RANDOM_ATTACK))\r
- {\r
- switch (ob->obclass)\r
- {\r
- case zombieobj:\r
- ob->state = &s_zombie_attack;\r
- break;\r
-\r
- case antobj:\r
- ob->state = &s_ant_attack1;\r
- break;\r
-\r
- case treeobj:\r
- ob->state = &s_tree_attack1;\r
- break;\r
-\r
- case godessobj:\r
- ob->state = &s_godessattack1;\r
- break;\r
- }\r
- ob->ticcount = ob->state->tictime;\r
- return;\r
- }\r
- break;\r
- }\r
-}\r
-\r
-//--------------------------------------------------------------------------\r
-// T_AwakeThink()\r
-//--------------------------------------------------------------------------\r
-void T_AwakeThink(objtype *obj)\r
-{\r
- if (obj->obclass == realsolidobj)\r
- {\r
- if (obj->flags & of_tree)\r
- obj->obclass = treeobj;\r
- else\r
- obj->obclass = godessobj;\r
- obj->hitpoints = EasyHitPoints(12);\r
- }\r
- else\r
- obj->flags |= of_shootable;\r
-}\r
-\r
-\r
-\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-// ShootPlayer()\r
-//--------------------------------------------------------------------------\r
-boolean ShootPlayer(objtype *ob, short obclass, short speed, statetype *state)\r
-{\r
- int angle = AngleNearPlayer(ob);\r
-\r
- if (angle == -1)\r
- return(false);\r
-\r
- DSpawnNewObjFrac (ob->x,ob->y,state,PIXRADIUS*35);\r
- new->obclass = obclass;\r
- new->active = always;\r
- new->angle = angle;\r
-\r
- //\r
- // If the shot is Grelminar's, then determine the power of the shot.\r
- // The shot speed is hard-wired as 10000. But the shot power is\r
- // determined by speed. Speed now contains "Grelminar's level of\r
- // hardness" and this is multiplied by 3 to get the shot power.\r
- //\r
- if (obclass == gshotobj)\r
- {\r
- new->speed = 10000;\r
- new->temp1 = speed*3;\r
- }\r
- else\r
- new->speed = speed;\r
-\r
-\r
- return(true);\r
-}\r
-\r
-//--------------------------------------------------------------------------\r
-// T_ShootPlayer()\r
-//--------------------------------------------------------------------------\r
-void T_ShootPlayer(objtype *ob)\r
-{\r
- objtype *check;\r
- long xmove,ymove,speed;\r
-\r
- speed = ob->speed*tics;\r
-\r
- xmove = FixedByFrac(speed,costable[ob->angle]);\r
- ymove = -FixedByFrac(speed,sintable[ob->angle]);\r
-\r
- if (ShotClipMove(ob,xmove,ymove))\r
- {\r
- ob->state = &s_pshot_exp1;\r
- ob->ticcount = ob->state->tictime;\r
- return;\r
- }\r
-\r
- ob->tilex = ob->x >> TILESHIFT;\r
- ob->tiley = ob->y >> TILESHIFT;\r
-\r
-\r
-// check for collision with wall\r
-//\r
- if (tilemap[ob->tilex][ob->tiley])\r
- {\r
- SD_PlaySound (SHOOTWALLSND);\r
- ob->state = &s_pshot_exp1;\r
- ob->ticcount = s_pshot_exp1.tictime;\r
- return;\r
- }\r
-\r
-\r
-\r
-// check for collision with player\r
-//\r
- if ( ob->xl <= player->xh\r
- && ob->xh >= player->xl\r
- && ob->yl <= player->yh\r
- && ob->yh >= player->yl)\r
- {\r
- switch (ob->obclass)\r
- {\r
- case eshotobj:\r
- TakeDamage (ESHOTDAMAGE);\r
- break;\r
-\r
- case mshotobj:\r
- TakeDamage (MSHOTDAMAGE);\r
- break;\r
-\r
- case gshotobj:\r
- TakeDamage (ob->temp1); // the damage of Grelminar's shot -\r
- break; // see Grelminar's spawning\r
-\r
- case sshotobj:\r
- TakeDamage(SSHOTDAMAGE);\r
- break;\r
-\r
- case dshotobj:\r
- TakeDamage(7);\r
- break;\r
- }\r
- ob->state = NULL;\r
- return;\r
- }\r
-\r
-// check for collision with other solid and realsolid objects.\r
-// Great terminology!! -- solid objects really aren't solid\r
-// -- realsolid objects ARE solid\r
-// if ((actorat[ob->tilex][ob->tiley]) && (actorat[ob->tilex][ob->tiley]->obclass != ob->obclass))\r
- if (((actorat[ob->tilex][ob->tiley]->obclass == realsolidobj) ||\r
- (actorat[ob->tilex][ob->tiley]->obclass == solidobj)) &&\r
- (actorat[ob->tilex][ob->tiley]->flags & of_shootable))\r
- {\r
- ob->state = &s_pshot_exp1;\r
- ob->ticcount = s_pshot_exp1.tictime;\r
- return;\r
- }\r
-\r
-\r
-// check for collision with player\r
-//\r
- for (check = player->next; check; check=check->next)\r
- if ((ob->flags & of_shootable) && ob->obclass != mageobj\r
- && ob->xl <= check->xh\r
- && ob->xh >= check->xl\r
- && ob->yl <= check->yh\r
- && ob->yh >= check->yl)\r
- {\r
- switch (ob->obclass)\r
- {\r
- case eshotobj:\r
- ShootActor (check,ESHOTDAMAGE);\r
- break;\r
-\r
- case mshotobj:\r
- ShootActor (check,MSHOTDAMAGE);\r
- break;\r
-\r
- case gshotobj:\r
- ShootActor (check,25); //NOLAN--check on me!!!!!!!\r
- break;\r
-\r
- case pshotobj:\r
- ShootActor (check,25);\r
- break;\r
-\r
- case sshotobj:\r
- ShootActor(check, SSHOTDAMAGE);\r
- break;\r
-\r
- case dshotobj:\r
- ShootActor(check, 7);\r
- break;\r
- }\r
- ob->state = &s_pshot_exp1;\r
- ob->ticcount = s_pshot_exp1.tictime;\r
- return;\r
- }\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// AngleNearPlayer()\r
-//-------------------------------------------------------------------------\r
-int AngleNearPlayer(objtype *ob)\r
-{\r
- int angle=-1;\r
- int xdiff = ob->tilex-player->tilex;\r
- int ydiff = ob->tiley-player->tiley;\r
-\r
- if (ob->tiley == player->tiley)\r
- {\r
- if (ob->tilex < player->tilex)\r
- angle = 0;\r
- else\r
- angle = 180;\r
- }\r
- else\r
- if (ob->tilex == player->tilex)\r
- {\r
- if (ob->tiley < player->tiley)\r
- angle = 270;\r
- else\r
- angle = 90;\r
- }\r
- else\r
- if (xdiff == ydiff)\r
- if (ob->tilex < player->tilex)\r
- {\r
- if (ob->tiley < player->tiley)\r
- angle = 315;\r
- else\r
- angle = 45;\r
- }\r
- else\r
- {\r
- if (ob->tiley < player->tiley)\r
- angle = 225;\r
- else\r
- angle = 135;\r
- }\r
-\r
- return(angle);\r
-}\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// C4_PLAY.C\r
-\r
-#include "DEF.H"\r
-#pragma hdrstop\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-\r
-//-------------------------------------------------------------------------\r
-//\r
-// ARCH OBJECTS\r
-//\r
-//-------------------------------------------------------------------------\r
-\r
-\r
-\r
-//-------------------------------------------------------------------------\r
-// ARCH\r
-//-------------------------------------------------------------------------\r
-\r
-void SpawnArch(int tilex, int tiley, int num);\r
-\r
-extern statetype s_arch_1;\r
-extern statetype s_arch_2;\r
-extern statetype s_arch_3;\r
-extern statetype s_arch_4;\r
-extern statetype s_arch_5;\r
-extern statetype s_arch_6;\r
-extern statetype s_arch_7;\r
-extern statetype s_arch_8;\r
-extern statetype s_arch_9;\r
-extern statetype s_arch_10;\r
-extern statetype s_arch_11;\r
-extern statetype s_arch_12;\r
-extern statetype s_arch_13;\r
-\r
-statetype s_arch_1 = {ARCH1PIC, 20, NULL, &s_arch_1};\r
-statetype s_arch_2 = {ARCH2PIC, 20, NULL, &s_arch_2};\r
-statetype s_arch_3 = {ARCH3PIC, 20, NULL, &s_arch_3};\r
-statetype s_arch_4 = {ARCH4PIC, 20, NULL, &s_arch_4};\r
-statetype s_arch_5 = {ARCH5PIC, 20, NULL, &s_arch_5};\r
-statetype s_arch_6 = {ARCH6PIC, 20, NULL, &s_arch_6};\r
-statetype s_arch_7 = {ARCH7PIC, 20, NULL, &s_arch_7};\r
-statetype s_arch_8 = {ARCH8PIC, 20, NULL, &s_arch_8};\r
-statetype s_arch_9 = {ARCH9PIC, 20, NULL, &s_arch_9};\r
-statetype s_arch_10 = {ARCH10PIC, 20, NULL, &s_arch_10};\r
-statetype s_arch_11 = {ARCH11PIC, 20, NULL, &s_arch_11};\r
-statetype s_arch_12 = {ARCH12PIC, 20, NULL, &s_arch_12};\r
-statetype s_arch_13 = {ARCH13PIC, 20, NULL, &s_arch_13};\r
-\r
-void SpawnArch (int tilex, int tiley, int num)\r
-{\r
- statetype *objstate;\r
-\r
-\r
- switch (num)\r
- {\r
- case 1:\r
- objstate = &s_arch_1;\r
- break;\r
- case 2:\r
- objstate = &s_arch_2;\r
- break;\r
- case 3:\r
- objstate = &s_arch_3;\r
- break;\r
- case 4:\r
- objstate = &s_arch_4;\r
- break;\r
- case 5:\r
- objstate = &s_arch_5;\r
- break;\r
- case 6:\r
- objstate = &s_arch_6;\r
- break;\r
- case 7:\r
- objstate = &s_arch_7;\r
- break;\r
- case 8:\r
- objstate = &s_arch_8;\r
- break;\r
- case 9:\r
- objstate = &s_arch_9;\r
- break;\r
- case 10:\r
- objstate = &s_arch_10;\r
- break;\r
- case 11:\r
- objstate = &s_arch_11;\r
- break;\r
- case 12:\r
- objstate = &s_arch_12;\r
- break;\r
- case 13:\r
- objstate = &s_arch_13;\r
- break;\r
- }\r
- ASpawnNewObj(tilex,tiley,objstate,PIXRADIUS*35);\r
- new->obclass = solidobj;\r
- new->flags &= ~of_shootable;\r
-}\r
-\r
-\r
-//-------------------------------------------------------------------------\r
-//\r
-// MISC OBJECTS\r
-//\r
-//-------------------------------------------------------------------------\r
-\r
-\r
-//-------------------------------------------------------------------------\r
-// COLUMN, SULPHUR GAS HOLE, FIRE POT, FOUNTAIN\r
-//-------------------------------------------------------------------------\r
-\r
-\r
-void SpawnMiscObjects(int tilex, int tiley, int num);\r
-\r
-extern statetype s_column;\r
-extern statetype s_sulphur_gas_1;\r
-extern statetype s_sulphur_gas_2;\r
-extern statetype s_sulphur_gas_3;\r
-extern statetype s_fire_pot_1;\r
-extern statetype s_fire_pot_2;\r
-extern statetype s_fountain;\r
-\r
-statetype s_column = {COLUMNPIC, 20, NULL, &s_column};\r
-statetype s_sulphur_gas_1 = {SULPHUR_GAS_1PIC, 20, NULL, &s_sulphur_gas_2};\r
-statetype s_sulphur_gas_2 = {SULPHUR_GAS_2PIC, 20, NULL, &s_sulphur_gas_3};\r
-statetype s_sulphur_gas_3 = {SULPHUR_GAS_3PIC, 20, NULL, &s_sulphur_gas_1};\r
-statetype s_fire_pot_1 = {FIRE_POT_1PIC, 20, NULL, &s_fire_pot_2};\r
-statetype s_fire_pot_2 = {FIRE_POT_2PIC, 20, NULL, &s_fire_pot_1};\r
-statetype s_fountain = {WFOUNTAINPIC, 20, NULL, &s_fountain};\r
-\r
-\r
-void SpawnMiscObjects(int tilex, int tiley, int num)\r
-{\r
- statetype *objstate;\r
-\r
- switch (num)\r
- {\r
- case 1:\r
- objstate = &s_column;\r
- break;\r
-\r
- case 2:\r
- objstate = &s_sulphur_gas_1;\r
- break;\r
-\r
- case 3:\r
- objstate = &s_fire_pot_1;\r
- break;\r
-\r
- case 4:\r
- objstate = &s_fountain;\r
- break;\r
- }\r
-\r
- SpawnNewObj(tilex,tiley,objstate,PIXRADIUS*35);\r
- new->obclass = realsolidobj;\r
- if (num == 2)\r
- new->flags &= ~of_shootable;\r
- else\r
- new->flags |= of_shootable;\r
-}\r
-\r
-\r
-\r
-\r
-\r
-\r
-#if 0\r
-void SpawnColumn(int tilex, int tiley);\r
-\r
-extern statetype s_column;\r
-statetype s_column = {COLUMNPIC, 20, NULL, &s_column};\r
-\r
-void SpawnColumn(int tilex, int tiley)\r
-{\r
- SpawnNewObj(tilex,tiley,&s_column,PIXRADIUS*35);\r
- new->obclass = realsolidobj;\r
- new->flags |= of_shootable;\r
-}\r
-\r
-\r
-//-------------------------------------------------------------------------\r
-// SULPHUR GAS\r
-//-------------------------------------------------------------------------\r
-\r
-void SpawnSulphurGas(int tilex, int tiley);\r
-\r
-extern statetype s_sulphur_gas_1;\r
-extern statetype s_sulphur_gas_2;\r
-extern statetype s_sulphur_gas_3;\r
-\r
-statetype s_sulphur_gas_1 = {SULPHUR_GAS_1PIC, 20, NULL, &s_sulphur_gas_2};\r
-statetype s_sulphur_gas_2 = {SULPHUR_GAS_2PIC, 20, NULL, &s_sulphur_gas_3};\r
-statetype s_sulphur_gas_3 = {SULPHUR_GAS_3PIC, 20, NULL, &s_sulphur_gas_1};\r
-\r
-void SpawnSulphurGas(int tilex, int tiley)\r
-{\r
- SpawnNewObj(tilex,tiley,&s_sulphur_gas_1,PIXRADIUS*35);\r
- new->obclass = realsolidobj;\r
- new->flags &= ~of_shootable;\r
-}\r
-\r
-\r
-//-------------------------------------------------------------------------\r
-// FIRE POT\r
-//-------------------------------------------------------------------------\r
-\r
-void SpawnFirePot(int tilex, int tiley);\r
-\r
-extern statetype s_fire_pot_1;\r
-extern statetype s_fire_pot_2;\r
-\r
-statetype s_fire_pot_1 = {FIRE_POT_1PIC, 20, NULL, &s_fire_pot_2};\r
-statetype s_fire_pot_2 = {FIRE_POT_2PIC, 20, NULL, &s_fire_pot_1};\r
-\r
-void SpawnFirePot(int tilex, int tiley)\r
-{\r
- SpawnNewObj(tilex,tiley,&s_fire_pot_1,PIXRADIUS*35);\r
- new->obclass = realsolidobj;\r
- new->flags |= of_shootable;\r
-\r
-}\r
-\r
-//------------------------------------------------------------------------\r
-// FOUNTAIN\r
-//------------------------------------------------------------------------\r
-\r
-void SpawnFountain(int tilex, int tiley);\r
-\r
-extern statetype s_fountain;\r
-statetype s_fountain = {WFOUNTAINPIC, 20, NULL, &s_fountain};\r
-\r
-void SpawnFountain(int tilex, int tiley)\r
-{\r
- SpawnNewObj(tilex,tiley,&s_fountain,PIXRADIUS*35);\r
- new->obclass = realsolidobj;\r
- new->flags |= of_shootable;\r
-}\r
-\r
-#endif\r
-\r
-\r
-//------------------------------------------------------------------------\r
-// FORCE FIELD\r
-//------------------------------------------------------------------------\r
-\r
-void SpawnForceField(int tilex, int tiley);\r
-void T_ForceField(objtype *ob);\r
-void T_ForceFieldRemove(objtype *ob);\r
-\r
-extern statetype s_force_field_1;\r
-extern statetype s_force_field_2;\r
-extern statetype s_force_field_3;\r
-extern statetype s_force_field_4;\r
-extern statetype s_force_field_die1;\r
-\r
-statetype s_force_field_1 = {FORCE_FIELD_1PIC, 10, T_ForceField, &s_force_field_2};\r
-statetype s_force_field_2 = {FORCE_FIELD_2PIC, 10, T_ForceField, &s_force_field_3};\r
-statetype s_force_field_3 = {FORCE_FIELD_3PIC, 10, T_ForceField, &s_force_field_4};\r
-statetype s_force_field_4 = {FORCE_FIELD_4PIC, 10, T_ForceField, &s_force_field_1};\r
-\r
-statetype s_force_field_die = {0,0,T_ForceFieldRemove,&s_force_field_die1};\r
-statetype s_force_field_die1 = {0,0,NULL,NULL};\r
-\r
-void SpawnForceField(int tilex, int tiley)\r
-{\r
- SpawnNewObj(tilex,tiley,&s_force_field_1,PIXRADIUS*35);\r
- new->obclass = solidobj;\r
- new->hitpoints = EasyHitPoints(20);\r
- new->flags |= of_forcefield; //sets bit 7 :: makes it nonsolid, but also detectable\r
- // without adding another object type!\r
- new->flags |= of_shootable;\r
-}\r
-\r
-void T_ForceField(objtype *ob)\r
-{\r
- long move,deltax,deltay,size;\r
-\r
- size = (long)ob->size + player->size;\r
-\r
- deltax = ob->x - player->x;\r
- deltay = ob->y - player->y;\r
-\r
- if (deltax <= size && deltax >= -size\r
- && deltay <= size && deltay >= -size)\r
- TakeDamage (20);\r
-\r
-}\r
-\r
-void T_ForceFieldRemove(objtype *ob)\r
-{\r
- actorat[ob->tilex][ob->tiley] = 0;\r
-}\r
-\r
-\r
-//------------------------------------------------------------------------\r
-// SKELETON HANGING FROM CEILING\r
-//------------------------------------------------------------------------\r
-\r
-void SpawnSkeletonHanging(int tilex, int tiley);\r
-void T_SkelHangThink(objtype *ob);\r
-\r
-extern statetype s_skeleton_hanging;\r
-statetype s_skeleton_hanging = {SKEL_HANGPIC, 20, T_SkelHangThink, &s_skeleton_hanging};\r
-\r
-void SpawnSkeletonHanging(int tilex, int tiley)\r
-{\r
- unsigned tile;\r
-\r
- SpawnNewObj(tilex,tiley,&s_skeleton_hanging,PIXRADIUS*35);\r
- new->obclass = solidobj;\r
-\r
- tile = *(mapsegs[2]+farmapylookup[tiley+1]+tilex);\r
- if (tile)\r
- new->temp1 = (tile>>8)*30;\r
- else\r
- new->temp1 = (3*60)+random(4*60);\r
-\r
- new->flags |= of_shootable;\r
-}\r
-\r
-void T_SkelHangThink(objtype *ob)\r
-{\r
- ob->temp1 -= realtics;\r
- if (ob->temp1 <= 0)\r
- {\r
- ob->state = &s_skel_1;\r
- ob->ticcount = ob->state->tictime;\r
- ob->obclass = skeletonobj;\r
- ob->speed = 2036;\r
- ob->flags |= of_shootable;\r
- ob->hitpoints = EasyHitPoints(12);\r
- }\r
-}\r
-\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// EasyHitPoints\r
-//\r
-// Checks to see if the player has selected the easy mode for playing.\r
-// If so then the normal hit points are cut in half.\r
-// This is when the object is spawned.\r
-//\r
-// Parms\r
-// NrmHitPts - the normal hit points\r
-//\r
-// Returns\r
-// Half of NrmHitPts\r
-//\r
-/////////////////////////////////////////////////////////////////////////////\r
-\r
-int EasyHitPoints(int NrmHitPts)\r
-{\r
- if (EASYMODEON) // Wimpy, Wimpy, Wimpy!!!!!\r
- {\r
- return(NrmHitPts/4);\r
- }\r
- else\r
- return(NrmHitPts);\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// EasyDoDamage\r
-//\r
-// Checks to see if the player has selected the easy mode for playing.\r
-// If so then the normal amount of damage is cut in half.\r
-// This is called each time a monster does damage.\r
-//\r
-// Parms\r
-// Damage - the normal damage taken\r
-//\r
-// Returns\r
-// Half of Damage\r
-//\r
-/////////////////////////////////////////////////////////////////////////////\r
-\r
-int EasyDoDamage(int Damage)\r
-{\r
- if (EASYMODEON) // Wimpy, Wimpy, Wimpy!!!!!\r
- return(Damage/2);\r
- else\r
- return(Damage);\r
-}\r
-\r
+++ /dev/null
-; Catacomb Armageddon Source Code\r
-; Copyright (C) 1993-2014 Flat Rock Software\r
-;\r
-; This program is free software; you can redistribute it and/or modify\r
-; it under the terms of the GNU General Public License as published by\r
-; the Free Software Foundation; either version 2 of the License, or\r
-; (at your option) any later version.\r
-;\r
-; This program is distributed in the hope that it will be useful,\r
-; but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-; GNU General Public License for more details.\r
-;\r
-; You should have received a copy of the GNU General Public License along\r
-; with this program; if not, write to the Free Software Foundation, Inc.,\r
-; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-\r
-IDEAL\r
-\r
-MODEL MEDIUM,C\r
-\r
-INCLUDE "ID_ASM.EQU"\r
-\r
-VIEWWIDTH = (40*8) ;33\r
-GC_INDEX = 03CEh\r
-\r
-DATASEG\r
-EVEN\r
-\r
-;=================== Tables filled in by DrawVWall ==========================\r
-\r
-;\r
-; wallheight has the height (scale number) of that collumn of scaled wall\r
-; it is pre bounded to 1-MAXSCALE (the actuial height on screen is 2*height)\r
-;\r
-wallheight dw VIEWWIDTH dup (?)\r
-\r
-;\r
-; wallwidth has the pixel width (1-7) of that collumn\r
-;\r
-wallwidth dw VIEWWIDTH dup (?)\r
-\r
-;\r
-; wallseg has the segment of the wall picture\r
-;\r
-wallseg dw VIEWWIDTH dup (?)\r
-\r
-;\r
-; wallofs has the offset of the wall picture\r
-;\r
-wallofs dw VIEWWIDTH dup (?)\r
-\r
-;============================================================================\r
-\r
-;\r
-; screenbyte is just position/8\r
-;\r
-LABEL screenbyte WORD\r
-pos = 0\r
-REPT VIEWWIDTH\r
- dw pos/8\r
-pos = pos+1\r
-ENDM\r
-\r
-;\r
-; screenbit is (position&7)*16\r
-;\r
-LABEL screenbit WORD\r
-pos = 0\r
-REPT VIEWWIDTH\r
- dw (pos AND 7)*16\r
-pos = pos+1\r
-ENDM\r
-\r
-;\r
-; Use offset: screenbit[]+pixwidth*2\r
-; acess from bitmasks-2+offset for one biased pixwidth\r
-; the low byte of bitmasks is for the first screen byte, the high byte\r
-; is the bitmask for the second screen byte (if non 0)\r
-;\r
-\r
-bitmasks dw 0080h,00c0h,00e0h,00f0h,00f8h,00fch,00feh,00ffh\r
- dw 0040h,0060h,0070h,0078h,007ch,007eh,007fh,807fh\r
- dw 0020h,0030h,0038h,003ch,003eh,003fh,803fh,0c03fh\r
- dw 0010h,0018h,001ch,001eh,001fh,801fh,0c01fh,0e01fh\r
- dw 0008h,000ch,000eh,000fh,800fh,0c00fh,0e00fh,0f00fh\r
- dw 0004h,0006h,0007h,8007h,0c007h,0e007h,0f007h,0f807h\r
- dw 0002h,0003h,8003h,0c003h,0e003h,0f003h,0f803h,0fc03h\r
- dw 0001h,8001h,0c001h,0e001h,0f001h,0f801h,0fc01h,0fe01h\r
-\r
-\r
-;\r
-; wallscalecall is a far pointer to the start of a compiled scaler\r
-; The low word will never change, while the high word is set to\r
-; compscaledirectory[scale]\r
-;\r
-wallscalecall dd (65*6) ; offset of t_compscale->code[0]\r
-\r
-\r
-PUBLIC wallheight,wallwidth,wallseg,wallofs,screenbyte,screenbit\r
-PUBLIC bitmasks,wallscalecall\r
-\r
-\r
-EXTRN scaledirectory:WORD ; array of MAXSCALE segment pointers to\r
- ; compiled scalers\r
-EXTRN screenseg:WORD ; basically just 0xa000\r
-EXTRN bufferofs:WORD ; offset of the current work screen\r
-EXTRN ylookup:WORD\r
-EXTRN screenpage:WORD\r
-\r
-CODESEG\r
-\r
-;============================================================================\r
-;\r
-; ScaleWalls\r
-;\r
-; AX AL is scratched in bit mask setting and scaling\r
-; BX table index\r
-; CX pixwidth*2\r
-; DX GC_INDEX\r
-; SI offset into wall data to scale from, allways 0,64,128,...4032\r
-; DI byte at top of screen that the collumn is contained in\r
-; BP x pixel * 2, index into VIEWWIDTH wide tables\r
-; DS segment of the wall data to texture map\r
-; ES screenseg\r
-; SS addressing DGROUP variables\r
-;\r
-;============================================================================\r
-\r
-PROC ScaleWalls\r
-PUBLIC ScaleWalls\r
-USES SI,DI,BP\r
-\r
- xor bp,bp ; start at location 0 in the tables\r
- mov dx,GC_INDEX+1\r
- mov es,[screenseg]\r
-\r
-;\r
-; scale one collumn of data, possibly across two bytes\r
-;\r
-nextcollumn:\r
-\r
- mov bx,[wallheight+bp] ; height of walls (1-MAXSCALE)\r
- shl bx,1\r
- mov ax,[ss:scaledirectory+bx] ; segment of the compiled scaler\r
- mov [WORD PTR ss:wallscalecall+2],ax\r
-\r
- mov cx,[wallwidth+bp]\r
- or cx,cx\r
- jnz okwidth\r
- mov cx,2\r
- jmp next\r
-\r
-okwidth:\r
- shl cx,1\r
- mov ds,[wallseg+bp]\r
- mov si,[wallofs+bp]\r
-\r
- mov di,[screenbyte+bp] ; byte at the top of the scaled collumn\r
- add di,[ss:bufferofs] ; offset of current page flip\r
- mov bx,[screenbit+bp] ; 0-7 << 4\r
- add bx,cx\r
- mov ax,[ss:bitmasks-2+bx]\r
- out dx,al ; set bit mask register\r
- call [DWORD PTR ss:wallscalecall] ; scale the line of pixels\r
- or ah,ah ; is there anything in the second byte?\r
- jnz secondbyte\r
-;\r
-; next\r
-;\r
-next:\r
- add bp,cx\r
- cmp bp,VIEWWIDTH*2\r
- jb nextcollumn\r
- jmp done\r
-\r
-;\r
-; draw a second byte for vertical strips that cross two bytes\r
-;\r
-secondbyte:\r
- mov al,ah\r
- inc di ; next byte over\r
- out dx,al ; set bit mask register\r
- call [DWORD PTR ss:wallscalecall] ; scale the line of pixels\r
-;\r
-; next\r
-;\r
- add bp,cx\r
- cmp bp,VIEWWIDTH*2\r
- jb nextcollumn\r
-\r
-done:\r
- mov ax,ss\r
- mov ds,ax\r
- ret\r
-\r
-ENDP\r
-\r
-;---------------------------------------------------------------------------\r
-;\r
-; RadarBlip()\r
-;\r
-; Displays a 'blip' (1 pixel wide X 2 pixel high) on the radar at\r
-; an (X,Y) relative to (RADAR_X,RADAR_Y) (defined below...)\r
-;\r
-;---------------------------------------------------------------------------\r
-\r
-PROC RadarBlip x:WORD, y:WORD, color:WORD\r
-USES SI,DI\r
-PUBLIC RadarBlip\r
-\r
- mov ax,[screenseg]\r
-\r
- mov es,ax\r
- xor di,di\r
-\r
- lea si,[ylookup]\r
- add si,[y]\r
- add si,[y]\r
- add di,[si]\r
-\r
- mov ax,[x]\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add di,ax\r
-\r
- mov ax,[x]\r
- and ax,7\r
- mov cl,al\r
- mov ah,080h\r
- shr ah,cl\r
- cli\r
- mov al,GC_BITMASK\r
- mov dx,GC_INDEX\r
- out dx,ax\r
- sti\r
-\r
- mov ax,[color]\r
- mov ah,[es:di] ; read into latches\r
- mov [es:di],al ; write latches / color bit\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-END\r
-\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// C3_DEBUG.C\r
-\r
-#include "DEF.H"\r
-#include "gelib.h"\r
-#pragma hdrstop\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define DEBUG_OVERHEAD 0\r
-\r
-\r
-#define VIEWTILEX 20\r
-#define VIEWTILEY (VIEWHEIGHT/16)\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-short colordelay=0;\r
-boolean autofire=false;\r
-int maporgx;\r
-int maporgy;\r
-enum {mapview,tilemapview,actoratview,visview,mapseg2,lastview} viewtype;\r
-\r
-void ViewMap (void);\r
-\r
-//===========================================================================\r
-\r
-#if 0\r
-/*\r
-================\r
-=\r
-= PicturePause\r
-=\r
-================\r
-*/\r
-\r
-void PicturePause (void)\r
-{\r
- int y;\r
- unsigned source;\r
-\r
- source = displayofs+panadjust;\r
-\r
-// VW_ColorBorder (15);\r
- VW_SetLineWidth (40);\r
- VW_SetScreen (0,0);\r
-\r
- if (source<0x10000l-200*64)\r
- {\r
- //\r
- // copy top line first\r
- //\r
- for (y=0;y<200;y++)\r
- VW_ScreenToScreen (source+y*64,y*40,40,1);\r
- }\r
- else\r
- {\r
- //\r
- // copy bottom line first\r
- //\r
- for (y=199;y>=0;y--)\r
- VW_ScreenToScreen (source+y*64,y*40,40,1);\r
- }\r
-\r
- IN_Shutdown ();\r
-\r
- VW_WaitVBL(70);\r
- bioskey(0);\r
- VW_WaitVBL(70);\r
- Quit (NULL);\r
-}\r
-#endif\r
-\r
-\r
-//===========================================================================\r
-\r
-//===========================================================================\r
-\r
-#define sc_1 0x02\r
-#define sc_2 0x03\r
-#define sc_3 0x04\r
-#define sc_4 0x05\r
-#define sc_5 0x06\r
-#define sc_6 0x07\r
-#define sc_7 0x08\r
-#define sc_8 0x09\r
-#define sc_9 0x0a\r
-#define sc_0 0x0b\r
-\r
-\r
-\r
-/*\r
-================\r
-=\r
-= DebugKeys\r
-=\r
-================\r
-*/\r
-\r
-int DebugKeys (void)\r
-{\r
- boolean esc;\r
- int level,i;\r
-\r
-#if DEBUG_KEYS_AVAILABLE\r
- if (Keyboard[sc_R])\r
- {\r
- CenterWindow (12,2);\r
- if (autofire)\r
- US_PrintCentered ("Rapid-Fire OFF");\r
- else\r
- US_PrintCentered ("Rapid-Fire ON");\r
- VW_UpdateScreen();\r
- IN_Ack();\r
- autofire ^= 1;\r
- return 1;\r
- }\r
-#endif\r
-\r
-#if DEBUG_KEYS_AVAILABLE\r
- if (Keyboard[sc_A])\r
- {\r
- char levelstr[50];\r
- unsigned org_tile,org_mapon,msgnum;\r
- boolean newmsg=true,newlevel=false;\r
-\r
- VW_FixRefreshBuffer ();\r
- CenterWindow (16,3);\r
- US_Print("\n");\r
- US_CPrint("Message Test");\r
- VW_UpdateScreen();\r
-\r
- org_mapon = mapon;\r
- msgnum = (org_tile = *(mapsegs[0]+farmapylookup[player->tiley]+player->tilex))-NAMESTART;\r
- while (1)\r
- {\r
- // Get outta' here\r
- //\r
- if (Keyboard[sc_Escape])\r
- {\r
- while (Keyboard[sc_Escape]);\r
- break;\r
- }\r
-\r
- // Move to previous message\r
- //\r
- if (Keyboard[sc_UpArrow])\r
- {\r
- if (msgnum)\r
- {\r
- msgnum--;\r
- newmsg = true;\r
- }\r
- }\r
-\r
- // Move to next message\r
- //\r
- if (Keyboard[sc_DownArrow])\r
- {\r
- if (msgnum < 24)\r
- {\r
- msgnum++;\r
- newmsg = true;\r
- }\r
- }\r
-\r
- // Move to previous level\r
- //\r
- if (Keyboard[sc_LeftArrow])\r
- {\r
- if (mapon)\r
- {\r
- MM_SetPurge(&grsegs[LEVEL1TEXT+mapon],3);\r
- mapon--;\r
- newlevel = true;\r
- }\r
- }\r
-\r
- // Move to next level\r
- //\r
- if (Keyboard[sc_RightArrow])\r
- {\r
- if (mapon < LASTMAP-1)\r
- {\r
- MM_SetPurge(&grsegs[LEVEL1TEXT+mapon],3);\r
- mapon++;\r
- newlevel = true;\r
- }\r
- }\r
-\r
- // Load new level text\r
- //\r
- if (newlevel)\r
- {\r
- CA_CacheGrChunk(LEVEL1TEXT+mapon);\r
- ScanText();\r
- newmsg = true;\r
- newlevel=false;\r
- }\r
-\r
- // Display new message text\r
- //\r
- if (newmsg)\r
- {\r
- *(mapsegs[0]+farmapylookup[player->tiley]+player->tilex) = msgnum+NAMESTART;\r
- DrawText(true);\r
- strcpy(levelstr,"Level: ");\r
- itoa(mapon,levelstr+strlen(levelstr),10);\r
- strcat(levelstr," Msg: ");\r
- itoa(msgnum,levelstr+strlen(levelstr),10);\r
- DisplaySMsg(levelstr,NULL);\r
- newmsg = false;\r
-\r
- if (Keyboard[sc_UpArrow] || Keyboard[sc_DownArrow] || Keyboard[sc_LeftArrow] || Keyboard[sc_RightArrow])\r
- VW_WaitVBL(6);\r
- }\r
-\r
- }\r
-// Restore game\r
-//\r
- MM_SetPurge(&grsegs[LEVEL1TEXT+mapon],3);\r
- mapon = org_mapon;\r
- CA_CacheGrChunk(LEVEL1TEXT+mapon);\r
- ScanText();\r
- *(mapsegs[0]+farmapylookup[player->tiley]+player->tilex) = org_tile;\r
- DrawText(true);\r
- status_flag = 0;\r
- }\r
-\r
-\r
- if (Keyboard[sc_V])\r
- {\r
- displayofs = bufferofs = screenloc[screenpage];\r
- CenterWindow (16,4);\r
- US_CPrint("\n"GAMENAME);\r
- US_CPrint(VERSION);\r
- US_CPrint(REVISION);\r
- VW_UpdateScreen();\r
- IN_Ack ();\r
- }\r
-\r
-\r
- if (Keyboard[sc_Q]) // Q = Insta-Quit!\r
- Quit("Insta-Quit!");\r
-\r
- if (Keyboard[sc_Z]) // Z = freeze Time\r
- {\r
- if (FreezeTime)\r
- FreezeTime = 1; // Allow refresh to dec to zero..\r
- else\r
- StopTime();\r
-\r
- IN_Ack();\r
- return 1;\r
- }\r
-#endif\r
-\r
-\r
-// if (Keyboard[sc_E])\r
-// FaceDoor((player->x>>16l)+1,(player->y>>16l));\r
-// FaceAngle(90);\r
-\r
-#if 0\r
- if (Keyboard[sc_B]) // B = border color\r
- {\r
- CenterWindow(24,3);\r
- PrintY+=6;\r
- US_Print(" Border color (0-15):");\r
- VW_UpdateScreen();\r
- esc = !US_LineInput (px,py,str,NULL,true,2,0);\r
- if (!esc)\r
- {\r
- level = atoi (str);\r
- if (level>=0 && level<=15)\r
- VW_ColorBorder (level);\r
- }\r
- return 1;\r
- }\r
-#endif\r
-\r
-\r
-#if 1//DEBUG_KEYS_AVAILABLE\r
- if (Keyboard[sc_O])\r
- {\r
- extern unsigned objectcount,latchmemavail;\r
- unsigned unused,total;\r
-\r
- CenterWindow (30,13);\r
- US_Print ("Objects: ");\r
- US_PrintUnsigned (objectcount);\r
-\r
- US_Print("\n\nTics: ");\r
- US_PrintUnsigned (tics);\r
- US_Print(" Real Tics: ");\r
- US_PrintUnsigned(realtics);\r
-\r
- US_Print ("\n\n Total Available: ");\r
- US_PrintUnsigned (mminfo.mainmem/1024);\r
- US_Print ("k\n Mem In Use: ");\r
- unused=MM_UnusedMemory()/1024;\r
- US_PrintUnsigned (unused);\r
- US_Print ("k\n Mem After Purge: ");\r
- total=MM_TotalFree()/1024;\r
- US_PrintUnsigned (total);\r
- US_Print ("k (");\r
- US_PrintUnsigned (total-unused);\r
-\r
- US_Print (")\n\nLatch Mem Free: ");\r
- US_PrintUnsigned (latchmemavail);\r
- US_Print ("\n");\r
- VW_UpdateScreen();\r
- IN_Ack();\r
- }\r
-\r
- if (colordelay<1)\r
- {\r
- if (Keyboard[26])\r
- {\r
- extern unsigned *groundcolor,debug_gnd;\r
-\r
- groundcolor = &debug_gnd;\r
- debug_gnd += 0x0101;\r
- if (debug_gnd == 0x1010)\r
- debug_gnd = 0;\r
- colordelay = 10;\r
- }\r
-\r
- if (Keyboard[27])\r
- {\r
- extern unsigned *skycolor,debug_sky;\r
-\r
- skycolor = &debug_sky;\r
- debug_sky += 0x0101;\r
- if (debug_sky == 0x1010)\r
- debug_sky = 0;\r
- colordelay = 10;\r
- }\r
- }\r
- else\r
- colordelay -= realtics;\r
-#endif\r
-\r
-\r
-#if 0\r
- if (Keyboard[sc_C]) // C = count objects\r
- {\r
- CountObjects();\r
- return 1;\r
- }\r
-\r
-\r
- if (Keyboard[sc_D]) // D = start / end demo record\r
- {\r
- if (DemoMode == demo_Off)\r
- StartDemoRecord ();\r
- else if (DemoMode == demo_Record)\r
- {\r
- EndDemoRecord ();\r
- playstate = ex_completed;\r
- }\r
- return 1;\r
- }\r
-#endif\r
-\r
-#if 0\r
- if (Keyboard[sc_E]) // E = quit level\r
- {\r
- if (tedlevel)\r
- TEDDeath();\r
- playstate = ex_warped;\r
- gamestate.mapon++;\r
- }\r
-#endif\r
-\r
-#if 0\r
- if (Keyboard[sc_F]) // F = facing spot\r
- {\r
- CenterWindow (12,4);\r
- US_Print ("X:");\r
- US_PrintUnsigned (player->x);\r
- US_Print ("Y:");\r
- US_PrintUnsigned (player->y);\r
- US_Print ("A:");\r
- US_PrintUnsigned (player->angle);\r
- VW_UpdateScreen();\r
- IN_Ack();\r
- return 1;\r
- }\r
-#endif\r
-\r
- if (Keyboard[sc_G]) // G = god mode\r
- {\r
- CenterWindow (12,2);\r
- if (godmode)\r
- US_PrintCentered ("God mode OFF");\r
- else\r
- US_PrintCentered ("God mode ON");\r
- VW_UpdateScreen();\r
- IN_Ack();\r
- godmode ^= 1;\r
- return 1;\r
- }\r
-\r
-#if 0\r
- if (Keyboard[sc_H]) // H = hurt self\r
- {\r
- TakeDamage (5);\r
- }\r
-#endif\r
-\r
- if (Keyboard[sc_I]) // I = item cheat\r
- {\r
- extern boolean redraw_gems;\r
-\r
- CenterWindow (12,3);\r
- US_PrintCentered ("Free items!");\r
- VW_UpdateScreen();\r
- for (i=0;i<4;i++)\r
- {\r
- GiveBolt ();\r
- GiveNuke ();\r
- GivePotion ();\r
-// if (!gamestate.keys[i])\r
- GiveKey (i);\r
- gamestate.gems[i] = GEM_DELAY_TIME;\r
- }\r
- gamestate.gems[4] = GEM_DELAY_TIME;\r
- redraw_gems = true;\r
-///////// for (i=0;i<8;i++)\r
-///////// GiveScroll (i,false);\r
-\r
- IN_Ack ();\r
- return 1;\r
- }\r
-\r
-#if DEBUG_OVERHEAD\r
- if (Keyboard[sc_Z]) // O is used elsewhere...\r
- {\r
- ViewMap();\r
- return 1;\r
- }\r
-#endif\r
-\r
-#if 0\r
- if (Keyboard[sc_P]) // P = pause with no screen disruptioon\r
- {\r
- PicturePause ();\r
- return 1;\r
- }\r
-#endif\r
-\r
-#if 0\r
- if (Keyboard[sc_S]) // S = slow motion\r
- {\r
- singlestep^=1;\r
- CenterWindow (18,3);\r
- if (singlestep)\r
- US_PrintCentered ("Slow motion ON");\r
- else\r
- US_PrintCentered ("Slow motion OFF");\r
- VW_UpdateScreen();\r
- IN_Ack ();\r
- return 1;\r
- }\r
-#endif\r
-\r
-#if 0\r
- if (Keyboard[sc_V]) // V = extra VBLs\r
- {\r
- CenterWindow(30,3);\r
- PrintY+=6;\r
- US_Print(" Add how many extra VBLs(0-8):");\r
- VW_UpdateScreen();\r
- esc = !US_LineInput (px,py,str,NULL,true,2,0);\r
- if (!esc)\r
- {\r
- level = atoi (str);\r
- if (level>=0 && level<=8)\r
- extravbls = level;\r
- }\r
- return 1;\r
- }\r
-#endif\r
-\r
- if (Keyboard[sc_W]) // W = warp to level\r
- {\r
- CenterWindow(26,3);\r
- PrintY+=6;\r
- US_Print(" Warp to which level(0-16):");\r
- VW_UpdateScreen();\r
- esc = !US_LineInput (px,py,str,NULL,true,2,0);\r
- if (!esc)\r
- {\r
- level = atoi (str);\r
- if (level>=0 && level<=LASTMAP-1)\r
- {\r
- gamestate.mapon = level;\r
- playstate = ex_warped;\r
- lasttext = -1;\r
- }\r
- }\r
- return 1;\r
- }\r
-\r
-#if 0\r
- if (Keyboard[sc_X]) // X = item cheat\r
- {\r
- CenterWindow (12,3);\r
- US_PrintCentered ("Extra stuff!");\r
- VW_UpdateScreen();\r
- for (i=0;i<4;i++)\r
- {\r
- GiveBolt ();\r
- GiveNuke ();\r
- GivePotion ();\r
- }\r
- IN_Ack ();\r
- return 1;\r
- }\r
-#endif\r
-\r
-//////// if (LastScan >= sc_1 && LastScan <= sc_8) // free scrolls\r
-//////// {\r
-//////// GiveScroll (LastScan-sc_1,false);\r
-//////// IN_ClearKeysDown ();\r
-//////// }\r
-\r
- return 0;\r
-}\r
-\r
-\r
-#if DEBUG_OVERHEAD\r
-\r
-/*\r
-=====================\r
-=\r
-= LatchDrawChar\r
-=\r
-=====================\r
-*/\r
-\r
-void LatchDrawChar (unsigned x, unsigned y, unsigned picnum)\r
-{\r
- unsigned source, dest;\r
-\r
- dest = bufferofs + ylookup[y]+x;\r
- source = latchpics[0]+picnum*8;\r
-\r
- EGAWRITEMODE(1);\r
- EGAMAPMASK(15);\r
-\r
-asm mov bx,[linewidth]\r
-asm dec bx\r
-\r
-asm mov ax,[screenseg]\r
-asm mov es,ax\r
-asm mov ds,ax\r
-\r
-asm mov si,[source]\r
-asm mov di,[dest]\r
-\r
-asm movsb\r
-asm add di,bx\r
-asm movsb\r
-asm add di,bx\r
-asm movsb\r
-asm add di,bx\r
-asm movsb\r
-asm add di,bx\r
-asm movsb\r
-asm add di,bx\r
-asm movsb\r
-asm add di,bx\r
-asm movsb\r
-asm add di,bx\r
-asm movsb\r
-\r
-asm mov ax,ss\r
-asm mov ds,ax // restore turbo's data segment\r
-\r
- EGAWRITEMODE(0);\r
-}\r
-\r
-#endif\r
-\r
-\r
-#if DEBUG_OVERHEAD\r
-/*\r
-=====================\r
-=\r
-= LatchDrawTile\r
-=\r
-=====================\r
-*/\r
-\r
-void LatchDrawTile (unsigned x, unsigned y, unsigned picnum)\r
-{\r
- unsigned source, dest;\r
-\r
- dest = bufferofs + ylookup[y]+x;\r
- source = tileoffsets[picnum];\r
-\r
- EGAWRITEMODE(1);\r
- EGAMAPMASK(15);\r
-\r
-asm mov bx,[linewidth]\r
-asm sub bx,2\r
-\r
-asm mov ax,[screenseg]\r
-asm mov es,ax\r
-asm mov ds,ax\r
-\r
-asm mov si,[source]\r
-asm mov di,[dest]\r
-asm mov dx,16\r
-\r
-lineloop:\r
-asm movsb\r
-asm movsb\r
-asm add di,bx\r
-\r
-asm dec dx\r
-asm jnz lineloop\r
-\r
-asm mov ax,ss\r
-asm mov ds,ax // restore turbo's data segment\r
-\r
- EGAWRITEMODE(0);\r
-}\r
-#endif\r
-\r
-\r
-#if DEBUG_OVERHEAD\r
-/*\r
-===================\r
-=\r
-= OverheadRefresh\r
-=\r
-===================\r
-*/\r
-\r
-void OverheadRefresh (void)\r
-{\r
- unsigned x,y,endx,endy,sx,sy;\r
- unsigned tile;\r
-\r
-\r
- if (++screenpage == 3)\r
- screenpage = 0;\r
-\r
- bufferofs = screenloc[screenpage];\r
-\r
- endx = maporgx+VIEWTILEX;\r
- endy = maporgy+VIEWTILEY;\r
-\r
- for (y=maporgy;y<endy;y++)\r
- for (x=maporgx;x<endx;x++)\r
- {\r
- sx = (x-maporgx)*2;\r
- sy = (y-maporgy)*16;\r
-\r
- switch (viewtype)\r
- {\r
- case mapview:\r
- tile = *(mapsegs[0]+farmapylookup[y]+x);\r
- break;\r
-\r
- case tilemapview:\r
- tile = tilemap[x][y];\r
- break;\r
-\r
- case actoratview:\r
- tile = (unsigned)actorat[x][y];\r
- break;\r
-\r
- case visview:\r
- tile = spotvis[x][y];\r
- break;\r
-\r
- case mapseg2:\r
- tile = *(mapsegs[2]+farmapylookup[y]+x);\r
- if (tile < 256)\r
- tile = *(mapsegs[0]+farmapylookup[y]+x);\r
- break;\r
-\r
- }\r
-\r
- if (tile<NUMTILE16)\r
- LatchDrawTile(sx,sy,tile);\r
- else\r
- {\r
- LatchDrawChar(sx,sy,NUMBERCHARS+((tile&0xf000)>>12));\r
- LatchDrawChar(sx+1,sy,NUMBERCHARS+((tile&0x0f00)>>8));\r
- LatchDrawChar(sx,sy+8,NUMBERCHARS+((tile&0x00f0)>>4));\r
- LatchDrawChar(sx+1,sy+8,NUMBERCHARS+(tile&0x000f));\r
- }\r
- }\r
-\r
- VW_SetScreen (bufferofs,0);\r
- displayofs = bufferofs;\r
-}\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= ViewMap\r
-=\r
-===================\r
-*/\r
-\r
-void ViewMap (void)\r
-{\r
- boolean button0held;\r
-\r
- viewtype = actoratview;\r
- button0held = false;\r
-\r
-\r
- maporgx = player->tilex - VIEWTILEX/2;\r
- if (maporgx<0)\r
- maporgx = 0;\r
- maporgy = player->tiley - VIEWTILEY/2;\r
- if (maporgy<0)\r
- maporgy = 0;\r
-\r
- do\r
- {\r
-//\r
-// let user pan around\r
-//\r
- IN_ReadControl(0,&control);\r
- if (control.xaxis == -1 && maporgx>0)\r
- maporgx--;\r
- if (control.xaxis == 1 && maporgx<mapwidth-VIEWTILEX)\r
- maporgx++;\r
- if (control.yaxis == -1 && maporgy>0)\r
- maporgy--;\r
- if (control.yaxis == 1 && maporgy<mapheight-VIEWTILEY)\r
- maporgy++;\r
-\r
- if (control.button0 && !button0held)\r
- {\r
- button0held = true;\r
- viewtype++;\r
- if (viewtype==lastview)\r
- viewtype = mapview;\r
- }\r
- if (!control.button0)\r
- button0held = false;\r
-\r
-\r
- OverheadRefresh ();\r
-\r
- } while (!Keyboard[sc_Escape]);\r
-\r
- IN_ClearKeysDown ();\r
- DrawPlayScreen ();\r
-}\r
-#endif\r
-\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// C3_DRAW.C\r
-\r
-#include "DEF.H"\r
-#pragma hdrstop\r
-\r
-//#define DRAWEACH // draw walls one at a time for debugging\r
-\r
-unsigned highest;\r
-unsigned mostwalls,numwalls;\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define PI 3.141592657\r
-#define ANGLEQUAD (ANGLES/4)\r
-\r
-unsigned oldend;\r
-\r
-#define FINEANGLES 3600\r
-\r
-#define MINRATIO 16\r
-\r
-\r
-const unsigned MAXSCALEHEIGHT = (VIEWWIDTH/2);\r
-const unsigned MAXVISHEIGHT = (VIEWHEIGHT/2);\r
-const unsigned BASESCALE = 32;\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-//\r
-// calculate location of screens in video memory so they have the\r
-// maximum possible distance seperating them (for scaling overflow)\r
-//\r
-\r
-unsigned screenloc[3]= {PAGE1START,PAGE2START,PAGE3START};\r
-unsigned freelatch = FREESTART;\r
-\r
-boolean fizzlein;\r
-\r
-long scaleshapecalll;\r
-long scaletablecall;\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-long bytecount,endcount; // for profiling\r
-int animframe;\r
-int pixelangle[VIEWWIDTH];\r
-int far finetangent[FINEANGLES+1];\r
-int fineviewangle;\r
-unsigned viewxpix,viewypix;\r
-\r
-/*\r
-============================================================================\r
-\r
- 3 - D DEFINITIONS\r
-\r
-============================================================================\r
-*/\r
-\r
-fixed tileglobal = TILEGLOBAL;\r
-fixed focallength = FOCALLENGTH;\r
-fixed mindist = MINDIST;\r
-int viewheight = VIEWHEIGHT;\r
-fixed scale;\r
-\r
-\r
-tilept tile,lasttile, // tile of wall being followed\r
- focal, // focal point in tiles\r
- left,mid,right; // rightmost tile in view\r
-\r
-globpt edge,view;\r
-\r
-int segstart[VIEWHEIGHT], // addline tracks line segment and draws\r
- segend[VIEWHEIGHT],\r
- segcolor[VIEWHEIGHT]; // only when the color changes\r
-\r
-\r
-walltype walls[MAXWALLS],*leftwall,*rightwall;\r
-\r
-\r
-//==========================================================================\r
-\r
-//\r
-// refresh stuff\r
-//\r
-\r
-int screenpage;\r
-\r
-long lasttimecount;\r
-\r
-//\r
-// rendering stuff\r
-//\r
-\r
-int firstangle,lastangle;\r
-\r
-fixed prestep;\r
-\r
-fixed sintable[ANGLES+ANGLES/4],*costable = sintable+(ANGLES/4);\r
-\r
-fixed viewx,viewy; // the focal point\r
-int viewangle;\r
-fixed viewsin,viewcos;\r
-\r
-int zbuffer[VIEWXH+1]; // holds the height of the wall at that point\r
-\r
-//==========================================================================\r
-\r
-void DrawLine (int xl, int xh, int y,int color);\r
-void DrawWall (walltype *wallptr);\r
-void TraceRay (unsigned angle);\r
-fixed FixedByFrac (fixed a, fixed b);\r
-fixed FixedAdd (void);\r
-fixed TransformX (fixed gx, fixed gy);\r
-int FollowTrace (fixed tracex, fixed tracey, long deltax, long deltay, int max);\r
-int BackTrace (int finish);\r
-void ForwardTrace (void);\r
-int TurnClockwise (void);\r
-int TurnCounterClockwise (void);\r
-void FollowWall (void);\r
-\r
-void NewScene (void);\r
-void BuildTables (void);\r
-\r
-//==========================================================================\r
-\r
-\r
-#if 0\r
-/*\r
-==================\r
-=\r
-= DrawLine\r
-=\r
-= Must be in write mode 2 with all planes enabled\r
-= The bit mask is left set to the end value, so clear it after all lines are\r
-= drawn\r
-=\r
-= draws a black dot at the left edge of the line\r
-=\r
-==================\r
-*/\r
-\r
-unsigned static char dotmask[8] = {0x80,0x40,0x20,0x10,8,4,2,1};\r
-unsigned static char leftmask[8] = {0xff,0x7f,0x3f,0x1f,0xf,7,3,1};\r
-unsigned static char rightmask[8] = {0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff};\r
-\r
-void DrawLine (int xl, int xh, int y,int color)\r
-{\r
- unsigned dest,xlp,xlb,xhb,maskleft,maskright,maskdot,mid;\r
-\r
- xlb=xl/8;\r
- xhb=xh/8;\r
-\r
- if (xh<xl)\r
- Quit("DrawLine: xh<xl");\r
- if (y<VIEWY)\r
- Quit("DrawLine: y<VIEWY");\r
- if (y>VIEWYH)\r
- Quit("DrawLine: y>VIEWYH");\r
-\r
- xlp = xl&7;\r
- maskleft = leftmask[xlp];\r
- maskright = rightmask[xh&7];\r
-\r
- mid = xhb-xlb-1;\r
- dest = bufferofs+ylookup[y]+xlb;\r
-\r
- //\r
- // set the GC index register to point to the bit mask register\r
- //\r
- asm mov al,GC_BITMASK\r
- asm mov dx,GC_INDEX\r
- asm out dx,al\r
-\r
- if (xlb==xhb)\r
- {\r
- //\r
- // entire line is in one byte\r
- //\r
-\r
- maskleft&=maskright;\r
-\r
- asm mov es,[screenseg]\r
- asm mov di,[dest]\r
- asm mov dx,GC_INDEX+1\r
-\r
- asm mov al,[BYTE PTR maskleft]\r
- asm out dx,al // mask off pixels\r
-\r
- asm mov al,[BYTE PTR color]\r
- asm xchg al,[es:di] // load latches and write pixels\r
-\r
- return;\r
- }\r
-\r
-asm mov es,[screenseg]\r
-asm mov di,[dest]\r
-asm mov dx,GC_INDEX+1\r
-asm mov bh,[BYTE PTR color]\r
-\r
-//\r
-// draw left side\r
-//\r
-asm mov al,[BYTE PTR maskleft]\r
-asm out dx,al // mask off pixels\r
-\r
-asm mov al,bh\r
-asm xchg al,[es:di] // load latches and write pixels\r
-asm inc di\r
-\r
-//\r
-// draw middle\r
-//\r
-asm mov al,255\r
-asm out dx,al // no masking\r
-\r
-asm mov al,bh\r
-asm mov cx,[mid]\r
-asm rep stosb\r
-\r
-//\r
-// draw right side\r
-//\r
-asm mov al,[BYTE PTR maskright]\r
-asm out dx,al // mask off pixels\r
-asm xchg bh,[es:di] // load latches and write pixels\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-void DrawLineDot (int xl, int xh, int y,int color)\r
-{\r
- unsigned dest,xlp,xlb,xhb,maskleft,maskright,maskdot,mid;\r
-\r
- xlb=xl/8;\r
- xhb=xh/8;\r
-\r
- if (xh<xl)\r
- Quit("DrawLine: xh<xl");\r
- if (y<VIEWY)\r
- Quit("DrawLine: y<VIEWY");\r
- if (y>VIEWYH)\r
- Quit("DrawLine: y>VIEWYH");\r
-\r
- xlp = xl&7;\r
- maskdot = dotmask[xlp];\r
- maskleft = leftmask[xlp];\r
- maskright = rightmask[xh&7];\r
-\r
- mid = xhb-xlb-1;\r
- dest = bufferofs+ylookup[y]+xlb;\r
-\r
- //\r
- // set the GC index register to point to the bit mask register\r
- //\r
- asm mov al,GC_BITMASK\r
- asm mov dx,GC_INDEX\r
- asm out dx,al\r
-\r
- if (xlb==xhb)\r
- {\r
- //\r
- // entire line is in one byte\r
- //\r
-\r
- maskleft&=maskright;\r
-\r
- asm mov es,[screenseg]\r
- asm mov di,[dest]\r
- asm mov dx,GC_INDEX+1\r
-\r
- asm mov al,[BYTE PTR maskleft]\r
- asm out dx,al // mask off pixels\r
-\r
- asm mov al,[BYTE PTR color]\r
- asm xchg al,[es:di] // load latches and write pixels\r
-\r
-\r
- //\r
- // write the black dot at the start\r
- //\r
- asm mov al,[BYTE PTR maskdot]\r
- asm out dx,al // mask off pixels\r
-\r
- asm xor al,al\r
- asm xchg al,[es:di] // load latches and write pixels\r
-\r
-\r
- return;\r
- }\r
-\r
-asm mov es,[screenseg]\r
-asm mov di,[dest]\r
-asm mov dx,GC_INDEX+1\r
-asm mov bh,[BYTE PTR color]\r
-\r
-//\r
-// draw left side\r
-//\r
-asm mov al,[BYTE PTR maskleft]\r
-asm out dx,al // mask off pixels\r
-\r
-asm mov al,bh\r
-asm xchg al,[es:di] // load latches and write pixels\r
-\r
-//\r
-// write the black dot at the start\r
-//\r
-asm mov al,[BYTE PTR maskdot]\r
-asm out dx,al // mask off pixels\r
-asm xor al,al\r
-asm xchg al,[es:di] // load latches and write pixels\r
-asm inc di\r
-\r
-//\r
-// draw middle\r
-//\r
-asm mov al,255\r
-asm out dx,al // no masking\r
-\r
-asm mov al,bh\r
-asm mov cx,[mid]\r
-asm rep stosb\r
-\r
-//\r
-// draw right side\r
-//\r
-asm mov al,[BYTE PTR maskright]\r
-asm out dx,al // mask off pixels\r
-asm xchg bh,[es:di] // load latches and write pixels\r
-\r
-}\r
-\r
-#endif\r
-\r
-//==========================================================================\r
-\r
-\r
-long wallscalesource;\r
-\r
-#ifdef DRAWEACH\r
-/*\r
-====================\r
-=\r
-= ScaleOneWall\r
-=\r
-====================\r
-*/\r
-\r
-void near ScaleOneWall (int xl, int xh)\r
-{\r
- int x,pixwidth,height;\r
-\r
- *(((unsigned *)&wallscalesource)+1) = wallseg[xl];\r
-\r
- for (x=xl;x<=xh;x+=pixwidth)\r
- {\r
- height = wallheight[x];\r
- pixwidth = wallwidth[x];\r
- (unsigned)wallscalesource = wallofs[x];\r
-\r
- *(((unsigned *)&scaletablecall)+1) = (unsigned)scaledirectory[height];\r
- (unsigned)scaletablecall = scaledirectory[height]->codeofs[0];\r
-\r
- //\r
- // scale a byte wide strip of wall\r
- //\r
- asm mov bx,[x]\r
- asm mov di,bx\r
- asm shr di,1\r
- asm shr di,1\r
- asm shr di,1 // X in bytes\r
- asm add di,[bufferofs]\r
- asm and bx,7\r
- asm shl bx,1\r
- asm shl bx,1\r
- asm shl bx,1\r
- asm add bx,[pixwidth] // bx = pixel*8+pixwidth-1\r
- asm dec bx\r
- asm mov al,BYTE PTR [bitmasks1+bx]\r
- asm mov dx,GC_INDEX+1\r
- asm out dx,al // set bit mask register\r
- asm mov es,[screenseg]\r
- asm lds si,[wallscalesource]\r
- asm call [DWORD PTR ss:scaletablecall] // scale the line of pixels\r
-\r
- asm mov al,BYTE PTR [ss:bitmasks2+bx]\r
- asm or al,al\r
- asm jz nosecond\r
-\r
- //\r
- // draw a second byte for vertical strips that cross two bytes\r
- //\r
- asm inc di\r
- asm out dx,al // set bit mask register\r
- asm call [DWORD PTR ss:scaletablecall] // scale the line of pixels\r
- nosecond:\r
- asm mov ax,ss\r
- asm mov ds,ax\r
- }\r
-}\r
-\r
-#endif\r
-\r
-char wall_anim_pos[NUMFLOORS];\r
-\r
-// EAST / WEST WALLS\r
-//\r
-int far walllight1[NUMFLOORS] = {0,\r
-\r
- CRYSTAL_LIGHT_1PIC,\r
- CRYSTAL_LIGHT_2PIC,\r
- CRYSTAL_LIGHT_3PIC,\r
- CRYSTAL_LIGHT_4PIC, //4\r
-\r
- FIRE_WALL_1PIC,\r
- FIRE_WALL_2PIC,\r
- FIRE_WALL_3PIC,\r
- FIRE_WALL_4PIC, //8\r
-\r
- BRN_STONE_GATEPIC,\r
- BRN_STONE_WALL_1PIC,\r
- KUDZU_WEAK_LIGHTPIC,\r
- KUDZU_LIGHT_WALLPIC,\r
- HEDGE_WALLPIC,\r
- HEDGE_EYESPIC, //14\r
-\r
- W_GEN_DOOR1PIC, //15\r
- BRN_WINDOW_LIGHTPIC,\r
-\r
- ALTAR_LEFTPIC,\r
- ALTAR_RIGHTPIC,\r
- GRAY_LIGHT_WALLPIC,\r
- GRAY_LIGHT_SIGNPIC, //20\r
-\r
- MANICLE_LIGHT_WALLPIC,\r
- MANICLE_LIGHT_BLOODYPIC,\r
-\r
- LIGHT_CURTAIN_WINDOWPIC,\r
- LIGHT_CURTAIN_WALLPIC,\r
- BRN_LIGHT_SIGNPIC, //25\r
-\r
- LIGHT_STONE_WALLPIC,\r
-\r
- W_GEN_DOOR2PIC, //27\r
-\r
- TROLL_LIGHT_STONEPIC,\r
-\r
- BRN_FLAGSTONE_LIGHT_2PIC,\r
-\r
- W_CRYSTAL_DOORPIC,\r
-\r
- DMG_BRN_FSTN_LTPIC,\r
-\r
- RUST_METAL_LIGHTPIC,\r
- GRAY_METAL_LIGHTPIC, //33\r
-\r
- WEAK_STONE_LIGHTPIC,\r
-\r
- DMG_FIN_FSTN_LTPIC,\r
-\r
- WEAK_GRAY_RFGSTN_LIGHTPIC,\r
- 0,\r
-\r
- WEAK_CRYSTAL_LIGHTPIC,\r
-\r
- RED_MUD_LIGHTPIC,\r
-\r
- STEEL_DOOR1PIC, //40\r
-\r
- RED_MUD_WEAK_LIGHTPIC,\r
-\r
- STEEL_DOOR2PIC, //42\r
-\r
- HORN_DOORPIC,\r
- TROLL_BLOODY_LT_STONEPIC,\r
- CLOSED_DOOR_1PIC,\r
-\r
- GRY_DOOR_LTPIC, //46\r
-\r
- BRN_DOOR_LTPIC, //47\r
-\r
- GRY_FGSTN_LTPIC, //48\r
- DOOR_2PIC,\r
-\r
- WATER_LIGHT_WEAK_1PIC,\r
- WATER_LIGHT_WEAK_2PIC,\r
- WATER_LIGHT_WEAK_3PIC, //52\r
-\r
- WATER_LIGHT_1PIC,\r
- WATER_LIGHT_2PIC,\r
- WATER_LIGHT_3PIC,\r
-\r
- LIGHT_BREATH_1PIC,\r
- LIGHT_BREATH_2PIC,\r
- LIGHT_BREATH_3PIC, //58\r
-\r
- EXP_WALL_1PIC,\r
- EXP_WALL_2PIC,\r
- EXP_WALL_3PIC,\r
-\r
- WATER_EXP_WALL_1PIC,\r
- WATER_EXP_WALL_2PIC,\r
- WATER_EXP_WALL_3PIC, //64\r
-\r
- FINALWALLPIC,\r
-\r
- LT_SKEL1PIC,\r
- DK_SKEL1PIC,\r
- LT_SKEL2PIC,\r
- DK_SKEL2PIC,\r
-\r
- 0,\r
-\r
- TAP_1PIC,\r
- TAP_2PIC,\r
- TAP_3PIC,\r
- TAP_4PIC,\r
- TAP_5PIC,\r
-\r
- WATER_DOOR1_PIC,\r
- WATER_DOOR2_PIC,\r
- };\r
-\r
-// NORTH / SOUTH WALLS\r
-//\r
-int far walldark1[NUMFLOORS] = {0,\r
-\r
- CRYSTAL_DARK_1PIC,\r
- CRYSTAL_DARK_2PIC,\r
- CRYSTAL_DARK_3PIC,\r
- CRYSTAL_DARK_4PIC, //4\r
-\r
- FIRE_WALL_1PIC,\r
- FIRE_WALL_2PIC,\r
- FIRE_WALL_3PIC,\r
- FIRE_WALL_4PIC, //8\r
-\r
- BRN_STONE_GATEPIC,\r
- BRN_STONE_WALL_2PIC,\r
- KUDZU_WEAK_DARKPIC,\r
- KUDZU_DARK_WALLPIC,\r
- HEDGE_WALLPIC,\r
- HEDGE_EYESPIC, //14\r
-\r
- W_GEN_DOOR1PIC, //15\r
- BRN_WINDOW_DARKPIC,\r
-\r
- ALTAR_LEFTPIC,\r
- ALTAR_RIGHTPIC,\r
- GRAY_DARK_WALLPIC,\r
- GRAY_DARK_SIGNPIC, //20\r
-\r
- MANICLE_DARK_WALLPIC,\r
- MANICLE_DARK_BLOODYPIC,\r
-\r
- DARK_CURTAIN_WINDOWPIC,\r
- DARK_CURTAIN_WALLPIC,\r
- BRN_DARK_SIGNPIC,\r
-\r
- DARK_STONE_WALLPIC,\r
-\r
- W_GEN_DOOR2PIC, //27\r
-\r
- TROLL_DARK_STONEPIC,\r
-\r
- BRN_FLAGSTONE_DARK_2PIC,\r
-\r
- W_CRYSTAL_DOORPIC, //30\r
-\r
- DMG_BRN_FSTN_DKPIC,\r
-\r
- RUST_METAL_DARKPIC,\r
- GRAY_METAL_DARKPIC,\r
-\r
- WEAK_STONE_DARKPIC,\r
-\r
- DMG_FIN_FSTN_DKPIC, //35\r
-\r
- WEAK_GRAY_RFGSTN_DARKPIC,\r
- 0,\r
-\r
- WEAK_CRYSTAL_DARKPIC,\r
-\r
- BRN_MUD_DARKPIC,\r
-\r
- STEEL_DOOR1PIC, //40\r
-\r
- BRN_MUD_WEAK_DARKPIC,\r
-\r
- STEEL_DOOR2PIC,\r
-\r
- HORN_DOORPIC,\r
- TROLL_BLOODY_DK_STONEPIC,\r
-\r
- CLOSED_DOOR_1PIC,\r
-\r
- GRY_DOOR_DKPIC, //46\r
- BRN_DOOR_DKPIC, //47\r
- GRY_FGSTN_DKPIC, //48\r
- DOOR_2PIC,\r
-\r
- WATER_DARK_WEAK_1PIC,\r
- WATER_DARK_WEAK_2PIC,\r
- WATER_DARK_WEAK_3PIC,\r
-\r
- WATER_DARK_1PIC,\r
- WATER_DARK_2PIC,\r
- WATER_DARK_3PIC,\r
-\r
- DARK_BREATH_1PIC,\r
- DARK_BREATH_2PIC,\r
- DARK_BREATH_3PIC,\r
-\r
- EXP_WALL_1PIC,\r
- EXP_WALL_2PIC,\r
- EXP_WALL_3PIC,\r
-\r
- WATER_EXP_WALL_1PIC,\r
- WATER_EXP_WALL_2PIC,\r
- WATER_EXP_WALL_3PIC,\r
-\r
- FINALWALLPIC,\r
-\r
- LT_SKEL1PIC,\r
- DK_SKEL1PIC,\r
- LT_SKEL2PIC,\r
- DK_SKEL2PIC,\r
-\r
- 0,\r
-\r
- TAP_1PIC,\r
- TAP_2PIC,\r
- TAP_3PIC,\r
- TAP_4PIC,\r
- TAP_5PIC,\r
-\r
- WATER_DOOR1_PIC,\r
- WATER_DOOR2_PIC,\r
- };\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= DrawVWall\r
-=\r
-= Draws a wall by vertical segments, for texture mapping!\r
-=\r
-= wallptr->side is true for east/west walls (constant x)\r
-=\r
-= fracheight and fracstep are 16.16 bit fractions\r
-=\r
-=====================\r
-*/\r
-\r
-void DrawVWall (walltype *wallptr)\r
-{\r
- int x,i;\r
- unsigned source;\r
- unsigned width,sourceint;\r
- unsigned wallpic,wallpicseg;\r
- unsigned skip;\r
- long fracheight,fracstep,longheightchange;\r
- unsigned height;\r
- int heightchange;\r
- unsigned slope,distance;\r
- int traceangle,angle;\r
- int mapadd;\r
- unsigned lastpix,lastsource,lastwidth;\r
-\r
- if (wallptr->rightclip < wallptr->leftclip)\r
- Quit ("DrawVWall: Right < Left");\r
-\r
-//\r
-// setup for height calculation\r
-//\r
- wallptr->height1 >>= 1;\r
- wallptr->height2 >>= 1;\r
- wallptr->planecoord>>=10; // remove non significant bits\r
-\r
- width = wallptr->x2 - wallptr->x1;\r
- if (width)\r
- {\r
- heightchange = wallptr->height2 - wallptr->height1;\r
- asm mov ax,[heightchange]\r
- asm mov WORD PTR [longheightchange+2],ax\r
- asm mov WORD PTR [longheightchange],0 // avoid long shift by 16\r
- fracstep = longheightchange/width;\r
- }\r
-\r
- fracheight = ((long)wallptr->height1<<16)+0x8000;\r
- skip = wallptr->leftclip - wallptr->x1;\r
- if (skip)\r
- fracheight += fracstep*skip;\r
-\r
-//\r
-// setup for texture mapping\r
-//\r
-// mapadd is 64*64 (to keep source positive) + the origin wall intercept\r
-// distance has 6 unit bits, and 6 frac bits\r
-// traceangle is the center view angle in FINEANGLES, moved to be in\r
-// the +-90 degree range (to thew right of origin)\r
-//\r
- traceangle = fineviewangle;\r
- //\r
- // find wall picture to map from\r
- //\r
- if (wallptr->side)\r
- { // east or west wall\r
-\r
- wallpic = walllight1[wallptr->color+wall_anim_pos[wallptr->color]];\r
- if (wallptr->planecoord < viewxpix)\r
- {\r
- distance = viewxpix-wallptr->planecoord;\r
- traceangle -= FINEANGLES/2;\r
- mapadd = (64-viewypix&63); // the pixel spot of the origin\r
- }\r
- else\r
- {\r
- distance = wallptr->planecoord-viewxpix;\r
- // traceangle is correct\r
- mapadd = viewypix&63; // the pixel spot of the origin\r
- }\r
- }\r
- else\r
- { // north or south wall\r
-\r
- wallpic = walldark1[wallptr->color+wall_anim_pos[wallptr->color]];\r
- if (wallptr->planecoord < viewypix)\r
- {\r
- distance = viewypix-wallptr->planecoord;\r
- traceangle -= FINEANGLES/4;\r
- mapadd = viewxpix&63; // the pixel spot of the origin\r
- }\r
- else\r
- {\r
- distance = wallptr->planecoord-viewypix;\r
- traceangle -= FINEANGLES*3/4;\r
- mapadd = (64-viewxpix&63); // the pixel spot of the origin\r
- }\r
- }\r
-\r
- mapadd = 64*64-mapadd; // make sure it stays positive\r
-\r
- wallpicseg = (unsigned)walldirectory[wallpic-FIRSTWALLPIC];\r
- if (traceangle > FINEANGLES/2)\r
- traceangle -= FINEANGLES;\r
-\r
-//\r
-// calculate everything\r
-//\r
-// IMPORTANT! This loop is executed around 5000 times / second!\r
-//\r
- lastpix = lastsource = (unsigned)-1;\r
-\r
- for (x = wallptr->leftclip ; x <= wallptr->rightclip ; x++)\r
- {\r
- //\r
- // height\r
- //\r
- asm mov ax,WORD PTR [fracheight]\r
- asm mov dx,WORD PTR [fracheight+2]\r
- asm mov cx,dx\r
- asm add ax,WORD PTR [fracstep]\r
- asm adc dx,WORD PTR [fracstep+2]\r
- asm mov WORD PTR [fracheight],ax\r
- asm mov WORD PTR [fracheight+2],dx\r
- asm mov bx,[x]\r
- asm shl bx,1\r
- asm cmp cx,MAXSCALEHEIGHT\r
- asm jbe storeheight\r
- asm mov cx,MAXSCALEHEIGHT\r
-storeheight:\r
- asm mov WORD PTR [wallheight+bx],cx\r
- asm mov WORD PTR [zbuffer+bx],cx\r
-\r
-// height = fracheight>>16;\r
-// fracheight += fracstep;\r
-// if (height > MAXSCALEHEIGHT)\r
-// height = MAXSCALEHEIGHT;\r
-// wallheight[x] = zbuffer[x] = height;\r
-\r
- //\r
- // texture map\r
- //\r
- angle = pixelangle[x]+traceangle;\r
- if (angle<0)\r
- angle+=FINEANGLES;\r
-\r
- slope = finetangent[angle];\r
-\r
-//\r
-// distance is an unsigned 6.6 bit number (12 pixel bits)\r
-// slope is a signed 5.10 bit number\r
-// result is a signed 11.16 bit number\r
-//\r
-\r
-#if 0\r
- source = distance*slope;\r
- source >>=20;\r
-\r
- source += mapadd;\r
- source &= 63; // mask off the unused units\r
- source = 63-source;\r
- source <<= 6; // multiply by 64 for offset into pic\r
-#endif\r
- asm mov ax,[distance]\r
- asm imul [slope] // ax is the source pixel\r
- asm mov al,ah\r
- asm shr al,1\r
- asm shr al,1 // low 6 bits is now pixel number\r
- asm add ax,[mapadd]\r
- asm and ax,63\r
- asm mov dx,63\r
- asm sub dx,ax // otherwise it is backwards\r
- asm shl dx,1\r
- asm shl dx,1\r
- asm shl dx,1\r
- asm shl dx,1\r
- asm shl dx,1\r
- asm shl dx,1 // *64 to index into shape\r
- asm mov [source],dx\r
-\r
- if (source != lastsource)\r
- {\r
- if (lastpix != (unsigned)-1)\r
- {\r
- wallofs[lastpix] = lastsource;\r
- wallseg[lastpix] = wallpicseg;\r
- wallwidth[lastpix] = lastwidth;\r
- }\r
- lastpix = x;\r
- lastsource = source;\r
- lastwidth = 1;\r
- }\r
- else\r
- lastwidth++; // optimized draw, same map as last one\r
- }\r
- wallofs[lastpix] = lastsource;\r
- wallseg[lastpix] = wallpicseg;\r
- wallwidth[lastpix] = lastwidth;\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= TraceRay\r
-=\r
-= Used to find the left and rightmost tile in the view area to be traced from\r
-= Follows a ray of the given angle from viewx,viewy in the global map until\r
-= it hits a solid tile\r
-= sets:\r
-= tile.x,tile.y : tile coordinates of contacted tile\r
-= tilecolor : solid tile's color\r
-=\r
-==================\r
-*/\r
-\r
-int tilecolor;\r
-\r
-void TraceRay (unsigned angle)\r
-{\r
- long tracex,tracey,tracexstep,traceystep,searchx,searchy;\r
- fixed fixtemp;\r
- int otx,oty,searchsteps;\r
-\r
- tracexstep = costable[angle];\r
- traceystep = sintable[angle];\r
-\r
-//\r
-// advance point so it is even with the view plane before we start checking\r
-//\r
- fixtemp = FixedByFrac(prestep,tracexstep);\r
- tracex = viewx+fixtemp;\r
- fixtemp = FixedByFrac(prestep,traceystep);\r
- tracey = viewy-fixtemp;\r
-\r
- tile.x = tracex>>TILESHIFT; // starting point in tiles\r
- tile.y = tracey>>TILESHIFT;\r
-\r
-\r
- if (tracexstep<0) // use 2's complement, not signed magnitude\r
- tracexstep = -(tracexstep&0x7fffffff);\r
-\r
- if (traceystep<0) // use 2's complement, not signed magnitude\r
- traceystep = -(traceystep&0x7fffffff);\r
-\r
-//\r
-// we assume viewx,viewy is not inside a solid tile, so go ahead one step\r
-//\r
-\r
- do // until a solid tile is hit\r
- {\r
- otx = tile.x;\r
- oty = tile.y;\r
- spotvis[otx][oty] = true;\r
- tracex += tracexstep;\r
- tracey -= traceystep;\r
- tile.x = tracex>>TILESHIFT;\r
- tile.y = tracey>>TILESHIFT;\r
-\r
- if (tile.x!=otx && tile.y!=oty && (tilemap[otx][tile.y] || tilemap[tile.x][oty]) )\r
- {\r
- //\r
- // trace crossed two solid tiles, so do a binary search along the line\r
- // to find a spot where only one tile edge is crossed\r
- //\r
- searchsteps = 0;\r
- searchx = tracexstep;\r
- searchy = traceystep;\r
- do\r
- {\r
- searchx/=2;\r
- searchy/=2;\r
- if (tile.x!=otx && tile.y!=oty)\r
- {\r
- // still too far\r
- tracex -= searchx;\r
- tracey += searchy;\r
- }\r
- else\r
- {\r
- // not far enough, no tiles crossed\r
- tracex += searchx;\r
- tracey -= searchy;\r
- }\r
-\r
- //\r
- // if it is REAL close, go for the most clockwise intersection\r
- //\r
- if (++searchsteps == 16)\r
- {\r
- tracex = (long)otx<<TILESHIFT;\r
- tracey = (long)oty<<TILESHIFT;\r
- if (tracexstep>0)\r
- {\r
- if (traceystep<0)\r
- {\r
- tracex += TILEGLOBAL-1;\r
- tracey += TILEGLOBAL;\r
- }\r
- else\r
- {\r
- tracex += TILEGLOBAL;\r
- }\r
- }\r
- else\r
- {\r
- if (traceystep<0)\r
- {\r
- tracex --;\r
- tracey += TILEGLOBAL-1;\r
- }\r
- else\r
- {\r
- tracey --;\r
- }\r
- }\r
- }\r
-\r
- tile.x = tracex>>TILESHIFT;\r
- tile.y = tracey>>TILESHIFT;\r
-\r
- } while (( tile.x!=otx && tile.y!=oty) || (tile.x==otx && tile.y==oty) );\r
- }\r
- } while (!(tilecolor = tilemap[tile.x][tile.y]) );\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-========================\r
-=\r
-= FixedByFrac\r
-=\r
-= multiply a 16/16 bit, 2's complement fixed point number by a 16 bit\r
-= fraction, passed as a signed magnitude 32 bit number\r
-=\r
-========================\r
-*/\r
-\r
-#pragma warn -rvl // I stick the return value in with ASMs\r
-\r
-fixed FixedByFrac (fixed a, fixed b)\r
-{\r
- fixed value;\r
-\r
-//\r
-// setup\r
-//\r
-asm mov si,[WORD PTR b+2] // sign of result = sign of fraction\r
-\r
-asm mov ax,[WORD PTR a]\r
-asm mov cx,[WORD PTR a+2]\r
-\r
-asm or cx,cx\r
-asm jns aok: // negative?\r
-asm not ax\r
-asm not cx\r
-asm add ax,1\r
-asm adc cx,0\r
-asm xor si,0x8000 // toggle sign of result\r
-aok:\r
-\r
-//\r
-// multiply cx:ax by bx\r
-//\r
-asm mov bx,[WORD PTR b]\r
-asm mul bx // fraction*fraction\r
-asm mov di,dx // di is low word of result\r
-asm mov ax,cx //\r
-asm mul bx // units*fraction\r
-asm add ax,di\r
-asm adc dx,0\r
-\r
-//\r
-// put result dx:ax in 2's complement\r
-//\r
-asm test si,0x8000 // is the result negative?\r
-asm jz ansok:\r
-asm not ax\r
-asm not dx\r
-asm add ax,1\r
-asm adc dx,0\r
-\r
-ansok:;\r
-\r
-}\r
-\r
-#pragma warn +rvl\r
-\r
-#if 0\r
-/*\r
-=========================\r
-=\r
-= FixedAdd\r
-=\r
-= add two 16 bit fixed point numbers\r
-= to subtract, invert the sign of B before invoking\r
-=\r
-=========================\r
-*/\r
-\r
-fixed FixedAdd (fixed a, fixed b)\r
-{\r
- fixed value;\r
-\r
-asm mov ax,[WORD PTR a]\r
-asm mov dx,[WORD PTR a+2]\r
-\r
-asm mov bx,[WORD PTR b]\r
-asm mov cx,[WORD PTR b+2]\r
-\r
-asm or dx,dx\r
-asm jns aok: // negative?\r
-asm and dx,0x7fff\r
-asm not ax // convert a from signed magnitude to 2's compl\r
-asm not dx\r
-asm add ax,1\r
-asm adc dx,0\r
-aok:\r
-\r
-asm or cx,cx\r
-asm jns bok: // negative?\r
-asm and cx,0x7fff\r
-asm not bx // convert b from signed magnitude to 2's compl\r
-asm not cx\r
-asm add bx,1\r
-asm adc cx,0\r
-bok:\r
-\r
-asm add ax,bx // perform the addition\r
-asm adc dx,cx\r
-asm jns done\r
-\r
-asm and dx,0x7fff // value was negative\r
-asm not ax // back to signed magnitude\r
-asm not dx\r
-asm add ax,1\r
-asm adc dx,0\r
-\r
-done:\r
-\r
-asm mov [WORD PTR value],ax\r
-asm mov [WORD PTR value+2],dx\r
-\r
- return value;\r
-}\r
-#endif\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-========================\r
-=\r
-= TransformPoint\r
-=\r
-= Takes paramaters:\r
-= gx,gy : globalx/globaly of point\r
-=\r
-= globals:\r
-= viewx,viewy : point of view\r
-= viewcos,viewsin : sin/cos of viewangle\r
-=\r
-=\r
-= defines:\r
-= CENTERX : pixel location of center of view window\r
-= TILEGLOBAL : size of one\r
-= FOCALLENGTH : distance behind viewx/y for center of projection\r
-= scale : conversion from global value to screen value\r
-=\r
-= returns:\r
-= screenx,screenheight: projected edge location and size\r
-=\r
-========================\r
-*/\r
-\r
-void TransformPoint (fixed gx, fixed gy, int *screenx, unsigned *screenheight)\r
-{\r
- int ratio;\r
- fixed gxt,gyt,nx,ny;\r
-\r
-//\r
-// translate point to view centered coordinates\r
-//\r
- gx = gx-viewx;\r
- gy = gy-viewy;\r
-\r
-//\r
-// calculate newx\r
-//\r
- gxt = FixedByFrac(gx,viewcos);\r
- gyt = FixedByFrac(gy,viewsin);\r
- nx = gxt-gyt;\r
-\r
-//\r
-// calculate newy\r
-//\r
- gxt = FixedByFrac(gx,viewsin);\r
- gyt = FixedByFrac(gy,viewcos);\r
- ny = gyt+gxt;\r
-\r
-//\r
-// calculate perspective ratio\r
-//\r
- if (nx<0)\r
- nx = 0;\r
-\r
- ratio = nx*scale/FOCALLENGTH;\r
-\r
- if (ratio<=MINRATIO)\r
- ratio = MINRATIO;\r
-\r
- *screenx = CENTERX + ny/ratio;\r
-\r
- *screenheight = TILEGLOBAL/ratio;\r
-\r
-}\r
-\r
-\r
-//\r
-// transform actor\r
-//\r
-void TransformActor (objtype *ob)\r
-{\r
- int ratio;\r
- fixed gx,gy,gxt,gyt,nx,ny;\r
-\r
-//\r
-// translate point to view centered coordinates\r
-//\r
- gx = ob->x-viewx;\r
- gy = ob->y-viewy;\r
-\r
-//\r
-// calculate newx\r
-//\r
- gxt = FixedByFrac(gx,viewcos);\r
- gyt = FixedByFrac(gy,viewsin);\r
- nx = gxt-gyt-ob->size;\r
-\r
-//\r
-// calculate newy\r
-//\r
- gxt = FixedByFrac(gx,viewsin);\r
- gyt = FixedByFrac(gy,viewcos);\r
- ny = gyt+gxt;\r
-\r
-//\r
-// calculate perspective ratio\r
-//\r
- if (nx<0)\r
- nx = 0;\r
-\r
- ratio = nx*scale/FOCALLENGTH;\r
-\r
- if (ratio<=MINRATIO)\r
- ratio = MINRATIO;\r
-\r
- ob->viewx = CENTERX + ny/ratio;\r
-\r
- ob->viewheight = TILEGLOBAL/ratio;\r
-}\r
-\r
-//==========================================================================\r
-\r
-fixed TransformX (fixed gx, fixed gy)\r
-{\r
- int ratio;\r
- fixed gxt,gyt,nx,ny;\r
-\r
-//\r
-// translate point to view centered coordinates\r
-//\r
- gx = gx-viewx;\r
- gy = gy-viewy;\r
-\r
-//\r
-// calculate newx\r
-//\r
- gxt = FixedByFrac(gx,viewcos);\r
- gyt = FixedByFrac(gy,viewsin);\r
-\r
- return gxt-gyt;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= BuildTables\r
-=\r
-= Calculates:\r
-=\r
-= scale projection constant\r
-= sintable/costable overlapping fractional tables\r
-= firstangle/lastangle angles from focalpoint to left/right view edges\r
-= prestep distance from focal point before checking for tiles\r
-=\r
-==================\r
-*/\r
-\r
-void BuildTables (void)\r
-{\r
- int i;\r
- long intang;\r
- long x;\r
- float angle,anglestep,radtoint;\r
- double tang;\r
- fixed value;\r
-\r
-//\r
-// calculate the angle offset from view angle of each pixel's ray\r
-//\r
- radtoint = (float)FINEANGLES/2/PI;\r
- for (i=0;i<VIEWWIDTH/2;i++)\r
- {\r
- // start 1/2 pixel over, so viewangle bisects two middle pixels\r
- x = (TILEGLOBAL*i+TILEGLOBAL/2)/VIEWWIDTH;\r
- tang = (float)x/(FOCALLENGTH+MINDIST);\r
- angle = atan(tang);\r
- intang = angle*radtoint;\r
- pixelangle[VIEWWIDTH/2-1-i] = intang;\r
- pixelangle[VIEWWIDTH/2+i] = -intang;\r
- }\r
-\r
-//\r
-// calculate fine tangents\r
-// 1 sign bit, 5 units (clipped to), 10 fracs\r
-//\r
-#define MININT (-MAXINT)\r
-\r
- for (i=0;i<FINEANGLES/4;i++)\r
- {\r
- intang = tan(i/radtoint)*(1l<<10);\r
-\r
- //\r
- // if the tangent is not reprentable in this many bits, bound the\r
- // units part ONLY\r
- //\r
- if (intang>MAXINT)\r
- intang = 0x8f00 | (intang & 0xff);\r
- else if (intang<MININT)\r
- intang = 0xff00 | (intang & 0xff);\r
-\r
- finetangent[i] = intang;\r
-// finetangent[FINEANGLES/2+i] = intang;\r
-// finetangent[FINEANGLES/2-i-1] = -intang;\r
- finetangent[FINEANGLES-i-1] = -intang;\r
- }\r
-\r
-//\r
-// calculate scale value so one tile at mindist allmost fills the view horizontally\r
-//\r
- scale = GLOBAL1/VIEWWIDTH;\r
- scale *= focallength;\r
- scale /= (focallength+mindist);\r
-\r
-//\r
-// costable overlays sintable with a quarter phase shift\r
-// ANGLES is assumed to be divisable by four\r
-//\r
-// The low word of the value is the fraction, the high bit is the sign bit,\r
-// bits 16-30 should be 0\r
-//\r
-\r
- angle = 0;\r
- anglestep = PI/2/ANGLEQUAD;\r
- for (i=0;i<=ANGLEQUAD;i++)\r
- {\r
- value=GLOBAL1*sin(angle);\r
- sintable[i]=\r
- sintable[i+ANGLES]=\r
- sintable[ANGLES/2-i] = value;\r
- sintable[ANGLES-i]=\r
- sintable[ANGLES/2+i] = value | 0x80000000l;\r
- angle += anglestep;\r
- }\r
-\r
-//\r
-// figure trace angles for first and last pixel on screen\r
-//\r
- angle = atan((float)VIEWWIDTH/2*scale/FOCALLENGTH);\r
- angle *= ANGLES/(PI*2);\r
-\r
- intang = (int)angle+1;\r
- firstangle = intang;\r
- lastangle = -intang;\r
-\r
- prestep = GLOBAL1*((float)FOCALLENGTH/costable[firstangle]);\r
-\r
-//\r
-// misc stuff\r
-//\r
- walls[0].x2 = VIEWX-1;\r
- walls[0].height2 = 32000;\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= ClearScreen\r
-=\r
-=====================\r
-*/\r
-\r
-void ClearScreen (void)\r
-{\r
- unsigned topcolor=*skycolor, bottomcolor=*groundcolor;\r
- unsigned topimage=topcolor&0xf0,bottomimage=bottomcolor&0xf0;\r
- unsigned pfoffset=0;\r
-\r
-\r
-#if USE_STRIPS\r
- if (topimage == 0x20) // special code for lightning\r
- topimage = topcolor = 0;\r
-\r
-// Manually wipe screen with solid color.\r
-// If BOTH sky and ground are 'images' don't manually clear it!\r
-//\r
- if ((!topimage) || (!bottomimage))\r
- {\r
-#endif\r
-\r
- //\r
- // clear the screen\r
- //\r
-asm mov dx,GC_INDEX\r
-asm mov ax,GC_MODE + 256*2 // read mode 0, write mode 2\r
-asm out dx,ax\r
-asm mov ax,GC_BITMASK + 255*256\r
-asm out dx,ax\r
-\r
-//asm mov dx,40-VIEWWIDTH/8 // dx = modulo\r
-asm mov bl,VIEWWIDTH/16\r
-asm mov bh,CENTERY+1\r
-\r
-asm mov ax,topcolor\r
-asm mov es,[screenseg]\r
-asm mov di,[bufferofs]\r
-asm add di,((SCREENWIDTH*VIEWY)+(VIEWX/8))\r
-\r
-toploop:\r
-asm mov cl,bl\r
-asm rep stosw\r
-asm stosb\r
-//asm add di,dx // no need to add "0" modulo\r
-asm dec bh\r
-asm jnz toploop\r
-\r
-asm mov bh,CENTERY+1\r
-asm mov ax,bottomcolor\r
-\r
-bottomloop:\r
-asm mov cl,bl\r
-asm rep stosw\r
-asm stosb\r
-//asm add di,dx // no need to add "0" modulo\r
-asm dec bh\r
-asm jnz bottomloop\r
-\r
-#if USE_STRIPS\r
- }\r
-\r
-\r
-//\r
-// code to test parallax turning\r
-//\r
-\r
- if (topimage)\r
- {\r
- topimage -= 16;\r
- pfoffset = LONG_PERCENTAGE(3200,359,(359-player->angle),12);\r
- while (pfoffset >= 640)\r
- pfoffset -= 640;\r
- LatchDrawPicStrip(0,0,SKY1PIC+topimage,pfoffset+8);\r
- }\r
-\r
- if (bottomimage)\r
- {\r
-//// pfoffset = LONG_PERCENTAGE(3200,359,(359-player->angle),12)+320;\r
-// pfoffset += 320;\r
-// while (pfoffset >= 640)\r
-// pfoffset -= 640;\r
-// LatchDrawPicStrip(0,64,SKY1PIC+topimage,pfoffset+8);\r
- bottomimage -= 16;\r
- LatchDrawPic(0,64,GND1PIC+bottomimage);\r
- }\r
-#endif\r
-\r
-\r
-asm mov dx,GC_INDEX\r
-asm mov ax,GC_MODE + 256*10 // read mode 1, write mode 2\r
-asm out dx,ax\r
-asm mov al,GC_BITMASK\r
-asm out dx,al\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= DrawWallList\r
-=\r
-= Clips and draws all the walls traced this refresh\r
-=\r
-=====================\r
-*/\r
-\r
-void DrawWallList (void)\r
-{\r
- int i,leftx,newleft,rightclip;\r
- walltype *wall, *check;\r
-\r
-asm mov ax,ds\r
-asm mov es,ax\r
-asm mov di,OFFSET wallwidth\r
-asm xor ax,ax\r
-asm mov cx,VIEWWIDTH/2\r
-asm rep stosw\r
-\r
- ClearScreen ();\r
-\r
- rightwall->x1 = VIEWXH+1;\r
- rightwall->height1 = 32000;\r
- (rightwall+1)->x1 = 32000;\r
-\r
- leftx = -1;\r
-\r
- for (wall=&walls[1];wall<rightwall && leftx<=VIEWXH ;wall++)\r
- {\r
- if (leftx >= wall->x2)\r
- continue;\r
-\r
- rightclip = wall->x2;\r
-\r
- check = wall+1;\r
- while (check->x1 <= rightclip && check->height1 >= wall->height2)\r
- {\r
- rightclip = check->x1-1;\r
- check++;\r
- }\r
-\r
- if (rightclip>VIEWXH)\r
- rightclip=VIEWXH;\r
-\r
- if (leftx < wall->x1 - 1)\r
- newleft = wall->x1-1; // there was black space between walls\r
- else\r
- newleft = leftx;\r
-\r
- if (rightclip > newleft)\r
- {\r
- wall->leftclip = newleft+1;\r
- wall->rightclip = rightclip;\r
- DrawVWall (wall);\r
- leftx = rightclip;\r
- }\r
- }\r
-\r
-#ifndef DRAWEACH\r
- ScaleWalls (); // draw all the walls\r
-#endif\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= DrawScaleds\r
-=\r
-= Draws all objects that are visable\r
-=\r
-=====================\r
-*/\r
-\r
-objtype *depthsort[MAXACTORS];\r
-\r
-void DrawScaleds (void)\r
-{\r
-#if USE_INERT_LIST\r
- extern inertobjtype inertobjlist[], *inert;\r
-\r
- boolean inertlist=false;\r
-#endif\r
- int i,j,least,numvisable,height;\r
- objtype *obj,**vislist,*farthest;\r
- memptr shape;\r
- byte *tilespot,*visspot;\r
-\r
- numvisable = 0;\r
-\r
-//\r
-// calculate base positions of all objects\r
-//\r
- vislist = &depthsort[0];\r
-\r
- obj = player->next;\r
- while (obj)\r
- {\r
- tilespot = &tilemap[0][0]+(obj->tilex<<6)+obj->tiley;\r
- visspot = &spotvis[0][0]+(obj->tilex<<6)+obj->tiley;\r
- //\r
- // could be in any of the nine surrounding tiles\r
- //\r
- if (*visspot\r
- || ( *(visspot-1) && !*(tilespot-1) )\r
- || ( *(visspot+1) && !*(tilespot+1) )\r
- || ( *(visspot-65) && !*(tilespot-65) )\r
- || ( *(visspot-64) && !*(tilespot-64) )\r
- || ( *(visspot-63) && !*(tilespot-63) )\r
- || ( *(visspot+65) && !*(tilespot+65) )\r
- || ( *(visspot+64) && !*(tilespot+64) )\r
- || ( *(visspot+63) && !*(tilespot+63) ) )\r
- {\r
-#if USE_INERT_LIST\r
- if (!inertlist)\r
-#endif\r
- if ((obj->active == noalways) || (obj->active == always))\r
- obj->active = always;\r
- else\r
- obj->active = yes;\r
- TransformActor (obj);\r
- if (!obj->viewheight || obj->viewheight > VIEWWIDTH)\r
- goto cont; // too close or far away\r
-\r
- if (!obj->state->shapenum)\r
- goto cont;\r
-\r
- *vislist++ = obj;\r
- numvisable++;\r
- }\r
- else\r
-#if USE_INERT_LIST\r
- if (!inertlist)\r
-#endif\r
- if ((obj->active != always) && (obj->active != noalways))\r
- obj->active = no;\r
-\r
-cont:;\r
- obj = obj->next;\r
-#if USE_INERT_LIST\r
- if ((!obj) && (!inertlist))\r
- {\r
- if (inert != inertobjlist)\r
- obj = (objtype *)inertobjlist;\r
- inertlist = true;\r
- }\r
-#endif\r
- }\r
-\r
- if (vislist == &depthsort[0])\r
- return; // no visable objects\r
-\r
-//\r
-// draw from back to front\r
-//\r
- for (i = 0; i<numvisable; i++)\r
- {\r
- least = 32000;\r
- for (j=0;j<numvisable;j++)\r
- {\r
- height = depthsort[j]->viewheight;\r
- if (height < least)\r
- {\r
- least = height;\r
- farthest = depthsort[j];\r
- }\r
- }\r
- //\r
- // draw farthest\r
- //\r
- shape = shapedirectory[farthest->state->shapenum-FIRSTSCALEPIC];\r
- ScaleShape(farthest->viewx,shape,farthest->viewheight);\r
- farthest->viewheight = 32000;\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= CalcTics\r
-=\r
-=====================\r
-*/\r
-\r
-void CalcTics (void)\r
-{\r
- long newtime,oldtimecount;\r
-\r
-\r
-#ifdef PROFILE\r
- tics = 1;\r
- return;\r
-#endif\r
-\r
-//\r
-// calculate tics since last refresh for adaptive timing\r
-//\r
- if (lasttimecount > TimeCount)\r
- TimeCount = lasttimecount; // if the game was paused a LONG time\r
-\r
-#if 0\r
- if (DemoMode) // demo recording and playback needs\r
- { // to be constant\r
-//\r
-// take DEMOTICS or more tics, and modify Timecount to reflect time taken\r
-//\r
- oldtimecount = lasttimecount;\r
- while (TimeCount<oldtimecount+DEMOTICS*2)\r
- ;\r
- lasttimecount = oldtimecount + DEMOTICS;\r
- TimeCount = lasttimecount + DEMOTICS;\r
- realtics = tics = DEMOTICS;\r
- }\r
- else\r
-#endif\r
- {\r
-//\r
-// non demo, so report actual time\r
-//\r
- newtime = TimeCount;\r
- realtics = tics = newtime-lasttimecount;\r
- lasttimecount = newtime;\r
-\r
-#ifdef FILEPROFILE\r
- strcpy (scratch,"\tTics:");\r
- itoa (tics,str,10);\r
- strcat (scratch,str);\r
- strcat (scratch,"\n");\r
- write (profilehandle,scratch,strlen(scratch));\r
-#endif\r
-\r
- if (tics>MAXTICS)\r
- {\r
- TimeCount -= (tics-MAXTICS);\r
- tics = MAXTICS;\r
- }\r
-\r
- if (realtics>MAXREALTICS)\r
- realtics = MAXREALTICS;\r
- }\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-========================\r
-=\r
-= DrawHand\r
-=\r
-========================\r
-*/\r
-\r
-void DrawHand (void)\r
-{\r
- #define HAND_X_POS ((VIEWWIDTH/16)-(10/2)) // "10" = hand width in bytes\r
-\r
- #define picnum HAND1PICM\r
-\r
- memptr source;\r
- unsigned dest,width,height;\r
-\r
-// if (gamestate.shotpower || boltsleft)\r
-// picnum += (((unsigned)TimeCount>>3)&1);\r
-\r
- source = grsegs[picnum];\r
- dest = ylookup[VIEWHEIGHT-handheight]+HAND_X_POS+bufferofs; // 12\r
- width = picmtable[picnum-STARTPICM].width;\r
- height = picmtable[picnum-STARTPICM].height;\r
-\r
- VW_MaskBlock(source,0,dest,width,handheight,width*height);\r
- EGAMAPMASK(15);\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-========================\r
-=\r
-= ThreeDRefresh\r
-=\r
-========================\r
-*/\r
-\r
-void ThreeDRefresh (void)\r
-{\r
- int tracedir;\r
-\r
-restart:\r
- aborttrace = false;\r
-\r
-//\r
-// clear out the traced array\r
-//\r
-asm mov ax,ds\r
-asm mov es,ax\r
-asm mov di,OFFSET spotvis\r
-asm xor ax,ax\r
-asm mov cx,[mapwidth] // mapheight*32 words\r
-asm shl cx,1\r
-asm shl cx,1\r
-asm shl cx,1\r
-asm shl cx,1\r
-asm shl cx,1\r
-asm rep stosw\r
-\r
-\r
-//\r
-// set up variables for this view\r
-//\r
-\r
- viewangle = player->angle;\r
- fineviewangle = viewangle*(FINEANGLES/ANGLES);\r
- viewsin = sintable[viewangle];\r
- viewcos = costable[viewangle];\r
- viewx = player->x - FixedByFrac(FOCALLENGTH,viewcos);\r
- viewy = player->y + FixedByFrac(FOCALLENGTH,viewsin);\r
- viewx &= 0xfffffc00; // stop on a pixel boundary\r
- viewy &= 0xfffffc00;\r
- viewx += 0x180;\r
- viewy += 0x180;\r
- viewxpix = viewx>>10;\r
- viewypix = viewy>>10;\r
-\r
- focal.x = viewx>>TILESHIFT;\r
- focal.y = viewy>>TILESHIFT;\r
-\r
-//\r
-// find the rightmost visable tile in view\r
-//\r
- tracedir = viewangle + lastangle;\r
- if (tracedir<0)\r
- tracedir+=ANGLES;\r
- else if (tracedir>=ANGLES)\r
- tracedir-=ANGLES;\r
- TraceRay( tracedir );\r
- right.x = tile.x;\r
- right.y = tile.y;\r
-\r
-//\r
-// find the leftmost visable tile in view\r
-//\r
- tracedir = viewangle + firstangle;\r
- if (tracedir<0)\r
- tracedir+=ANGLES;\r
- else if (tracedir>=ANGLES)\r
- tracedir-=ANGLES;\r
- TraceRay( tracedir );\r
-\r
-//\r
-// follow the walls from there to the right\r
-//\r
- rightwall = &walls[1];\r
- FollowWalls ();\r
-\r
- if (aborttrace)\r
- goto restart;\r
-\r
-//\r
-// actually draw stuff\r
-//\r
- if (++screenpage == 3)\r
- screenpage = 0;\r
-\r
- bufferofs = screenloc[screenpage];\r
-\r
- EGAWRITEMODE(2);\r
- EGAMAPMASK(15);\r
-\r
-//\r
-// draw the wall list saved be FollowWalls ()\r
-//\r
-// animframe = (TimeCount&8)>>3;\r
-\r
-//\r
-// draw all the scaled images\r
-//\r
- asm mov dx,GC_INDEX\r
-\r
- asm mov ax,GC_COLORDONTCARE\r
- asm out dx,ax // don't look at any of the planes\r
-\r
- asm mov ax,GC_MODE + 256*(10) // read mode 1, write mode 2\r
- asm out dx,ax\r
-\r
- asm mov al,GC_BITMASK\r
- asm out dx,al\r
-\r
- AnimateWallList();\r
- DrawWallList();\r
- DrawScaleds();\r
-\r
- EGAWRITEMODE(0);\r
- EGABITMASK(0xff);\r
-\r
-//\r
-// draw hand\r
-//\r
- if (handheight)\r
- DrawHand ();\r
-\r
-//\r
-// show screen and time last cycle\r
-//\r
- if (fizzlein)\r
- {\r
- fizzlein = false;\r
- FizzleFade(bufferofs,displayofs,VIEWWIDTH,VIEWHEIGHT,true);\r
- lasttimecount = TimeCount;\r
- if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement\r
- }\r
-\r
-asm cli\r
-asm mov cx,[bufferofs]\r
-asm mov dx,3d4h // CRTC address register\r
-asm mov al,0ch // start address high register\r
-asm out dx,al\r
-asm inc dx\r
-asm mov al,ch\r
-asm out dx,al // set the high byte\r
-asm dec dx\r
-asm mov al,0dh // start address low register\r
-asm out dx,al\r
-asm inc dx\r
-asm mov al,cl\r
-asm out dx,al // set the low byte\r
-asm sti\r
-\r
- displayofs = bufferofs;\r
-\r
- CalcTics ();\r
-\r
-}\r
-\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// C3_GAME.C\r
-\r
-#include <stdlib.h>\r
-\r
-#include "DEF.H"\r
-#include "gelib.h"\r
-#pragma hdrstop\r
-\r
-#ifdef PROFILE\r
-#include "TIME.H"\r
-#endif\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define NUMLUMPS 61\r
-\r
-#define SUCCUBUSLUMP 0\r
-#define FATDEMONLUMP 1\r
-#define BOLTLUMP 2\r
-#define NUKELUMP 3\r
-#define POTIONLUMP 4\r
-#define RKEYLUMP 5\r
-#define YKEYLUMP 6\r
-#define GKEYLUMP 7\r
-#define BKEYLUMP 8\r
-//#define SCROLLLUMP 9\r
-#define CHESTLUMP 10\r
-#define PLAYERLUMP 11\r
-#define WALL1LUMP 12\r
-#define WALL2LUMP 13\r
-#define BDOORLUMP 14\r
-#define GODESSLUMP 15\r
-#define MAGELUMP 16\r
-#define BATLUMP 17\r
-#define GRELLUMP 18\r
-#define TOMBSTONESLUMP 19\r
-#define ZOMBIELUMP 20\r
-#define ANTLUMP 21\r
-#define SKELETONLUMP 22\r
-#define RGEMLUMP 23\r
-#define GGEMLUMP 24\r
-#define BGEMLUMP 25\r
-#define YGEMLUMP 26\r
-#define PGEMLUMP 27\r
-//#define RKEY2LUMP 28\r
-#define DRAGONLUMP 29\r
-#define OBJ_WARPLUMP 30\r
-#define EYELUMP 31\r
-#define REDDEMONLUMP 32\r
-//#define PITLUMP 33\r
-#define FTIMELUMP 34\r
-#define WATERCHESTLUMP 35\r
-#define TREELUMP 36\r
-#define ARCH1LUMP 37\r
-#define BUNNYLUMP 38\r
-#define ANTHILLLUMP 39\r
-#define COLUMNLUMP 40\r
-#define SULPHURGASLUMP 41\r
-#define FIREPOTLUMP 42\r
-//#define WHIRLPOOLLUMP 43\r
-#define FOUNTAINLUMP 44\r
-#define FORCEFIELDLUMP 45\r
-#define ARCH2LUMP 46\r
-#define ARCH3LUMP 47\r
-#define ARCH4LUMP 48\r
-#define ARCH5LUMP 49\r
-#define ARCH6LUMP 50\r
-#define SKELHANGLUMP 51\r
-//#define SKELPILELUMP 52\r
-#define ARCH7LUMP 53\r
-#define ARCH8LUMP 54\r
-#define ARCH9LUMP 55\r
-#define ARCH10LUMP 56\r
-#define ARCH11LUMP 57\r
-#define ARCH12LUMP 58\r
-#define ARCH13LUMP 59\r
-\r
-int lumpstart[NUMLUMPS] = {\r
-SUCCUBUS_LUMP_START,\r
-FATDEMON_LUMP_START,\r
-BOLT_LUMP_START,\r
-NUKE_LUMP_START,\r
-POTION_LUMP_START,\r
-RKEY_LUMP_START,\r
-YKEY_LUMP_START,\r
-GKEY_LUMP_START,\r
-BKEY_LUMP_START,\r
-0,\r
-//SCROLL_LUMP_START,\r
-CHEST_LUMP_START,\r
-PLAYER_LUMP_START,\r
-//WALL1_LUMP_START,\r
-//WALL2_LUMP_START,\r
-//BDOOR_LUMP_START,\r
-0,0,0,\r
-GODESS_LUMP_START,\r
-MAGE_LUMP_START,\r
-BAT_LUMP_START,\r
-GREL_LUMP_START,\r
-TOMBSTONES_LUMP_START,\r
-ZOMBIE_LUMP_START,\r
-ANT_LUMP_START,\r
-SKELDUDE_LUMP_START,\r
-RGEM_LUMP_START,\r
-GGEM_LUMP_START,\r
-BGEM_LUMP_START,\r
-YGEM_LUMP_START,\r
-PGEM_LUMP_START,\r
-0, //RKEY2_LUMP_START,\r
-DRAGON_LUMP_START,\r
-OBJ_WARP_LUMP_START,\r
-EYE_LUMP_START,\r
-REDDEMON_LUMP_START,\r
-0, //PIT_LUMP_START,\r
-TIME_LUMP_START,\r
-O_WATER_CHEST_LUMP_START,\r
-TREE_LUMP_START,\r
-ARCH1_LUMP_START,\r
-BUNNY_LUMP_START,\r
-ANTHILL_LUMP_START,\r
-COLUMN_LUMP_START,\r
-SULPHURGAS_LUMP_START,\r
-FIREPOT_LUMP_START,\r
-0, //WHIRLPOOL_LUMP_START,\r
-FOUNTAIN_LUMP_START,\r
-FORCEFIELD_LUMP_START,\r
-ARCH2_LUMP_START,\r
-ARCH3_LUMP_START,\r
-ARCH4_LUMP_START,\r
-ARCH5_LUMP_START,\r
-ARCH6_LUMP_START,\r
-SKELHANG_LUMP_START,\r
-0, //SKELPILE_LUMP_START,\r
-ARCH7_LUMP_START,\r
-ARCH8_LUMP_START,\r
-ARCH9_LUMP_START,\r
-ARCH10_LUMP_START,\r
-ARCH11_LUMP_START,\r
-ARCH12_LUMP_START,\r
-ARCH13_LUMP_START,\r
-};\r
-\r
-\r
-int lumpend[NUMLUMPS] = {\r
-SUCCUBUS_LUMP_END,\r
-FATDEMON_LUMP_END,\r
-BOLT_LUMP_END,\r
-NUKE_LUMP_END,\r
-POTION_LUMP_END,\r
-RKEY_LUMP_END,\r
-YKEY_LUMP_END,\r
-GKEY_LUMP_END,\r
-BKEY_LUMP_END,\r
-0,\r
-//SCROLL_LUMP_END,\r
-CHEST_LUMP_END,\r
-PLAYER_LUMP_END,\r
-0,0,0,\r
-GODESS_LUMP_END,\r
-MAGE_LUMP_END,\r
-BAT_LUMP_END,\r
-GREL_LUMP_END,\r
-TOMBSTONES_LUMP_END,\r
-ZOMBIE_LUMP_END,\r
-ANT_LUMP_END,\r
-SKELDUDE_LUMP_END,\r
-RGEM_LUMP_END,\r
-GGEM_LUMP_END,\r
-BGEM_LUMP_END,\r
-YGEM_LUMP_END,\r
-PGEM_LUMP_END,\r
-0, //RKEY2_LUMP_END,\r
-DRAGON_LUMP_END,\r
-OBJ_WARP_LUMP_END,\r
-EYE_LUMP_END,\r
-REDDEMON_LUMP_END,\r
-0, //PIT_LUMP_END,\r
-TIME_LUMP_END,\r
-O_WATER_CHEST_LUMP_END,\r
-TREE_LUMP_END,\r
-ARCH1_LUMP_END,\r
-BUNNY_LUMP_END,\r
-ANTHILL_LUMP_END,\r
-COLUMN_LUMP_END,\r
-SULPHURGAS_LUMP_END,\r
-FIREPOT_LUMP_END,\r
-0, //WHIRLPOOL_LUMP_END,\r
-FOUNTAIN_LUMP_END,\r
-FORCEFIELD_LUMP_END,\r
-ARCH2_LUMP_END,\r
-ARCH3_LUMP_END,\r
-ARCH4_LUMP_END,\r
-ARCH5_LUMP_END,\r
-ARCH6_LUMP_END,\r
-SKELHANG_LUMP_END,\r
-0, //SKELPILE_LUMP_END,\r
-ARCH7_LUMP_END,\r
-ARCH8_LUMP_END,\r
-ARCH9_LUMP_END,\r
-ARCH10_LUMP_END,\r
-ARCH11_LUMP_END,\r
-ARCH12_LUMP_END,\r
-ARCH13_LUMP_END,\r
-};\r
-\r
-\r
-//extern unsigned scolor,gcolor;\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-unsigned latchpics[NUMLATCHPICS];\r
-unsigned tileoffsets[NUMTILE16];\r
-unsigned textstarts[27];\r
-\r
-boolean splitscreen=false;\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-boolean lumpneeded[NUMLUMPS];\r
-\r
-\r
-//===========================================================================\r
-\r
-//==========================================================================\r
-//\r
-//\r
-// LOCAL PROTOTYPES\r
-//\r
-//\r
-//==========================================================================\r
-\r
-void CashPoints(void);\r
-\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= ScanInfoPlane\r
-=\r
-= Spawn all actors and mark down special places\r
-=\r
-==========================\r
-*/\r
-\r
-void ScanInfoPlane (void)\r
-{\r
- unsigned char hibyte;\r
- unsigned x,y,i,j;\r
- unsigned int tile;\r
- unsigned far *start;\r
-\r
- InitObjList(); // start spawning things with a clean slate\r
-\r
- scolor = gcolor = 0;\r
- skycolor = &scolor;\r
- groundcolor = &gcolor;\r
-\r
-\r
- memset (lumpneeded,0,sizeof(lumpneeded));\r
-\r
- start = mapsegs[2];\r
- for (y=0;y<mapheight;y++)\r
- for (x=0;x<mapwidth;x++)\r
- {\r
- tile = *start++;\r
- hibyte = tile >> 8;\r
- tile &= 0xff;\r
-\r
- switch (hibyte)\r
- {\r
- char hi;\r
-\r
- case 0xFB:\r
- wall_anim_time = tile;\r
- tile = 0;\r
- break;\r
-\r
- case 0xfa: // sky/ground color\r
- case 0xf9: // sky/ground 'strip'\r
- x++;\r
- tile = *start++;\r
- hi = tile >> 8;\r
- tile &= 0xff;\r
- switch (hibyte)\r
- {\r
- case 0xfa: // sky / ground color\r
- scolor = ((hi)|(hi<<8));\r
- gcolor = ((tile)|(tile<<8));\r
- skycolor = &scolor;\r
- groundcolor = &gcolor;\r
- break;\r
-\r
- case 0xf9: // sky / ground 'strip'\r
- break;\r
- }\r
- break;\r
- }\r
-\r
- if ((!tile) || (hibyte))\r
- continue;\r
-\r
- switch (tile)\r
- {\r
- case 1:\r
- case 2:\r
- case 3:\r
- case 4:\r
- lumpneeded[PLAYERLUMP] = true;\r
- SpawnPlayer(x,y,NORTH+tile-1);\r
- break;\r
-\r
- case 5:\r
- case 6:\r
- case 7:\r
- case 8:\r
- case 9:\r
- case 10:\r
- case 11:\r
- lumpneeded[tile-5+BOLTLUMP] = true;\r
- SpawnBonus(x,y,tile-5);\r
- break;\r
-\r
-#if 0\r
- case 12:\r
- case 13:\r
- case 14:\r
- case 15:\r
- case 16:\r
- case 17:\r
- case 18:\r
- case 19:\r
- lumpneeded[SCROLLLUMP] = true;\r
- SpawnBonus(x,y,B_SCROLL1+tile-12);\r
- break;\r
-#endif\r
-\r
- case 20:\r
- lumpneeded[REDDEMONLUMP] = true;\r
- SpawnRedDemon (x,y);\r
- break;\r
-\r
-#if 0\r
- case 20: // goal\r
- lumpneeded[GOALLUMP] = true;\r
- SpawnBonus(x,y,B_GOAL);\r
- break;\r
-#endif\r
-\r
- case 21:\r
- lumpneeded[GODESSLUMP] = true;\r
- SpawnGodess (x,y);\r
- break;\r
-\r
- case 22:\r
- lumpneeded[FATDEMONLUMP] = true;\r
- SpawnFatDemon (x,y);\r
- break;\r
-\r
- case 23:\r
- lumpneeded[SUCCUBUSLUMP] = true;\r
- SpawnSuccubus (x,y);\r
- break;\r
-\r
- case 24:\r
- lumpneeded[DRAGONLUMP] = true;\r
- SpawnDragon(x,y);\r
- break;\r
-\r
- case 25:\r
- lumpneeded[BATLUMP] = true;\r
- SpawnBat (x,y);\r
- break;\r
-\r
- case 26:\r
- lumpneeded[EYELUMP] = true;\r
- SpawnEye(x,y);\r
- break;\r
-\r
- case 27:\r
- lumpneeded[MAGELUMP] = true;\r
- SpawnMage (x,y);\r
- break;\r
-\r
- case 28:\r
- lumpneeded[RKEYLUMP] = lumpneeded[GRELLUMP] = true;\r
- SpawnGrelminar (x,y);\r
- break;\r
-\r
- case 30:\r
- lumpneeded[ANTLUMP] = true;\r
- SpawnAnt(x,y);\r
- break;\r
-\r
- case 31:\r
- case 32:\r
- case 33:\r
- case 34:\r
- case 35:\r
- lumpneeded[OBJ_WARPLUMP] = true;\r
- SpawnWarp (x,y,tile-30);\r
- break;\r
-\r
- case 36:\r
- lumpneeded[ZOMBIELUMP] = true;\r
- SpawnZombie(x,y);\r
- break;\r
-\r
- case 37:\r
- lumpneeded[SKELETONLUMP] = true;\r
- SpawnSkeleton(x,y);\r
- break;\r
-\r
- case 38:\r
- lumpneeded[SKELETONLUMP] = true;\r
- SpawnWallSkeleton(x,y);\r
- break;\r
-\r
- case 39:\r
- lumpneeded[FTIMELUMP] = true;\r
- SpawnFTime(x,y);\r
- break;\r
-\r
- case 40:\r
- case 41:\r
- case 42:\r
- case 43:\r
- case 44:\r
- lumpneeded[tile-40+RGEMLUMP] = true;\r
- SpawnBonus(x,y,tile-40+B_RGEM);\r
- break;\r
-\r
- case 45:\r
- case 46:\r
- case 47:\r
- lumpneeded[TOMBSTONESLUMP] = true;\r
- SpawnTombstone(x,y,tile-45);\r
- break;\r
-\r
-#if 0\r
- case 48:\r
- lumpneeded[PITLUMP] = true;\r
- SpawnWarp(x,y,0);\r
- break;\r
-#endif\r
- case 49: // chest\r
- if (gcolor == 0x0101)\r
- lumpneeded[WATERCHESTLUMP] = true;\r
- else\r
- lumpneeded[CHESTLUMP] = true;\r
- SpawnBonus(x,y,B_CHEST);\r
- break;\r
-\r
- case 50:\r
- lumpneeded[TREELUMP] = true;\r
- SpawnTree(x,y);\r
- break;\r
-\r
- case 51:\r
- lumpneeded[BUNNYLUMP] = true;\r
- SpawnBunny(x,y);\r
- break;\r
-\r
- case 52:\r
- lumpneeded[ARCH1LUMP] = true;\r
- SpawnArch(x,y,1);\r
- break;\r
-\r
- case 53:\r
- lumpneeded[ANTHILLLUMP] = true;\r
- SpawnWarp(x,y,0);\r
- break;\r
-\r
- case 54:\r
- lumpneeded[COLUMNLUMP] = true;\r
- SpawnMiscObjects(x,y,1); //1=column,2=sulphur hole,3=fire pot,4=fountain\r
- break;\r
-\r
- case 55:\r
- lumpneeded[SULPHURGASLUMP] = true;\r
- SpawnMiscObjects(x,y,2);\r
- break;\r
-\r
- case 56:\r
- lumpneeded[FIREPOTLUMP] = true;\r
- SpawnMiscObjects(x,y,3);\r
- break;\r
-\r
- case 57:\r
- lumpneeded[ARCH13LUMP] = true;\r
- SpawnArch(x,y,13);\r
- break;\r
-\r
- case 58:\r
- lumpneeded[FOUNTAINLUMP] = true;\r
- SpawnMiscObjects(x,y,4);\r
- break;\r
-\r
- case 59:\r
- lumpneeded[FORCEFIELDLUMP] = true;\r
- SpawnForceField(x,y);\r
- break;\r
-\r
- case 60:\r
- lumpneeded[ARCH2LUMP] = true;\r
- SpawnArch(x,y,2);\r
- break;\r
-\r
- case 61:\r
- lumpneeded[ARCH3LUMP] = true;\r
- SpawnArch(x,y,3);\r
- break;\r
-\r
- case 62:\r
- lumpneeded[ARCH4LUMP] = true;\r
- SpawnArch(x,y,4);\r
- break;\r
-\r
- case 63:\r
- lumpneeded[ARCH5LUMP] = true;\r
- SpawnArch(x,y,5);\r
- break;\r
-\r
- case 64:\r
- lumpneeded[ARCH6LUMP] = true;\r
- SpawnArch(x,y,6);\r
- break;\r
-\r
- case 65:\r
- lumpneeded[SKELHANGLUMP] = true;\r
- lumpneeded[SKELETONLUMP] = true;\r
- SpawnSkeletonHanging(x,y);\r
- break;\r
-\r
- case 66:\r
- lumpneeded[ARCH12LUMP] = true;\r
- SpawnArch(x,y,12);\r
- break;\r
-\r
- case 67:\r
- lumpneeded[ARCH7LUMP] = true;\r
- SpawnArch(x,y,7);\r
- break;\r
-\r
- case 68:\r
- lumpneeded[ARCH8LUMP] = true;\r
- SpawnArch(x,y,8);\r
- break;\r
-\r
- case 69:\r
- lumpneeded[ARCH9LUMP] = true;\r
- SpawnArch(x,y,9);\r
- break;\r
-\r
- case 70:\r
- lumpneeded[ARCH10LUMP] = true;\r
- SpawnArch(x,y,10);\r
- break;\r
-\r
- case 71:\r
- lumpneeded[ARCH11LUMP] = true;\r
- SpawnArch(x,y,11);\r
- break;\r
- }\r
- }\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= ScanText\r
-=\r
-==================\r
-*/\r
-\r
-void ScanText (void)\r
-{\r
- int i;\r
- char far *text;\r
-\r
- text = (char _seg *)grsegs[LEVEL1TEXT+mapon];\r
-\r
- textstarts[0] = 0;\r
-\r
- for (i=1;i<=26;i++)\r
- {\r
- while (*text != '\n')\r
- {\r
- if (*text == '\r')\r
- *text = 0;\r
- text++;\r
- }\r
- text++;\r
- textstarts[i] = FP_OFF(text);\r
- }\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= DrawEnterScreen\r
-=\r
-==================\r
-*/\r
-#if 0\r
-static char *levelnames[] =\r
- {\r
- "Programmers Test Map",\r
- "The Garden of Tears",\r
- "The Den of Zombies",\r
- "The Mausoleum Grounds",\r
- "The Main Floor of the Mausoleum",\r
- "Mike's Blastable Passage",\r
- "The Crypt of Nemesis the Undead",\r
- "The Subterranean Vault",\r
- "The Ancient Aqueduct",\r
- "The Orc Mines",\r
- "The Lair of the Troll",\r
- "The Demon's Inferno",\r
- "The Battleground of the Titans",\r
- "The Coven of Mages",\r
- "The Inner Sanctum",\r
- "The Haunt of Nemesis",\r
- "The Passage to the Surface",\r
- "Big Jim's Domain",\r
- "Nolan",\r
- "19",\r
- "20",\r
- "21",\r
- "22",\r
- "23",\r
- "24",\r
- "25",\r
- "26",\r
- "27",\r
- "28",\r
- "29",\r
- "30",\r
- "31",\r
- "32",\r
- "33",\r
- "34",\r
- "35",\r
- "36",\r
- "37",\r
- "38",\r
- "39",\r
- };\r
-#endif\r
-\r
-void DrawEnterScreen (void)\r
-{\r
- int width;\r
-\r
- bufferofs = displayofs = screenloc[screenpage];\r
- VW_Bar(0,0,VIEWWIDTH,VIEWHEIGHT,0);\r
-// width = strlen(levelnames[gamestate.mapon]);\r
- width = strlen("You enter a new area ...");\r
- if (width < 20)\r
- width = 20;\r
- CenterWindow(width,3);\r
- US_CPrint("\nYou enter a new area ...\n");\r
-// US_CPrint(levelnames[gamestate.mapon]);\r
-}\r
-\r
-//==========================================================================\r
-\r
-boolean tileneeded[NUMFLOORS];\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= CacheScaleds\r
-=\r
-==================\r
-*/\r
-\r
-void CacheScaleds (void)\r
-{\r
- int i,j;\r
- unsigned source,dest;\r
-\r
- FreeUpMemory ();\r
- CA_CacheGrChunk(LEVEL1TEXT+mapon);\r
- ScanText ();\r
-\r
-//\r
-// make sure we are displaying screenpage 0\r
-//\r
- if (screenpage)\r
- {\r
- source = screenloc[screenpage];\r
- dest = screenloc[0];\r
- VW_ScreenToScreen (source,dest,40,VIEWHEIGHT);\r
- screenpage = 0;\r
- VW_SetScreen (dest,0);\r
- displayofs = dest;\r
- }\r
-\r
-//\r
-// cache wall pictures\r
-//\r
- for (i=1;i<NUMFLOORS;i++)\r
- if (tileneeded[i])\r
- {\r
- SetupScaleWall (walllight1[i]);\r
- SetupScaleWall (walldark1[i]);\r
- }\r
-\r
-//\r
-// cache the actor pictures\r
-//\r
- for (i=0;i<NUMLUMPS;i++)\r
- if (lumpneeded[i])\r
- for (j=lumpstart[i];j<=lumpend[i];j++)\r
- SetupScalePic(j);\r
-\r
- source = screenloc[0];\r
- for (i=1;i<=2;i++)\r
- {\r
- dest = screenloc[i];\r
- VW_ScreenToScreen (source,dest,40,VIEWHEIGHT);\r
- }\r
-\r
- screenpage = 1;\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= SetupGameLevel\r
-=\r
-==================\r
-*/\r
-\r
-void SetupGameLevel ()\r
-{\r
- int x,y,i,loop;\r
- unsigned far *map,tile,far *spotptr,spot;\r
- unsigned search_tile;\r
- boolean exploding_walls_present = false;\r
-\r
- memset (tileneeded,0,sizeof(tileneeded));\r
-//\r
-// randomize if not a demo\r
-//\r
-#if 0\r
- if (DemoMode)\r
- {\r
- US_InitRndT(false);\r
- gamestate.difficulty = gd_Normal;\r
- }\r
- else\r
-#endif\r
- US_InitRndT(true);\r
-\r
-//\r
-// load the level\r
-//\r
- CA_CacheMap (gamestate.mapon);\r
-\r
- mapwidth = mapheaderseg[mapon]->width;\r
- mapheight = mapheaderseg[mapon]->height;\r
-\r
-//\r
-// make a lookup table for the maps left edge\r
-//\r
- spot = 0;\r
- for (y=0;y<mapheight;y++)\r
- {\r
- farmapylookup[y] = spot;\r
- spot += mapwidth;\r
- }\r
-\r
-\r
-//\r
-// copy the wall data to a data segment array\r
-//\r
- memset (tilemap,0,sizeof(tilemap));\r
- memset (actorat,0,sizeof(actorat));\r
- map = mapsegs[0];\r
- spotptr = mapsegs[2];\r
- for (y=0;y<mapheight;y++)\r
- for (x=0;x<mapwidth;x++)\r
- {\r
- tile = *map++;\r
-\r
- if (((*spotptr)>>8) == EXP_WALL_CODE)\r
- {\r
- exploding_walls_present = true;\r
- }\r
-\r
- if (tile<NUMFLOORS)\r
- {\r
-#if 0\r
- if (tile == WALL_SKELETON_CODE)\r
- {\r
- tileneeded[tile+1] = tileneeded[tile+2] = true;\r
- tilemap[x][y] = tile;\r
- }\r
-#endif\r
- if ((tile == 66) || (tile == 67) || (tile == 68) || (tile == 69))\r
- {\r
- if ((tile == 66) || (tile == 67))\r
- tileneeded[tile+2] = true;\r
- tileneeded[21] = tileneeded[tile] = true;\r
- tilemap[x][y] = tile;\r
- }\r
- else\r
- if (tile != INVISIBLEWALL)\r
- {\r
- tileneeded[tile] = true;\r
- tilemap[x][y] = tile;\r
- if (ANIM_FLAGS(tile))\r
- {\r
- search_tile = tile+(char signed)ANIM_FLAGS(tile);\r
-\r
- if (!tileneeded[search_tile])\r
- while (search_tile != tile)\r
- {\r
- tileneeded[search_tile] = true;\r
- if (ANIM_FLAGS(search_tile))\r
- search_tile += (char signed)ANIM_FLAGS(search_tile);\r
- else\r
- TrashProg("Unending Tile Animation!");\r
- }\r
- }\r
-\r
- }\r
- if (tile>0)\r
- (unsigned)actorat[x][y] = tile;\r
- }\r
- spotptr++;\r
- }\r
-\r
-\r
- //\r
- // Mark any gfx chunks needed\r
- //\r
-\r
-// CA_MarkGrChunk(NORTHICONSPR);\r
-// CA_CacheMarks(NULL);\r
-\r
-\r
-//\r
-// decide which graphics are needed and spawn actors\r
-//\r
- zombie_base_delay = 0; // (1*60) + random(1*60);\r
- ScanInfoPlane ();\r
- _fmemset(wall_anim_pos,0,sizeof(wall_anim_pos));\r
-\r
-\r
-//\r
-// mark which exploding walls are needed ---- the check for floor color\r
-// is preformed in ScanInfoPlane.\r
-//\r
-\r
- if (exploding_walls_present)\r
- {\r
- extern unsigned gnd_colors[];\r
-\r
- if (gcolor == 0x0101)\r
- tileneeded[WATEREXP] = tileneeded[WATEREXP+1] = tileneeded[WATEREXP+2] = true;\r
- else\r
- tileneeded[WALLEXP] = tileneeded[WALLEXP+1] = tileneeded[WALLEXP+2] = true;\r
-\r
- }\r
-\r
-\r
-//\r
-// have the caching manager load and purge stuff to make sure all marks\r
-// are in memory\r
-//\r
- CA_LoadAllSounds ();\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= LatchDrawPic\r
-=\r
-=====================\r
-*/\r
-\r
-void LatchDrawPic (unsigned x, unsigned y, unsigned picnum)\r
-{\r
- unsigned height, source, dest;\r
- unsigned wide;\r
-\r
- wide = pictable[picnum-STARTPICS].width;\r
- height = pictable[picnum-STARTPICS].height;\r
- dest = bufferofs + ylookup[y]+x;\r
- source = latchpics[picnum-FIRSTLATCHPIC];\r
-\r
- EGAWRITEMODE(1);\r
- EGAMAPMASK(15);\r
-\r
-asm mov bx,[linewidth]\r
-asm sub bx,[wide]\r
-\r
-asm mov ax,[screenseg]\r
-asm mov es,ax\r
-asm mov ds,ax\r
-\r
-asm mov si,[source]\r
-asm mov di,[dest]\r
-asm mov dx,[height] // scan lines to draw\r
-asm mov ax,[wide]\r
-\r
-lineloop:\r
-asm mov cx,ax\r
-asm rep movsb\r
-asm add di,bx\r
-\r
-asm dec dx\r
-asm jnz lineloop\r
-\r
-asm mov ax,ss\r
-asm mov ds,ax // restore turbo's data segment\r
-\r
- EGAWRITEMODE(0);\r
-}\r
-\r
-#if USE_STRIPS\r
-\r
-//--------------------------------------------------------------------------\r
-// LatchDrawPicStrip() - srcoff is distance into source file (in PIXELS!)\r
-//--------------------------------------------------------------------------\r
-void LatchDrawPicStrip (unsigned x, unsigned y, unsigned picnum, unsigned srcoff)\r
-{\r
- unsigned wide, height, source, dest, shift, srcmod;\r
-\r
- shift = (srcoff & 7) >> 1;\r
- srcoff >>= 3;\r
- wide = pictable[picnum-STARTPICS].width;\r
- srcmod = wide - linewidth + (shift != 3);\r
- if (wide > linewidth)\r
- wide = linewidth;\r
- height = pictable[picnum-STARTPICS].height;\r
- dest = bufferofs + ylookup[y]+x;\r
-\r
- picnum = ((picnum - (FIRSTSTRIPPIC+1)) >> 2) + (shift);\r
- source = latchpics[(FIRSTSTRIPPIC-FIRSTLATCHPIC+1)+picnum];\r
-\r
- EGAWRITEMODE(1);\r
- EGAMAPMASK(15);\r
-\r
-asm mov bx,[linewidth]\r
-asm sub bx,[wide]\r
-\r
-asm mov ax,[screenseg]\r
-asm mov es,ax\r
-asm mov ds,ax\r
-\r
-asm mov si,[source]\r
-asm add si,[srcoff]\r
-asm mov di,[dest]\r
-asm mov dx,[height] // scan lines to draw\r
-asm mov ax,[wide]\r
-\r
-lineloop:\r
-asm mov cx,ax\r
-asm rep movsb\r
-asm add di,bx\r
-asm add si,[srcmod]\r
-\r
-asm dec dx\r
-asm jnz lineloop\r
-\r
-asm mov ax,ss\r
-asm mov ds,ax // restore turbo's data segment\r
-\r
- EGAWRITEMODE(0);\r
-}\r
-\r
-#endif\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= Victory\r
-=\r
-=====================\r
-*/\r
-\r
-void Victory (boolean playsounds)\r
-{\r
- struct Shape shape;\r
-\r
- if (playsounds)\r
- {\r
- SD_PlaySound (GETBOLTSND);\r
- SD_WaitSoundDone ();\r
- SD_PlaySound (GETNUKESND);\r
- SD_WaitSoundDone ();\r
- SD_PlaySound (GETPOTIONSND);\r
- SD_WaitSoundDone ();\r
- SD_PlaySound (GETKEYSND);\r
- SD_WaitSoundDone ();\r
- SD_PlaySound (GETSCROLLSND);\r
- SD_WaitSoundDone ();\r
- SD_PlaySound (GETPOINTSSND);\r
- }\r
-\r
- FreeUpMemory();\r
-\r
- if (!screenfaded)\r
- VW_FadeOut();\r
-\r
- NormalScreen ();\r
-\r
- screenpage = bufferofs = 0;\r
-\r
- CA_CacheGrChunk (FINALEPIC);\r
- UNMARKGRCHUNK(FINALEPIC);\r
- VW_DrawPic(0, 0, FINALEPIC);\r
-\r
- VW_FadeIn();\r
-}\r
-\r
-//==========================================================================\r
-\r
-#if 0\r
-/*\r
-===================\r
-=\r
-= Died\r
-=\r
-===================\r
-*/\r
-\r
-void Died (void)\r
-{\r
- unsigned page1,page2;\r
-//\r
-// fizzle fade screen to grey\r
-//\r
- FreeUpMemory ();\r
- SD_PlaySound (GAMEOVERSND);\r
- bufferofs = screenloc[(screenpage+1)%3];\r
- DisplayMsg("Though fallen, your Spirit ...",NULL);\r
-// LatchDrawPic(0,0,DEADPIC);\r
-// FizzleFade(bufferofs,displayofs,VIEWWIDTH,VIEWHEIGHT,false);\r
- IN_ClearKeysDown();\r
- while (!Keyboard[sc_Enter]);\r
-// IN_Ack();\r
- VW_SetScreen (bufferofs,0);\r
- VW_ColorBorder(0);\r
-}\r
-#endif\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===================\r
-=\r
-= NormalScreen\r
-=\r
-===================\r
-*/\r
-\r
-void NormalScreen (void)\r
-{\r
- VW_SetSplitScreen (200);\r
- bufferofs = displayofs = SCREEN1START;\r
- VW_Bar(0,0,320,200,0);\r
- bufferofs = SCREEN2START;\r
- VW_Bar(0,0,320,200,0);\r
- VW_SetScreen (displayofs,0);\r
- splitscreen = false;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===================\r
-=\r
-= DrawPlayScreen\r
-=\r
-===================\r
-*/\r
-\r
-void DrawPlayScreen (void)\r
-{\r
- int i,j,p,m;\r
-\r
- screenpage = 0;\r
-\r
- bufferofs = 0;\r
- VW_Bar (0,0,320,STATUSLINES,0);\r
- for (i=0;i<3;i++)\r
- {\r
- bufferofs = screenloc[i];\r
- VW_Bar (0,0,320,VIEWHEIGHT,0);\r
- }\r
-\r
- splitscreen = true;\r
- VW_SetSplitScreen(120);\r
- VW_SetScreen(screenloc[0],0);\r
-\r
- CA_CacheGrChunk (STATUSPIC);\r
-\r
- bufferofs = 0;\r
- VW_DrawPic (0,0,STATUSPIC);\r
-\r
- grneeded[STATUSPIC] &= ~ca_levelbit;\r
- MM_SetPurge(&grsegs[STATUSPIC],3);\r
-\r
- RedrawStatusWindow ();\r
- bufferofs = displayofs = screenloc[0];\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===================\r
-=\r
-= LoadLatchMem\r
-=\r
-===================\r
-*/\r
-\r
-unsigned latchmemavail;\r
-\r
-void LoadLatchMem (void)\r
-{\r
- static unsigned base_destoff=0;\r
- static int base_numpics=0;\r
- int i,j,p,m,numpics;\r
- byte far *src, far *dest;\r
- unsigned destoff;\r
-\r
- EGAWRITEMODE(0);\r
-\r
-//\r
-// draw some pics into latch memory\r
-//\r
-\r
- if (!base_numpics)\r
- {\r
-\r
-//\r
-// tile 8s\r
-//\r
- latchpics[0] = freelatch;\r
- src = (byte _seg *)grsegs[STARTTILE8];\r
- dest = MK_FP(0xa000,freelatch);\r
-\r
- for (i=0;i<NUMTILE8;i++)\r
- {\r
- for (p=0;p<4;p++)\r
- {\r
- m = 1<<p;\r
- asm mov dx,SC_INDEX\r
- asm mov al,SC_MAPMASK\r
- asm mov ah,[BYTE PTR m]\r
- asm out dx,ax\r
- for (j=0;j<8;j++)\r
- *(dest+j)=*src++;\r
- }\r
- dest+=8;\r
- }\r
-\r
-//\r
-// tile 16s\r
-//\r
- src = (byte _seg *)grsegs[STARTTILE16];\r
-\r
- for (i=0;i<NUMTILE16;i++)\r
- {\r
- CA_CacheGrChunk (STARTTILE16+i);\r
- src = (byte _seg *)grsegs[STARTTILE16+i];\r
- if (src)\r
- {\r
- tileoffsets[i] = FP_OFF(dest);\r
- for (p=0;p<4;p++)\r
- {\r
- m = 1<<p;\r
- asm mov dx,SC_INDEX\r
- asm mov al,SC_MAPMASK\r
- asm mov ah,[BYTE PTR m]\r
- asm out dx,ax\r
- for (j=0;j<32;j++)\r
- *(dest+j)=*src++;\r
- }\r
- dest+=32;\r
- MM_FreePtr (&grsegs[STARTTILE16+i]);\r
- UNMARKGRCHUNK(STARTTILE16+i);\r
- }\r
- else\r
- tileoffsets[i] = 0;\r
- }\r
-\r
-\r
-//\r
-// pics\r
-//\r
- numpics=1;\r
- destoff = FP_OFF(dest);\r
- for (i=FIRSTLATCHPIC+1;i<FIRSTGROUNDPIC;i++)\r
- {\r
- latchpics[numpics++] = destoff;\r
- CA_CacheGrChunk (i);\r
- j = pictable[i-STARTPICS].width * pictable[i-STARTPICS].height;\r
- VW_MemToScreen (grsegs[i],destoff,j,1);\r
- destoff+=j;\r
- MM_FreePtr (&grsegs[i]);\r
- UNMARKGRCHUNK(i);\r
- }\r
-\r
- base_numpics = numpics;\r
- base_destoff = destoff;\r
-\r
- }\r
-\r
- numpics = base_numpics;\r
- destoff = base_destoff;\r
-\r
-#if USE_STRIPS\r
-//\r
-// ground pics\r
-//\r
- numpics++;\r
- for (i=FIRSTGROUNDPIC+1;i<FIRSTSTRIPPIC;i++)\r
- {\r
- int shape = (*groundcolor & 0xf0) - 16;\r
-\r
- // Is current shape needed?\r
- //\r
- if (shape != (i-(FIRSTGROUNDPIC+1)))\r
- {\r
- numpics++;\r
- continue;\r
- }\r
-\r
- latchpics[numpics++] = destoff;\r
- CA_CacheGrChunk (i);\r
- j = pictable[i-STARTPICS].width * pictable[i-STARTPICS].height;\r
- VW_MemToScreen (grsegs[i],destoff,j,1);\r
- destoff+=j;\r
- MM_FreePtr (&grsegs[i]);\r
- UNMARKGRCHUNK(i);\r
- }\r
-\r
-\r
-//\r
-// 'parallax' strips - used in place of a sky color\r
-//\r
-// Under current setup, each strip takes about 7k in latch memory.\r
-// To create 2 pixel scrolling, 4 strips are needed, that's 28k of\r
-// latch memory needed to produce this effect.\r
-//\r
- numpics++;\r
- for (i=FIRSTSTRIPPIC+1;i<FIRSTSCALEPIC;i++)\r
- {\r
- memptr work;\r
- unsigned workdest,stripsize,planesize;\r
- short loop,pic=i-STARTPICS;\r
- int shape = (*skycolor & 0xf0) - 16;\r
-\r
- // Is current shape needed?\r
- //\r
- if (shape != (i-(FIRSTSTRIPPIC+1)))\r
- {\r
- numpics++;\r
- continue;\r
- }\r
-\r
- // CAL_ShiftSprite() works with the SRC and DST in the same\r
- // segment. So we must allocate memory for two strips, and\r
- // move the base strip into that segment. Then we can use the\r
- // 2nd half of that memory for each shifted strip.\r
- //\r
- CA_CacheGrChunk (i);\r
- planesize = (pictable[pic].width+1) * pictable[pic].height;\r
- stripsize = planesize * 4;\r
-// MM_GetPtr(&work,(stripsize*2)+0000);\r
- MM_GetPtr(&work,65536);\r
- movedata((unsigned)grsegs[i],0,(unsigned)work,0,stripsize);\r
- workdest = 32768; //(stripsize+15) & 0xFFF0;\r
-\r
- // Free base strip\r
- //\r
- MM_FreePtr (&grsegs[i]);\r
- UNMARKGRCHUNK(i);\r
-\r
- // Create three shifted strips and move 'em to latch!\r
- //\r
- for (loop=3; loop; loop--)\r
- {\r
- // Produce current shift for this strip\r
- //\r
- latchpics[numpics++] = destoff;\r
- CAL_ShiftSprite ((unsigned)work,0,workdest,pictable[pic].width,\r
- pictable[pic].height,loop*2,false);\r
-\r
- // Copy this shift to latch memory\r
- //\r
- VW_MemToScreen ((memptr)((unsigned)work+(workdest>>4)),destoff,planesize,1);\r
- destoff+=planesize;\r
- }\r
-\r
- // Copy unshifted strip to latch\r
- //\r
- latchpics[numpics++] = destoff;\r
- planesize = pictable[pic].width * pictable[pic].height;\r
- VW_MemToScreen (work,destoff,planesize,1);\r
- destoff+=planesize;\r
-\r
- // Free work buffer\r
- //\r
- MM_FreePtr(&work);\r
- }\r
-#endif\r
-\r
-// Keep track of how much latch memory we have...\r
-//\r
- latchmemavail = 65535-destoff;\r
-\r
- EGAMAPMASK(15);\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===================\r
-=\r
-= FizzleOut\r
-=\r
-===================\r
-*/\r
-\r
-void FizzleOut (int showlevel)\r
-{\r
- unsigned page1,page2;\r
-//\r
-// fizzle fade screen to grey\r
-//\r
- bufferofs = screenloc[(screenpage+1)%3];\r
- if (showlevel)\r
- DrawEnterScreen ();\r
- FizzleFade(bufferofs,displayofs,VIEWWIDTH,VIEWHEIGHT,false);\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= FreeUpMemory\r
-=\r
-====================\r
-*/\r
-\r
-void FreeUpMemory (void)\r
-{\r
- int i;\r
-\r
- for (i=0;i<NUMSCALEPICS;i++)\r
- if (shapedirectory[i])\r
- MM_SetPurge (&(memptr)shapedirectory[i],3);\r
-\r
- for (i=0;i<NUMSCALEWALLS;i++)\r
- if (walldirectory[i])\r
- MM_SetPurge (&(memptr)walldirectory[i],3);\r
-}\r
-\r
-//==========================================================================\r
-\r
-#if 0\r
-\r
-/*\r
-==================\r
-=\r
-= DrawHighScores\r
-=\r
-==================\r
-*/\r
-\r
-void DrawHighScores(void)\r
-{\r
- char buffer[16],*str;\r
- word i,j,\r
- w,h,\r
- x,y;\r
- HighScore *s;\r
-\r
-\r
- CA_CacheGrChunk (HIGHSCORESPIC);\r
- VWB_DrawPic (0,0,HIGHSCORESPIC);\r
- MM_SetPurge (&grsegs[HIGHSCORESPIC],3);\r
- UNMARKGRCHUNK(HIGHSCORESPIC);\r
-\r
- for (i = 0,s = Scores;i < MaxScores;i++,s++)\r
- {\r
- PrintY = 68 + (16 * i);\r
-\r
- //\r
- // name\r
- //\r
- PrintX = 60;\r
- US_Print(s->name);\r
-\r
- //\r
- // level\r
- //\r
- ultoa(s->completed,buffer,10);\r
- for (str = buffer;*str;str++)\r
- *str = *str + (129 - '0'); // Used fixed-width numbers (129...)\r
- USL_MeasureString(buffer,&w,&h);\r
- PrintX = (25 * 8) - 8 - w;\r
- US_Print(buffer);\r
-\r
- //\r
- // score\r
- //\r
- ultoa(s->score,buffer,10);\r
- for (str = buffer;*str;str++)\r
- *str = *str + (129 - '0'); // Used fixed-width numbers (129...)\r
- USL_MeasureString(buffer,&w,&h);\r
- PrintX = (34 * 8) - 8 - w;\r
- US_Print(buffer);\r
- }\r
-\r
- fontcolor = F_BLACK;\r
-}\r
-\r
-\r
-\r
-/*\r
-=======================\r
-=\r
-= CheckHighScore\r
-=\r
-=======================\r
-*/\r
-\r
-void CheckHighScore (long score,word other)\r
-{\r
- word i,j;\r
- int n;\r
- HighScore myscore;\r
-\r
- strcpy(myscore.name,"");\r
- myscore.score = score;\r
- myscore.completed = other;\r
-\r
- for (i = 0,n = -1;i < MaxScores;i++)\r
- {\r
- if\r
- (\r
- (myscore.score > Scores[i].score)\r
- || (\r
- (myscore.score == Scores[i].score)\r
- && (myscore.completed > Scores[i].completed)\r
- )\r
- )\r
- {\r
- for (j = MaxScores;--j > i;)\r
- Scores[j] = Scores[j - 1];\r
- Scores[i] = myscore;\r
- n = i;\r
- HighScoresDirty = true;\r
- break;\r
- }\r
- }\r
-\r
- if (n != -1)\r
- {\r
- //\r
- // got a high score\r
- //\r
- DrawHighScores ();\r
- PrintY = 68 + (16 * n);\r
- PrintX = 60;\r
- US_LineInput(PrintX,PrintY,Scores[n].name,nil,true,MaxHighName,100);\r
- }\r
-}\r
-\r
-#endif\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===================\r
-=\r
-= GameLoop\r
-=\r
-===================\r
-*/\r
-\r
-void GameLoop (void)\r
-{\r
- boolean wait = false;\r
- int i,xl,yl,xh,yh;\r
- char num[20];\r
-#ifdef PROFILE\r
- clock_t start,end;\r
-#endif\r
-\r
- DrawPlayScreen ();\r
- IN_ClearKeysDown();\r
-\r
-restart:\r
- if (!loadedgame)\r
- {\r
- gamestate.difficulty = restartgame;\r
- restartgame = gd_Continue;\r
- DrawEnterScreen ();\r
- if (gamestate.mapon != 8)\r
- fizzlein = true;\r
- wait = true;\r
- }\r
-\r
- do\r
- {\r
- playstate = gd_Continue;\r
- if (!loadedgame)\r
- SetupGameLevel ();\r
- else\r
- loadedgame = false;\r
-\r
- FreeUpMemory();\r
- LoadLatchMem();\r
- CacheScaleds ();\r
-\r
- if (EASYMODEON)\r
- DisplaySMsg("*** NOVICE ***", NULL);\r
- else\r
- DisplaySMsg("*** WARRIOR ***", NULL);\r
-\r
- status_delay = 250;\r
-\r
- RedrawStatusWindow();\r
- if (wait)\r
- {\r
- VW_WaitVBL(120);\r
- wait = false;\r
- }\r
-\r
-#ifdef PROFILE\r
-start = clock();\r
-while (start == clock());\r
-start++;\r
-#endif\r
-\r
- PlayLoop ();\r
-\r
-#ifdef PROFILE\r
-end = clock();\r
-itoa(end-start,str,10);\r
- Quit (str);\r
-#endif\r
-\r
-\r
- switch (playstate)\r
- {\r
- case ex_abort:\r
- FreeUpMemory ();\r
- return;\r
- case ex_resetgame:\r
- NewGame();\r
- case ex_loadedgame:\r
- case ex_warped:\r
- FreeUpMemory();\r
- if (playstate != ex_resetgame)\r
- DisplayMsg(" ", NULL);\r
- DisplaySMsg(" ", NULL);\r
- goto restart;\r
- case ex_victorious:\r
- screenpage = 0;\r
- bufferofs = 0;\r
- status_flag = 0;\r
- return;\r
- }\r
-\r
- } while (1);\r
-\r
-}\r
-\r
-\r
-#if 0\r
-//\r
-// make wall pictures purgable\r
-//\r
- for (i=0;i<NUMSCALEWALLS;i++)\r
- if (walldirectory[i])\r
- MM_SetPurge (&(memptr)walldirectory[i],3);\r
-\r
-\r
-//\r
-// cache wall pictures back in\r
-//\r
- for (i=1;i<NUMFLOORS;i++)\r
- if (tileneeded[i])\r
- {\r
- SetupScaleWall (walllight1[i]);\r
- SetupScaleWall (walllight2[i]);\r
- SetupScaleWall (walldark1[i]);\r
- SetupScaleWall (walldark2[i]);\r
- }\r
-#endif\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// C3_MAIN.C\r
-\r
-#define CATALOG\r
-\r
-\r
-#include <time.h>\r
-#include <stdarg.h>\r
-\r
-#include "DEF.H"\r
-#include "GELIB.H"\r
-#pragma hdrstop\r
-#include <dir.h>\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-PresenterInfo MainHelpText;\r
-\r
-GameDiff restartgame;\r
-boolean loadedgame,abortgame,ingame;\r
-\r
-\r
-memptr scalesegs[NUMPICS];\r
-char str[80],str2[20];\r
-unsigned tedlevelnum;\r
-boolean tedlevel;\r
-gametype gamestate;\r
-exittype playstate;\r
-char SlowMode = 0;\r
-int starting_level;\r
-\r
-//extern unsigned scolor,gcolor; //NPM\r
-\r
-short NumGames=0;\r
-unsigned Flags=0;\r
-\r
-boolean LoadShapes = true;\r
-boolean EASYMODEON = false;\r
-\r
-void DisplayIntroText(void);\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-\r
-//===========================================================================\r
-\r
-#if 0\r
-// JAB Hack begin\r
-#define MyInterrupt 0x60\r
-void interrupt (*intaddr)();\r
-void interrupt (*oldintaddr)();\r
- char *JHParmStrings[] = {"no386",nil};\r
-\r
-void\r
-jabhack(void)\r
-{\r
-extern void far jabhack2(void);\r
-extern int far CheckIs386(void);\r
-\r
- int i;\r
-\r
- oldintaddr = getvect(MyInterrupt);\r
-\r
- for (i = 1;i < _argc;i++)\r
- if (US_CheckParm(_argv[i],JHParmStrings) == 0)\r
- return;\r
-\r
- if (CheckIs386())\r
- {\r
- jabhack2();\r
- setvect(MyInterrupt,intaddr);\r
- }\r
-}\r
-\r
-void\r
-jabunhack(void)\r
-{\r
- setvect(MyInterrupt,oldintaddr);\r
-}\r
-// JAB Hack end\r
-#endif\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= NewGame\r
-=\r
-= Set up new game to start from the beginning\r
-=\r
-=====================\r
-*/\r
-\r
-void NewGame (void)\r
-{\r
- if (!loadedgame)\r
- {\r
- memset (&gamestate,0,sizeof(gamestate));\r
- gamestate.mapon = starting_level;\r
- gamestate.body = MAXBODY;\r
- }\r
-\r
- BGFLAGS = BGF_NOT_LIGHTNING;\r
- Flags &= FL_CLEAR;\r
-\r
- boltsleft = bolttimer = 0;\r
-\r
-// memset (gamestate.levels,-1,sizeof(gamestate.levels));\r
-}\r
-\r
-//===========================================================================\r
-\r
-#define RLETAG 0xABCD\r
-\r
-/*\r
-==================\r
-=\r
-= SaveTheGame\r
-=\r
-==================\r
-*/\r
-\r
-boolean SaveTheGame(int file)\r
-{\r
- word i,compressed,expanded;\r
- objtype *o;\r
- memptr bigbuffer;\r
-\r
- // save the sky and ground colors\r
- if (!CA_FarWrite(file,(void far *)&skycolor,sizeof(skycolor)))\r
- return(false);\r
- if (!CA_FarWrite(file,(void far *)&groundcolor,sizeof(groundcolor)))\r
- return(false);\r
-\r
- if (!CA_FarWrite(file,(void far *)&FreezeTime,sizeof(FreezeTime)))\r
- return(false);\r
-\r
- if (!CA_FarWrite(file,(void far *)&gamestate,sizeof(gamestate)))\r
- return(false);\r
-\r
- if (!CA_FarWrite(file,(void far *)&EASYMODEON,sizeof(EASYMODEON)))\r
- return(false);\r
-\r
- expanded = mapwidth * mapheight * 2;\r
- MM_GetPtr (&bigbuffer,expanded);\r
-\r
- for (i = 0;i < 3;i+=2) // Write planes 0 and 2\r
- {\r
-//\r
-// leave a word at start of compressed data for compressed length\r
-//\r
- compressed = (unsigned)CA_RLEWCompress ((unsigned huge *)mapsegs[i]\r
- ,expanded,((unsigned huge *)bigbuffer)+1,RLETAG);\r
-\r
- *(unsigned huge *)bigbuffer = compressed;\r
-\r
- if (!CA_FarWrite(file,(void far *)bigbuffer,compressed+2) )\r
- {\r
- MM_FreePtr (&bigbuffer);\r
- return(false);\r
- }\r
- }\r
-\r
- for (o = player;o;o = o->next)\r
- if (!CA_FarWrite(file,(void far *)o,sizeof(objtype)))\r
- {\r
- MM_FreePtr (&bigbuffer);\r
- return(false);\r
- }\r
-\r
- MM_FreePtr (&bigbuffer);\r
-\r
- return(true);\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= LoadTheGame\r
-=\r
-==================\r
-*/\r
-\r
-boolean LoadTheGame(int file)\r
-{\r
- unsigned i,x,y;\r
- objtype *obj,*prev,*next,*followed;\r
- unsigned compressed,expanded;\r
- unsigned far *map,tile;\r
- memptr bigbuffer;\r
-\r
- screenpage = 0;\r
- FreeUpMemory();\r
-\r
- playstate = ex_loadedgame;\r
- // load the sky and ground colors\r
- if (!CA_FarRead(file,(void far *)&skycolor,sizeof(skycolor)))\r
- return(false);\r
- if (!CA_FarRead(file,(void far *)&groundcolor,sizeof(groundcolor)))\r
- return(false);\r
-\r
- if (!CA_FarRead(file,(void far *)&FreezeTime,sizeof(FreezeTime)))\r
- return(false);\r
-\r
- if (!CA_FarRead(file,(void far *)&gamestate,sizeof(gamestate)))\r
- return(false);\r
-\r
- if (!CA_FarRead(file,(void far *)&EASYMODEON,sizeof(EASYMODEON)))\r
- return(false);\r
-\r
- SetupGameLevel (); // load in and cache the base old level\r
-\r
- if (!FindFile(Filename,"SAVE GAME",-1))\r
- Quit("Error: Can't find saved game file!");\r
-\r
- expanded = mapwidth * mapheight * 2;\r
- MM_GetPtr (&bigbuffer,expanded);\r
-\r
- for (i = 0;i < 3;i+=2) // Read planes 0 and 2\r
- {\r
- if (!CA_FarRead(file,(void far *)&compressed,sizeof(compressed)) )\r
- {\r
- MM_FreePtr (&bigbuffer);\r
- return(false);\r
- }\r
-\r
- if (!CA_FarRead(file,(void far *)bigbuffer,compressed) )\r
- {\r
- MM_FreePtr (&bigbuffer);\r
- return(false);\r
- }\r
-\r
- CA_RLEWexpand ((unsigned huge *)bigbuffer,\r
- (unsigned huge *)mapsegs[i],expanded,RLETAG);\r
- }\r
-\r
- MM_FreePtr (&bigbuffer);\r
-//\r
-// copy the wall data to a data segment array again, to handle doors and\r
-// bomb walls that are allready opened\r
-//\r
- memset (tilemap,0,sizeof(tilemap));\r
- memset (actorat,0,sizeof(actorat));\r
- map = mapsegs[0];\r
- for (y=0;y<mapheight;y++)\r
- for (x=0;x<mapwidth;x++)\r
- {\r
- tile = *map++;\r
- if (tile<NUMFLOORS)\r
- {\r
- if (tile != INVISIBLEWALL)\r
- tilemap[x][y] = tile;\r
- if (tile>0)\r
- (unsigned)actorat[x][y] = tile;\r
- }\r
- }\r
-\r
-\r
- // Read the object list back in - assumes at least one object in list\r
-\r
- InitObjList ();\r
- new = player;\r
- while (true)\r
- {\r
- prev = new->prev;\r
- next = new->next;\r
- if (!CA_FarRead(file,(void far *)new,sizeof(objtype)))\r
- return(false);\r
- followed = new->next;\r
- new->prev = prev;\r
- new->next = next;\r
- actorat[new->tilex][new->tiley] = new; // drop a new marker\r
-\r
- if (followed)\r
- GetNewObj (false);\r
- else\r
- break;\r
- }\r
-\r
- return(true);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= ResetGame\r
-=\r
-==================\r
-*/\r
-\r
-void ResetGame(void)\r
-{\r
- NewGame ();\r
-\r
- ca_levelnum--;\r
- ca_levelbit>>=1;\r
- CA_ClearMarks();\r
- ca_levelbit<<=1;\r
- ca_levelnum++;\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= ShutdownId\r
-=\r
-= Shuts down all ID_?? managers\r
-=\r
-==========================\r
-*/\r
-\r
-void ShutdownId (void)\r
-{\r
- US_Shutdown ();\r
-#ifndef PROFILE\r
- SD_Shutdown ();\r
- IN_Shutdown ();\r
-#endif\r
- VW_Shutdown ();\r
- CA_Shutdown ();\r
- MM_Shutdown ();\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==========================\r
-=\r
-= InitGame\r
-=\r
-= Load a few things right away\r
-=\r
-==========================\r
-*/\r
-\r
-void InitGame (void)\r
-{\r
- unsigned segstart,seglength;\r
- int i,x,y;\r
- unsigned *blockstart;\r
-\r
-// US_TextScreen();\r
-\r
- MM_Startup ();\r
- VW_Startup ();\r
-#ifndef PROFILE\r
- IN_Startup ();\r
- SD_Startup ();\r
-#endif\r
- US_Startup ();\r
-\r
-// US_UpdateTextScreen();\r
-\r
- CA_Startup ();\r
- US_Setup ();\r
-\r
- US_SetLoadSaveHooks(LoadTheGame,SaveTheGame,ResetGame);\r
-\r
-\r
-//\r
-// load in and lock down some basic chunks\r
-//\r
-\r
- CA_ClearMarks ();\r
-\r
- CA_MarkGrChunk(STARTFONT);\r
- CA_MarkGrChunk(STARTTILE8);\r
- CA_MarkGrChunk(STARTTILE8M);\r
- CA_MarkGrChunk(HAND1PICM);\r
-\r
- CA_MarkGrChunk(NORTHICONSPR);\r
- CA_CacheMarks (NULL);\r
-\r
- MM_SetLock (&grsegs[STARTFONT],true);\r
- MM_SetLock (&grsegs[STARTTILE8],true);\r
- MM_SetLock (&grsegs[STARTTILE8M],true);\r
- MM_SetLock (&grsegs[HAND1PICM],true);\r
-\r
- fontcolor = WHITE;\r
-\r
-\r
-//\r
-// build some tables\r
-//\r
- for (i=0;i<MAPSIZE;i++)\r
- nearmapylookup[i] = &tilemap[0][0]+MAPSIZE*i;\r
-\r
- for (i=0;i<PORTTILESHIGH;i++)\r
- uwidthtable[i] = UPDATEWIDE*i;\r
-\r
- blockstart = &blockstarts[0];\r
- for (y=0;y<UPDATEHIGH;y++)\r
- for (x=0;x<UPDATEWIDE;x++)\r
- *blockstart++ = SCREENWIDTH*16*y+x*TILEWIDTH;\r
-\r
- BuildTables (); // 3-d tables\r
-\r
- SetupScaling ();\r
-\r
-#ifndef PROFILE\r
-// US_FinishTextScreen();\r
-#endif\r
-\r
-#if 0\r
-//\r
-// reclaim the memory from the linked in text screen\r
-//\r
- segstart = FP_SEG(&introscn);\r
- seglength = 4000/16;\r
- if (FP_OFF(&introscn))\r
- {\r
- segstart++;\r
- seglength--;\r
- }\r
- MML_UseSpace (segstart,seglength);\r
-#endif\r
-\r
- VW_SetScreenMode (GRMODE);\r
- ge_textmode = false;\r
-// VW_ColorBorder (3);\r
- VW_ClearVideo (BLACK);\r
-\r
-//\r
-// initialize variables\r
-//\r
- updateptr = &update[0];\r
- *(unsigned *)(updateptr + UPDATEWIDE*PORTTILESHIGH) = UPDATETERMINATE;\r
- bufferofs = 0;\r
- displayofs = 0;\r
- VW_SetLineWidth(SCREENWIDTH);\r
-}\r
-\r
-//===========================================================================\r
-\r
-void clrscr (void); // can't include CONIO.H because of name conflicts...\r
-\r
-/*\r
-==========================\r
-=\r
-= Quit\r
-=\r
-==========================\r
-*/\r
-\r
-void Quit (char *error, ...)\r
-{\r
- short exit_code=0;\r
- unsigned finscreen;\r
-\r
- va_list ap;\r
-\r
- va_start(ap,error);\r
-\r
-#ifndef CATALOG\r
- if (!error)\r
- {\r
- CA_SetAllPurge ();\r
- CA_CacheGrChunk (PIRACY);\r
- finscreen = (unsigned)grsegs[PIRACY];\r
- }\r
-#endif\r
-\r
- ShutdownId ();\r
-\r
- if (error && *error)\r
- {\r
- vprintf(error,ap);\r
- exit_code = 1;\r
- }\r
-#ifndef CATALOG\r
- else\r
- if (!NoWait)\r
- {\r
- movedata (finscreen,0,0xb800,0,4000);\r
- bioskey (0);\r
- }\r
-#endif\r
-\r
- va_end(ap);\r
-\r
-#ifndef CATALOG\r
- if (!error)\r
- {\r
- _argc = 2;\r
- _argv[1] = "LAST.SHL";\r
- _argv[2] = "ENDSCN.SCN";\r
- _argv[3] = NULL;\r
- if (execv("LOADSCN.EXE", _argv) == -1)\r
- {\r
- clrscr();\r
- puts("Couldn't find executable LOADSCN.EXE.\n");\r
- exit(1);\r
- }\r
- }\r
-#endif\r
-\r
- exit(exit_code);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= TEDDeath\r
-=\r
-==================\r
-*/\r
-\r
-void TEDDeath(void)\r
-{\r
- ShutdownId();\r
- execlp("TED5.EXE","TED5.EXE","/LAUNCH",NULL);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= DisplayDepartment\r
-=\r
-====================\r
-*/\r
-void DisplayDepartment(char *text)\r
-{\r
- short temp;\r
-\r
-// bufferofs = 0;\r
- PrintY = 1;\r
- WindowX = 0;\r
- WindowW = 320;\r
-\r
- VW_Bar(WindowX,PrintY+1,WindowW,7,7);\r
- temp = fontcolor;\r
- fontcolor = 2;\r
- US_CPrintLine (text);\r
- fontcolor = temp;\r
-}\r
-\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= DemoLoop\r
-=\r
-=====================\r
-*/\r
-\r
-void DemoLoop (void)\r
-{\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// main game cycle\r
-/////////////////////////////////////////////////////////////////////////////\r
-\r
- displayofs = bufferofs = 0;\r
- VW_Bar (0,0,320,200,0);\r
- VW_SetScreen(0,0);\r
-\r
-//\r
-// Read in all the graphic images needed for the title sequence\r
-//\r
- VW_WaitVBL(1);\r
- IN_ReadControl(0,&control);\r
-\r
-// set EASYMODE\r
-//\r
- if (stricmp(_argv[2], "1") == 0)\r
- EASYMODEON = true;\r
- else\r
- EASYMODEON = false;\r
-\r
-// restore game\r
-//\r
- if (stricmp(_argv[3], "1") == 0)\r
- {\r
- VW_FadeOut();\r
- bufferofs = displayofs = 0;\r
- VW_Bar(0,0,320,200,0);\r
- if (GE_LoadGame())\r
- {\r
- loadedgame = true;\r
- playstate = ex_loadedgame;\r
- Keyboard[sc_Enter] = true;\r
- VW_Bar(0,0,320,200,0);\r
- ColoredPalette();\r
- }\r
- VW_Bar(0,0,320,200,0);\r
- VW_FadeIn();\r
- }\r
-\r
- // Play a game\r
- //\r
- restartgame = gd_Normal;\r
- NewGame();\r
- GameLoop();\r
-}\r
-\r
-\r
-//-------------------------------------------------------------------------\r
-// DisplayIntroText()\r
-//-------------------------------------------------------------------------\r
-void DisplayIntroText()\r
-{\r
- PresenterInfo pi;\r
-\r
-#ifdef TEXT_PRESENTER\r
- char *toptext = "You stand before the gate leading into the Towne "\r
- "of Morbidity.... "\r
- "^XX";\r
-\r
- char *bottomtext = "Enter now boldly to defeat the evil Nemesis "\r
- "deep inside the catacombs."\r
- "\r
- "^XX";\r
-#endif\r
-\r
- char oldfontcolor=fontcolor;\r
-\r
- fontcolor = 14;\r
-\r
-\r
-#ifdef TEXT_PRESENTER\r
- pi.xl = 0;\r
- pi.yl = 0;\r
- pi.xh = 319;\r
- pi.yh = 1;\r
- pi.bgcolor = 0;\r
- pi.script[0] = (char far *)toptext;\r
- Presenter(&pi);\r
-\r
- pi.yl = 160;\r
- pi.yh = 161;\r
- pi.script[0] = (char far *)bottomtext;\r
- Presenter(&pi);\r
-\r
-#else\r
- PrintY = 1;\r
- PrintX = 0;\r
- WindowX = 0;\r
- WindowW = 320;\r
- US_Print (" You stand before the gate leading into\n");\r
- US_Print (" the Towne of Morbidity...\n");\r
-\r
- PrintY = 180;\r
- US_Print (" Enter now boldly to defeat the evil Nemesis\n");\r
- US_Print (" deep inside the catacombs.\n");\r
-\r
-#endif\r
-\r
- fontcolor = oldfontcolor;\r
-}\r
-\r
-#if 0\r
-boolean ChooseGameLevel()\r
-{\r
- char choices[] = {sc_Escape,sc_E,sc_N,sc_H,0},ch;\r
-\r
- CenterWindow(20,10);\r
-\r
- US_Print("\n Choose difficulty level:\n");\r
- US_Print(" (E)asy\n");\r
- US_Print(" (N)ormal\n");\r
- US_Print(" (H)ard\n");\r
- US_Print("\n (ESC)ape aborts\n");\r
-\r
-// VW_UpdateScreen();\r
- if ((ch=GetKeyChoice(choices)) == sc_Escape)\r
- {\r
- while (Keyboard[sc_Escape]);\r
- LastScan = 0;\r
- return(false);\r
- }\r
-\r
- if (ch == sc_E)\r
- restartgame = gd_Easy;\r
- else\r
- if (ch == sc_N)\r
- restartgame = gd_Normal;\r
- else\r
- restartgame = gd_Hard;\r
-\r
- return(true);\r
-}\r
-#endif\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==========================\r
-=\r
-= SetupScalePic\r
-=\r
-==========================\r
-*/\r
-\r
-void SetupScalePic (unsigned picnum)\r
-{\r
- unsigned scnum;\r
-\r
- if (picnum == 1)\r
- return;\r
-\r
- scnum = picnum-FIRSTSCALEPIC;\r
-\r
- if (shapedirectory[scnum])\r
- {\r
- MM_SetPurge (&(memptr)shapedirectory[scnum],0);\r
- return; // allready in memory\r
- }\r
-\r
- CA_CacheGrChunk (picnum);\r
- DeplanePic (picnum);\r
- shapesize[scnum] = BuildCompShape (&shapedirectory[scnum]);\r
- grneeded[picnum]&= ~ca_levelbit;\r
- MM_FreePtr (&grsegs[picnum]);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==========================\r
-=\r
-= SetupScaleWall\r
-=\r
-==========================\r
-*/\r
-\r
-void SetupScaleWall (unsigned picnum)\r
-{\r
- int x,y;\r
- unsigned scnum;\r
- byte far *dest;\r
-\r
- if (picnum == 1)\r
- return;\r
-\r
- scnum = picnum-FIRSTWALLPIC;\r
-\r
- if (walldirectory[scnum])\r
- {\r
- MM_SetPurge (&walldirectory[scnum],0);\r
- return; // allready in memory\r
- }\r
-\r
- CA_CacheGrChunk (picnum);\r
- DeplanePic (picnum);\r
- MM_GetPtr(&walldirectory[scnum],64*64);\r
- dest = (byte far *)walldirectory[scnum];\r
- for (x=0;x<64;x++)\r
- for (y=0;y<64;y++)\r
- *dest++ = spotvis[y][x];\r
- grneeded[picnum]&= ~ca_levelbit;\r
- MM_FreePtr (&grsegs[picnum]);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==========================\r
-=\r
-= SetupScaling\r
-=\r
-==========================\r
-*/\r
-\r
-void SetupScaling (void)\r
-{\r
- int i,x,y;\r
- byte far *dest;\r
-\r
-//\r
-// build the compiled scalers\r
-//\r
- for (i=1;i<=VIEWWIDTH/2;i++)\r
- BuildCompScale (i*2,&scaledirectory[i]);\r
-}\r
-\r
-//===========================================================================\r
-\r
-int showscorebox;\r
-\r
-void RF_FixOfs (void)\r
-{\r
-}\r
-\r
-void HelpScreens (void)\r
-{\r
-}\r
-\r
-\r
-#if 0\r
-/*\r
-==================\r
-=\r
-= CheckMemory\r
-=\r
-==================\r
-*/\r
-\r
-#define MINMEMORY 400000l\r
-\r
-void CheckMemory(void)\r
-{\r
- unsigned finscreen;\r
-\r
- if (Flags & FL_NOMEMCHECK)\r
- return;\r
-\r
- if (mminfo.nearheap+mminfo.farheap+mminfo.EMSmem+mminfo.XMSmem\r
- >= MINMEMORY)\r
- return;\r
-\r
- CA_CacheGrChunk (OUTOFMEM);\r
- finscreen = (unsigned)grsegs[OUTOFMEM];\r
- ShutdownId ();\r
- movedata (finscreen,7,0xb800,0,4000);\r
- gotoxy (1,24);\r
- exit(1);\r
-}\r
-#endif\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= main\r
-=\r
-==========================\r
-*/\r
-\r
-char *MainParmStrings[] = {"q","l","ver","nomemcheck","helptest",nil};\r
-\r
-void main (void)\r
-{\r
- short i;\r
-\r
- starting_level = 0;\r
-\r
- for (i = 1;i < _argc;i++)\r
- {\r
- switch (US_CheckParm(_argv[i],MainParmStrings))\r
- {\r
- case 0:\r
- Flags |= FL_QUICK;\r
- break;\r
-\r
- case 1:\r
- starting_level = atoi(_argv[i]+1);\r
- if ((starting_level < 0) || (starting_level > LASTMAP-1))\r
- starting_level = 0;\r
- break;\r
-\r
- case 2:\r
- printf("%s\n", GAMENAME);\r
- printf("Copyright 1992-93 Softdisk Publishing\n");\r
- printf("%s %s\n",VERSION,REVISION);\r
- printf("\n");\r
- exit(0);\r
- break;\r
-\r
- case 3:\r
- Flags |= FL_NOMEMCHECK;\r
- break;\r
-\r
- case 4:\r
- Flags |= (FL_HELPTEST|FL_QUICK);\r
- break;\r
- }\r
- }\r
-\r
- if (stricmp(_argv[1], "^(a@&r`"))\r
- Quit("You must type CATARM to run CATACOMB ARMAGEDDON 3-D\n");\r
-\r
- MainHelpText.xl = 0;\r
- MainHelpText.yl = 0;\r
- MainHelpText.xh = 639;\r
- MainHelpText.yh = 199;\r
- MainHelpText.bgcolor = 7;\r
- MainHelpText.ltcolor = 15;\r
- MainHelpText.dkcolor = 8;\r
-\r
-// jabhack();\r
-\r
- randomize();\r
-\r
- InitGame ();\r
-// CheckMemory ();\r
- LoadLatchMem ();\r
-\r
-// if (!LoadTextFile("MAINHELP."EXT,&MainHelpText))\r
-// Quit("Can't load MAINHELP."EXT);\r
-\r
-#ifdef PROFILE\r
- NewGame ();\r
- GameLoop ();\r
-#endif\r
-\r
- DemoLoop();\r
- Quit(NULL);\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// Display640()\r
-//-------------------------------------------------------------------------\r
-void Display640()\r
-{\r
-// Can you believe it takes all this just to change to 640 mode!!???!\r
-//\r
- VW_ScreenToScreen(0,FREESTART-STATUSLEN,40,80);\r
- VW_SetLineWidth(80);\r
- MoveScreen(0,0);\r
- VW_Bar (0,0,640,200,0);\r
- VW_SetScreenMode(EGA640GR);\r
- VW_SetLineWidth(80);\r
- BlackPalette();\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// Display320()\r
-//-------------------------------------------------------------------------\r
-void Display320()\r
-{\r
-// Can you believe it takes all this just to change to 320 mode!!???!\r
-//\r
- VW_ColorBorder(0);\r
- VW_FadeOut();\r
- VW_SetLineWidth(40);\r
- MoveScreen(0,0);\r
- VW_Bar (0,0,320,200,0);\r
- VW_SetScreenMode(EGA320GR);\r
- BlackPalette();\r
- VW_ScreenToScreen(FREESTART-STATUSLEN,0,40,80);\r
-}\r
-\r
-void PrintHelp(void)\r
-{\r
- char oldfontcolor = fontcolor;\r
- PrintY = 1;\r
- WindowX = 135;\r
- WindowW = 640;\r
-\r
- VW_FadeOut();\r
- bufferofs = displayofs = screenloc[0];\r
- VW_Bar(0,0,320,200,0);\r
-\r
- Display640();\r
-\r
- VW_Bar(0, 0, 640, 200, 7);\r
-\r
- fontcolor = (7 ^ 1);\r
- US_Print ("\n\n SUMMARY OF GAME CONTROLS\n\n");\r
-\r
- fontcolor = (7 ^ 4);\r
- US_Print (" ACTION\n\n");\r
-\r
- US_Print ("Arrow keys, joystick, or mouse\n");\r
- US_Print ("TAB or V while turning\n");\r
- US_Print ("ALT or Button 2 while turning\n");\r
- US_Print ("CTRL or Button 1\n");\r
- US_Print ("Z\n");\r
- US_Print ("X or Enter\n");\r
- US_Print ("F1\n");\r
- US_Print ("F2\n");\r
- US_Print ("F3\n");\r
- US_Print ("F4\n");\r
- US_Print ("F5\n");\r
- US_Print ("ESC\n\n");\r
-#ifndef CATALOG\r
- fontcolor = (7 ^ 0);\r
- US_Print (" (See complete Instructions for more info)\n");\r
-#endif\r
-\r
- fontcolor = (7 ^ 8);\r
- PrintX = 400;\r
- PrintY = 37;\r
- WindowX = 400;\r
- US_Print (" REACTION\n\n");\r
- US_Print ("Move and turn\n");\r
- US_Print ("Turn quickly (Quick Turn)\n");\r
- US_Print ("Move sideways\n");\r
- US_Print ("Shoot a Missile\n");\r
- US_Print ("Shoot a Zapper\n");\r
- US_Print ("Shoot an Xterminator\n");\r
- US_Print ("Help (this screen)\n");\r
- US_Print ("Sound control\n");\r
- US_Print ("Save game position\n");\r
- US_Print ("Restore a saved game\n");\r
- US_Print ("Joystick control\n");\r
- US_Print ("System options\n\n\n");\r
-\r
- VW_UpdateScreen();\r
- VW_FadeIn();\r
- VW_ColorBorder(8 | 56);\r
- IN_Ack();\r
- Display320();\r
- fontcolor = oldfontcolor;\r
-}
\ No newline at end of file
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// C3_PLAY.C\r
-\r
-#include "DEF.H"\r
-#include "gelib.h"\r
-#pragma hdrstop\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define POINTTICS 6\r
-#define PAUSE 300\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-byte bcolor;\r
-short skytimer=-1,skytimer_reset;\r
-short groundtimer=-1,groundtimer_reset;\r
-\r
-unsigned scolor,gcolor;\r
-unsigned *skycolor,*groundcolor,debug_sky,debug_gnd;\r
-\r
-unsigned nocolorchange=0xFFFF;\r
-byte BGFLAGS, // global that holds all current flags\r
- bgflag; // used by BG changer, this flag is set when done\r
-\r
-\r
-unsigned sky_daytonight[]={0x0909,0x0101,0x0808,0x0000,0xFFFF};\r
-//unsigned gnd_daytonight[]={0x0202,0xFFFF};\r
-\r
-unsigned sky_lightning[]={0x0101,0x0909,0x0f0f,0x0808,0x0000,0xFFFF};\r
-\r
-unsigned sky_colors[NUMLEVELS]={0x0000,0x0000,0x0000,0x0000,0x0808,\r
- 0x0404,0x0000,0x0000,0x0000,0x0000,\r
- 0x0000,0x0000,0x0000,0x0000,0x0606,\r
- 0x0000,0x0000,0x0000,0x0000,0x0000,\r
- 0x0000};\r
-unsigned gnd_colors[NUMLEVELS]={0x0202,0x0202,0x0606,0x0202,0x0707,\r
- 0x0505,0x0808,0x0606,0x0101,0x0808,\r
- 0x0606,0x0404,0x0808,0x0c0c,0x0e0e,\r
- 0x0808,0x0808,0x0c0c,0x0000,0x0707,\r
- 0x0808};\r
-\r
-\r
-ControlInfo control;\r
-boolean running=false; //,slowturn;\r
-\r
-int bordertime;\r
-objtype objlist[MAXACTORS],*new,*obj,*player,*lastobj,*objfreelist;\r
-\r
-#if USE_INERT_LIST\r
-inertobjtype inertobjlist[MAXINERTOBJ],*inert;\r
-#endif\r
-\r
-unsigned farmapylookup[MAPSIZE];\r
-byte *nearmapylookup[MAPSIZE];\r
-\r
-boolean singlestep,godmode;\r
-int extravbls;\r
-status_flags status_flag;\r
-int status_delay;\r
-\r
-//\r
-// replacing refresh manager\r
-//\r
-unsigned mapwidth,mapheight,tics,realtics;\r
-boolean compatability;\r
-byte *updateptr;\r
-unsigned mapwidthtable[64];\r
-unsigned uwidthtable[UPDATEHIGH];\r
-unsigned blockstarts[UPDATEWIDE*UPDATEHIGH];\r
-#define UPDATESCREENSIZE (UPDATEWIDE*PORTTILESHIGH+2)\r
-#define UPDATESPARESIZE (UPDATEWIDE*2+4)\r
-#define UPDATESIZE (UPDATESCREENSIZE+2*UPDATESPARESIZE)\r
-byte update[UPDATESIZE];\r
-\r
-int mousexmove,mouseymove;\r
-int pointcount,pointsleft;\r
-\r
-short BeepTime = 0;\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-void CalcBounds (objtype *ob);\r
-void DrawPlayScreen (void);\r
-void PreFullDisplay(void);\r
-void PostFullDisplay(boolean draw_view);\r
-\r
-\r
-//\r
-// near data map array (wall values only, get text number from far data)\r
-//\r
-byte tilemap[MAPSIZE][MAPSIZE];\r
-byte spotvis[MAPSIZE][MAPSIZE];\r
-objtype *actorat[MAPSIZE][MAPSIZE];\r
-\r
-objtype dummyobj;\r
-\r
-int bordertime;\r
-int objectcount;\r
-\r
-void StopMusic(void);\r
-void StartMusic(void);\r
-\r
-void CalibrateJoystick(short joynum);\r
-\r
-//==========================================================================\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// CenterWindow() - Generates a window of a given width & height in the\r
-// middle of the screen\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-\r
-#define MAXX 320\r
-#define MAXY 120\r
-\r
-void CenterWindow(word w,word h)\r
-{\r
- US_DrawWindow(((MAXX / 8) - w) / 2,((MAXY / 8) - h) / 2,w,h);\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= CheckKeys\r
-=\r
-=====================\r
-*/\r
-\r
-void CheckKeys (void)\r
-{\r
- extern boolean autofire;\r
-\r
- if (screenfaded) // don't do anything with a faded screen\r
- return;\r
-\r
-#if 0\r
-//\r
-// pause key wierdness can't be checked as a scan code\r
-//\r
- if (Paused)\r
- {\r
- CenterWindow (8,3);\r
- US_PrintCentered ("PAUSED");\r
- VW_UpdateScreen ();\r
-// SD_MusicOff();\r
- IN_Ack();\r
-// SD_MusicOn();\r
- Paused = false;\r
- if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement\r
- }\r
- else\r
- if (Keyboard[sc_Enter]) // P = pause with no screen disruptioon\r
- {\r
-// SD_MusicOff();\r
- DisplaySMsg("PAUSED",NULL);\r
- IN_Ack();\r
-// SD_MusicOn();\r
- if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement\r
- }\r
- else\r
- if (Keyboard[sc_S])\r
- {\r
- char *Text[] = {{"Slow Mode ON"},{"Slow Mode OFF"}};\r
-\r
- SlowMode ^= 1;\r
- extravbls = SlowMode << 3;\r
- CenterWindow (8,3);\r
- US_PrintCentered (Text[SlowMode]);\r
- VW_UpdateScreen ();\r
-// SD_MusicOff();\r
- IN_Ack();\r
-// SD_MusicOn();\r
- if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement\r
- }\r
-#endif\r
-\r
-\r
-// F2 - SOUND OPTIONS\r
-//\r
- if (Keyboard[sc_F2])\r
- {\r
- int height=7;\r
- boolean ChoiceMade = false;\r
-\r
- if (AdLibPresent)\r
- height++;\r
-\r
- VW_FixRefreshBuffer();\r
- CenterWindow(22,height);\r
- US_Print( "\n 1 ) NO SOUND \n");\r
- US_Print( " 2 ) PC AUDIO \n");\r
-\r
- if (AdLibPresent)\r
- US_Print(" 3 ) ADLIB AUDIO\n");\r
-\r
- US_Print( "\n ESC) EXIT ");\r
- VW_UpdateScreen();\r
-\r
- // Switch audio device ON/OFF & load sounds if there\r
- // was a change in the device.\r
-\r
- do {\r
-\r
- if (Keyboard[1]) // ESC - Exit\r
- ChoiceMade = true;\r
- else\r
- if (Keyboard[2]) // 1 - No Sound\r
- {\r
- SD_SetSoundMode(sdm_Off);\r
- ChoiceMade = true;\r
- }\r
- else\r
- if (Keyboard[3]) // 2 - PC Audio\r
- {\r
- SD_SetSoundMode(sdm_PC);\r
-// if (oldsoundmode != sdm_PC)\r
- CA_LoadAllSounds();\r
- ChoiceMade = true;\r
- }\r
- else\r
- if ((Keyboard[4]) && AdLibPresent) // 3 - AdLib Audio\r
- {\r
- SD_SetSoundMode(sdm_AdLib);\r
-// if (oldsoundmode != sdm_AdLib)\r
- CA_LoadAllSounds();\r
- ChoiceMade = true;\r
- }\r
-\r
- } while (!ChoiceMade);\r
- tics = realtics = 1;\r
- IN_ClearKeysDown();\r
- }\r
-\r
-// F5 - CALIBRATE JOYSTICK\r
-//\r
- if (Keyboard[sc_F5])\r
- {\r
- CalibrateJoystick(0);\r
- tics = realtics = 1;\r
- IN_ClearKeysDown();\r
- }\r
-\r
-deadloop:;\r
-// ESCAPE - quits game\r
-//\r
- if ((Keyboard[sc_Escape]) || (Flags & FL_DEAD))\r
- {\r
- char ch;\r
-\r
- DisplaySMsg("Options", NULL);\r
- status_flag = S_NONE;\r
-\r
-\r
- if (Flags & FL_DEAD)\r
- {\r
- char choices[] = {sc_Escape,sc_R,sc_N,sc_Q,0};\r
- ch = DisplayMsg("Restore New Quit",choices);\r
- }\r
- else\r
- {\r
- char choices[] = {sc_Escape,sc_S,sc_R,sc_N,sc_Q,0};\r
- ch = DisplayMsg("Save Restore New Quit",choices);\r
- }\r
- DrawText(true);\r
-\r
- switch (ch)\r
- {\r
- case sc_S:\r
- if (!(Flags & FL_DEAD))\r
- Keyboard[sc_F3] = true;\r
- break;\r
-\r
- case sc_R:\r
- Keyboard[sc_F4] = true;\r
- break;\r
-\r
- case sc_N:\r
- DisplaySMsg("Starting anew", NULL);\r
- VW_WaitVBL(60);\r
- playstate = ex_resetgame;\r
- Flags &= ~FL_DEAD;\r
- break;\r
-\r
- case sc_Q:\r
- DisplaySMsg("FARE THEE WELL!", NULL);\r
- VW_WaitVBL(120);\r
- if (!Flags & FL_QUICK)\r
- VW_FadeOut();\r
- NormalScreen();\r
- FreeUpMemory();\r
- Quit(NULL);\r
- break;\r
- }\r
- tics = realtics = 1;\r
- }\r
-\r
-// F1 - DISPLAY HELP\r
-//\r
- if (Keyboard[sc_F1])\r
- {\r
- PrintHelp();\r
-\r
-#ifdef TEXT_PRESENTER\r
-\r
- extern PresenterInfo MainHelpText;\r
-\r
- VW_FadeOut();\r
-\r
- FreeUpMemory();\r
- if (!LoadPresenterScript("HELP.TXT",&MainHelpText))\r
- {\r
- VW_FadeIn();\r
- CenterWindow(30,5);\r
- US_CPrint("\nError loading HELP file.\n");\r
- US_CPrint("Press any key.");\r
- IN_Ack();\r
- VW_FadeOut();\r
- }\r
- else\r
- {\r
- VW_SetSplitScreen(200);\r
- bufferofs = displayofs = screenloc[0];\r
- VW_Bar(0,0,320,200,0);\r
-\r
- Display640();\r
- Presenter(&MainHelpText);\r
- Display320();\r
- }\r
- FreePresenterScript(&MainHelpText);\r
-#endif\r
- VW_SetSplitScreen(120);\r
- VW_SetScreen(screenloc[0],0);\r
- screenpage = 0;\r
- CacheScaleds();\r
-\r
- bufferofs = 0;\r
- RedrawStatusWindow();\r
- ThreeDRefresh();\r
- VW_FadeIn();\r
- Keyboard[sc_F1] = false;\r
- tics = realtics = 1;\r
- IN_ClearKeysDown();\r
- }\r
-\r
-// F3 - SAVE GAME\r
-//\r
- if ((Keyboard[sc_F3]) && (!(Flags & FL_DEAD)))\r
- {\r
- PreFullDisplay();\r
- GE_SaveGame();\r
- PostFullDisplay(true);\r
- tics = realtics = 1;\r
- IN_ClearKeysDown();\r
- }\r
-\r
-// F4 - LOAD GAME\r
-//\r
- if (Keyboard[sc_F4])\r
- {\r
- PreFullDisplay();\r
- if (GE_LoadGame())\r
- {\r
- loadedgame = true;\r
- playstate = ex_loadedgame;\r
- Flags &= ~FL_DEAD;\r
- lasttext = -1;\r
- PostFullDisplay(false);\r
- }\r
- else\r
- if (playstate == ex_victorious)\r
- {\r
- PostFullDisplay(false);\r
- Victory(false);\r
- IN_Ack();\r
-// gamestate.mapon++;\r
- }\r
- else\r
- PostFullDisplay(true);\r
- Keyboard[sc_F5] = false;\r
- tics = realtics = 1;\r
- IN_ClearKeysDown();\r
- }\r
-\r
- if (Flags & FL_DEAD)\r
- goto deadloop;\r
-\r
-//\r
-// F10-? debug keys\r
-//\r
- if (Keyboard[sc_BackSpace])\r
- {\r
- DebugKeys();\r
- if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement\r
- lasttimecount = TimeCount;\r
- }\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// PreFullDisplay()\r
-//-------------------------------------------------------------------------\r
-void PreFullDisplay()\r
-{\r
- VW_FadeOut();\r
- VW_SetSplitScreen(200);\r
- bufferofs = displayofs = screenloc[0];\r
- VW_Bar(0,0,320,200,0);\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// PostFullDisplay()\r
-//-------------------------------------------------------------------------\r
-void PostFullDisplay(boolean draw_view)\r
-{\r
- VW_SetSplitScreen(120);\r
- bufferofs = 0;\r
- RedrawStatusWindow();\r
- if (draw_view)\r
- {\r
- ThreeDRefresh();\r
- VW_FadeIn();\r
- }\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-#############################################################################\r
-\r
- The objlist data structure\r
-\r
-#############################################################################\r
-\r
-objlist containt structures for every actor currently playing. The structure\r
-is accessed as a linked list starting at *player, ending when ob->next ==\r
-NULL. GetNewObj inserts a new object at the end of the list, meaning that\r
-if an actor spawn another actor, the new one WILL get to think and react the\r
-same frame. RemoveObj unlinks the given object and returns it to the free\r
-list, but does not damage the objects ->next pointer, so if the current object\r
-removes itself, a linked list following loop can still safely get to the\r
-next element.\r
-\r
-<backwardly linked free list>\r
-\r
-#############################################################################\r
-*/\r
-\r
-\r
-/*\r
-=========================\r
-=\r
-= InitObjList\r
-=\r
-= Call to clear out the entire object list, returning them all to the free\r
-= list. Allocates a special spot for the player.\r
-=\r
-=========================\r
-*/\r
-\r
-void InitObjList (void)\r
-{\r
- int i;\r
-\r
- for (i=0;i<MAXACTORS;i++)\r
- {\r
- objlist[i].prev = &objlist[i+1];\r
- objlist[i].next = NULL;\r
- }\r
-\r
- objlist[MAXACTORS-1].prev = NULL;\r
-\r
- objfreelist = &objlist[0];\r
- lastobj = NULL;\r
-\r
- objectcount = 0;\r
-\r
-//\r
-// give the player and score the first free spots\r
-//\r
- GetNewObj (false);\r
- player = new;\r
-\r
-#if USE_INERT_LIST\r
- inert = inertobjlist;\r
-#endif\r
-\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=========================\r
-=\r
-= GetNewObj\r
-=\r
-= Sets the global variable new to point to a free spot in objlist.\r
-= The free spot is inserted at the end of the liked list\r
-=\r
-= When the object list is full, the caller can either have it bomb out ot\r
-= return a dummy object pointer that will never get used\r
-=\r
-=========================\r
-*/\r
-\r
-void GetNewObj (boolean usedummy)\r
-{\r
- if (!objfreelist)\r
- {\r
- if (usedummy)\r
- {\r
- new = &dummyobj;\r
- return;\r
- }\r
- Quit ("GetNewObj: No free spots in objlist!");\r
- }\r
-\r
- new = objfreelist;\r
- objfreelist = new->prev;\r
- memset (new,0,sizeof(*new));\r
-\r
- if (lastobj)\r
- lastobj->next = new;\r
- new->prev = lastobj; // new->next is allready NULL from memset\r
-\r
- new->active = false;\r
- lastobj = new;\r
-\r
- objectcount++;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=========================\r
-=\r
-= RemoveObj\r
-=\r
-= Add the given object back into the free list, and unlink it from it's\r
-= neighbors\r
-=\r
-=========================\r
-*/\r
-\r
-void RemoveObj (objtype *gone)\r
-{\r
- objtype **spotat;\r
-\r
- if (gone == player)\r
- Quit ("RemoveObj: Tried to remove the player!");\r
-\r
-//\r
-// fix the next object's back link\r
-//\r
- if (gone == lastobj)\r
- lastobj = (objtype *)gone->prev;\r
- else\r
- gone->next->prev = gone->prev;\r
-\r
-//\r
-// fix the previous object's forward link\r
-//\r
- gone->prev->next = gone->next;\r
-\r
-//\r
-// add it back in to the free list\r
-//\r
- gone->prev = objfreelist;\r
- objfreelist = gone;\r
-\r
- objectcount--;\r
-}\r
-\r
-#if USE_INERT_LIST\r
-\r
-//--------------------------------------------------------------------------\r
-// MoveObjToInert()\r
-//--------------------------------------------------------------------------\r
-void MoveObjToInert(objtype *obj)\r
-{\r
-\r
- if (inert == &inertobjlist[MAXINERTOBJ])\r
- return;\r
-\r
-// Transfer info needed by inert objtype\r
-//\r
- inert->x = obj->x;\r
- inert->y = obj->y;\r
- inert->size = obj->size;\r
- inert->viewx = obj->viewx;\r
- inert->tilex = obj->tilex;\r
- inert->tiley = obj->tiley;\r
- inert->state = obj->state;\r
- inert->ticcount = obj->ticcount;\r
-\r
-// Setup links between inert objects\r
-//\r
- if (inert != inertobjlist)\r
- (inert-1)->next = inert;\r
- inert->next = NULL;\r
- inert++;\r
-\r
-// Free 'real' object from list.\r
-//\r
- RemoveObj(obj);\r
-}\r
-\r
-#endif\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===================\r
-=\r
-= PollControls\r
-=\r
-===================\r
-*/\r
-\r
-void PollControls (void)\r
-{\r
- unsigned buttons;\r
-\r
- IN_ReadControl(0,&control);\r
-\r
- if (MousePresent)\r
- {\r
- Mouse(MButtons);\r
- buttons = _BX;\r
- Mouse(MDelta);\r
- mousexmove = _CX;\r
- mouseymove = _DX;\r
-\r
- if (buttons&1)\r
- control.button0 = 1;\r
- if (buttons&2)\r
- control.button1 = 1;\r
-\r
- }\r
-\r
- if (Keyboard[sc_V] || Keyboard[sc_Tab])\r
- running = true;\r
- else\r
- running = false;\r
-}\r
-\r
-//==========================================================================\r
-\r
-#if 0\r
-/*\r
-=================\r
-=\r
-= StopMusic\r
-=\r
-=================\r
-*/\r
-\r
-void StopMusic(void)\r
-{\r
- int i;\r
-\r
- SD_MusicOff();\r
- for (i = 0;i < LASTMUSIC;i++)\r
- if (audiosegs[STARTMUSIC + i])\r
- {\r
- MM_SetPurge(&((memptr)audiosegs[STARTMUSIC + i]),3);\r
- MM_SetLock(&((memptr)audiosegs[STARTMUSIC + i]),false);\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= StartMusic\r
-=\r
-=================\r
-*/\r
-\r
-// JAB - Cache & start the appropriate music for this level\r
-void StartMusic(void)\r
-{\r
- musicnames chunk;\r
-\r
- SD_MusicOff();\r
- chunk = TOOHOT_MUS;\r
-// if ((chunk == -1) || (MusicMode != smm_AdLib))\r
-//DEBUG control panel return;\r
-\r
- MM_BombOnError (false);\r
- CA_CacheAudioChunk(STARTMUSIC + chunk);\r
- MM_BombOnError (true);\r
- if (mmerror)\r
- mmerror = false;\r
- else\r
- {\r
- MM_SetLock(&((memptr)audiosegs[STARTMUSIC + chunk]),true);\r
- SD_StartMusic((MusicGroup far *)audiosegs[STARTMUSIC + chunk]);\r
- }\r
-}\r
-#endif\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= PlayLoop\r
-=\r
-===================\r
-*/\r
-\r
-void PlayLoop (void)\r
-{\r
- char shot_color[3] = {4,9,14};\r
-\r
- int allgems[5]={GEM_DELAY_TIME, // used for Q & D comparison\r
- GEM_DELAY_TIME, // for having all gems...\r
- GEM_DELAY_TIME, // the "allgems" declaration MUST\r
- GEM_DELAY_TIME, // match the "gems" declaration in\r
- GEM_DELAY_TIME // the gametype structure!\r
- };\r
-\r
-// int originx=0;\r
-// int i=100;\r
- signed long dx,dy,radius,psin,pcos,newx,newy;\r
- int give;\r
- short objnum;\r
- signed long ox,oy,xl,xh,yl,yh,px,py,norm_dx,norm_dy;\r
- short o_radius;\r
-\r
- void (*think)();\r
-\r
- ingame = true;\r
- playstate = TimeCount = 0;\r
- gamestate.shotpower = handheight = 0;\r
- pointcount = pointsleft = 0;\r
-\r
- status_flag = S_NONE;\r
-\r
-#if 0\r
- // setup sky/ground colors and effects (based on level)\r
- //\r
- switch (gamestate.mapon)\r
- {\r
- case 255:\r
- if (!(BGFLAGS & BGF_NIGHT))\r
- {\r
- InitBgChange(3*60,sky_daytonight,-1,NULL,BGF_NIGHT);\r
- groundcolor = &gnd_colors[0];\r
- }\r
- else\r
- {\r
- skycolor = &sky_colors[0];\r
- groundcolor = &gnd_colors[0];\r
- }\r
- break;\r
-\r
- default:\r
- skycolor = &sky_colors[gamestate.mapon];\r
- groundcolor = &gnd_colors[gamestate.mapon];\r
- skytimer = groundtimer = -1;\r
- break;\r
- }\r
-#endif\r
-\r
- BGFLAGS |= BGF_NOT_LIGHTNING;\r
- skytimer = groundtimer = -1;\r
-\r
- debug_gnd = *groundcolor;\r
- debug_sky = *skycolor;\r
- RedrawStatusWindow();\r
- ThreeDRefresh();\r
- if (screenfaded)\r
- VW_FadeIn();\r
-\r
-#ifndef PROFILE\r
- fizzlein = true; // fizzle fade in the first refresh\r
-#endif\r
- TimeCount = lasttimecount = lastnuke = 0;\r
-\r
- PollControls (); // center mouse\r
-// StartMusic ();\r
- do\r
- {\r
-#ifndef PROFILE\r
- PollControls();\r
-#else\r
- control.xaxis = 1;\r
- if (++TimeCount == 300)\r
- return;\r
-#endif\r
- DisplayStatus(&status_flag);\r
-\r
- objnum=0;\r
- for (obj = player;obj;obj = obj->next)\r
- {\r
- if ((obj->active >= yes) && (!(FreezeTime && (obj!=player))))\r
- {\r
- if (obj->ticcount)\r
- {\r
- obj->ticcount-=realtics;\r
- while ( obj->ticcount <= 0)\r
- {\r
- think = obj->state->think;\r
- if (think)\r
- {\r
- statetype *oldstate=obj->state;\r
-\r
- think (obj);\r
- if (!obj->state)\r
- {\r
- RemoveObj (obj);\r
- goto nextactor;\r
- }\r
- if (obj->state != oldstate)\r
- break;\r
- }\r
-\r
- obj->state = obj->state->next;\r
- if (!obj->state)\r
- {\r
- RemoveObj (obj);\r
- goto nextactor;\r
- }\r
- if (!obj->state->tictime)\r
- {\r
- obj->ticcount = 0;\r
- goto nextactor;\r
- }\r
- if (obj->state->tictime>0)\r
- obj->ticcount += obj->state->tictime;\r
- }\r
- }\r
-\r
- think = obj->state->think;\r
- if (think)\r
- {\r
- think (obj);\r
- if (!obj->state)\r
- RemoveObj (obj);\r
- }\r
-nextactor:;\r
- }\r
-\r
- // keep a list of objects around the player for radar updates\r
- //\r
- if (obj == player)\r
- {\r
- px = player->x;\r
- py = player->y;\r
- psin = sintable[player->angle];\r
- pcos = costable[player->angle];\r
- xl = px-((long)RADAR_WIDTH<<TILESHIFT)/2;\r
- xh = px+((long)RADAR_WIDTH<<TILESHIFT)/2-1;\r
- yl = py-((long)RADAR_HEIGHT<<TILESHIFT)/2;\r
- yh = py+((long)RADAR_HEIGHT<<TILESHIFT)/2;\r
- }\r
-\r
- if (objnum > MAX_RADAR_BLIPS-2)\r
- objnum = MAX_RADAR_BLIPS-2;\r
-\r
- ox = obj->x;\r
- oy = obj->y;\r
-\r
-\r
- if ((ox >= xl) && (ox <= xh) && (oy >= yl) && (oy <= yh))\r
- {\r
- norm_dx = (dx = px-ox)>>TILESHIFT;\r
- norm_dy = (dy = oy-py)>>TILESHIFT;\r
-\r
- o_radius = IntSqrt((norm_dx * norm_dx) + (norm_dy * norm_dy));\r
-\r
- if (o_radius < RADAR_RADIUS)\r
- {\r
- newx = FixedByFrac(dy,pcos)-FixedByFrac(dx,psin);\r
- newy = FixedByFrac(dy,psin)+FixedByFrac(dx,pcos);\r
-\r
- RadarXY[objnum][0]=newx>>TILESHIFT;\r
- RadarXY[objnum][1]=newy>>TILESHIFT;\r
-\r
- // Define color to use for this object...\r
- //\r
-\r
- switch (obj->obclass)\r
- {\r
- // NO GEM NEEDED\r
- //\r
- // THE WIZARD! (YOU)\r
- //\r
- case playerobj:\r
- RadarXY[objnum++][2]=15;\r
- break;\r
-\r
- // WIZARD'S SHOTS\r
- //\r
- case pshotobj:\r
- case bigpshotobj:\r
- RadarXY[objnum++][2]=shot_color[screenpage];\r
- break;\r
-\r
- // BATS (DK GRAY)\r
- //\r
- case batobj:\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=8;\r
- break;\r
-\r
- // RABBITS (LT GRAY)\r
- //\r
- case bunnyobj:\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=7;\r
- break;\r
-\r
- // RED GEM\r
- //\r
- // EYE, RED DEMON (DK RED)\r
- //\r
- case eyeobj:\r
- case reddemonobj:\r
- if (gamestate.gems[B_RGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=4;\r
- break;\r
-\r
- // RED MAGE (LT RED)\r
- //\r
- case mageobj:\r
- if (gamestate.gems[B_RGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=12;\r
- break;\r
-\r
- // BLUE GEM\r
- //\r
- // SUCCUBUS (LT BLUE)\r
- //\r
- case succubusobj:\r
- if (gamestate.gems[B_BGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=9;\r
- break;\r
-\r
- // WATER DRAGON (DK BLUE)\r
- //\r
- case wetobj:\r
- if (gamestate.gems[B_GGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=1;\r
- break;\r
-\r
-\r
-\r
- // GREEN GEM\r
- //\r
- // GREEN TROLL (LT GREEN)\r
- //\r
- case fatdemonobj:\r
- if (gamestate.gems[B_GGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=10;\r
- break;\r
-\r
- // GODESS (DK GREEN)\r
- //\r
- case godessobj:\r
- if (gamestate.gems[B_GGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=2;\r
- break;\r
-\r
- // YELLOW GEM\r
- //\r
- // ANT (BROWN)\r
- //\r
- case antobj:\r
- case treeobj:\r
- if (gamestate.gems[B_YGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=6;\r
- break;\r
-\r
- // SKELETON (YELLOW)\r
- //\r
- case skeletonobj:\r
- if (gamestate.gems[B_YGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=14;\r
- break;\r
-\r
- // PURPLE GEM\r
- //\r
- // ZOMBIE\r
- //\r
- case zombieobj:\r
- if (gamestate.gems[B_PGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=13;\r
- break;\r
-\r
- // ALL GEMS NEEDED\r
- //\r
- // NEMESIS\r
- //\r
- case grelmobj:\r
- if (!memcmp(gamestate.gems,allgems,sizeof(gamestate.gems)))\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=15;\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- RadarXY[objnum][2]=-1; // Signals end of RadarXY list...\r
-\r
-#if USE_INERT_LIST\r
- if (inert != inertobjlist)\r
- for (obj=(objtype *)inertobjlist;obj;obj=obj->next)\r
- if (obj->ticcount)\r
- {\r
- obj->ticcount-=realtics;\r
- while ( obj->ticcount <= 0)\r
- {\r
- obj->state = obj->state->next;\r
- if (!obj->state)\r
- Quit("Removable object in INERT list.");\r
-\r
- if (!obj->state->tictime)\r
- {\r
- obj->ticcount = 0;\r
- goto nextactor;\r
- }\r
-\r
- if (obj->state->tictime>0)\r
- obj->ticcount += obj->state->tictime;\r
- }\r
- }\r
-#endif\r
-\r
- if (bordertime)\r
- {\r
- bordertime -= realtics;\r
- if (bordertime<=0)\r
- {\r
- bordertime = 0;\r
- VW_ColorBorder(0);\r
- }\r
- }\r
-\r
-#if 1\r
-// random lightning?\r
-//\r
- if (BGFLAGS & (BGF_NOT_LIGHTNING))\r
- {\r
- if ((scolor & 0xe0) && (!(random(20-realtics))))\r
- {\r
- BGFLAGS &= ~BGF_NOT_LIGHTNING;\r
- InitBgChange(1,sky_lightning,-1,NULL,BGF_NOT_LIGHTNING);\r
- }\r
- }\r
-\r
-// handle sky/ground color changes\r
-//\r
- if (skytimer != -1)\r
- {\r
- skytimer -= realtics;\r
- if (skytimer < 0)\r
- {\r
- skycolor++;\r
- if (*skycolor == 0xffff)\r
- {\r
- skytimer = -1;\r
-// skycolor--;\r
- skycolor = &scolor;\r
- if (groundtimer == -1)\r
- BGFLAGS |= bgflag;\r
- }\r
- else\r
- skytimer = skytimer_reset;\r
- }\r
- }\r
-\r
- if (groundtimer != -1)\r
- {\r
- groundtimer -= realtics;\r
- if (groundtimer < 0)\r
- {\r
- groundcolor++;\r
- if (*groundcolor == 0xffff)\r
- {\r
- groundtimer = -1;\r
-// groundcolor--;\r
- groundcolor = &gcolor;\r
- if (skytimer == -1)\r
- BGFLAGS |= bgflag;\r
- }\r
- else\r
- groundtimer = groundtimer_reset;\r
- }\r
- }\r
-#endif\r
-\r
-\r
-//\r
-// Handle FreezeTime counter..\r
-//\r
- if (FreezeTime)\r
- {\r
- if (FreezeTime<20*30)\r
- if ((BeepTime+=realtics)>=60)\r
- {\r
- BeepTime -= 60;\r
- SD_PlaySound(TICKSND);\r
- }\r
-\r
- if ((FreezeTime-=realtics)<=0)\r
- {\r
- FreezeTime=0;\r
- SD_PlaySound(TIMERETURNSND);\r
- DisplaySMsg(NULL,NULL);\r
- status_flag = S_NONE;\r
- }\r
- }\r
-\r
-\r
-// refresh all\r
-//\r
- ThreeDRefresh ();\r
-\r
- if (Flags & FL_DEAD)\r
- {\r
- SD_PlaySound (GAMEOVERSND);\r
- DisplaySMsg("DEAD",NULL);\r
- DrawHealth();\r
- if (gamestate.potions)\r
- {\r
- bufferofs = displayofs = screenloc[screenpage];\r
- CenterWindow(35,3);\r
- US_CPrint("\nYou should use your Cure Potions wisely\n");\r
- IN_Ack();\r
- }\r
- }\r
-\r
-// check for win\r
-//\r
- if (playstate == ex_victorious)\r
- {\r
- Victory(true);\r
-// Flags |= FL_DEAD;\r
- IN_Ack();\r
-// gamestate.mapon++;\r
- }\r
-\r
- CheckKeys();\r
-\r
- }while (!playstate);\r
-// StopMusic ();\r
-\r
- ingame = false;\r
- if (bordertime)\r
- {\r
- bordertime = 0;\r
- VW_ColorBorder(0);\r
- }\r
-\r
- if (abortgame)\r
- abortgame = false;\r
-}\r
-\r
-//--------------------------------------------------------------------------\r
-// IntSqrt() - by Master Programmer, George Leritte!\r
-//--------------------------------------------------------------------------\r
-int IntSqrt(long va)\r
-{\r
-asm mov AX, word ptr va\r
-asm mov DX, word ptr va+2\r
-asm mov bx,dx // {bx = integer square root of dx:ax}\r
-asm or bx,ax // {if dx:ax=0 then return}\r
-asm jz isq01\r
-asm mov bx,dx\r
-asm shl bx,1\r
-asm or bl,ah\r
-asm or bl,al\r
-asm dec bx\r
-asm add bx,dx // { initial guess}\r
-asm jg isq10\r
-asm inc bx // { don't return zero}\r
-asm jg isq10\r
-asm mov bx,7fffh\r
-isq01:;\r
- goto exitrout;\r
-\r
-isq10:;\r
-asm push ax\r
-asm push dx\r
-asm div bx\r
-asm sub ax,bx\r
-asm cmp ax,1\r
-asm jbe isq90\r
-asm cmp ax,-1\r
-asm jae isq90\r
-asm sar ax,1\r
-asm add bx,ax\r
-asm pop dx\r
-asm pop ax\r
-asm jmp isq10\r
-isq90:;\r
-asm pop dx\r
-asm pop ax\r
-exitrout:;\r
-asm mov ax,bx\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// InitBgChange()\r
-//-------------------------------------------------------------------------\r
-void InitBgChange(short stimer, unsigned *scolors, short gtimer, unsigned *gcolors, byte flag)\r
-{\r
- skytimer_reset = skytimer = stimer;\r
- if (scolors)\r
- skycolor = scolors;\r
-\r
- groundtimer_reset = groundtimer = gtimer;\r
- if (gcolors)\r
- groundcolor = gcolors;\r
-\r
- bgflag = flag;\r
-}\r
-\r
-////////////////////////////////////////////////////////\r
-//\r
-// DisplayStatus\r
-//\r
-// Stat_Flag - contains the type of status displayed\r
-// -- also uses status_delay (global variable) will not\r
-// change display until this variable is zero.\r
-// -- heirarchy is determined by the series of if statements,\r
-// to change it, rearrange th if statements.\r
-//\r
-////////////////////////////////////////////////////////\r
-\r
-#define MESSAGEDELAY 25\r
-void DisplayStatus (status_flags *stat_flag)\r
-{\r
- status_flags temp_status;\r
-\r
-\r
- if (*stat_flag == S_TIMESTOP)\r
- return;\r
-\r
- if (status_delay > 0)\r
- {\r
- status_delay -= realtics;\r
- return;\r
- }\r
- else\r
- status_delay = 0;\r
-\r
- // check for a change in status from previous call\r
-\r
- temp_status = S_VIEWING; //precaution\r
-\r
- if (Keyboard[sc_Control] || control.button0)\r
- temp_status = S_MISSLE;\r
-\r
- if (Keyboard[sc_Z] && !Keyboard[sc_F10])\r
- temp_status = S_ZAPPER;\r
-\r
- if ((Keyboard[sc_X] && !Keyboard[sc_F10]) || Keyboard[sc_Enter])\r
- temp_status = S_XTER;\r
-\r
- if (control.x)\r
- temp_status = S_TURN;\r
-\r
- if ((Keyboard[sc_V] || Keyboard[sc_Tab]) && control.x)\r
- temp_status = S_QTURN;\r
-\r
- if (Keyboard[sc_Alt] && control.x)\r
- temp_status = S_SIDESTEP;\r
-\r
- if (control.y < 0)\r
- temp_status = S_ADVANCE;\r
-\r
- if (control.y > 0)\r
- temp_status = S_RETREAT;\r
-\r
- if (Keyboard[sc_F5])\r
- temp_status = S_JOYSTICK;\r
-\r
- if (Keyboard[sc_F4])\r
- temp_status = S_RESTORING;\r
-\r
- if (Keyboard[sc_F3])\r
- temp_status = S_SAVING;\r
-\r
- if (Keyboard[sc_F2])\r
- temp_status = S_SND;\r
-\r
- if (Keyboard[sc_F1])\r
- temp_status = S_HELP;\r
-\r
- if (temp_status != *stat_flag)\r
- {\r
- *stat_flag = temp_status;\r
-\r
-\r
- switch (*stat_flag)\r
- {\r
- case S_MISSLE:\r
- DisplaySMsg("Magick Missile", NULL);\r
- status_delay = MESSAGEDELAY;\r
- break;\r
-\r
- case S_ZAPPER:\r
- if (gamestate.bolts)\r
- {\r
- DisplaySMsg("Zapper", NULL);\r
- status_delay = MESSAGEDELAY+10;\r
- }\r
- break;\r
-\r
- case S_XTER:\r
- if (gamestate.nukes)\r
- {\r
- DisplaySMsg("Xterminator", NULL);\r
- status_delay = MESSAGEDELAY+5;\r
- }\r
- break;\r
-\r
- case S_TURN:\r
- DisplaySMsg("Turning", NULL);\r
- status_delay = MESSAGEDELAY;\r
- break;\r
-\r
- case S_QTURN:\r
- DisplaySMsg("Quick Turning", NULL);\r
- status_delay = MESSAGEDELAY;\r
- break;\r
-\r
- case S_SIDESTEP:\r
- DisplaySMsg("Sidestepping", NULL);\r
- status_delay = MESSAGEDELAY;\r
- break;\r
-\r
- case S_ADVANCE:\r
- DisplaySMsg("Advancing", NULL);\r
- status_delay = MESSAGEDELAY;\r
- break;\r
-\r
- case S_RETREAT:\r
- DisplaySMsg("Retreating", NULL);\r
- status_delay = MESSAGEDELAY;\r
- break;\r
-\r
- case S_JOYSTICK:\r
- DisplaySMsg("Adjusting Joystick", NULL);\r
- break;\r
-\r
- case S_RESTORING:\r
- DisplaySMsg("Restoring", NULL);\r
- break;\r
-\r
- case S_SAVING:\r
- DisplaySMsg("Saving", NULL);\r
- break;\r
-\r
- case S_SND:\r
- DisplaySMsg("Select Sound", NULL);\r
- break;\r
-\r
- case S_HELP:\r
- DisplaySMsg("Getting Help", NULL);\r
- break;\r
-\r
- case S_VIEWING:\r
- DisplaySMsg("Viewing", NULL);\r
- break;\r
- }\r
- bufferofs = displayofs = screenloc[screenpage];\r
-\r
- }\r
-}\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// C3_SCALE.C\r
-\r
-#include "DEF.H"\r
-#pragma hdrstop\r
-\r
-//const unsigned viewheight = 144;\r
-const unsigned screenbwide = 40;\r
-const byte BACKGROUNDPIX = 5;\r
-\r
-unsigned shapesize[NUMSCALEPICS];\r
-t_compscale _seg *scaledirectory[NUMSCALEPICS];\r
-t_compshape _seg *shapedirectory[NUMSCALEPICS];\r
-memptr walldirectory[NUMSCALEWALLS];\r
-\r
-/*\r
-===========================\r
-=\r
-= DeplanePic\r
-=\r
-= Takes a raw bit map of width bytes by height and creates a scaleable shape\r
-=\r
-= Returns the length of the shape in bytes\r
-=\r
-= Fills in spotvis (a convenient 64*64 array) with the color values\r
-=\r
-===========================\r
-*/\r
-\r
-void DeplanePic (int picnum)\r
-{\r
- byte far *plane0,far *plane1,far *plane2,far *plane3;\r
- byte by0,by1,by2,by3;\r
- unsigned x,y,b,color,shift,width,height;\r
- byte *dest;\r
-\r
-//\r
-// convert ega pixels to byte color values in a temp buffer\r
-//\r
- width = pictable[picnum-STARTPICS].width;\r
- height = pictable[picnum-STARTPICS].height;\r
-\r
- if (width>8 || height!=64)\r
- Quit ("DePlanePic: Bad size shape");\r
-\r
- memset (spotvis,BACKGROUNDPIX,sizeof(spotvis));\r
-\r
- plane0 = (byte _seg *)grsegs[picnum];\r
- plane1 = plane0 + width*height;\r
- plane2 = plane1 + width*height;\r
- plane3 = plane2 + width*height;\r
-\r
- for (y=0;y<height;y++)\r
- {\r
- dest = &spotvis[y][0];\r
- for (x=0;x<width;x++)\r
- {\r
- by0 = *plane0++;\r
- by1 = *plane1++;\r
- by2 = *plane2++;\r
- by3 = *plane3++;\r
-\r
- for (b=0;b<8;b++)\r
- {\r
- shift=8-b;\r
-\r
- color = 0;\r
- asm mov cl,[BYTE PTR shift]\r
- asm mov al,[BYTE PTR by3]\r
- asm rcr al,cl;\r
- asm rcl [BYTE PTR color],1;\r
-\r
- asm mov cl,[BYTE PTR shift]\r
- asm mov al,[BYTE PTR by2]\r
- asm rcr al,cl;\r
- asm rcl [BYTE PTR color],1;\r
-\r
- asm mov cl,[BYTE PTR shift]\r
- asm mov al,[BYTE PTR by1]\r
- asm rcr al,cl;\r
- asm rcl [BYTE PTR color],1;\r
-\r
- asm mov cl,[BYTE PTR shift]\r
- asm mov al,[BYTE PTR by0]\r
- asm rcr al,cl;\r
- asm rcl [BYTE PTR color],1;\r
-\r
- *dest++ = color;\r
- } // B\r
- } // X\r
- } // Y\r
-}\r
-\r
-\r
-\r
-\r
-/*\r
-========================\r
-=\r
-= BuildCompScale\r
-=\r
-= Builds a compiled scaler object that will scale a 64 tall object to\r
-= the given height (centered vertically on the screen)\r
-=\r
-= height should be even\r
-=\r
-= Call with\r
-= ---------\r
-= DS:SI Source for scale\r
-= ES:DI Dest for scale\r
-=\r
-= Calling the compiled scaler only destroys AL\r
-=\r
-========================\r
-*/\r
-\r
-unsigned BuildCompScale (int height, memptr *finalspot)\r
-{\r
- t_compscale _seg *work;\r
- byte far *code;\r
-\r
- int i;\r
- long fix,step;\r
- unsigned src,totalscaled,totalsize;\r
- int startpix,endpix,toppix;\r
-\r
-\r
- MM_GetPtr (&(memptr)work,20000);\r
-\r
- step = ((long)height<<16) / 64;\r
- code = &work->code[0];\r
- toppix = (viewheight-height)/2;\r
- fix = 0;\r
-\r
- for (src=0;src<=64;src++)\r
- {\r
- startpix = fix>>16;\r
- fix += step;\r
- endpix = fix>>16;\r
-\r
- work->start[src] = startpix;\r
- if (endpix>startpix)\r
- work->width[src] = endpix-startpix;\r
- else\r
- work->width[src] = 0;\r
-\r
-//\r
-// mark the start of the code\r
-//\r
- work->codeofs[src] = FP_OFF(code);\r
-\r
-//\r
-// compile some code if the source pixel generates any screen pixels\r
-//\r
- startpix+=toppix;\r
- endpix+=toppix;\r
-\r
- if (startpix == endpix || endpix < 0 || startpix >= VIEWHEIGHT || src == 64)\r
- continue;\r
-\r
- //\r
- // mov al,[si+src]\r
- //\r
- *code++ = 0x8a;\r
- *code++ = 0x44;\r
- *code++ = src;\r
-\r
- for (;startpix<endpix;startpix++)\r
- {\r
- if (startpix >= VIEWHEIGHT)\r
- break; // off the bottom of the view area\r
- if (startpix < 0)\r
- continue; // not into the view area\r
-\r
- //\r
- // and [es:di+heightofs],al\r
- //\r
- *code++ = 0x26;\r
- *code++ = 0x20;\r
- *code++ = 0x85;\r
- *((unsigned far *)code)++ = startpix*screenbwide;\r
- }\r
-\r
- }\r
-\r
-//\r
-// retf\r
-//\r
- *code++ = 0xcb;\r
-\r
- totalsize = FP_OFF(code);\r
- MM_GetPtr (finalspot,totalsize);\r
- _fmemcpy ((byte _seg *)(*finalspot),(byte _seg *)work,totalsize);\r
- MM_FreePtr (&(memptr)work);\r
-\r
- return totalsize;\r
-}\r
-\r
-\r
-\r
-\r
-/*\r
-========================\r
-=\r
-= BuildCompShape\r
-=\r
-= typedef struct\r
-= {\r
-= unsigned width;\r
-= unsigned codeofs[64];\r
-= } t_compshape;\r
-=\r
-= Width is the number of compiled line draws in the shape. The shape\r
-= drawing code will assume that the midpoint of the shape is in the\r
-= middle of the width.\r
-=\r
-= The non background pixel data will start at codeofs[width], so codeofs\r
-= greater than width will be invalid.\r
-=\r
-= Each code offset will draw one vertical line of the shape, consisting\r
-= of 0 or more segments of scaled pixels.\r
-=\r
-= The scaled shapes use ss:0-4 as a scratch variable for the far call to\r
-= the compiled scaler, so zero it back out after the shape is scaled, or\r
-= a "null pointer assignment" will result upon termination.\r
-=\r
-= Setup for a call to a compiled shape\r
-= -----------------------------------\r
-= ax toast\r
-= bx toast\r
-= cx toast\r
-= dx segment of compiled shape\r
-= si toast\r
-= di byte at top of view area to draw the line in\r
-= bp 0\r
-= ss:2 and ds the segment of the compiled scaler to use\r
-= es screenseg\r
-=\r
-= Upon return, ds IS NOT SET to the data segment. Do:\r
-= mov ax,ss\r
-= mov ds,ax\r
-=\r
-=\r
-= GC_BITMASK set to the pixels to be drawn in the row of bytes under DI\r
-= GC_MODE read mode 1, write mode 2\r
-= GC_COLORDONTCARE set to 0, so all reads from video memory return 0xff\r
-=\r
-=\r
-= Code generated for each segment\r
-= -------------------------------\r
-= mov bx,[(segend+1)*2]\r
-= mov cx,[bx]\r
-= mov [BYTE PTR bx],0xc8 // far return\r
-= mov ax,[segstart*2]\r
-= mov [ss:0],ax // entry point into the compiled scaler\r
-= mov ds,dx // (mov ds,cs) the data is after the compiled code\r
-= mov si,ofs data\r
-= call [bp] // scale some pixels\r
-= mov ds,[bp+2]\r
-= mov [bx],cx // un patch return\r
-=\r
-= Code generated after all segments on a line\r
-= -------------------------------------------\r
-= retf\r
-=\r
-========================\r
-*/\r
-\r
-unsigned BuildCompShape (t_compshape _seg **finalspot)\r
-{\r
- t_compshape _seg *work;\r
- byte far *code;\r
- int firstline,lastline,x,y;\r
- unsigned firstpix,lastpix,width;\r
- unsigned totalsize,pixelofs;\r
- unsigned buff;\r
-\r
-\r
-// MM_GetPtr (&(memptr)work,20000);\r
- EGAWRITEMODE(0);\r
- EGAREADMAP(0); // use ega screen memory for temp buffer\r
- EGAMAPMASK(1);\r
- buff = screenloc[1];\r
- work = (t_compshape _seg *)(0xa000+(buff+15)/16);\r
-\r
-//\r
-// find the width of the shape\r
-//\r
- firstline = -1;\r
- x=0;\r
- do\r
- {\r
- for (y=0;y<64;y++)\r
- if (spotvis[y][x] != BACKGROUNDPIX)\r
- {\r
- firstline = x;\r
- break;\r
- }\r
- if (++x == 64)\r
- Quit ("BuildCompShape: No shape data!");\r
- } while (firstline == -1);\r
-\r
- lastline = -1;\r
- x=63;\r
- do\r
- {\r
- for (y=0;y<64;y++)\r
- if (spotvis[y][x] != BACKGROUNDPIX)\r
- {\r
- lastline = x;\r
- break;\r
- }\r
- x--;\r
- } while (lastline == -1);\r
-\r
- width = lastline-firstline+1;\r
-\r
- work->width = width;\r
- code = (byte far *)&work->codeofs[width];\r
-\r
-//\r
-// copy all non background pixels to the work space\r
-//\r
- pixelofs = FP_OFF(code);\r
-\r
- for (x=firstline;x<=lastline;x++)\r
- for (y=0;y<64;y++)\r
- if (spotvis[y][x] != BACKGROUNDPIX)\r
- *code++ = spotvis[y][x];\r
-\r
-//\r
-// start compiling the vertical lines\r
-//\r
- for (x=firstline;x<=lastline;x++)\r
- {\r
- work->codeofs[x-firstline] = FP_OFF(code);\r
-\r
- y=0;\r
- do\r
- {\r
- //\r
- // scan past black background pixels\r
- //\r
- while (spotvis[y][x] == BACKGROUNDPIX && y<64)\r
- y++;\r
-\r
- if (y>63) // no more segments\r
- break;\r
-\r
- firstpix = y+1; // +1 because width is before codeofs\r
-\r
- //\r
- // scan past scalable pixels\r
- //\r
- while (spotvis[y][x] != BACKGROUNDPIX && y<64)\r
- y++;\r
-\r
- if (y>63)\r
- lastpix = 65;\r
- else\r
- lastpix = y+1; // actually one pixel past the last displayed\r
-\r
- //\r
- // compile the scale call\r
- //\r
- *code++ = 0x8b; // mov bx,[lastpix*2]\r
- *code++ = 0x1e;\r
- *((unsigned far *)code)++ = lastpix*2;\r
-\r
- *code++ = 0x8b; // mov cx,[bx]\r
- *code++ = 0x0f;\r
-\r
- *code++ = 0xc6; // move [BYTE bx],0xcb\r
- *code++ = 0x07;\r
- *code++ = 0xcb;\r
-\r
- *code++ = 0xa1; // mov ax,[firstpix*2] /*************\r
- *((unsigned far *)code)++ = firstpix*2;\r
-\r
- *code++ = 0x36; // mov [ss:0],ax\r
- *code++ = 0xa3;\r
- *code++ = 0x00;\r
- *code++ = 0x00;\r
-\r
- *code++ = 0x8e; // mov ds,dx (mov ds,cs)\r
- *code++ = 0xda;\r
-\r
- *code++ = 0xbe; // mov si,OFFSET pixelofs-firstpixel\r
- *((unsigned far *)code)++ = pixelofs-firstpix;\r
-\r
- *code++ = 0xff; // call [DWORD bp]\r
- *code++ = 0x5e;\r
- *code++ = 0x00;\r
-\r
- *code++ = 0x8e; // mov ds,[bp+2]\r
- *code++ = 0x5e;\r
- *code++ = 0x02;\r
-\r
- *code++ = 0x89; // mov [bx],cx\r
- *code++ = 0x0f;\r
-\r
- pixelofs += (lastpix-firstpix);\r
- } while (y<63);\r
-\r
- //\r
- // retf\r
- //\r
- *code++ = 0xcb;\r
- }\r
-\r
-\r
-//\r
-// copy the final shape to a properly sized buffer\r
-//\r
- totalsize = FP_OFF(code);\r
-\r
- if (totalsize >= (PAGELEN*2))\r
- Quit("BuildCompShape(): Shape is too complex!");\r
-\r
- MM_GetPtr ((memptr *)finalspot,totalsize);\r
- _fmemcpy ((byte _seg *)(*finalspot),(byte _seg *)work,totalsize);\r
-// MM_FreePtr (&(memptr)work);\r
-\r
- return totalsize;\r
-}\r
-\r
-\r
-\r
-/*\r
-=======================\r
-=\r
-= ScaleShape\r
-=\r
-= Draws a compiled shape at [scale] pixels high\r
-=\r
-= Setup for call\r
-= --------------\r
-= GC_MODE read mode 1, write mode 2\r
-= GC_COLORDONTCARE set to 0, so all reads from video memory return 0xff\r
-= GC_INDEX pointing at GC_BITMASK\r
-=\r
-=======================\r
-*/\r
-\r
-static long longtemp;\r
-\r
-void ScaleShape (int xcenter, t_compshape _seg *compshape, unsigned scale)\r
-{\r
- #define MAX_OBJ_SCALE (MAXSCALE)\r
-\r
-\r
- t_compscale _seg *comptable;\r
- unsigned width,scalewidth;\r
- int x,pixel,lastpixel,pixwidth,min;\r
- unsigned far *codehandle, far *widthptr;\r
- unsigned badcodeptr;\r
- int rightclip;\r
-\r
- if (!compshape)\r
- Quit ("ScaleShape: NULL compshape ptr!");\r
-\r
- scale = (scale+1)/2;\r
- if (!scale)\r
- return; // too far away\r
- if (scale>MAX_OBJ_SCALE)\r
- scale = MAX_OBJ_SCALE;\r
- comptable = scaledirectory[scale];\r
-\r
- width = compshape->width;\r
- scalewidth = comptable->start[width];\r
-\r
- pixel = xcenter - scalewidth/2;\r
- lastpixel = pixel+scalewidth-1;\r
- if (pixel >= VIEWWIDTH || lastpixel < 0)\r
- return; // totally off screen\r
-\r
-//\r
-// scan backwards from the right edge until pixels are visable\r
-// rightclip is the first NON VISABLE pixel\r
-//\r
- if (lastpixel>=VIEWWIDTH-1)\r
- rightclip = VIEWWIDTH-1;\r
- else\r
- rightclip = lastpixel;\r
-\r
- if (zbuffer[rightclip]>scale)\r
- {\r
- if (pixel>0)\r
- min = pixel;\r
- else\r
- min = 0;\r
- do\r
- {\r
- if (--rightclip < min)\r
- return; // totally covered or before 0\r
- if (zbuffer[rightclip]<=scale)\r
- break;\r
- } while (1);\r
- }\r
- rightclip++;\r
-\r
-//\r
-// scan from the left until it is on screen, leaving\r
-// [pixel],[pixwidth],[codehandle],and [widthptr] set correctly\r
-//\r
- *(((unsigned *)&longtemp)+1) = (unsigned)compshape; // seg of shape\r
- codehandle = &compshape->codeofs[0];\r
- badcodeptr = compshape->codeofs[width];\r
- widthptr = &comptable->width[0];\r
- asm mov ax,[comptable]\r
- asm mov WORD PTR [2],ax // ds:0-4 is used as a far call pointer\r
- // by the compiled shapes\r
- pixwidth = *widthptr; // scaled width of this pixel\r
- while (!pixwidth)\r
- {\r
- pixwidth = *++widthptr; // find the first visable pixel\r
- codehandle++;\r
- }\r
-\r
- if (pixel<0)\r
- {\r
- do\r
- {\r
- if (pixel+pixwidth>0)\r
- {\r
- pixwidth += pixel;\r
- pixel = 0;\r
- break;\r
- }\r
- do\r
- {\r
- pixwidth = *++widthptr;\r
- codehandle++;\r
- } while (!pixwidth);\r
- pixel+=pixwidth;\r
- } while (1);\r
- }\r
-\r
-//\r
-// scan until it is visable, leaving\r
-// [pixel],[pixwidth],[codehandle],and [widthptr] set correctly\r
-//\r
- do\r
- {\r
- if (zbuffer[pixel] <= scale)\r
- break; // start drawing here\r
- pixel++;\r
- if (!--pixwidth)\r
- {\r
- do\r
- {\r
- pixwidth = *++widthptr;\r
- codehandle++;\r
- } while (!pixwidth);\r
- }\r
- } while (1);\r
-\r
- if (pixel+pixwidth>rightclip)\r
- pixwidth = rightclip-pixel;\r
-//\r
-// draw lines\r
-//\r
- do // while (1)\r
- {\r
- //\r
- // scale a vertical segment [pixwidth] pixels wide at [pixel]\r
- //\r
- (unsigned)longtemp = *codehandle; // offset of compiled code\r
- if ((unsigned)longtemp == badcodeptr)\r
- Quit ("ScaleShape: codehandle past end!");\r
-\r
- asm mov bx,[pixel]\r
- asm mov di,bx\r
- asm shr di,1\r
- asm shr di,1\r
- asm shr di,1 // X in bytes\r
- asm add di,[bufferofs]\r
- asm and bx,7\r
- asm shl bx,1\r
- asm shl bx,1\r
- asm shl bx,1\r
- asm add bx,[pixwidth] // bx = pixel*8+pixwidth-1\r
- asm dec bx\r
- asm push bx\r
- asm mov al,BYTE PTR [bitmasks1+bx]\r
- asm mov dx,GC_INDEX+1\r
- asm out dx,al // set bit mask register\r
-\r
- asm mov es,[screenseg]\r
- asm push si\r
- asm push di\r
- asm push bp\r
- asm xor bp,bp\r
- asm mov dx,[WORD PTR longtemp+2]\r
- asm mov ds,[2]\r
- asm call ss:[DWORD PTR longtemp] // scale the line of pixels\r
- asm mov ax,ss\r
- asm mov ds,ax\r
- asm pop bp\r
- asm pop di\r
- asm pop si\r
-\r
- asm pop bx\r
- asm mov al,BYTE PTR [bitmasks2+bx]\r
- asm or al,al\r
- asm jz nosecond\r
-\r
- //\r
- // draw a second byte for vertical strips that cross two bytes\r
- //\r
- asm inc di\r
- asm mov dx,GC_INDEX+1\r
- asm out dx,al // set bit mask register\r
- asm push si\r
- asm push di\r
- asm push bp\r
- asm xor bp,bp\r
- asm mov dx,[WORD PTR longtemp+2]\r
- asm mov ds,[2]\r
- asm call ss:[DWORD PTR longtemp] // scale the line of pixels\r
- asm mov ax,ss\r
- asm mov ds,ax\r
- asm pop bp\r
- asm pop di\r
- asm pop si\r
-\r
-\r
- //\r
- // advance to the next drawn line\r
- //\r
-nosecond:;\r
- if ( (pixel+=pixwidth) == rightclip )\r
- {\r
- asm mov WORD PTR [0],0\r
- asm mov WORD PTR [2],0\r
- return; // all done!\r
- }\r
-\r
- do\r
- {\r
- pixwidth = *++widthptr;\r
- codehandle++;\r
- } while (!pixwidth);\r
-\r
- if (pixel+pixwidth > rightclip)\r
- pixwidth = rightclip-pixel;\r
-\r
- } while (1);\r
-\r
-}\r
-\r
-//\r
-// bit mask tables for drawing scaled strips up to eight pixels wide\r
-//\r
-\r
-byte bitmasks1[8][8] = {\r
-{0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff},\r
-{0x40,0x60,0x70,0x78,0x7c,0x7e,0x7f,0x7f},\r
-{0x20,0x30,0x38,0x3c,0x3e,0x3f,0x3f,0x3f},\r
-{0x10,0x18,0x1c,0x1e,0x1f,0x1f,0x1f,0x1f},\r
-{0x8,0xc,0xe,0xf,0xf,0xf,0xf,0xf},\r
-{0x4,0x6,0x7,0x7,0x7,0x7,0x7,0x7},\r
-{0x2,0x3,0x3,0x3,0x3,0x3,0x3,0x3},\r
-{0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1} };\r
-\r
-byte bitmasks2[8][8] = {\r
-{0,0,0,0,0,0,0,0},\r
-{0,0,0,0,0,0,0,0x80},\r
-{0,0,0,0,0,0,0x80,0xc0},\r
-{0,0,0,0,0,0x80,0xc0,0xe0},\r
-{0,0,0,0,0x80,0xc0,0xe0,0xf0},\r
-{0,0,0,0x80,0xc0,0xe0,0xf0,0xf8},\r
-{0,0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc},\r
-{0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe} };\r
-\r
-\r
-\r
-\r
-\r
-\r
+++ /dev/null
-; Catacomb Armageddon Source Code\r
-; Copyright (C) 1993-2014 Flat Rock Software\r
-;\r
-; This program is free software; you can redistribute it and/or modify\r
-; it under the terms of the GNU General Public License as published by\r
-; the Free Software Foundation; either version 2 of the License, or\r
-; (at your option) any later version.\r
-;\r
-; This program is distributed in the hope that it will be useful,\r
-; but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-; GNU General Public License for more details.\r
-;\r
-; You should have received a copy of the GNU General Public License along\r
-; with this program; if not, write to the Free Software Foundation, Inc.,\r
-; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-\r
-IDEAL\r
-MODEL MEDIUM,C\r
-\r
-include "ID_ASM.EQU"\r
-\r
-;===========================================================================\r
-;\r
-; SCALING GRAPHICS\r
-;\r
-;===========================================================================\r
-\r
-\r
-\r
-MACRO MAKELAB NUM\r
-\r
-lab&NUM:\r
-\r
-ENDM\r
-\r
-MACRO MAKEREF NUM\r
-\r
-dw OFFSET lab&NUM\r
-\r
-ENDM\r
-\r
-\r
-;=========================================================================\r
-\r
-MAXSCALES equ 256\r
-\r
- DATASEG\r
-\r
-EXTRN screenseg:WORD\r
-EXTRN linewidth:WORD\r
-\r
-LABEL endtable WORD\r
-labcount = 0\r
-REPT MAXSCALES\r
-MAKEREF %labcount\r
-labcount = labcount + 1\r
-ENDM\r
-\r
-\r
- CODESEG\r
-\r
-;==================================================\r
-;\r
-; void scaleline (int scale, unsigned picseg, unsigned maskseg,\r
-; unsigned screen, unsigned width)\r
-;\r
-;==================================================\r
-\r
-PROC ScaleLine pixels:word, scaleptr:dword, picptr:dword, screen:word\r
-USES si,di\r
-PUBLIC ScaleLine\r
-\r
-;\r
-; modify doline procedure for proper width\r
-;\r
- mov bx,[pixels]\r
- cmp bx,MAXSCALES\r
- jbe @@scaleok\r
- mov bx,MAXSCALES\r
-@@scaleok:\r
- shl bx,1\r
- mov bx,[endtable+bx]\r
- push [cs:bx] ;save the code that will be modified over\r
- mov [WORD cs:bx],0d18eh ;mov ss,cx\r
- push [cs:bx+2] ;save the code that will be modified over\r
- mov [WORD cs:bx+2],90c3h ;ret / nop\r
- push bx\r
-\r
- mov dx,[linewidth]\r
-\r
- mov di,[WORD screen]\r
- mov es,[screenseg]\r
-\r
- mov si,[WORD scaleptr]\r
- mov ds,[WORD scaleptr+2]\r
-\r
- mov bx,[WORD picptr]\r
- mov ax,[WORD picptr+2] ;will be moved into ss after call\r
-\r
- mov bp,bx\r
-\r
- cli\r
- call doline\r
- sti\r
-;\r
-; restore doline to regular state\r
-;\r
- pop bx ;address of modified code\r
- pop [cs:bx+2]\r
- pop [cs:bx]\r
-\r
- mov ax,ss\r
- mov ds,ax\r
- ret\r
-\r
-;================\r
-;\r
-; doline\r
-;\r
-; Big unwound scaling routine\r
-;\r
-; ds:si = scale table\r
-; ss:bx = pic data\r
-; es:di = screen location\r
-;\r
-;================\r
-\r
-doline:\r
-\r
- mov cx,ss\r
- mov ss,ax ;can't call a routine with ss used...\r
-\r
-labcount = 0\r
-\r
-REPT MAXSCALES\r
-\r
-MAKELAB %labcount\r
-labcount = labcount + 1\r
-\r
- lodsb ; get scaled pixel number\r
- xlat [ss:bx] ; look it up in the picture\r
- xchg [es:di],al ; load latches and write pixel to screen\r
- add di,dx ; down to next line\r
-\r
-ENDM\r
-\r
- mov ss,cx\r
- ret\r
-\r
-ENDP\r
-\r
-END
\ No newline at end of file
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// C3_STATE.C\r
-\r
-#include "DEF.H"\r
-#pragma hdrstop\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-dirtype opposite[9] =\r
- {south,west,north,east,southwest,northwest,northeast,southeast,nodir};\r
-\r
-\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= Internal_SpawnNewObj\r
-=\r
-===================\r
-*/\r
-void Internal_SpawnNewObj (unsigned x, unsigned y, statetype *state, unsigned size, boolean UseDummy, boolean PutInActorat)\r
-{\r
- extern objtype dummyobj;\r
-\r
- GetNewObj(UseDummy);\r
- new->size = size;\r
- new->state = state;\r
- new->ticcount = random (state->tictime)+1;\r
-\r
- new->tilex = x;\r
- new->tiley = y;\r
- new->x = ((long)x<<TILESHIFT)+TILEGLOBAL/2;\r
- new->y = ((long)y<<TILESHIFT)+TILEGLOBAL/2;\r
- CalcBounds(new);\r
- new->dir = nodir;\r
- new->active = noalways;\r
-\r
- if (new != &dummyobj && PutInActorat)\r
- actorat[new->tilex][new->tiley] = new;\r
-}\r
-\r
-void Internal_SpawnNewObjFrac (long x, long y, statetype *state, unsigned size,boolean UseDummy)\r
-{\r
- GetNewObj(UseDummy);\r
- new->size = size;\r
- new->state = state;\r
- new->ticcount = random (state->tictime)+1;\r
- new->active = noalways;\r
-\r
- new->x = x;\r
- new->y = y;\r
- new->tilex = x>>TILESHIFT;\r
- new->tiley = y>>TILESHIFT;\r
- CalcBounds(new);\r
- new->distance = 100;\r
- new->dir = nodir;\r
-}\r
-\r
-\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= CheckHandAttack\r
-=\r
-= If the object can move next to the player, it will return true\r
-=\r
-===================\r
-*/\r
-\r
-boolean CheckHandAttack (objtype *ob)\r
-{\r
- long deltax,deltay,size;\r
-\r
- size = (long)ob->size + player->size + ob->speed*tics + SIZE_TEST;\r
- deltax = ob->x - player->x;\r
- deltay = ob->y - player->y;\r
-\r
- if (deltax > size || deltax < -size || deltay > size || deltay < -size)\r
- return false;\r
-\r
- return true;\r
-}\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= T_DoDamage\r
-=\r
-= Attacks the player if still nearby, then immediately changes to next state\r
-=\r
-===================\r
-*/\r
-\r
-void T_DoDamage (objtype *ob)\r
-{\r
- int points;\r
-\r
-\r
- if (CheckHandAttack(ob) && (!(ob->flags & of_damagedone)))\r
- {\r
- points = 0;\r
-\r
- switch (ob->obclass)\r
- {\r
- case zombieobj:\r
- case fatdemonobj:\r
- points = 8;\r
- break;\r
- case reddemonobj:\r
- case godessobj:\r
- points = 15;\r
- break;\r
- case antobj:\r
- points = 2;\r
- break;\r
- case skeletonobj:\r
- points = 6;\r
- break;\r
-\r
- case wetobj:\r
- points = 7;\r
- break;\r
- case treeobj:\r
- points = 7;\r
- break;\r
- case bunnyobj:\r
- points = 4;\r
- break;\r
- }\r
- TakeDamage (points);\r
- ob->flags |= of_damagedone;\r
- }\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-==================================\r
-=\r
-= Walk\r
-=\r
-==================================\r
-*/\r
-\r
-boolean Walk (objtype *ob)\r
-{\r
- switch (ob->dir)\r
- {\r
- case north:\r
- if (actorat[ob->tilex][ob->tiley-1])\r
- return false;\r
- ob->tiley--;\r
- ob->distance = TILEGLOBAL;\r
- return true;\r
-\r
- case northeast:\r
- if (actorat[ob->tilex+1][ob->tiley-1])\r
- return false;\r
- ob->tilex++;\r
- ob->tiley--;\r
- ob->distance = TILEGLOBAL;\r
- return true;\r
-\r
- case east:\r
- if (actorat[ob->tilex+1][ob->tiley])\r
- return false;\r
- ob->tilex++;\r
- ob->distance = TILEGLOBAL;\r
- return true;\r
-\r
- case southeast:\r
- if (actorat[ob->tilex+1][ob->tiley+1])\r
- return false;\r
- ob->tilex++;\r
- ob->tiley++;\r
- ob->distance = TILEGLOBAL;\r
- return true;\r
-\r
- case south:\r
- if (actorat[ob->tilex][ob->tiley+1])\r
- return false;\r
- ob->tiley++;\r
- ob->distance = TILEGLOBAL;\r
- return true;\r
-\r
- case southwest:\r
- if (actorat[ob->tilex-1][ob->tiley+1])\r
- return false;\r
- ob->tilex--;\r
- ob->tiley++;\r
- ob->distance = TILEGLOBAL;\r
- return true;\r
-\r
- case west:\r
- if (actorat[ob->tilex-1][ob->tiley])\r
- return false;\r
- ob->tilex--;\r
- ob->distance = TILEGLOBAL;\r
- return true;\r
-\r
- case northwest:\r
- if (actorat[ob->tilex-1][ob->tiley-1])\r
- return false;\r
- ob->tilex--;\r
- ob->tiley--;\r
- ob->distance = TILEGLOBAL;\r
- return true;\r
-\r
- case nodir:\r
- return false;\r
- }\r
-\r
- Quit ("Walk: Bad dir");\r
- return false;\r
-}\r
-\r
-\r
-\r
-/*\r
-==================================\r
-=\r
-= ChaseThink\r
-= have the current monster go after the player,\r
-= either diagonally or straight on\r
-=\r
-==================================\r
-*/\r
-\r
-void ChaseThink (objtype *obj, boolean diagonal)\r
-{\r
- int deltax,deltay,i;\r
- dirtype d[3];\r
- dirtype tdir, olddir, turnaround;\r
-\r
-\r
- olddir=obj->dir;\r
- turnaround=opposite[olddir];\r
-\r
- deltax=player->tilex - obj->tilex;\r
- deltay=player->tiley - obj->tiley;\r
-\r
- d[1]=nodir;\r
- d[2]=nodir;\r
-\r
- if (deltax>0)\r
- d[1]= east;\r
- if (deltax<0)\r
- d[1]= west;\r
- if (deltay>0)\r
- d[2]=south;\r
- if (deltay<0)\r
- d[2]=north;\r
-\r
- if (abs(deltay)>abs(deltax))\r
- {\r
- tdir=d[1];\r
- d[1]=d[2];\r
- d[2]=tdir;\r
- }\r
-\r
- if (d[1]==turnaround)\r
- d[1]=nodir;\r
- if (d[2]==turnaround)\r
- d[2]=nodir;\r
-\r
-\r
- if (diagonal)\r
- { /*ramdiagonals try the best dir first*/\r
- if (d[1]!=nodir)\r
- {\r
- obj->dir=d[1];\r
- if (Walk(obj))\r
- return; /*either moved forward or attacked*/\r
- }\r
-\r
- if (d[2]!=nodir)\r
- {\r
- obj->dir=d[2];\r
- if (Walk(obj))\r
- return;\r
- }\r
- }\r
- else\r
- { /*ramstraights try the second best dir first*/\r
-\r
- if (d[2]!=nodir)\r
- {\r
- obj->dir=d[2];\r
- if (Walk(obj))\r
- return;\r
- }\r
-\r
- if (d[1]!=nodir)\r
- {\r
- obj->dir=d[1];\r
- if (Walk(obj))\r
- return;\r
- }\r
- }\r
-\r
-/* there is no direct path to the player, so pick another direction */\r
-\r
- obj->dir=olddir;\r
- if (Walk(obj))\r
- return;\r
-\r
- if (US_RndT()>128) /*randomly determine direction of search*/\r
- {\r
- for (tdir=north;tdir<=west;tdir++)\r
- {\r
- if (tdir!=turnaround)\r
- {\r
- obj->dir=tdir;\r
- if (Walk(obj))\r
- return;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- for (tdir=west;tdir>=north;tdir--)\r
- {\r
- if (tdir!=turnaround)\r
- {\r
- obj->dir=tdir;\r
- if (Walk(obj))\r
- return;\r
- }\r
- }\r
- }\r
-\r
- obj->dir=turnaround;\r
- Walk(obj); /*last chance, don't worry about returned value*/\r
-}\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= MoveObj\r
-=\r
-=================\r
-*/\r
-\r
-void MoveObj (objtype *ob, long move)\r
-{\r
- ob->distance -=move;\r
-\r
- switch (ob->dir)\r
- {\r
- case north:\r
- ob->y -= move;\r
- return;\r
- case northeast:\r
- ob->x += move;\r
- ob->y -= move;\r
- return;\r
- case east:\r
- ob->x += move;\r
- return;\r
- case southeast:\r
- ob->x += move;\r
- ob->y += move;\r
- return;\r
- case south:\r
- ob->y += move;\r
- return;\r
- case southwest:\r
- ob->x -= move;\r
- ob->y += move;\r
- return;\r
- case west:\r
- ob->x -= move;\r
- return;\r
- case northwest:\r
- ob->x -= move;\r
- ob->y -= move;\r
- return;\r
-\r
- case nodir:\r
- return;\r
- }\r
-}\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= Chase\r
-=\r
-= returns true if hand attack range\r
-=\r
-=================\r
-*/\r
-\r
-boolean Chase (objtype *ob, boolean diagonal)\r
-{\r
- long move;\r
- long deltax,deltay,size;\r
-\r
- ob->flags &= ~of_damagedone;\r
-\r
- move = ob->speed*tics;\r
- size = (long)ob->size + player->size + move + SIZE_TEST;\r
-\r
- while (move)\r
- {\r
- deltax = ob->x - player->x;\r
- deltay = ob->y - player->y;\r
-\r
- if (deltax <= size && deltax >= -size\r
- && deltay <= size && deltay >= -size)\r
- {\r
- CalcBounds (ob);\r
- return true;\r
- }\r
-\r
- if (move < ob->distance)\r
- {\r
- MoveObj (ob,move);\r
- break;\r
- }\r
- actorat[ob->tilex][ob->tiley] = 0; // pick up marker from goal\r
- if (ob->dir == nodir)\r
- ob->dir = north;\r
-\r
- ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;\r
- ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;\r
- move -= ob->distance;\r
-\r
- ChaseThink (ob,diagonal);\r
- if (!ob->distance)\r
- break; // no possible move\r
- actorat[ob->tilex][ob->tiley] = ob; // set down a new goal marker\r
- }\r
- CalcBounds (ob);\r
- return false;\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= ShootActor\r
-=\r
-===================\r
-*/\r
-\r
-void ShootActor (objtype *ob, unsigned damage)\r
-{\r
- ob->hitpoints -= damage;\r
-\r
- if (ob->hitpoints<=0)\r
- {\r
- switch (ob->obclass)\r
- {\r
- case reddemonobj:\r
- ob->state = &s_red_demondie1;\r
- break;\r
- case succubusobj:\r
- ob->state = &s_succubus_death1;\r
- break;\r
- case fatdemonobj:\r
- ob->state = &s_fatdemon_blowup1;\r
- break;\r
- case godessobj:\r
- ob->state = &s_godessdie1;\r
- break;\r
- case mageobj:\r
- ob->state = &s_magedie1;\r
- break;\r
- case batobj:\r
- ob->state = &s_batdie1;\r
-#if USE_INERT_LIST\r
- ob->obclass = solidobj; // don't add this obj to inert list\r
-#endif\r
- break;\r
- case grelmobj:\r
- ob->state = &s_greldie1;\r
- break;\r
-\r
- case zombieobj:\r
- ob->state = &s_zombie_death1;\r
- break;\r
-\r
- case skeletonobj:\r
- ob->state = &s_skel_die1;\r
- break;\r
-\r
- case antobj:\r
- ob->state = &s_ant_die1;\r
- break;\r
-\r
- case wetobj:\r
- ob->state = &s_wet_die1;\r
-#if USE_INERT_LIST\r
- ob->obclass = solidobj; // don't add this obj to inert list\r
-#endif\r
- break;\r
-\r
- case eyeobj:\r
- ob->state = &s_eye_die1;\r
- break;\r
-\r
- case sshotobj:\r
- case eshotobj:\r
- case mshotobj:\r
- ob->state = &s_bonus_die;\r
-#if USE_INERT_LIST\r
- ob->obclass = solidobj; // don't add these objs to inert list\r
-#endif\r
- break;\r
-\r
- case treeobj:\r
- ob->state = &s_tree_death1;\r
- ob->obclass = solidobj;\r
- ob->temp1 = 3;\r
- ob->flags &= ~of_damagedone;\r
- CalcBounds(ob);\r
- break;\r
-\r
- case bunnyobj:\r
- ob->state = &s_bunny_death1;\r
- break;\r
-\r
- case bonusobj:\r
- case freezeobj:\r
- switch (ob->temp1)\r
- {\r
- case B_POTION:\r
- case B_CHEST:\r
- case B_NUKE:\r
- case B_BOLT:\r
- ob->state = &s_pshot_exp1;\r
- ob->obclass = expobj;\r
- ob->ticcount = ob->state->tictime;\r
- SpawnBigExplosion(ob->x,ob->y,12,(16l<<16L));\r
- bordertime = FLASHTICS<<2;\r
- bcolor = 14;\r
- VW_ColorBorder(14 | 56);\r
- DisplaySMsg("Item destroyed", NULL);\r
- status_flag = S_NONE;\r
- status_delay = 80;\r
- break;\r
- }\r
-#if USE_INERT_LIST\r
- ob->obclass = solidobj; // don't add this obj to inert list\r
-#endif\r
- break;\r
-\r
- }\r
-\r
- if (ob->obclass != solidobj && ob->obclass != realsolidobj)\r
- {\r
- ob->obclass = inertobj;\r
- ob->flags &= ~of_shootable;\r
- actorat[ob->tilex][ob->tiley] = NULL;\r
-#if USE_INERT_LIST\r
- MoveObjToInert(ob);\r
-#endif\r
- }\r
- else\r
- {\r
- if (ob->flags & of_forcefield)\r
- {\r
- ob->state = &s_force_field_die;\r
- ob->flags &= ~of_shootable;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- switch (ob->obclass)\r
- {\r
- case reddemonobj:\r
- if (!(random(8)))\r
- ob->state = &s_red_demonouch;\r
- else\r
- return;\r
- break;\r
- case succubusobj:\r
- ob->state = &s_succubus_ouch;\r
- break;\r
- case fatdemonobj:\r
- ob->state = &s_fatdemon_ouch;\r
- break;\r
- case godessobj:\r
- ob->state = &s_godessouch;\r
- break;\r
- case mageobj:\r
- ob->state = &s_mageouch;\r
- break;\r
-\r
- case grelmobj:\r
- ob->state = &s_grelouch;\r
- break;\r
-\r
- case zombieobj:\r
- ob->state = &s_zombie_ouch;\r
- break;\r
-\r
- case antobj:\r
- ob->state = &s_ant_ouch;\r
- break;\r
-\r
- case skeletonobj:\r
- ob->state = &s_skel_ouch;\r
- break;\r
-\r
- case wetobj:\r
- ob->state = &s_wet_ouch;\r
- break;\r
-\r
- case eyeobj:\r
- ob->state = &s_eye_ouch;\r
- break;\r
-\r
- case treeobj:\r
- ob->state = &s_tree_ouch;\r
- break;\r
-\r
- case bunnyobj:\r
- ob->state = &s_bunny_ouch;\r
- break;\r
- }\r
- }\r
- ob->ticcount = ob->state->tictime;\r
-}\r
-\r
-\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// C3_TRACE.C\r
-\r
-#include "DEF.H"\r
-#pragma hdrstop\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-//\r
-// TESTWALLVISABLE will set the global variable wallvisable to 1 or 0\r
-// depending on if tile.x,tile.y,wallon is visable from focal point\r
-//\r
-#define TESTWALLVISABLE { \\r
- if (tile.y<focal.y) \\r
- voffset = 0; \\r
- else if (tile.y==focal.y) \\r
- voffset = 3; \\r
- else \\r
- voffset = 6; \\r
- if (tile.x==focal.x) \\r
- voffset ++; \\r
- else if (tile.x>focal.x) \\r
- voffset += 2; \\r
- wallvisable = visable[voffset][wallon]; }\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-boolean aborttrace;\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-unsigned wallvisable,voffset;\r
-\r
-\r
-fixed edgex,edgey;\r
-\r
-int wallon;\r
-int basecolor;\r
-\r
-walltype *oldwall;\r
-\r
-//\r
-// offsets from upper left corner of a tile to the left and right edges of\r
-// a given wall (NORTH-WEST)\r
-//\r
-fixed point1x[4] = {GLOBAL1,GLOBAL1,0 ,0 };\r
-fixed point1y[4] = {0 ,GLOBAL1,GLOBAL1,0 };\r
-\r
-fixed point2x[4] = {0 ,GLOBAL1,GLOBAL1,0 };\r
-fixed point2y[4] = {0 ,0 ,GLOBAL1 ,GLOBAL1};\r
-\r
-\r
-//\r
-// offset from tile.x,tile.y of the tile that shares wallon side\r
-// (side is not visable if it is shared)\r
-//\r
-int sharex[4] = { 0, 1, 0,-1};\r
-int sharey[4] = {-1, 0, 1, 0};\r
-\r
-//\r
-// amount to move tile.x,tile.y to follow wallon to another tile\r
-//\r
-int followx[4] = {-1, 0, 1, 0};\r
-int followy[4] = { 0,-1, 0, 1};\r
-\r
-//\r
-// cornerwall gives the wall on the same tile to start following when the\r
-// wall ends at an empty tile (go around an edge on same tile)\r
-// turnwall gives the wall on tile.x+sharex,tile.y+sharey to start following\r
-// when the wall hits another tile (right angle corner)\r
-//\r
-int cornerwall[4] = {WEST,NORTH,EAST,SOUTH};\r
-int turnwall[4] = {EAST,SOUTH,WEST,NORTH};\r
-\r
-//\r
-// wall visabilities in reletive locations\r
-// -,- 0,- +,-\r
-// -,0 0,0 +,0\r
-// -,+ 0,+ +,+\r
-//\r
-int visable[9][4] =\r
-{\r
- {0,1,1,0}, {0,0,1,0}, {0,0,1,1},\r
- {0,1,0,0}, {0,0,0,0}, {0,0,0,1},\r
- {1,1,0,0}, {1,0,0,0}, {1,0,0,1}\r
-};\r
-\r
-int startwall[9] = {2,2,3, 1,0,3, 1,0,0};\r
-int backupwall[9] = {3,3,0, 2,0,0, 2,1,1};\r
-\r
-\r
-int walllength;\r
-\r
-/*\r
-=============================================================================\r
-\r
- FUNCTIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-========================\r
-=\r
-= FollowTrace\r
-=\r
-========================\r
-*/\r
-\r
-int FollowTrace (fixed tracex, fixed tracey, long deltax, long deltay, int max)\r
-{\r
- int tx,ty,otx,oty;\r
- long absdx,absdy,xstep,ystep;\r
-\r
- tx = tracex>>TILESHIFT;\r
- ty = tracey>>TILESHIFT;\r
-\r
- spotvis[tx][ty] = true;\r
-\r
- absdx=LABS(deltax);\r
- absdy=LABS(deltay);\r
-\r
- if (absdx>absdy)\r
- {\r
- ystep = (deltay<<8)/(absdx>>8);\r
-\r
- if (!ystep)\r
- ystep = deltay>0 ? 1 : -1;\r
-\r
- oty = (tracey+ystep)>>TILESHIFT;\r
- if (deltax>0)\r
- {\r
-//###############\r
-//\r
-// step x by +1\r
-//\r
-//###############\r
- do\r
- {\r
- tx++;\r
- spotvis[tx][ty] = true;\r
- tracey+=ystep;\r
- ty = tracey>>TILESHIFT;\r
-\r
- if (ty!=oty)\r
- {\r
- if (tilemap[tx-1][ty])\r
- {\r
- tile.x = tx-1;\r
- tile.y = ty;\r
- return 1;\r
- }\r
- oty = ty;\r
- }\r
- if (tilemap[tx][ty])\r
- {\r
- tile.x = tx;\r
- tile.y = ty;\r
- return 1;\r
- }\r
- } while (--max);\r
- return 0;\r
- }\r
- else\r
- {\r
-//###############\r
-//\r
-// step x by -1\r
-//\r
-//###############\r
- do\r
- {\r
- tx--;\r
- spotvis[tx][ty] = true;\r
- tracey+=ystep;\r
- ty = tracey>>TILESHIFT;\r
-\r
- if (ty!=oty)\r
- {\r
- if (tilemap[tx][oty])\r
- {\r
- tile.x = tx;\r
- tile.y = oty;\r
- return 1;\r
- }\r
- oty = ty;\r
- }\r
- if (tilemap[tx][ty])\r
- {\r
- tile.x = tx;\r
- tile.y = ty;\r
- return 1;\r
- }\r
- } while (--max);\r
- return 0;\r
-\r
- }\r
- }\r
- else\r
- {\r
- xstep = (deltax<<8)/(absdy>>8);\r
- if (!xstep)\r
- xstep = deltax>0 ? 1 : -1;\r
-\r
-\r
- otx = (tracex+xstep)>>TILESHIFT;\r
- if (deltay>0)\r
- {\r
-//###############\r
-//\r
-// step y by +1\r
-//\r
-//###############\r
- do\r
- {\r
- ty++;\r
- spotvis[tx][ty] = true;\r
- tracex+=xstep;\r
- tx = tracex>>TILESHIFT;\r
-\r
- if (tx!=otx)\r
- {\r
- if (tilemap[tx][ty-1])\r
- {\r
- tile.x = tx;\r
- tile.y = ty-1;\r
- return 1;\r
- }\r
- otx = tx;\r
- }\r
- if (tilemap[tx][ty])\r
- {\r
- tile.x = tx;\r
- tile.y = ty;\r
- return 1;\r
- }\r
- } while (--max);\r
- return 0;\r
- }\r
- else\r
- {\r
-//###############\r
-//\r
-// step y by -1\r
-//\r
-//###############\r
- do\r
- {\r
- ty--;\r
- spotvis[tx][ty] = true;\r
- tracex+=xstep;\r
- tx = tracex>>TILESHIFT;\r
-\r
- if (tx!=otx)\r
- {\r
- if (tilemap[otx][ty])\r
- {\r
- tile.x = otx;\r
- tile.y = ty;\r
- return 1;\r
- }\r
- otx = tx;\r
- }\r
- if (tilemap[tx][ty])\r
- {\r
- tile.x = tx;\r
- tile.y = ty;\r
- return 1;\r
- }\r
- } while (--max);\r
- return 0;\r
- }\r
-\r
- }\r
-\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= BackTrace\r
-=\r
-= Traces backwards from edgex,edgey to viewx,viewy to see if a closer\r
-= tile obscures the given point. If it does, it finishes the wall and\r
-= starts a new one.\r
-= Returns true if a tile is hit.\r
-= Call with a 1 to have it automatically finish the current wall\r
-=\r
-=================\r
-*/\r
-\r
-int BackTrace (int finish)\r
-{\r
- fixed tracex,tracey;\r
- long deltax,deltay,absdx,absdy;\r
- int steps,otx,oty,testx,testheight,offset,wall;\r
-\r
- deltax = viewx-edgex;\r
- deltay = viewy-edgey;\r
-\r
- absdx = LABS(deltax);\r
- absdy = LABS(deltay);\r
-\r
- if (absdx>absdy)\r
- steps = ABS(focal.x-(edgex>>TILESHIFT))-1;\r
- else\r
- steps = ABS(focal.y-(edgey>>TILESHIFT))-1;\r
-\r
- if (steps<=0)\r
- return 0;\r
-\r
- otx = tile.x;\r
- oty = tile.y;\r
- if (!FollowTrace(edgex,edgey,deltax,deltay,steps))\r
- return 0;\r
-\r
-//\r
-// if the start wall is behind the focal point, the trace went too far back\r
-//\r
- if (ABS(tile.x-focal.x)<2 && ABS(tile.y-focal.y)<2) // too close\r
- {\r
- if (tile.x == focal.x && tile.y == focal.y)\r
- {\r
- tile.x = otx;\r
- tile.y = oty;\r
- return 0;\r
- }\r
-\r
- if (tile.x<focal.x)\r
- {\r
- if (tile.y<focal.y)\r
- wall = SOUTH;\r
- else\r
- wall = EAST;\r
- }\r
- else if (tile.x==focal.x)\r
- {\r
- if (tile.y<focal.y)\r
- wall = SOUTH;\r
- else\r
- wall = NORTH;\r
- }\r
- else\r
- {\r
- if (tile.y<=focal.y)\r
- wall = WEST;\r
- else\r
- wall = NORTH;\r
- }\r
-\r
- //\r
- // rotate the X value to see if it is behind the view plane\r
- //\r
- if (TransformX (((long)tile.x<<16)+point1x[wall],\r
- ((long)tile.y<<16)+point1y[wall]) < FOCALLENGTH)\r
- {\r
- tile.x = otx;\r
- tile.y = oty;\r
- return 0;\r
- }\r
- }\r
-\r
-//\r
-// if the old wall is still behind a closer wall, ignore the back trace\r
-// and continue on (dealing with limited precision...)\r
-//\r
- if (finish && !FinishWall ()) // the wall is still behind a forward wall\r
- {\r
- tile.x = otx;\r
- tile.y = oty;\r
- rightwall->x1 = oldwall->x2; // common edge with last wall\r
- rightwall->height1 = oldwall->height2;\r
- return 0;\r
- }\r
-\r
-\r
-//\r
-// back up along the intersecting face to find the rightmost wall\r
-//\r
-\r
- if (tile.y<focal.y)\r
- offset = 0;\r
- else if (tile.y==focal.y)\r
- offset = 3;\r
- else\r
- offset = 6;\r
- if (tile.x==focal.x)\r
- offset ++;\r
- else if (tile.x>focal.x)\r
- offset += 2;\r
-\r
- wallon = backupwall[offset];\r
-\r
- while (tilemap[tile.x][tile.y])\r
- {\r
- tile.x += followx[wallon];\r
- tile.y += followy[wallon];\r
- };\r
-\r
- tile.x -= followx[wallon];\r
- tile.y -= followy[wallon];\r
-\r
- wallon = cornerwall[wallon]; // turn to first visable face\r
-\r
- edgex = ((long)tile.x<<16);\r
- edgey = ((long)tile.y<<16);\r
-\r
- TransformPoint (edgex+point1x[wallon],edgey+point1y[wallon],\r
- &rightwall->x1,&rightwall->height1);\r
-\r
- basecolor = tilemap[tile.x][tile.y];\r
-\r
- return 1;\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= ForwardTrace\r
-=\r
-= Traces forwards from edgex,edgey along the line from viewx,viewy until\r
-= a solid tile is hit. Sets tile.x,tile.y\r
-=\r
-=================\r
-*/\r
-\r
-void ForwardTrace (void)\r
-{\r
- int offset;\r
- fixed tracex,tracey;\r
- long deltax,deltay;\r
-\r
- deltax = edgex-viewx;\r
- deltay = edgey-viewy;\r
-\r
- FollowTrace(edgex,edgey,deltax,deltay,0);\r
-\r
- if (tile.y<focal.y)\r
- offset = 0;\r
- else if (tile.y==focal.y)\r
- offset = 3;\r
- else\r
- offset = 6;\r
- if (tile.x==focal.x)\r
- offset ++;\r
- else if (tile.x>focal.x)\r
- offset += 2;\r
-\r
- wallon = startwall[offset];\r
-\r
-//\r
-// start the new wall\r
-//\r
- edgex = ((long)tile.x<<16);\r
- edgey = ((long)tile.y<<16);\r
-\r
-//\r
-// if entire first wall is invisable, corner\r
-//\r
- TransformPoint (edgex+point2x[wallon],edgey+point2y[wallon],\r
- &rightwall->x2,&rightwall->height2);\r
-\r
- if (tilemap [tile.x+sharex[wallon]] [tile.y+sharey[wallon]]\r
- || rightwall->x2 < (rightwall-1)->x2 )\r
- wallon = cornerwall [wallon];\r
-\r
-//\r
-// transform first point\r
-//\r
-\r
- TransformPoint (edgex+point1x[wallon],edgey+point1y[wallon],\r
- &rightwall->x1,&rightwall->height1);\r
-\r
- basecolor = tilemap[tile.x][tile.y];\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= FinishWall\r
-=\r
-= Transforms edgex,edgey as the next point of the current wall\r
-= and sticks it in the wall list\r
-=\r
-=================\r
-*/\r
-\r
-int FinishWall (void)\r
-{\r
- char num[20];\r
-\r
- oldwall = rightwall;\r
-\r
- rightwall->color = basecolor;\r
-\r
- TransformPoint (edgex,edgey,&rightwall->x2,&rightwall->height2);\r
-\r
- if (rightwall->x2 <= (rightwall-1)->x2+2\r
- && rightwall->height2 < (rightwall-1)->height2 )\r
- return 0;\r
-\r
- rightwall->walllength = walllength;\r
-\r
- switch (wallon)\r
- {\r
- case north:\r
- case south:\r
- rightwall->side = 0;\r
- rightwall->planecoord = edgey;\r
- break;\r
-\r
- case west:\r
- case east:\r
- rightwall->side = 1;\r
- rightwall->planecoord = edgex;\r
- break;\r
- }\r
-\r
- walllength = 1;\r
-\r
- rightwall++;\r
-\r
- return 1;\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= InsideCorner\r
-=\r
-=================\r
-*/\r
-\r
-void InsideCorner (void)\r
-{\r
- int offset;\r
-\r
- //\r
- // the wall turned -90 degrees, so draw what we have, move to the new tile,\r
- // change wallon, change color, and continue following.\r
- //\r
- FinishWall ();\r
-\r
- tile.x += sharex[wallon];\r
- tile.y += sharey[wallon];\r
-\r
- wallon = turnwall[wallon];\r
-\r
- //\r
- // if the new wall is visable, continue following it. Otherwise\r
- // follow it backwards until it turns\r
- //\r
- TESTWALLVISABLE;\r
-\r
- if (wallvisable)\r
- {\r
- //\r
- // just turn to the next wall and continue\r
- //\r
- rightwall->x1 = oldwall->x2; // common edge with last wall\r
- rightwall->height1 = oldwall->height2;\r
- basecolor = tilemap[tile.x][tile.y];\r
- return; // continue from here\r
- }\r
-\r
- //\r
- // back follow the invisable wall until it turns, then follow that\r
- //\r
- do\r
- {\r
- tile.x += followx[wallon];\r
- tile.y += followy[wallon];\r
- } while (tilemap[tile.x][tile.y]);\r
-\r
- tile.x -= followx[wallon];\r
- tile.y -= followy[wallon];\r
-\r
- wallon = cornerwall[wallon]; // turn to first visable face\r
-\r
- edgex = ((long)tile.x<<16)+point1x[wallon];\r
- edgey = ((long)tile.y<<16)+point1y[wallon];\r
-\r
- if (!BackTrace(0)) // backtrace without finishing a wall\r
- {\r
- TransformPoint (edgex,edgey,&rightwall->x1,&rightwall->height1);\r
- basecolor = tilemap[tile.x][tile.y];\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= OutsideCorner\r
-=\r
-=================\r
-*/\r
-\r
-void OutsideCorner (void)\r
-{\r
- int offset;\r
-\r
- //\r
- // edge is the outside edge of a corner, so draw the current wall and\r
- // turn the corner (+90 degrees)\r
- //\r
- FinishWall ();\r
-\r
- tile.x -= followx[wallon]; // backup to the real tile\r
- tile.y -= followy[wallon];\r
- wallon = cornerwall[wallon];\r
-\r
- //\r
- // if the new wall is visable, continue following it. Otherwise\r
- // trace a ray from the corner to find a wall in the distance to\r
- // follow\r
- //\r
- TESTWALLVISABLE;\r
-\r
- if (wallvisable)\r
- {\r
- //\r
- // the new wall is visable, so just continue on\r
- //\r
- rightwall->x1 = oldwall->x2; // common edge with last wall\r
- rightwall->height1 = oldwall->height2;\r
- return; // still on same tile, so color is ok\r
- }\r
-\r
-//\r
-// start from a new tile further away\r
-//\r
- ForwardTrace(); // find the next wall further back\r
-\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= FollowWalls\r
-=\r
-= Starts a wall edge at the leftmost edge of tile.x,tile.y and follows it\r
-= until something else is seen or the entire view area is covered\r
-=\r
-=================\r
-*/\r
-\r
-void FollowWalls (void)\r
-{\r
- int height,newcolor,offset,wall;\r
-\r
-//####################\r
-//\r
-// figure leftmost wall of new tile\r
-//\r
-//####################\r
-\r
-restart:\r
-\r
- walllength = 1;\r
-\r
- if (tile.y<focal.y)\r
- offset = 0;\r
- else if (tile.y==focal.y)\r
- offset = 3;\r
- else\r
- offset = 6;\r
- if (tile.x==focal.x)\r
- offset ++;\r
- else if (tile.x>focal.x)\r
- offset += 2;\r
-\r
- wallon = startwall[offset];\r
-\r
-//\r
-// if the start wall is inside a block, skip it by cornering to the second wall\r
-//\r
- if ( tilemap [tile.x+sharex[wallon]] [tile.y+sharey[wallon]])\r
- wallon = cornerwall [wallon];\r
-\r
-//\r
-// transform first edge to screen coordinates\r
-//\r
- edgex = ((long)tile.x<<16);\r
- edgey = ((long)tile.y<<16);\r
-\r
- TransformPoint (edgex+point1x[wallon],edgey+point1y[wallon],\r
- &rightwall->x1,&rightwall->height1);\r
-\r
- basecolor = tilemap[tile.x][tile.y];\r
-\r
-//##################\r
-//\r
-// follow the wall as long as possible\r
-//\r
-//##################\r
-\r
-advance:\r
-\r
- do // while ( tile.x != right.x || tile.y != right.y)\r
- {\r
-//\r
-// check for conditions that shouldn't happed...\r
-//\r
- if (rightwall->x1 > VIEWXH) // somehow missed right tile...\r
- return;\r
-\r
- if (rightwall == &walls[DANGERHIGH])\r
- {\r
- //\r
- // somethiing got messed up! Correct by thrusting ahead...\r
- //\r
-// VW_ColorBorder(6);\r
- bordertime = 60;\r
- Thrust(player->angle,TILEGLOBAL/4);\r
- player->angle+=5;\r
- if (player->angle>ANGLES)\r
- player->angle-=ANGLES;\r
- aborttrace = true;\r
- return;\r
-\r
-#if 0\r
- strcpy (str,"Wall list overflow at LE:");\r
- itoa(mapon+1,str2,10);\r
- strcat (str,str2);\r
- strcat (str," X:");\r
- ltoa(objlist[0].x,str2,10);\r
- strcat (str,str2);\r
- strcat (str," Y:");\r
- ltoa(objlist[0].y,str2,10);\r
- strcat (str,str2);\r
- strcat (str," AN:");\r
- itoa(objlist[0].angle,str2,10);\r
- strcat (str,str2);\r
-\r
- Quit (str);\r
-#endif\r
- }\r
-\r
-//\r
-// proceed along wall\r
-//\r
-\r
- edgex = ((long)tile.x<<16)+point2x[wallon];\r
- edgey = ((long)tile.y<<16)+point2y[wallon];\r
-\r
- if (BackTrace(1)) // went behind a closer wall\r
- continue;\r
-\r
- //\r
- // advance to next tile along wall\r
- //\r
- tile.x += followx[wallon];\r
- tile.y += followy[wallon];\r
-\r
- if (tilemap [tile.x+sharex[wallon]] [tile.y+sharey[wallon]])\r
- {\r
- InsideCorner (); // turn at a corner\r
- continue;\r
- }\r
-\r
- newcolor = tilemap[tile.x][tile.y];\r
-\r
- if (!newcolor) // turn around an edge\r
- {\r
- OutsideCorner ();\r
- continue;\r
- }\r
-\r
- if (newcolor != basecolor)\r
- {\r
- //\r
- // wall changed color, so draw what we have and continue following\r
- //\r
- FinishWall ();\r
- rightwall->x1 = oldwall->x2; // new wall shares this edge\r
- rightwall->height1 = oldwall->height2;\r
- basecolor = newcolor;\r
-\r
- continue;\r
- }\r
- walllength++;\r
- } while (tile.x != right.x || tile.y != right.y);\r
-\r
-\r
-\r
-//######################\r
-//\r
-// draw the last tile\r
-//\r
-//######################\r
-\r
- edgex = ((long)tile.x<<16)+point2x[wallon];\r
- edgey = ((long)tile.y<<16)+point2y[wallon];\r
- FinishWall();\r
-\r
- wallon = cornerwall[wallon];\r
-\r
- //\r
- // if the corner wall is visable, draw it\r
- //\r
- TESTWALLVISABLE;\r
-\r
- if (wallvisable)\r
- {\r
- rightwall->x1 = oldwall->x2; // common edge with last wall\r
- rightwall->height1 = oldwall->height2;\r
- edgex = ((long)tile.x<<16)+point2x[wallon];\r
- edgey = ((long)tile.y<<16)+point2y[wallon];\r
- FinishWall();\r
- }\r
-\r
-}\r
-\r
-//===========================================================================\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// C3_WIZ.C\r
-\r
-#include "DEF.H"\r
-#include "gelib.h"\r
-#pragma hdrstop\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-////////#define NUMSCROLLS 8\r
-\r
-#define SHOWITEMS 9\r
-\r
-#define NUKETIME 40\r
-#define NUMBOLTS 10\r
-#define BOLTTICS 6\r
-\r
-#define STATUSCOLOR 8\r
-#define TEXTCOLOR 14\r
-\r
-#define SIDEBARWIDTH 5\r
-\r
-#define BODYLINE 8\r
-#define POWERLINE 80\r
-\r
-#define SPECTILESTART 0 // 18\r
-\r
-\r
-#define SHOTDAMAGE 1\r
-#define BIGSHOTDAMAGE 3\r
-\r
-\r
-#define PLAYERSPEED 5120\r
-#define RUNSPEED (8192<<1)\r
-\r
-#define SHOTSPEED 10000\r
-\r
-//#define LASTWALLTILE 47\r
-//#define LASTSPECIALTILE 37\r
-\r
-#define LASTTILE (LASTWALLPIC-FIRSTWALLPIC) // 47\r
-\r
-#define FIRETIME 2\r
-\r
-#define HANDPAUSE 60\r
-\r
-#define RIGHTEDGE 205;\r
-#define LEFTEDGE 95;\r
-#define PRNY 32;\r
-#define WINX 10;\r
-#define WINY 32;\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-long lastnuke,lasthand;\r
-int lasttext;\r
-int handheight;\r
-int boltsleft,bolttimer;\r
-short RadarXY[MAX_RADAR_BLIPS][3]={-1,-1,-1};\r
-short radarx=RADARX,radary=RADARY,radar_xcenter=RADAR_XCENTER,radar_ycenter=RADAR_YCENTER;\r
-int key_x[4]={24,27,27,24},key_y[4]={30,57,30,57};\r
-\r
-boolean redraw_gems,button0down;\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-int lastradar;\r
-unsigned lastfiretime;\r
-\r
-int strafeangle[9] = {0,90,180,270,45,135,225,315,0};\r
-\r
-short RotateAngle = -1; // -1 == No Angle to turn to...\r
-short FreezeTime = 0; // Stops all think (except player)\r
-short RotateSpeed; // Speed (and dir) to rotate..\r
-\r
-\r
-//===========================================================================\r
-\r
-void CalcBounds(objtype *ob);\r
-boolean VerifyGateExit(void);\r
-void DrawNSEWIcons(void);\r
-void DrawGems(void);\r
-void DrawRadar (void);\r
-void DrawChar (unsigned x, unsigned y, unsigned tile);\r
-void RedrawStatusWindow (void);\r
-void GiveBolt (void);\r
-void TakeBolt (void);\r
-void GiveNuke (void);\r
-void TakeNuke (void);\r
-void GivePotion (void);\r
-void TakePotion (void);\r
-void GiveKey (int keytype);\r
-void TakeKey (int keytype);\r
-////////////void GiveScroll (int scrolltype,boolean show);\r
-////////////void ReadScroll (int scroll);\r
-////////////void DrawScrolls(void);\r
-\r
-void DrawNum(short x,short y,short value,short maxdigits);\r
-\r
-//----------\r
-\r
-void Shoot (void);\r
-void BigShoot (void);\r
-void CastBolt (void);\r
-void CastNuke (void);\r
-void DrinkPotion (void);\r
-\r
-//----------\r
-void DrawHealth(void);\r
-\r
-void SpawnPlayer (int tilex, int tiley, int dir);\r
-void Thrust (int angle, unsigned speed);\r
-void T_Player (objtype *ob);\r
-\r
-//void AddPoints (int points);\r
-\r
-void ClipMove (objtype *ob, long xmove, long ymove);\r
-boolean ShotClipMove (objtype *ob, long xmove, long ymove);\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= DrawChar\r
-=\r
-===============\r
-*/\r
-\r
-void DrawChar (unsigned x, unsigned y, unsigned tile)\r
-{\r
- unsigned junk = latchpics[0];\r
-\r
- EGAWRITEMODE(1);\r
-asm mov bx,[y]\r
-asm shl bx,1\r
-asm mov di,[WORD PTR ylookup+bx]\r
-asm add di,[x]\r
-asm mov si,[tile]\r
-asm shl si,1\r
-asm shl si,1\r
-asm shl si,1\r
-asm add si,[junk] // the damn inline assembler won't reference latchpics\r
-asm mov ax,[screenseg]\r
-asm mov es,ax\r
-asm mov ds,ax\r
-asm mov dx,SCREENWIDTH-1\r
-asm movsb\r
-asm add di,dx\r
-asm movsb\r
-asm add di,dx\r
-asm movsb\r
-asm add di,dx\r
-asm movsb\r
-asm add di,dx\r
-asm movsb\r
-asm add di,dx\r
-asm movsb\r
-asm add di,dx\r
-asm movsb\r
-asm add di,dx\r
-asm movsb\r
-\r
-asm mov ax,ss\r
-asm mov ds,ax\r
- EGAWRITEMODE(0);\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= RedrawStatusWindow\r
-=\r
-===============\r
-*/\r
-\r
-void RedrawStatusWindow (void)\r
-{\r
- short keytype;\r
-\r
- EGABITMASK(0xff);\r
- for (keytype=0; keytype<4; keytype++)\r
- DrawNum(key_x[keytype],key_y[keytype],gamestate.keys[keytype],2);\r
- DrawNum(20,54,gamestate.potions,2);\r
- DrawNum(20,36,gamestate.nukes,2);\r
- DrawNum(20,18,gamestate.bolts,2);\r
-\r
- DrawHealth();\r
- DrawRadar();\r
- EGAWRITEMODE(0);\r
- DrawGems();\r
-//////// DrawScrolls();\r
- redraw_gems = false;\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= GiveBolt\r
-=\r
-===============\r
-*/\r
-\r
-void GiveBolt (void)\r
-{\r
- if (gamestate.bolts == 99)\r
- return;\r
-\r
- SD_PlaySound (GETBOLTSND);\r
- DrawNum(20,18,++gamestate.bolts,2);\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= TakeBolt\r
-=\r
-===============\r
-*/\r
-\r
-void TakeBolt (void)\r
-{\r
- SD_PlaySound (USEBOLTSND);\r
- DrawNum(20,18,--gamestate.bolts,2);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= GiveNuke\r
-=\r
-===============\r
-*/\r
-\r
-void GiveNuke (void)\r
-{\r
- if (gamestate.nukes == 99)\r
- return;\r
-\r
- SD_PlaySound (GETNUKESND);\r
- DrawNum(20,36,++gamestate.nukes,2);\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= TakeNuke\r
-=\r
-===============\r
-*/\r
-\r
-void TakeNuke (void)\r
-{\r
- SD_PlaySound (USENUKESND);\r
- DrawNum(20,36,--gamestate.nukes,2);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= GivePotion\r
-=\r
-===============\r
-*/\r
-\r
-void GivePotion (void)\r
-{\r
- if (gamestate.potions == 99)\r
- return;\r
-\r
- SD_PlaySound (GETPOTIONSND);\r
- DrawNum(20,54,++gamestate.potions,2);\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= TakePotion\r
-=\r
-===============\r
-*/\r
-\r
-void TakePotion (void)\r
-{\r
- SD_PlaySound (USEPOTIONSND);\r
- DrawNum(20,54,--gamestate.potions,2);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= GiveKey\r
-=\r
-===============\r
-*/\r
-\r
-void GiveKey (int keytype)\r
-{\r
- int i,j,x;\r
-\r
- if (gamestate.keys[keytype] == 99)\r
- return;\r
-\r
- SD_PlaySound (GETKEYSND);\r
- DrawNum(key_x[keytype],key_y[keytype],++gamestate.keys[keytype],2);\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= TakeKey\r
-=\r
-===============\r
-*/\r
-\r
-void TakeKey (int keytype)\r
-{\r
- int i,j,x;\r
- char *key_colors[] = {"a RED key",\r
- "a YELLOW key",\r
- "a GREEN key",\r
- "a BLUE key"};\r
-\r
-\r
- SD_PlaySound (USEKEYSND);\r
- DrawNum(key_x[keytype],key_y[keytype],--gamestate.keys[keytype],2);\r
- displayofs = bufferofs = screenloc[screenpage];\r
- CenterWindow(20,5);\r
- US_CPrint("\nYou use\n");\r
- US_CPrint(key_colors[keytype]);\r
- VW_UpdateScreen();\r
- VW_WaitVBL(120);\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= GiveGem\r
-=\r
-===============\r
-*/\r
-\r
-void GiveGem (int gemtype)\r
-{\r
-#if 0\r
- int i,j,x;\r
-\r
- SD_PlaySound (GETKEYSND);\r
- DrawNum(key_x[keytype],key_y[keytype],++gamestate.keys[keytype],2);\r
-#endif\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= TakeGem\r
-=\r
-===============\r
-*/\r
-\r
-void TakeGem (int gemtype)\r
-{\r
-#if 0\r
- int i,j,x;\r
-\r
- SD_PlaySound (USEKEYSND);\r
- DrawNum(key_x[keytype],key_y[keytype],--gamestate.keys[keytype],2);\r
-#endif\r
-}\r
-\r
-/*\r
-===============\r
-=\r
-= DrawGem\r
-=\r
-===============\r
-*/\r
-\r
-void DrawGems()\r
-{\r
- short loop;\r
-\r
- redraw_gems = false;\r
-\r
- bufferofs = 0;\r
- LatchDrawPic (31,51,RADAR_BOTTOMPIC);\r
- for (loop=0; loop<5; loop++)\r
- if (gamestate.gems[loop])\r
- LatchDrawPic (32+loop,53,RADAR_RGEMPIC+loop);\r
-}\r
-\r
-//===========================================================================\r
-\r
-#if 0\r
-\r
-/*\r
-===============\r
-=\r
-= GiveScroll\r
-=\r
-===============\r
-*/\r
-\r
-void GiveScroll (int scrolltype,boolean show)\r
-{\r
- int i,j,x,y,scrollnum;\r
-\r
- SD_PlaySound (GETSCROLLSND);\r
- gamestate.scrolls[scrolltype] = true;\r
-\r
- y = 30 + ((scrolltype > 3) * 10);\r
- x = 26 + (scrolltype % 4);\r
- DrawChar(x,y,SCROLLCHARS+scrolltype);\r
-\r
- if (show)\r
- ReadScroll(scrolltype);\r
-}\r
-\r
-/*\r
-===============\r
-=\r
-= DrawScrolls\r
-=\r
-= Force draw of all scrolls\r
-=\r
-===============\r
-*/\r
-void DrawScrolls()\r
-{\r
- int loop,x,y;\r
-\r
- VW_Bar(210,30,30,18,0xf);\r
-\r
- for (loop=0;loop<8;loop++)\r
- if (gamestate.scrolls[loop])\r
- {\r
- y = 30 + ((loop > 3) * 10);\r
- x = 26 + (loop % 4);\r
- DrawChar(x,y,SCROLLCHARS+loop);\r
- }\r
-}\r
-#endif\r
-\r
-\r
-//===========================================================================\r
-\r
-#if 0\r
-/*\r
-===============\r
-=\r
-= GivePoints\r
-=\r
-===============\r
-*/\r
-\r
-void GivePoints (int points)\r
-{\r
- pointcount = 1;\r
- pointsleft += points;\r
-}\r
-#endif\r
-\r
-\r
-//===========================================================================\r
-\r
-#if 0\r
-/*\r
-===============\r
-=\r
-= AddPoints\r
-=\r
-===============\r
-*/\r
-\r
-void AddPoints (int points)\r
-{\r
- char str[10];\r
- int len,x,i;\r
-\r
- gamestate.score += points;\r
-\r
- ltoa (gamestate.score,str,10);\r
- len = strlen (str);\r
-\r
- x=24+(8-len);\r
- for (i=0;i<len;i++)\r
- DrawChar(x++,40,NUMBERCHARS+str[i]-'0');\r
-}\r
-#endif\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= DrawHealth\r
-=\r
-===============\r
-*/\r
-void DrawHealth()\r
-{\r
- char picnum;\r
- int percentage;\r
-\r
- percentage = PERCENTAGE(100,MAXBODY,gamestate.body,9);\r
-\r
- DrawNum(11,57,percentage,3);\r
-\r
- if (percentage > 75)\r
- picnum = FACE1PIC;\r
- else\r
- if (percentage > 50)\r
- picnum = FACE2PIC;\r
- else\r
- if (percentage > 25)\r
- picnum = FACE3PIC;\r
- else\r
- if (percentage)\r
- picnum = FACE4PIC;\r
- else\r
- {\r
- picnum = FACE5PIC;\r
- CA_CacheGrChunk (picnum);\r
- }\r
-\r
- bufferofs = 0;\r
- if (!percentage)\r
- {\r
- UNMARKGRCHUNK(picnum);\r
-// VW_DrawPic(8,14,picnum);\r
- VW_DrawPic(10,14,picnum);\r
- }\r
- else\r
- LatchDrawPic(10,14,picnum);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= DrawFreezeTime\r
-=\r
-===============\r
-*/\r
-void DrawFreezeTime()\r
-{\r
- long percentage;\r
- percentage = PERCENTAGE(100,MAXFREEZETIME,(long)FreezeTime,7);\r
- DrawNum(23,70,percentage,3);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= DrawNum\r
-=\r
-===============\r
-*/\r
-void DrawNum(short x,short y,short value,short maxdigits)\r
-{\r
- char str[10],len,i;\r
-\r
- itoa(value,str,10);\r
- len=strlen(str);\r
-\r
- for (i=len; i<maxdigits; i++)\r
- DrawChar(x++,y,BLANKCHAR);\r
-\r
- for (i=0;i<len;i++)\r
- DrawChar(x++,y,NUMBERCHARS+str[i]-'0');\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= GiveChest\r
-=\r
-===============\r
-*/\r
-\r
-void GiveChest(void)\r
-{\r
- char i;\r
-\r
- for (i=0;i<random(4);i++)\r
- {\r
- GiveBolt();\r
- SD_WaitSoundDone();\r
- }\r
-\r
- for (i=0;i<random(3);i++)\r
- {\r
- GiveNuke();\r
- SD_WaitSoundDone();\r
- }\r
-\r
- for (i=0;i<random(2);i++)\r
- {\r
- GivePotion();\r
- SD_WaitSoundDone();\r
- }\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= GiveGoal\r
-=\r
-===============\r
-*/\r
-\r
-void GiveGoal (void)\r
-{\r
- SD_PlaySound (GETPOINTSSND);\r
- playstate = ex_victorious;\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-#if 0\r
-/*\r
-===============\r
-=\r
-= DrawLevelNumber\r
-=\r
-===============\r
-*/\r
-\r
-void DrawLevelNumber (int number)\r
-{\r
- char str[10];\r
- int len;\r
- unsigned temp;\r
-\r
- bufferofs = 0;\r
- if (number<9)\r
- PrintX=13;\r
- else\r
- PrintX = 5;\r
- PrintY = 4;\r
- VW_Bar (5,4,16,9,STATUSCOLOR);\r
- temp = fontcolor;\r
- fontcolor = TEXTCOLOR^STATUSCOLOR;\r
- US_PrintUnsigned (number+1);\r
- fontcolor = temp;\r
-}\r
-#endif\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= DrawText\r
-=\r
-===============\r
-*/\r
-\r
-void DrawText (boolean draw_text_whether_it_needs_it_or_not)\r
-{\r
- unsigned number;\r
- char str[80];\r
- char far *text;\r
- unsigned temp;\r
-\r
- //\r
- // draw a new text description if needed\r
- //\r
- number = *(mapsegs[0]+farmapylookup[player->tiley]+player->tilex)-NAMESTART;\r
-\r
- if ( number>26 )\r
- number = 0;\r
-\r
- if ((number == lasttext) && (!draw_text_whether_it_needs_it_or_not))\r
- return;\r
-\r
- lasttext = number;\r
-\r
- text = (char _seg *)grsegs[LEVEL1TEXT+mapon]+textstarts[number];\r
-\r
- _fmemcpy (str,text,80);\r
- DisplayMsg(str,NULL);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= DisplayMsg\r
-=\r
-===============\r
-*/\r
-\r
-char DisplayMsg(char *text,char *choices)\r
-{\r
- char ch=true;\r
- short temp;\r
-\r
- bufferofs = 0;\r
- PrintY = 1;\r
- WindowX = 20;\r
- WindowW = 270;\r
-\r
- VW_Bar (WindowX,2,WindowW,8,STATUSCOLOR);\r
- temp = fontcolor;\r
- fontcolor = TEXTCOLOR^STATUSCOLOR;\r
- US_CPrintLine (text);\r
- fontcolor = temp;\r
-\r
- if (choices)\r
- {\r
- ch=GetKeyChoice(choices,true);\r
- LastScan = 0;\r
- }\r
-\r
- return(ch);\r
-}\r
-\r
-/*\r
-===============\r
-=\r
-= DisplaySMsg\r
-=\r
-===============\r
-*/\r
-char DisplaySMsg(char *text,char *choices)\r
-{\r
- char ch=true;\r
- short temp;\r
-\r
- bufferofs = 0;\r
- PrintY = 69;\r
- WindowX = 98;\r
- WindowW = 115;\r
-\r
- VW_Bar(WindowX,PrintY+1,WindowW,8,STATUSCOLOR);\r
- temp = fontcolor;\r
- fontcolor = TEXTCOLOR^STATUSCOLOR;\r
- US_CPrintLine (text);\r
- fontcolor = temp;\r
-\r
- if (choices)\r
- {\r
- ch=GetKeyChoice(choices,true);\r
- LastScan = 0;\r
- }\r
-\r
- return(ch);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= DrawRadar\r
-=\r
-===============\r
-*/\r
-\r
-void DrawRadar (void)\r
-{\r
- int angle,number;\r
- short objnum;\r
-\r
- bufferofs = 0;\r
- LatchDrawPic (radarx,radary,RADAR_TOPPIC);\r
-\r
- asm cli\r
- asm mov dx,GC_INDEX\r
- asm mov ax,2*256+GC_MODE\r
- asm out dx,ax // write mode 2\r
-\r
- asm mov ax,GC_DATAROTATE\r
- asm out dx,ax // no rotation / logical operation\r
-\r
- asm mov dx,SC_INDEX\r
- asm mov al,SC_MAPMASK\r
- asm mov ah,15\r
- asm out dx,ax // write to all four planes\r
- asm sti\r
-\r
- objnum = 0;\r
- while (RadarXY[objnum][2] != -1)\r
- {\r
- RadarBlip(radar_xcenter+RadarXY[objnum][0],radar_ycenter+RadarXY[objnum][1],RadarXY[objnum][2]);\r
- objnum++;\r
- }\r
-\r
- asm cli\r
- asm mov dx,GC_INDEX\r
- asm mov ax,255*256+GC_BITMASK\r
- asm out dx,ax // reset bitmask to %11111111\r
- asm sti\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-// DrawNSEWIcons(void)\r
-//--------------------------------------------------------------------------\r
-\r
-void DrawRadarObj(short dx, short dy, unsigned sprnum,signed long psin,signed long pcos);\r
-\r
-void DrawNSEWIcons()\r
-{\r
- signed x,y;\r
-\r
- x = -FixedByFrac(RADAR_X_IRADIUS,costable[player->angle]);\r
- y = -FixedByFrac(RADAR_Y_IRADIUS,sintable[player->angle]);\r
-\r
- VWB_DrawSprite(radar_xcenter+x-3,radar_ycenter+y-3,NORTHICONSPR);\r
-\r
-}\r
-\r
-#if 0\r
-/*\r
-===============\r
-=\r
-= DrawBars\r
-=\r
-===============\r
-*/\r
-\r
-void DrawBars (void)\r
-{\r
- int i;\r
- unsigned source,dest,topline;\r
-\r
- for (i=0;i<3;i++)\r
- {\r
- bufferofs = screenloc[i];\r
- VW_Bar (34*8,POWERLINE,40,MAXSHOTPOWER,1);\r
- }\r
- EGAWRITEMODE(1);\r
- asm mov es,[screenseg]\r
-\r
-//\r
-// shot power\r
-//\r
- if (gamestate.shotpower)\r
- {\r
- topline = MAXSHOTPOWER - gamestate.shotpower;\r
-\r
- source = latchpics[SHOTPOWERPIC-FIRSTLATCHPIC]+topline*SIDEBARWIDTH;\r
- dest = (POWERLINE+topline)*SCREENWIDTH+34;\r
-\r
- asm mov si,[source]\r
- asm mov di,[dest]\r
-\r
- asm mov cx,[WORD PTR gamestate.shotpower]\r
-newline:\r
- asm mov al,[es:si]\r
- asm mov [es:di+PAGE1START],al\r
- asm mov [es:di+PAGE2START],al\r
- asm mov [es:di+PAGE3START],al\r
- asm mov al,[es:si+1]\r
- asm mov [es:di+1+PAGE1START],al\r
- asm mov [es:di+1+PAGE2START],al\r
- asm mov [es:di+1+PAGE3START],al\r
- asm mov al,[es:si+2]\r
- asm mov [es:di+2+PAGE1START],al\r
- asm mov [es:di+2+PAGE2START],al\r
- asm mov [es:di+2+PAGE3START],al\r
- asm mov al,[es:si+3]\r
- asm mov [es:di+3+PAGE1START],al\r
- asm mov [es:di+3+PAGE2START],al\r
- asm mov [es:di+3+PAGE3START],al\r
- asm mov al,[es:si+4]\r
- asm mov [es:di+4+PAGE1START],al\r
- asm mov [es:di+4+PAGE2START],al\r
- asm mov [es:di+4+PAGE3START],al\r
-\r
- asm add di,SCREENWIDTH\r
- asm add si,5\r
-\r
- asm loop newline\r
- }\r
-\r
-//\r
-// body\r
-//\r
- if (gamestate.body)\r
- {\r
- source = latchpics[BODYPIC-FIRSTLATCHPIC];\r
- dest = BODYLINE*SCREENWIDTH+34;\r
-\r
- asm mov si,[source]\r
- asm mov di,[dest]\r
-\r
- asm mov cx,[WORD PTR gamestate.body]\r
-newline2:\r
- asm mov al,[es:si]\r
- asm mov [es:di+PAGE1START],al\r
- asm mov [es:di+PAGE2START],al\r
- asm mov [es:di+PAGE3START],al\r
- asm mov al,[es:si+1]\r
- asm mov [es:di+1+PAGE1START],al\r
- asm mov [es:di+1+PAGE2START],al\r
- asm mov [es:di+1+PAGE3START],al\r
- asm mov al,[es:si+2]\r
- asm mov [es:di+2+PAGE1START],al\r
- asm mov [es:di+2+PAGE2START],al\r
- asm mov [es:di+2+PAGE3START],al\r
- asm mov al,[es:si+3]\r
- asm mov [es:di+3+PAGE1START],al\r
- asm mov [es:di+3+PAGE2START],al\r
- asm mov [es:di+3+PAGE3START],al\r
- asm mov al,[es:si+4]\r
- asm mov [es:di+4+PAGE1START],al\r
- asm mov [es:di+4+PAGE2START],al\r
- asm mov [es:di+4+PAGE3START],al\r
-\r
- asm add di,SCREENWIDTH\r
- asm add si,5\r
-\r
- asm loop newline2\r
- }\r
-\r
- if (gamestate.body != MAXBODY)\r
- {\r
- source = latchpics[NOBODYPIC-FIRSTLATCHPIC]+gamestate.body*SIDEBARWIDTH;\r
- dest = (BODYLINE+gamestate.body)*SCREENWIDTH+34;\r
- topline = MAXBODY-gamestate.body;\r
-\r
- asm mov si,[source]\r
- asm mov di,[dest]\r
-\r
- asm mov cx,[WORD PTR topline]\r
-newline3:\r
- asm mov al,[es:si]\r
- asm mov [es:di+PAGE1START],al\r
- asm mov [es:di+PAGE2START],al\r
- asm mov [es:di+PAGE3START],al\r
- asm mov al,[es:si+1]\r
- asm mov [es:di+1+PAGE1START],al\r
- asm mov [es:di+1+PAGE2START],al\r
- asm mov [es:di+1+PAGE3START],al\r
- asm mov al,[es:si+2]\r
- asm mov [es:di+2+PAGE1START],al\r
- asm mov [es:di+2+PAGE2START],al\r
- asm mov [es:di+2+PAGE3START],al\r
- asm mov al,[es:si+3]\r
- asm mov [es:di+3+PAGE1START],al\r
- asm mov [es:di+3+PAGE2START],al\r
- asm mov [es:di+3+PAGE3START],al\r
- asm mov al,[es:si+4]\r
- asm mov [es:di+4+PAGE1START],al\r
- asm mov [es:di+4+PAGE2START],al\r
- asm mov [es:di+4+PAGE3START],al\r
-\r
- asm add di,SCREENWIDTH\r
- asm add si,5\r
-\r
- asm loop newline3\r
- }\r
-\r
- EGAWRITEMODE(0);\r
-}\r
-#endif\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// Check the object and make sure it is a monster. Used in making the sound\r
-// of a monster being shot.\r
-//\r
-/////////////////////////////////////////////////////////////////////////////\r
-\r
-boolean PlayMonsterSound(classtype objclass)\r
-{\r
- switch (objclass)\r
- {\r
- case solidobj:\r
- case realsolidobj:\r
- return false;\r
- default:\r
- return true;\r
- }\r
-}\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- SHOTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-void T_Pshot (objtype *ob);\r
-\r
-\r
-extern statetype s_pshot1;\r
-extern statetype s_pshot2;\r
-\r
-//extern statetype s_bigpshot1;\r
-//extern statetype s_bigpshot2;\r
-\r
-\r
-statetype s_pshot1 = {PSHOT1PIC,8,&T_Pshot,&s_pshot2};\r
-statetype s_pshot2 = {PSHOT2PIC,8,&T_Pshot,&s_pshot1};\r
-\r
-\r
-statetype s_pshot_exp1 = {PSHOT_EXP1PIC,7,NULL,&s_pshot_exp2};\r
-statetype s_pshot_exp2 = {PSHOT_EXP2PIC,7,NULL,&s_pshot_exp3};\r
-statetype s_pshot_exp3 = {PSHOT_EXP3PIC,7,NULL,NULL};\r
-\r
-\r
-//statetype s_shotexplode = {PSHOT2PIC,8,NULL,NULL};\r
-\r
-//statetype s_bigpshot1 = {BIGPSHOT1PIC,8,&T_Pshot,&s_bigpshot2};\r
-//statetype s_bigpshot2 = {BIGPSHOT2PIC,8,&T_Pshot,&s_bigpshot1};\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= SpawnPShot\r
-=\r
-===================\r
-*/\r
-\r
-void SpawnPShot (void)\r
-{\r
- DSpawnNewObjFrac (player->x,player->y,&s_pshot1,PIXRADIUS*7);\r
- new->obclass = pshotobj;\r
- new->speed = SHOTSPEED;\r
- new->angle = player->angle;\r
- new->active = always;\r
-}\r
-\r
-#if 0\r
-void SpawnBigPShot (void)\r
-{\r
- SpawnNewObjFrac (player->x,player->y,&s_bigpshot1,24*PIXRADIUS);\r
- new->obclass = bigpshotobj;\r
- new->speed = SHOTSPEED;\r
- new->angle = player->angle;\r
-}\r
-#endif\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= JimsShotClipMove\r
-=\r
-= Only checks corners, so the object better be less than one tile wide!\r
-=\r
-===================\r
-*/\r
-boolean JimsShotClipMove (objtype *ob, long xmove, long ymove)\r
-{\r
- int xl,yl,xh,yh,tx,ty,nt1,nt2,x,y;\r
- long intersect,basex,basey,pointx,pointy;\r
- unsigned inside,total,tile;\r
- objtype *check;\r
- boolean moveok;\r
-\r
-//\r
-// move player and check to see if any corners are in solid tiles\r
-//\r
-// basex = ob->x;\r
-// basey = ob->y;\r
-\r
-// ob->x += xmove;\r
-// ob->y += ymove;\r
-\r
-// CalcBounds (ob);\r
-\r
- xl = ob->xl>>TILESHIFT;\r
- yl = ob->yl>>TILESHIFT;\r
-\r
- xh = ob->xh>>TILESHIFT;\r
- yh = ob->yh>>TILESHIFT;\r
-\r
- for (y=yl;y<=yh;y++)\r
- for (x=xl;x<=xh;x++)\r
- {\r
- check = actorat[x][y];\r
-\r
- if ((!check) || (check == player) || (!(check->flags & of_shootable)))\r
- continue;\r
-\r
- ob->x -= xmove;\r
- ob->y -= ymove;\r
-\r
- if (check->obclass != solidobj && check->obclass != hbunnyobj)\r
- {\r
- if (PlayMonsterSound(check->obclass))\r
- SD_PlaySound (SHOOTMONSTERSND);\r
- if (ob->obclass == bigpshotobj)\r
- ShootActor (check,BIGSHOTDAMAGE);\r
- else\r
- ShootActor (check,SHOTDAMAGE);\r
- }\r
- else\r
- if (check->obclass == solidobj && (check->flags & of_forcefield))\r
- {\r
- if (PlayMonsterSound(check->obclass))\r
- SD_PlaySound (SHOOTMONSTERSND);\r
- if (ob->obclass == bigpshotobj)\r
- ShootActor (check,BIGSHOTDAMAGE);\r
- else\r
- ShootActor (check,SHOTDAMAGE);\r
- }\r
- ob->state = &s_pshot_exp1;\r
- ob->ticcount = ob->state->tictime;\r
- return(true);\r
- }\r
-\r
- return(false); // move is OK!\r
-\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= T_Pshot\r
-=\r
-===============\r
-*/\r
-#if 0\r
-void T_Pshot (objtype *ob)\r
-{\r
- objtype *check;\r
- long xmove,ymove,speed;\r
-\r
-//\r
-// check current position for monsters having moved into it\r
-//\r
- for (check = player->next; check; check=check->next)\r
- if ((check->flags & of_shootable)\r
- && ob->xl <= check->xh\r
- && ob->xh >= check->xl\r
- && ob->yl <= check->yh\r
- && ob->yh >= check->yl)\r
- {\r
-\r
- if (check->obclass != solidobj)\r
- {\r
- if (PlayMonsterSound(check->obclass))\r
- SD_PlaySound (SHOOTMONSTERSND);\r
- if (ob->obclass == bigpshotobj)\r
- ShootActor (check,BIGSHOTDAMAGE);\r
- else\r
- ShootActor (check,SHOTDAMAGE);\r
- }\r
-\r
- ob->state = &s_pshot_exp1;\r
- ob->ticcount = ob->state->tictime;\r
- return;\r
- }\r
-\r
-\r
-//\r
-// move ahead, possibly hitting a wall\r
-//\r
- speed = ob->speed*tics;\r
-\r
- xmove = FixedByFrac(speed,costable[ob->angle]);\r
- ymove = -FixedByFrac(speed,sintable[ob->angle]);\r
-\r
- if (ShotClipMove(ob,xmove,ymove))\r
- {\r
- ob->state = &s_pshot_exp1;\r
- ob->ticcount = ob->state->tictime;\r
- return;\r
- }\r
-\r
- ob->tilex = ob->x >> TILESHIFT;\r
- ob->tiley = ob->y >> TILESHIFT;\r
-\r
-//\r
-// check final position for monsters hit\r
-//\r
- for (check = player->next; check; check=check->next)\r
- if ((ob->flags & of_shootable)\r
- && ob->xl <= check->xh\r
- && ob->xh >= check->xl\r
- && ob->yl <= check->yh\r
- && ob->yh >= check->yl)\r
- {\r
- ShootActor (check,SHOTDAMAGE);\r
- ob->state = &s_pshot_exp1;\r
- ob->ticcount = ob->state->tictime;\r
- return;\r
- }\r
-}\r
-#endif\r
-\r
-\r
-\r
-void T_Pshot (objtype *ob)\r
-{\r
- objtype *check;\r
- long xmove,ymove,speed;\r
- int xl,yl,xh,yh,tx,ty,nt1,nt2,x,y;\r
- long intersect,basex,basey,pointx,pointy;\r
- unsigned inside,total,tile;\r
- boolean moveok;\r
-\r
-//\r
-// check current position for monsters having moved into it\r
-//\r
- for (check = player->next; check; check=check->next)\r
- if ((check->flags & of_shootable)\r
- && ob->xl <= check->xh\r
- && ob->xh >= check->xl\r
- && ob->yl <= check->yh\r
- && ob->yh >= check->yl)\r
- {\r
-\r
- if (check->obclass != solidobj && check->obclass != hbunnyobj)\r
- {\r
- if (PlayMonsterSound(check->obclass))\r
- SD_PlaySound (SHOOTMONSTERSND);\r
- if (ob->obclass == bigpshotobj)\r
- ShootActor (check,BIGSHOTDAMAGE);\r
- else\r
- ShootActor (check,SHOTDAMAGE);\r
- }\r
-\r
- ob->state = &s_pshot_exp1;\r
- ob->obclass = expobj;\r
- ob->ticcount = ob->state->tictime;\r
- return;\r
- }\r
-\r
-\r
-//\r
-// move ahead, possibly hitting a wall\r
-//\r
- speed = ob->speed*tics;\r
-\r
- xmove = FixedByFrac(speed,costable[ob->angle]);\r
- ymove = -FixedByFrac(speed,sintable[ob->angle]);\r
-\r
- if (ShotClipMove(ob,xmove,ymove))\r
- {\r
- ob->state = &s_pshot_exp1;\r
- ob->obclass = expobj;\r
- ob->ticcount = ob->state->tictime;\r
- return;\r
- }\r
-\r
- ob->tilex = ob->x >> TILESHIFT;\r
- ob->tiley = ob->y >> TILESHIFT;\r
-\r
-//\r
-// check final position for monsters hit\r
-//\r
-\r
- JimsShotClipMove(obj,xmove,ymove);\r
-\r
-}\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- PLAYER ACTIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-===============\r
-=\r
-= BuildShotPower\r
-=\r
-===============\r
-*/\r
-\r
-void BuildShotPower (void)\r
-{\r
- int newlines,topline;\r
- long i;\r
- unsigned source,dest;\r
-\r
- if (gamestate.shotpower == MAXSHOTPOWER)\r
- return;\r
-\r
- newlines = 0;\r
- for (i=lasttimecount-realtics;i<lasttimecount;i++)\r
- newlines += (i&1);\r
-\r
- gamestate.shotpower += newlines;\r
-\r
- if (gamestate.shotpower > MAXSHOTPOWER)\r
- {\r
- newlines -= (gamestate.shotpower - MAXSHOTPOWER);\r
- gamestate.shotpower = MAXSHOTPOWER;\r
- }\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= ClearShotPower\r
-=\r
-===============\r
-*/\r
-\r
-void ClearShotPower (void)\r
-{\r
- unsigned source,dest,topline;\r
-\r
-#if 0\r
- topline = MAXSHOTPOWER - gamestate.shotpower;\r
-\r
- source = latchpics[L_NOSHOT]+topline*SIDEBARWIDTH;\r
- dest = (POWERLINE+topline)*SCREENWIDTH+34;\r
-\r
- asm mov es,[screenseg]\r
- asm mov si,[source]\r
- asm mov di,[dest]\r
-\r
- if (!gamestate.shotpower)\r
- return;\r
-\r
- EGAWRITEMODE(1);\r
-\r
- asm mov cx,[WORD PTR gamestate.shotpower]\r
-newline:\r
- asm mov al,[es:si]\r
- asm mov [es:di+PAGE1START],al\r
- asm mov [es:di+PAGE2START],al\r
- asm mov [es:di+PAGE3START],al\r
- asm mov al,[es:si+1]\r
- asm mov [es:di+1+PAGE1START],al\r
- asm mov [es:di+1+PAGE2START],al\r
- asm mov [es:di+1+PAGE3START],al\r
- asm mov al,[es:si+2]\r
- asm mov [es:di+2+PAGE1START],al\r
- asm mov [es:di+2+PAGE2START],al\r
- asm mov [es:di+2+PAGE3START],al\r
- asm mov al,[es:si+3]\r
- asm mov [es:di+3+PAGE1START],al\r
- asm mov [es:di+3+PAGE2START],al\r
- asm mov [es:di+3+PAGE3START],al\r
- asm mov al,[es:si+4]\r
- asm mov [es:di+4+PAGE1START],al\r
- asm mov [es:di+4+PAGE2START],al\r
- asm mov [es:di+4+PAGE3START],al\r
-\r
- asm add di,SCREENWIDTH\r
- asm add si,5\r
-\r
- asm loop newline\r
-\r
- EGAWRITEMODE(0);\r
-#endif\r
-\r
- gamestate.shotpower = 0;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= Shoot\r
-=\r
-===============\r
-*/\r
-\r
-void Shoot (void)\r
-{\r
- ClearShotPower ();\r
- SD_PlaySound (SHOOTSND);\r
- SpawnPShot ();\r
-}\r
-\r
-//===========================================================================\r
-\r
-#if 0\r
-/*\r
-===============\r
-=\r
-= BigShoot\r
-=\r
-===============\r
-*/\r
-\r
-void BigShoot (void)\r
-{\r
- ClearShotPower ();\r
- SD_PlaySound (BIGSHOOTSND);\r
- SpawnBigPShot ();\r
-}\r
-#endif\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= CastBolt\r
-=\r
-===============\r
-*/\r
-\r
-void CastBolt (void)\r
-{\r
- if (!gamestate.bolts)\r
- {\r
- SD_PlaySound (NOITEMSND);\r
- return;\r
- }\r
-\r
- TakeBolt ();\r
- boltsleft = NUMBOLTS;\r
- bolttimer = BOLTTICS;\r
- Shoot ();\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= ContinueBolt\r
-=\r
-===============\r
-*/\r
-\r
-void ContinueBolt (void)\r
-{\r
- bolttimer-=realtics;\r
- if (bolttimer<0)\r
- {\r
- boltsleft--;\r
- bolttimer = BOLTTICS;\r
- Shoot ();\r
- }\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= CastNuke\r
-=\r
-===============\r
-*/\r
-\r
-void CastNuke (void)\r
-{\r
- extern boolean autofire;\r
-\r
- int angle;\r
-\r
- if (!gamestate.nukes)\r
- {\r
- SD_PlaySound (NOITEMSND);\r
- return;\r
- }\r
-\r
- if (!autofire)\r
- TakeNuke ();\r
- lastnuke = TimeCount;\r
-\r
- for (angle = 0; angle < ANGLES; angle+= ANGLES/16)\r
- {\r
- DSpawnNewObjFrac (player->x,player->y,&s_pshot1,24*PIXRADIUS);\r
- new->obclass = bigpshotobj;\r
- new->speed = SHOTSPEED;\r
- new->angle = angle;\r
- new->active = always;\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= DrinkPotion\r
-=\r
-===============\r
-*/\r
-\r
-void DrinkPotion (void)\r
-{\r
- unsigned source,dest,topline;\r
-\r
- if (!gamestate.potions)\r
- {\r
- SD_PlaySound (NOITEMSND);\r
- return;\r
- }\r
-\r
- DisplaySMsg("Curing", NULL);\r
- TakePotion ();\r
- gamestate.body = MAXBODY;\r
- VW_WaitVBL(30);\r
- status_flag = S_NONE;\r
-\r
-#if 0\r
-//\r
-// draw a full up bar\r
-//\r
- source = latchpics[L_BODYBAR];\r
- dest = BODYLINE*SCREENWIDTH+34;\r
-\r
- asm mov es,[screenseg]\r
- asm mov si,[source]\r
- asm mov di,[dest]\r
-\r
- EGAWRITEMODE(1);\r
-\r
- asm mov cx,MAXBODY\r
-newline:\r
- asm mov al,[es:si]\r
- asm mov [es:di+PAGE1START],al\r
- asm mov [es:di+PAGE2START],al\r
- asm mov [es:di+PAGE3START],al\r
- asm mov al,[es:si+1]\r
- asm mov [es:di+1+PAGE1START],al\r
- asm mov [es:di+1+PAGE2START],al\r
- asm mov [es:di+1+PAGE3START],al\r
- asm mov al,[es:si+2]\r
- asm mov [es:di+2+PAGE1START],al\r
- asm mov [es:di+2+PAGE2START],al\r
- asm mov [es:di+2+PAGE3START],al\r
- asm mov al,[es:si+3]\r
- asm mov [es:di+3+PAGE1START],al\r
- asm mov [es:di+3+PAGE2START],al\r
- asm mov [es:di+3+PAGE3START],al\r
- asm mov al,[es:si+4]\r
- asm mov [es:di+4+PAGE1START],al\r
- asm mov [es:di+4+PAGE2START],al\r
- asm mov [es:di+4+PAGE3START],al\r
- asm add di,SCREENWIDTH\r
- asm add si,5\r
-\r
- asm loop newline\r
-\r
- EGAWRITEMODE(0);\r
-#endif\r
-}\r
-\r
-\r
-\r
-//===========================================================================\r
-\r
-#if 0\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// GetScrollText\r
-//\r
-// parms - scroll -- the number of the scroll to display\r
-// returns - a far pointer to the scroll text\r
-//\r
-////////////////////////////////////////////////////////////////////////////\r
-\r
-char far *GetScrollText (int scroll)\r
-{\r
- boolean found;\r
- int i;\r
- char far *txt;\r
- unsigned ofset;\r
-\r
- CA_CacheGrChunk(SCROLLTEXT);\r
-\r
- found = false;\r
- i = 0;\r
-\r
- txt = (char _seg *)grsegs[SCROLLTEXT];\r
-\r
- while (!found)\r
- {\r
- while (*txt != '\n')\r
- {\r
- if (*txt == '\r')\r
- *txt = 0;\r
- txt++;\r
- }\r
- txt++;\r
- if (i == scroll)\r
- {\r
- found = true;\r
- ofset = FP_OFF(txt);\r
-\r
- while (*txt != '\n')\r
- {\r
- if (*txt == '\r')\r
- *txt = 0;\r
- txt++;\r
- }\r
- }\r
- i++;\r
- }\r
- txt = (char _seg *)grsegs[SCROLLTEXT]+ofset;\r
-\r
- UNMARKGRCHUNK(SCROLLTEXT);\r
- return(txt);\r
-} //End of GetScrollText\r
-\r
-//===========================================================================\r
-\r
-/*\r
-===============\r
-=\r
-= ReadScroll\r
-=\r
-===============\r
-*/\r
-\r
-extern boolean tileneeded[NUMFLOORS];\r
-\r
-void ReadScroll (int scroll)\r
-{\r
- PresenterInfo pi;\r
- int i;\r
- unsigned *skytemp,*gndtemp,blackcolor=0;\r
- char far *scrolltext;\r
-\r
- DisplaySMsg("Reading Scroll", NULL);\r
- bufferofs = displayofs = screenloc[screenpage];\r
-\r
- if (status_flag != S_TIMESTOP)\r
- status_flag = S_NONE;\r
-\r
- FreeUpMemory();\r
-\r
- CA_CacheGrChunk (SCROLLTOPPIC);\r
- CA_CacheGrChunk (SCROLL1PIC);\r
- CA_CacheGrChunk (SCROLLBOTTOMPIC);\r
-\r
- skytemp = skycolor;\r
- gndtemp = groundcolor;\r
- skycolor = groundcolor = &blackcolor;\r
-\r
- VW_Bar(0,0,VIEWWIDTH,VIEWHEIGHT,0);\r
- VW_DrawPic (10,0,SCROLLTOPPIC);\r
- VW_DrawPic (10,32,SCROLL1PIC);\r
- VW_DrawPic (10,88,SCROLLBOTTOMPIC);\r
-\r
- scrolltext = GetScrollText(scroll);\r
-\r
- pi.xl = LEFTEDGE;\r
- pi.yl = PRNY;\r
- pi.xh = RIGHTEDGE;\r
- pi.yh = PRNY+1;\r
- pi.bgcolor = 7;\r
- pi.script[0] = (char far *)scrolltext;\r
- Presenter(&pi);\r
-\r
- skycolor = skytemp;\r
- groundcolor = gndtemp;\r
-\r
- UNMARKGRCHUNK(SCROLL1PIC);\r
- UNMARKGRCHUNK(SCROLLTOPPIC);\r
- UNMARKGRCHUNK(SCROLLBOTTOMPIC);\r
- MM_FreePtr (&grsegs[SCROLL1PIC]);\r
- MM_FreePtr (&grsegs[SCROLLTOPPIC]);\r
- MM_FreePtr (&grsegs[SCROLLBOTTOMPIC]);\r
-\r
- CacheScaleds();\r
-\r
- IN_ClearKeysDown ();\r
- lasttext = -1;\r
- DisplayMsg("Press ENTER or ESC to exit.",NULL);\r
- while ((!Keyboard[sc_Escape]) && (!Keyboard[sc_Enter]));\r
- IN_ClearKeysDown ();\r
-\r
- if (status_flag == S_TIMESTOP)\r
- DisplaySMsg("Time Stopped: ",NULL);\r
-}\r
-\r
-#endif\r
-\r
-\r
-//===============\r
-//\r
-// StopTime()\r
-//\r
-//\r
-//===============\r
-void StopTime()\r
-{\r
- FreezeTime = MAXFREEZETIME;\r
- SD_PlaySound(FREEZETIMESND);\r
- DisplaySMsg("Time Stopped: ",NULL);\r
- status_flag = S_TIMESTOP;\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= TakeDamage\r
-=\r
-===============\r
-*/\r
-\r
-void TakeDamage (int points)\r
-{\r
- unsigned source,dest,topline;\r
-\r
- if (!gamestate.body || (bordertime && bcolor==FLASHCOLOR) || godmode)\r
- return;\r
-\r
- if (points != 1)\r
- points = EasyDoDamage(points);\r
-\r
- if (points >= gamestate.body)\r
- {\r
- points = gamestate.body;\r
- Flags |= FL_DEAD;\r
- }\r
-\r
- bordertime = FLASHTICS<<2;\r
- bcolor = FLASHCOLOR;\r
- VW_ColorBorder (FLASHCOLOR);\r
-\r
- DisplaySMsg("Damaging blows!", NULL);\r
- status_flag = S_NONE;\r
- status_delay = 80;\r
-\r
- if (gamestate.body<MAXBODY/3)\r
- SD_PlaySound (TAKEDMGHURTSND);\r
- else\r
- SD_PlaySound (TAKEDAMAGESND);\r
-\r
- gamestate.body -= points;\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- INTERACTION\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-#if 0\r
-/*\r
-==================\r
-=\r
-= OpenDoor\r
-=\r
-==================\r
-*/\r
-\r
-void OpenDoor (unsigned bx, unsigned by, unsigned doorbase)\r
-{\r
- int x,y;\r
- unsigned far *map;\r
-\r
- x=bx;\r
- y=by;\r
- map = mapsegs[0]+farmapylookup[y]+x;\r
- while (tilemap[x][y]-doorbase<4)\r
- {\r
- tilemap[x][y] = (unsigned)actorat[x][y] = *map = 0;\r
- map--;\r
- x--;\r
- }\r
- x=bx+1;\r
- map = mapsegs[0]+farmapylookup[y]+x;\r
- while (tilemap[x][y]-doorbase<4)\r
- {\r
- tilemap[x][y] = (unsigned)actorat[x][y] = *map = 0;\r
- map++;\r
- x++;\r
- }\r
- x=bx;\r
- y=by-1;\r
- map = mapsegs[0]+farmapylookup[y]+x;\r
- while (tilemap[x][y]-doorbase<4)\r
- {\r
- tilemap[x][y] = (unsigned)actorat[x][y] = *map = 0;\r
- map-=mapwidth;\r
- y--;\r
- }\r
- y=by+1;\r
- map = mapsegs[0]+farmapylookup[y]+x;\r
- while (tilemap[x][y]-doorbase<4)\r
- {\r
- tilemap[x][y] = (unsigned)actorat[x][y] = *map = 0;\r
- map+=mapwidth;\r
- y++;\r
- }\r
-}\r
-#endif\r
-\r
-#if 0\r
-/*\r
-==================\r
-=\r
-= RemoveWalls - similar to OpenDoor(), but on a different plane\r
-=\r
-==================\r
-*/\r
-void RemoveWalls (unsigned bx, unsigned by, unsigned remove_code)\r
-{\r
- int x,y;\r
- unsigned far *map,*p2;\r
-\r
- x=bx;\r
- y=by;\r
- p2 = *(mapsegs[2]+farmapylookup[y]+x);\r
- map = mapsegs[0]+farmapylookup[y]+x;\r
- while (*p2 == remove_code)\r
- {\r
- tilemap[x][y] = (unsigned)actorat[x][y] = *map = 0;\r
- map--;\r
- p2--;\r
- x--;\r
- }\r
- x=bx+1;\r
- p2 = *(mapsegs[2]+farmapylookup[y]+x);\r
- map = mapsegs[0]+farmapylookup[y]+x;\r
- while (*p2 == remove_code)\r
- {\r
- tilemap[x][y] = (unsigned)actorat[x][y] = *map = 0;\r
- map++;\r
- p2++;\r
- x++;\r
- }\r
- x=bx;\r
- y=by-1;\r
- p2 = *(mapsegs[2]+farmapylookup[y]+x);\r
- map = mapsegs[0]+farmapylookup[y]+x;\r
- while (*p2 == remove_code)\r
- {\r
- tilemap[x][y] = (unsigned)actorat[x][y] = *map = 0;\r
- map-=mapwidth;\r
- p2 -= mapwidth;\r
- y--;\r
- }\r
- y=by+1;\r
- p2 = *(mapsegs[2]+farmapylookup[y]+x);\r
- map = mapsegs[0]+farmapylookup[y]+x;\r
- while (*p2 == remove_code)\r
- {\r
- tilemap[x][y] = (unsigned)actorat[x][y] = *map = 0;\r
- map+=mapwidth;\r
- p2 += mapwidth;\r
- y++;\r
- }\r
-}\r
-#endif\r
-\r
-/*\r
-==================\r
-=\r
-= HitSpecialTile\r
-=\r
-= Returns true if the move is blocked\r
-=\r
-==================\r
-*/\r
-\r
-boolean HitSpecialTile (unsigned x, unsigned y, unsigned tile)\r
-{\r
- objtype *check;\r
- short keyspot;\r
- unsigned temp,spot,curmap=gamestate.mapon,newlevel;\r
- char *key_colors[] = {"a RED key",\r
- "a YELLOW key",\r
- "a GREEN key",\r
- "a BLUE key"};\r
-\r
- switch (tile)\r
- {\r
- case 65:\r
- playstate = ex_victorious;\r
- break;\r
-\r
- case 9:\r
- case 15:\r
- case 27:\r
- case 30:\r
- case 40:\r
- case 42:\r
- case 43:\r
- case 45:\r
- case 46:\r
- case 47:\r
- case 49:\r
- case 76:\r
- case 77:\r
-\r
- if (!playstate && !FreezeTime)\r
- {\r
-\r
- // Is this an openable door? (Is "openable" a word?)\r
- //\r
- spot = (*(mapsegs[2]+farmapylookup[y]+x)) >> 8;\r
- if (spot == CANT_OPEN_CODE) // CAN'T EVER OPEN (it's just for looks)\r
- {\r
- CenterWindow(30,4);\r
- US_CPrint("\nThis door is permanently blocked");\r
- VW_UpdateScreen();\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
- return;\r
- }\r
-\r
- // make sure player has key to get into door\r
- //\r
-\r
- if (TILE_FLAGS(tile) & tf_EMBEDDED_KEY_COLOR)\r
- keyspot = GATE_KEY_COLOR(tile);\r
- else\r
- keyspot = (*(mapsegs[2]+farmapylookup[y+1]+x)) >> 8;\r
-\r
- if (keyspot--)\r
- if (!gamestate.keys[keyspot])\r
- {\r
- SD_PlaySound(HIT_GATESND);\r
- CenterWindow(20,5);\r
- US_CPrint("\nYou need\n");\r
- US_CPrint(key_colors[keyspot]);\r
- VW_UpdateScreen();\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
- return;\r
- }\r
-\r
- //\r
- // deal with this gate (warp? simply open? whatever...)\r
- //\r
- switch (spot)\r
- {\r
- case NEXT_LEVEL_CODE: // WARP TO NEXT LEVEL\r
- newlevel = gamestate.mapon+1;\r
- playstate = ex_warped;\r
- break;\r
-\r
- case REMOVE_DOOR_CODE: // REMOVE DOOR\r
- (unsigned)actorat[x][y] = tilemap[x][y] = *(mapsegs[0]+farmapylookup[y]+x) = 0;\r
- *(mapsegs[2]+farmapylookup[y+1]+x) = 0; // key no longer needed\r
- if (keyspot>=0)\r
- TakeKey(keyspot);\r
- break;\r
-\r
- default: // WARP TO A LEVEL\r
- newlevel = spot;\r
- playstate = ex_warped;\r
- break;\r
- }\r
-\r
- if (playstate == ex_warped)\r
- {\r
- SD_PlaySound(HIT_GATESND);\r
-// levelinfo *li=&gamestate.levels[curmap];\r
-\r
-// OldAngle = FaceDoor(x,y);\r
-\r
- if (!VerifyGateExit())\r
- {\r
- IN_ClearKeysDown ();\r
- playstate = ex_stillplaying;\r
- break;\r
- }\r
-\r
-// FaceAngle(OldAngle);\r
-\r
- if (keyspot>=0)\r
- TakeKey(keyspot);\r
- *(mapsegs[2]+farmapylookup[y+1]+x) = 0; // key no longer needed\r
-\r
- gamestate.mapon = newlevel;\r
- SD_PlaySound(WARPUPSND);\r
- IN_ClearKeysDown ();\r
-\r
-// li->x = player->tilex;\r
-// li->y = player->tiley;\r
-// li->angle = player->angle+180;\r
-// if (li->angle > 360)\r
-// li->angle -= 360;\r
- }\r
- }\r
- break;\r
- }\r
-\r
- return true;\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// VerifyGateExit()\r
-//-------------------------------------------------------------------------\r
-boolean VerifyGateExit()\r
-{\r
- char choices[] = {sc_Escape,sc_Y,sc_N,0},ch;\r
-\r
- ch=DisplayMsg("Pass this way? Y/N",choices);\r
- DrawText(true);\r
-\r
- return(ch == sc_Y);\r
-}\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= TouchActor\r
-=\r
-= Returns true if the move is blocked\r
-=\r
-==================\r
-*/\r
-\r
-boolean TouchActor (objtype *ob, objtype *check)\r
-{\r
- if (ob->xh < check->xl || ob->xl > check->xh ||\r
- ob->yh < check->yl || ob->yl > check->yh)\r
- return false; // not quite touching\r
-\r
- switch (check->obclass)\r
- {\r
- case bonusobj:\r
- switch (check->temp1)\r
- {\r
- case B_BOLT: GiveBolt (); break;\r
-\r
- case B_NUKE: GiveNuke (); break;\r
-\r
- case B_POTION: GivePotion (); break;\r
-\r
-// case B_RKEY2: GiveKey(B_RKEY-B_RKEY); break;\r
-\r
- case B_RKEY:\r
- case B_YKEY:\r
- case B_GKEY:\r
- case B_BKEY: GiveKey (check->temp1-B_RKEY); break;\r
-\r
-#if 0\r
- case B_SCROLL1:\r
- case B_SCROLL2:\r
- case B_SCROLL3:\r
- case B_SCROLL4:\r
- case B_SCROLL5:\r
- case B_SCROLL6:\r
- case B_SCROLL7:\r
- case B_SCROLL8: GiveScroll (check->temp1-B_SCROLL1,true); break;\r
-#endif\r
-\r
- case B_CHEST: GiveChest (); break;\r
-\r
- case B_RGEM:\r
- case B_YGEM:\r
- case B_GGEM:\r
- case B_BGEM:\r
- case B_PGEM:\r
- SD_PlaySound(GETGEMSND);\r
- gamestate.gems[check->temp1-B_RGEM] = GEM_DELAY_TIME;\r
- redraw_gems = true;\r
- break;\r
-\r
- default:\r
- Quit("TouchActor(): INVALID BONUS");\r
- break;\r
- }\r
-\r
- (unsigned)actorat[check->tilex][check->tiley] = 0;\r
- RemoveObj (check);\r
-\r
- return false;\r
-\r
- case freezeobj:\r
- StopTime();\r
- (unsigned)actorat[check->tilex][check->tiley] = 0;\r
- RemoveObj(check);\r
- return(false);\r
-\r
- case cloudobj:\r
- TakeDamage(2);\r
- return false;\r
- }\r
-\r
- return true;\r
-}\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= CalcBounds\r
-=\r
-==================\r
-*/\r
-\r
-void CalcBounds (objtype *ob)\r
-{\r
-//\r
-// calculate hit rect\r
-//\r
- ob->xl = ob->x - ob->size;\r
- ob->xh = ob->x + ob->size;\r
- ob->yl = ob->y - ob->size;\r
- ob->yh = ob->y + ob->size;\r
-}\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= LocationInActor\r
-=\r
-===================\r
-*/\r
-\r
-boolean LocationInActor (objtype *ob)\r
-{\r
- int x,y,xmin,ymin,xmax,ymax;\r
- objtype *check;\r
-\r
- CalcBounds (ob);\r
-\r
- xmin = (ob->x >> TILESHIFT)-2;\r
- ymin = (ob->y >> TILESHIFT)-2;\r
- xmax = xmin+5;\r
- ymax = ymin+5;\r
-\r
- for (x=xmin;x<xmax;x++)\r
- for (y=ymin;y<ymax;y++)\r
- {\r
- check = actorat[x][y];\r
- if (check>(objtype *)LASTTILE\r
- && (check->flags & of_shootable)\r
- && (check->obclass != bonusobj)\r
- && (check->obclass != freezeobj)\r
- && (check->obclass != solidobj)\r
- && ob->xl-SIZE_TEST <= check->xh\r
- && ob->xh+SIZE_TEST >= check->xl\r
- && ob->yl-SIZE_TEST <= check->yh\r
- && ob->yh+SIZE_TEST >= check->yl)\r
- return true;\r
- }\r
-\r
- return false;\r
-}\r
-\r
-/*\r
-===================\r
-=\r
-= ClipXMove\r
-=\r
-= Only checks corners, so the object better be less than one tile wide!\r
-=\r
-===================\r
-*/\r
-void ClipXMove (objtype *ob, long xmove)\r
-{\r
- int xl,yl,xh,yh,tx,ty,nt1,nt2,x,y;\r
- long intersect,basex,basey,pointx,pointy;\r
- unsigned inside,total,tile;\r
- objtype *check;\r
- boolean moveok;\r
- boolean invisible_present = false;\r
-\r
-//\r
-// move player and check to see if any corners are in solid tiles\r
-//\r
- basex = ob->x;\r
- basey = ob->y;\r
-\r
- ob->x += xmove;\r
-\r
- CalcBounds (ob);\r
-\r
- xl = ob->xl>>TILESHIFT;\r
- yl = ob->yl>>TILESHIFT;\r
-\r
- xh = ob->xh>>TILESHIFT;\r
- yh = ob->yh>>TILESHIFT;\r
-\r
- for (y=yl;y<=yh;y++)\r
- for (x=xl;x<=xh;x++)\r
- {\r
- check = actorat[x][y];\r
-\r
- if (!check)\r
- continue; // blank floor, walk ok\r
-\r
- if ((unsigned)check <= LASTTILE)\r
- {\r
- if (TILE_FLAGS((unsigned)check) & tf_SPECIAL)\r
- {\r
- HitSpecialTile(x,y,(unsigned)check-SPECTILESTART);\r
- goto blockmove;\r
- }\r
-\r
- if (TILE_FLAGS((unsigned)check) & tf_INVISIBLE_WALL)\r
- {\r
- invisible_present = true;\r
- goto blockmove;\r
- }\r
-\r
-\r
- if (TILE_FLAGS((unsigned)check) & tf_SOLID)\r
- {\r
- goto blockmove; // solid wall\r
- }\r
- }\r
-\r
- TouchActor(ob,check); // pick up items\r
- }\r
-\r
-//\r
-// check nearby actors\r
-//\r
- if (LocationInActor(ob))\r
- {\r
- ob->x -= xmove;\r
- if (LocationInActor(ob))\r
- {\r
- ob->x += xmove;\r
- if (LocationInActor(ob))\r
- ob->x -= xmove;\r
- }\r
- }\r
- return; // move is OK!\r
-\r
-\r
-blockmove:\r
-\r
-// if (!SD_SoundPlaying())\r
-// SD_PlaySound (HITWALLSND);\r
-\r
- moveok = false;\r
-\r
- do\r
- {\r
- xmove /= 2;\r
- if (moveok)\r
- {\r
- ob->x += xmove;\r
- }\r
- else\r
- {\r
- ob->x -= xmove;\r
- }\r
- CalcBounds (ob);\r
- xl = ob->xl>>TILESHIFT;\r
- yl = ob->yl>>TILESHIFT;\r
- xh = ob->xh>>TILESHIFT;\r
- yh = ob->yh>>TILESHIFT;\r
- if (tilemap[xl][yl] || tilemap[xh][yl]\r
- || tilemap[xh][yh] || tilemap[xl][yh] )\r
- {\r
- moveok = false;\r
- if (xmove>=-2048 && xmove <=2048)\r
- {\r
- ob->x = basex;\r
- ob->y = basey;\r
- return;\r
- }\r
- }\r
- else\r
- if (invisible_present)\r
- {\r
- moveok = false;\r
- if (xmove>=-2048 && xmove <=2048)\r
- {\r
- ob->x = basex;\r
- ob->y = basey;\r
- return;\r
- }\r
- }\r
- else\r
- if (xmove>=-2048 && xmove <=2048)\r
- return;\r
- moveok = true;\r
- } while (1);\r
-}\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= ClipYMove\r
-=\r
-= Only checks corners, so the object better be less than one tile wide!\r
-=\r
-===================\r
-*/\r
-void ClipYMove (objtype *ob, long ymove)\r
-{\r
- int xl,yl,xh,yh,tx,ty,nt1,nt2,x,y;\r
- long intersect,basex,basey,pointx,pointy;\r
- unsigned inside,total,tile;\r
- objtype *check;\r
- boolean moveok;\r
- boolean invisible_present = false;\r
-\r
-//\r
-// move player and check to see if any corners are in solid tiles\r
-//\r
- basex = ob->x;\r
- basey = ob->y;\r
-\r
- ob->y += ymove;\r
-\r
- CalcBounds (ob);\r
-\r
- xl = ob->xl>>TILESHIFT;\r
- yl = ob->yl>>TILESHIFT;\r
-\r
- xh = ob->xh>>TILESHIFT;\r
- yh = ob->yh>>TILESHIFT;\r
-\r
- for (y=yl;y<=yh;y++)\r
- for (x=xl;x<=xh;x++)\r
- {\r
- check = actorat[x][y];\r
- if (!check)\r
- continue; // blank floor, walk ok\r
-\r
- if ((unsigned)check <= LASTTILE)\r
- {\r
- if (TILE_FLAGS((unsigned)check) & tf_SPECIAL) // <=LASTSPECIALTILE)\r
- {\r
- HitSpecialTile (x,y,(unsigned)check-SPECTILESTART);\r
- goto blockmove;\r
- }\r
-\r
- if (TILE_FLAGS((unsigned)check) & tf_INVISIBLE_WALL)\r
- {\r
- invisible_present = true;\r
- goto blockmove;\r
- }\r
-\r
-\r
- if (TILE_FLAGS((unsigned)check) & tf_SOLID) // LASTWALLTILE)\r
- {\r
- goto blockmove; // solid wall\r
- }\r
- }\r
-\r
- TouchActor(ob,check); // pick up items\r
- }\r
-\r
-//\r
-// check nearby actors\r
-//\r
- if (LocationInActor(ob))\r
- {\r
- if (LocationInActor(ob))\r
- {\r
- ob->y -= ymove;\r
- }\r
- }\r
- return; // move is OK!\r
-\r
-\r
-blockmove:\r
-\r
-// if (!SD_SoundPlaying())\r
-// SD_PlaySound (HITWALLSND);\r
-\r
- moveok = false;\r
-\r
- do\r
- {\r
- ymove /= 2;\r
- if (moveok)\r
- {\r
- ob->y += ymove;\r
- }\r
- else\r
- {\r
- ob->y -= ymove;\r
- }\r
- CalcBounds (ob);\r
- xl = ob->xl>>TILESHIFT;\r
- yl = ob->yl>>TILESHIFT;\r
- xh = ob->xh>>TILESHIFT;\r
- yh = ob->yh>>TILESHIFT;\r
- if (tilemap[xl][yl] || tilemap[xh][yl]\r
- || tilemap[xh][yh] || tilemap[xl][yh] )\r
- {\r
- moveok = false;\r
- if (ymove>=-2048 && ymove <=2048)\r
- {\r
- ob->x = basex;\r
- ob->y = basey;\r
- return;\r
- }\r
- }\r
- else\r
- if (invisible_present)\r
- {\r
- moveok = false;\r
- if (ymove>=-2048 && ymove <=2048)\r
- {\r
- ob->x = basex;\r
- ob->y = basey;\r
- return;\r
- }\r
- }\r
- else\r
- if (ymove>=-2048 && ymove <=2048)\r
- return;\r
- moveok = true;\r
- } while (1);\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= ShotClipMove\r
-=\r
-= Only checks corners, so the object better be less than one tile wide!\r
-=\r
-===================\r
-*/\r
-\r
-boolean ShotClipMove (objtype *ob, long xmove, long ymove)\r
-{\r
- int xl,yl,xh,yh,tx,ty,nt1,nt2,x,y;\r
- long intersect,basex,basey,pointx,pointy;\r
- unsigned inside,total,spot,tile;\r
- objtype *check;\r
- boolean moveok;\r
-\r
-//\r
-// move shot and check to see if any corners are in solid tiles\r
-//\r
- basex = ob->x;\r
- basey = ob->y;\r
-\r
- ob->x += xmove;\r
- ob->y += ymove;\r
-\r
- CalcBounds (ob);\r
-\r
- xl = ob->xl>>TILESHIFT;\r
- yl = ob->yl>>TILESHIFT;\r
-\r
- xh = ob->xh>>TILESHIFT;\r
- yh = ob->yh>>TILESHIFT;\r
-\r
- for (y=yl;y<=yh;y++)\r
- for (x=xl;x<=xh;x++)\r
- {\r
- spot = (*(mapsegs[2]+farmapylookup[y]+x)) >> 8;\r
- if (spot == EXP_WALL_CODE)\r
- switch (ob->obclass)\r
- {\r
- case pshotobj:\r
- case bigpshotobj:\r
- ExplodeWall (x,y);\r
- goto blockmove;\r
- break;\r
- }\r
-\r
- tile = *(mapsegs[0]+farmapylookup[y]+x);\r
- if (TILE_FLAGS(tile) & tf_SOLID)\r
- goto blockmove;\r
- }\r
- return false; // move is OK!\r
-\r
-\r
-blockmove:\r
-\r
- SD_PlaySound (SHOOTWALLSND);\r
-\r
- moveok = false;\r
-\r
- do\r
- {\r
- xmove /= 2;\r
- ymove /= 2;\r
- if (moveok)\r
- {\r
- ob->x += xmove;\r
- ob->y += ymove;\r
- }\r
- else\r
- {\r
- ob->x -= xmove;\r
- ob->y -= ymove;\r
- }\r
- CalcBounds (ob);\r
- xl = ob->xl>>TILESHIFT;\r
- yl = ob->yl>>TILESHIFT;\r
- xh = ob->xh>>TILESHIFT;\r
- yh = ob->yh>>TILESHIFT;\r
- if (tilemap[xl][yl] || tilemap[xh][yl]\r
- || tilemap[xh][yh] || tilemap[xl][yh] )\r
- {\r
- moveok = false;\r
- if (xmove>=-2048 && xmove <=2048 && ymove>=-2048 && ymove <=2048)\r
- {\r
- ob->x = basex;\r
- ob->y = basey;\r
- return true;\r
- }\r
- }\r
- else\r
- {\r
- if (xmove>=-2048 && xmove <=2048 && ymove>=-2048 && ymove <=2048)\r
- return true;\r
- moveok = true;\r
- }\r
- } while (1);\r
-}\r
-\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- PLAYER CONTROL\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-\r
-void T_Player (objtype *ob);\r
-\r
-statetype s_player = {0,0,&T_Player,&s_player};\r
-\r
-/*\r
-===============\r
-=\r
-= SpawnPlayer\r
-=\r
-===============\r
-*/\r
-\r
-void SpawnPlayer (int tilex, int tiley, int dir)\r
-{\r
-#if 0\r
- levelinfo *li=&gamestate.levels[gamestate.mapon];\r
-\r
- if (li->x != -1)\r
- {\r
- tilex = li->x;\r
- tiley = li->y;\r
- player->angle = li->angle;\r
- }\r
- else\r
- player->angle = (1-dir)*90;\r
-#endif\r
-\r
- player->obclass = playerobj;\r
- player->active = always;\r
- player->tilex = tilex;\r
- player->tiley = tiley;\r
- player->x = ((long)tilex<<TILESHIFT)+TILEGLOBAL/2;\r
- player->y = ((long)tiley<<TILESHIFT)+TILEGLOBAL/2;\r
- player->state = &s_player;\r
- player->size = MINDIST;\r
- CalcBounds(player);\r
- player->angle = (1-dir)*90;\r
- if (player->angle<0)\r
- player->angle += ANGLES;\r
-}\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= Thrust\r
-=\r
-===================\r
-*/\r
-\r
-void Thrust (int angle, unsigned speed)\r
-{\r
- long xmove,ymove;\r
-\r
- if (lasttimecount>>5 != ((lasttimecount-tics)>>5) )\r
- {\r
- //\r
- // walk sound\r
- //\r
- if (lasttimecount&32)\r
- SD_PlaySound (WALK1SND);\r
- else\r
- SD_PlaySound (WALK2SND);\r
- }\r
-\r
- xmove = FixedByFrac(speed,costable[angle]);\r
- ymove = -FixedByFrac(speed,sintable[angle]);\r
-\r
- ClipXMove(player,xmove);\r
- ClipYMove(player,ymove);\r
- player->tilex = player->x >> TILESHIFT;\r
- player->tiley = player->y >> TILESHIFT;\r
-}\r
-\r
-\r
-\r
-/*\r
-=======================\r
-=\r
-= ControlMovement\r
-=\r
-=======================\r
-*/\r
-\r
-void ControlMovement (objtype *ob)\r
-{\r
- int angle;\r
- long speed;\r
-\r
-\r
- if (control.button1)\r
- {\r
- //\r
- // strafing\r
- //\r
- //\r
- // side to side move\r
- //\r
- if (!mousexmove)\r
- speed = 0;\r
- else if (mousexmove<0)\r
- speed = -(long)mousexmove*300;\r
- else\r
- speed = -(long)mousexmove*300;\r
-\r
- if (control.xaxis == -1)\r
- {\r
- speed += PLAYERSPEED*tics;\r
- }\r
- else if (control.xaxis == 1)\r
- {\r
- speed -= PLAYERSPEED*tics;\r
- }\r
-\r
- if (speed > 0)\r
- {\r
- if (speed >= TILEGLOBAL)\r
- speed = TILEGLOBAL-1;\r
- angle = ob->angle + ANGLES/4;\r
- if (angle >= ANGLES)\r
- angle -= ANGLES;\r
- Thrust (angle,speed); // move to left\r
- }\r
- else if (speed < 0)\r
- {\r
- if (speed <= -TILEGLOBAL)\r
- speed = -TILEGLOBAL+1;\r
- angle = ob->angle - ANGLES/4;\r
- if (angle < 0)\r
- angle += ANGLES;\r
- Thrust (angle,-speed); // move to right\r
- }\r
- }\r
- else\r
- {\r
- //\r
- // not strafing\r
- //\r
-\r
- //\r
- // turning\r
- //\r
- if (control.xaxis == 1)\r
- {\r
- ob->angle -= tics;\r
- if (running) // fast turn\r
- ob->angle -= (tics<<1);\r
- }\r
- else if (control.xaxis == -1)\r
- {\r
- ob->angle+= tics;\r
- if (running) // fast turn\r
- ob->angle += (tics<<1);\r
- }\r
-\r
- ob->angle -= (mousexmove/10);\r
-\r
- if (ob->angle >= ANGLES)\r
- ob->angle -= ANGLES;\r
- if (ob->angle < 0)\r
- ob->angle += ANGLES;\r
-\r
- }\r
-\r
- //\r
- // forward/backwards move\r
- //\r
- if (!mouseymove)\r
- speed = 0;\r
- else if (mouseymove<0)\r
- speed = -(long)mouseymove*500;\r
- else\r
- speed = -(long)mouseymove*200;\r
-\r
- if (control.yaxis == -1)\r
- {\r
- speed += PLAYERSPEED*tics;\r
- }\r
- else if (control.yaxis == 1)\r
- {\r
- speed -= PLAYERSPEED*tics;\r
- }\r
-\r
- if (speed > 0)\r
- {\r
- if (speed >= TILEGLOBAL)\r
- speed = TILEGLOBAL-1;\r
- Thrust (ob->angle,speed); // move forwards\r
- }\r
- else if (speed < 0)\r
- {\r
- if (speed <= -TILEGLOBAL)\r
- speed = -TILEGLOBAL+1;\r
- angle = ob->angle + ANGLES/2;\r
- if (angle >= ANGLES)\r
- angle -= ANGLES;\r
- Thrust (angle,-speed); // move backwards\r
- }\r
-}\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= T_Player\r
-=\r
-===============\r
-*/\r
-\r
-void T_Player (objtype *ob)\r
-{\r
- extern boolean autofire;\r
-\r
- int angle,speed,scroll,loop;\r
- unsigned text,tilex,tiley;\r
- long lspeed;\r
-\r
-// boolean radar_moved=false;\r
-\r
-\r
- ControlMovement (ob);\r
-\r
-\r
- //\r
- // firing\r
- //\r
- if (boltsleft)\r
- {\r
- handheight+=(realtics<<2);\r
- if (handheight>MAXHANDHEIGHT)\r
- handheight = MAXHANDHEIGHT;\r
-\r
- ContinueBolt ();\r
- lasthand = lasttimecount;\r
- }\r
- else\r
- {\r
- if (control.button0)\r
- {\r
- handheight+=(realtics<<2);\r
- if (handheight>MAXHANDHEIGHT)\r
- handheight = MAXHANDHEIGHT;\r
- lasthand = lasttimecount;\r
-\r
- if (!button0down)\r
- Shoot();\r
-\r
- if (!autofire)\r
- button0down=true;\r
- }\r
- else\r
- {\r
- if (lasttimecount > lasthand+HANDPAUSE)\r
- {\r
- handheight-=(realtics<<1);\r
- if (handheight<0)\r
- handheight = 0;\r
- }\r
-\r
- button0down = false;\r
- }\r
-}\r
-\r
-#if 0\r
- if (control.button0)\r
- {\r
- handheight+=(realtics<<2);\r
- if (handheight>MAXHANDHEIGHT)\r
- handheight = MAXHANDHEIGHT;\r
-\r
- if ((unsigned)TimeCount/FIRETIME != lastfiretime)\r
- BuildShotPower ();\r
- lasthand = lasttimecount;\r
- }\r
- else\r
- {\r
- if (lasttimecount > lasthand+HANDPAUSE)\r
- {\r
- handheight-=(realtics<<1);\r
- if (handheight<0)\r
- handheight = 0;\r
- }\r
-\r
- if (gamestate.shotpower)\r
- {\r
- lastfiretime = (unsigned)TimeCount/FIRETIME;\r
- Shoot ();\r
- }\r
- }\r
- }\r
-#endif\r
-\r
- //\r
- // special actions\r
- //\r
-\r
- if ((Keyboard[sc_Space] || Keyboard[sc_C]) && gamestate.body != MAXBODY)\r
- DrinkPotion ();\r
-\r
- if (Keyboard[sc_Z] && !boltsleft)\r
- CastBolt ();\r
-\r
- if ( (Keyboard[sc_Enter] || Keyboard[sc_X]) && ((TimeCount-lastnuke > NUKETIME) || (autofire)))\r
- CastNuke ();\r
-\r
-#if 0\r
- scroll = LastScan-2;\r
- if ( scroll>=0 && scroll<NUMSCROLLS && gamestate.scrolls[scroll])\r
- ReadScroll (scroll);\r
-#endif\r
-\r
- DrawText(false);\r
- DrawHealth();\r
- if (FreezeTime)\r
- DrawFreezeTime();\r
- DrawRadar();\r
- EGAWRITEMODE(0);\r
- DrawNSEWIcons();\r
-\r
- if (redraw_gems)\r
- DrawGems();\r
-\r
-#if 0\r
-// gems fade out over time...\r
-//\r
- for (loop=0; loop<5; loop++)\r
- if (gamestate.gems[loop])\r
- {\r
- gamestate.gems[loop] -= realtics;\r
- if (gamestate.gems[loop] < 0)\r
- {\r
- gamestate.gems[loop] = 0;\r
- redraw_gems = true;\r
- }\r
- }\r
-#endif\r
-}\r
-\r
-#if 0\r
-//------------------------------------------------------------------------\r
-// FaceDir() -\r
-//\r
-// PARAMS : x,y - pixle coords to bring in to view.\r
-//\r
-// NOTE : Params CAN NOT be shifted fracs!\r
-//------------------------------------------------------------------------\r
-void FaceDir(short x,short y,boolean StopTime)\r
-{\r
- short diff;\r
-\r
- RotateAngle = CalcAngle(x-(player->x>>16l),(player->y>>16l)-y);\r
- FreezeTime = StopTime;\r
-\r
- diff = player->angle - RotateAngle;\r
-\r
- if (((diff>0) && (diff<180)) || ((diff<0) && (diff>-180)))\r
- RotateSpeed = -ROTATE_SPEED;\r
- else\r
- RotateSpeed = ROTATE_SPEED;\r
-}\r
-#endif\r
-\r
-#if 0\r
-//------------------------------------------------------------------------\r
-// CalcAngle() -\r
-//\r
-// DESC: Calculates the angle from a given dy & dx\r
-//------------------------------------------------------------------------\r
-short CalcAngle(short dx,short dy)\r
-{\r
- #define degtorad (180/PI)\r
- float angle;\r
- short diff;\r
- float rad_angle;\r
-\r
- if (dx)\r
- {\r
- angle = atan((float)dy/dx)* degtorad;\r
- if (angle<=0)\r
- angle += 180;\r
- if (dy>0)\r
- angle += 180;\r
- }\r
- else\r
- {\r
- // 90 Deg shift\r
-\r
- if (dy < 0)\r
- angle = 0 + 90; // Above player (NORTH)\r
- else\r
- angle = 180 + 90; // Below player (SOUTH)\r
- }\r
-\r
- if (!angle) // HACK\r
- angle++;\r
-\r
- return((short)abs(angle));\r
-}\r
-\r
-#endif\r
-\r
-#if 0\r
-\r
-//-------------------------------------------------------------------------\r
-// RotateView() -\r
-//\r
-// DESC : Rotates view (current view of game) to a dest angle.\r
-//-------------------------------------------------------------------------\r
-void RotateView()\r
-{\r
- short LastPos;\r
-\r
- // Store old angle position then change angle...\r
- //\r
-\r
- LastPos = player->angle;\r
-\r
- player->angle += RotateSpeed;\r
-\r
- // Check to see if we cranked past out dest angle...\r
- //\r
-\r
-\r
- if ((player->angle>ANGLES) || (!player->angle))\r
- player->angle = 1;\r
- else\r
- if (player->angle<1)\r
- player->angle = ANGLES;\r
-\r
- // Check to see if we over shot our dest angle...\r
- //\r
-\r
- if (((LastPos < RotateAngle) && (player->angle > RotateAngle) && (RotateSpeed > 0)) ||\r
- ((LastPos > RotateAngle) && (player->angle < RotateAngle) && (RotateSpeed < 0)))\r
- player->angle = RotateAngle;\r
-\r
- // Check for ending force turn....\r
- //\r
-\r
- if (player->angle == RotateAngle)\r
- RotateAngle = -1;\r
-\r
-}\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-// InitRotate()\r
-//--------------------------------------------------------------------------\r
-void InitRotate(short DestAngle)\r
-{\r
- if (player->angle != DestAngle)\r
- {\r
- RotateAngle = DestAngle;\r
-\r
- if (player->angle > DestAngle)\r
- RotateSpeed = -ROTATE_SPEED;\r
- else\r
- RotateSpeed = ROTATE_SPEED;\r
-\r
- if (abs(player->angle - RotateAngle) > 180)\r
- RotateSpeed =- RotateSpeed;\r
- }\r
-}\r
-\r
-\r
-\r
-//------------------------------------------------------------------------\r
-// FaceAngle() -\r
-//\r
-// PARAMS : DestAngle - Destination angle to turn to\r
-//------------------------------------------------------------------------\r
-void FaceAngle(short DestAngle)\r
-{\r
- signed long dx,dy,radius,psin,pcos,newx,newy;\r
- int give;\r
- short objnum,LastPos;\r
- signed long ox,oy,xl,xh,yl,yh,px,py,norm_dx,norm_dy;\r
- short o_radius;\r
- void (*think)();\r
-\r
-\r
- // Calculate the direction we want to turn to...\r
- //\r
-\r
- InitRotate(DestAngle);\r
-\r
- RedrawStatusWindow();\r
-\r
- while (RotateAngle != -1)\r
- {\r
-\r
- RotateView();\r
-\r
-// PollControls();\r
-\r
- objnum=0;\r
-\r
- for (obj = player;obj;obj = obj->next)\r
- {\r
- if (obj->active >= yes)\r
- {\r
-\r
- // keep a list of objects around the player for radar updates\r
- //\r
- if (obj == player)\r
- {\r
- px = player->x;\r
- py = player->y;\r
- psin = sintable[player->angle];\r
- pcos = costable[player->angle];\r
- xl = px-((long)RADAR_WIDTH<<TILESHIFT)/2;\r
- xh = px+((long)RADAR_WIDTH<<TILESHIFT)/2-1;\r
- yl = py-((long)RADAR_HEIGHT<<TILESHIFT)/2;\r
- yh = py+((long)RADAR_HEIGHT<<TILESHIFT)/2;\r
- }\r
-\r
- if (objnum > MAX_RADAR_BLIPS-2)\r
- objnum = MAX_RADAR_BLIPS-2;\r
-\r
- ox = obj->x;\r
- oy = obj->y;\r
-\r
-\r
- if ((ox >= xl) && (ox <= xh) && (oy >= yl) && (oy <= yh))\r
- {\r
- norm_dx = (dx = px-ox)>>TILESHIFT;\r
- norm_dy = (dy = oy-py)>>TILESHIFT;\r
-\r
- o_radius = IntSqrt((norm_dx * norm_dx) + (norm_dy * norm_dy));\r
-\r
- if (o_radius < RADAR_RADIUS)\r
- {\r
- newx = FixedByFrac(dy,pcos)-FixedByFrac(dx,psin);\r
- newy = FixedByFrac(dy,psin)+FixedByFrac(dx,pcos);\r
-\r
- RadarXY[objnum][0]=newx>>TILESHIFT;\r
- RadarXY[objnum][1]=newy>>TILESHIFT;\r
-\r
- // Define color to use for this object...\r
- //\r
-\r
- switch (obj->obclass)\r
- {\r
- case playerobj:\r
- RadarXY[objnum++][2]=15;\r
- break;\r
-\r
- // RED GEM\r
- //\r
- case godessobj:\r
- if (gamestate.gems[B_RGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=12;\r
- break;\r
-\r
- // GREEN GEM\r
- //\r
- case fatdemonobj:\r
- if (gamestate.gems[B_GGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=10;\r
- break;\r
-\r
- // YELLOW GEM\r
- //\r
- case skeletonobj:\r
- if (gamestate.gems[B_YGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=14;\r
- break;\r
-\r
- // BLUE GEM\r
- //\r
- case mageobj:\r
- case wetobj:\r
- if (gamestate.gems[B_BGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=9;\r
- break;\r
-\r
- // PURPLE GEM\r
- //\r
- case zombieobj:\r
- if (gamestate.gems[B_PGEM-B_RGEM])\r
- if (obj->active == always)\r
- RadarXY[objnum++][2]=13;\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- RadarXY[objnum][2]=-1; // Signals end of RadarXY list...\r
-\r
-// refresh all\r
-//\r
-\r
- ThreeDRefresh();\r
- DrawRadar();\r
- EGAWRITEMODE(0);\r
- DrawNSEWIcons();\r
-\r
-// CheckKeys();\r
- }\r
-}\r
-\r
-\r
-//-------------------------------------------------------------------------\r
-// FaceDoor() - Turns the player to face a door (a tile) at a given TILE x & y\r
-//\r
-// RETURNS : Returns the orginal angle of the player.\r
-//------------------------------------------------------------------------\r
-short FaceDoor(short x, short y)\r
-{\r
- short p_x,p_y,angle,old_angle;\r
-\r
- old_angle = player->angle;\r
-\r
- p_x = player->x>>16l;\r
- p_y = player->y>>16l;\r
-\r
- if (p_x != x)\r
- {\r
- if (p_x > x)\r
- angle = 180; // Face Left\r
- else\r
- angle = 1; // Face Right\r
- }\r
-\r
- if (p_y != y)\r
- {\r
- if (p_y > y)\r
- angle = 90; // Face Up\r
- else\r
- angle = 270; // Face Down\r
- }\r
-\r
- FaceAngle(angle);\r
-\r
- return(old_angle);\r
-}\r
-\r
-\r
-#endif\r
-\r
-\r
-\r
-/*==========================================================================\r
-\r
- EXPLOSION SPAWNING ROUTINES\r
-\r
-===========================================================================*/\r
-\r
-statetype s_explode = {0,1,T_ExpThink,&s_explode};\r
-\r
-//-------------------------------------------------------------------------\r
-// SpawnExplosion()\r
-//------------------------------------------------------------------------\r
-void SpawnExplosion(fixed x, fixed y, short Delay)\r
-{\r
- DSpawnNewObjFrac(x,y,&s_explode,PIXRADIUS*7);\r
- new->obclass = expobj;\r
- new->active = always;\r
- new->temp1 = Delay;\r
-}\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// T_ExpThink()\r
-//---------------------------------------------------------------------------\r
-void T_ExpThink(objtype *obj)\r
-{\r
- if (obj->temp1)\r
- {\r
- if ((obj->temp1-=realtics) <= 0)\r
- obj->temp1 = 0;\r
- }\r
- else\r
- {\r
- obj->state = &s_pshot_exp1;\r
- obj->ticcount = obj->state->tictime;\r
- SD_PlaySound(BOOMSND);\r
- }\r
-}\r
-\r
-\r
-\r
-//-------------------------------------------------------------------------\r
-// SpawnBigExplosion()\r
-//------------------------------------------------------------------------\r
-void SpawnBigExplosion(fixed x, fixed y, short Delay, fixed Range)\r
-{\r
- SpawnExplosion(x-random(Range),y+random(Range),random(Delay));\r
- SpawnExplosion(x+random(Range),y-random(Range),random(Delay));\r
- SpawnExplosion(x-random(Range),y-random(Range),random(Delay));\r
- SpawnExplosion(x+random(Range),y+random(Range),random(Delay));\r
-}\r
-\r
+++ /dev/null
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#include "ID_HEADS.H"\r
-#include <MATH.H>\r
-#include <VALUES.H>\r
-\r
-//#define PROFILE\r
-\r
-#define DEBUG_KEYS_AVAILABLE 0\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-//\r
-// SOFTLIB GFX FILENAME\r
-//\r
-#define SLIB_GFX "ARM_SLIB."EXT\r
-\r
-\r
-#define USE_INERT_LIST false\r
-\r
-\r
-//\r
-// MAX_BASE - represents 100 percent in 1st base\r
-// MAX_PERC - represents 100 percent in 2nd base\r
-// PERC - fractional portion of 2nd base\r
-// SCALE - arbitrary scaling value (bigger number means more accurate)\r
-//\r
-// ex: PERCENTAGE(320,16,8,7) returns 160\r
-//\r
-// Make sure values used won't overflow a WORD! In general, if largest number\r
-// to be used (320 in ex: above) * (1<<SCALE) is greater than 65535, use\r
-// LONG_PERCENTAGE or a lower SCALE. Using a SCALE of 8 in the example\r
-// above would overflow a WORD in some circumstances!\r
-//\r
-// LONG_PERCENTAGE is to be used for larger SCALEs, thus, giving you\r
-// massive accuracy!\r
-//\r
-#define PERCENTAGE(MAX_BASE,MAX_PERC,PERC,SCALE) ((unsigned)(MAX_BASE*((PERC<<SCALE)/MAX_PERC))>>SCALE)\r
-#define LONG_PERCENTAGE(MAX_BASE,MAX_PERC,PERC,SCALE) (((long)MAX_BASE*(((long)PERC<<SCALE)/MAX_PERC))>>SCALE)\r
-\r
-#define PI 3.141592657\r
-\r
-//#define SIZE_TEST 65000\r
-#define SIZE_TEST 0\r
-\r
-\r
-#define FL_QUICK 0x01\r
-#define FL_NOMEMCHECK 0x02\r
-#define FL_HELPTEST 0x04\r
-\r
-#define FL_CLEAR (FL_QUICK|FL_NOMEMCHECK|FL_HELPTEST)\r
-\r
-#if 0\r
-#define GEM_SHIFT 2\r
-#define FL_RGEM 0x04\r
-#define FL_GGEM 0x08\r
-#define FL_BGEM 0x10\r
-#define FL_YGEM 0x20\r
-#define FL_PGEM 0x40\r
-#endif\r
-\r
-#define FL_DEAD 0x80\r
-\r
-\r
-\r
-#define MAXBOLTS 10\r
-#define MAXNUKES 10\r
-#define MAXPOTIONS 10\r
-\r
-#define NUKE_COST (1000)\r
-#define BOLT_COST (1200)\r
-#define POTION_COST (1300)\r
-\r
-#define NUKE_COST_TXT ("1000") // Allows for Q&D positioning..\r
-#define BOLT_COST_TXT ("1200")\r
-#define POTION_COST_TXT ("1300")\r
-\r
-#define RADARX 31 // bytes\r
-#define RADARY 11 // pixels\r
-#define RADAR_WIDTH 51 // "\r
-#define RADAR_HEIGHT 51 // "\r
-#define RADAR_XCENTER ((RADARX*8)+(RADAR_WIDTH/2)+3) // "\r
-#define RADAR_YCENTER ((RADARY-8)+(RADAR_HEIGHT/2)+5) // "\r
-#define MAX_RADAR_BLIPS 60\r
-\r
-\r
-#define RADAR_RADIUS 17\r
-#define RADAR_RADIUS_NSEW 15\r
-#define RADAR_X_IRADIUS (113/5)\r
-#define RADAR_Y_IRADIUS (113/7)\r
-#define RADAR_ICON_CENTER 4 // Center offset into icon.\r
-\r
-#define NAMESTART 180\r
-#define REMOVED_DOOR_TILE NAMESTART\r
-\r
-#define NEXT_LEVEL_CODE 0xff\r
-#define REMOVE_DOOR_CODE 0xfe\r
-#define CANT_OPEN_CODE 0xfd\r
-#define EXP_WALL_CODE 0xfc\r
-\r
-\r
-#define UNMARKGRCHUNK(chunk) (grneeded[chunk]&=~ca_levelbit)\r
-\r
-#define MOUSEINT 0x33\r
-\r
-#define EXPWALLSTART 8\r
-#define NUMEXPWALLS 7\r
-#define WALLEXP 59\r
-#define WATEREXP 62\r
-#define NUMFLOORS 80 //71\r
-\r
-#define NUMLATCHPICS (FIRSTWALLPIC-FIRSTLATCHPIC) //+5\r
-#define NUMSCALEPICS (FIRSTWALLPIC-FIRSTSCALEPIC) //+5\r
-#define NUMSCALEWALLS (LASTWALLPIC-FIRSTWALLPIC) //+5\r
-\r
-\r
-#define FLASHCOLOR 12\r
-#define FLASHTICS 4\r
-\r
-\r
-#define NUMLEVELS 32 //21\r
-\r
-#define VIEWX 0 // corner of view window\r
-#define VIEWY 0\r
-#define VIEWWIDTH (40*8) // size of view window // 33\r
-#define VIEWHEIGHT (15*8) // 18\r
-#define VIEWXH (VIEWX+VIEWWIDTH-1)\r
-#define VIEWYH (VIEWY+VIEWHEIGHT-1)\r
-\r
-#define CENTERX (VIEWX+VIEWWIDTH/2-1) // middle of view window\r
-#define CENTERY (VIEWY+VIEWHEIGHT/2-1)\r
-\r
-#define GLOBAL1 (1l<<16)\r
-#define TILEGLOBAL GLOBAL1\r
-#define TILESHIFT 16l\r
-\r
-#define MINDIST (2*GLOBAL1/5)\r
-#define FOCALLENGTH (TILEGLOBAL) // in global coordinates\r
-\r
-#define ANGLES 360 // must be divisable by 4\r
-\r
-#define MAPSIZE 64 // maps are 64*64 max\r
-#define MAXACTORS 100 // max number of tanks, etc / map\r
-\r
-#define NORTH 0\r
-#define EAST 1\r
-#define SOUTH 2\r
-#define WEST 3\r
-\r
-#define SIGN(x) ((x)>0?1:-1)\r
-#define ABS(x) ((int)(x)>0?(x):-(x))\r
-#define LABS(x) ((long)(x)>0?(x):-(x))\r
-\r
-#define MAXSCALE (VIEWWIDTH/2)\r
-\r
-\r
-#define MAXBODY 100\r
-#define MAXSHOTPOWER 56\r
-\r
-#define SCREEN1START 0\r
-#define SCREEN2START 8320\r
-\r
-#define STATUSLEN 0xc80\r
-#define PAGELEN 0x1700\r
-\r
-#define PAGE1START STATUSLEN\r
-#define PAGE2START (PAGE1START+PAGELEN)\r
-#define PAGE3START (PAGE2START+PAGELEN)\r
-#define FREESTART (PAGE3START+PAGELEN)\r
-\r
-#define PIXRADIUS 512\r
-\r
-#define STATUSLINES (200-VIEWHEIGHT)\r
-\r
-enum bonusnumbers {B_BOLT,B_NUKE,B_POTION,B_RKEY,B_YKEY,B_GKEY,B_BKEY,B_SCROLL1,\r
- B_SCROLL2,B_SCROLL3,B_SCROLL4,B_SCROLL5,B_SCROLL6,B_SCROLL7,B_SCROLL8,\r
- B_GOAL,B_CHEST,B_RGEM,B_GGEM,B_BGEM,B_YGEM,B_PGEM};\r
-\r
-\r
-#define MAX_DOOR_STORAGE 5\r
-\r
-#define GEM_DELAY_TIME (120*60)\r
-\r
-#define ROTATE_SPEED (6)\r
-\r
-#define WALL_SKELETON_CODE 6\r
-\r
-#define MAXREALTICS (2*60)\r
-\r
-#define MAXFREEZETIME (100*30) // 50 secs (100 half)\r
-\r
-#define INVISIBLEWALL 0x46\r
-\r
-#define USE_STRIPS FALSE\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL TYPES\r
-\r
-=============================================================================\r
-*/\r
-\r
-enum {BLANKCHAR=9,BOLTCHAR,NUKECHAR,POTIONCHAR,KEYCHARS,SCROLLCHARS=17,\r
- NUMBERCHARS=25};\r
-\r
-typedef long fixed;\r
-\r
-typedef struct {int x,y;} tilept;\r
-typedef struct {fixed x,y;} globpt;\r
-\r
-typedef struct\r
-{\r
- int x1,x2,leftclip,rightclip;// first pixel of wall (may not be visable)\r
- unsigned height1,height2,color,walllength,side;\r
- long planecoord;\r
-} walltype;\r
-\r
-typedef enum\r
- {nothing,playerobj,bonusobj,succubusobj,batobj,skeletonobj,fatdemonobj,godessobj,\r
- mageobj,pshotobj,bigpshotobj,mshotobj,inertobj,bounceobj,grelmobj,sshotobj,\r
- gateobj,zombieobj,antobj,wetobj,expobj,eyeobj,wallskelobj,eshotobj,treeobj,\r
- gshotobj,reddemonobj,freezeobj,solidobj,cloudobj,dshotobj,hbunnyobj,bunnyobj,\r
- realsolidobj} classtype;\r
-\r
-typedef enum {north,east,south,west,northeast,southeast,southwest,\r
- northwest,nodir} dirtype; // a catacombs 2 carryover\r
-\r
-typedef struct statestruct\r
-{\r
- int shapenum;\r
- int tictime;\r
- void (*think) ();\r
- struct statestruct far *next;\r
-} statetypestruct;\r
-\r
-#define statetype statetypestruct far\r
-\r
-#define of_shootable 0x01\r
-#define of_damagedone 0x02\r
-#define of_forcefield 0x40 // defines a solid object as a forcefield???????????\r
-#define of_tree 0x80 // used to identify between a tree and a statue --\r
- // last minute changes for Greg\r
-\r
-typedef struct objstruct\r
-{\r
-\r
- int ticcount; //\r
- statetype *state; // THESE MEMBERS MUST BE IN THE SAME\r
- fixed x,y; // ORDER AS THE MEMBERS DEFINED IN\r
- int viewx; // IOBJSTRUCT OR ALL HELL WILL BREAK\r
- unsigned tilex,tiley; // LOOSE!!\r
- unsigned viewheight; //\r
- unsigned size; //\r
- struct objstruct *next; //\r
-\r
-\r
- struct objstruct *prev;\r
- enum {no,noalways,yes,always} active;\r
- classtype obclass;\r
-\r
- unsigned char flags;\r
-\r
- long distance;\r
- dirtype dir;\r
-\r
- int angle;\r
- int hitpoints;\r
- long speed;\r
-\r
- fixed xl,xh,yl,yh; // hit rectangle\r
-\r
- int temp1,temp2;\r
-} objtype;\r
-\r
-#if USE_INERT_LIST\r
-\r
-#define MAXINERTOBJ 20\r
-\r
-typedef struct iobjstruct {\r
- int ticcount;\r
- statetype *state;\r
- fixed x,y;\r
- int viewx;\r
- unsigned tilex,tiley;\r
- unsigned viewheight;\r
- unsigned size;\r
- struct iobjstruct *next;\r
-} inertobjtype;\r
-\r
-#endif\r
-\r
-\r
-typedef enum {ex_stillplaying,ex_died,ex_warped,ex_resetgame\r
- ,ex_loadedgame,ex_victorious,ex_turning,ex_abort} exittype;\r
-\r
-\r
-typedef enum {S_NONE, S_HELP, S_SND, S_SAVING, S_RESTORING,\r
- S_JOYSTICK, S_RETREAT, S_ADVANCE, S_SIDESTEP, S_QTURN,\r
- S_MISSLE, S_ZAPPER, S_XTER, S_CURING, S_READ,\r
- S_VIEWING, S_ITEMDES, S_DAMAGE, S_TURN, S_TIMESTOP} status_flags;\r
-\r
-typedef struct {\r
- char x,y;\r
- unsigned ondoor,underdoor;\r
-} doorinfo;\r
-\r
-typedef struct {\r
- char x,y;\r
- short angle;\r
- doorinfo doors[MAX_DOOR_STORAGE];\r
-} levelinfo;\r
-\r
-typedef struct\r
-{\r
- int difficulty;\r
- int mapon;\r
- int bolts,nukes,potions,keys[4],scrolls[8];\r
-\r
- int gems[5]; // "int allgems[5]" is used for 1:1 comparison\r
- // in play loop for radar... CHANGE IT, TOO!\r
-\r
- long score;\r
- int body,shotpower;\r
- short mapwidth,mapheight;\r
-// levelinfo levels[NUMLEVELS];\r
-} gametype;\r
-\r
-/*\r
-=============================================================================\r
-\r
- C3_MAIN DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern char inlevel[][2];\r
-extern char str[80],str2[20];\r
-extern unsigned tedlevelnum;\r
-extern boolean tedlevel;\r
-extern gametype gamestate;\r
-extern exittype playstate;\r
-extern char SlowMode;\r
-extern unsigned Flags;\r
-extern boolean LoadShapes;\r
-extern boolean EASYMODEON;\r
-\r
-\r
-void NewGame (void);\r
-boolean SaveTheGame(int file);\r
-boolean LoadTheGame(int file);\r
-void ResetGame(void);\r
-void ShutdownId (void);\r
-void InitGame (void);\r
-void Quit (char *error, ...);\r
-void TEDDeath(void);\r
-void DemoLoop (void);\r
-void SetupScalePic (unsigned picnum);\r
-void SetupScaleWall (unsigned picnum);\r
-void SetupScaling (void);\r
-void main (void);\r
-void Display320(void);\r
-void Display640(void);\r
-void PrintHelp(void);\r
-\r
-/*\r
-=============================================================================\r
-\r
- C3_GAME DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern unsigned latchpics[NUMLATCHPICS];\r
-extern unsigned tileoffsets[NUMTILE16];\r
-extern unsigned textstarts[27];\r
-\r
-\r
-#define L_CHARS 0\r
-#define L_NOSHOT 1\r
-#define L_SHOTBAR 2\r
-#define L_NOBODY 3\r
-#define L_BODYBAR 4\r
-\r
-\r
-void ScanInfoPlane (void);\r
-void ScanText (void);\r
-void SetupGameLevel(void);\r
-void Victory (boolean playsounds);\r
-void Died (void);\r
-void NormalScreen (void);\r
-void DrawPlayScreen (void);\r
-void LoadLatchMem (void);\r
-void FizzleFade (unsigned source, unsigned dest,\r
- unsigned width,unsigned height, boolean abortable);\r
-void FizzleOut (int showlevel);\r
-void FreeUpMemory (void);\r
-void GameLoop (void);\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- C3_PLAY DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define BGF_NIGHT 0x01 // it is officially night\r
-#define BGF_NOT_LIGHTNING 0x02 // lightning flash has ended\r
-\r
-extern byte BGFLAGS,bcolor;\r
-\r
-extern unsigned *skycolor,*groundcolor;\r
-\r
-extern ControlInfo control;\r
-extern boolean running,slowturn;\r
-\r
-extern int bordertime;\r
-\r
-extern byte tilemap[MAPSIZE][MAPSIZE];\r
-extern objtype *actorat[MAPSIZE][MAPSIZE];\r
-extern byte spotvis[MAPSIZE][MAPSIZE];\r
-\r
-extern objtype objlist[MAXACTORS],*new,*obj,*player;\r
-\r
-extern unsigned farmapylookup[MAPSIZE];\r
-extern byte *nearmapylookup[MAPSIZE];\r
-extern byte update[];\r
-\r
-extern boolean godmode,singlestep;\r
-extern int extravbls;\r
-\r
-extern int mousexmove,mouseymove;\r
-extern int pointcount,pointsleft;\r
-extern status_flags status_flag;\r
-extern int status_delay;\r
-\r
-extern objtype dummyobj;\r
-extern short BeepTime;\r
-extern unsigned scolor,gcolor;\r
-\r
-void CenterWindow(word w,word h);\r
-void DebugMemory (void);\r
-void PicturePause (void);\r
-int DebugKeys (void);\r
-void CheckKeys (void);\r
-void InitObjList (void);\r
-void GetNewObj (boolean usedummy);\r
-void RemoveObj (objtype *gone);\r
-void PollControlls (void);\r
-void PlayLoop (void);\r
-void InitBgChange(short stimer, unsigned *scolors, short gtimer, unsigned *gcolors, byte flag);\r
-\r
-void DisplayStatus (status_flags *stat_flag);\r
-\r
-/*\r
-=============================================================================\r
-\r
- C3_STATE DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-//void SpawnNewObj (unsigned x, unsigned y, statetype *state, unsigned size);\r
-//void SpawnNewObjFrac (long x, long y, statetype *state, unsigned size);\r
-\r
-void Internal_SpawnNewObj (unsigned x, unsigned y, statetype *state, unsigned size, boolean UseDummy, boolean PutInActorat);\r
-void Internal_SpawnNewObjFrac (long x, long y, statetype *state, unsigned size,boolean UseDummy);\r
-\r
-#define DSpawnNewObj(x, y, state, size) Internal_SpawnNewObj(x,y,state,size,true,true)\r
-#define SpawnNewObj(x, y, state, size) Internal_SpawnNewObj(x,y,state,size,false,true)\r
-#define ASpawnNewObj(x, y, state, size) Internal_SpawnNewObj(x,y,state,size,false,false)\r
-#define SpawnNewObjFrac(x, y, state, size,Dummy) Internal_SpawnNewObjFrac(x, y, state, size,false)\r
-#define DSpawnNewObjFrac(x, y, state, size) Internal_SpawnNewObjFrac(x, y, state, size,true)\r
-\r
-boolean CheckHandAttack (objtype *ob);\r
-void T_DoDamage (objtype *ob);\r
-boolean Walk (objtype *ob);\r
-void ChaseThink (objtype *obj, boolean diagonal);\r
-void MoveObj (objtype *ob, long move);\r
-boolean Chase (objtype *ob, boolean diagonal);\r
-\r
-extern dirtype opposite[9];\r
-\r
-/*\r
-=============================================================================\r
-\r
- C3_TRACE DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-int FollowTrace (fixed tracex, fixed tracey, long deltax, long deltay, int max);\r
-int BackTrace (int finish);\r
-void ForwardTrace (void);\r
-int FinishWall (void);\r
-void InsideCorner (void);\r
-void OutsideCorner (void);\r
-void FollowWalls (void);\r
-\r
-extern boolean aborttrace;\r
-\r
-/*\r
-=============================================================================\r
-\r
- C3_DRAW DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define MAXWALLS 50\r
-#define DANGERHIGH 45\r
-\r
-#define MIDWALL (MAXWALLS/2)\r
-\r
-//==========================================================================\r
-\r
-extern tilept tile,lasttile,focal,left,mid,right;\r
-\r
-extern globpt edge,view;\r
-\r
-extern unsigned screenloc[3];\r
-extern unsigned freelatch;\r
-\r
-extern int screenpage;\r
-\r
-extern boolean fizzlein;\r
-\r
-extern long lasttimecount;\r
-\r
-extern int firstangle,lastangle;\r
-\r
-extern fixed prestep;\r
-\r
-extern int traceclip,tracetop;\r
-\r
-extern fixed sintable[ANGLES+ANGLES/4],*costable;\r
-\r
-extern fixed viewx,viewy,viewsin,viewcos; // the focal point\r
-extern int viewangle;\r
-\r
-extern fixed scale,scaleglobal;\r
-extern unsigned slideofs;\r
-\r
-extern int zbuffer[VIEWXH+1];\r
-\r
-extern walltype walls[MAXWALLS],*leftwall,*rightwall;\r
-\r
-\r
-extern fixed tileglobal;\r
-extern fixed focallength;\r
-extern fixed mindist;\r
-extern int viewheight;\r
-extern fixed scale;\r
-\r
-extern int far walllight1[NUMFLOORS];\r
-extern int far walldark1[NUMFLOORS];\r
-\r
-extern unsigned topcolor,bottomcolor;\r
-\r
-extern char wall_anim_info[NUMFLOORS];\r
-extern char wall_anim_pos[NUMFLOORS];\r
-\r
-//==========================================================================\r
-\r
-void DrawLine (int xl, int xh, int y,int color);\r
-void DrawWall (walltype *wallptr);\r
-void TraceRay (unsigned angle);\r
-fixed FixedByFrac (fixed a, fixed b);\r
-void TransformPoint (fixed gx, fixed gy, int *screenx, unsigned *screenheight);\r
-fixed TransformX (fixed gx, fixed gy);\r
-int FollowTrace (fixed tracex, fixed tracey, long deltax, long deltay, int max);\r
-void ForwardTrace (void);\r
-int FinishWall (void);\r
-int TurnClockwise (void);\r
-int TurnCounterClockwise (void);\r
-void FollowWall (void);\r
-\r
-void NewScene (void);\r
-void BuildTables (void);\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- C3_SCALE DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-#define COMPSCALECODESTART (65*6) // offset to start of code in comp scaler\r
-\r
-typedef struct\r
-{\r
- unsigned codeofs[65];\r
- unsigned start[65];\r
- unsigned width[65];\r
- byte code[];\r
-} t_compscale;\r
-\r
-typedef struct\r
-{\r
- unsigned width;\r
- unsigned codeofs[64];\r
-} t_compshape;\r
-\r
-\r
-extern unsigned scaleblockwidth,\r
- scaleblockheight,\r
- scaleblockdest;\r
-\r
-extern byte plotpix[8];\r
-extern byte bitmasks1[8][8];\r
-extern byte bitmasks2[8][8];\r
-\r
-\r
-extern t_compscale _seg *scaledirectory[NUMSCALEPICS];\r
-extern t_compshape _seg *shapedirectory[NUMSCALEPICS];\r
-extern memptr walldirectory[NUMSCALEWALLS];\r
-extern unsigned shapesize[NUMSCALEPICS];\r
-\r
-void DeplanePic (int picnum);\r
-void ScaleShape (int xcenter, t_compshape _seg *compshape, unsigned scale);\r
-unsigned BuildCompShape (t_compshape _seg **finalspot);\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- C3_ASM DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern unsigned wallheight [VIEWWIDTH];\r
-extern unsigned wallwidth [VIEWWIDTH];\r
-extern unsigned wallseg [VIEWWIDTH];\r
-extern unsigned wallofs [VIEWWIDTH];\r
-extern unsigned screenbyte [VIEWWIDTH];\r
-extern unsigned screenbit [VIEWWIDTH];\r
-extern unsigned bitmasks [64];\r
-\r
-extern long wallscalecall;\r
-\r
-void ScaleWalls (void);\r
-\r
-/*\r
-=============================================================================\r
-\r
- C3_WIZ DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define MAXHANDHEIGHT 72\r
-\r
-extern statetype s_pshot_exp1;\r
-extern statetype s_pshot_exp2;\r
-extern statetype s_pshot_exp3;\r
-\r
-extern long lastnuke;\r
-extern int lasttext;\r
-extern int handheight;\r
-extern int boltsleft,bolttimer;\r
-extern short RadarXY[][3];\r
-\r
-extern short RotateAngle;\r
-extern short FreezeTime;\r
-\r
-//void FaceDir(short x, short y, boolean StopTime);\r
-//short CalcAngle(short dx, short dy);\r
-\r
-void FaceAngle(short DestAngle);\r
-void RotateView();\r
-void InitRotate(short DestAngle);\r
-short FaceDoor(short x, short y);\r
-\r
-char DisplayMsg(char *text,char *choices);\r
-char DisplaySMsg(char *text,char *choices);\r
-\r
-extern statetype s_explode;\r
-\r
-void SpawnExplosion(fixed x, fixed y,short Delay);\r
-void T_ExpThink(objtype *obj);\r
-void SpawnBigExplosion(fixed x, fixed y, short Delay, fixed Range);\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- C3_ACT1 DEFINITIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-int EasyHitPoints(int NrmHitPts);\r
-int EasyDoDamage(int Damage);\r
-\r
-#define zombie_mode ob->temp1\r
-#define zombie_delay ob->temp2\r
-\r
-enum zombie_modes {zm_wait_for_dark,zm_wait_to_rise,zm_active};\r
-\r
-enum eye_modes {em_other1,em_player1,em_other2,em_player2,em_other3,em_player3,em_other4,em_player4,em_dummy};\r
-\r
-#define MSHOTDAMAGE 2\r
-#define MSHOTSPEED 10000\r
-\r
-#define ESHOTDAMAGE 1\r
-#define ESHOTSPEED 5000\r
-\r
-#define SSHOTDAMAGE 3\r
-#define SSHOTSPEED 6500\r
-\r
-#define RANDOM_ATTACK 20\r
-\r
-extern dirtype dirtable[];\r
-extern short other_x[], other_y[];\r
-extern short zombie_base_delay;\r
-\r
-extern statetype s_fatdemon_ouch;\r
-extern statetype s_fatdemon_blowup1;\r
-\r
-extern statetype s_succubus_ouch;\r
-extern statetype s_succubus_death1;\r
-\r
-extern statetype s_godessouch;\r
-extern statetype s_godessdie1;\r
-\r
-extern statetype s_mageouch;\r
-extern statetype s_magedie1;\r
-\r
-extern statetype s_grelouch;\r
-extern statetype s_greldie1;\r
-\r
-extern statetype s_batdie1;\r
-\r
-extern statetype s_zombie_death1;\r
-extern statetype s_zombie_ouch;\r
-\r
-extern statetype s_zombie_rise1;\r
-extern statetype s_zombie_rise2;\r
-extern statetype s_zombie_rise3;\r
-extern statetype s_zombie_rise4;\r
-\r
-extern statetype s_ant_wait;\r
-extern statetype s_ant_egg;\r
-extern statetype s_ant_walk1;\r
-extern statetype s_ant_walk2;\r
-extern statetype s_ant_walk3;\r
-extern statetype s_ant_attack1;\r
-extern statetype s_ant_pause;\r
-extern statetype s_ant_ouch;\r
-extern statetype s_ant_die1;\r
-extern statetype s_ant_die2;\r
-extern statetype s_ant_die3;\r
-\r
-extern statetype s_skel_pause;\r
-extern statetype s_skel_1;\r
-extern statetype s_skel_2;\r
-extern statetype s_skel_3;\r
-extern statetype s_skel_4;\r
-extern statetype s_skel_attack1;\r
-extern statetype s_skel_attack2;\r
-extern statetype s_skel_attack3;\r
-extern statetype s_skel_ouch;\r
-extern statetype s_skel_die1;\r
-extern statetype s_skel_die2;\r
-extern statetype s_skel_die3;\r
-\r
-extern statetype s_wet_pause;\r
-\r
-extern statetype s_wet_bubbles1;\r
-extern statetype s_wet_bubbles2;\r
-extern statetype s_wet_bubbles3;\r
-extern statetype s_wet_bubbles4;\r
-\r
-extern statetype s_wet_peek;\r
-\r
-extern statetype s_wet_rise1;\r
-extern statetype s_wet_rise2;\r
-extern statetype s_wet_rise3;\r
-extern statetype s_wet_rise4;\r
-extern statetype s_wet_rise5;\r
-\r
-extern statetype s_wet_sink1;\r
-extern statetype s_wet_sink2;\r
-extern statetype s_wet_sink3;\r
-\r
-extern statetype s_wet_walk1;\r
-extern statetype s_wet_walk2;\r
-extern statetype s_wet_walk3;\r
-extern statetype s_wet_walk4;\r
-\r
-extern statetype s_wet_attack1;\r
-extern statetype s_wet_attack2;\r
-extern statetype s_wet_attack3;\r
-extern statetype s_wet_attack4;\r
-\r
-extern statetype s_wet_ouch;\r
-\r
-extern statetype s_wet_die1;\r
-extern statetype s_wet_die2;\r
-extern statetype s_wet_die3;\r
-extern statetype s_wet_die4;\r
-extern statetype s_wet_die5;\r
-\r
-extern statetype s_obj_gate1;\r
-extern statetype s_obj_gate2;\r
-extern statetype s_obj_gate3;\r
-extern statetype s_obj_gate4;\r
-\r
-extern statetype s_eye_pause;\r
-\r
-extern statetype s_eye_1;\r
-extern statetype s_eye_2;\r
-extern statetype s_eye_3;\r
-extern statetype s_eye_4;\r
-\r
-extern statetype s_eye_ouch;\r
-extern statetype s_eye_ouch2;\r
-\r
-extern statetype s_eye_die1;\r
-extern statetype s_eye_die2;\r
-extern statetype s_eye_die3;\r
-\r
-extern statetype s_mshot1;\r
-extern statetype s_mshot2;\r
-\r
-extern statetype s_bonus_die;\r
-\r
-extern statetype s_red_demonouch;\r
-extern statetype s_red_demondie1;\r
-\r
-extern statetype s_bunny_death1;\r
-extern statetype s_bunny_ouch;\r
-\r
-extern statetype s_tree_death1;\r
-extern statetype s_tree_ouch;\r
-\r
-extern statetype s_force_field_die;
\ No newline at end of file
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#include <dos.h>\r
-#include <conio.h>\r
-#include <stdio.h>\r
-#include <dir.h>\r
-#include "mem.h"\r
-#include "string.h"\r
-#include "time.h"\r
-#include "stdarg.h"\r
-#include "io.h"\r
-\r
-#include "DEF.H"\r
-#include "gelib.h"\r
-#include "sl_file.h"\r
-\r
-\r
-#define MAX_GAMELIST_NAMES 20\r
-#define FNAME_LEN 9\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// Global variables\r
-//\r
-boolean InLoadSaveGame = false;\r
-//AudioDeviceType ge_DigiMode;\r
-boolean ConserveMemory = false;\r
-char GameListNames[MAX_GAMELIST_NAMES+1][FNAME_LEN],current_disk=1;\r
-short NumGames;\r
-short PPT_LeftEdge=0,PPT_RightEdge=320;\r
-boolean LeaveDriveOn=false,ge_textmode=true;\r
-char Filename[FILENAME_LEN+1], ID[sizeof(GAMENAME)], VER[sizeof(SAVEVER_DATA)];\r
-short wall_anim_delay,wall_anim_time = 7;\r
-BufferedIO lzwBIO;\r
-\r
-\r
-\r
-\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// CalibrateJoystick()\r
-//\r
-void CalibrateJoystick(short joynum)\r
-{\r
- word minx,maxx,\r
- miny,maxy;\r
-\r
- IN_ClearKeysDown();\r
-\r
- VW_HideCursor();\r
-\r
- VW_FixRefreshBuffer();\r
- CenterWindow(30,8);\r
-\r
- US_Print("\n");\r
- US_CPrintLine("Move joystick to the upper-left");\r
- US_CPrintLine("and press one of the buttons.");\r
- VW_UpdateScreen();\r
-\r
- while ((LastScan != sc_Escape) && !IN_GetJoyButtonsDB(joynum));\r
- if (LastScan == sc_Escape)\r
- return;\r
-\r
- IN_GetJoyAbs(joynum,&minx,&miny);\r
- while (IN_GetJoyButtonsDB(joynum));\r
-\r
- US_Print("\n");\r
- US_CPrintLine("Move joystick to the lower-right");\r
- US_CPrintLine("and press one of the buttons.");\r
- VW_UpdateScreen();\r
-\r
- while ((LastScan != sc_Escape) && !IN_GetJoyButtonsDB(joynum));\r
- if (LastScan == sc_Escape)\r
- return;\r
-\r
- IN_GetJoyAbs(joynum,&maxx,&maxy);\r
- if ((minx == maxx) && (miny == maxy))\r
- return;\r
-\r
- IN_SetupJoy(joynum,minx,maxx,miny,maxy);\r
-\r
- while (IN_GetJoyButtonsDB(joynum));\r
- if (LastScan)\r
- IN_ClearKeysDown();\r
-\r
- JoystickCalibrated = true;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// WaitKeyVBL()\r
-//\r
-void WaitKeyVBL(short key, short vbls)\r
-{\r
- while (vbls--)\r
- {\r
- VW_WaitVBL(1);\r
- IN_ReadControl(0,&control);\r
- if ((control.button0|control.button1)||(Keyboard[key]))\r
- break;\r
- }\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// MoveScreen()\r
-//\r
-// panadjust must be saved and restored if MoveScreen is being called from\r
-// inside a level.\r
-//\r
-void MoveScreen(short x, short y)\r
-{\r
- unsigned address;\r
-\r
- address = (y*linewidth)+(x/8);\r
- VW_SetScreen(address,0);\r
- bufferofs = displayofs = address;\r
- panadjust=0;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// MoveGfxDst()\r
-//\r
-void MoveGfxDst(short x, short y)\r
-{\r
- unsigned address;\r
-\r
- address = (y*linewidth)+(x/8);\r
- bufferofs = displayofs = address;\r
-}\r
-\r
-#if 0\r
-\r
-#if GRAPHIC_PIRATE\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// DoPiracy() - Graphics piracy code...\r
-//\r
-void DoPiracy()\r
-{\r
- struct Shape Pirate1Shp;\r
- struct Shape Pirate2Shp;\r
-\r
- VW_SetScreenMode (EGA320GR);\r
- VW_ClearVideo(BLACK);\r
-\r
- // Load shapes...\r
- //\r
- if (LoadShape("PIRATE1E."EXT,&Pirate1Shp))\r
- TrashProg("Can't load PIRATE1E.BIO");\r
-\r
- if (LoadShape("PIRATE2E."EXT,&Pirate2Shp))\r
- TrashProg("Can't load PIRATE2E.BIO");\r
-\r
- // Deal with shapes...\r
- //\r
- VW_SetLineWidth(40);\r
-\r
- VW_FadeOut();\r
-\r
- MoveScreen(0,0);\r
- UnpackEGAShapeToScreen(&Pirate1Shp,(linewidth-Pirate1Shp.BPR)<<2,0);\r
-\r
- MoveScreen(0,200);\r
- UnpackEGAShapeToScreen(&Pirate2Shp,(linewidth-Pirate2Shp.BPR)<<2,0);\r
-\r
- MoveScreen(0,0);\r
- VW_FadeIn();\r
- WaitKeyVBL(57,200);\r
- while (Keyboard[57]);\r
-\r
- SD_PlaySound(GOOD_PICKSND);\r
-\r
- MoveScreen(0,200);\r
- WaitKeyVBL(57,300);\r
- while (Keyboard[57]);\r
- VW_FadeOut();\r
-\r
- FreeShape(&Pirate1Shp);\r
- FreeShape(&Pirate2Shp);\r
-}\r
-\r
-#else\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// DoPiracy() - Text-based piracy code...\r
-//\r
-void DoPiracy()\r
-{\r
-}\r
-\r
-#endif\r
-#endif\r
-\r
-//--------------------------------------------------------------------------\r
-// BlackPalette()\r
-//--------------------------------------------------------------------------\r
-void BlackPalette()\r
-{\r
- extern char colors[7][17];\r
-\r
- _ES=FP_SEG(&colors[0]);\r
- _DX=FP_OFF(&colors[0]);\r
- _AX=0x1002;\r
- geninterrupt(0x10);\r
- screenfaded = true;\r
-}\r
-\r
-//--------------------------------------------------------------------------\r
-// ColoredPalette()\r
-//--------------------------------------------------------------------------\r
-void ColoredPalette()\r
-{\r
- extern char colors[7][17];\r
-\r
- _ES=FP_SEG(&colors[3]);\r
- _DX=FP_OFF(&colors[3]);\r
- _AX=0x1002;\r
- geninterrupt(0x10);\r
- screenfaded = false;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// Verify()\r
-//\r
-long Verify(char *filename)\r
-{\r
- int handle;\r
- long size;\r
-\r
- if ((handle=open(filename,O_BINARY))==-1)\r
- return (0);\r
- size=filelength(handle);\r
- close(handle);\r
- return(size);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// GE_SaveGame\r
-//\r
-// Handles user i/o for saving a game\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-\r
-void GE_SaveGame()\r
-{\r
- boolean GettingFilename=true;\r
-// char Filename[FILENAME_LEN+1]; //, ID[sizeof(GAMENAME)], VER[sizeof(SAVEVER_DATA)];\r
- int handle;\r
- struct dfree dfree;\r
- long davail;\r
-\r
- VW_FixRefreshBuffer();\r
- ReadGameList();\r
- while (GettingFilename)\r
- {\r
- DisplayGameList(2,7,3,10);\r
- US_DrawWindow(5,1,30,3);\r
- memset(Filename,0,sizeof(Filename));\r
- US_CPrint("Enter name to SAVE this game:");\r
- VW_UpdateScreen();\r
- if (screenfaded)\r
- VW_FadeIn();\r
- if (!US_LineInput((linewidth<<2)-32,20,Filename,"",true,8,0))\r
- goto EXIT_FUNC;\r
- if (!strlen(Filename))\r
- goto EXIT_FUNC;\r
- getdfree(getdisk()+1,&dfree);\r
- davail = (long)dfree.df_avail*(long)dfree.df_bsec*(long)dfree.df_sclus;\r
- if (davail < 10000)\r
- {\r
- US_CenterWindow(22,4);\r
- US_Print("\n");\r
- US_CPrintLine("Disk Full: Can't save game.");\r
- US_CPrintLine("Try inserting another disk.");\r
- VW_UpdateScreen();\r
-\r
- IN_Ack();\r
- }\r
- else\r
- {\r
- strcat(Filename,".SAV");\r
- GettingFilename = false;\r
- if (Verify(Filename)) // FILE EXISTS\r
- {\r
- US_CenterWindow(22,4);\r
- US_CPrintLine("That file already exists...");\r
- US_CPrintLine("Overwrite it ????");\r
- US_CPrintLine("(Y)es or (N)o?");\r
- VW_UpdateScreen();\r
-\r
- while((!Keyboard[21]) && (!Keyboard[49]) && !Keyboard[27]);\r
-\r
- if (Keyboard[27])\r
- goto EXIT_FUNC;\r
- if (Keyboard[49])\r
- {\r
- GettingFilename = true;\r
- VW_UpdateScreen();\r
- }\r
- }\r
- }\r
- }\r
-\r
- handle = open(Filename,O_RDWR|O_CREAT|O_BINARY,S_IREAD|S_IWRITE);\r
- if (handle==-1)\r
- goto EXIT_FUNC;\r
-\r
- if ((!CA_FarWrite(handle,(void far *)GAMENAME,sizeof(GAMENAME))) || (!CA_FarWrite(handle,(void far *)SAVEVER_DATA,sizeof(SAVEVER_DATA))))\r
- {\r
- if (!screenfaded)\r
- VW_FadeOut();\r
-\r
- return;\r
- }\r
-\r
- if (!USL_SaveGame(handle))\r
- Quit("Save game error");\r
-\r
-\r
-\r
-EXIT_FUNC:;\r
-\r
- if (handle!=-1)\r
- close(handle);\r
-\r
- if (handle==-1)\r
- {\r
- remove(Filename);\r
- US_CenterWindow(22,6);\r
- US_CPrintLine("DISK ERROR");\r
- US_CPrintLine("Check: Write protect...");\r
- US_CPrintLine("File name...");\r
- US_CPrintLine("Bytes free on disk...");\r
- US_CPrintLine("Press SPACE to continue.");\r
- VW_UpdateScreen();\r
- while (!Keyboard[57]);\r
- while (Keyboard[57]);\r
- }\r
-\r
- while (Keyboard[1]);\r
-\r
- if (!screenfaded)\r
- VW_FadeOut();\r
-}\r
-\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// GE_LoadGame\r
-//\r
-// Handles user i/o for loading a game\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-\r
-boolean GE_LoadGame()\r
-{\r
- boolean GettingFilename=true,rt_code=false;\r
- int handle;\r
-\r
- IN_ClearKeysDown();\r
- memset(ID,0,sizeof(ID));\r
- memset(VER,0,sizeof(VER));\r
- VW_FixRefreshBuffer();\r
- ReadGameList();\r
- while (GettingFilename)\r
- {\r
- DisplayGameList(2,7,3,10);\r
- US_DrawWindow(5,1,30,3);\r
- memset(Filename,0,sizeof(Filename));\r
- US_CPrint("Enter name of game to RESTORE:");\r
- VW_UpdateScreen();\r
- if (screenfaded)\r
- VW_FadeIn();\r
- if (!US_LineInput((linewidth<<2)-32,20,Filename,"",true,8,0))\r
- goto EXIT_FUNC;\r
- strcat(Filename,".SAV");\r
- GettingFilename = false;\r
-\r
- if (!Verify(Filename)) // FILE DOESN'T EXIST\r
- {\r
- US_CenterWindow(22,3);\r
- US_CPrintLine(" That file doesn't exist....");\r
- US_CPrintLine("Press SPACE to try again.");\r
- VW_UpdateScreen();\r
-\r
- while (!Keyboard[57]);\r
- while (Keyboard[57]);\r
- GettingFilename = true;\r
- }\r
- }\r
-\r
- handle = open(Filename,O_RDWR|O_BINARY);\r
- if (handle==-1)\r
- goto EXIT_FUNC;\r
-\r
- if ((!CA_FarRead(handle,(void far *)&ID,sizeof(ID))) || (!CA_FarRead(handle,(void far *)&VER,sizeof(VER))))\r
- return(false);\r
-\r
- if ((strcmp(ID,GAMENAME)) || (strcmp(VER,SAVEVER_DATA)))\r
- {\r
- US_CenterWindow(32,4);\r
- US_CPrintLine("That isn't a "GAMENAME);\r
- US_CPrintLine(".SAV file.");\r
- US_CPrintLine("Press SPACE to continue.");\r
- VW_UpdateScreen();\r
- while (!Keyboard[57]);\r
- while (Keyboard[57]);\r
-\r
- if (!screenfaded)\r
- VW_FadeOut();\r
-\r
- return(false);\r
- }\r
-\r
- if (!USL_LoadGame(handle))\r
- Quit("Load game error.");\r
-\r
- rt_code = true;\r
-\r
-\r
-EXIT_FUNC:;\r
- if (handle==-1)\r
- {\r
- US_CenterWindow(22,3);\r
- US_CPrintLine("DISK ERROR ** LOAD **");\r
- US_CPrintLine("Press SPACE to continue.");\r
- while (!Keyboard[57]);\r
- while (Keyboard[57]);\r
- }\r
- else\r
- close(handle);\r
-\r
- if (!screenfaded)\r
- VW_FadeOut();\r
-\r
- return(rt_code);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// GE_HardError() - Handles the Abort/Retry/Fail sort of errors passed\r
-// from DOS. Hard coded to ignore if during Load/Save Game.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#pragma warn -par\r
-#pragma warn -rch\r
-int GE_HardError(word errval,int ax,int bp,int si)\r
-{\r
-#define IGNORE 0\r
-#define RETRY 1\r
-#define ABORT 2\r
-extern void ShutdownId(void);\r
-\r
-static char buf[32];\r
-static WindowRec wr;\r
-static boolean oldleavedriveon;\r
- int di;\r
- char c,*s,*t;\r
-boolean holdscreenfaded;\r
-\r
- if (InLoadSaveGame)\r
- hardresume(IGNORE);\r
-\r
-\r
- di = _DI;\r
-\r
- oldleavedriveon = LeaveDriveOn;\r
- LeaveDriveOn = false;\r
-\r
- if (ax < 0)\r
- s = "Device Error";\r
- else\r
- {\r
- if ((di & 0x00ff) == 0)\r
- s = "Drive ~ is Write Protected";\r
- else\r
- s = "Error on Drive ~";\r
- for (t = buf;*s;s++,t++) // Can't use sprintf()\r
- if ((*t = *s) == '~')\r
- *t = (ax & 0x00ff) + 'A';\r
- *t = '\0';\r
- s = buf;\r
- }\r
-\r
- c = peekb(0x40,0x49); // Get the current screen mode\r
- if ((c < 4) || (c == 7))\r
- goto oh_kill_me;\r
-\r
- // DEBUG - handle screen cleanup\r
- holdscreenfaded=screenfaded;\r
-\r
- US_SaveWindow(&wr);\r
- VW_ClearVideo(0); ////////////// added for exiting\r
- US_CenterWindow(30,3);\r
- US_CPrint(s);\r
- US_CPrint("(R)etry or (A)bort?");\r
- VW_UpdateScreen();\r
- if (holdscreenfaded)\r
- VW_FadeIn();\r
- IN_ClearKeysDown();\r
-\r
-asm sti // Let the keyboard interrupts come through\r
-\r
- while (true)\r
- {\r
- switch (IN_WaitForASCII())\r
- {\r
- case key_Escape:\r
- case 'a':\r
- case 'A':\r
- goto oh_kill_me;\r
- break;\r
- case key_Return:\r
- case key_Space:\r
- case 'r':\r
- case 'R':\r
- if (holdscreenfaded)\r
- VW_FadeOut();\r
- US_ClearWindow();\r
- VW_UpdateScreen();\r
- US_RestoreWindow(&wr);\r
- LeaveDriveOn = oldleavedriveon;\r
- return(RETRY);\r
- break;\r
- }\r
- }\r
-\r
-oh_kill_me:\r
- abortprogram = s;\r
- TrashProg("Terminal Error: %s\n",s);\r
-// if (tedlevel)\r
-// fprintf(stderr,"You launched from TED. I suggest that you reboot...\n");\r
-\r
- return(ABORT);\r
-#undef IGNORE\r
-#undef RETRY\r
-#undef ABORT\r
-}\r
-#pragma warn +par\r
-#pragma warn +rch\r
-\r
-//--------------------------------------------------------------------------\r
-//\r
-//\r
-// B O B ROUTINES\r
-//\r
-//\r
-//--------------------------------------------------------------------------\r
-\r
-\r
-\r
-#ifdef BOBLIST\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// UpdateBOBList() - Adds a sprite to an objects BOBlist. The BOB List\r
-// must already be allocated and have an available slot.\r
-//\r
-// RETURNS : true = Success adding Sprite / false = Failure.\r
-//\r
-// NOTE : This also sets the users 'needtoreact' flag to true.\r
-//\r
-boolean UpdateBOBList(objtype *obj,struct Simple_Shape *Shape,shapeclass Class, short priority, spriteflags sprflags)\r
-{\r
- struct BOB_Shape *CurBOBShape = NULL;\r
-\r
-#pragma warn -pia\r
-\r
- if (CurBOBShape = obj->nextshape)\r
- {\r
- // Treverse down BOBList looking for a sprite with the same class\r
- // OR an empty shape struct to store the new shape.\r
-\r
- while ((CurBOBShape->class != Class) && (CurBOBShape->class) && CurBOBShape)\r
- {\r
- CurBOBShape = CurBOBShape->nextshape;\r
- }\r
-\r
- if (CurBOBShape)\r
- {\r
- RF_RemoveSprite(&CurBOBShape->sprite);\r
- CurBOBShape->shapenum = Shape->shapenum;\r
- CurBOBShape->x_offset = Shape->x_offset;\r
- CurBOBShape->y_offset = Shape->y_offset;\r
- CurBOBShape->priority = priority;\r
- CurBOBShape->sprflags = sprflags;\r
- CurBOBShape->class = Class;\r
- return(true);\r
- }\r
- }\r
- return(false);\r
-\r
-#pragma warn +pia\r
-\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// RemoveBOBShape() - Removes a sprite from a BOBList.\r
-//\r
-// RETURNS : true = Success / false = Failure (shape not found)\r
-//\r
-boolean RemoveBOBShape(objtype *obj, shapeclass Class)\r
-{\r
- struct BOB_Shape *CurBOBShape = NULL;\r
-\r
-#pragma warn -pia\r
-\r
- if (CurBOBShape = obj->nextshape)\r
- {\r
- while ((CurBOBShape->class != Class) && (!CurBOBShape->class) && CurBOBShape)\r
- {\r
- CurBOBShape = CurBOBShape->nextshape;\r
- }\r
-\r
- if (CurBOBShape)\r
- {\r
- CurBOBShape->class = noshape;\r
- return(true);\r
- }\r
- }\r
- return(false);\r
-\r
-#pragma warn +pia\r
-\r
-}\r
-\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// RemoveBOBList() - Removes an entire BOBList attached to an object.\r
-//\r
-//\r
-void RemoveBOBList(objtype *obj)\r
-{\r
- struct BOB_Shape *CurBOBShape;\r
-\r
-#pragma warn -pia\r
-\r
- if (CurBOBShape = obj->nextshape)\r
- {\r
- // Treverse down BOBList looking for a sprite with the same class\r
- // OR an empty shape struct to store the new shape.\r
-\r
- while (CurBOBShape)\r
- {\r
- if (CurBOBShape->class)\r
- {\r
- CurBOBShape->class = noshape;\r
- RF_RemoveSprite (&CurBOBShape->sprite);\r
- }\r
- CurBOBShape = CurBOBShape->nextshape;\r
- }\r
- }\r
-\r
-#pragma warn +pia\r
-\r
-}\r
-\r
-\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// InitBOBList() -- This initializes a BOB list for all the possible shapes\r
-// attached at one time. This is done with an array of\r
-// BOB_Shape structs and links the 'nextshape' pointer to\r
-// to the next element.\r
-//\r
-//\r
-void InitBOBList(objtype *obj, struct BOB_Shape *BOB_Shape, short NumElements)\r
-{\r
- struct BOB_Shape *CurShape;\r
- short loop;\r
-\r
- obj->nextshape = BOB_Shape;\r
-\r
- for (loop=1;loop<NumElements;loop++)\r
- {\r
- CurShape = BOB_Shape++;\r
- CurShape->nextshape = BOB_Shape;\r
- }\r
-\r
- BOB_Shape->nextshape = NULL;\r
-}\r
-\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// RefreshBOBList() -- This routine updates all sprites attached to the\r
-// BOBList and refreshes there position in the sprite\r
-// list.\r
-//\r
-void RefreshBOBList(objtype *obj)\r
-{\r
- struct BOB_Shape *Shape;\r
-\r
- Shape = obj->nextshape;\r
-\r
- while (Shape)\r
- {\r
- if (Shape->class)\r
- RF_PlaceSprite(&Shape->sprite,obj->x+Shape->x_offset,obj->y+Shape->y_offset, Shape->shapenum, spritedraw,Shape->priority,Shape->sprflags);\r
- Shape = Shape->nextshape;\r
- }\r
-}\r
-#endif\r
-\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-// InitBufferedIO()\r
-//--------------------------------------------------------------------------\r
-memptr InitBufferedIO(int handle, BufferedIO *bio)\r
-{\r
- bio->handle = handle;\r
- bio->offset = BIO_BUFFER_LEN;\r
- bio->status = 0;\r
- MM_GetPtr(&bio->buffer,BIO_BUFFER_LEN);\r
-\r
- return(bio->buffer);\r
-}\r
-\r
-//--------------------------------------------------------------------------\r
-// FreeBufferedIO()\r
-//--------------------------------------------------------------------------\r
-void FreeBufferedIO(BufferedIO *bio)\r
-{\r
- if (bio->buffer)\r
- MM_FreePtr(&bio->buffer);\r
-}\r
-\r
-//--------------------------------------------------------------------------\r
-// bio_readch()\r
-//--------------------------------------------------------------------------\r
-byte bio_readch(BufferedIO *bio)\r
-{\r
- byte far *buffer;\r
-\r
- if (bio->offset == BIO_BUFFER_LEN)\r
- {\r
- bio->offset = 0;\r
- bio_fillbuffer(bio);\r
- }\r
-\r
- buffer = MK_FP(bio->buffer,bio->offset++);\r
-\r
- return(*buffer);\r
-}\r
-\r
-//--------------------------------------------------------------------------\r
-// bio_fillbuffer()\r
-//\r
-// BUGS (Not really bugs... More like RULES!)\r
-//\r
-// 1) This code assumes BIO_BUFFER_LEN is no smaller than\r
-// NEAR_BUFFER_LEN!!\r
-//\r
-// 2) BufferedIO.status should be altered by this code to report\r
-// read errors, end of file, etc... If you know how big the file\r
-// is you're reading, determining EOF should be no problem.\r
-//\r
-//--------------------------------------------------------------------------\r
-void bio_fillbuffer(BufferedIO *bio)\r
-{\r
- #define NEAR_BUFFER_LEN (64)\r
- byte near_buffer[NEAR_BUFFER_LEN];\r
- short bio_length,bytes_read,bytes_requested;\r
-\r
- bytes_read = 0;\r
- bio_length = BIO_BUFFER_LEN;\r
- while (bio_length)\r
- {\r
- if (bio_length > NEAR_BUFFER_LEN-1)\r
- bytes_requested = NEAR_BUFFER_LEN;\r
- else\r
- bytes_requested = bio_length;\r
-\r
- read(bio->handle,near_buffer,bytes_requested);\r
- _fmemcpy(MK_FP(bio->buffer,bytes_read),near_buffer,bytes_requested);\r
-\r
- bio_length -= bytes_requested;\r
- bytes_read += bytes_requested;\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SwapLong()\r
-//\r
-void SwapLong(long far *Var)\r
-{\r
- asm les bx,Var\r
- asm mov ax,[es:bx]\r
- asm xchg ah,al\r
- asm xchg ax,[es:bx+2]\r
- asm xchg ah,al\r
- asm mov [es:bx],ax\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SwapWord()\r
-//\r
-void SwapWord(unsigned int far *Var)\r
-{\r
- asm les bx,Var\r
- asm mov ax,[es:bx]\r
- asm xchg ah,al\r
- asm mov [es:bx],ax\r
-}\r
-\r
-\r
-#if 0\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// LoadShape()\r
-//\r
-int LoadShape(char *Filename,struct Shape *SHP)\r
-{\r
- #define CHUNK(Name) (*ptr == *Name) && \\r
- (*(ptr+1) == *(Name+1)) && \\r
- (*(ptr+2) == *(Name+2)) && \\r
- (*(ptr+3) == *(Name+3))\r
-\r
-\r
- int RT_CODE;\r
-// struct ffblk ffblk;\r
- FILE *fp;\r
- char CHUNK[5];\r
- char far *ptr;\r
- memptr IFFfile = NULL;\r
- unsigned long FileLen, size, ChunkLen;\r
- int loop;\r
-\r
-\r
- RT_CODE = 1;\r
-\r
- // Decompress to ram and return ptr to data and return len of data in\r
- // passed variable...\r
-\r
- if (!(FileLen = BLoad(Filename,&IFFfile)))\r
- TrashProg("Can't load Compressed Shape - Possibly corrupt file!");\r
-\r
- // Evaluate the file\r
- //\r
- ptr = MK_FP(IFFfile,0);\r
- if (!CHUNK("FORM"))\r
- goto EXIT_FUNC;\r
- ptr += 4;\r
-\r
- FileLen = *(long far *)ptr;\r
- SwapLong((long far *)&FileLen);\r
- ptr += 4;\r
-\r
- if (!CHUNK("ILBM"))\r
- goto EXIT_FUNC;\r
- ptr += 4;\r
-\r
- FileLen += 4;\r
- while (FileLen)\r
- {\r
- ChunkLen = *(long far *)(ptr+4);\r
- SwapLong((long far *)&ChunkLen);\r
- ChunkLen = (ChunkLen+1) & 0xFFFFFFFE;\r
-\r
- if (CHUNK("BMHD"))\r
- {\r
- ptr += 8;\r
- SHP->bmHdr.w = ((struct BitMapHeader far *)ptr)->w;\r
- SHP->bmHdr.h = ((struct BitMapHeader far *)ptr)->h;\r
- SHP->bmHdr.x = ((struct BitMapHeader far *)ptr)->x;\r
- SHP->bmHdr.y = ((struct BitMapHeader far *)ptr)->y;\r
- SHP->bmHdr.d = ((struct BitMapHeader far *)ptr)->d;\r
- SHP->bmHdr.trans = ((struct BitMapHeader far *)ptr)->trans;\r
- SHP->bmHdr.comp = ((struct BitMapHeader far *)ptr)->comp;\r
- SHP->bmHdr.pad = ((struct BitMapHeader far *)ptr)->pad;\r
- SwapWord(&SHP->bmHdr.w);\r
- SwapWord(&SHP->bmHdr.h);\r
- SwapWord(&SHP->bmHdr.x);\r
- SwapWord(&SHP->bmHdr.y);\r
- ptr += ChunkLen;\r
- }\r
- else\r
- if (CHUNK("BODY"))\r
- {\r
- ptr += 4;\r
- size = *((long far *)ptr);\r
- ptr += 4;\r
- SwapLong((long far *)&size);\r
- SHP->BPR = (SHP->bmHdr.w+7) >> 3;\r
- MM_GetPtr(&SHP->Data,size);\r
- if (!SHP->Data)\r
- goto EXIT_FUNC;\r
- movedata(FP_SEG(ptr),FP_OFF(ptr),FP_SEG(SHP->Data),0,size);\r
- ptr += ChunkLen;\r
-\r
- break;\r
- }\r
- else\r
- ptr += ChunkLen+8;\r
-\r
- FileLen -= ChunkLen+8;\r
- }\r
-\r
- RT_CODE = 0;\r
-\r
-EXIT_FUNC:;\r
- if (IFFfile)\r
- {\r
-// segptr = (memptr)FP_SEG(IFFfile);\r
- MM_FreePtr(&IFFfile);\r
- }\r
-\r
- return (RT_CODE);\r
-}\r
-\r
-#endif\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// FreeShape()\r
-//\r
-void FreeShape(struct Shape *shape)\r
-{\r
- if (shape->Data)\r
- MM_FreePtr(&shape->Data);\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// UnpackEGAShapeToScreen()\r
-//\r
-int UnpackEGAShapeToScreen(struct Shape *SHP,int startx,int starty)\r
-{\r
- int currenty;\r
- signed char n, Rep, far *Src, far *Dst[8], loop, Plane;\r
- unsigned int BPR, Height;\r
- boolean NotWordAligned;\r
-\r
- NotWordAligned = SHP->BPR & 1;\r
- startx>>=3;\r
- Src = MK_FP(SHP->Data,0);\r
- currenty = starty;\r
- Plane = 0;\r
- Height = SHP->bmHdr.h;\r
- while (Height--)\r
- {\r
- Dst[0] = (MK_FP(0xA000,displayofs));\r
- Dst[0] += ylookup[currenty];\r
- Dst[0] += startx;\r
- for (loop=1; loop<SHP->bmHdr.d; loop++)\r
- Dst[loop] = Dst[0];\r
-\r
-\r
- for (Plane=0; Plane<SHP->bmHdr.d; Plane++)\r
- {\r
- outport(0x3c4,((1<<Plane)<<8)|2);\r
-\r
- BPR = ((SHP->BPR+1) >> 1) << 1; // IGNORE WORD ALIGN\r
- while (BPR)\r
- {\r
- if (SHP->bmHdr.comp)\r
- n = *Src++;\r
- else\r
- n = BPR-1;\r
-\r
- if (n < 0)\r
- {\r
- if (n != -128)\r
- {\r
- n = (-n)+1;\r
- BPR -= n;\r
- Rep = *Src++;\r
- if ((!BPR) && (NotWordAligned)) // IGNORE WORD ALIGN\r
- n--;\r
-\r
- while (n--)\r
- *Dst[Plane]++ = Rep;\r
- }\r
- else\r
- BPR--;\r
- }\r
- else\r
- {\r
- n++;\r
- BPR -= n;\r
- if ((!BPR) && (NotWordAligned)) // IGNORE WORD ALIGN\r
- n--;\r
-\r
- while (n--)\r
- *Dst[Plane]++ = *Src++;\r
-\r
- if ((!BPR) && (NotWordAligned)) // IGNORE WORD ALIGN\r
- Src++;\r
- }\r
- }\r
- }\r
- currenty++;\r
- }\r
-\r
- return(0);\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// GetKeyChoice()\r
-//\r
-char GetKeyChoice(char *choices,boolean clear)\r
-{\r
- extern void DoEvents(void);\r
-\r
- boolean waiting;\r
- char *s,*ss;\r
-\r
- IN_ClearKeysDown();\r
-\r
- waiting = true;\r
- while (waiting)\r
- {\r
- s = choices;\r
- while (*s)\r
- {\r
- if (Keyboard[*s++])\r
- {\r
- waiting=false;\r
- break;\r
- }\r
- }\r
- }\r
-\r
- IN_ClearKeysDown();\r
-\r
- return(*(--s));\r
-}\r
-\r
-#if 0\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// AnimateObj()\r
-//\r
-boolean AnimateObj(objtype *obj)\r
-{\r
- boolean Done;\r
-\r
- Done = false;\r
-\r
- if (obj->animtype == at_NONE) // Animation finished?\r
- return(true); // YEP!\r
-\r
- if (obj->animdelay) // Check animation delay.\r
- {\r
- obj->animdelay -= tics;\r
- if (obj->animdelay < 0)\r
- obj->animdelay = 0;\r
- return(false);\r
- }\r
-\r
- switch (obj->animtype) // Animate this object!\r
- {\r
- case at_ONCE:\r
- case at_CYCLE:\r
- switch (obj->animdir)\r
- {\r
- case at_FWD:\r
- if (obj->curframe < obj->maxframe)\r
- AdvanceAnimFWD(obj);\r
- else\r
- if (obj->animtype == at_CYCLE)\r
- {\r
- obj->curframe = 0; // RESET CYCLE ANIMATION\r
- obj->animdelay=1;\r
- }\r
- else\r
- {\r
- obj->animtype = at_NONE; // TERMINATE ONCE ANIM\r
- Done = true;\r
- }\r
- break;\r
-\r
- case at_REV:\r
- if (obj->curframe > 0)\r
- AdvanceAnimREV(obj);\r
- else\r
- if (obj->animtype == at_CYCLE)\r
- {\r
- obj->curframe = obj->maxframe; // RESET CYCLE ANIMATION\r
- obj->animdelay = 1;\r
- }\r
- else\r
- {\r
- obj->animtype = at_NONE; // TERMINATE ONCE ANIM\r
- Done = true;\r
- }\r
- break; // REV\r
- }\r
- break;\r
-\r
- case at_REBOUND:\r
- switch (obj->animdir)\r
- {\r
- case at_FWD:\r
- if (obj->curframe < obj->maxframe)\r
- AdvanceAnimFWD(obj);\r
- else\r
- {\r
- obj->animdir = at_REV;\r
- obj->animdelay = 1;\r
- }\r
- break;\r
-\r
- case at_REV:\r
- if (obj->curframe > 0)\r
- AdvanceAnimREV(obj);\r
- else\r
- {\r
- obj->animdir = at_FWD;\r
- obj->animdelay = 1;\r
- Done = true;\r
- }\r
- break;\r
- }\r
- break; /* REBOUND */\r
-\r
- case at_WAIT:\r
- Done = true;\r
- break;\r
- }\r
-\r
- return(Done);\r
-}\r
-\r
-void AdvanceAnimFWD(objtype *obj) // Advances a Frame of ANIM for ONCE,CYCLE, REBOUND\r
-{\r
- obj->curframe++; // INC frames\r
- obj->animdelay = obj->maxdelay; // Init Delay Counter.\r
- obj->needtoreact = true;\r
-}\r
-\r
-\r
-void AdvanceAnimREV(objtype *obj) // Advances a Frame of ANIM for ONCE,CYCLE, REBOUND\r
-{\r
- obj->curframe--; // DEC frames\r
- obj->animdelay = obj->maxdelay; // Init Delay Counter.\r
- obj->needtoreact = true;\r
-}\r
-#endif\r
-\r
-#if 0\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// LoadASArray() - Load an array of audio samples in FAR memory.\r
-//\r
-void LoadASArray(struct Sample *ASArray)\r
-{\r
- int loop = 0;\r
-\r
- while (ASArray[loop].filename)\r
- {\r
- if (!BLoad(ASArray[loop].filename,(memptr *)&ASArray[loop].data))\r
- TrashProg("Unable to load sample in LoadASArray()");\r
- loop++;\r
- }\r
-}\r
-\r
-\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// FreeASArray() - Frees an ASArray from memory that has been loaded with\r
-// LoadASArray()\r
-//\r
-void FreeASArray(struct Sample *ASArray)\r
-{\r
- unsigned loop = 0;\r
-\r
- while (ASArray[loop].data)\r
- {\r
- MM_SetPurge((memptr *)&ASArray[loop++].data,3);\r
- MM_FreePtr((memptr *)&ASArray[loop++].data);\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// GE_LoadAllDigiSounds() - This is a hook that CA_LoadAllSounds()\r
-// calls to load all of the Digitized sounds for\r
-// Sound Blaster & Sound Source.\r
-//\r
-// NOTE : This stub would do any other necessary routines for DigiSounds\r
-// specific to GAMERS EDGE code. (Keeping seperate from ID's)\r
-//\r
-void GE_LoadAllDigiSounds()\r
-{\r
- LoadASArray(DigiSounds);\r
-}\r
-\r
-\r
-\r
-/////////////////////////////////////////////////////////////////////////\r
-//\r
-// GE_FreeAllDigiSounds() -- This is a hook that CA_LoadAllSounds()\r
-// calls to free all digitized sounds for\r
-// which ever hardware and allow for any necessary\r
-// clean up.\r
-//\r
-//\r
-// NOTE : This stub would do any other necessary routines for DigiSounds\r
-// specific to GAMERS EDGE code. (Keeping seperate from ID's)\r
-//\r
-void GE_FreeAllDigiSounds()\r
-{\r
- FreeASArray(DigiSounds);\r
-}\r
-\r
-\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// GE_LoadAllSounds() - Loads ALL sounds needed for detected hardware.\r
-//\r
-void GE_LoadAllSounds()\r
-{\r
- unsigned i,start;\r
-\r
- start = STARTPCSOUNDS;\r
- for (i=0;i<NUMSOUNDS;i++,start++)\r
- CA_CacheAudioChunk (start);\r
-\r
- if (AdLibPresent)\r
- {\r
- start = STARTADLIBSOUNDS;\r
- for (i=0;i<NUMSOUNDS;i++,start++)\r
- CA_CacheAudioChunk (start);\r
- }\r
-\r
- if (SoundBlasterPresent)\r
- LoadASArray(DigiSounds);\r
-}\r
-\r
-\r
-//////////////////////////////////////////////////////////////////////////\r
-//\r
-// GE_PurgeAllSounds() - Frees all sounds that were loaded.\r
-//\r
-void GE_PurgeAllSounds()\r
-{\r
- unsigned start,i;\r
-\r
- start = STARTPCSOUNDS;\r
- for (i=0;i<NUMSOUNDS;i++,start++)\r
- if (audiosegs[start])\r
- MM_SetPurge (&(memptr)audiosegs[start],3); // make purgable\r
-\r
-\r
- if (AdLibPresent)\r
- {\r
- start = STARTADLIBSOUNDS;\r
- for (i=0;i<NUMSOUNDS;i++,start++)\r
- if (audiosegs[start])\r
- MM_SetPurge (&(memptr)audiosegs[start],3); // make purgable\r
- }\r
-\r
- if (SoundBlasterPresent)\r
- GE_FreeAllDigiSounds();\r
-}\r
-\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// PlaySample() -- Plays a DIGITIZED sample using SoundBlaster OR SoundSource\r
-//\r
-// PARAMETERS : Sample Number (Corresponding to ASArray "DigiSounds[]".\r
-//\r
-void PlaySample(unsigned SampleNum)\r
-{\r
-\r
- if (!DigiSounds[SampleNum].data)\r
- TrashProg("PlaySample - Trying to play an unloaded digi sound!");\r
-\r
-\r
- switch (SoundMode) // external variable in ID_SD for sound mode..\r
- {\r
- case sdm_SoundBlaster:\r
- case sdm_SoundBlasterAdLib:\r
- SDL_SBPlaySample(MK_FP(DigiSounds[SampleNum].data,0));\r
- break;\r
-\r
- default:\r
- TrashProg("PlaySample() - incorrect SoundMode for PlaySample()");\r
- break;\r
- }\r
-}\r
-\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// SelectDigiAudio() -- This routine intergrates multi sound hardware with\r
-// id's routines.\r
-//\r
-void SelectDigiAudio(AudioDeviceType Device)\r
-{\r
- switch (Device)\r
- {\r
- case ged_SoundSource:\r
- case ged_SoundBlaster:\r
- break;\r
- }\r
-}\r
-#endif\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// DisplayGameList()\r
-//\r
-void DisplayGameList(short winx, short winy, short list_width, short list_height)\r
-{\r
- #define SPACES 2\r
-\r
- short width,col,row,orgcol,games_printed=0,h;\r
-\r
- // Possibly shrink window.\r
- //\r
- h = (NumGames / list_width) + ((NumGames % list_width) > 0);\r
- if (h < list_height)\r
- list_height = h;\r
-\r
- // Open window and print header...\r
- //\r
- US_DrawWindow(winx,winy,list_width*(8+SPACES*2),list_height+3);\r
- US_CPrintLine("LIST OF SAVED GAMES");\r
- US_Print("\n");\r
-\r
- col = orgcol = PrintX;\r
- row = PrintY;\r
-\r
- // Display as many 'save game' files as can fit in the window.\r
- //\r
- width = list_width;\r
- while ((games_printed<NumGames) && (list_height))\r
- {\r
- // Print filename and padding spaces.\r
- //\r
- US_Printxy(col+(SPACES*8),row,GameListNames[games_printed]);\r
- col += 8*((SPACES*2)+8);\r
-\r
- // Check for end-of-line or end-of-window.\r
- //\r
- width--;\r
- if (!width)\r
- {\r
- col = orgcol;\r
- row += 8;\r
- width = list_width;\r
- list_height--;\r
- US_Print("\n");\r
- }\r
-\r
- games_printed++;\r
- }\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// ReadGameList()\r
-//\r
-void ReadGameList()\r
-{\r
- struct ffblk ffblk;\r
- short done,len;\r
-\r
- NumGames = -1;\r
- done = findfirst("*.sav",&ffblk,0);\r
-\r
- while (!done)\r
- {\r
- if (NumGames == MAX_GAMELIST_NAMES)\r
- memcpy(GameListNames,GameListNames[1],MAX_GAMELIST_NAMES*sizeof(GameListNames[0]));\r
- else\r
- NumGames++;\r
-\r
- fnsplit(ffblk.ff_name,NULL,NULL,GameListNames[NumGames],NULL);\r
-\r
- done=findnext(&ffblk);\r
- }\r
-\r
- NumGames++;\r
-}\r
-\r
-#if 0\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// CenterObj()\r
-//\r
-void CenterObj(objtype *obj, unsigned x, unsigned y)\r
-{\r
- spritetabletype far *sprite;\r
- unsigned width, height;\r
-\r
- sprite=&spritetable[obj->baseshape+obj->curframe-STARTSPRITES];\r
-\r
- width = (sprite->xh-sprite->xl+(1<<G_P_SHIFT)) >> 1;\r
- if (obj->sprflags&sf_vertflip)\r
- {\r
- height = (sprite->yl-(sprite->height<<G_P_SHIFT) + sprite->yh+(1<<G_P_SHIFT)) >> 1;\r
- }\r
- else\r
- height = (sprite->yh-sprite->yl+(1<<G_P_SHIFT)) >> 1;\r
-\r
- obj->x = x-width;\r
- obj->y = y-height;\r
-}\r
-#endif\r
-\r
-#if 0\r
-//-------------------------------------------------------------------------\r
-// cacheout()\r
-//-------------------------------------------------------------------------\r
-void cacheout(short s,short e)\r
-{\r
- short i;\r
-\r
- for(i=(s);i<=(e);i++)\r
- {\r
- grneeded[i]&=~ca_levelbit;\r
- if (grsegs[i])\r
- MM_SetPurge(&grsegs[i],3);\r
- }\r
-\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// cachein()\r
-//-------------------------------------------------------------------------\r
-void cachein(short s,short e)\r
-{\r
- short i;\r
-\r
- for(i=(s);i<=(e);i++)\r
- {\r
- CA_MarkGrChunk(i);\r
- if (grsegs[i])\r
- MM_SetPurge(&grsegs[i],0);\r
- }\r
-}\r
-#endif\r
-\r
-#if 0\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// SetUpdateBlock()\r
-//\r
-void SetUpdateBlock(unsigned x,unsigned y,unsigned width,unsigned height,char refresh)\r
-{\r
- eraseblocktype *erase;\r
-\r
-#if 0 //SP unsure if this is needed\r
- x = (x+((MAPBORDER+MAPXLEFTOFFSET)<<4))>>3;\r
- y += ((MAPBORDER+MAPYTOPOFFSET)<<4);\r
-#else\r
- x = (x+(MAPBORDER<<4))>>3;\r
- y += (MAPBORDER<<4);\r
-#endif\r
- width >>= 3;\r
-\r
- if (refresh & 1)\r
- {\r
- erase = eraselistptr[0]++;\r
- erase->screenx=x;\r
- erase->screeny=y;\r
- erase->width=width;\r
- erase->height=height;\r
- }\r
-\r
- if (refresh & 2)\r
- {\r
- erase = eraselistptr[1]++;\r
- erase->screenx=x;\r
- erase->screeny=y;\r
- erase->width=width;\r
- erase->height=height;\r
- }\r
-}\r
-\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// ObjHeight\r
-//\r
-unsigned ObjHeight(objtype *obj)\r
-{\r
- spritetabletype far *sprite;\r
-\r
- sprite=&spritetable[obj->baseshape+obj->curframe-STARTSPRITES];\r
-\r
- if (obj->sprflags&sf_vertflip)\r
- {\r
- return((sprite->yl-(sprite->height<<G_P_SHIFT) + sprite->yh+(1<<G_P_SHIFT)) >> 1);\r
- }\r
- else\r
- return((sprite->yh-sprite->yl+(1<<G_P_SHIFT)) >> 1);\r
-}\r
-\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// ObjWidth\r
-//\r
-unsigned ObjWidth(objtype *obj)\r
-{\r
- spritetabletype far *sprite;\r
-\r
- sprite=&spritetable[obj->baseshape+obj->curframe-STARTSPRITES];\r
-\r
- return((sprite->xh-sprite->xl+(1<<G_P_SHIFT)) >> 1);\r
-}\r
-#endif\r
-\r
-#if 0\r
-//--------------------------------------------------------------------------\r
-// visible_on()\r
-//--------------------------------------------------------------------------\r
-boolean visible_on(objtype *obj)\r
-{\r
- if (!(obj->flags & of_visible))\r
- {\r
- obj->needtoreact=true;\r
- obj->flags |= of_visible;\r
- return(true);\r
- }\r
-\r
- return(false);\r
-}\r
-\r
-//--------------------------------------------------------------------------\r
-// visible_off()\r
-//--------------------------------------------------------------------------\r
-boolean visible_off(objtype *obj)\r
-{\r
- if (obj->flags & of_visible)\r
- {\r
- obj->needtoreact=true;\r
- obj->flags &= ~of_visible;\r
- return(true);\r
- }\r
-\r
- return(false);\r
-}\r
-#endif\r
-\r
-\r
-/*\r
-===================\r
-=\r
-= FizzleFade\r
-=\r
-===================\r
-*/\r
-\r
-#define PIXPERFRAME 10000\r
-\r
-void FizzleFade (unsigned source, unsigned dest,\r
- unsigned width,unsigned height, boolean abortable)\r
-{\r
- unsigned drawofs,pagedelta;\r
- unsigned char maskb[8] = {1,2,4,8,16,32,64,128};\r
- unsigned x,y,p,frame;\r
- long rndval;\r
- ScanCode lastLastScan=LastScan=0;\r
-\r
- width--;\r
- height--;\r
-\r
- pagedelta = dest-source;\r
-// VW_SetScreen (dest,0);\r
- rndval = 1;\r
- y = 0;\r
-\r
-asm mov es,[screenseg]\r
-asm mov dx,SC_INDEX\r
-asm mov al,SC_MAPMASK\r
-asm out dx,al\r
-\r
- TimeCount=frame=0;\r
- do // while (1)\r
- {\r
- if ((abortable) || (Flags & FL_QUICK))\r
- {\r
- IN_ReadControl(0,&control);\r
- if (control.button0 || control.button1 || (lastLastScan != LastScan)\r
- || Keyboard[sc_Escape] || (Flags & FL_QUICK))\r
- {\r
- VW_ScreenToScreen (source,dest,(width+1)/8,height+1);\r
- goto exitfunc;\r
- }\r
- }\r
-\r
- for (p=0;p<PIXPERFRAME;p++)\r
- {\r
- //\r
- // seperate random value into x/y pair\r
- //\r
- asm mov ax,[WORD PTR rndval]\r
- asm mov dx,[WORD PTR rndval+2]\r
- asm mov bx,ax\r
- asm dec bl\r
- asm mov [BYTE PTR y],bl // low 8 bits - 1 = y xoordinate\r
- asm mov bx,ax\r
- asm mov cx,dx\r
- asm shr cx,1\r
- asm rcr bx,1\r
- asm shr bx,1\r
- asm shr bx,1\r
- asm shr bx,1\r
- asm shr bx,1\r
- asm shr bx,1\r
- asm shr bx,1\r
- asm shr bx,1\r
- asm mov [x],bx // next 9 bits = x xoordinate\r
- //\r
- // advance to next random element\r
- //\r
- asm shr dx,1\r
- asm rcr ax,1\r
- asm jnc noxor\r
- asm xor dx,0x0001\r
- asm xor ax,0x2000\r
-noxor:\r
- asm mov [WORD PTR rndval],ax\r
- asm mov [WORD PTR rndval+2],dx\r
-\r
- if (x>width || y>height)\r
- continue;\r
- drawofs = source+ylookup[y];\r
-\r
- asm mov cx,[x]\r
- asm mov si,cx\r
- asm and si,7\r
- asm mov dx,GC_INDEX\r
- asm mov al,GC_BITMASK\r
- asm mov ah,BYTE PTR [maskb+si]\r
- asm out dx,ax\r
-\r
- asm mov si,[drawofs]\r
- asm shr cx,1\r
- asm shr cx,1\r
- asm shr cx,1\r
- asm add si,cx\r
- asm mov di,si\r
- asm add di,[pagedelta]\r
-\r
- asm mov dx,GC_INDEX\r
- asm mov al,GC_READMAP // leave GC_INDEX set to READMAP\r
- asm out dx,al\r
-\r
- asm mov dx,SC_INDEX+1\r
- asm mov al,1\r
- asm out dx,al\r
- asm mov dx,GC_INDEX+1\r
- asm mov al,0\r
- asm out dx,al\r
-\r
- asm mov bl,[es:si]\r
- asm xchg [es:di],bl\r
-\r
- asm mov dx,SC_INDEX+1\r
- asm mov al,2\r
- asm out dx,al\r
- asm mov dx,GC_INDEX+1\r
- asm mov al,1\r
- asm out dx,al\r
-\r
- asm mov bl,[es:si]\r
- asm xchg [es:di],bl\r
-\r
- asm mov dx,SC_INDEX+1\r
- asm mov al,4\r
- asm out dx,al\r
- asm mov dx,GC_INDEX+1\r
- asm mov al,2\r
- asm out dx,al\r
-\r
- asm mov bl,[es:si]\r
- asm xchg [es:di],bl\r
-\r
- asm mov dx,SC_INDEX+1\r
- asm mov al,8\r
- asm out dx,al\r
- asm mov dx,GC_INDEX+1\r
- asm mov al,3\r
- asm out dx,al\r
-\r
- asm mov bl,[es:si]\r
- asm xchg [es:di],bl\r
-\r
- if (rndval == 1) // entire sequence has been completed\r
- goto exitfunc;\r
- }\r
-// frame++;\r
-// while (TimeCount<frame); // don't go too fast\r
-\r
- } while (1);\r
-\r
-exitfunc:;\r
- EGABITMASK(255);\r
- EGAMAPMASK(15);\r
- return;\r
-}\r
-\r
-#if 0\r
-//-------------------------------------------------------------------------\r
-// mprintf()\r
-//-------------------------------------------------------------------------\r
-void mprintf(char *msg, ...)\r
-{\r
- static char x=0;\r
- static char y=0;\r
- static char far *video = MK_FP(0xb000,0x0000);\r
- char buffer[100],*ptr;\r
-\r
- va_list(ap);\r
-\r
- va_start(ap,msg);\r
-\r
- vsprintf(buffer,msg,ap);\r
-\r
- ptr = buffer;\r
- while (*ptr)\r
- {\r
- switch (*ptr)\r
- {\r
- case '\n':\r
- if (y >= 23)\r
- {\r
- video -= (x<<1);\r
- _fmemcpy(MK_FP(0xb000,0x0000),MK_FP(0xb000,0x00a0),3840);\r
- }\r
- else\r
- {\r
- y++;\r
- video += ((80-x)<<1);\r
- }\r
- x=0;\r
- break;\r
-\r
- default:\r
- *video = *ptr;\r
- video[1] = 15;\r
- video += 2;\r
- x++;\r
- break;\r
- }\r
- ptr++;\r
- }\r
-\r
- va_end(ap);\r
-}\r
-#endif\r
-\r
-#if 0\r
-\r
-//--------------------------------------------------------------------------\r
-// FULL SCREEN REFRESH/ANIM MANAGERS\r
-//--------------------------------------------------------------------------\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// InitLatchRefresh() -- Loads an ILBM (JAMPAK'd) into the Master Latch\r
-// to be used as the background refresh screen...\r
-//\r
-void InitLatchRefresh(char *filename)\r
-{\r
- struct Shape RefreshShp;\r
- short yofs;\r
-\r
- VW_ClearVideo(0);\r
-\r
- if (LoadShape(filename,&RefreshShp))\r
- TrashProg("Can't load %s",filename);\r
-\r
- VW_SetLineWidth(RefreshShp.BPR);\r
-\r
- yofs = masterswap/SCREENWIDTH;\r
- MoveGfxDst(0,yofs); // Handle title screen\r
- UnpackEGAShapeToScreen(&RefreshShp,0,0);\r
- FreeShape(&RefreshShp);\r
-\r
- MoveScreen(0,0);\r
- VW_InitDoubleBuffer();\r
-\r
- RF_NewPosition(0,0);\r
-\r
- RF_Refresh();\r
-\r
- SetUpdateBlock(0,0,RefreshShp.bmHdr.w,RefreshShp.bmHdr.h,3);\r
-}\r
-\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// InitFullScreenAnim() -- Initialize ALL necessary functions for full screen\r
-// animation types.\r
-//\r
-// filename - filename for background lbm.\r
-// SpawnAll - spawn function to call to spawn all inital objects..\r
-//\r
-void InitFullScreenAnim(char *filename, void (*SpawnAll)())\r
-{\r
- unsigned old_flags;\r
-\r
- old_flags = GE_SystemFlags.flags;\r
- GE_SystemFlags.flags &= ~(GEsf_Tiles | GEsf_Panning | GEsf_RefreshVec);\r
-\r
- CA_ClearMarks();\r
-\r
- RFL_InitSpriteList();\r
- InitObjArray();\r
-\r
- if (SpawnAll)\r
- SpawnAll();\r
-\r
- CA_CacheMarks(NULL);\r
-\r
- CalcInactivate();\r
- CalcSprites();\r
-\r
- InitLatchRefresh(filename);\r
-\r
- RF_ForceRefresh();\r
- RF_ForceRefresh();\r
-\r
- GE_SystemFlags.flags = old_flags;\r
-}\r
-\r
-\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// DoFullScreenAnim() -- a General "Do-Every-Thing" function that\r
-// displays a full screen animation...\r
-//\r
-// filename - Filename of background lbm\r
-// SpawnAll - Function to call to spawn all inital objects (REQUIRED)\r
-// CheckKey - Function to call every cycle - The function called must\r
-// return a value of greater than zero (0) to terminate the\r
-// animation cycle. (REQUIRED)\r
-// CleanUp - Function to call upon exiting the animation. (OPTIONAL)\r
-//\r
-void DoFullScreenAnim(char *filename, void (*SpawnAll)(), short (*CheckKey)(),void (*CleanUp)())\r
-{\r
- unsigned old_flags;\r
- boolean ExitAnim = false;\r
-\r
- // Save off the current system flags....\r
-\r
- old_flags = GE_SystemFlags.flags;\r
- GE_SystemFlags.flags &= ~(GEsf_Tiles | GEsf_Panning);\r
-\r
-// randomize();\r
-\r
- // Init refresh latch screen, initalize all object, and setup video mode.\r
-\r
- InitFullScreenAnim(filename,SpawnAll);\r
-\r
- VW_FadeIn();\r
-\r
- while (!ExitAnim)\r
- {\r
- CalcInactivate();\r
- CalcSprites();\r
- RF_Refresh();\r
-\r
- ExitAnim = (boolean)CheckKey();\r
- }\r
-\r
-// RemoveBOBList(player);\r
-// CalcInactivate();\r
-\r
- if (CleanUp)\r
- CleanUp();\r
-\r
- // Restore old system flags...\r
-\r
- GE_SystemFlags.flags = old_flags;\r
-}\r
-\r
-#endif\r
-\r
-//--------------------------------------------------------------------------\r
-// FindFile()\r
-//--------------------------------------------------------------------------\r
-boolean FindFile(char *filename,char *disktext,char disknum)\r
-{\r
- extern boolean splitscreen;\r
-\r
- char command[100];\r
- char choices[]={sc_Escape,sc_Space,0},drive[2];\r
- boolean fadeitout=false,rt_code=2;\r
-\r
- if (!disktext)\r
- disktext = GAMENAME;\r
- drive[0] = getdisk() + 'A';\r
- drive[1] = 0;\r
- while (rt_code == 2)\r
- {\r
- if (Verify(filename))\r
- rt_code = true;\r
- else\r
- {\r
- if (ge_textmode)\r
- {\r
- clrscr();\r
- gotoxy(1,1);\r
- printf("\nInsert %s disk %d into drive %s.\n",disktext,disknum,drive);\r
- printf("Press SPACE to continue, ESC to abort.\n");\r
- }\r
- else\r
- {\r
- if (splitscreen)\r
- {\r
- bufferofs = displayofs = screenloc[screenpage];\r
- CenterWindow(38,5);\r
- }\r
- else\r
- {\r
- bufferofs = displayofs = 0;\r
- US_CenterWindow(38,5);\r
- }\r
-\r
- strcpy(command,"\nInsert ");\r
- strcat(command,disktext);\r
- strcat(command," disk");\r
- if (disknum != -1)\r
- {\r
- strcat(command," ");\r
- itoa(disknum,command+strlen(command),10);\r
- }\r
- strcat(command," into drive ");\r
- strcat(command,drive);\r
- strcat(command,".");\r
- US_CPrint(command);\r
- US_CPrint("Press SPACE to continue, ESC to abort.");\r
- }\r
-\r
- sound(300);\r
- VW_WaitVBL(20);\r
- nosound();\r
-\r
- if (!ge_textmode)\r
- {\r
- if (screenfaded)\r
- {\r
- VW_FadeIn();\r
- fadeitout=true;\r
- }\r
- }\r
- if (GetKeyChoice(choices,true) == sc_Escape)\r
- rt_code = false;\r
- }\r
- }\r
-\r
- if (!ge_textmode)\r
- if (fadeitout)\r
- VW_FadeOut();\r
-\r
- return(rt_code);\r
-}\r
-\r
-#if 0\r
-//--------------------------------------------------------------------------\r
-// CacheAll()\r
-//--------------------------------------------------------------------------\r
-void CacheAV(char *title)\r
-{\r
- if (Verify("EGAGRAPH."EXT))\r
- {\r
- CA_CacheMarks(title);\r
- if (!FindFile("EGAGRAPH."EXT,AUDIO_DISK))\r
- TrashProg("Can't find graphics files.");\r
-\r
-// cache in audio\r
-\r
- current_disk = AUDIO_DISK;\r
- }\r
- else\r
- {\r
-\r
-// cache in audio\r
-\r
- if (!FindFile("EGAGRAPH."EXT,VIDEO_DISK))\r
- TrashProg("Can't find audio files.");\r
- CA_CacheMarks(title);\r
-\r
- current_disk = VIDEO_DISK;\r
- }\r
-}\r
-#endif\r
-\r
-#ifdef TEXT_PRESENTER\r
-//--------------------------------------------------------------------------\r
-//\r
-// TEXT PRESENTER CODE\r
-//\r
-//--------------------------------------------------------------------------\r
-\r
-typedef enum pi_stype {pis_pic2x,pis_latch_pic} pi_stype;\r
-\r
-\r
-typedef struct { // 4 bytes\r
- unsigned shapenum;\r
- pi_stype shape_type;\r
-} pi_shape_info;\r
-\r
-#define pia_active 0x01\r
-\r
-typedef struct { // 10 bytes\r
- char baseshape;\r
- char frame;\r
- char maxframes;\r
- short delay;\r
- short maxdelay;\r
- short x,y;\r
-} pi_anim_info;\r
-\r
- #define PI_CASE_SENSITIVE\r
-\r
- #define PI_RETURN_CHAR '\n'\r
- #define PI_CONTROL_CHAR '^'\r
-\r
- #define PI_CNVT_CODE(c1,c2) ((c1)|(c2<<8))\r
-\r
-// shape table provides a way for the presenter to access and\r
-// display any shape.\r
-//\r
-pi_shape_info far pi_shape_table[] = {\r
-\r
- {BOLTOBJPIC,pis_pic2x}, // 0\r
- {NUKEOBJPIC,pis_pic2x},\r
- {SKELETON_1PIC,pis_pic2x},\r
- {EYE_WALK1PIC,pis_pic2x},\r
- {ZOMB_WALK1PIC,pis_pic2x},\r
-\r
- {TIMEOBJ1PIC,pis_pic2x}, // 5\r
- {POTIONOBJPIC,pis_pic2x},\r
- {RKEYOBJPIC,pis_pic2x},\r
- {YKEYOBJPIC,pis_pic2x},\r
- {GKEYOBJPIC,pis_pic2x},\r
-\r
- {BKEYOBJPIC,pis_pic2x}, // 10\r
- {RGEM1PIC,pis_pic2x},\r
- {GGEM1PIC,pis_pic2x},\r
- {BGEM1PIC,pis_pic2x},\r
- {YGEM1PIC,pis_pic2x},\r
-\r
- {PGEM1PIC,pis_pic2x}, // 15\r
- {CHESTOBJPIC,pis_pic2x},\r
- {PSHOT1PIC,pis_pic2x},\r
- {RED_DEMON1PIC,pis_pic2x},\r
- {MAGE1PIC,pis_pic2x},\r
-\r
- {BAT1PIC,pis_pic2x}, // 20\r
- {GREL1PIC,pis_pic2x},\r
- {GODESS_WALK1PIC,pis_pic2x},\r
- {ANT_WALK1PIC,pis_pic2x},\r
- {FATDEMON_WALK1PIC,pis_pic2x},\r
-\r
- {SUCCUBUS_WALK1PIC,pis_pic2x}, //25\r
- {TREE_WALK1PIC,pis_pic2x},\r
- {DRAGON_WALK1PIC,pis_pic2x},\r
- {BUNNY_LEFT1PIC,pis_pic2x},\r
-\r
-};\r
-\r
-// anim table holds info about each different animation.\r
-//\r
-pi_anim_info far pi_anim_table[] = {{0,0,3,0,10}, // 0 BOLT\r
- {1,0,3,0,10}, // NUKE\r
- {2,0,4,0,10}, // SKELETON\r
- {3,0,3,0,10}, // EYE\r
- {4,0,3,0,10}, // ZOMBIE\r
-\r
- {5,0,2,0,10}, // 5 FREEZE TIME\r
- {11,0,2,0,10}, // RED GEM\r
- {12,0,2,0,10}, // GREEN GEM\r
- {13,0,2,0,10}, // BLUE GEM\r
- {14,0,2,0,10}, // YELLOW GEM\r
-\r
- {15,0,2,0,10}, // 10 PURPLE GEM\r
- {17,0,2,0,10}, // PLAYER'S SHOT\r
- {18,0,3,0,10}, // RED DEMON\r
- {19,0,2,0,10}, // MAGE\r
- {20,0,4,0,10}, // BAT\r
-\r
- {21,0,2,0,10}, // 15 GRELMINAR\r
- {22,0,3,0,10}, // GODESS\r
- {23,0,3,0,10}, // ANT\r
- {24,0,4,0,10}, // FAT DEMON\r
- {25,0,4,0,10}, // SUCCUBUS\r
-\r
- {26,0,2,0,10}, // 20 TREE\r
- {27,0,3,0,10}, // DRAGON\r
- {28,0,2,0,10}, // BUNNY\r
-};\r
-\r
-// anim list is created on the fly from the anim table...\r
-// this allows a single animation to be display in more than\r
-// one place...\r
-//\r
-pi_anim_info far pi_anim_list[PI_MAX_ANIMS];\r
-boolean pi_recursing=false;\r
-\r
-//--------------------------------------------------------------------------\r
-// Presenter() - DANGEROUS DAVE "Presenter()" is more up-to-date than this.\r
-//\r
-//\r
-// Active control codes:\r
-//\r
-// ^CE - center text between 'left margin' and 'right margin'\r
-// ^FCn - set font color\r
-// ^LMnnn - set left margin (if 'nnn' == "fff" uses current x)\r
-// ^RMnnn - set right margin (if 'nnn' == "fff" uses current x)\r
-// ^EP - end of page (waits for up/down arrow)\r
-// ^PXnnn - move x to coordinate 'n'\r
-// ^PYnnn - move y to coordinate 'n'\r
-// ^XX - exit presenter\r
-// ^LJ - left justify --\ ^RJ doesn't handle imbedded control\r
-// ^RJ - right justify --/ codes properly. Use with caution.\r
-// ^BGn - set background color\r
-// ^ANnn - define animation\r
-// ^SHnnn - display shape 'n' at current x,y\r
-//\r
-//\r
-// Future control codes:\r
-//\r
-// ^OBnnn - activate object 'n'\r
-// ^FL - flush to edges (whatever it's called)\r
-//\r
-//\r
-// Other info:\r
-//\r
-// All 'n' values are hex numbers (0 - f), case insensitive.\r
-// The number of N's listed is the number of digits REQUIRED by that control\r
-// code. (IE: ^LMnnn MUST have 3 values! --> 003, 1a2, 01f, etc...)\r
-//\r
-// If a line consists only of control codes, the cursor is NOT advanced\r
-// to the next line (the ending <CR><LF> is skipped). If just ONE non-control\r
-// code is added, the number "8" for example, then the "8" is displayed\r
-// and the cursor is advanced to the next line.\r
-//\r
-// ^CE must be on the same line as the text it should center!\r
-//\r
-//--------------------------------------------------------------------------\r
-void Presenter(PresenterInfo *pi)\r
-{\r
-#ifdef AMIGA\r
- XBitMap **font = pi->font;\r
-\r
- #define ch_width(ch) font[ch]->pad\r
- char font_height = font[0]->Rows;\r
-#else\r
- fontstruct _seg *font = (fontstruct _seg *)grsegs[STARTFONT];\r
-\r
- #define MAX_PB 150\r
- #define ch_width(ch) font->width[ch]\r
- char font_height = font->height-1; // "-1" squeezes font vertically\r
- char pb[MAX_PB];\r
- short length;\r
-#endif\r
-\r
- enum {jm_left,jm_right,jm_flush};\r
- char justify_mode = jm_left;\r
- boolean centering=false;\r
-\r
- short bgcolor = pi->bgcolor;\r
- short xl=pi->xl,yl=pi->yl,xh=pi->xh,yh=pi->yh;\r
- short cur_x = xl, cur_y = yl;\r
- char far *first_ch = pi->script[0];\r
-\r
- char far *scan_ch,temp;\r
- short scan_x,PageNum=0,numanims=0;\r
- boolean up_released=true,dn_released=true;\r
- boolean presenting=true,start_of_line=true;\r
-\r
-// if set background is first thing in file, make sure initial screen\r
-// clear uses this color.\r
-//\r
- if (!_fstrncmp(first_ch,"^BG",3))\r
- bgcolor = PI_VALUE(first_ch+3,1);\r
-\r
- if (!pi_recursing)\r
- {\r
- PurgeAllGfx();\r
- CachePage(first_ch);\r
- }\r
- VW_Bar(xl,yl,xh-xl+1,yh-yl+1,bgcolor);\r
-\r
- while (presenting)\r
- {\r
-//\r
-// HANDLE WORD-WRAPPING TEXT\r
-//\r
- if (*first_ch != PI_CONTROL_CHAR)\r
- {\r
- start_of_line = false;\r
-\r
- // Parse script until one of the following:\r
- //\r
- // 1) text extends beyond right margin\r
- // 2) NULL termination is reached\r
- // 3) PI_RETURN_CHAR is reached\r
- // 4) PI_CONTROL_CHAR is reached\r
- //\r
- scan_x = cur_x;\r
- scan_ch = first_ch;\r
- while ((scan_x+ch_width(*scan_ch) <= xh) && (*scan_ch) &&\r
- (*scan_ch != PI_RETURN_CHAR) && (*scan_ch != PI_CONTROL_CHAR))\r
- scan_x += ch_width(*scan_ch++);\r
-\r
- // if 'text extends beyond right margin', scan backwards for\r
- // a SPACE\r
- //\r
- if (scan_x+ch_width(*scan_ch) > xh)\r
- {\r
- short last_x = scan_x;\r
- char far *last_ch = scan_ch;\r
-\r
- while ((scan_ch != first_ch) && (*scan_ch != ' ') && (*scan_ch != PI_RETURN_CHAR))\r
- scan_x -= ch_width(*scan_ch--);\r
-\r
- if (scan_ch == first_ch)\r
- scan_ch = last_ch, scan_x = last_x;\r
- }\r
-\r
- // print current line\r
- //\r
-#ifdef AMIGA\r
- while (first_ch < scan_ch)\r
- {\r
- qBlit(font[*first_ch++],pi->dst,cur_x,cur_y);\r
-// qBlit(font[*first_ch],pi->dst,cur_x,cur_y);\r
-// cur_x += ch_width(*first_ch++);\r
- }\r
-#else\r
- temp = *scan_ch;\r
- *scan_ch = 0;\r
-\r
- if ((justify_mode == jm_right)&&(!centering))\r
- {\r
- unsigned width,height;\r
-\r
- VWL_MeasureString(first_ch,&width,&height,font);\r
- cur_x = xh-width;\r
- if (cur_x < xl)\r
- cur_x = xl;\r
- }\r
-\r
- px = cur_x;\r
- py = cur_y;\r
-\r
- length = scan_ch-first_ch+1; // USL_DrawString only works with\r
- if (length > MAX_PB)\r
- Quit("Presenter(): Print buffer string too long!");\r
- _fmemcpy(pb,first_ch,length); // near pointers...\r
-\r
- if (*first_ch != '\n')\r
- USL_DrawString(pb);\r
-\r
- *scan_ch = temp;\r
- first_ch = scan_ch;\r
-#endif\r
- cur_x = scan_x;\r
- centering = false;\r
-\r
- // skip SPACES / RETURNS at end of line\r
- //\r
- if ((*first_ch==' ') || (*first_ch==PI_RETURN_CHAR))\r
- first_ch++;\r
-\r
- // PI_CONTROL_CHARs don't advance to next character line\r
- //\r
- if (*scan_ch != PI_CONTROL_CHAR)\r
- {\r
- cur_x = xl;\r
- cur_y += font_height;\r
- }\r
- }\r
- else\r
-//\r
-// HANDLE CONTROL CODES\r
-//\r
- {\r
- PresenterInfo endmsg;\r
- pi_anim_info far *anim;\r
- pi_shape_info far *shape_info;\r
- unsigned shapenum;\r
- short length;\r
- char far *s;\r
-\r
- if (first_ch[-1] == '\n')\r
- start_of_line = true;\r
-\r
- first_ch++;\r
-#ifndef PI_CASE_SENSITIVE\r
- *first_ch=toupper(*first_ch);\r
- *(first_ch+1)=toupper(*(first_ch+1));\r
-#endif\r
- switch (*((unsigned far *)first_ch)++)\r
- {\r
- // CENTER TEXT ------------------------------------------------------\r
- //\r
- case PI_CNVT_CODE('C','E'):\r
- length = 0;\r
- s = first_ch;\r
- while (*s && (*s != PI_RETURN_CHAR))\r
- {\r
- switch (*s)\r
- {\r
- case PI_CONTROL_CHAR:\r
- s++;\r
- switch (*((unsigned *)s)++)\r
- {\r
-#ifndef AMIGA\r
- case PI_CNVT_CODE('F','C'):\r
- case PI_CNVT_CODE('B','G'):\r
- s++;\r
- break;\r
-#endif\r
-\r
- case PI_CNVT_CODE('L','M'):\r
- case PI_CNVT_CODE('R','M'):\r
- case PI_CNVT_CODE('S','H'):\r
- case PI_CNVT_CODE('P','X'):\r
- case PI_CNVT_CODE('P','Y'):\r
- s += 3;\r
- break;\r
-\r
- case PI_CNVT_CODE('L','J'):\r
- case PI_CNVT_CODE('R','J'):\r
- // No parameters to pass over!\r
- break;\r
- }\r
- break;\r
-\r
- default:\r
- length += ch_width(*s++);\r
- break;\r
- }\r
- }\r
- cur_x = ((xh-xl+1)-length)/2;\r
- centering = true;\r
- break;\r
-\r
- // DRAW SHAPE -------------------------------------------------------\r
- //\r
- case PI_CNVT_CODE('S','H'):\r
- shapenum = PI_VALUE(first_ch,3);\r
- first_ch += 3;\r
- shape_info = &pi_shape_table[shapenum];\r
- switch (shape_info->shape_type)\r
- {\r
- short width;\r
-\r
- case pis_pic2x:\r
- cur_x = ((cur_x+2) + 7) & 0xFFF8;\r
- width=BoxAroundPic(cur_x-2,cur_y-1,shape_info->shapenum,pi);\r
- VW_DrawPic2x(cur_x>>3,cur_y,shape_info->shapenum);\r
- cur_x += width;\r
- break;\r
- }\r
- break;\r
-\r
- // INIT ANIMATION ---------------------------------------------------\r
- //\r
- case PI_CNVT_CODE('A','N'):\r
- shapenum = PI_VALUE(first_ch,2);\r
- first_ch += 2;\r
- _fmemcpy(&pi_anim_list[numanims],&pi_anim_table[shapenum],sizeof(pi_anim_info));\r
- anim = &pi_anim_list[numanims++];\r
- shape_info = &pi_shape_table[anim->baseshape+anim->frame];\r
- switch (shape_info->shape_type)\r
- {\r
- short width;\r
-\r
- case pis_pic2x:\r
- cur_x = ((cur_x+2) + 7) & 0xFFF8;\r
- width=BoxAroundPic(cur_x-2,cur_y-1,shape_info->shapenum,pi);\r
- VW_DrawPic2x(cur_x>>3,cur_y,shape_info->shapenum);\r
- anim->x = cur_x>>3;\r
- anim->y = cur_y;\r
- cur_x += width;\r
- break;\r
- }\r
- break;\r
-\r
-#ifndef AMIGA\r
- // FONT COLOR -------------------------------------------------------\r
- //\r
- case PI_CNVT_CODE('F','C'):\r
- fontcolor = bgcolor ^ PI_VALUE(first_ch++,1);\r
- break;\r
-#endif\r
-\r
- // BACKGROUND COLOR -------------------------------------------------\r
- //\r
- case PI_CNVT_CODE('B','G'):\r
- bgcolor = PI_VALUE(first_ch++,1);\r
- break;\r
-\r
- // LEFT MARGIN ------------------------------------------------------\r
- //\r
- case PI_CNVT_CODE('L','M'):\r
- shapenum = PI_VALUE(first_ch,3);\r
- first_ch += 3;\r
- if (shapenum == 0xfff)\r
- xl = cur_x;\r
- else\r
- xl = shapenum;\r
- break;\r
-\r
- // RIGHT MARGIN -----------------------------------------------------\r
- //\r
- case PI_CNVT_CODE('R','M'):\r
- shapenum = PI_VALUE(first_ch,3);\r
- first_ch += 3;\r
- if (shapenum == 0xfff)\r
- xh = cur_x;\r
- else\r
- xh = shapenum;\r
- break;\r
-\r
- // SET X COORDINATE -------------------------------------------------\r
- //\r
- case PI_CNVT_CODE('P','X'):\r
- cur_x = PI_VALUE(first_ch,3);\r
- first_ch += 3;\r
- break;\r
-\r
- // SET Y COORDINATE -------------------------------------------------\r
- //\r
- case PI_CNVT_CODE('P','Y'):\r
- cur_y = PI_VALUE(first_ch,3);\r
- first_ch += 3;\r
- break;\r
-\r
- // LEFT JUSTIFY -----------------------------------------------------\r
- //\r
- case PI_CNVT_CODE('L','J'):\r
- justify_mode = jm_left;\r
- break;\r
-\r
- // RIGHT JUSTIFY ----------------------------------------------------\r
- //\r
- case PI_CNVT_CODE('R','J'):\r
- justify_mode = jm_right;\r
- break;\r
-\r
- // END OF PAGE ------------------------------------------------------\r
- //\r
- case PI_CNVT_CODE('E','P'):\r
- if (pi_recursing)\r
- Quit("Presenter(): Can't use ^EP when recursing!");\r
-\r
- endmsg.xl = cur_x;\r
- endmsg.yl = yh-(font_height+2);\r
- endmsg.xh = xh;\r
- endmsg.yh = yh;\r
- endmsg.bgcolor = bgcolor;\r
- endmsg.ltcolor = pi->ltcolor;\r
- endmsg.dkcolor = pi->dkcolor;\r
- endmsg.script[0] = (char far *)"^CE^FC8- ^FC0ESC ^FC8to return to play, or ^FC0ARROW KEYS ^FC8to page through more Help -^XX";\r
-\r
- pi_recursing = true;\r
- Presenter(&endmsg);\r
- pi_recursing = false;\r
-\r
-#ifndef AMIGA\r
- if (screenfaded)\r
- VW_FadeIn();\r
- VW_ColorBorder(8 | 56);\r
-#endif\r
-\r
- while (1)\r
- {\r
-#ifndef AMIGA\r
- long newtime;\r
-\r
- VW_WaitVBL(1);\r
- newtime = TimeCount;\r
- realtics = tics = newtime-lasttimecount;\r
- lasttimecount = newtime;\r
-#else\r
- WaitVBL(1);\r
- CALC_TICS;\r
-#endif\r
- AnimatePage(numanims);\r
- IN_ReadControl(0,&control);\r
-\r
- if (control.button1 || Keyboard[1])\r
- {\r
- presenting=false;\r
- break;\r
- }\r
- else\r
- {\r
- if (ControlTypeUsed != ctrl_Keyboard)\r
- control.dir = dir_None;\r
-\r
- if (((control.dir == dir_North) || (control.dir == dir_West)) && (PageNum))\r
- {\r
- if (up_released)\r
- {\r
- PageNum--;\r
- up_released = false;\r
- break;\r
- }\r
- }\r
- else\r
- {\r
- up_released = true;\r
- if (((control.dir == dir_South) || (control.dir == dir_East)) && (PageNum < pi->numpages-1))\r
- {\r
- if (dn_released)\r
- {\r
- PageNum++;\r
- dn_released = false;\r
- break;\r
- }\r
- }\r
- else\r
- dn_released = true;\r
- }\r
- }\r
- }\r
-\r
- cur_x = xl;\r
- cur_y = yl;\r
- if (cur_y+font_height > yh)\r
- cur_y = yh-font_height;\r
- first_ch = pi->script[PageNum];\r
-\r
- numanims = 0;\r
- PurgeAllGfx();\r
- CachePage(first_ch);\r
-\r
- VW_Bar(xl,yl,xh-xl+1,yh-yl+1,bgcolor);\r
- break;\r
-\r
- // EXIT PRESENTER ---------------------------------------------------\r
- //\r
- case PI_CNVT_CODE('X','X'):\r
- presenting=false;\r
- break;\r
- }\r
-\r
- if ((first_ch[0] == ' ') && (first_ch[1] == '\n') && start_of_line)\r
- first_ch += 2;\r
- }\r
- }\r
-}\r
-\r
-//--------------------------------------------------------------------------\r
-// ResetAnims()\r
-//--------------------------------------------------------------------------\r
-void ResetAnims()\r
-{\r
- pi_anim_list[0].baseshape = -1;\r
-}\r
-\r
-//--------------------------------------------------------------------------\r
-// AnimatePage()\r
-//--------------------------------------------------------------------------\r
-void AnimatePage(short numanims)\r
-{\r
- pi_anim_info far *anim=pi_anim_list;\r
- pi_shape_info far *shape_info;\r
-\r
- while (numanims--)\r
- {\r
- anim->delay += tics;\r
- if (anim->delay >= anim->maxdelay)\r
- {\r
- anim->delay = 0;\r
- anim->frame++;\r
- if (anim->frame == anim->maxframes)\r
- anim->frame = 0;\r
-\r
-#if ANIM_USES_SHAPETABLE\r
- shape_info = &pi_shape_table[anim->baseshape+anim->frame];\r
-#else\r
- shape_info = &pi_shape_table[anim->baseshape];\r
-#endif\r
- switch (shape_info->shape_type)\r
- {\r
- case pis_pic2x:\r
-#if ANIM_USES_SHAPETABLE\r
- VW_DrawPic2x(anim->x,anim->y,shape_info->shapenum);\r
-#else\r
- VW_DrawPic2x(anim->x,anim->y,shape_info->shapenum+anim->frame);\r
-#endif\r
- break;\r
- }\r
- }\r
- anim++;\r
- }\r
-}\r
-\r
-//--------------------------------------------------------------------------\r
-// BoxAroundPic()\r
-//--------------------------------------------------------------------------\r
-short BoxAroundPic(short x1, short y1, unsigned picnum, PresenterInfo *pi)\r
-{\r
- short x2,y2;\r
-\r
- x2 = x1+(pictable[picnum-STARTPICS].width<<4)+2;\r
- y2 = y1+(pictable[picnum-STARTPICS].height)+1;\r
- VWB_Hlin(x1,x2,y1,pi->ltcolor);\r
- VWB_Hlin(x1,x2,y2,pi->dkcolor);\r
- VWB_Vlin(y1,y2,x1,pi->ltcolor);\r
- VWB_Vlin(y1,y2,x1+1,pi->ltcolor);\r
- VWB_Vlin(y1,y2,x2,pi->dkcolor);\r
- VWB_Vlin(y1,y2,x2+1,pi->dkcolor);\r
-\r
- return(x2-x1+1);\r
-}\r
-\r
-//--------------------------------------------------------------------------\r
-// PurgeAllGfx()\r
-//--------------------------------------------------------------------------\r
-void PurgeAllGfx()\r
-{\r
- ResetAnims();\r
- FreeUpMemory();\r
-}\r
-\r
-//--------------------------------------------------------------------------\r
-// CachePage()\r
-//--------------------------------------------------------------------------\r
-void CachePage(char far *script)\r
-{\r
- pi_anim_info far *anim;\r
- short loop;\r
- unsigned shapenum;\r
- boolean end_of_page=false;\r
- short numanims=0;\r
-\r
- while (!end_of_page)\r
- {\r
- switch (*script++)\r
- {\r
- case PI_CONTROL_CHAR:\r
-#ifndef PI_CASE_SENSITIVE\r
- *script=toupper(*script);\r
- *(script+1)=toupper(*(script+1));\r
-#endif\r
- switch (*((unsigned far *)script)++)\r
- {\r
- case PI_CNVT_CODE('S','H'):\r
- shapenum = PI_VALUE(script,3);\r
- script += 3;\r
- CA_MarkGrChunk(pi_shape_table[shapenum].shapenum);\r
- break;\r
-\r
- case PI_CNVT_CODE('A','N'):\r
- shapenum = PI_VALUE(script,2);\r
- script += 2;\r
-\r
- if (numanims++ == PI_MAX_ANIMS)\r
- Quit("CachePage(): Too many anims on one page.");\r
-\r
- anim = &pi_anim_table[shapenum];\r
-#if ANIM_USES_SHAPETABLE\r
- for (loop=anim->baseshape;loop < anim->baseshape+anim->maxframes; loop++)\r
- CA_MarkGrChunk(pi_shape_table[loop].shapenum);\r
-#else\r
- shapenum = pi_shape_table[anim->baseshape].shapenum;\r
- for (loop=0; loop<anim->maxframes; loop++)\r
- CA_MarkGrChunk(shapenum+loop);\r
-#endif\r
- break;\r
-\r
- case PI_CNVT_CODE('X','X'):\r
- case PI_CNVT_CODE('E','P'):\r
- end_of_page = true;\r
- break;\r
- }\r
- break;\r
- }\r
- }\r
-\r
- CA_CacheMarks(NULL);\r
-}\r
-\r
-//--------------------------------------------------------------------------\r
-// PI_VALUE()\r
-//--------------------------------------------------------------------------\r
-unsigned PI_VALUE(char far *ptr,char num_nybbles)\r
-{\r
- char ch,nybble,shift;\r
- unsigned value=0;\r
-\r
- for (nybble=0; nybble<num_nybbles; nybble++)\r
- {\r
- shift = 4*(num_nybbles-nybble-1);\r
-\r
- ch = *ptr++;\r
- if (isxdigit(ch))\r
- if (isalpha(ch))\r
- value |= (toupper(ch)-'A'+10)<<shift;\r
- else\r
- value |= (ch-'0')<<shift;\r
- }\r
-\r
- return(value);\r
-}\r
-\r
-//--------------------------------------------------------------------------\r
-// LoadPresenterScript()\r
-//--------------------------------------------------------------------------\r
-long LoadPresenterScript(char *filename,PresenterInfo *pi)\r
-{\r
-#pragma warn -pia\r
- long size;\r
-\r
- if (!(size=BLoad(filename,&pi->scriptstart)))\r
- return(0);\r
- pi->script[0] = MK_FP(pi->scriptstart,0);\r
- pi->script[0][size-1] = 0; // Last byte is trashed!\r
- InitPresenterScript(pi);\r
-\r
- return(size);\r
-#pragma warn +pia\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// FreePresenterScript()\r
-//-------------------------------------------------------------------------\r
-void FreePresenterScript(PresenterInfo *pi)\r
-{\r
- if (pi->script)\r
- MM_FreePtr(&pi->scriptstart);\r
-}\r
-\r
-//-------------------------------------------------------------------------\r
-// InitPresenterScript()\r
-//-------------------------------------------------------------------------\r
-void InitPresenterScript(PresenterInfo *pi)\r
-{\r
- char far *script = pi->script[0];\r
-\r
- pi->numpages = 1; // Assume at least 1 page\r
- while (*script)\r
- {\r
- switch (*script++)\r
- {\r
- case PI_CONTROL_CHAR:\r
-#ifndef PI_CASE_SENSITIVE\r
- *script=toupper(*script);\r
- *(script+1)=toupper(*(script+1));\r
-#endif\r
- switch (*((unsigned far *)script)++)\r
- {\r
- case PI_CNVT_CODE('E','P'):\r
- if (pi->numpages < PI_MAX_PAGES)\r
- pi->script[pi->numpages++] = script;\r
- else\r
- TrashProg("GE ERROR: Too many Presenter() pages. --> %d",pi->numpages);\r
- break;\r
- }\r
- break;\r
-\r
- case '\r':\r
- if (*script == '\n')\r
- {\r
- *(script-1) = ' ';\r
- script++;\r
- }\r
- break;\r
- }\r
- }\r
-\r
- pi->numpages--; // Last page defined is not a real page.\r
-}\r
-#endif\r
-\r
-\r
-//-------------------------------------------------------------------------\r
-// AnimateWallList()\r
-//-------------------------------------------------------------------------\r
-void AnimateWallList(void)\r
-{\r
- walltype *wall, *check;\r
- unsigned i;\r
- int tile,org_tile;\r
-\r
- if (wall_anim_delay>0)\r
- {\r
- wall_anim_delay-=realtics;\r
- return;\r
- }\r
-\r
- //\r
- // Re-Init our counter...\r
- //\r
-\r
- wall_anim_delay = wall_anim_time;\r
-\r
- //\r
- // Clear all previous flags marking animation being DONE.\r
- //\r
-\r
- for (i=0;i<NUMFLOORS;i++)\r
- TILE_FLAGS(i) &= ~tf_MARKED;\r
-\r
-\r
- //\r
- // Run though wall list updating only then needed animations\r
- //\r
-\r
- for (wall=&walls[1];wall<rightwall;wall++)\r
- {\r
- org_tile = tile = wall->color + wall_anim_pos[wall->color];\r
-\r
- if (ANIM_FLAGS(tile))\r
- {\r
- do\r
- {\r
- if (!(TILE_FLAGS(tile) & tf_MARKED))\r
- {\r
- //\r
- // update our offset table (0-NUMANIMS)\r
- //\r
-\r
- wall_anim_pos[tile] += (char signed)ANIM_FLAGS(tile+(char signed)wall_anim_pos[tile]);\r
-\r
- //\r
- // Mark tile as being already updated..\r
- //\r
-\r
- TILE_FLAGS(tile) |= tf_MARKED;\r
- }\r
-\r
- //\r
- // Check rest of tiles in this animation string...\r
- //\r
-\r
- tile += (char signed)ANIM_FLAGS(tile);\r
-\r
- } while (tile != org_tile);\r
- }\r
- }\r
-}\r
-\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#include "SL_FILE.h"\r
-\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// Defines\r
-//\r
-\r
-#define ANIM_USES_SHAPE_TABLE false\r
-#define PI_MAX_ANIMS 10\r
-#define PI_MAX_PAGES 40\r
-\r
-#define SAVEVER_DATA "0.01"\r
-#define FILENAME_LEN 15\r
-\r
-#define GAMENAME "CATACOMB ARMAGEDDON 3-D"\r
-#define VERSION "V1.02"\r
-#define REVISION " rev 1 "\r
-\r
-//#define BOBLIST 1 //SP - Undefine if not using BOBList\r
-\r
-#define AUDIO_DISK (2)\r
-#define VIDEO_DISK (1)\r
-#define LEVEL_DISK (2)\r
-\r
-#define BIO_BUFFER_LEN (512)\r
-\r
-#define TrashProg Quit\r
-\r
-// #define AMIGA\r
-\r
-\r
-typedef struct Sample {\r
- char *filename;\r
- memptr *data;\r
-} Sample;\r
-\r
-typedef enum {ged_none, ged_SoundSource,ged_SoundBlaster} AudioDeviceType;\r
-\r
-//typedef struct {\r
-// memptr textptr;\r
-// char far *pages[MAX_TEXT_PAGES];\r
-// short totalpages;\r
-//} textinfo;\r
-\r
-typedef struct {\r
- int handle; // handle of file\r
- memptr buffer; // pointer to buffer\r
- word offset; // offset into buffer\r
- word status; // read/write status\r
-} BufferedIO;\r
-\r
-typedef enum ANIMINFO {at_NONE,at_INIT,at_WAIT,at_ONCE,at_CYCLE,\r
- at_REBOUND,at_EXTRA,\r
- at_FWD,at_REV\r
-} ANIMINFO;\r
-\r
-struct BitMapHeader {\r
- unsigned int w,h,x,y;\r
- unsigned char d,trans,comp,pad;\r
-};\r
-\r
-struct BitMap {\r
- unsigned int Width;\r
- unsigned int Height;\r
- unsigned int Depth;\r
- unsigned int BytesPerRow;\r
- char far *Planes[8];\r
-};\r
-\r
-struct Shape {\r
- memptr Data;\r
- long size;\r
- unsigned int BPR;\r
- struct BitMapHeader bmHdr;\r
-};\r
-\r
-#ifdef AMIGA\r
-typedef struct {\r
- char *script[PI_MAX_PAGES];\r
- XBitMap **shapes;\r
- XBitMap **font;\r
- short xl,yl,xh,yh;\r
- struct BitMap *dst;\r
- char numpages,bgcolor;\r
-} PresenterInfo;\r
-#else\r
-typedef struct {\r
- char far *script[PI_MAX_PAGES];\r
- memptr scriptstart;\r
- short xl,yl,xh,yh;\r
- char numpages,bgcolor,ltcolor,dkcolor;\r
-} PresenterInfo;\r
-#endif\r
-\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// Externs\r
-//\r
-\r
-extern char Filename[], ID[], VER[];\r
-extern boolean ge_textmode;\r
-extern short PPT_LeftEdge,PPT_RightEdge;\r
-//extern boolean ConserveMemory;\r
-extern BufferedIO lzwBIO;\r
-extern short wall_anim_delay,wall_anim_time;\r
-\r
-\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// Function prototypes\r
-//\r
-void WaitKeyVBL(short key, short vbls);\r
-void CalibrateJoystick(short joynum);\r
-void MoveScreen(short x, short y);\r
-void MoveGfxDst(short x, short y);\r
-void DoPiracy(void);\r
-void PrintPropText(char far *text);\r
-//void DisplayText(textinfo *textinfo);\r
-//long LoadTextFile(char *filename,textinfo *textinfo);\r
-//void FreeTextFile(textinfo *textinfo);\r
-//void InitTextFile(textinfo *textinfo);\r
-long Verify(char *filename);\r
-void GE_SaveGame(void);\r
-boolean GE_LoadGame(void);\r
-int GE_HardError(word errval,int ax,int bp,int si);\r
-\r
-#ifdef BOBLIST\r
-\r
-\r
-boolean UpdateBOBList(objtype *obj,struct Simple_Shape *Shape,shapeclass Class, short priority, spriteflags sprflags);\r
-boolean RemoveBOBShape(objtype *obj, shapeclass Class);\r
-void RemoveBOBList(objtype *obj);\r
-void InitBOBList(objtype *obj, struct BOB_Shape *BOB_Shape, short NumElements);\r
-void RefreshBOBList(objtype *obj);\r
-#endif\r
-\r
-\r
-unsigned long BLoad(char *SourceFile, memptr *DstPtr);\r
-void lzwDecompressFromRAM(byte far *SrcPtr, byte far *DstPtr, longword SrcLen);\r
-void lzwDecompressFromFile(BufferedIO *SrcPtr, byte far *DstPtr, longword SrcLen);\r
-byte readch(int handle);\r
-\r
-memptr InitBufferedIO(int handle, BufferedIO *bio);\r
-void FreeBufferedIO(BufferedIO *bio);\r
-byte bio_readch(BufferedIO *bio);\r
-void bio_fillbuffer(BufferedIO *bio);\r
-\r
-\r
-void SwapLong(long far *Var);\r
-void SwapWord(unsigned int far *Var);\r
-int LoadShape(char *Filename,struct Shape *SHP);\r
-void FreeShape(struct Shape *shape);\r
-int UnpackEGAShapeToScreen(struct Shape *SHP,int startx,int starty);\r
-char GetKeyChoice(char *choices,boolean clear);\r
-boolean AnimateObj(objtype *obj);\r
-void AdvanceAnimFWD(objtype *obj);\r
-void AdvanceAnimREV(objtype *obj);\r
-\r
-void LoadASArray(struct Sample *ASArray);\r
-void FreeASArray(struct Sample *ASArray);\r
-//void SelectDigiAudio(AudioDeviceType Device);\r
-void PlaySample(unsigned SampleNum);\r
-void GE_FreeAllDigiSounds(void);\r
-void GE_LoadAllDigiSounds(void);\r
-void DisplayGameList(short winx, short winy, short list_width, short list_height);\r
-void ReadGameList(void);\r
-void CheckStack(void);\r
-void CenterObj(objtype *obj, unsigned x, unsigned y);\r
-void cachein(short s,short e);\r
-void cacheout(short s,short e);\r
-void FizzleFade (unsigned source, unsigned dest,unsigned width,unsigned height, boolean abortable);\r
-void mprintf(char *msg, ...);\r
-boolean FindFile(char *filename,char *disktext,char disknum);\r
-void CacheAV(char *title);\r
-void BlackPalette(void);\r
-void ColoredPalette(void);\r
-void Presenter(PresenterInfo *pi);\r
-unsigned PI_VALUE(char far *ptr,char num_nybbles);\r
-long LoadPresenterScript(char *filename,PresenterInfo *pi);\r
-void FreePresenterScript(PresenterInfo *pi);\r
-void InitPresenterScript(PresenterInfo *pi);\r
-\r
-void AnimatePage(short numanims);\r
-short BoxAroundPic(short x1, short y1, unsigned picnum, PresenterInfo *pi);\r
-void PurgeAllGfx(void);\r
-void CachePage(char far *script);\r
-\r
-\r
-void AnimateWallList(void);\r
+++ /dev/null
-;=====================================\r
-;\r
-; Graphics .EQU file for .ARM\r
-; IGRAB-ed on Thu Dec 02 13:59:00 1993\r
-;\r
-;=====================================\r
-\r
-FINALEPIC = 4\r
-STATUSPIC = 5\r
-FACE5PIC = 6\r
-FIRSTLATCHPIC = 7\r
-FACE1PIC = 8\r
-FACE2PIC = 9\r
-FACE3PIC = 10\r
-FACE4PIC = 11\r
-RADAR_TOPPIC = 12\r
-RADAR_BOTTOMPIC = 13\r
-RADAR_RGEMPIC = 14\r
-RADAR_GGEMPIC = 15\r
-RADAR_BGEMPIC = 16\r
-RADAR_YGEMPIC = 17\r
-RADAR_PGEMPIC = 18\r
-FIRSTGROUNDPIC = 19\r
-FIRSTSTRIPPIC = 20\r
-FIRSTSCALEPIC = 21\r
-SKELETON_1PIC = 22\r
-SKELETON_2PIC = 23\r
-SKELETON_3PIC = 24\r
-SKELETON_4PIC = 25\r
-SKELETON_ATTACK_1PIC = 26\r
-SKELETON_ATTACK_2PIC = 27\r
-SKELETON_ATTACK_3PIC = 28\r
-SKELETON_OUCHPIC = 29\r
-SKELETON_DEATH_1PIC = 30\r
-SKELETON_DEATH_2PIC = 31\r
-TOMB1PIC = 32\r
-TOMB2PIC = 33\r
-TOMB3PIC = 34\r
-OBJ_WARP1PIC = 35\r
-OBJ_WARP2PIC = 36\r
-OBJ_WARP3PIC = 37\r
-OBJ_WARP4PIC = 38\r
-EYE_WALK1PIC = 39\r
-EYE_WALK2PIC = 40\r
-EYE_WALK3PIC = 41\r
-EYE_OUCH1PIC = 42\r
-EYE_OUCH2PIC = 43\r
-EYE_DEATH1PIC = 44\r
-EYE_DEATH2PIC = 45\r
-EYE_DEATH3PIC = 46\r
-EYE_SCOWLPIC = 47\r
-EYE_SHOT1PIC = 48\r
-EYE_SHOT2PIC = 49\r
-ZOMB_APPEAR1PIC = 50\r
-ZOMB_APPEAR2PIC = 51\r
-ZOMB_APPEAR3PIC = 52\r
-ZOMB_APPEAR4PIC = 53\r
-ZOMB_WALK1PIC = 54\r
-ZOMB_WALK2PIC = 55\r
-ZOMB_WALK3PIC = 56\r
-ZOMB_OUCHPIC = 57\r
-ZOMB_ATTACKPIC = 58\r
-ZOMB_DIE1PIC = 59\r
-ZOMB_DIE2PIC = 60\r
-ZOMB_DIE3PIC = 61\r
-BOLTOBJPIC = 62\r
-BOLT2OBJPIC = 63\r
-BOLT3OBJPIC = 64\r
-NUKEOBJPIC = 65\r
-NUKE2OBJPIC = 66\r
-NUKE3OBJPIC = 67\r
-TIMEOBJ1PIC = 68\r
-TIMEOBJ2PIC = 69\r
-O_WATER_CHEST1PIC = 70\r
-O_WATER_CHEST2PIC = 71\r
-POTIONOBJPIC = 72\r
-RKEYOBJPIC = 73\r
-YKEYOBJPIC = 74\r
-GKEYOBJPIC = 75\r
-BKEYOBJPIC = 76\r
-RGEM1PIC = 77\r
-RGEM2PIC = 78\r
-GGEM1PIC = 79\r
-GGEM2PIC = 80\r
-BGEM1PIC = 81\r
-BGEM2PIC = 82\r
-YGEM1PIC = 83\r
-YGEM2PIC = 84\r
-PGEM1PIC = 85\r
-PGEM2PIC = 86\r
-CHESTOBJPIC = 87\r
-PSHOT1PIC = 88\r
-PSHOT2PIC = 89\r
-PSHOT_EXP1PIC = 90\r
-PSHOT_EXP2PIC = 91\r
-PSHOT_EXP3PIC = 92\r
-RED_DEMON1PIC = 93\r
-RED_DEMON2PIC = 94\r
-RED_DEMON3PIC = 95\r
-RED_DEMON4PIC = 96\r
-RED_DEMONATTACK1PIC = 97\r
-RED_DEMONATTACK2PIC = 98\r
-RED_DEMONATTACK3PIC = 99\r
-RED_DEMONOUCHPIC = 100\r
-RED_DEMONDIE1PIC = 101\r
-RED_DEMONDIE2PIC = 102\r
-RED_DEMONDIE3PIC = 103\r
-MAGE1PIC = 104\r
-MAGE2PIC = 105\r
-MAGEOUCHPIC = 106\r
-MAGEATTACKPIC = 107\r
-MAGEDIE1PIC = 108\r
-MAGEDIE2PIC = 109\r
-BAT1PIC = 110\r
-BAT2PIC = 111\r
-BAT3PIC = 112\r
-BAT4PIC = 113\r
-BATDIE1PIC = 114\r
-BATDIE2PIC = 115\r
-GREL1PIC = 116\r
-GREL2PIC = 117\r
-GRELATTACKPIC = 118\r
-GRELHITPIC = 119\r
-GRELDIE1PIC = 120\r
-GRELDIE2PIC = 121\r
-GRELDIE3PIC = 122\r
-GRELDIE4PIC = 123\r
-GRELDIE5PIC = 124\r
-GRELDIE6PIC = 125\r
-SKULL_SHOTPIC = 126\r
-GODESS_WALK1PIC = 127\r
-GODESS_WALK2PIC = 128\r
-GODESS_WALK3PIC = 129\r
-GODESS_ATTACK1PIC = 130\r
-GODESS_ATTACK2PIC = 131\r
-GODESS_ATTACK3PIC = 132\r
-GODESS_STATUEPIC = 133\r
-GODESS_OUCHPIC = 134\r
-GODESS_DEATH1PIC = 135\r
-GODESS_DEATH2PIC = 136\r
-ANT_EGG1PIC = 137\r
-ANT_EGG2PIC = 138\r
-ANT_WALK1PIC = 139\r
-ANT_WALK2PIC = 140\r
-ANT_WALK3PIC = 141\r
-ANT_ATTACKPIC = 142\r
-ANT_DEATH1PIC = 143\r
-ANT_DEATH2PIC = 144\r
-ANT_DEATH3PIC = 145\r
-FATDEMON_WALK1PIC = 146\r
-FATDEMON_WALK2PIC = 147\r
-FATDEMON_WALK3PIC = 148\r
-FATDEMON_WALK4PIC = 149\r
-FATDEMON_ATTACK1PIC = 150\r
-FATDEMON_ATTACK2PIC = 151\r
-FATDEMON_OUCHPIC = 152\r
-FATDEMON_BLOWUP1PIC = 153\r
-FATDEMON_BLOWUP2PIC = 154\r
-FATDEMON_BLOWUP3PIC = 155\r
-FATDEMON_EXPLODEPIC = 156\r
-FATDEMON_FEETPIC = 157\r
-SUCCUBUS_WALK1PIC = 158\r
-SUCCUBUS_WALK2PIC = 159\r
-SUCCUBUS_WALK3PIC = 160\r
-SUCCUBUS_WALK4PIC = 161\r
-SUCCUBUS_ATTACK1PIC = 162\r
-SUCCUBUS_ATTACK2PIC = 163\r
-SUCCUBUS_OUCHPIC = 164\r
-SUCCUBUS_DEATH1PIC = 165\r
-SUCCUBUS_DEATH2PIC = 166\r
-SUCCUBUS_SHOT1PIC = 167\r
-TREE_IDLEPIC = 168\r
-TREE_AWAKENINGPIC = 169\r
-TREE_WALK1PIC = 170\r
-TREE_WALK2PIC = 171\r
-TREE_ATTACK1PIC = 172\r
-TREE_ATTACK2PIC = 173\r
-TREE_ATTACK3PIC = 174\r
-TREE_DEATH1PIC = 175\r
-TREE_DEATH2PIC = 176\r
-TREE_DEATH3PIC = 177\r
-DRAGON_BUBBLES1PIC = 178\r
-DRAGON_BUBBLES2PIC = 179\r
-DRAGON_EYESPIC = 180\r
-DRAGON_RISE1PIC = 181\r
-DRAGON_RISE2PIC = 182\r
-DRAGON_WALK1PIC = 183\r
-DRAGON_WALK2PIC = 184\r
-DRAGON_WALK3PIC = 185\r
-DRAGON_WALK4PIC = 186\r
-DRAGON_ATTACK1PIC = 187\r
-DRAGON_ATTACK2PIC = 188\r
-DRAGON_ATTACK3PIC = 189\r
-DRAGON_OUCHPIC = 190\r
-DRAGON_DEATH1PIC = 191\r
-DRAGON_DEATH2PIC = 192\r
-DRAGON_DEATH3PIC = 193\r
-BUNNY_LEFT1PIC = 194\r
-BUNNY_LEFT2PIC = 195\r
-BUNNY_RIGHT1PIC = 196\r
-BUNNY_RIGHT2PIC = 197\r
-BUNNY_META1PIC = 198\r
-BUNNY_META2PIC = 199\r
-BUNNY_WALK1PIC = 200\r
-BUNNY_WALK2PIC = 201\r
-BUNNY_OUCHPIC = 202\r
-BUNNY_DEATH1PIC = 203\r
-BUNNY_DEATH2PIC = 204\r
-ARCH1PIC = 205\r
-ARCH2PIC = 206\r
-ARCH3PIC = 207\r
-ARCH4PIC = 208\r
-ARCH5PIC = 209\r
-ARCH6PIC = 210\r
-ARCH7PIC = 211\r
-ARCH8PIC = 212\r
-ARCH9PIC = 213\r
-ARCH10PIC = 214\r
-ARCH11PIC = 215\r
-ARCH12PIC = 216\r
-ARCH13PIC = 217\r
-ANT_HILLPIC = 218\r
-COLUMNPIC = 219\r
-SULPHUR_GAS_1PIC = 220\r
-SULPHUR_GAS_2PIC = 221\r
-SULPHUR_GAS_3PIC = 222\r
-FIRE_POT_1PIC = 223\r
-FIRE_POT_2PIC = 224\r
-SKEL_HANGPIC = 225\r
-FORCE_FIELD_1PIC = 226\r
-FORCE_FIELD_2PIC = 227\r
-FORCE_FIELD_3PIC = 228\r
-FORCE_FIELD_4PIC = 229\r
-WFOUNTAINPIC = 230\r
-FIRSTWALLPIC = 231\r
-CRYSTAL_LIGHT_1PIC = 232\r
-CRYSTAL_LIGHT_2PIC = 233\r
-CRYSTAL_LIGHT_3PIC = 234\r
-CRYSTAL_LIGHT_4PIC = 235\r
-CRYSTAL_DARK_1PIC = 236\r
-CRYSTAL_DARK_2PIC = 237\r
-CRYSTAL_DARK_3PIC = 238\r
-CRYSTAL_DARK_4PIC = 239\r
-FIRE_WALL_1PIC = 240\r
-FIRE_WALL_2PIC = 241\r
-FIRE_WALL_3PIC = 242\r
-FIRE_WALL_4PIC = 243\r
-BRN_STONE_GATEPIC = 244\r
-BRN_STONE_WALL_1PIC = 245\r
-BRN_STONE_WALL_2PIC = 246\r
-KUDZU_LIGHT_WALLPIC = 247\r
-KUDZU_DARK_WALLPIC = 248\r
-HEDGE_WALLPIC = 249\r
-HEDGE_EYESPIC = 250\r
-BRN_WINDOW_LIGHTPIC = 251\r
-ALTAR_LEFTPIC = 252\r
-ALTAR_RIGHTPIC = 253\r
-GRAY_LIGHT_WALLPIC = 254\r
-GRAY_DARK_WALLPIC = 255\r
-GRAY_LIGHT_SIGNPIC = 256\r
-GRAY_DARK_SIGNPIC = 257\r
-MANICLE_LIGHT_BLOODYPIC = 258\r
-MANICLE_DARK_BLOODYPIC = 259\r
-LIGHT_CURTAIN_WINDOWPIC = 260\r
-LIGHT_CURTAIN_WALLPIC = 261\r
-DARK_CURTAIN_WINDOWPIC = 262\r
-DARK_CURTAIN_WALLPIC = 263\r
-BRN_LIGHT_SIGNPIC = 264\r
-BRN_DARK_SIGNPIC = 265\r
-LIGHT_STONE_WALLPIC = 266\r
-DARK_STONE_WALLPIC = 267\r
-BRN_FLAGSTONE_LIGHT_2PIC = 268\r
-BRN_FLAGSTONE_DARK_2PIC = 269\r
-RUST_METAL_LIGHTPIC = 270\r
-RUST_METAL_DARKPIC = 271\r
-GRAY_METAL_LIGHTPIC = 272\r
-GRAY_METAL_DARKPIC = 273\r
-WEAK_STONE_LIGHTPIC = 274\r
-WEAK_STONE_DARKPIC = 275\r
-WEAK_GRAY_RFGSTN_LIGHTPIC = 276\r
-WEAK_GRAY_RFGSTN_DARKPIC = 277\r
-WEAK_CRYSTAL_LIGHTPIC = 278\r
-WEAK_CRYSTAL_DARKPIC = 279\r
-RED_MUD_LIGHTPIC = 280\r
-BRN_MUD_DARKPIC = 281\r
-RED_MUD_WEAK_LIGHTPIC = 282\r
-BRN_MUD_WEAK_DARKPIC = 283\r
-HORN_DOORPIC = 284\r
-CLOSED_DOOR_1PIC = 285\r
-DOOR_2PIC = 286\r
-WATER_LIGHT_WEAK_1PIC = 287\r
-WATER_LIGHT_WEAK_2PIC = 288\r
-WATER_LIGHT_WEAK_3PIC = 289\r
-WATER_DARK_WEAK_1PIC = 290\r
-WATER_DARK_WEAK_2PIC = 291\r
-WATER_DARK_WEAK_3PIC = 292\r
-WATER_LIGHT_1PIC = 293\r
-WATER_LIGHT_2PIC = 294\r
-WATER_LIGHT_3PIC = 295\r
-WATER_DARK_1PIC = 296\r
-WATER_DARK_2PIC = 297\r
-WATER_DARK_3PIC = 298\r
-TROLL_LIGHT_STONEPIC = 299\r
-TROLL_DARK_STONEPIC = 300\r
-TROLL_BLOODY_LT_STONEPIC = 301\r
-TROLL_BLOODY_DK_STONEPIC = 302\r
-LIGHT_BREATH_1PIC = 303\r
-LIGHT_BREATH_2PIC = 304\r
-LIGHT_BREATH_3PIC = 305\r
-DARK_BREATH_1PIC = 306\r
-DARK_BREATH_2PIC = 307\r
-DARK_BREATH_3PIC = 308\r
-EXP_WALL_1PIC = 309\r
-EXP_WALL_2PIC = 310\r
-EXP_WALL_3PIC = 311\r
-WATER_EXP_WALL_1PIC = 312\r
-WATER_EXP_WALL_2PIC = 313\r
-WATER_EXP_WALL_3PIC = 314\r
-W_GEN_DOOR1PIC = 315\r
-W_GEN_DOOR2PIC = 316\r
-W_CRYSTAL_DOORPIC = 317\r
-DMG_BRN_FSTN_LTPIC = 318\r
-DMG_BRN_FSTN_DKPIC = 319\r
-DMG_FIN_FSTN_LTPIC = 320\r
-DMG_FIN_FSTN_DKPIC = 321\r
-STEEL_DOOR1PIC = 322\r
-STEEL_DOOR2PIC = 323\r
-BRN_WINDOW_DARKPIC = 324\r
-GRY_DOOR_LTPIC = 325\r
-GRY_DOOR_DKPIC = 326\r
-BRN_DOOR_LTPIC = 327\r
-BRN_DOOR_DKPIC = 328\r
-GRY_FGSTN_LTPIC = 329\r
-GRY_FGSTN_DKPIC = 330\r
-KUDZU_WEAK_LIGHTPIC = 331\r
-KUDZU_WEAK_DARKPIC = 332\r
-LT_SKEL1PIC = 333\r
-DK_SKEL1PIC = 334\r
-LT_SKEL2PIC = 335\r
-DK_SKEL2PIC = 336\r
-MANICLE_LIGHT_WALLPIC = 337\r
-MANICLE_DARK_WALLPIC = 338\r
-TAP_1PIC = 339\r
-TAP_2PIC = 340\r
-TAP_3PIC = 341\r
-TAP_4PIC = 342\r
-TAP_5PIC = 343\r
-FINALWALLPIC = 344\r
-WATER_DOOR1_PIC = 345\r
-WATER_DOOR2_PIC = 346\r
-LASTWALLPIC = 347\r
-\r
-HAND1PICM = 348\r
-\r
-NORTHICONSPR = 349\r
-\r
-LEVEL1TEXT = 640\r
-LEVEL2TEXT = 641\r
-LEVEL3TEXT = 642\r
-LEVEL4TEXT = 643\r
-LEVEL5TEXT = 644\r
-LEVEL6TEXT = 645\r
-LEVEL7TEXT = 646\r
-LEVEL8TEXT = 647\r
-LEVEL9TEXT = 648\r
-LEVEL10TEXT = 649\r
-LEVEL11TEXT = 650\r
-LEVEL12TEXT = 651\r
-LEVEL13TEXT = 652\r
-LEVEL14TEXT = 653\r
-LEVEL15TEXT = 654\r
-LEVEL16TEXT = 655\r
-LEVEL17TEXT = 656\r
-PIRACY = 657\r
-\r
-SKELDUDE_LUMP_START = 22\r
-SKELDUDE_LUMP_END = 31\r
-\r
-TOMBSTONES_LUMP_START = 32\r
-TOMBSTONES_LUMP_END = 34\r
-\r
-OBJ_WARP_LUMP_START = 35\r
-OBJ_WARP_LUMP_END = 38\r
-\r
-EYE_LUMP_START = 39\r
-EYE_LUMP_END = 49\r
-\r
-ZOMBIE_LUMP_START = 50\r
-ZOMBIE_LUMP_END = 61\r
-\r
-BOLT_LUMP_START = 62\r
-BOLT_LUMP_END = 64\r
-\r
-NUKE_LUMP_START = 65\r
-NUKE_LUMP_END = 67\r
-\r
-TIME_LUMP_START = 68\r
-TIME_LUMP_END = 69\r
-\r
-O_WATER_CHEST_LUMP_START = 70\r
-O_WATER_CHEST_LUMP_END = 71\r
-\r
-POTION_LUMP_START = 72\r
-POTION_LUMP_END = 72\r
-\r
-RKEY_LUMP_START = 73\r
-RKEY_LUMP_END = 73\r
-\r
-YKEY_LUMP_START = 74\r
-YKEY_LUMP_END = 74\r
-\r
-GKEY_LUMP_START = 75\r
-GKEY_LUMP_END = 75\r
-\r
-BKEY_LUMP_START = 76\r
-BKEY_LUMP_END = 76\r
-\r
-RGEM_LUMP_START = 77\r
-RGEM_LUMP_END = 78\r
-\r
-GGEM_LUMP_START = 79\r
-GGEM_LUMP_END = 80\r
-\r
-BGEM_LUMP_START = 81\r
-BGEM_LUMP_END = 82\r
-\r
-YGEM_LUMP_START = 83\r
-YGEM_LUMP_END = 84\r
-\r
-PGEM_LUMP_START = 85\r
-PGEM_LUMP_END = 86\r
-\r
-CHEST_LUMP_START = 87\r
-CHEST_LUMP_END = 87\r
-\r
-PLAYER_LUMP_START = 88\r
-PLAYER_LUMP_END = 92\r
-\r
-REDDEMON_LUMP_START = 93\r
-REDDEMON_LUMP_END = 103\r
-\r
-MAGE_LUMP_START = 104\r
-MAGE_LUMP_END = 109\r
-\r
-BAT_LUMP_START = 110\r
-BAT_LUMP_END = 115\r
-\r
-GREL_LUMP_START = 116\r
-GREL_LUMP_END = 126\r
-\r
-GODESS_LUMP_START = 127\r
-GODESS_LUMP_END = 136\r
-\r
-ANT_LUMP_START = 137\r
-ANT_LUMP_END = 145\r
-\r
-FATDEMON_LUMP_START = 146\r
-FATDEMON_LUMP_END = 157\r
-\r
-SUCCUBUS_LUMP_START = 158\r
-SUCCUBUS_LUMP_END = 167\r
-\r
-TREE_LUMP_START = 168\r
-TREE_LUMP_END = 177\r
-\r
-DRAGON_LUMP_START = 178\r
-DRAGON_LUMP_END = 193\r
-\r
-BUNNY_LUMP_START = 194\r
-BUNNY_LUMP_END = 204\r
-\r
-ARCH1_LUMP_START = 205\r
-ARCH1_LUMP_END = 205\r
-\r
-ARCH2_LUMP_START = 206\r
-ARCH2_LUMP_END = 206\r
-\r
-ARCH3_LUMP_START = 207\r
-ARCH3_LUMP_END = 207\r
-\r
-ARCH4_LUMP_START = 208\r
-ARCH4_LUMP_END = 208\r
-\r
-ARCH5_LUMP_START = 209\r
-ARCH5_LUMP_END = 209\r
-\r
-ARCH6_LUMP_START = 210\r
-ARCH6_LUMP_END = 210\r
-\r
-ARCH7_LUMP_START = 211\r
-ARCH7_LUMP_END = 211\r
-\r
-ARCH8_LUMP_START = 212\r
-ARCH8_LUMP_END = 212\r
-\r
-ARCH9_LUMP_START = 213\r
-ARCH9_LUMP_END = 213\r
-\r
-ARCH10_LUMP_START = 214\r
-ARCH10_LUMP_END = 214\r
-\r
-ARCH11_LUMP_START = 215\r
-ARCH11_LUMP_END = 215\r
-\r
-ARCH12_LUMP_START = 216\r
-ARCH12_LUMP_END = 216\r
-\r
-ARCH13_LUMP_START = 217\r
-ARCH13_LUMP_END = 217\r
-\r
-ANTHILL_LUMP_START = 218\r
-ANTHILL_LUMP_END = 218\r
-\r
-COLUMN_LUMP_START = 219\r
-COLUMN_LUMP_END = 219\r
-\r
-SULPHURGAS_LUMP_START = 220\r
-SULPHURGAS_LUMP_END = 222\r
-\r
-FIREPOT_LUMP_START = 223\r
-FIREPOT_LUMP_END = 224\r
-\r
-SKELHANG_LUMP_START = 225\r
-SKELHANG_LUMP_END = 225\r
-\r
-FORCEFIELD_LUMP_START = 226\r
-FORCEFIELD_LUMP_END = 229\r
-\r
-FOUNTAIN_LUMP_START = 230\r
-FOUNTAIN_LUMP_END = 230\r
-\r
-\r
-;\r
-; Amount of each data item\r
-;\r
-NUMCHUNKS = 658\r
-NUMFONT = 1\r
-NUMFONTM = 0\r
-NUMPICS = 344\r
-NUMPICM = 1\r
-NUMSPRITES = 1\r
-NUMTILE8 = 108\r
-NUMTILE8M = 36\r
-NUMTILE16 = 216\r
-NUMTILE16M = 72\r
-NUMTILE32 = 0\r
-NUMTILE32M = 0\r
-NUMEXTERN = 18\r
-;\r
-; File offsets for data items\r
-;\r
-STRUCTPIC = 0\r
-STRUCTPICM = 1\r
-STRUCTSPRITE = 2\r
-\r
-STARTFONT = 3\r
-STARTFONTM = 4\r
-STARTPICS = 4\r
-STARTPICM = 348\r
-STARTSPRITES = 349\r
-STARTTILE8 = 350\r
-STARTTILE8M = 351\r
-STARTTILE16 = 352\r
-STARTTILE16M = 568\r
-STARTTILE32 = 640\r
-STARTTILE32M = 640\r
-STARTEXTERN = 640\r
-\r
-;\r
-; Thank you for using IGRAB!\r
-;\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//////////////////////////////////////\r
-//\r
-// Graphics .H file for .ARM\r
-// IGRAB-ed on Thu Dec 02 13:58:59 1993\r
-//\r
-//////////////////////////////////////\r
-\r
-typedef enum {\r
- FINALEPIC=4,\r
- STATUSPIC, // 5\r
- FACE5PIC, // 6\r
- FIRSTLATCHPIC, // 7\r
- FACE1PIC, // 8\r
- FACE2PIC, // 9\r
- FACE3PIC, // 10\r
- FACE4PIC, // 11\r
- RADAR_TOPPIC, // 12\r
- RADAR_BOTTOMPIC, // 13\r
- RADAR_RGEMPIC, // 14\r
- RADAR_GGEMPIC, // 15\r
- RADAR_BGEMPIC, // 16\r
- RADAR_YGEMPIC, // 17\r
- RADAR_PGEMPIC, // 18\r
- FIRSTGROUNDPIC, // 19\r
- FIRSTSTRIPPIC, // 20\r
- FIRSTSCALEPIC, // 21\r
- // Lump Start\r
- SKELETON_1PIC, // 22\r
- SKELETON_2PIC, // 23\r
- SKELETON_3PIC, // 24\r
- SKELETON_4PIC, // 25\r
- SKELETON_ATTACK_1PIC, // 26\r
- SKELETON_ATTACK_2PIC, // 27\r
- SKELETON_ATTACK_3PIC, // 28\r
- SKELETON_OUCHPIC, // 29\r
- SKELETON_DEATH_1PIC, // 30\r
- SKELETON_DEATH_2PIC, // 31\r
- // Lump Start\r
- TOMB1PIC, // 32\r
- TOMB2PIC, // 33\r
- TOMB3PIC, // 34\r
- // Lump Start\r
- OBJ_WARP1PIC, // 35\r
- OBJ_WARP2PIC, // 36\r
- OBJ_WARP3PIC, // 37\r
- OBJ_WARP4PIC, // 38\r
- // Lump Start\r
- EYE_WALK1PIC, // 39\r
- EYE_WALK2PIC, // 40\r
- EYE_WALK3PIC, // 41\r
- EYE_OUCH1PIC, // 42\r
- EYE_OUCH2PIC, // 43\r
- EYE_DEATH1PIC, // 44\r
- EYE_DEATH2PIC, // 45\r
- EYE_DEATH3PIC, // 46\r
- EYE_SCOWLPIC, // 47\r
- EYE_SHOT1PIC, // 48\r
- EYE_SHOT2PIC, // 49\r
- // Lump Start\r
- ZOMB_APPEAR1PIC, // 50\r
- ZOMB_APPEAR2PIC, // 51\r
- ZOMB_APPEAR3PIC, // 52\r
- ZOMB_APPEAR4PIC, // 53\r
- ZOMB_WALK1PIC, // 54\r
- ZOMB_WALK2PIC, // 55\r
- ZOMB_WALK3PIC, // 56\r
- ZOMB_OUCHPIC, // 57\r
- ZOMB_ATTACKPIC, // 58\r
- ZOMB_DIE1PIC, // 59\r
- ZOMB_DIE2PIC, // 60\r
- ZOMB_DIE3PIC, // 61\r
- // Lump Start\r
- BOLTOBJPIC, // 62\r
- BOLT2OBJPIC, // 63\r
- BOLT3OBJPIC, // 64\r
- // Lump Start\r
- NUKEOBJPIC, // 65\r
- NUKE2OBJPIC, // 66\r
- NUKE3OBJPIC, // 67\r
- // Lump Start\r
- TIMEOBJ1PIC, // 68\r
- TIMEOBJ2PIC, // 69\r
- // Lump Start\r
- O_WATER_CHEST1PIC, // 70\r
- O_WATER_CHEST2PIC, // 71\r
- // Lump Start\r
- POTIONOBJPIC, // 72\r
- // Lump Start\r
- RKEYOBJPIC, // 73\r
- // Lump Start\r
- YKEYOBJPIC, // 74\r
- // Lump Start\r
- GKEYOBJPIC, // 75\r
- // Lump Start\r
- BKEYOBJPIC, // 76\r
- // Lump Start\r
- RGEM1PIC, // 77\r
- RGEM2PIC, // 78\r
- // Lump Start\r
- GGEM1PIC, // 79\r
- GGEM2PIC, // 80\r
- // Lump Start\r
- BGEM1PIC, // 81\r
- BGEM2PIC, // 82\r
- // Lump Start\r
- YGEM1PIC, // 83\r
- YGEM2PIC, // 84\r
- // Lump Start\r
- PGEM1PIC, // 85\r
- PGEM2PIC, // 86\r
- // Lump Start\r
- CHESTOBJPIC, // 87\r
- // Lump Start\r
- PSHOT1PIC, // 88\r
- PSHOT2PIC, // 89\r
- PSHOT_EXP1PIC, // 90\r
- PSHOT_EXP2PIC, // 91\r
- PSHOT_EXP3PIC, // 92\r
- // Lump Start\r
- RED_DEMON1PIC, // 93\r
- RED_DEMON2PIC, // 94\r
- RED_DEMON3PIC, // 95\r
- RED_DEMON4PIC, // 96\r
- RED_DEMONATTACK1PIC, // 97\r
- RED_DEMONATTACK2PIC, // 98\r
- RED_DEMONATTACK3PIC, // 99\r
- RED_DEMONOUCHPIC, // 100\r
- RED_DEMONDIE1PIC, // 101\r
- RED_DEMONDIE2PIC, // 102\r
- RED_DEMONDIE3PIC, // 103\r
- // Lump Start\r
- MAGE1PIC, // 104\r
- MAGE2PIC, // 105\r
- MAGEOUCHPIC, // 106\r
- MAGEATTACKPIC, // 107\r
- MAGEDIE1PIC, // 108\r
- MAGEDIE2PIC, // 109\r
- // Lump Start\r
- BAT1PIC, // 110\r
- BAT2PIC, // 111\r
- BAT3PIC, // 112\r
- BAT4PIC, // 113\r
- BATDIE1PIC, // 114\r
- BATDIE2PIC, // 115\r
- // Lump Start\r
- GREL1PIC, // 116\r
- GREL2PIC, // 117\r
- GRELATTACKPIC, // 118\r
- GRELHITPIC, // 119\r
- GRELDIE1PIC, // 120\r
- GRELDIE2PIC, // 121\r
- GRELDIE3PIC, // 122\r
- GRELDIE4PIC, // 123\r
- GRELDIE5PIC, // 124\r
- GRELDIE6PIC, // 125\r
- SKULL_SHOTPIC, // 126\r
- // Lump Start\r
- GODESS_WALK1PIC, // 127\r
- GODESS_WALK2PIC, // 128\r
- GODESS_WALK3PIC, // 129\r
- GODESS_ATTACK1PIC, // 130\r
- GODESS_ATTACK2PIC, // 131\r
- GODESS_ATTACK3PIC, // 132\r
- GODESS_STATUEPIC, // 133\r
- GODESS_OUCHPIC, // 134\r
- GODESS_DEATH1PIC, // 135\r
- GODESS_DEATH2PIC, // 136\r
- // Lump Start\r
- ANT_EGG1PIC, // 137\r
- ANT_EGG2PIC, // 138\r
- ANT_WALK1PIC, // 139\r
- ANT_WALK2PIC, // 140\r
- ANT_WALK3PIC, // 141\r
- ANT_ATTACKPIC, // 142\r
- ANT_DEATH1PIC, // 143\r
- ANT_DEATH2PIC, // 144\r
- ANT_DEATH3PIC, // 145\r
- // Lump Start\r
- FATDEMON_WALK1PIC, // 146\r
- FATDEMON_WALK2PIC, // 147\r
- FATDEMON_WALK3PIC, // 148\r
- FATDEMON_WALK4PIC, // 149\r
- FATDEMON_ATTACK1PIC, // 150\r
- FATDEMON_ATTACK2PIC, // 151\r
- FATDEMON_OUCHPIC, // 152\r
- FATDEMON_BLOWUP1PIC, // 153\r
- FATDEMON_BLOWUP2PIC, // 154\r
- FATDEMON_BLOWUP3PIC, // 155\r
- FATDEMON_EXPLODEPIC, // 156\r
- FATDEMON_FEETPIC, // 157\r
- // Lump Start\r
- SUCCUBUS_WALK1PIC, // 158\r
- SUCCUBUS_WALK2PIC, // 159\r
- SUCCUBUS_WALK3PIC, // 160\r
- SUCCUBUS_WALK4PIC, // 161\r
- SUCCUBUS_ATTACK1PIC, // 162\r
- SUCCUBUS_ATTACK2PIC, // 163\r
- SUCCUBUS_OUCHPIC, // 164\r
- SUCCUBUS_DEATH1PIC, // 165\r
- SUCCUBUS_DEATH2PIC, // 166\r
- SUCCUBUS_SHOT1PIC, // 167\r
- // Lump Start\r
- TREE_IDLEPIC, // 168\r
- TREE_AWAKENINGPIC, // 169\r
- TREE_WALK1PIC, // 170\r
- TREE_WALK2PIC, // 171\r
- TREE_ATTACK1PIC, // 172\r
- TREE_ATTACK2PIC, // 173\r
- TREE_ATTACK3PIC, // 174\r
- TREE_DEATH1PIC, // 175\r
- TREE_DEATH2PIC, // 176\r
- TREE_DEATH3PIC, // 177\r
- // Lump Start\r
- DRAGON_BUBBLES1PIC, // 178\r
- DRAGON_BUBBLES2PIC, // 179\r
- DRAGON_EYESPIC, // 180\r
- DRAGON_RISE1PIC, // 181\r
- DRAGON_RISE2PIC, // 182\r
- DRAGON_WALK1PIC, // 183\r
- DRAGON_WALK2PIC, // 184\r
- DRAGON_WALK3PIC, // 185\r
- DRAGON_WALK4PIC, // 186\r
- DRAGON_ATTACK1PIC, // 187\r
- DRAGON_ATTACK2PIC, // 188\r
- DRAGON_ATTACK3PIC, // 189\r
- DRAGON_OUCHPIC, // 190\r
- DRAGON_DEATH1PIC, // 191\r
- DRAGON_DEATH2PIC, // 192\r
- DRAGON_DEATH3PIC, // 193\r
- // Lump Start\r
- BUNNY_LEFT1PIC, // 194\r
- BUNNY_LEFT2PIC, // 195\r
- BUNNY_RIGHT1PIC, // 196\r
- BUNNY_RIGHT2PIC, // 197\r
- BUNNY_META1PIC, // 198\r
- BUNNY_META2PIC, // 199\r
- BUNNY_WALK1PIC, // 200\r
- BUNNY_WALK2PIC, // 201\r
- BUNNY_OUCHPIC, // 202\r
- BUNNY_DEATH1PIC, // 203\r
- BUNNY_DEATH2PIC, // 204\r
- // Lump Start\r
- ARCH1PIC, // 205\r
- // Lump Start\r
- ARCH2PIC, // 206\r
- // Lump Start\r
- ARCH3PIC, // 207\r
- // Lump Start\r
- ARCH4PIC, // 208\r
- // Lump Start\r
- ARCH5PIC, // 209\r
- // Lump Start\r
- ARCH6PIC, // 210\r
- // Lump Start\r
- ARCH7PIC, // 211\r
- // Lump Start\r
- ARCH8PIC, // 212\r
- // Lump Start\r
- ARCH9PIC, // 213\r
- // Lump Start\r
- ARCH10PIC, // 214\r
- // Lump Start\r
- ARCH11PIC, // 215\r
- // Lump Start\r
- ARCH12PIC, // 216\r
- // Lump Start\r
- ARCH13PIC, // 217\r
- // Lump Start\r
- ANT_HILLPIC, // 218\r
- // Lump Start\r
- COLUMNPIC, // 219\r
- // Lump Start\r
- SULPHUR_GAS_1PIC, // 220\r
- SULPHUR_GAS_2PIC, // 221\r
- SULPHUR_GAS_3PIC, // 222\r
- // Lump Start\r
- FIRE_POT_1PIC, // 223\r
- FIRE_POT_2PIC, // 224\r
- // Lump Start\r
- SKEL_HANGPIC, // 225\r
- // Lump Start\r
- FORCE_FIELD_1PIC, // 226\r
- FORCE_FIELD_2PIC, // 227\r
- FORCE_FIELD_3PIC, // 228\r
- FORCE_FIELD_4PIC, // 229\r
- // Lump Start\r
- WFOUNTAINPIC, // 230\r
- FIRSTWALLPIC, // 231\r
- CRYSTAL_LIGHT_1PIC, // 232\r
- CRYSTAL_LIGHT_2PIC, // 233\r
- CRYSTAL_LIGHT_3PIC, // 234\r
- CRYSTAL_LIGHT_4PIC, // 235\r
- CRYSTAL_DARK_1PIC, // 236\r
- CRYSTAL_DARK_2PIC, // 237\r
- CRYSTAL_DARK_3PIC, // 238\r
- CRYSTAL_DARK_4PIC, // 239\r
- FIRE_WALL_1PIC, // 240\r
- FIRE_WALL_2PIC, // 241\r
- FIRE_WALL_3PIC, // 242\r
- FIRE_WALL_4PIC, // 243\r
- BRN_STONE_GATEPIC, // 244\r
- BRN_STONE_WALL_1PIC, // 245\r
- BRN_STONE_WALL_2PIC, // 246\r
- KUDZU_LIGHT_WALLPIC, // 247\r
- KUDZU_DARK_WALLPIC, // 248\r
- HEDGE_WALLPIC, // 249\r
- HEDGE_EYESPIC, // 250\r
- BRN_WINDOW_LIGHTPIC, // 251\r
- ALTAR_LEFTPIC, // 252\r
- ALTAR_RIGHTPIC, // 253\r
- GRAY_LIGHT_WALLPIC, // 254\r
- GRAY_DARK_WALLPIC, // 255\r
- GRAY_LIGHT_SIGNPIC, // 256\r
- GRAY_DARK_SIGNPIC, // 257\r
- MANICLE_LIGHT_BLOODYPIC, // 258\r
- MANICLE_DARK_BLOODYPIC, // 259\r
- LIGHT_CURTAIN_WINDOWPIC, // 260\r
- LIGHT_CURTAIN_WALLPIC, // 261\r
- DARK_CURTAIN_WINDOWPIC, // 262\r
- DARK_CURTAIN_WALLPIC, // 263\r
- BRN_LIGHT_SIGNPIC, // 264\r
- BRN_DARK_SIGNPIC, // 265\r
- LIGHT_STONE_WALLPIC, // 266\r
- DARK_STONE_WALLPIC, // 267\r
- BRN_FLAGSTONE_LIGHT_2PIC, // 268\r
- BRN_FLAGSTONE_DARK_2PIC, // 269\r
- RUST_METAL_LIGHTPIC, // 270\r
- RUST_METAL_DARKPIC, // 271\r
- GRAY_METAL_LIGHTPIC, // 272\r
- GRAY_METAL_DARKPIC, // 273\r
- WEAK_STONE_LIGHTPIC, // 274\r
- WEAK_STONE_DARKPIC, // 275\r
- WEAK_GRAY_RFGSTN_LIGHTPIC, // 276\r
- WEAK_GRAY_RFGSTN_DARKPIC, // 277\r
- WEAK_CRYSTAL_LIGHTPIC, // 278\r
- WEAK_CRYSTAL_DARKPIC, // 279\r
- RED_MUD_LIGHTPIC, // 280\r
- BRN_MUD_DARKPIC, // 281\r
- RED_MUD_WEAK_LIGHTPIC, // 282\r
- BRN_MUD_WEAK_DARKPIC, // 283\r
- HORN_DOORPIC, // 284\r
- CLOSED_DOOR_1PIC, // 285\r
- DOOR_2PIC, // 286\r
- WATER_LIGHT_WEAK_1PIC, // 287\r
- WATER_LIGHT_WEAK_2PIC, // 288\r
- WATER_LIGHT_WEAK_3PIC, // 289\r
- WATER_DARK_WEAK_1PIC, // 290\r
- WATER_DARK_WEAK_2PIC, // 291\r
- WATER_DARK_WEAK_3PIC, // 292\r
- WATER_LIGHT_1PIC, // 293\r
- WATER_LIGHT_2PIC, // 294\r
- WATER_LIGHT_3PIC, // 295\r
- WATER_DARK_1PIC, // 296\r
- WATER_DARK_2PIC, // 297\r
- WATER_DARK_3PIC, // 298\r
- TROLL_LIGHT_STONEPIC, // 299\r
- TROLL_DARK_STONEPIC, // 300\r
- TROLL_BLOODY_LT_STONEPIC, // 301\r
- TROLL_BLOODY_DK_STONEPIC, // 302\r
- LIGHT_BREATH_1PIC, // 303\r
- LIGHT_BREATH_2PIC, // 304\r
- LIGHT_BREATH_3PIC, // 305\r
- DARK_BREATH_1PIC, // 306\r
- DARK_BREATH_2PIC, // 307\r
- DARK_BREATH_3PIC, // 308\r
- EXP_WALL_1PIC, // 309\r
- EXP_WALL_2PIC, // 310\r
- EXP_WALL_3PIC, // 311\r
- WATER_EXP_WALL_1PIC, // 312\r
- WATER_EXP_WALL_2PIC, // 313\r
- WATER_EXP_WALL_3PIC, // 314\r
- W_GEN_DOOR1PIC, // 315\r
- W_GEN_DOOR2PIC, // 316\r
- W_CRYSTAL_DOORPIC, // 317\r
- DMG_BRN_FSTN_LTPIC, // 318\r
- DMG_BRN_FSTN_DKPIC, // 319\r
- DMG_FIN_FSTN_LTPIC, // 320\r
- DMG_FIN_FSTN_DKPIC, // 321\r
- STEEL_DOOR1PIC, // 322\r
- STEEL_DOOR2PIC, // 323\r
- BRN_WINDOW_DARKPIC, // 324\r
- GRY_DOOR_LTPIC, // 325\r
- GRY_DOOR_DKPIC, // 326\r
- BRN_DOOR_LTPIC, // 327\r
- BRN_DOOR_DKPIC, // 328\r
- GRY_FGSTN_LTPIC, // 329\r
- GRY_FGSTN_DKPIC, // 330\r
- KUDZU_WEAK_LIGHTPIC, // 331\r
- KUDZU_WEAK_DARKPIC, // 332\r
- LT_SKEL1PIC, // 333\r
- DK_SKEL1PIC, // 334\r
- LT_SKEL2PIC, // 335\r
- DK_SKEL2PIC, // 336\r
- MANICLE_LIGHT_WALLPIC, // 337\r
- MANICLE_DARK_WALLPIC, // 338\r
- TAP_1PIC, // 339\r
- TAP_2PIC, // 340\r
- TAP_3PIC, // 341\r
- TAP_4PIC, // 342\r
- TAP_5PIC, // 343\r
- FINALWALLPIC, // 344\r
- WATER_DOOR1_PIC, // 345\r
- WATER_DOOR2_PIC, // 346\r
- LASTWALLPIC, // 347\r
-\r
- HAND1PICM=348,\r
-\r
- NORTHICONSPR=349,\r
-\r
- LEVEL1TEXT=640,\r
- LEVEL2TEXT, // 641\r
- LEVEL3TEXT, // 642\r
- LEVEL4TEXT, // 643\r
- LEVEL5TEXT, // 644\r
- LEVEL6TEXT, // 645\r
- LEVEL7TEXT, // 646\r
- LEVEL8TEXT, // 647\r
- LEVEL9TEXT, // 648\r
- LEVEL10TEXT, // 649\r
- LEVEL11TEXT, // 650\r
- LEVEL12TEXT, // 651\r
- LEVEL13TEXT, // 652\r
- LEVEL14TEXT, // 653\r
- LEVEL15TEXT, // 654\r
- LEVEL16TEXT, // 655\r
- LEVEL17TEXT, // 656\r
- PIRACY, // 657\r
- ENUMEND\r
- } graphicnums;\r
-\r
-//\r
-// Data LUMPs\r
-//\r
-#define SKELDUDE_LUMP_START 22\r
-#define SKELDUDE_LUMP_END 31\r
-\r
-#define TOMBSTONES_LUMP_START 32\r
-#define TOMBSTONES_LUMP_END 34\r
-\r
-#define OBJ_WARP_LUMP_START 35\r
-#define OBJ_WARP_LUMP_END 38\r
-\r
-#define EYE_LUMP_START 39\r
-#define EYE_LUMP_END 49\r
-\r
-#define ZOMBIE_LUMP_START 50\r
-#define ZOMBIE_LUMP_END 61\r
-\r
-#define BOLT_LUMP_START 62\r
-#define BOLT_LUMP_END 64\r
-\r
-#define NUKE_LUMP_START 65\r
-#define NUKE_LUMP_END 67\r
-\r
-#define TIME_LUMP_START 68\r
-#define TIME_LUMP_END 69\r
-\r
-#define O_WATER_CHEST_LUMP_START 70\r
-#define O_WATER_CHEST_LUMP_END 71\r
-\r
-#define POTION_LUMP_START 72\r
-#define POTION_LUMP_END 72\r
-\r
-#define RKEY_LUMP_START 73\r
-#define RKEY_LUMP_END 73\r
-\r
-#define YKEY_LUMP_START 74\r
-#define YKEY_LUMP_END 74\r
-\r
-#define GKEY_LUMP_START 75\r
-#define GKEY_LUMP_END 75\r
-\r
-#define BKEY_LUMP_START 76\r
-#define BKEY_LUMP_END 76\r
-\r
-#define RGEM_LUMP_START 77\r
-#define RGEM_LUMP_END 78\r
-\r
-#define GGEM_LUMP_START 79\r
-#define GGEM_LUMP_END 80\r
-\r
-#define BGEM_LUMP_START 81\r
-#define BGEM_LUMP_END 82\r
-\r
-#define YGEM_LUMP_START 83\r
-#define YGEM_LUMP_END 84\r
-\r
-#define PGEM_LUMP_START 85\r
-#define PGEM_LUMP_END 86\r
-\r
-#define CHEST_LUMP_START 87\r
-#define CHEST_LUMP_END 87\r
-\r
-#define PLAYER_LUMP_START 88\r
-#define PLAYER_LUMP_END 92\r
-\r
-#define REDDEMON_LUMP_START 93\r
-#define REDDEMON_LUMP_END 103\r
-\r
-#define MAGE_LUMP_START 104\r
-#define MAGE_LUMP_END 109\r
-\r
-#define BAT_LUMP_START 110\r
-#define BAT_LUMP_END 115\r
-\r
-#define GREL_LUMP_START 116\r
-#define GREL_LUMP_END 126\r
-\r
-#define GODESS_LUMP_START 127\r
-#define GODESS_LUMP_END 136\r
-\r
-#define ANT_LUMP_START 137\r
-#define ANT_LUMP_END 145\r
-\r
-#define FATDEMON_LUMP_START 146\r
-#define FATDEMON_LUMP_END 157\r
-\r
-#define SUCCUBUS_LUMP_START 158\r
-#define SUCCUBUS_LUMP_END 167\r
-\r
-#define TREE_LUMP_START 168\r
-#define TREE_LUMP_END 177\r
-\r
-#define DRAGON_LUMP_START 178\r
-#define DRAGON_LUMP_END 193\r
-\r
-#define BUNNY_LUMP_START 194\r
-#define BUNNY_LUMP_END 204\r
-\r
-#define ARCH1_LUMP_START 205\r
-#define ARCH1_LUMP_END 205\r
-\r
-#define ARCH2_LUMP_START 206\r
-#define ARCH2_LUMP_END 206\r
-\r
-#define ARCH3_LUMP_START 207\r
-#define ARCH3_LUMP_END 207\r
-\r
-#define ARCH4_LUMP_START 208\r
-#define ARCH4_LUMP_END 208\r
-\r
-#define ARCH5_LUMP_START 209\r
-#define ARCH5_LUMP_END 209\r
-\r
-#define ARCH6_LUMP_START 210\r
-#define ARCH6_LUMP_END 210\r
-\r
-#define ARCH7_LUMP_START 211\r
-#define ARCH7_LUMP_END 211\r
-\r
-#define ARCH8_LUMP_START 212\r
-#define ARCH8_LUMP_END 212\r
-\r
-#define ARCH9_LUMP_START 213\r
-#define ARCH9_LUMP_END 213\r
-\r
-#define ARCH10_LUMP_START 214\r
-#define ARCH10_LUMP_END 214\r
-\r
-#define ARCH11_LUMP_START 215\r
-#define ARCH11_LUMP_END 215\r
-\r
-#define ARCH12_LUMP_START 216\r
-#define ARCH12_LUMP_END 216\r
-\r
-#define ARCH13_LUMP_START 217\r
-#define ARCH13_LUMP_END 217\r
-\r
-#define ANTHILL_LUMP_START 218\r
-#define ANTHILL_LUMP_END 218\r
-\r
-#define COLUMN_LUMP_START 219\r
-#define COLUMN_LUMP_END 219\r
-\r
-#define SULPHURGAS_LUMP_START 220\r
-#define SULPHURGAS_LUMP_END 222\r
-\r
-#define FIREPOT_LUMP_START 223\r
-#define FIREPOT_LUMP_END 224\r
-\r
-#define SKELHANG_LUMP_START 225\r
-#define SKELHANG_LUMP_END 225\r
-\r
-#define FORCEFIELD_LUMP_START 226\r
-#define FORCEFIELD_LUMP_END 229\r
-\r
-#define FOUNTAIN_LUMP_START 230\r
-#define FOUNTAIN_LUMP_END 230\r
-\r
-\r
-//\r
-// Amount of each data item\r
-//\r
-#define NUMCHUNKS 658\r
-#define NUMFONT 1\r
-#define NUMFONTM 0\r
-#define NUMPICS 344\r
-#define NUMPICM 1\r
-#define NUMSPRITES 1\r
-#define NUMTILE8 108\r
-#define NUMTILE8M 36\r
-#define NUMTILE16 216\r
-#define NUMTILE16M 72\r
-#define NUMTILE32 0\r
-#define NUMTILE32M 0\r
-#define NUMEXTERNS 18\r
-//\r
-// File offsets for data items\r
-//\r
-#define STRUCTPIC 0\r
-#define STRUCTPICM 1\r
-#define STRUCTSPRITE 2\r
-\r
-#define STARTFONT 3\r
-#define STARTFONTM 4\r
-#define STARTPICS 4\r
-#define STARTPICM 348\r
-#define STARTSPRITES 349\r
-#define STARTTILE8 350\r
-#define STARTTILE8M 351\r
-#define STARTTILE16 352\r
-#define STARTTILE16M 568\r
-#define STARTTILE32 640\r
-#define STARTTILE32M 640\r
-#define STARTEXTERNS 640\r
-\r
-//\r
-// Thank you for using IGRAB!\r
-//\r
+++ /dev/null
-;\r
-; Equates for all .ASM files\r
-;\r
-\r
-;----------------------------------------------------------------------------\r
-\r
-INCLUDE "GFXE_ARM.EQU"\r
-\r
-;----------------------------------------------------------------------------\r
-\r
-CGAGR = 1\r
-EGAGR = 2\r
-VGAGR = 3\r
-\r
-GRMODE = EGAGR\r
-PROFILE = 0 ; 1=keep stats on tile drawing\r
-\r
-SC_INDEX = 03C4h\r
-SC_RESET = 0\r
-SC_CLOCK = 1\r
-SC_MAPMASK = 2\r
-SC_CHARMAP = 3\r
-SC_MEMMODE = 4\r
-\r
-CRTC_INDEX = 03D4h\r
-CRTC_H_TOTAL = 0\r
-CRTC_H_DISPEND = 1\r
-CRTC_H_BLANK = 2\r
-CRTC_H_ENDBLANK = 3\r
-CRTC_H_RETRACE = 4\r
-CRTC_H_ENDRETRACE = 5\r
-CRTC_V_TOTAL = 6\r
-CRTC_OVERFLOW = 7\r
-CRTC_ROWSCAN = 8\r
-CRTC_MAXSCANLINE = 9\r
-CRTC_CURSORSTART = 10\r
-CRTC_CURSOREND = 11\r
-CRTC_STARTHIGH = 12\r
-CRTC_STARTLOW = 13\r
-CRTC_CURSORHIGH = 14\r
-CRTC_CURSORLOW = 15\r
-CRTC_V_RETRACE = 16\r
-CRTC_V_ENDRETRACE = 17\r
-CRTC_V_DISPEND = 18\r
-CRTC_OFFSET = 19\r
-CRTC_UNDERLINE = 20\r
-CRTC_V_BLANK = 21\r
-CRTC_V_ENDBLANK = 22\r
-CRTC_MODE = 23\r
-CRTC_LINECOMPARE = 24\r
-\r
-\r
-GC_INDEX = 03CEh\r
-GC_SETRESET = 0\r
-GC_ENABLESETRESET = 1\r
-GC_COLORCOMPARE = 2\r
-GC_DATAROTATE = 3\r
-GC_READMAP = 4\r
-GC_MODE = 5\r
-GC_MISCELLANEOUS = 6\r
-GC_COLORDONTCARE = 7\r
-GC_BITMASK = 8\r
-\r
-ATR_INDEX = 03c0h\r
-ATR_MODE = 16\r
-ATR_OVERSCAN = 17\r
-ATR_COLORPLANEENABLE = 18\r
-ATR_PELPAN = 19\r
-ATR_COLORSELECT = 20\r
-\r
-STATUS_REGISTER_1 = 03dah\r
-\r
-\r
-MACRO WORDOUT\r
- out dx,ax\r
-ENDM\r
-\r
-if 0\r
-\r
-MACRO WORDOUT\r
- out dx,al\r
- inc dx\r
- xchg al,ah\r
- out dx,al\r
- dec dx\r
- xchg al,ah\r
-ENDM\r
-\r
-endif\r
-\r
-UPDATEWIDE = 22\r
-UPDATEHIGH = 13 ; hack for catacombs\r
-\r
-;\r
-; tile info offsets from segment tinf\r
-;\r
-\r
-SPEED = 402\r
-ANIM = (SPEED+NUMTILE16)\r
-\r
-NORTHWALL = (ANIM+NUMTILE16)\r
-EASTWALL = (NORTHWALL+NUMTILE16M)\r
-SOUTHWALL = (EASTWALL+NUMTILE16M)\r
-WESTWALL = (SOUTHWALL+NUMTILE16M)\r
-MANIM = (WESTWALL+NUMTILE16M)\r
-INTILE = (MANIM+NUMTILE16M)\r
-MSPEED = (INTILE+NUMTILE16M)\r
-\r
-IFE GRMODE-EGAGR\r
-SCREENWIDTH = 40\r
-ENDIF\r
-IFE GRMODE-CGAGR\r
-SCREENWIDTH = 128\r
-ENDIF\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_CA.C\r
-\r
-/*\r
-=============================================================================\r
-\r
-Id Software Caching Manager\r
----------------------------\r
-\r
-Must be started BEFORE the memory manager, because it needs to get the headers\r
-loaded into the data segment\r
-\r
-=============================================================================\r
-*/\r
-\r
-#include "LIB_HEAD.H"\r
-#pragma hdrstop\r
-//#include "ID_STRS.H"\r
-\r
-#pragma warn -pro\r
-#pragma warn -use\r
-\r
-#define THREEBYTEGRSTARTS\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-typedef struct\r
-{\r
- unsigned bit0,bit1; // 0-255 is a character, > is a pointer to a node\r
-} huffnode;\r
-\r
-\r
-typedef struct\r
-{\r
- unsigned RLEWtag;\r
- long headeroffsets[100];\r
- byte tileinfo[];\r
-} mapfiletype;\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-byte _seg *tinf;\r
-int mapon;\r
-\r
-unsigned _seg *mapsegs[3];\r
-maptype _seg *mapheaderseg[NUMMAPS];\r
-byte _seg *audiosegs[NUMSNDCHUNKS];\r
-void _seg *grsegs[NUMCHUNKS];\r
-\r
-byte far grneeded[NUMCHUNKS];\r
-byte ca_levelbit,ca_levelnum;\r
-\r
-int profilehandle,debughandle;\r
-\r
-void (*drawcachebox) (char *title, unsigned numcache);\r
-void (*updatecachebox) (void);\r
-void (*finishcachebox) (void);\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern long far CGAhead;\r
-extern long far EGAhead;\r
-extern byte CGAdict;\r
-extern byte EGAdict;\r
-extern byte far maphead;\r
-extern byte mapdict;\r
-extern byte far audiohead;\r
-extern byte audiodict;\r
-\r
-\r
-long _seg *grstarts; // array of offsets in egagraph, -1 for sparse\r
-long _seg *audiostarts; // array of offsets in audio / audiot\r
-\r
-#ifdef GRHEADERLINKED\r
-huffnode *grhuffman;\r
-#else\r
-huffnode grhuffman[255];\r
-#endif\r
-\r
-#ifdef AUDIOHEADERLINKED\r
-huffnode *audiohuffman;\r
-#else\r
-huffnode audiohuffman[255];\r
-#endif\r
-\r
-\r
-int grhandle; // handle to EGAGRAPH\r
-int maphandle; // handle to MAPTEMP / GAMEMAPS\r
-int audiohandle; // handle to AUDIOT / AUDIO\r
-\r
-long chunkcomplen,chunkexplen;\r
-\r
-SDMode oldsoundmode;\r
-\r
-\r
-\r
-void CAL_DialogDraw (char *title,unsigned numcache);\r
-void CAL_DialogUpdate (void);\r
-void CAL_DialogFinish (void);\r
-void CAL_CarmackExpand (unsigned far *source, unsigned far *dest,\r
- unsigned length);\r
-\r
-\r
-#ifdef THREEBYTEGRSTARTS\r
-#define FILEPOSSIZE 3\r
-//#define GRFILEPOS(c) (*(long far *)(((byte far *)grstarts)+(c)*3)&0xffffff)\r
-long GRFILEPOS(int c)\r
-{\r
- long value;\r
- int offset;\r
-\r
- offset = c*3;\r
-\r
- value = *(long far *)(((byte far *)grstarts)+offset);\r
-\r
- value &= 0x00ffffffl;\r
-\r
- if (value == 0xffffffl)\r
- value = -1;\r
-\r
- return value;\r
-};\r
-#else\r
-#define FILEPOSSIZE 4\r
-#define GRFILEPOS(c) (grstarts[c])\r
-#endif\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOW LEVEL ROUTINES\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-============================\r
-=\r
-= CA_OpenDebug / CA_CloseDebug\r
-=\r
-= Opens a binary file with the handle "debughandle"\r
-=\r
-============================\r
-*/\r
-\r
-void CA_OpenDebug (void)\r
-{\r
- unlink ("DEBUG.TXT");\r
- debughandle = open("DEBUG.TXT", O_CREAT | O_WRONLY | O_TEXT);\r
-}\r
-\r
-void CA_CloseDebug (void)\r
-{\r
- close (debughandle);\r
-}\r
-\r
-\r
-\r
-/*\r
-============================\r
-=\r
-= CAL_GetGrChunkLength\r
-=\r
-= Gets the length of an explicit length chunk (not tiles)\r
-= The file pointer is positioned so the compressed data can be read in next.\r
-=\r
-============================\r
-*/\r
-\r
-void CAL_GetGrChunkLength (int chunk)\r
-{\r
- lseek(grhandle,GRFILEPOS(chunk),SEEK_SET);\r
- read(grhandle,&chunkexplen,sizeof(chunkexplen));\r
- chunkcomplen = GRFILEPOS(chunk+1)-GRFILEPOS(chunk)-4;\r
-}\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= CA_FarRead\r
-=\r
-= Read from a file to a far pointer\r
-=\r
-==========================\r
-*/\r
-\r
-boolean CA_FarRead (int handle, byte far *dest, long length)\r
-{\r
- if (length>0xffffl)\r
- Quit ("CA_FarRead doesn't support 64K reads yet!");\r
-\r
-asm push ds\r
-asm mov bx,[handle]\r
-asm mov cx,[WORD PTR length]\r
-asm mov dx,[WORD PTR dest]\r
-asm mov ds,[WORD PTR dest+2]\r
-asm mov ah,0x3f // READ w/handle\r
-asm int 21h\r
-asm pop ds\r
-asm jnc good\r
- errno = _AX;\r
- return false;\r
-good:\r
-asm cmp ax,[WORD PTR length]\r
-asm je done\r
- errno = EINVFMT; // user manager knows this is bad read\r
- return false;\r
-done:\r
- return true;\r
-}\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= CA_SegWrite\r
-=\r
-= Write from a file to a far pointer\r
-=\r
-==========================\r
-*/\r
-\r
-boolean CA_FarWrite (int handle, byte far *source, long length)\r
-{\r
- if (length>0xffffl)\r
- Quit ("CA_FarWrite doesn't support 64K reads yet!");\r
-\r
-asm push ds\r
-asm mov bx,[handle]\r
-asm mov cx,[WORD PTR length]\r
-asm mov dx,[WORD PTR source]\r
-asm mov ds,[WORD PTR source+2]\r
-asm mov ah,0x40 // WRITE w/handle\r
-asm int 21h\r
-asm pop ds\r
-asm jnc good\r
- errno = _AX;\r
- return false;\r
-good:\r
-asm cmp ax,[WORD PTR length]\r
-asm je done\r
- errno = ENOMEM; // user manager knows this is bad write\r
- return false;\r
-\r
-done:\r
- return true;\r
-}\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= CA_ReadFile\r
-=\r
-= Reads a file into an allready allocated buffer\r
-=\r
-==========================\r
-*/\r
-\r
-boolean CA_ReadFile (char *filename, memptr *ptr)\r
-{\r
- int handle;\r
- long size;\r
-\r
- if ((handle = open(filename,O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- return false;\r
-\r
- size = filelength (handle);\r
- if (!CA_FarRead (handle,*ptr,size))\r
- {\r
- close (handle);\r
- return false;\r
- }\r
- close (handle);\r
- return true;\r
-}\r
-\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= CA_LoadFile\r
-=\r
-= Allocate space for and load a file\r
-=\r
-==========================\r
-*/\r
-\r
-boolean CA_LoadFile (char *filename, memptr *ptr)\r
-{\r
- int handle;\r
- long size;\r
-\r
- if ((handle = open(filename,O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- return false;\r
-\r
- size = filelength (handle);\r
- MM_GetPtr (ptr,size);\r
- if (!CA_FarRead (handle,*ptr,size))\r
- {\r
- close (handle);\r
- return false;\r
- }\r
- close (handle);\r
- return true;\r
-}\r
-\r
-/*\r
-============================================================================\r
-\r
- COMPRESSION routines, see JHUFF.C for more\r
-\r
-============================================================================\r
-*/\r
-\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= CAL_OptimizeNodes\r
-=\r
-= Goes through a huffman table and changes the 256-511 node numbers to the\r
-= actular address of the node. Must be called before CAL_HuffExpand\r
-=\r
-===============\r
-*/\r
-\r
-void CAL_OptimizeNodes (huffnode *table)\r
-{\r
- huffnode *node;\r
- int i;\r
-\r
- node = table;\r
-\r
- for (i=0;i<255;i++)\r
- {\r
- if (node->bit0 >= 256)\r
- node->bit0 = (unsigned)(table+(node->bit0-256));\r
- if (node->bit1 >= 256)\r
- node->bit1 = (unsigned)(table+(node->bit1-256));\r
- node++;\r
- }\r
-}\r
-\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_HuffExpand\r
-=\r
-= Length is the length of the EXPANDED data\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_HuffExpand (byte huge *source, byte huge *dest,\r
- long length,huffnode *hufftable)\r
-{\r
-// unsigned bit,byte,node,code;\r
- unsigned sourceseg,sourceoff,destseg,destoff,endoff;\r
- huffnode *headptr;\r
-// huffnode *nodeon;\r
-\r
- headptr = hufftable+254; // head node is allways node 254\r
-\r
- source++; // normalize\r
- source--;\r
- dest++;\r
- dest--;\r
-\r
- sourceseg = FP_SEG(source);\r
- sourceoff = FP_OFF(source);\r
- destseg = FP_SEG(dest);\r
- destoff = FP_OFF(dest);\r
- endoff = destoff+length;\r
-\r
-//\r
-// ds:si source\r
-// es:di dest\r
-// ss:bx node pointer\r
-//\r
-\r
- if (length <0xfff0)\r
- {\r
-\r
-//--------------------------\r
-// expand less than 64k of data\r
-//--------------------------\r
-\r
-asm mov bx,[headptr]\r
-\r
-asm mov si,[sourceoff]\r
-asm mov di,[destoff]\r
-asm mov es,[destseg]\r
-asm mov ds,[sourceseg]\r
-asm mov ax,[endoff]\r
-\r
-asm mov ch,[si] // load first byte\r
-asm inc si\r
-asm mov cl,1\r
-\r
-expandshort:\r
-asm test ch,cl // bit set?\r
-asm jnz bit1short\r
-asm mov dx,[ss:bx] // take bit0 path from node\r
-asm shl cl,1 // advance to next bit position\r
-asm jc newbyteshort\r
-asm jnc sourceupshort\r
-\r
-bit1short:\r
-asm mov dx,[ss:bx+2] // take bit1 path\r
-asm shl cl,1 // advance to next bit position\r
-asm jnc sourceupshort\r
-\r
-newbyteshort:\r
-asm mov ch,[si] // load next byte\r
-asm inc si\r
-asm mov cl,1 // back to first bit\r
-\r
-sourceupshort:\r
-asm or dh,dh // if dx<256 its a byte, else move node\r
-asm jz storebyteshort\r
-asm mov bx,dx // next node = (huffnode *)code\r
-asm jmp expandshort\r
-\r
-storebyteshort:\r
-asm mov [es:di],dl\r
-asm inc di // write a decopmpressed byte out\r
-asm mov bx,[headptr] // back to the head node for next bit\r
-\r
-asm cmp di,ax // done?\r
-asm jne expandshort\r
- }\r
- else\r
- {\r
-\r
-//--------------------------\r
-// expand more than 64k of data\r
-//--------------------------\r
-\r
- length--;\r
-\r
-asm mov bx,[headptr]\r
-asm mov cl,1\r
-\r
-asm mov si,[sourceoff]\r
-asm mov di,[destoff]\r
-asm mov es,[destseg]\r
-asm mov ds,[sourceseg]\r
-\r
-asm lodsb // load first byte\r
-\r
-expand:\r
-asm test al,cl // bit set?\r
-asm jnz bit1\r
-asm mov dx,[ss:bx] // take bit0 path from node\r
-asm jmp gotcode\r
-bit1:\r
-asm mov dx,[ss:bx+2] // take bit1 path\r
-\r
-gotcode:\r
-asm shl cl,1 // advance to next bit position\r
-asm jnc sourceup\r
-asm lodsb\r
-asm cmp si,0x10 // normalize ds:si\r
-asm jb sinorm\r
-asm mov cx,ds\r
-asm inc cx\r
-asm mov ds,cx\r
-asm xor si,si\r
-sinorm:\r
-asm mov cl,1 // back to first bit\r
-\r
-sourceup:\r
-asm or dh,dh // if dx<256 its a byte, else move node\r
-asm jz storebyte\r
-asm mov bx,dx // next node = (huffnode *)code\r
-asm jmp expand\r
-\r
-storebyte:\r
-asm mov [es:di],dl\r
-asm inc di // write a decopmpressed byte out\r
-asm mov bx,[headptr] // back to the head node for next bit\r
-\r
-asm cmp di,0x10 // normalize es:di\r
-asm jb dinorm\r
-asm mov dx,es\r
-asm inc dx\r
-asm mov es,dx\r
-asm xor di,di\r
-dinorm:\r
-\r
-asm sub [WORD PTR ss:length],1\r
-asm jnc expand\r
-asm dec [WORD PTR ss:length+2]\r
-asm jns expand // when length = ffff ffff, done\r
-\r
- }\r
-\r
-asm mov ax,ss\r
-asm mov ds,ax\r
-\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_CarmackExpand\r
-=\r
-= Length is the length of the EXPANDED data\r
-=\r
-======================\r
-*/\r
-\r
-#define NEARTAG 0xa7\r
-#define FARTAG 0xa8\r
-\r
-void CAL_CarmackExpand (unsigned far *source, unsigned far *dest, unsigned length)\r
-{\r
- unsigned ch,chhigh,count,offset;\r
- unsigned far *copyptr, far *inptr, far *outptr;\r
-\r
- length/=2;\r
-\r
- inptr = source;\r
- outptr = dest;\r
-\r
- while (length)\r
- {\r
- ch = *inptr++;\r
- chhigh = ch>>8;\r
- if (chhigh == NEARTAG)\r
- {\r
- count = ch&0xff;\r
- if (!count)\r
- { // have to insert a word containing the tag byte\r
- ch |= *((unsigned char far *)inptr)++;\r
- *outptr++ = ch;\r
- length--;\r
- }\r
- else\r
- {\r
- offset = *((unsigned char far *)inptr)++;\r
- copyptr = outptr - offset;\r
- length -= count;\r
- while (count--)\r
- *outptr++ = *copyptr++;\r
- }\r
- }\r
- else if (chhigh == FARTAG)\r
- {\r
- count = ch&0xff;\r
- if (!count)\r
- { // have to insert a word containing the tag byte\r
- ch |= *((unsigned char far *)inptr)++;\r
- *outptr++ = ch;\r
- length --;\r
- }\r
- else\r
- {\r
- offset = *inptr++;\r
- copyptr = dest + offset;\r
- length -= count;\r
- while (count--)\r
- *outptr++ = *copyptr++;\r
- }\r
- }\r
- else\r
- {\r
- *outptr++ = ch;\r
- length --;\r
- }\r
- }\r
-}\r
-\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CA_RLEWcompress\r
-=\r
-======================\r
-*/\r
-\r
-long CA_RLEWCompress (unsigned huge *source, long length, unsigned huge *dest,\r
- unsigned rlewtag)\r
-{\r
- long complength;\r
- unsigned value,count,i;\r
- unsigned huge *start,huge *end;\r
-\r
- start = dest;\r
-\r
- end = source + (length+1)/2;\r
-\r
-//\r
-// compress it\r
-//\r
- do\r
- {\r
- count = 1;\r
- value = *source++;\r
- while (*source == value && source<end)\r
- {\r
- count++;\r
- source++;\r
- }\r
- if (count>3 || value == rlewtag)\r
- {\r
- //\r
- // send a tag / count / value string\r
- //\r
- *dest++ = rlewtag;\r
- *dest++ = count;\r
- *dest++ = value;\r
- }\r
- else\r
- {\r
- //\r
- // send word without compressing\r
- //\r
- for (i=1;i<=count;i++)\r
- *dest++ = value;\r
- }\r
-\r
- } while (source<end);\r
-\r
- complength = 2*(dest-start);\r
- return complength;\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CA_RLEWexpand\r
-= length is EXPANDED length\r
-=\r
-======================\r
-*/\r
-\r
-void CA_RLEWexpand (unsigned huge *source, unsigned huge *dest,long length,\r
- unsigned rlewtag)\r
-{\r
-// unsigned value,count,i;\r
- unsigned huge *end;\r
- unsigned sourceseg,sourceoff,destseg,destoff,endseg,endoff;\r
-\r
-\r
-//\r
-// expand it\r
-//\r
-#if 0\r
- do\r
- {\r
- value = *source++;\r
- if (value != rlewtag)\r
- //\r
- // uncompressed\r
- //\r
- *dest++=value;\r
- else\r
- {\r
- //\r
- // compressed string\r
- //\r
- count = *source++;\r
- value = *source++;\r
- for (i=1;i<=count;i++)\r
- *dest++ = value;\r
- }\r
- } while (dest<end);\r
-#endif\r
-\r
- end = dest + (length)/2;\r
- sourceseg = FP_SEG(source);\r
- sourceoff = FP_OFF(source);\r
- destseg = FP_SEG(dest);\r
- destoff = FP_OFF(dest);\r
- endseg = FP_SEG(end);\r
- endoff = FP_OFF(end);\r
-\r
-\r
-//\r
-// ax = source value\r
-// bx = tag value\r
-// cx = repeat counts\r
-// dx = scratch\r
-//\r
-// NOTE: A repeat count that produces 0xfff0 bytes can blow this!\r
-//\r
-\r
-asm mov bx,rlewtag\r
-asm mov si,sourceoff\r
-asm mov di,destoff\r
-asm mov es,destseg\r
-asm mov ds,sourceseg\r
-\r
-expand:\r
-asm lodsw\r
-asm cmp ax,bx\r
-asm je repeat\r
-asm stosw\r
-asm jmp next\r
-\r
-repeat:\r
-asm lodsw\r
-asm mov cx,ax // repeat count\r
-asm lodsw // repeat value\r
-asm rep stosw\r
-\r
-next:\r
-\r
-asm cmp si,0x10 // normalize ds:si\r
-asm jb sinorm\r
-asm mov ax,si\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm mov dx,ds\r
-asm add dx,ax\r
-asm mov ds,dx\r
-asm and si,0xf\r
-sinorm:\r
-asm cmp di,0x10 // normalize es:di\r
-asm jb dinorm\r
-asm mov ax,di\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm mov dx,es\r
-asm add dx,ax\r
-asm mov es,dx\r
-asm and di,0xf\r
-dinorm:\r
-\r
-asm cmp di,ss:endoff\r
-asm jne expand\r
-asm mov ax,es\r
-asm cmp ax,ss:endseg\r
-asm jb expand\r
-\r
-asm mov ax,ss\r
-asm mov ds,ax\r
-\r
-}\r
-\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- CACHE MANAGER ROUTINES\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_SetupGrFile\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_SetupGrFile (void)\r
-{\r
- int handle;\r
- memptr compseg;\r
-\r
-#ifdef GRHEADERLINKED\r
-\r
-#if GRMODE == EGAGR\r
- grhuffman = (huffnode *)&EGAdict;\r
- grstarts = (long _seg *)FP_SEG(&EGAhead);\r
-#endif\r
-#if GRMODE == CGAGR\r
- grhuffman = (huffnode *)&CGAdict;\r
- grstarts = (long _seg *)FP_SEG(&CGAhead);\r
-#endif\r
-\r
- CAL_OptimizeNodes (grhuffman);\r
-\r
-#else\r
-\r
-//\r
-// load ???dict.ext (huffman dictionary for graphics files)\r
-//\r
-\r
- if ((handle = open(GREXT"DICT."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open "GREXT"DICT."EXT"!");\r
-\r
- read(handle, &grhuffman, sizeof(grhuffman));\r
- close(handle);\r
- CAL_OptimizeNodes (grhuffman);\r
-//\r
-// load the data offsets from ???head.ext\r
-//\r
- MM_GetPtr (&(memptr)grstarts,(NUMCHUNKS+1)*FILEPOSSIZE);\r
-\r
- if ((handle = open(GREXT"HEAD."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open "GREXT"HEAD."EXT"!");\r
-\r
- CA_FarRead(handle, (memptr)grstarts, (NUMCHUNKS+1)*FILEPOSSIZE);\r
-\r
- close(handle);\r
-\r
-\r
-#endif\r
-\r
-//\r
-// Open the graphics file, leaving it open until the game is finished\r
-//\r
- grhandle = open(GREXT"GRAPH."EXT, O_RDONLY | O_BINARY);\r
- if (grhandle == -1)\r
- Quit ("Cannot open "GREXT"GRAPH."EXT"!");\r
-\r
-\r
-//\r
-// load the pic and sprite headers into the arrays in the data segment\r
-//\r
-#if NUMPICS>0\r
- MM_GetPtr(&(memptr)pictable,NUMPICS*sizeof(pictabletype));\r
- CAL_GetGrChunkLength(STRUCTPIC); // position file pointer\r
- MM_GetPtr(&compseg,chunkcomplen);\r
- CA_FarRead (grhandle,compseg,chunkcomplen);\r
- CAL_HuffExpand (compseg, (byte huge *)pictable,NUMPICS*sizeof(pictabletype),grhuffman);\r
- MM_FreePtr(&compseg);\r
-#endif\r
-\r
-#if NUMPICM>0\r
- MM_GetPtr(&(memptr)picmtable,NUMPICM*sizeof(pictabletype));\r
- CAL_GetGrChunkLength(STRUCTPICM); // position file pointer\r
- MM_GetPtr(&compseg,chunkcomplen);\r
- CA_FarRead (grhandle,compseg,chunkcomplen);\r
- CAL_HuffExpand (compseg, (byte huge *)picmtable,NUMPICS*sizeof(pictabletype),grhuffman);\r
- MM_FreePtr(&compseg);\r
-#endif\r
-\r
-#if NUMSPRITES>0\r
- MM_GetPtr(&(memptr)spritetable,NUMSPRITES*sizeof(spritetabletype));\r
- CAL_GetGrChunkLength(STRUCTSPRITE); // position file pointer\r
- MM_GetPtr(&compseg,chunkcomplen);\r
- CA_FarRead (grhandle,compseg,chunkcomplen);\r
- CAL_HuffExpand (compseg, (byte huge *)spritetable,NUMSPRITES*sizeof(spritetabletype),grhuffman);\r
- MM_FreePtr(&compseg);\r
-#endif\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_SetupMapFile\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_SetupMapFile (void)\r
-{\r
- int handle;\r
- long length;\r
-\r
-//\r
-// load maphead.ext (offsets and tileinfo for map file)\r
-//\r
-#ifndef MAPHEADERLINKED\r
- if ((handle = open("MAPHEAD."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open MAPHEAD."EXT"!");\r
- length = filelength(handle);\r
- MM_GetPtr (&(memptr)tinf,length);\r
- CA_FarRead(handle, tinf, length);\r
- close(handle);\r
-#else\r
-\r
- tinf = (byte _seg *)FP_SEG(&maphead);\r
-\r
-#endif\r
-\r
-//\r
-// open the data file\r
-//\r
-#ifdef MAPHEADERLINKED\r
- if ((maphandle = open("GAMEMAPS."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open GAMEMAPS."EXT"!");\r
-#else\r
- if ((maphandle = open("MAPTEMP."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open MAPTEMP."EXT"!");\r
-#endif\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_SetupAudioFile\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_SetupAudioFile (void)\r
-{\r
- int handle;\r
- long length;\r
-\r
-//\r
-// load maphead.ext (offsets and tileinfo for map file)\r
-//\r
-#ifndef AUDIOHEADERLINKED\r
- if ((handle = open("AUDIOHED."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open AUDIOHED."EXT"!");\r
- length = filelength(handle);\r
- MM_GetPtr (&(memptr)audiostarts,length);\r
- CA_FarRead(handle, (byte far *)audiostarts, length);\r
- close(handle);\r
-#else\r
- audiohuffman = (huffnode *)&audiodict;\r
- CAL_OptimizeNodes (audiohuffman);\r
- audiostarts = (long _seg *)FP_SEG(&audiohead);\r
-#endif\r
-\r
-//\r
-// open the data file\r
-//\r
-#ifndef AUDIOHEADERLINKED\r
- if ((audiohandle = open("AUDIOT."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open AUDIOT."EXT"!");\r
-#else\r
- if ((audiohandle = open("AUDIO."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open AUDIO."EXT"!");\r
-#endif\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CA_Startup\r
-=\r
-= Open all files and load in headers\r
-=\r
-======================\r
-*/\r
-\r
-void CA_Startup (void)\r
-{\r
-#ifdef PROFILE\r
- unlink ("PROFILE.TXT");\r
- profilehandle = open("PROFILE.TXT", O_CREAT | O_WRONLY | O_TEXT);\r
-#endif\r
-\r
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("AUDIO."EXT,NULL,2))\r
- Quit("CA_Startup(): Can't find audio files.");\r
-//\r
-// MDM end\r
-\r
-#ifndef NOAUDIO\r
- CAL_SetupAudioFile ();\r
-#endif\r
-\r
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("GAMEMAPS."EXT,NULL,1))\r
- Quit("CA_Startup(): Can't find level files.");\r
-//\r
-// MDM end\r
-\r
-#ifndef NOMAPS\r
- CAL_SetupMapFile ();\r
-#endif\r
-\r
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("EGAGRAPH."EXT,NULL,2))\r
- Quit("CA_Startup(): Can't find graphics files.");\r
-//\r
-// MDM end\r
-\r
-#ifndef NOGRAPHICS\r
- CAL_SetupGrFile ();\r
-#endif\r
-\r
- mapon = -1;\r
- ca_levelbit = 1;\r
- ca_levelnum = 0;\r
-\r
- drawcachebox = CAL_DialogDraw;\r
- updatecachebox = CAL_DialogUpdate;\r
- finishcachebox = CAL_DialogFinish;\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CA_Shutdown\r
-=\r
-= Closes all files\r
-=\r
-======================\r
-*/\r
-\r
-void CA_Shutdown (void)\r
-{\r
-#ifdef PROFILE\r
- close (profilehandle);\r
-#endif\r
-\r
- close (maphandle);\r
- close (grhandle);\r
- close (audiohandle);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_CacheAudioChunk\r
-=\r
-======================\r
-*/\r
-\r
-void CA_CacheAudioChunk (int chunk)\r
-{\r
- long pos,compressed;\r
-#ifdef AUDIOHEADERLINKED\r
- long expanded;\r
- memptr bigbufferseg;\r
- byte far *source;\r
-#endif\r
-\r
- if (audiosegs[chunk])\r
- {\r
- MM_SetPurge (&(memptr)audiosegs[chunk],0);\r
- return; // allready in memory\r
- }\r
-\r
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("AUDIO."EXT,NULL,2))\r
- Quit("CA_CacheAudioChunk(): Can't find audio files.");\r
-//\r
-// MDM end\r
-\r
-//\r
-// load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
-// a larger buffer\r
-//\r
- pos = audiostarts[chunk];\r
- compressed = audiostarts[chunk+1]-pos;\r
-\r
- lseek(audiohandle,pos,SEEK_SET);\r
-\r
-#ifndef AUDIOHEADERLINKED\r
-\r
- MM_GetPtr (&(memptr)audiosegs[chunk],compressed);\r
- if (mmerror)\r
- return;\r
-\r
- CA_FarRead(audiohandle,audiosegs[chunk],compressed);\r
-\r
-#else\r
-\r
- if (compressed<=BUFFERSIZE)\r
- {\r
- CA_FarRead(audiohandle,bufferseg,compressed);\r
- source = bufferseg;\r
- }\r
- else\r
- {\r
- MM_GetPtr(&bigbufferseg,compressed);\r
- if (mmerror)\r
- return;\r
- MM_SetLock (&bigbufferseg,true);\r
- CA_FarRead(audiohandle,bigbufferseg,compressed);\r
- source = bigbufferseg;\r
- }\r
-\r
- expanded = *(long far *)source;\r
- source += 4; // skip over length\r
- MM_GetPtr (&(memptr)audiosegs[chunk],expanded);\r
- if (mmerror)\r
- goto done;\r
- CAL_HuffExpand (source,audiosegs[chunk],expanded,audiohuffman);\r
-\r
-done:\r
- if (compressed>BUFFERSIZE)\r
- MM_FreePtr(&bigbufferseg);\r
-#endif\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_LoadAllSounds\r
-=\r
-= Purges all sounds, then loads all new ones (mode switch)\r
-=\r
-======================\r
-*/\r
-\r
-void CA_LoadAllSounds (void)\r
-{\r
- unsigned start,i;\r
-\r
- switch (oldsoundmode)\r
- {\r
- case sdm_Off:\r
- goto cachein;\r
- case sdm_PC:\r
- start = STARTPCSOUNDS;\r
- break;\r
- case sdm_AdLib:\r
- start = STARTADLIBSOUNDS;\r
- break;\r
- }\r
-\r
- for (i=0;i<NUMSOUNDS;i++,start++)\r
- if (audiosegs[start])\r
- MM_SetPurge (&(memptr)audiosegs[start],3); // make purgable\r
-\r
-cachein:\r
-\r
- switch (SoundMode)\r
- {\r
- case sdm_Off:\r
- return;\r
- case sdm_PC:\r
- start = STARTPCSOUNDS;\r
- break;\r
- case sdm_AdLib:\r
- start = STARTADLIBSOUNDS;\r
- break;\r
- }\r
-\r
- for (i=0;i<NUMSOUNDS;i++,start++)\r
- CA_CacheAudioChunk (start);\r
-\r
- oldsoundmode = SoundMode;\r
-}\r
-\r
-//===========================================================================\r
-\r
-#if GRMODE == EGAGR\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_ShiftSprite\r
-=\r
-= Make a shifted (one byte wider) copy of a sprite into another area\r
-=\r
-======================\r
-*/\r
-\r
-unsigned static sheight,swidth;\r
-boolean static dothemask;\r
-\r
-void CAL_ShiftSprite (unsigned segment,unsigned source,unsigned dest,\r
- unsigned width, unsigned height, unsigned pixshift, boolean domask)\r
-{\r
-\r
- sheight = height; // because we are going to reassign bp\r
- swidth = width;\r
- dothemask = domask;\r
-\r
-asm mov ax,[segment]\r
-asm mov ds,ax // source and dest are in same segment, and all local\r
-\r
-asm mov bx,[source]\r
-asm mov di,[dest]\r
-\r
-asm mov bp,[pixshift]\r
-asm shl bp,1\r
-asm mov bp,WORD PTR [shifttabletable+bp] // bp holds pointer to shift table\r
-\r
-asm cmp [ss:dothemask],0\r
-asm je skipmask\r
-\r
-//\r
-// table shift the mask\r
-//\r
-asm mov dx,[ss:sheight]\r
-\r
-domaskrow:\r
-\r
-asm mov BYTE PTR [di],255 // 0xff first byte\r
-asm mov cx,ss:[swidth]\r
-\r
-domaskbyte:\r
-\r
-asm mov al,[bx] // source\r
-asm not al\r
-asm inc bx // next source byte\r
-asm xor ah,ah\r
-asm shl ax,1\r
-asm mov si,ax\r
-asm mov ax,[bp+si] // table shift into two bytes\r
-asm not ax\r
-asm and [di],al // and with first byte\r
-asm inc di\r
-asm mov [di],ah // replace next byte\r
-\r
-asm loop domaskbyte\r
-\r
-asm inc di // the last shifted byte has 1s in it\r
-asm dec dx\r
-asm jnz domaskrow\r
-\r
-skipmask:\r
-\r
-//\r
-// table shift the data\r
-//\r
-asm mov dx,ss:[sheight]\r
-asm shl dx,1\r
-asm shl dx,1 // four planes of data\r
-\r
-dodatarow:\r
-\r
-asm mov BYTE PTR [di],0 // 0 first byte\r
-asm mov cx,ss:[swidth]\r
-\r
-dodatabyte:\r
-\r
-asm mov al,[bx] // source\r
-asm inc bx // next source byte\r
-asm xor ah,ah\r
-asm shl ax,1\r
-asm mov si,ax\r
-asm mov ax,[bp+si] // table shift into two bytes\r
-asm or [di],al // or with first byte\r
-asm inc di\r
-asm mov [di],ah // replace next byte\r
-\r
-asm loop dodatabyte\r
-\r
-asm inc di // the last shifted byte has 0s in it\r
-asm dec dx\r
-asm jnz dodatarow\r
-\r
-//\r
-// done\r
-//\r
-\r
-asm mov ax,ss // restore data segment\r
-asm mov ds,ax\r
-\r
-}\r
-\r
-#endif\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_CacheSprite\r
-=\r
-= Generate shifts and set up sprite structure for a given sprite\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_CacheSprite (int chunk, byte far *compressed)\r
-{\r
- int i;\r
- unsigned shiftstarts[5];\r
- unsigned smallplane,bigplane,expanded;\r
- spritetabletype far *spr;\r
- spritetype _seg *dest;\r
-\r
-#if GRMODE == CGAGR\r
-//\r
-// CGA has no pel panning, so shifts are never needed\r
-//\r
- spr = &spritetable[chunk-STARTSPRITES];\r
- smallplane = spr->width*spr->height;\r
- MM_GetPtr (&grsegs[chunk],smallplane*2+MAXSHIFTS*6);\r
- if (mmerror)\r
- return;\r
- dest = (spritetype _seg *)grsegs[chunk];\r
- dest->sourceoffset[0] = MAXSHIFTS*6; // start data after 3 unsigned tables\r
- dest->planesize[0] = smallplane;\r
- dest->width[0] = spr->width;\r
-\r
-//\r
-// expand the unshifted shape\r
-//\r
- CAL_HuffExpand (compressed, &dest->data[0],smallplane*2,grhuffman);\r
-\r
-#endif\r
-\r
-\r
-#if GRMODE == EGAGR\r
-\r
-//\r
-// calculate sizes\r
-//\r
- spr = &spritetable[chunk-STARTSPRITES];\r
- smallplane = spr->width*spr->height;\r
- bigplane = (spr->width+1)*spr->height;\r
-\r
- shiftstarts[0] = MAXSHIFTS*6; // start data after 3 unsigned tables\r
- shiftstarts[1] = shiftstarts[0] + smallplane*5; // 5 planes in a sprite\r
- shiftstarts[2] = shiftstarts[1] + bigplane*5;\r
- shiftstarts[3] = shiftstarts[2] + bigplane*5;\r
- shiftstarts[4] = shiftstarts[3] + bigplane*5; // nothing ever put here\r
-\r
- expanded = shiftstarts[spr->shifts];\r
- MM_GetPtr (&grsegs[chunk],expanded);\r
- if (mmerror)\r
- return;\r
- dest = (spritetype _seg *)grsegs[chunk];\r
-\r
-//\r
-// expand the unshifted shape\r
-//\r
- CAL_HuffExpand (compressed, &dest->data[0],smallplane*5,grhuffman);\r
-\r
-//\r
-// make the shifts!\r
-//\r
- switch (spr->shifts)\r
- {\r
- case 1:\r
- for (i=0;i<4;i++)\r
- {\r
- dest->sourceoffset[i] = shiftstarts[0];\r
- dest->planesize[i] = smallplane;\r
- dest->width[i] = spr->width;\r
- }\r
- break;\r
-\r
- case 2:\r
- for (i=0;i<2;i++)\r
- {\r
- dest->sourceoffset[i] = shiftstarts[0];\r
- dest->planesize[i] = smallplane;\r
- dest->width[i] = spr->width;\r
- }\r
- for (i=2;i<4;i++)\r
- {\r
- dest->sourceoffset[i] = shiftstarts[1];\r
- dest->planesize[i] = bigplane;\r
- dest->width[i] = spr->width+1;\r
- }\r
- CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
- dest->sourceoffset[2],spr->width,spr->height,4,true);\r
- break;\r
-\r
- case 4:\r
- dest->sourceoffset[0] = shiftstarts[0];\r
- dest->planesize[0] = smallplane;\r
- dest->width[0] = spr->width;\r
-\r
- dest->sourceoffset[1] = shiftstarts[1];\r
- dest->planesize[1] = bigplane;\r
- dest->width[1] = spr->width+1;\r
- CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
- dest->sourceoffset[1],spr->width,spr->height,2,true);\r
-\r
- dest->sourceoffset[2] = shiftstarts[2];\r
- dest->planesize[2] = bigplane;\r
- dest->width[2] = spr->width+1;\r
- CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
- dest->sourceoffset[2],spr->width,spr->height,4,true);\r
-\r
- dest->sourceoffset[3] = shiftstarts[3];\r
- dest->planesize[3] = bigplane;\r
- dest->width[3] = spr->width+1;\r
- CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
- dest->sourceoffset[3],spr->width,spr->height,6,true);\r
-\r
- break;\r
-\r
- default:\r
- Quit ("CAL_CacheSprite: Bad shifts number!");\r
- }\r
-\r
-#endif\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_ExpandGrChunk\r
-=\r
-= Does whatever is needed with a pointer to a compressed chunk\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_ExpandGrChunk (int chunk, byte far *source)\r
-{\r
- long expanded;\r
-\r
-\r
- if (chunk >= STARTTILE8 && chunk < STARTEXTERNS)\r
- {\r
- //\r
- // expanded sizes of tile8/16/32 are implicit\r
- //\r
-\r
-#if GRMODE == EGAGR\r
-#define BLOCK 32\r
-#define MASKBLOCK 40\r
-#endif\r
-\r
-#if GRMODE == CGAGR\r
-#define BLOCK 16\r
-#define MASKBLOCK 32\r
-#endif\r
-\r
- if (chunk<STARTTILE8M) // tile 8s are all in one chunk!\r
- expanded = BLOCK*NUMTILE8;\r
- else if (chunk<STARTTILE16)\r
- expanded = MASKBLOCK*NUMTILE8M;\r
- else if (chunk<STARTTILE16M) // all other tiles are one/chunk\r
- expanded = BLOCK*4;\r
- else if (chunk<STARTTILE32)\r
- expanded = MASKBLOCK*4;\r
- else if (chunk<STARTTILE32M)\r
- expanded = BLOCK*16;\r
- else\r
- expanded = MASKBLOCK*16;\r
- }\r
- else\r
- {\r
- //\r
- // everything else has an explicit size longword\r
- //\r
- expanded = *(long far *)source;\r
- source += 4; // skip over length\r
- }\r
-\r
-//\r
-// allocate final space, decompress it, and free bigbuffer\r
-// Sprites need to have shifts made and various other junk\r
-//\r
- if (chunk>=STARTSPRITES && chunk< STARTTILE8)\r
- CAL_CacheSprite(chunk,source);\r
- else\r
- {\r
- MM_GetPtr (&grsegs[chunk],expanded);\r
- if (mmerror)\r
- return;\r
- CAL_HuffExpand (source,grsegs[chunk],expanded,grhuffman);\r
- }\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_ReadGrChunk\r
-=\r
-= Gets a chunk off disk, optimizing reads to general buffer\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_ReadGrChunk (int chunk)\r
-{\r
- long pos,compressed;\r
- memptr bigbufferseg;\r
- byte far *source;\r
- int next;\r
-\r
-//\r
-// load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
-// a larger buffer\r
-//\r
- pos = GRFILEPOS(chunk);\r
- if (pos<0) // $FFFFFFFF start is a sparse tile\r
- return;\r
-\r
- next = chunk +1;\r
- while (GRFILEPOS(next) == -1) // skip past any sparse tiles\r
- next++;\r
-\r
- compressed = GRFILEPOS(next)-pos;\r
-\r
- lseek(grhandle,pos,SEEK_SET);\r
-\r
- if (compressed<=BUFFERSIZE)\r
- {\r
- CA_FarRead(grhandle,bufferseg,compressed);\r
- source = bufferseg;\r
- }\r
- else\r
- {\r
- MM_GetPtr(&bigbufferseg,compressed);\r
- if (mmerror)\r
- return;\r
- MM_SetLock (&bigbufferseg,true);\r
- CA_FarRead(grhandle,bigbufferseg,compressed);\r
- source = bigbufferseg;\r
- }\r
-\r
- CAL_ExpandGrChunk (chunk,source);\r
-\r
- if (compressed>BUFFERSIZE)\r
- MM_FreePtr(&bigbufferseg);\r
-}\r
-\r
-/*\r
-======================\r
-=\r
-= CA_CacheGrChunk\r
-=\r
-= Makes sure a given chunk is in memory, loadiing it if needed\r
-=\r
-======================\r
-*/\r
-\r
-void CA_CacheGrChunk (int chunk)\r
-{\r
- long pos,compressed;\r
- memptr bigbufferseg;\r
- byte far *source;\r
- int next;\r
-\r
- grneeded[chunk] |= ca_levelbit; // make sure it doesn't get removed\r
- if (grsegs[chunk])\r
- {\r
- MM_SetPurge (&grsegs[chunk],0);\r
- return; // allready in memory\r
- }\r
-\r
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("EGAGRAPH."EXT,NULL,2))\r
- Quit("CA_CacheGrChunk(): Can't find graphics files.");\r
-//\r
-// MDM end\r
-\r
-//\r
-// load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
-// a larger buffer\r
-//\r
- pos = GRFILEPOS(chunk);\r
- if (pos<0) // $FFFFFFFF start is a sparse tile\r
- return;\r
-\r
- next = chunk +1;\r
- while (GRFILEPOS(next) == -1) // skip past any sparse tiles\r
- next++;\r
-\r
- compressed = GRFILEPOS(next)-pos;\r
-\r
- lseek(grhandle,pos,SEEK_SET);\r
-\r
- if (compressed<=BUFFERSIZE)\r
- {\r
- CA_FarRead(grhandle,bufferseg,compressed);\r
- source = bufferseg;\r
- }\r
- else\r
- {\r
- MM_GetPtr(&bigbufferseg,compressed);\r
- MM_SetLock (&bigbufferseg,true);\r
- CA_FarRead(grhandle,bigbufferseg,compressed);\r
- source = bigbufferseg;\r
- }\r
-\r
- CAL_ExpandGrChunk (chunk,source);\r
-\r
- if (compressed>BUFFERSIZE)\r
- MM_FreePtr(&bigbufferseg);\r
-}\r
-\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_CacheMap\r
-=\r
-======================\r
-*/\r
-\r
-void CA_CacheMap (int mapnum)\r
-{\r
- long pos,compressed;\r
- int plane;\r
- memptr *dest,bigbufferseg;\r
- unsigned size;\r
- unsigned far *source;\r
-#ifdef MAPHEADERLINKED\r
- memptr buffer2seg;\r
- long expanded;\r
-#endif\r
-\r
-\r
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("GAMEMAPS."EXT,NULL,1))\r
- Quit("CA_CacheMap(): Can't find level files.");\r
-//\r
-// MDM end\r
-\r
-\r
-//\r
-// free up memory from last map\r
-//\r
- if (mapon>-1 && mapheaderseg[mapon])\r
- MM_SetPurge (&(memptr)mapheaderseg[mapon],3);\r
- for (plane=0;plane<MAPPLANES;plane++)\r
- if (mapsegs[plane])\r
- MM_FreePtr (&(memptr)mapsegs[plane]);\r
-\r
- mapon = mapnum;\r
-\r
-\r
-//\r
-// load map header\r
-// The header will be cached if it is still around\r
-//\r
- if (!mapheaderseg[mapnum])\r
- {\r
- pos = ((mapfiletype _seg *)tinf)->headeroffsets[mapnum];\r
- if (pos<0) // $FFFFFFFF start is a sparse map\r
- Quit ("CA_CacheMap: Tried to load a non existent map!");\r
-\r
- MM_GetPtr(&(memptr)mapheaderseg[mapnum],sizeof(maptype));\r
- lseek(maphandle,pos,SEEK_SET);\r
- CA_FarRead (maphandle,(memptr)mapheaderseg[mapnum],sizeof(maptype));\r
- }\r
- else\r
- MM_SetPurge (&(memptr)mapheaderseg[mapnum],0);\r
-\r
-//\r
-// load the planes in\r
-// If a plane's pointer still exists it will be overwritten (levels are\r
-// allways reloaded, never cached)\r
-//\r
-\r
- size = mapheaderseg[mapnum]->width * mapheaderseg[mapnum]->height * 2;\r
-\r
- for (plane = 0; plane<MAPPLANES; plane++)\r
- {\r
- pos = mapheaderseg[mapnum]->planestart[plane];\r
- compressed = mapheaderseg[mapnum]->planelength[plane];\r
-\r
- if (!compressed)\r
- continue; // the plane is not used in this game\r
-\r
- dest = &(memptr)mapsegs[plane];\r
- MM_GetPtr(dest,size);\r
-\r
- lseek(maphandle,pos,SEEK_SET);\r
- if (compressed<=BUFFERSIZE)\r
- source = bufferseg;\r
- else\r
- {\r
- MM_GetPtr(&bigbufferseg,compressed);\r
- MM_SetLock (&bigbufferseg,true);\r
- source = bigbufferseg;\r
- }\r
-\r
- CA_FarRead(maphandle,(byte far *)source,compressed);\r
-#ifdef MAPHEADERLINKED\r
- //\r
- // unhuffman, then unRLEW\r
- // The huffman'd chunk has a two byte expanded length first\r
- // The resulting RLEW chunk also does, even though it's not really\r
- // needed\r
- //\r
- expanded = *source;\r
- source++;\r
- MM_GetPtr (&buffer2seg,expanded);\r
- CAL_CarmackExpand (source, (unsigned far *)buffer2seg,expanded);\r
- CA_RLEWexpand (((unsigned far *)buffer2seg)+1,*dest,size,\r
- ((mapfiletype _seg *)tinf)->RLEWtag);\r
- MM_FreePtr (&buffer2seg);\r
-\r
-#else\r
- //\r
- // unRLEW, skipping expanded length\r
- //\r
- CA_RLEWexpand (source+1, *dest,size,\r
- ((mapfiletype _seg *)tinf)->RLEWtag);\r
-#endif\r
-\r
- if (compressed>BUFFERSIZE)\r
- MM_FreePtr(&bigbufferseg);\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_UpLevel\r
-=\r
-= Goes up a bit level in the needed lists and clears it out.\r
-= Everything is made purgable\r
-=\r
-======================\r
-*/\r
-\r
-void CA_UpLevel (void)\r
-{\r
- if (ca_levelnum==7)\r
- Quit ("CA_UpLevel: Up past level 7!");\r
-\r
- ca_levelbit<<=1;\r
- ca_levelnum++;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_DownLevel\r
-=\r
-= Goes down a bit level in the needed lists and recaches\r
-= everything from the lower level\r
-=\r
-======================\r
-*/\r
-\r
-void CA_DownLevel (void)\r
-{\r
- if (!ca_levelnum)\r
- Quit ("CA_DownLevel: Down past level 0!");\r
- ca_levelbit>>=1;\r
- ca_levelnum--;\r
- CA_CacheMarks(NULL);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_ClearMarks\r
-=\r
-= Clears out all the marks at the current level\r
-=\r
-======================\r
-*/\r
-\r
-void CA_ClearMarks (void)\r
-{\r
- int i;\r
-\r
- for (i=0;i<NUMCHUNKS;i++)\r
- grneeded[i]&=~ca_levelbit;\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_ClearAllMarks\r
-=\r
-= Clears out all the marks on all the levels\r
-=\r
-======================\r
-*/\r
-\r
-void CA_ClearAllMarks (void)\r
-{\r
- _fmemset (grneeded,0,sizeof(grneeded));\r
- ca_levelbit = 1;\r
- ca_levelnum = 0;\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_FreeGraphics\r
-=\r
-======================\r
-*/\r
-\r
-void CA_FreeGraphics (void)\r
-{\r
- int i;\r
-\r
- for (i=0;i<NUMCHUNKS;i++)\r
- if (grsegs[i])\r
- MM_SetPurge (&(memptr)grsegs[i],3);\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CA_SetAllPurge\r
-=\r
-= Make everything possible purgable\r
-=\r
-======================\r
-*/\r
-\r
-void CA_SetAllPurge (void)\r
-{\r
- int i;\r
-\r
- CA_ClearMarks ();\r
-\r
-//\r
-// free cursor sprite and background save\r
-//\r
- VW_FreeCursor ();\r
-\r
-//\r
-// free map headers and map planes\r
-//\r
- for (i=0;i<NUMMAPS;i++)\r
- if (mapheaderseg[i])\r
- MM_SetPurge (&(memptr)mapheaderseg[i],3);\r
-\r
- for (i=0;i<3;i++)\r
- if (mapsegs[i])\r
- MM_FreePtr (&(memptr)mapsegs[i]);\r
-\r
-//\r
-// free sounds\r
-//\r
- for (i=0;i<NUMSNDCHUNKS;i++)\r
- if (audiosegs[i])\r
- MM_SetPurge (&(memptr)audiosegs[i],3);\r
-\r
-//\r
-// free graphics\r
-//\r
- CA_FreeGraphics ();\r
-}\r
-\r
-\r
-void CA_SetGrPurge (void)\r
-{\r
- int i;\r
-\r
-//\r
-// free graphics\r
-//\r
- for (i=0;i<NUMCHUNKS;i++)\r
- if (grsegs[i])\r
- MM_SetPurge (&(memptr)grsegs[i],3);\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_DialogDraw\r
-=\r
-======================\r
-*/\r
-\r
-#define NUMBARS (17l*8)\r
-#define BARSTEP 8\r
-\r
-unsigned thx,thy,lastx;\r
-long barx,barstep;\r
-\r
-void CAL_DialogDraw (char *title,unsigned numcache)\r
-{\r
- unsigned homex,homey,x;\r
-\r
- barstep = (NUMBARS<<16)/numcache;\r
-\r
-//\r
-// draw dialog window (masked tiles 12 - 20 are window borders)\r
-//\r
- US_CenterWindow (20,8);\r
- homex = PrintX;\r
- homey = PrintY;\r
-\r
- US_CPrint ("Loading");\r
- fontcolor = F_SECONDCOLOR;\r
- US_CPrint (title);\r
- fontcolor = F_BLACK;\r
-\r
-//\r
-// draw thermometer bar\r
-//\r
- thx = homex + 8;\r
- thy = homey + 32;\r
- VWB_DrawTile8(thx,thy,0); // CAT3D numbers\r
- VWB_DrawTile8(thx,thy+8,3);\r
- VWB_DrawTile8(thx,thy+16,6);\r
- VWB_DrawTile8(thx+17*8,thy,2);\r
- VWB_DrawTile8(thx+17*8,thy+8,5);\r
- VWB_DrawTile8(thx+17*8,thy+16,8);\r
- for (x=thx+8;x<thx+17*8;x+=8)\r
- {\r
- VWB_DrawTile8(x,thy,1);\r
- VWB_DrawTile8(x,thy+8,4);\r
- VWB_DrawTile8(x,thy+16,7);\r
- }\r
-\r
- thx += 4; // first line location\r
- thy += 5;\r
- barx = (long)thx<<16;\r
- lastx = thx;\r
-\r
- VW_UpdateScreen();\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_DialogUpdate\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_DialogUpdate (void)\r
-{\r
- unsigned x,xh;\r
-\r
- barx+=barstep;\r
- xh = barx>>16;\r
- if (xh - lastx > BARSTEP)\r
- {\r
- for (x=lastx;x<=xh;x++)\r
-#if GRMODE == EGAGR\r
- VWB_Vlin (thy,thy+13,x,14);\r
-#endif\r
-#if GRMODE == CGAGR\r
- VWB_Vlin (thy,thy+13,x,SECONDCOLOR);\r
-#endif\r
- lastx = xh;\r
- VW_UpdateScreen();\r
- }\r
-}\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_DialogFinish\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_DialogFinish (void)\r
-{\r
- unsigned x,xh;\r
-\r
- xh = thx + NUMBARS;\r
- for (x=lastx;x<=xh;x++)\r
-#if GRMODE == EGAGR\r
- VWB_Vlin (thy,thy+13,x,14);\r
-#endif\r
-#if GRMODE == CGAGR\r
- VWB_Vlin (thy,thy+13,x,SECONDCOLOR);\r
-#endif\r
- VW_UpdateScreen();\r
-\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_CacheMarks\r
-=\r
-======================\r
-*/\r
-#define MAXEMPTYREAD 1024\r
-\r
-void CA_CacheMarks (char *title)\r
-{\r
- boolean dialog;\r
- int i,next,numcache;\r
- long pos,endpos,nextpos,nextendpos,compressed;\r
- long bufferstart,bufferend; // file position of general buffer\r
- byte far *source;\r
- memptr bigbufferseg;\r
-\r
- dialog = (title!=NULL);\r
-\r
- numcache = 0;\r
-//\r
-// go through and make everything not needed purgable\r
-//\r
- for (i=0;i<NUMCHUNKS;i++)\r
- if (grneeded[i]&ca_levelbit)\r
- {\r
- if (grsegs[i]) // its allready in memory, make\r
- MM_SetPurge(&grsegs[i],0); // sure it stays there!\r
- else\r
- numcache++;\r
- }\r
- else\r
- {\r
- if (grsegs[i]) // not needed, so make it purgeable\r
- MM_SetPurge(&grsegs[i],3);\r
- }\r
-\r
- if (!numcache) // nothing to cache!\r
- return;\r
-\r
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("EGAGRAPH."EXT,NULL,2))\r
- Quit("CA_CacheMarks(): Can't find graphics files.");\r
-//\r
-// MDM end\r
-\r
- if (dialog)\r
- {\r
-#ifdef PROFILE\r
- write(profilehandle,title,strlen(title));\r
- write(profilehandle,"\n",1);\r
-#endif\r
- if (drawcachebox)\r
- drawcachebox(title,numcache);\r
- }\r
-\r
-//\r
-// go through and load in anything still needed\r
-//\r
- bufferstart = bufferend = 0; // nothing good in buffer now\r
-\r
- for (i=0;i<NUMCHUNKS;i++)\r
- if ( (grneeded[i]&ca_levelbit) && !grsegs[i])\r
- {\r
-//\r
-// update thermometer\r
-//\r
- if (dialog && updatecachebox)\r
- updatecachebox ();\r
-\r
- pos = GRFILEPOS(i);\r
- if (pos<0)\r
- continue;\r
-\r
- next = i +1;\r
- while (GRFILEPOS(next) == -1) // skip past any sparse tiles\r
- next++;\r
-\r
- compressed = GRFILEPOS(next)-pos;\r
- endpos = pos+compressed;\r
-\r
- if (compressed<=BUFFERSIZE)\r
- {\r
- if (bufferstart<=pos\r
- && bufferend>= endpos)\r
- {\r
- // data is allready in buffer\r
- source = (byte _seg *)bufferseg+(pos-bufferstart);\r
- }\r
- else\r
- {\r
- // load buffer with a new block from disk\r
- // try to get as many of the needed blocks in as possible\r
- while ( next < NUMCHUNKS )\r
- {\r
- while (next < NUMCHUNKS &&\r
- !(grneeded[next]&ca_levelbit && !grsegs[next]))\r
- next++;\r
- if (next == NUMCHUNKS)\r
- continue;\r
-\r
- nextpos = GRFILEPOS(next);\r
- while (GRFILEPOS(++next) == -1) // skip past any sparse tiles\r
- ;\r
- nextendpos = GRFILEPOS(next);\r
- if (nextpos - endpos <= MAXEMPTYREAD\r
- && nextendpos-pos <= BUFFERSIZE)\r
- endpos = nextendpos;\r
- else\r
- next = NUMCHUNKS; // read pos to posend\r
- }\r
-\r
- lseek(grhandle,pos,SEEK_SET);\r
- CA_FarRead(grhandle,bufferseg,endpos-pos);\r
- bufferstart = pos;\r
- bufferend = endpos;\r
- source = bufferseg;\r
- }\r
- }\r
- else\r
- {\r
- // big chunk, allocate temporary buffer\r
- MM_GetPtr(&bigbufferseg,compressed);\r
- if (mmerror)\r
- return;\r
- MM_SetLock (&bigbufferseg,true);\r
- lseek(grhandle,pos,SEEK_SET);\r
- CA_FarRead(grhandle,bigbufferseg,compressed);\r
- source = bigbufferseg;\r
- }\r
-\r
- CAL_ExpandGrChunk (i,source);\r
- if (mmerror)\r
- return;\r
-\r
- if (compressed>BUFFERSIZE)\r
- MM_FreePtr(&bigbufferseg);\r
-\r
- }\r
-\r
-//\r
-// finish up any thermometer remnants\r
-//\r
- if (dialog && finishcachebox)\r
- finishcachebox();\r
-}\r
-\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_CA.H
-
-/*#ifndef __TYPES__\r
-#include "ID_TYPES.H"\r
-#endif\r
-\r
-#ifndef __ID_MM__\r
-#include "ID_MM.H"\r
-#endif\r
-\r
-#ifndef __ID_GLOB__\r
-#include "ID_GLOB.H"\r
-#endif*/\r
-\r
-#define __ID_CA__\r
-\r
-//===========================================================================\r
-\r
-//#define NOMAPS\r
-//#define NOGRAPHICS\r
-//#define NOAUDIO\r
-\r
-#define MAPHEADERLINKED\r
-#define GRHEADERLINKED\r
-#define AUDIOHEADERLINKED\r
-\r
-#define NUMMAPS 39\r
-#define MAPPLANES 3\r
-\r
-//===========================================================================
-\r
-typedef struct\r
-{\r
- long planestart[3];\r
- unsigned planelength[3];\r
- unsigned width,height;\r
- char name[16];\r
-} maptype;\r
-\r
-//===========================================================================\r
-\r
-extern byte /*_1seg*/ *tinf;\r
-extern int mapon;\r
-\r
-extern unsigned /*_1seg*/ *mapsegs[3];\r
-extern maptype /*_1seg*/ *mapheaderseg[NUMMAPS];\r
-extern byte /*_1seg*/ *audiosegs[NUMSNDCHUNKS];\r
-extern void /*_1seg*/ *grsegs[NUMCHUNKS];\r
-\r
-extern byte far grneeded[NUMCHUNKS];\r
-extern byte ca_levelbit,ca_levelnum;\r
-\r
-extern char *titleptr[8];\r
-\r
-extern int profilehandle,debughandle;\r
-\r
-//\r
-// hooks for custom cache dialogs\r
-//\r
-extern void (*drawcachebox) (char *title, unsigned numcache);\r
-extern void (*updatecachebox) (void);\r
-extern void (*finishcachebox) (void);\r
-\r
-//===========================================================================\r
-\r
-// just for the score box reshifting\r
-\r
-void CAL_ShiftSprite (unsigned segment,unsigned source,unsigned dest,\r
- unsigned width, unsigned height, unsigned pixshift, boolean domask);\r
-\r
-//===========================================================================\r
-\r
-void CA_OpenDebug (void);\r
-void CA_CloseDebug (void);\r
-boolean CA_FarRead (int handle, byte far *dest, long length);\r
-boolean CA_FarWrite (int handle, byte far *source, long length);\r
-boolean CA_ReadFile (char *filename, memptr *ptr);\r
-boolean CA_LoadFile (char *filename, memptr *ptr);\r
-\r
-long CA_RLEWCompress (unsigned huge *source, long length, unsigned huge *dest,\r
- unsigned rlewtag);\r
-\r
-void CA_RLEWexpand (unsigned huge *source, unsigned huge *dest,long length,\r
- unsigned rlewtag);\r
-\r
-void CA_Startup (void);\r
-void CA_Shutdown (void);\r
-\r
-void CA_CacheAudioChunk (int chunk);\r
-void CA_LoadAllSounds (void);\r
-\r
-void CA_UpLevel (void);\r
-void CA_DownLevel (void);\r
-\r
-void CA_SetAllPurge (void);\r
-\r
-void CA_ClearMarks (void);\r
-void CA_ClearAllMarks (void);\r
-\r
-#define CA_MarkGrChunk(chunk) grneeded[chunk]|=ca_levelbit\r
-\r
-void CA_CacheGrChunk (int chunk);\r
-void CA_CacheMap (int mapnum);\r
-\r
-void CA_CacheMarks (char *title);\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_GLOB.H\r
-\r
-\r
-#include <ALLOC.H>\r
-#include <CTYPE.H>\r
-#include <DOS.H>\r
-#include <ERRNO.H>\r
-#include <FCNTL.H>\r
-#include <IO.H>\r
-#include <MEM.H>\r
-#include <PROCESS.H>\r
-#include <STDIO.H>\r
-#include <STDLIB.H>\r
-#include <STRING.H>\r
-#include <SYS\STAT.H>\r
-\r
-#define __ID_GLOB__\r
-\r
-//--------------------------------------------------------------------------\r
-\r
-#define EXT "ARM"\r
-\r
-extern char far introscn;\r
-\r
-#include "GFXE_ARM.H"\r
-#include "AUDIOARM.H"\r
-#include "MAPSARM.H"\r
-\r
-//--------------------------------------------------------------------------\r
-\r
-//\r
-// DEFINES THE TILE ATTRIBUTE CHECKING CONVENTION (macros).\r
-//\r
-// DEFINE CUSTOM BIT-FLAG NAMES...\r
-//\r
-\r
-\r
-#define tf_SOLID 0x01\r
-#define tf_SPECIAL 0x02\r
-#define tf_EMBEDDED_KEY_COLOR 0x04\r
-#define tf_INVISIBLE_WALL 0x09\r
-#define tf_MARKED 0x80\r
-\r
-#define ANIM_FLAGS(tile) (tinf[ANIM+(tile)])\r
-#define TILE_FLAGS(tile) (tinf[FLAGS+(tile)])\r
-\r
-#define GATE_KEY_COLOR(tile) ((unsigned char)(TILE_FLAGS(tile)>>4))\r
-\r
-#define CAT3D\r
-\r
-#define TEXTGR 0\r
-#define CGAGR 1\r
-#define EGAGR 2\r
-#define VGAGR 3\r
-\r
-#define EGA320GR 10 // MDM (GAMERS EDGE)\r
-#define EGA640GR 11 // MDM (GAMERS EDGE)\r
-\r
-#define GRMODE EGAGR\r
-\r
-#if GRMODE == EGAGR\r
-#define GREXT "EGA"\r
-#endif\r
-#if GRMODE == CGAGR\r
-#define GREXT "CGA"\r
-#endif\r
-\r
-//#define PROFILE\r
-\r
-//\r
-// ID Engine\r
-// Types.h - Generic types, #defines, etc.\r
-// v1.0d1\r
-//\r
-\r
-#ifndef __TYPES__\r
-#define __TYPES__\r
-\r
-typedef enum {false,true} boolean;\r
-typedef unsigned char byte;\r
-typedef unsigned int word;\r
-typedef unsigned long longword;\r
-typedef byte * Ptr;\r
-\r
-typedef struct\r
- {\r
- int x,y;\r
- } Point;\r
-typedef struct\r
- {\r
- Point ul,lr;\r
- } Rect;\r
-\r
-#define nil ((void *)0)\r
-\r
-#endif\r
-\r
-#include "ID_MM.H"\r
-#include "ID_CA.H"\r
-#include "ID_VW.H"\r
-#include "ID_IN.H"\r
-#include "ID_SD.H"\r
-#include "ID_US.H"\r
-\r
-\r
-void Quit (char *error, ...); // defined in user program\r
-\r
-//\r
-// replacing refresh manager with custom routines\r
-//\r
-\r
-#define PORTTILESWIDE 21 // all drawing takes place inside a\r
-#define PORTTILESHIGH 14 // non displayed port of this size\r
-\r
-#define UPDATEWIDE (PORTTILESWIDE+1)\r
-#define UPDATEHIGH PORTTILESHIGH\r
-\r
-#define MAXTICS 6\r
-#define DEMOTICS 3\r
-\r
-#define UPDATETERMINATE 0x0301\r
-\r
-extern unsigned mapwidth,mapheight,tics,realtics;\r
-extern boolean compatability;\r
-\r
-extern byte *updateptr;\r
-extern unsigned uwidthtable[UPDATEHIGH];\r
-extern unsigned blockstarts[UPDATEWIDE*UPDATEHIGH];\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_IN.c - Input Manager\r
-// v1.0d1\r
-// By Jason Blochowiak\r
-//\r
-\r
-//\r
-// This module handles dealing with the various input devices\r
-//\r
-// Depends on: Memory Mgr (for demo recording), Sound Mgr (for timing stuff),\r
-// User Mgr (for command line parms)\r
-//\r
-// Globals:\r
-// LastScan - The keyboard scan code of the last key pressed\r
-// LastASCII - The ASCII value of the last key pressed\r
-// DEBUG - there are more globals\r
-//\r
-\r
-//#include "ID_HEADS.H"
-#include "id_in.h"\r
-//#pragma hdrstop\r
-\r
-#define KeyInt 9 // The keyboard ISR number\r
-\r
-// Stuff for the joystick\r
-#define JoyScaleMax 32768\r
-#define JoyScaleShift 8\r
-#define MaxJoyValue 5000\r
-\r
-// Global variables\r
- boolean JoystickCalibrated=false; // MDM (GAMERS EDGE) - added\r
- ControlType ControlTypeUsed; // MDM (GAMERS EDGE) - added\r
-\r
- boolean Keyboard[NumCodes],\r
- JoysPresent[MaxJoys],\r
- MousePresent;\r
- boolean Paused;\r
- char LastASCII;\r
- ScanCode LastScan;\r
- KeyboardDef KbdDefs[MaxKbds] = {{0x1d,0x38,0x47,0x48,0x49,0x4b,0x4d,0x4f,0x50,0x51}};\r
- JoystickDef JoyDefs[MaxJoys];\r
- ControlType Controls[MaxPlayers];\r
-\r
- Demo DemoMode = demo_Off;\r
- byte _seg *DemoBuffer;\r
- word DemoOffset,DemoSize;\r
-\r
-// Internal variables\r
-static boolean IN_Started;\r
-static boolean CapsLock;\r
-static ScanCode CurCode,LastCode;\r
-static byte far ASCIINames[] = // Unshifted ASCII for scan codes\r
- {\r
-// 0 1 2 3 4 5 6 7 8 9 A B C D E F\r
- 0 ,27 ,'1','2','3','4','5','6','7','8','9','0','-','=',8 ,9 , // 0\r
- 'q','w','e','r','t','y','u','i','o','p','[',']',13 ,0 ,'a','s', // 1\r
- 'd','f','g','h','j','k','l',';',39 ,'`',0 ,92 ,'z','x','c','v', // 2\r
- 'b','n','m',',','.','/',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4\r
- '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7\r
- },\r
- far ShiftNames[] = // Shifted ASCII for scan codes\r
- {\r
-// 0 1 2 3 4 5 6 7 8 9 A B C D E F\r
- 0 ,27 ,'!','@','#','$','%','^','&','*','(',')','_','+',8 ,9 , // 0\r
- 'Q','W','E','R','T','Y','U','I','O','P','{','}',13 ,0 ,'A','S', // 1\r
- 'D','F','G','H','J','K','L',':',34 ,'~',0 ,'|','Z','X','C','V', // 2\r
- 'B','N','M','<','>','?',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4\r
- '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7\r
- },\r
- far SpecialNames[] = // ASCII for 0xe0 prefixed codes\r
- {\r
-// 0 1 2 3 4 5 6 7 8 9 A B C D E F\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 0\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,13 ,0 ,0 ,0 , // 1\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 2\r
- 0 ,0 ,0 ,0 ,0 ,'/',0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 3\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 4\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6\r
- 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7\r
- },\r
-\r
-#if 0\r
- *ScanNames[] = // Scan code names with single chars\r
- {\r
- "?","?","1","2","3","4","5","6","7","8","9","0","-","+","?","?",\r
- "Q","W","E","R","T","Y","U","I","O","P","[","]","|","?","A","S",\r
- "D","F","G","H","J","K","L",";","\"","?","?","?","Z","X","C","V",\r
- "B","N","M",",",".","/","?","?","?","?","?","?","?","?","?","?",\r
- "?","?","?","?","?","?","?","?","\xf","?","-","\x15","5","\x11","+","?",\r
- "\x13","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",\r
- "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",\r
- "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?"\r
- }, // DEBUG - consolidate these\r
-#endif\r
-\r
- far ExtScanCodes[] = // Scan codes with >1 char names\r
- {\r
- 1,0xe,0xf,0x1d,0x2a,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,\r
- 0x3f,0x40,0x41,0x42,0x43,0x44,0x57,0x59,0x46,0x1c,0x36,\r
- 0x37,0x38,0x47,0x49,0x4f,0x51,0x52,0x53,0x45,0x48,\r
- 0x50,0x4b,0x4d,0x00\r
- };\r
-#if 0\r
- *ExtScanNames[] = // Names corresponding to ExtScanCodes\r
- {\r
- "Esc","BkSp","Tab","Ctrl","LShft","Space","CapsLk","F1","F2","F3","F4",\r
- "F5","F6","F7","F8","F9","F10","F11","F12","ScrlLk","Enter","RShft",\r
- "PrtSc","Alt","Home","PgUp","End","PgDn","Ins","Del","NumLk","Up",\r
- "Down","Left","Right",""\r
- };\r
-#endif\r
-static Direction DirTable[] = // Quick lookup for total direction\r
- {\r
- dir_NorthWest, dir_North, dir_NorthEast,\r
- dir_West, dir_None, dir_East,\r
- dir_SouthWest, dir_South, dir_SouthEast\r
- };\r
-\r
-static void (*INL_KeyHook)(void);\r
-static void interrupt (*OldKeyVect)(void);\r
-\r
-static char *ParmStrings[] = {"nojoys","nomouse",nil};\r
-\r
-// Internal routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_KeyService() - Handles a keyboard interrupt (key up/down)\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void interrupt\r
-INL_KeyService(void)\r
-{\r
-static boolean special;\r
- byte k,c,\r
- temp;\r
-\r
- k = inportb(0x60); // Get the scan code\r
-\r
- // Tell the XT keyboard controller to clear the key\r
- outportb(0x61,(temp = inportb(0x61)) | 0x80);\r
- outportb(0x61,temp);\r
-\r
- if (k == 0xe0) // Special key prefix\r
- special = true;\r
- else if (k == 0xe1) // Handle Pause key\r
- Paused = true;\r
- else\r
- {\r
- if (k & 0x80) // Break code\r
- {\r
- k &= 0x7f;\r
-\r
-// DEBUG - handle special keys: ctl-alt-delete, print scrn\r
-\r
- Keyboard[k] = false;\r
- }\r
- else // Make code\r
- {\r
- LastCode = CurCode;\r
- CurCode = LastScan = k;\r
- Keyboard[k] = true;\r
-\r
- if (special)\r
- c = SpecialNames[k];\r
- else\r
- {\r
- if (k == sc_CapsLock)\r
- {\r
- CapsLock ^= true;\r
- // DEBUG - make caps lock light work\r
- }\r
-\r
- if (Keyboard[sc_LShift] || Keyboard[sc_RShift]) // If shifted\r
- {\r
- c = ShiftNames[k];\r
- if ((c >= 'A') && (c <= 'Z') && CapsLock)\r
- c += 'a' - 'A';\r
- }\r
- else\r
- {\r
- c = ASCIINames[k];\r
- if ((c >= 'a') && (c <= 'z') && CapsLock)\r
- c -= 'a' - 'A';\r
- }\r
- }\r
- if (c)\r
- LastASCII = c;\r
- }\r
-\r
- special = false;\r
- }\r
-\r
- if (INL_KeyHook && !special)\r
- INL_KeyHook();\r
- outportb(0x20,0x20);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_GetMouseDelta() - Gets the amount that the mouse has moved from the\r
-// mouse driver\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-INL_GetMouseDelta(int *x,int *y)\r
-{\r
- Mouse(MDelta);\r
- *x = _CX;\r
- *y = _DX;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_GetMouseButtons() - Gets the status of the mouse buttons from the\r
-// mouse driver\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static word\r
-INL_GetMouseButtons(void)\r
-{\r
- word buttons;\r
-\r
- Mouse(MButtons);\r
- buttons = _BX;\r
- return(buttons);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_GetJoyAbs() - Reads the absolute position of the specified joystick\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_GetJoyAbs(word joy,word *xp,word *yp)\r
-{\r
- byte xb,yb,\r
- xs,ys;\r
- word x,y;\r
-\r
- x = y = 0;\r
- xs = joy? 2 : 0; // Find shift value for x axis\r
- xb = 1 << xs; // Use shift value to get x bit mask\r
- ys = joy? 3 : 1; // Do the same for y axis\r
- yb = 1 << ys;\r
-\r
-// Read the absolute joystick values\r
-asm pushf // Save some registers\r
-asm push si\r
-asm push di\r
-asm cli // Make sure an interrupt doesn't screw the timings\r
-\r
-\r
-asm mov dx,0x201\r
-asm in al,dx\r
-asm out dx,al // Clear the resistors\r
-\r
-asm mov ah,[xb] // Get masks into registers\r
-asm mov ch,[yb]\r
-\r
-asm xor si,si // Clear count registers\r
-asm xor di,di\r
-asm xor bh,bh // Clear high byte of bx for later\r
-\r
-asm push bp // Don't mess up stack frame\r
-asm mov bp,MaxJoyValue\r
-\r
-loop:\r
-asm in al,dx // Get bits indicating whether all are finished\r
-\r
-asm dec bp // Check bounding register\r
-asm jz done // We have a silly value - abort\r
-\r
-asm mov bl,al // Duplicate the bits\r
-asm and bl,ah // Mask off useless bits (in [xb])\r
-asm add si,bx // Possibly increment count register\r
-asm mov cl,bl // Save for testing later\r
-\r
-asm mov bl,al\r
-asm and bl,ch // [yb]\r
-asm add di,bx\r
-\r
-asm add cl,bl\r
-asm jnz loop // If both bits were 0, drop out\r
-\r
-done:\r
-asm pop bp\r
-\r
-asm mov cl,[xs] // Get the number of bits to shift\r
-asm shr si,cl // and shift the count that many times\r
-\r
-asm mov cl,[ys]\r
-asm shr di,cl\r
-\r
-asm mov [x],si // Store the values into the variables\r
-asm mov [y],di\r
-\r
-asm pop di\r
-asm pop si\r
-asm popf // Restore the registers\r
-\r
- *xp = x;\r
- *yp = y;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_GetJoyDelta() - Returns the relative movement of the specified\r
-// joystick (from +/-127, scaled adaptively)\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-INL_GetJoyDelta(word joy,int *dx,int *dy,boolean adaptive)\r
-{\r
- word x,y;\r
- longword time;\r
- JoystickDef *def;\r
-static longword lasttime;\r
-\r
- IN_GetJoyAbs(joy,&x,&y);\r
- def = JoyDefs + joy;\r
-\r
- if (x < def->threshMinX)\r
- {\r
- if (x < def->joyMinX)\r
- x = def->joyMinX;\r
-\r
- x = -(x - def->threshMinX);\r
- x *= def->joyMultXL;\r
- x >>= JoyScaleShift;\r
- *dx = (x > 127)? -127 : -x;\r
- }\r
- else if (x > def->threshMaxX)\r
- {\r
- if (x > def->joyMaxX)\r
- x = def->joyMaxX;\r
-\r
- x = x - def->threshMaxX;\r
- x *= def->joyMultXH;\r
- x >>= JoyScaleShift;\r
- *dx = (x > 127)? 127 : x;\r
- }\r
- else\r
- *dx = 0;\r
-\r
- if (y < def->threshMinY)\r
- {\r
- if (y < def->joyMinY)\r
- y = def->joyMinY;\r
-\r
- y = -(y - def->threshMinY);\r
- y *= def->joyMultYL;\r
- y >>= JoyScaleShift;\r
- *dy = (y > 127)? -127 : -y;\r
- }\r
- else if (y > def->threshMaxY)\r
- {\r
- if (y > def->joyMaxY)\r
- y = def->joyMaxY;\r
-\r
- y = y - def->threshMaxY;\r
- y *= def->joyMultYH;\r
- y >>= JoyScaleShift;\r
- *dy = (y > 127)? 127 : y;\r
- }\r
- else\r
- *dy = 0;\r
-\r
- if (adaptive)\r
- {\r
- time = (TimeCount - lasttime) / 2;\r
- if (time)\r
- {\r
- if (time > 8)\r
- time = 8;\r
- *dx *= time;\r
- *dy *= time;\r
- }\r
- }\r
- lasttime = TimeCount;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_GetJoyButtons() - Returns the button status of the specified\r
-// joystick\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static word\r
-INL_GetJoyButtons(word joy)\r
-{\r
-register word result;\r
-\r
- result = inportb(0x201); // Get all the joystick buttons\r
- result >>= joy? 6 : 4; // Shift into bits 0-1\r
- result &= 3; // Mask off the useless bits\r
- result ^= 3;\r
- return(result);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_GetJoyButtonsDB() - Returns the de-bounced button status of the\r
-// specified joystick\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-word\r
-IN_GetJoyButtonsDB(word joy)\r
-{\r
- longword lasttime;\r
- word result1,result2;\r
-\r
- do\r
- {\r
- result1 = INL_GetJoyButtons(joy);\r
- lasttime = TimeCount;\r
- while (TimeCount == lasttime)\r
- ;\r
- result2 = INL_GetJoyButtons(joy);\r
- } while (result1 != result2);\r
- return(result1);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_StartKbd() - Sets up my keyboard stuff for use\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-INL_StartKbd(void)\r
-{\r
- INL_KeyHook = 0; // Clear key hook\r
-\r
- IN_ClearKeysDown();\r
-\r
- OldKeyVect = getvect(KeyInt);\r
- setvect(KeyInt,INL_KeyService);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_ShutKbd() - Restores keyboard control to the BIOS\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-INL_ShutKbd(void)\r
-{\r
- poke(0x40,0x17,peek(0x40,0x17) & 0xfaf0); // Clear ctrl/alt/shift flags\r
-\r
- setvect(KeyInt,OldKeyVect);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_StartMouse() - Detects and sets up the mouse\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-INL_StartMouse(void)\r
-{\r
- if (getvect(MouseInt))\r
- {\r
- Mouse(MReset);\r
- if (_AX == 0xffff)\r
- return(true);\r
- }\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_ShutMouse() - Cleans up after the mouse\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-INL_ShutMouse(void)\r
-{\r
-}\r
-\r
-//\r
-// INL_SetJoyScale() - Sets up scaling values for the specified joystick\r
-//\r
-static void\r
-INL_SetJoyScale(word joy)\r
-{\r
- JoystickDef *def;\r
-\r
- def = &JoyDefs[joy];\r
- def->joyMultXL = JoyScaleMax / (def->threshMinX - def->joyMinX);\r
- def->joyMultXH = JoyScaleMax / (def->joyMaxX - def->threshMaxX);\r
- def->joyMultYL = JoyScaleMax / (def->threshMinY - def->joyMinY);\r
- def->joyMultYH = JoyScaleMax / (def->joyMaxY - def->threshMaxY);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_SetupJoy() - Sets up thresholding values and calls INL_SetJoyScale()\r
-// to set up scaling values\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_SetupJoy(word joy,word minx,word maxx,word miny,word maxy)\r
-{\r
- word d,r;\r
- JoystickDef *def;\r
-\r
- def = &JoyDefs[joy];\r
-\r
- def->joyMinX = minx;\r
- def->joyMaxX = maxx;\r
- r = maxx - minx;\r
- d = r / 5;\r
- def->threshMinX = ((r / 2) - d) + minx;\r
- def->threshMaxX = ((r / 2) + d) + minx;\r
-\r
- def->joyMinY = miny;\r
- def->joyMaxY = maxy;\r
- r = maxy - miny;\r
- d = r / 5;\r
- def->threshMinY = ((r / 2) - d) + miny;\r
- def->threshMaxY = ((r / 2) + d) + miny;\r
-\r
- INL_SetJoyScale(joy);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_StartJoy() - Detects & auto-configures the specified joystick\r
-// The auto-config assumes the joystick is centered\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-INL_StartJoy(word joy)\r
-{\r
- word x,y;\r
-\r
- IN_GetJoyAbs(joy,&x,&y);\r
-\r
- if\r
- (\r
- ((x == 0) || (x > MaxJoyValue - 10))\r
- || ((y == 0) || (y > MaxJoyValue - 10))\r
- )\r
- return(false);\r
- else\r
- {\r
- IN_SetupJoy(joy,0,x * 2,0,y * 2);\r
- return(true);\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_ShutJoy() - Cleans up the joystick stuff\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-INL_ShutJoy(word joy)\r
-{\r
- JoysPresent[joy] = false;\r
-}\r
-\r
-// Public routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_Startup() - Starts up the Input Mgr\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_Startup(void)\r
-{\r
- boolean checkjoys,checkmouse;\r
- word i;\r
-\r
- if (IN_Started)\r
- return;\r
-\r
- checkjoys = true;\r
- checkmouse = true;\r
- for (i = 1;i < _argc;i++)\r
- {\r
- switch (US_CheckParm(_argv[i],ParmStrings))\r
- {\r
- case 0:\r
- checkjoys = false;\r
- break;\r
- case 1:\r
- checkmouse = false;\r
- break;\r
- }\r
- }\r
-\r
- INL_StartKbd();\r
- MousePresent = checkmouse? INL_StartMouse() : false;\r
-\r
- for (i = 0;i < MaxJoys;i++)\r
- JoysPresent[i] = checkjoys? INL_StartJoy(i) : false;\r
-\r
- IN_Started = true;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_Default() - Sets up default conditions for the Input Mgr\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_Default(boolean gotit,ControlType in)\r
-{\r
- if\r
- (\r
- (!gotit)\r
- || ((in == ctrl_Joystick1) && !JoysPresent[0])\r
- || ((in == ctrl_Joystick2) && !JoysPresent[1])\r
- || ((in == ctrl_Mouse) && !MousePresent)\r
- )\r
- in = ctrl_Keyboard1;\r
- IN_SetControlType(0,in);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_Shutdown() - Shuts down the Input Mgr\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_Shutdown(void)\r
-{\r
- word i;\r
-\r
- if (!IN_Started)\r
- return;\r
-\r
- INL_ShutMouse();\r
- for (i = 0;i < MaxJoys;i++)\r
- INL_ShutJoy(i);\r
- INL_ShutKbd();\r
-\r
- IN_Started = false;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_SetKeyHook() - Sets the routine that gets called by INL_KeyService()\r
-// everytime a real make/break code gets hit\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_SetKeyHook(void (*hook)())\r
-{\r
- INL_KeyHook = hook;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_ClearKeyDown() - Clears the keyboard array\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_ClearKeysDown(void)\r
-{\r
- int i;\r
-\r
- LastScan = sc_None;\r
- LastASCII = key_None;\r
- for (i = 0;i < NumCodes;i++)\r
- Keyboard[i] = false;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// INL_AdjustCursor() - Internal routine of common code from IN_ReadCursor()\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-INL_AdjustCursor(CursorInfo *info,word buttons,int dx,int dy)\r
-{\r
- if (buttons & (1 << 0))\r
- info->button0 = true;\r
- if (buttons & (1 << 1))\r
- info->button1 = true;\r
-\r
- info->x += dx;\r
- info->y += dy;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_ReadCursor() - Reads the input devices and fills in the cursor info\r
-// struct\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_ReadCursor(CursorInfo *info)\r
-{\r
- word i,\r
- buttons;\r
- int dx,dy;\r
-\r
- info->x = info->y = 0;\r
- info->button0 = info->button1 = false;\r
-\r
- if (MousePresent)\r
- {\r
- buttons = INL_GetMouseButtons();\r
- INL_GetMouseDelta(&dx,&dy);\r
- INL_AdjustCursor(info,buttons,dx,dy);\r
- }\r
-\r
- for (i = 0;i < MaxJoys;i++)\r
- {\r
- if (!JoysPresent[i])\r
- continue;\r
-\r
- buttons = INL_GetJoyButtons(i);\r
- INL_GetJoyDelta(i,&dx,&dy,true);\r
- dx /= 64;\r
- dy /= 64;\r
- INL_AdjustCursor(info,buttons,dx,dy);\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_ReadControl() - Reads the device associated with the specified\r
-// player and fills in the control info struct\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_ReadControl(int player,ControlInfo *info)\r
-{\r
- boolean realdelta=false; // MDM (GAMERS EDGE)\r
- byte dbyte;\r
- word buttons;\r
- int dx,dy;\r
- Motion mx,my;\r
- ControlType type;\r
-register KeyboardDef *def;\r
-\r
- dx = dy = 0;\r
- mx = my = motion_None;\r
- buttons = 0;\r
-\r
-#if 0\r
- if (DemoMode == demo_Playback)\r
- {\r
- dbyte = DemoBuffer[DemoOffset + 1];\r
- my = (dbyte & 3) - 1;\r
- mx = ((dbyte >> 2) & 3) - 1;\r
- buttons = (dbyte >> 4) & 3;\r
-\r
- if (!(--DemoBuffer[DemoOffset]))\r
- {\r
- DemoOffset += 2;\r
- if (DemoOffset >= DemoSize)\r
- DemoMode = demo_PlayDone;\r
- }\r
-\r
- realdelta = false;\r
- }\r
- else if (DemoMode == demo_PlayDone)\r
- Quit("Demo playback exceeded");\r
- else\r
-#endif\r
- {\r
- // MDM begin (GAMERS EDGE) - added this block\r
- ControlTypeUsed = ctrl_None;\r
-\r
- // Handle mouse input...\r
- //\r
- if ((MousePresent) && (ControlTypeUsed == ctrl_None))\r
- {\r
- INL_GetMouseDelta(&dx,&dy);\r
- buttons = INL_GetMouseButtons();\r
- realdelta = true;\r
- if (dx || dy || buttons)\r
- ControlTypeUsed = ctrl_Mouse;\r
- }\r
-\r
- // Handle joystick input...\r
- //\r
- if ((JoystickCalibrated) && (ControlTypeUsed == ctrl_None))\r
- {\r
- type = ctrl_Joystick1;\r
- INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy,false);\r
- buttons = INL_GetJoyButtons(type - ctrl_Joystick);\r
- realdelta = true;\r
- if (dx || dy || buttons)\r
- ControlTypeUsed = ctrl_Joystick;\r
- }\r
-\r
- // Handle keyboard input...\r
- //\r
- if (ControlTypeUsed == ctrl_None)\r
- {\r
- type = ctrl_Keyboard1;\r
- def = &KbdDefs[type - ctrl_Keyboard];\r
-\r
- if (Keyboard[def->upleft])\r
- mx = motion_Left,my = motion_Up;\r
- else if (Keyboard[def->upright])\r
- mx = motion_Right,my = motion_Up;\r
- else if (Keyboard[def->downleft])\r
- mx = motion_Left,my = motion_Down;\r
- else if (Keyboard[def->downright])\r
- mx = motion_Right,my = motion_Down;\r
-\r
- if (Keyboard[def->up])\r
- my = motion_Up;\r
- else if (Keyboard[def->down])\r
- my = motion_Down;\r
-\r
- if (Keyboard[def->left])\r
- mx = motion_Left;\r
- else if (Keyboard[def->right])\r
- mx = motion_Right;\r
-\r
- if (Keyboard[def->button0])\r
- buttons += 1 << 0;\r
- if (Keyboard[def->button1])\r
- buttons += 1 << 1;\r
- realdelta = false;\r
- if (mx || my || buttons)\r
- ControlTypeUsed = ctrl_Keyboard;\r
- } // MDM end (GAMERS EDGE)\r
- }\r
-\r
- if (realdelta)\r
- {\r
- mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None);\r
- my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None);\r
- }\r
- else\r
- {\r
- dx = mx * 127;\r
- dy = my * 127;\r
- }\r
-\r
- info->x = dx;\r
- info->xaxis = mx;\r
- info->y = dy;\r
- info->yaxis = my;\r
- info->button0 = buttons & (1 << 0);\r
- info->button1 = buttons & (1 << 1);\r
- info->dir = DirTable[((my + 1) * 3) + (mx + 1)];\r
-\r
-#if 0\r
- if (DemoMode == demo_Record)\r
- {\r
- // Pack the control info into a byte\r
- dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1);\r
-\r
- if\r
- (\r
- (DemoBuffer[DemoOffset + 1] == dbyte)\r
- && (DemoBuffer[DemoOffset] < 255)\r
- )\r
- (DemoBuffer[DemoOffset])++;\r
- else\r
- {\r
- if (DemoOffset || DemoBuffer[DemoOffset])\r
- DemoOffset += 2;\r
-\r
- if (DemoOffset >= DemoSize)\r
- Quit("Demo buffer overflow");\r
-\r
- DemoBuffer[DemoOffset] = 1;\r
- DemoBuffer[DemoOffset + 1] = dbyte;\r
- }\r
- }\r
-#endif\r
-}\r
-\r
-#if 0\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_ReadControl() - Reads the device associated with the specified\r
-// player and fills in the control info struct\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_ReadControl(int player,ControlInfo *info)\r
-{\r
- boolean realdelta;\r
- byte dbyte;\r
- word buttons;\r
- int dx,dy;\r
- Motion mx,my;\r
- ControlType type;\r
-register KeyboardDef *def;\r
-\r
- dx = dy = 0;\r
- mx = my = motion_None;\r
- buttons = 0;\r
-\r
-#if 0\r
- if (DemoMode == demo_Playback)\r
- {\r
- dbyte = DemoBuffer[DemoOffset + 1];\r
- my = (dbyte & 3) - 1;\r
- mx = ((dbyte >> 2) & 3) - 1;\r
- buttons = (dbyte >> 4) & 3;\r
-\r
- if (!(--DemoBuffer[DemoOffset]))\r
- {\r
- DemoOffset += 2;\r
- if (DemoOffset >= DemoSize)\r
- DemoMode = demo_PlayDone;\r
- }\r
-\r
- realdelta = false;\r
- }\r
- else if (DemoMode == demo_PlayDone)\r
- Quit("Demo playback exceeded");\r
- else\r
-#endif\r
- {\r
- switch (type = Controls[player])\r
- {\r
- case ctrl_Keyboard1:\r
- case ctrl_Keyboard2:\r
- def = &KbdDefs[type - ctrl_Keyboard];\r
-\r
- if (Keyboard[def->upleft])\r
- mx = motion_Left,my = motion_Up;\r
- else if (Keyboard[def->upright])\r
- mx = motion_Right,my = motion_Up;\r
- else if (Keyboard[def->downleft])\r
- mx = motion_Left,my = motion_Down;\r
- else if (Keyboard[def->downright])\r
- mx = motion_Right,my = motion_Down;\r
-\r
- if (Keyboard[def->up])\r
- my = motion_Up;\r
- else if (Keyboard[def->down])\r
- my = motion_Down;\r
-\r
- if (Keyboard[def->left])\r
- mx = motion_Left;\r
- else if (Keyboard[def->right])\r
- mx = motion_Right;\r
-\r
- if (Keyboard[def->button0])\r
- buttons += 1 << 0;\r
- if (Keyboard[def->button1])\r
- buttons += 1 << 1;\r
- realdelta = false;\r
- break;\r
- case ctrl_Joystick1:\r
- case ctrl_Joystick2:\r
- INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy,false);\r
- buttons = INL_GetJoyButtons(type - ctrl_Joystick);\r
- realdelta = true;\r
- break;\r
- case ctrl_Mouse:\r
- INL_GetMouseDelta(&dx,&dy);\r
- buttons = INL_GetMouseButtons();\r
- realdelta = true;\r
- break;\r
- }\r
- }\r
-\r
- if (realdelta)\r
- {\r
- mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None);\r
- my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None);\r
- }\r
- else\r
- {\r
- dx = mx * 127;\r
- dy = my * 127;\r
- }\r
-\r
- info->x = dx;\r
- info->xaxis = mx;\r
- info->y = dy;\r
- info->yaxis = my;\r
- info->button0 = buttons & (1 << 0);\r
- info->button1 = buttons & (1 << 1);\r
- info->dir = DirTable[((my + 1) * 3) + (mx + 1)];\r
-\r
-#if 0\r
- if (DemoMode == demo_Record)\r
- {\r
- // Pack the control info into a byte\r
- dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1);\r
-\r
- if\r
- (\r
- (DemoBuffer[DemoOffset + 1] == dbyte)\r
- && (DemoBuffer[DemoOffset] < 255)\r
- )\r
- (DemoBuffer[DemoOffset])++;\r
- else\r
- {\r
- if (DemoOffset || DemoBuffer[DemoOffset])\r
- DemoOffset += 2;\r
-\r
- if (DemoOffset >= DemoSize)\r
- Quit("Demo buffer overflow");\r
-\r
- DemoBuffer[DemoOffset] = 1;\r
- DemoBuffer[DemoOffset + 1] = dbyte;\r
- }\r
- }\r
-#endif\r
-}\r
-#endif\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_SetControlType() - Sets the control type to be used by the specified\r
-// player\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_SetControlType(int player,ControlType type)\r
-{\r
- // DEBUG - check that requested type is present?\r
- Controls[player] = type;\r
-}\r
-\r
-#if 0\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_StartDemoRecord() - Starts the demo recording, using a buffer the\r
-// size passed. Returns if the buffer allocation was successful\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-IN_StartDemoRecord(word bufsize)\r
-{\r
- if (!bufsize)\r
- return(false);\r
-\r
- MM_GetPtr((memptr *)&DemoBuffer,bufsize);\r
- DemoMode = demo_Record;\r
- DemoSize = bufsize & ~1;\r
- DemoOffset = 0;\r
- DemoBuffer[0] = DemoBuffer[1] = 0;\r
-\r
- return(true);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_StartDemoPlayback() - Plays back the demo pointed to of the given size\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_StartDemoPlayback(byte /*_1seg*/ *buffer,word bufsize)\r
-{\r
- DemoBuffer = buffer;\r
- DemoMode = demo_Playback;\r
- DemoSize = bufsize & ~1;\r
- DemoOffset = 0;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_StopDemo() - Turns off demo mode\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_StopDemo(void)\r
-{\r
- if ((DemoMode == demo_Record) && DemoOffset)\r
- DemoOffset += 2;\r
-\r
- DemoMode = demo_Off;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_FreeDemoBuffer() - Frees the demo buffer, if it's been allocated\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_FreeDemoBuffer(void)\r
-{\r
- if (DemoBuffer)\r
- MM_FreePtr((memptr *)&DemoBuffer);\r
-}\r
-#endif\r
-\r
-\r
-#if 0\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_GetScanName() - Returns a string containing the name of the\r
-// specified scan code\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-byte *\r
-IN_GetScanName(ScanCode scan)\r
-{\r
- byte **p;\r
- ScanCode far *s;\r
-\r
- for (s = ExtScanCodes,p = ExtScanNames;*s;p++,s++)\r
- if (*s == scan)\r
- return(*p);\r
-\r
- return(ScanNames[scan]);\r
-}\r
-#endif\r
-\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_WaitForKey() - Waits for a scan code, then clears LastScan and\r
-// returns the scan code\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-ScanCode\r
-IN_WaitForKey(void)\r
-{\r
- ScanCode result;\r
-\r
- while (!(result = LastScan))\r
- ;\r
- LastScan = 0;\r
- return(result);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and\r
-// returns the ASCII value\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-char\r
-IN_WaitForASCII(void)\r
-{\r
- char result;\r
-\r
- while (!(result = LastASCII))\r
- ;\r
- LastASCII = '\0';\r
- return(result);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_AckBack() - Waits for either an ASCII keypress or a button press\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_AckBack(void)\r
-{\r
- word i;\r
-\r
- while (!LastScan)\r
- {\r
- if (MousePresent)\r
- {\r
- if (INL_GetMouseButtons())\r
- {\r
- while (INL_GetMouseButtons())\r
- ;\r
- return;\r
- }\r
- }\r
-\r
- for (i = 0;i < MaxJoys;i++)\r
- {\r
- if (JoysPresent[i])\r
- {\r
- if (IN_GetJoyButtonsDB(i))\r
- {\r
- while (IN_GetJoyButtonsDB(i))\r
- ;\r
- return;\r
- }\r
- }\r
- }\r
- }\r
-\r
- IN_ClearKey(LastScan);\r
- LastScan = sc_None;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_Ack() - Clears user input & then calls IN_AckBack()\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-IN_Ack(void)\r
-{\r
- word i;\r
-\r
- IN_ClearKey(LastScan);\r
- LastScan = sc_None;\r
-\r
- if (MousePresent)\r
- while (INL_GetMouseButtons())\r
- ;\r
- for (i = 0;i < MaxJoys;i++)\r
- if (JoysPresent[i])\r
- while (IN_GetJoyButtonsDB(i))\r
- ;\r
-\r
- IN_AckBack();\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_IsUserInput() - Returns true if a key has been pressed or a button\r
-// is down\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-IN_IsUserInput(void)\r
-{\r
- boolean result;\r
- word i;\r
-\r
- result = LastScan;\r
-\r
- if (MousePresent)\r
- if (INL_GetMouseButtons())\r
- result = true;\r
-\r
- for (i = 0;i < MaxJoys;i++)\r
- if (JoysPresent[i])\r
- if (INL_GetJoyButtons(i))\r
- result = true;\r
-\r
- return(result);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// IN_UserInput() - Waits for the specified delay time (in ticks) or the\r
-// user pressing a key or a mouse button. If the clear flag is set, it\r
-// then either clears the key or waits for the user to let the mouse\r
-// button up.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-IN_UserInput(longword delay,boolean clear)\r
-{\r
- longword lasttime;\r
-\r
- lasttime = TimeCount;\r
- do\r
- {\r
- if (IN_IsUserInput())\r
- {\r
- if (clear)\r
- IN_AckBack();\r
- return(true);\r
- }\r
- } while (TimeCount - lasttime < delay);\r
- return(false);\r
-}\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_IN.h - Header file for Input Manager\r
-// v1.0d1\r
-// By Jason Blochowiak\r
-//\r
-
-#include "lib_head.h"
-\r
-#ifndef __TYPES__\r
-#include "ID_Types.h"\r
-#endif\r
-\r
-#ifndef __ID_IN__\r
-#define __ID_IN__\r
-\r
-#ifdef __DEBUG__\r
-#define __DEBUG_InputMgr__\r
-#endif\r
-\r
-#define MaxPlayers 4\r
-#define MaxKbds 2\r
-#define MaxJoys 2\r
-#define NumCodes 128\r
-\r
-typedef byte ScanCode;\r
-#define sc_None 0\r
-#define sc_Bad 0xff\r
-#define sc_Return 0x1c\r
-#define sc_Enter sc_Return\r
-#define sc_Escape 0x01\r
-#define sc_Space 0x39\r
-#define sc_BackSpace 0x0e\r
-#define sc_Tab 0x0f\r
-#define sc_Alt 0x38\r
-#define sc_Control 0x1d\r
-#define sc_CapsLock 0x3a\r
-#define sc_LShift 0x2a\r
-#define sc_RShift 0x36\r
-#define sc_UpArrow 0x48\r
-#define sc_DownArrow 0x50\r
-#define sc_LeftArrow 0x4b\r
-#define sc_RightArrow 0x4d\r
-#define sc_Insert 0x52\r
-#define sc_Delete 0x53\r
-#define sc_Home 0x47\r
-#define sc_End 0x4f\r
-#define sc_PgUp 0x49\r
-#define sc_PgDn 0x51\r
-#define sc_F1 0x3b\r
-#define sc_F2 0x3c\r
-#define sc_F3 0x3d\r
-#define sc_F4 0x3e\r
-#define sc_F5 0x3f\r
-#define sc_F6 0x40\r
-#define sc_F7 0x41\r
-#define sc_F8 0x42\r
-#define sc_F9 0x43\r
-#define sc_F10 0x44\r
-#define sc_F11 0x57\r
-#define sc_F12 0x59\r
-\r
-#define sc_A 0x1e\r
-#define sc_B 0x30\r
-#define sc_C 0x2e\r
-#define sc_D 0x20\r
-#define sc_E 0x12\r
-#define sc_F 0x21\r
-#define sc_G 0x22\r
-#define sc_H 0x23\r
-#define sc_I 0x17\r
-#define sc_J 0x24\r
-#define sc_K 0x25\r
-#define sc_L 0x26\r
-#define sc_M 0x32\r
-#define sc_N 0x31\r
-#define sc_O 0x18\r
-#define sc_P 0x19\r
-#define sc_Q 0x10\r
-#define sc_R 0x13\r
-#define sc_S 0x1f\r
-#define sc_T 0x14\r
-#define sc_U 0x16\r
-#define sc_V 0x2f\r
-#define sc_W 0x11\r
-#define sc_X 0x2d\r
-#define sc_Y 0x15\r
-#define sc_Z 0x2c\r
-\r
-#define key_None 0\r
-#define key_Return 0x0d\r
-#define key_Enter key_Return\r
-#define key_Escape 0x1b\r
-#define key_Space 0x20\r
-#define key_BackSpace 0x08\r
-#define key_Tab 0x09\r
-#define key_Delete 0x7f\r
-\r
-// Stuff for the mouse\r
-#define MReset 0\r
-#define MButtons 3\r
-#define MDelta 11\r
-\r
-#define MouseInt 0x33\r
-#define Mouse(x) _AX = x,geninterrupt(MouseInt)\r
-\r
-typedef enum {\r
- demo_Off,demo_Record,demo_Playback,demo_PlayDone\r
- } Demo;\r
-typedef enum {\r
- ctrl_None, // MDM (GAMERS EDGE) - added\r
- ctrl_Keyboard,\r
- ctrl_Keyboard1 = ctrl_Keyboard,ctrl_Keyboard2,\r
- ctrl_Joystick,\r
- ctrl_Joystick1 = ctrl_Joystick,ctrl_Joystick2,\r
- ctrl_Mouse\r
- } ControlType;\r
-typedef enum {\r
- motion_Left = -1,motion_Up = -1,\r
- motion_None = 0,\r
- motion_Right = 1,motion_Down = 1\r
- } Motion;\r
-typedef enum {\r
- dir_North,dir_NorthEast,\r
- dir_East,dir_SouthEast,\r
- dir_South,dir_SouthWest,\r
- dir_West,dir_NorthWest,\r
- dir_None\r
- } Direction;\r
-typedef struct {\r
- boolean button0,button1;\r
- int x,y;\r
- Motion xaxis,yaxis;\r
- Direction dir;\r
- } CursorInfo;\r
-typedef CursorInfo ControlInfo;\r
-typedef struct {\r
- ScanCode button0,button1,\r
- upleft, up, upright,\r
- left, right,\r
- downleft, down, downright;\r
- } KeyboardDef;\r
-typedef struct {\r
- word joyMinX,joyMinY,\r
- threshMinX,threshMinY,\r
- threshMaxX,threshMaxY,\r
- joyMaxX,joyMaxY,\r
- joyMultXL,joyMultYL,\r
- joyMultXH,joyMultYH;\r
- } JoystickDef;\r
-// Global variables\r
-extern boolean Keyboard[],\r
- MousePresent,\r
- JoysPresent[];\r
-extern boolean Paused;\r
-extern char LastASCII;\r
-extern ScanCode LastScan;\r
-extern KeyboardDef KbdDefs[];\r
-extern JoystickDef JoyDefs[];\r
-extern ControlType Controls[MaxPlayers];\r
-\r
-extern boolean JoystickCalibrated; // MDM (GAMERS EDGE) - added\r
-extern ControlType ControlTypeUsed; // MDM (GAMERS EDGE) - added\r
-\r
-extern Demo DemoMode;\r
-extern byte _seg *DemoBuffer;\r
-extern word DemoOffset,DemoSize;\r
-\r
-// Function prototypes\r
-#define IN_KeyDown(code) (Keyboard[(code)])\r
-#define IN_ClearKey(code) {Keyboard[code] = false;\\r
- if (code == LastScan) LastScan = sc_None;}\r
-\r
-// DEBUG - put names in prototypes\r
-extern void IN_Startup(void),IN_Shutdown(void),\r
- IN_Default(boolean gotit,ControlType in),\r
- IN_SetKeyHook(void (*)()),\r
- IN_ClearKeysDown(void),\r
- IN_ReadCursor(CursorInfo *),\r
- IN_ReadControl(int,ControlInfo *),\r
- IN_SetControlType(int,ControlType),\r
- IN_GetJoyAbs(word joy,word *xp,word *yp),\r
- IN_SetupJoy(word joy,word minx,word maxx,\r
- word miny,word maxy),\r
- IN_StartDemoPlayback(byte _seg *buffer,word bufsize),\r
- IN_StopDemo(void),IN_FreeDemoBuffer(void),\r
- IN_Ack(void),IN_AckBack(void);\r
-extern boolean IN_UserInput(longword delay,boolean clear),\r
- IN_IsUserInput(void),\r
- IN_StartDemoRecord(word bufsize);\r
-extern byte *IN_GetScanName(ScanCode);\r
-extern char IN_WaitForASCII(void);\r
-extern ScanCode IN_WaitForKey(void);\r
-extern word IN_GetJoyButtonsDB(word joy);\r
-\r
-#endif\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// NEWMM.C\r
-\r
-/*\r
-=============================================================================\r
-\r
- ID software memory manager\r
- --------------------------\r
-\r
-Primary coder: John Carmack\r
-\r
-RELIES ON\r
----------\r
-Quit (char *error) function\r
-\r
-\r
-WORK TO DO\r
-----------\r
-MM_SizePtr to change the size of a given pointer\r
-\r
-Multiple purge levels utilized\r
-\r
-EMS / XMS unmanaged routines\r
-\r
-=============================================================================\r
-*/\r
-\r
-//#include "LIB_HEAD.H"
-#include "ID_MM.H"
-//#pragma hdrstop\r
-\r
-//#pragma warn -pro\r
-//#pragma warn -use\r
-\r
-\r
-#if 1 // 1 == Debug/Dev ; 0 == Production/final\r
-\r
-#define OUT_OF_MEM_MSG "MM_GetPtr: Out of memory!\nYou were short :%ld bytes"\r
-\r
-#else\r
-\r
-\r
-#define OUT_OF_MEM_MSG "\npee\n"
-\r
-#endif\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL INFO\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define LOCKBIT 0x80 // if set in attributes, block cannot be moved\r
-#define PURGEBITS 3 // 0-3 level, 0= unpurgable, 3= purge first\r
-#define PURGEMASK 0xfffc\r
-#define BASEATTRIBUTES 0 // unlocked, non purgable\r
-\r
-#define MAXUMBS 10\r
-\r
-typedef struct mmblockstruct\r
-{\r
- unsigned start,length;\r
- unsigned attributes;\r
- memptr *useptr; // pointer to the segment start\r
- struct mmblockstruct far *next;\r
-} mmblocktype;\r
-\r
-\r
-//#define GETNEWBLOCK {if(!(mmnew=mmfree))Quit("MM_GETNEWBLOCK: No free blocks!");mmfree=mmfree->next;}\r
-\r
-#define GETNEWBLOCK {if(!mmfree)MML_ClearBlock();mmnew=mmfree;mmfree=mmfree->next;}\r
-\r
-#define FREEBLOCK(x) {*x->useptr=NULL;x->next=mmfree;mmfree=x;}\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-mminfotype mminfo;\r
-memptr bufferseg;\r
-boolean mmerror;\r
-\r
-void (* beforesort) (void);\r
-void (* aftersort) (void);\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-boolean mmstarted;\r
-
-void huge *hugeheap;\r
-void far *farheap;\r
-void *nearheap;\r
-\r
-mmblocktype far mmblocks[MAXBLOCKS]\r
- ,far *mmhead,far *mmfree,far *mmrover,far *mmnew;\r
-\r
-boolean bombonerror;\r
-\r
-unsigned totalEMSpages,freeEMSpages,EMSpageframe,EMSpagesmapped,EMShandle;\r
-\r
-void (* XMSaddr) (void); // far pointer to XMS driver\r
-\r
-unsigned numUMBs,UMBbase[MAXUMBS];\r
-\r
-//==========================================================================\r
-\r
-//\r
-// local prototypes\r
-//\r
-\r
-boolean MML_CheckForEMS (void);\r
-void MML_ShutdownEMS (void);\r
-void MM_MapEMS (void);\r
-boolean MML_CheckForXMS (void);\r
-void MML_ShutdownXMS (void);\r
-void MML_UseSpace (unsigned segstart, unsigned seglength);\r
-void MML_ClearBlock (void);\r
-\r
-//==========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= MML_CheckForEMS\r
-=\r
-= Routine from p36 of Extending DOS\r
-=\r
-=======================\r
-*/\r
-\r
-boolean MML_CheckForEMS (void)\r
-{
- boolean emmcfems;
- char emmname[] = "EMMXXXX0";
-
- __asm {\r
- mov dx,OFFSET emmname[0]\r
- mov ax,0x3d00\r
- int 0x21 // try to open EMMXXXX0 device\r
- jc error\r
-\r
- mov bx,ax\r
- mov ax,0x4400\r
-\r
- int 0x21 // get device info\r
- jc error\r
-\r
- and dx,0x80\r
- jz error\r
-\r
- mov ax,0x4407\r
-\r
- int 0x21 // get status\r
- jc error\r
- or al,al\r
- jz error\r
-\r
- mov ah,0x3e\r
- int 0x21 // close handle\r
- jc error
- //\r
- // EMS is good\r
- //
- mov emmcfems,1
- jmp End
- error:
- //\r
- // EMS is bad\r
- //\r
- mov emmcfems,0
- End:
- }
- return(emmcfems);\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MML_SetupEMS\r
-=\r
-=======================\r
-*/\r
-\r
-void MML_SetupEMS (void)\r
-{\r
- char str[80],str2[10];\r
- unsigned error;\r
-\r
- totalEMSpages = freeEMSpages = EMSpageframe = EMSpagesmapped = 0;\r
-\r
- __asm {\r
- mov ah,EMS_STATUS\r
- int EMS_INT // make sure EMS hardware is present\r
- or ah,ah\r
- jnz error\r
-\r
- mov ah,EMS_VERSION\r
- int EMS_INT\r
- or ah,ah\r
- jnz error\r
- cmp al,0x32 // only work on ems 3.2 or greater\r
- jb error\r
-\r
- mov ah,EMS_GETFRAME\r
- int EMS_INT // find the page frame address\r
- or ah,ah\r
- jnz error\r
- mov [EMSpageframe],bx\r
-\r
- mov ah,EMS_GETPAGES\r
- int EMS_INT // find out how much EMS is there\r
- or ah,ah\r
- jnz error\r
- mov [totalEMSpages],dx\r
- mov [freeEMSpages],bx\r
- or bx,bx\r
- jz noEMS // no EMS at all to allocate\r
-\r
- cmp bx,4\r
- jle getpages // there is only 1,2,3,or 4 pages\r
- mov bx,4 // we can't use more than 4 pages\r
- }\r
-\r
-getpages:\r
-asm {\r
- mov [EMSpagesmapped],bx\r
- mov ah,EMS_ALLOCPAGES // allocate up to 64k of EMS\r
- int EMS_INT\r
- or ah,ah\r
- jnz error\r
- mov [EMShandle],dx\r
- }\r
- return;\r
-\r
-error:\r
- error = _AH;\r
- strcpy (str,"MML_SetupEMS: EMS error 0x");\r
- itoa(error,str2,16);\r
- strcpy (str,str2);\r
- Quit (str);\r
-\r
-noEMS:\r
-;\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MML_ShutdownEMS\r
-=\r
-=======================\r
-*/\r
-\r
-void MML_ShutdownEMS (void)\r
-{\r
- if (!EMShandle)\r
- return;\r
-\r
- {\r
- mov ah,EMS_FREEPAGES\r
- mov dx,[EMShandle]\r
- int EMS_INT\r
- or ah,ah\r
- jz ok\r
- }\r
-\r
- Quit ("MML_ShutdownEMS: Error freeing EMS!");\r
-\r
-ok:\r
-;\r
-}\r
-\r
-/*\r
-====================\r
-=\r
-= MM_MapEMS\r
-=\r
-= Maps the 64k of EMS used by memory manager into the page frame\r
-= for general use. This only needs to be called if you are keeping\r
-= other things in EMS.\r
-=\r
-====================\r
-*/\r
-\r
-void MM_MapEMS (void)\r
-{\r
- char str[80],str2[10];\r
- unsigned error;\r
- int i;\r
-\r
- for (i=0;i<EMSpagesmapped;i++)\r
- {\r
- {\r
- mov ah,EMS_MAPPAGE\r
- mov bx,[i] // logical page\r
- mov al,bl // physical page\r
- mov dx,[EMShandle] // handle\r
- int EMS_INT\r
- or ah,ah\r
- jnz error\r
- }\r
- }\r
-\r
- return;\r
-\r
-error:\r
- error = _AH;\r
- strcpy (str,"MM_MapEMS: EMS error 0x");\r
- itoa(error,str2,16);\r
- strcpy (str,str2);\r
- Quit (str);\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= MML_CheckForXMS\r
-=\r
-= Check for XMM driver\r
-=\r
-=======================\r
-*/\r
-\r
-boolean MML_CheckForXMS (void)\r
-{\r
- numUMBs = 0;\r
-\r
-asm {\r
- mov ax,0x4300\r
- int 0x2f // query status of installed diver\r
- cmp al,0x80\r
- je good\r
- }\r
- return false;\r
-good:\r
- return true;\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MML_SetupXMS\r
-=\r
-= Try to allocate all upper memory block\r
-=\r
-=======================\r
-*/\r
-\r
-void MML_SetupXMS (void)\r
-{\r
- unsigned base,size;\r
-\r
- {\r
- mov ax,0x4310\r
- int 0x2f\r
- mov [WORD PTR XMSaddr],bx\r
- mov [WORD PTR XMSaddr+2],es // function pointer to XMS driver\r
- }\r
-\r
-getmemory:\r
- {\r
- mov ah,XMS_ALLOCUMB\r
- mov dx,0xffff // try for largest block possible\r
- call [DWORD PTR XMSaddr]\r
- or ax,ax\r
- jnz gotone\r
-\r
- cmp bl,0xb0 // error: smaller UMB is available\r
- jne done;\r
-\r
- mov ah,XMS_ALLOCUMB\r
- call [DWORD PTR XMSaddr] // DX holds largest available UMB\r
- or ax,ax\r
- jz done // another error...\r
- }\r
-\r
-gotone:\r
- {\r
- mov [base],bx\r
- mov [size],dx\r
- }\r
- MML_UseSpace (base,size);\r
- mminfo.XMSmem += size*16;\r
- UMBbase[numUMBs] = base;\r
- numUMBs++;\r
- if (numUMBs < MAXUMBS)\r
- goto getmemory;\r
-\r
-done:;\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MML_ShutdownXMS\r
-=\r
-======================\r
-*/\r
-\r
-void MML_ShutdownXMS (void)\r
-{\r
- int i;\r
- unsigned base;\r
-\r
- for (i=0;i<numUMBs;i++)\r
- {\r
- base = UMBbase[i];\r
-\r
- mov ah,XMS_FREEUMB\r
- mov dx,[base]\r
- call [DWORD PTR XMSaddr]\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= MML_UseSpace\r
-=\r
-= Marks a range of paragraphs as usable by the memory manager\r
-= This is used to mark space for the near heap, far heap, ems page frame,\r
-= and upper memory blocks\r
-=\r
-======================\r
-*/\r
-\r
-void MML_UseSpace (unsigned segstart, unsigned seglength)\r
-{\r
- mmblocktype far *scan,far *last;\r
- unsigned oldend;\r
- long extra;\r
-\r
- scan = last = mmhead;\r
- mmrover = mmhead; // reset rover to start of memory\r
-\r
-//\r
-// search for the block that contains the range of segments\r
-//\r
- while (scan->start+scan->length < segstart)\r
- {\r
- last = scan;\r
- scan = scan->next;\r
- }\r
-\r
-//\r
-// take the given range out of the block\r
-//\r
- oldend = scan->start + scan->length;\r
- extra = oldend - (segstart+seglength);\r
- if (extra < 0)\r
- Quit ("MML_UseSpace: Segment spans two blocks!");\r
-\r
- if (segstart == scan->start)\r
- {\r
- last->next = scan->next; // unlink block\r
- FREEBLOCK(scan);\r
- scan = last;\r
- }\r
- else\r
- scan->length = segstart-scan->start; // shorten block\r
-\r
- if (extra > 0)\r
- {\r
- GETNEWBLOCK;\r
- mmnew->next = scan->next;\r
- scan->next = mmnew;\r
- mmnew->start = segstart+seglength;\r
- mmnew->length = extra;\r
- mmnew->attributes = LOCKBIT;\r
- }\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= MML_ClearBlock\r
-=\r
-= We are out of blocks, so free a purgable block\r
-=\r
-====================\r
-*/\r
-\r
-void MML_ClearBlock (void)\r
-{\r
- mmblocktype far *scan,far *last;\r
-\r
- scan = mmhead->next;\r
-\r
- while (scan)\r
- {\r
- if (!(scan->attributes&LOCKBIT) && (scan->attributes&PURGEBITS) )\r
- {\r
- MM_FreePtr(scan->useptr);\r
- return;\r
- }\r
- scan = scan->next;\r
- }\r
-\r
- Quit ("MM_ClearBlock: No purgable blocks!");\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===================\r
-=\r
-= MM_Startup\r
-=\r
-= Grabs all space from turbo with malloc/farmalloc\r
-= Allocates bufferseg misc buffer\r
-=\r
-===================\r
-*/\r
-\r
-static char *ParmStrings[] = {"noems","noxms",""};\r
-\r
-void MM_Startup (void)\r
-{\r
- int i;\r
- unsigned long length;\r
- void far *start;\r
- unsigned segstart,seglength,endfree;\r
-\r
- if (mmstarted)\r
- MM_Shutdown ();\r
-\r
-\r
- mmstarted = true;\r
- bombonerror = true;\r
-//\r
-// set up the linked list (everything in the free list;\r
-//\r
- mmhead = NULL;\r
- mmfree = &mmblocks[0];\r
- for (i=0;i<MAXBLOCKS-1;i++)\r
- mmblocks[i].next = &mmblocks[i+1];\r
- mmblocks[i].next = NULL;\r
-\r
-//\r
-// locked block of all memory until we punch out free space\r
-//\r
- GETNEWBLOCK;\r
- mmhead = mmnew; // this will allways be the first node\r
- mmnew->start = 0;\r
- mmnew->length = 0xffff;\r
- mmnew->attributes = LOCKBIT;\r
- mmnew->next = NULL;\r
- mmrover = mmhead;\r
-\r
-\r
-//\r
-// get all available near conventional memory segments\r
-//\r
- length=coreleft();\r
- start = (void far *)(nearheap = malloc(length));\r
-\r
- length -= 16-(FP_OFF(start)&15);\r
- length -= SAVENEARHEAP;\r
- seglength = length / 16; // now in paragraphs\r
- segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;\r
- MML_UseSpace (segstart,seglength);\r
- mminfo.nearheap = length;\r
-\r
-//\r
-// get all available far conventional memory segments\r
-//\r
- length=farcoreleft();\r
- start = farheap = farmalloc(length);\r
- length -= 16-(FP_OFF(start)&15);\r
- length -= SAVEFARHEAP;\r
- seglength = length / 16; // now in paragraphs\r
- segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;\r
- MML_UseSpace (segstart,seglength);\r
- mminfo.farheap = length;\r
- mminfo.mainmem = mminfo.nearheap + mminfo.farheap;\r
-\r
-\r
-//\r
-// detect EMS and allocate up to 64K at page frame\r
-//\r
- mminfo.EMSmem = 0;\r
- for (i = 1;i < _argc;i++)\r
- {\r
- if ( US_CheckParm(_argv[i],ParmStrings) == 0)\r
- goto emsskip; // param NOEMS\r
- }\r
-\r
- if (MML_CheckForEMS())\r
- {\r
- MML_SetupEMS(); // allocate space\r
- MML_UseSpace (EMSpageframe,EMSpagesmapped*0x400);\r
- MM_MapEMS(); // map in used pages\r
- mminfo.EMSmem = EMSpagesmapped*0x4000l;\r
- }\r
-\r
-//\r
-// detect XMS and get upper memory blocks\r
-//\r
-emsskip:\r
- mminfo.XMSmem = 0;\r
- for (i = 1;i < _argc;i++)\r
- {\r
- if ( US_CheckParm(_argv[i],ParmStrings) == 0)\r
- goto xmsskip; // param NOXMS\r
- }\r
-\r
- if (MML_CheckForXMS())\r
- MML_SetupXMS(); // allocate as many UMBs as possible\r
-\r
-//\r
-// allocate the misc buffer\r
-//\r
-xmsskip:\r
- mmrover = mmhead; // start looking for space after low block\r
-\r
- MM_GetPtr (&bufferseg,BUFFERSIZE);\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= MM_Shutdown\r
-=\r
-= Frees all conventional, EMS, and XMS allocated\r
-=\r
-====================\r
-*/\r
-\r
-void MM_Shutdown (void)\r
-{\r
- if (!mmstarted)\r
- return;\r
-\r
- farfree (farheap);\r
- free (nearheap);\r
- MML_ShutdownEMS ();\r
- MML_ShutdownXMS ();\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= MM_GetPtr\r
-=\r
-= Allocates an unlocked, unpurgable block\r
-=\r
-====================\r
-*/\r
-\r
-void MM_GetPtr (memptr *baseptr,unsigned long size)\r
-{\r
- mmblocktype far *scan,far *lastscan,far *endscan\r
- ,far *purge,far *next;\r
- int search;\r
- unsigned needed,startseg;\r
-\r
- needed = (size+15)/16; // convert size from bytes to paragraphs\r
-\r
- GETNEWBLOCK; // fill in start and next after a spot is found\r
- mmnew->length = needed;\r
- mmnew->useptr = baseptr;\r
- mmnew->attributes = BASEATTRIBUTES;\r
-\r
- for (search = 0; search<3; search++)\r
- {\r
- //\r
- // first search: try to allocate right after the rover, then on up\r
- // second search: search from the head pointer up to the rover\r
- // third search: compress memory, then scan from start\r
- if (search == 1 && mmrover == mmhead)\r
- search++;\r
-\r
- switch (search)\r
- {\r
- case 0:\r
- lastscan = mmrover;\r
- scan = mmrover->next;\r
- endscan = NULL;\r
- break;\r
- case 1:\r
- lastscan = mmhead;\r
- scan = mmhead->next;\r
- endscan = mmrover;\r
- break;\r
- case 2:\r
- MM_SortMem ();\r
- lastscan = mmhead;\r
- scan = mmhead->next;\r
- endscan = NULL;\r
- break;\r
- }\r
-\r
- startseg = lastscan->start + lastscan->length;\r
-\r
- while (scan != endscan)\r
- {\r
- if (scan->start - startseg >= needed)\r
- {\r
- //\r
- // got enough space between the end of lastscan and\r
- // the start of scan, so throw out anything in the middle\r
- // and allocate the new block\r
- //\r
- purge = lastscan->next;\r
- lastscan->next = mmnew;\r
- mmnew->start = *(unsigned *)baseptr = startseg;\r
- mmnew->next = scan;\r
- while ( purge != scan)\r
- { // free the purgable block\r
- next = purge->next;\r
- FREEBLOCK(purge);\r
- purge = next; // purge another if not at scan\r
- }\r
- mmrover = mmnew;\r
- return; // good allocation!\r
- }\r
-\r
- //\r
- // if this block is purge level zero or locked, skip past it\r
- //\r
- if ( (scan->attributes & LOCKBIT)\r
- || !(scan->attributes & PURGEBITS) )\r
- {\r
- lastscan = scan;\r
- startseg = lastscan->start + lastscan->length;\r
- }\r
-\r
-\r
- scan=scan->next; // look at next line\r
- }\r
- }\r
-\r
- if (bombonerror)\r
- Quit (OUT_OF_MEM_MSG,(size-mminfo.nearheap));\r
- else\r
- mmerror = true;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= MM_FreePtr\r
-=\r
-= Allocates an unlocked, unpurgable block\r
-=\r
-====================\r
-*/\r
-\r
-void MM_FreePtr (memptr *baseptr)\r
-{\r
- mmblocktype far *scan,far *last;\r
-\r
- last = mmhead;\r
- scan = last->next;\r
-\r
- if (baseptr == mmrover->useptr) // removed the last allocated block\r
- mmrover = mmhead;\r
-\r
- while (scan->useptr != baseptr && scan)\r
- {\r
- last = scan;\r
- scan = scan->next;\r
- }\r
-\r
- if (!scan)\r
- Quit ("MM_FreePtr: Block not found!");\r
-\r
- last->next = scan->next;\r
-\r
- FREEBLOCK(scan);\r
-}\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= MM_SetPurge\r
-=\r
-= Sets the purge level for a block (locked blocks cannot be made purgable)\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_SetPurge (memptr *baseptr, int purge)\r
-{\r
- mmblocktype far *start;\r
-\r
- start = mmrover;\r
-\r
- do\r
- {\r
- if (mmrover->useptr == baseptr)\r
- break;\r
-\r
- mmrover = mmrover->next;\r
-\r
- if (!mmrover)\r
- mmrover = mmhead;\r
- else if (mmrover == start)\r
- Quit ("MM_SetPurge: Block not found!");\r
-\r
- } while (1);\r
-\r
- mmrover->attributes &= ~PURGEBITS;\r
- mmrover->attributes |= purge;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= MM_SetLock\r
-=\r
-= Locks / unlocks the block\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_SetLock (memptr *baseptr, boolean locked)\r
-{\r
- mmblocktype far *start;\r
-\r
- start = mmrover;\r
-\r
- do\r
- {\r
- if (mmrover->useptr == baseptr)\r
- break;\r
-\r
- mmrover = mmrover->next;\r
-\r
- if (!mmrover)\r
- mmrover = mmhead;\r
- else if (mmrover == start)\r
- Quit ("MM_SetLock: Block not found!");\r
-\r
- } while (1);\r
-\r
- mmrover->attributes &= ~LOCKBIT;\r
- mmrover->attributes |= locked*LOCKBIT;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= MM_SortMem\r
-=\r
-= Throws out all purgable stuff and compresses movable blocks\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_SortMem (void)\r
-{\r
- mmblocktype far *scan,far *last,far *next;\r
- unsigned start,length,source,dest,oldborder;\r
- int playing;\r
-\r
- //\r
- // lock down a currently playing sound\r
- //\r
- playing = SD_SoundPlaying ();\r
- if (playing)\r
- {\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- playing += STARTPCSOUNDS;\r
- break;\r
- case sdm_AdLib:\r
- playing += STARTADLIBSOUNDS;\r
- break;\r
- }\r
- MM_SetLock(&(memptr)audiosegs[playing],true);\r
- }\r
-\r
-\r
- SD_StopSound();\r
-// oldborder = bordercolor;\r
-// VW_ColorBorder (15);\r
-\r
- if (beforesort)\r
- beforesort();\r
-\r
- scan = mmhead;\r
-\r
- last = NULL; // shut up compiler warning\r
-\r
- while (scan)\r
- {\r
- if (scan->attributes & LOCKBIT)\r
- {\r
- //\r
- // block is locked, so try to pile later blocks right after it\r
- //\r
- start = scan->start + scan->length;\r
- }\r
- else\r
- {\r
- if (scan->attributes & PURGEBITS)\r
- {\r
- //\r
- // throw out the purgable block\r
- //\r
- next = scan->next;\r
- FREEBLOCK(scan);\r
- last->next = next;\r
- scan = next;\r
- continue;\r
- }\r
- else\r
- {\r
- //\r
- // push the non purgable block on top of the last moved block\r
- //\r
- if (scan->start != start)\r
- {\r
- length = scan->length;\r
- source = scan->start;\r
- dest = start;\r
- while (length > 0xf00)\r
- {\r
- movedata(source,0,dest,0,0xf00*16);\r
- length -= 0xf00;\r
- source += 0xf00;\r
- dest += 0xf00;\r
- }\r
- movedata(source,0,dest,0,length*16);\r
-\r
- scan->start = start;\r
- *(unsigned *)scan->useptr = start;\r
- }\r
- start = scan->start + scan->length;\r
- }\r
- }\r
-\r
- last = scan;\r
- scan = scan->next; // go to next block\r
- }\r
-\r
- mmrover = mmhead;\r
-\r
- if (aftersort)\r
- aftersort();\r
-\r
-// VW_ColorBorder (oldborder);\r
-\r
- if (playing)\r
- MM_SetLock(&(memptr)audiosegs[playing],false);\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-#if 0\r
-/*\r
-=====================\r
-=\r
-= MM_ShowMemory\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_ShowMemory (void)\r
-{\r
- mmblocktype far *scan;\r
- unsigned color,temp;\r
- long end,owner;\r
- char scratch[80],str[10];\r
-\r
- VW_SetDefaultColors();\r
- VW_SetLineWidth(40);\r
- temp = bufferofs;\r
- bufferofs = 0;\r
- VW_SetScreen (0,0);\r
-\r
- scan = mmhead;\r
-\r
- end = -1;\r
-\r
-//CA_OpenDebug ();\r
-\r
- while (scan)\r
- {\r
- if (scan->attributes & PURGEBITS)\r
- color = 5; // dark purple = purgable\r
- else\r
- color = 9; // medium blue = non purgable\r
- if (scan->attributes & LOCKBIT)\r
- color = 12; // red = locked\r
- if (scan->start<=end)\r
- Quit ("MM_ShowMemory: Memory block order currupted!");\r
- end = scan->start+scan->length-1;\r
- VW_Hlin(scan->start,(unsigned)end,0,color);\r
- VW_Plot(scan->start,0,15);\r
- if (scan->next->start > end+1)\r
- VW_Hlin(end+1,scan->next->start,0,0); // black = free\r
-\r
-#if 0\r
-strcpy (scratch,"Size:");\r
-ltoa ((long)scan->length*16,str,10);\r
-strcat (scratch,str);\r
-strcat (scratch,"\tOwner:0x");\r
-owner = (unsigned)scan->useptr;\r
-ultoa (owner,str,16);\r
-strcat (scratch,str);\r
-strcat (scratch,"\n");\r
-write (debughandle,scratch,strlen(scratch));\r
-#endif\r
-\r
- scan = scan->next;\r
- }\r
-\r
-//CA_CloseDebug ();\r
-\r
- IN_Ack();\r
- VW_SetLineWidth(64);\r
- bufferofs = temp;\r
-}\r
-#endif\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MM_UnusedMemory\r
-=\r
-= Returns the total free space without purging\r
-=\r
-======================\r
-*/\r
-\r
-long MM_UnusedMemory (void)\r
-{\r
- unsigned free;\r
- mmblocktype far *scan;\r
-\r
- free = 0;\r
- scan = mmhead;\r
-\r
- while (scan->next)\r
- {\r
- free += scan->next->start - (scan->start + scan->length);\r
- scan = scan->next;\r
- }\r
-\r
- return free*16l;\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MM_TotalFree\r
-=\r
-= Returns the total free space with purging\r
-=\r
-======================\r
-*/\r
-\r
-long MM_TotalFree (void)\r
-{\r
- unsigned free;\r
- mmblocktype far *scan;\r
-\r
- free = 0;\r
- scan = mmhead;\r
-\r
- while (scan->next)\r
- {\r
- if ((scan->attributes&PURGEBITS) && !(scan->attributes&LOCKBIT))\r
- free += scan->length;\r
- free += scan->next->start - (scan->start + scan->length);\r
- scan = scan->next;\r
- }\r
-\r
- return free*16l;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= MM_BombOnError\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_BombOnError (boolean bomb)\r
-{\r
- bombonerror = bomb;\r
-}\r
-\r
-\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_MM.H
-
-#ifndef __ID_EXMM__\r
-\r
-#define __ID_EXMM__
-
-#include "LIB_HEAD.H"\r
-\r
-#define SAVENEARHEAP 0x400 // space to leave in data segment\r
-#define SAVEFARHEAP 0 // space to leave in far heap\r
-\r
-#define BUFFERSIZE 0x1000 // miscelanious, allways available buffer\r
-\r
-#define MAXBLOCKS 600\r
-\r
-\r
-//--------\r
-\r
-#define EMS_INT 0x67\r
-\r
-#define EMS_STATUS 0x40\r
-#define EMS_GETFRAME 0x41\r
-#define EMS_GETPAGES 0x42\r
-#define EMS_ALLOCPAGES 0x43\r
-#define EMS_MAPPAGE 0x44\r
-#define EMS_FREEPAGES 0x45\r
-#define EMS_VERSION 0x46\r
-\r
-//--------\r
-\r
-#define XMS_VERSION 0x00\r
-\r
-#define XMS_ALLOCHMA 0x01\r
-#define XMS_FREEHMA 0x02\r
-\r
-#define XMS_GENABLEA20 0x03\r
-#define XMS_GDISABLEA20 0x04\r
-#define XMS_LENABLEA20 0x05\r
-#define XMS_LDISABLEA20 0x06\r
-#define XMS_QUERYA20 0x07\r
-\r
-#define XMS_QUERYREE 0x08\r
-#define XMS_ALLOC 0x09\r
-#define XMS_FREE 0x0A\r
-#define XMS_MOVE 0x0B\r
-#define XMS_LOCK 0x0C\r
-#define XMS_UNLOCK 0x0D\r
-#define XMS_GETINFO 0x0E\r
-#define XMS_RESIZE 0x0F\r
-\r
-#define XMS_ALLOCUMB 0x10\r
-#define XMS_FREEUMB 0x11\r
-\r
-//==========================================================================\r
-\r
-typedef void /*_seg*/ * memptr;\r
-\r
-typedef struct\r
-{\r
- long nearheap,farheap,EMSmem,XMSmem,mainmem;\r
-} mminfotype;\r
-\r
-//==========================================================================\r
-\r
-extern mminfotype mminfo;\r
-extern memptr bufferseg;\r
-extern boolean mmerror;\r
-\r
-extern void (* beforesort) (void);\r
-extern void (* aftersort) (void);\r
-\r
-//==========================================================================\r
-\r
-void MM_Startup (void);\r
-void MM_Shutdown (void);\r
-void MM_MapEMS (void);\r
-\r
-void MM_GetPtr (memptr *baseptr,unsigned long size);\r
-void MM_FreePtr (memptr *baseptr);\r
-\r
-void MM_SetPurge (memptr *baseptr, int purge);\r
-void MM_SetLock (memptr *baseptr, boolean locked);\r
-void MM_SortMem (void);\r
-\r
-void MM_ShowMemory (void);\r
-\r
-long MM_UnusedMemory (void);\r
-long MM_TotalFree (void);\r
-\r
-void MM_BombOnError (boolean bomb);
-
-#endif
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_RF.C\r
-\r
-/*\r
-=============================================================================\r
-\r
-notes\r
------\r
-\r
-scrolling more than one tile / refresh forces a total redraw\r
-\r
-two overlapping sprites of equal priority can change drawing order when\r
-updated\r
-\r
-=============================================================================\r
-*/\r
-\r
-#include "ID_HEADS.H"\r
-#pragma hdrstop\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define SCREENTILESWIDE 20\r
-#define SCREENTILESHIGH 13\r
-\r
-#define SCREENSPACE (SCREENWIDTH*240)\r
-#define FREEEGAMEM (0x10000l-3l*SCREENSPACE)\r
-\r
-//\r
-// the update array must have enough space for two screens that can float\r
-// up two two tiles each way\r
-//\r
-// (PORTTILESWIDE+1)*PORTTILESHIGH must be even so the arrays can be cleared\r
-// by word width instructions\r
-\r
-#define UPDATESCREENSIZE (UPDATEWIDE*PORTTILESHIGH+2)\r
-#define UPDATESPARESIZE (UPDATEWIDE*2+4)\r
-#define UPDATESIZE (UPDATESCREENSIZE+2*UPDATESPARESIZE)\r
-\r
-#define G_EGASX_SHIFT 7 // global >> ?? = screen x\r
-#define G_CGASX_SHIFT 6 // global >> ?? = screen x\r
-#define G_SY_SHIFT 4 // global >> ?? = screen y\r
-\r
-unsigned SX_T_SHIFT; // screen x >> ?? = tile EGA = 1, CGA = 2;\r
-#define SY_T_SHIFT 4 // screen y >> ?? = tile\r
-\r
-\r
-#define EGAPORTSCREENWIDE 42\r
-#define CGAPORTSCREENWIDE 84\r
-#define PORTSCREENHIGH 224\r
-\r
-#define UPDATESCREENSIZE (UPDATEWIDE*PORTTILESHIGH+2)\r
-#define UPDATESPARESIZE (UPDATEWIDE*2+4)\r
-#define UPDATESIZE (UPDATESCREENSIZE+2*UPDATESPARESIZE)\r
-\r
-#define MAXSCROLLEDGES 6\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL TYPES\r
-\r
-=============================================================================\r
-*/\r
-\r
-typedef struct spriteliststruct\r
-{\r
- int screenx,screeny;\r
- int width,height;\r
-\r
- unsigned grseg,sourceofs,planesize;\r
- drawtype draw;\r
- unsigned tilex,tiley,tilewide,tilehigh;\r
- int priority,updatecount;\r
- struct spriteliststruct **prevptr,*nextsprite;\r
-} spritelisttype;\r
-\r
-\r
-typedef struct\r
-{\r
- int screenx,screeny;\r
- int width,height;\r
-} eraseblocktype;\r
-\r
-\r
-typedef struct\r
-{\r
- unsigned current; // foreground tiles have high bit set\r
- int count;\r
-} tiletype;\r
-\r
-\r
-typedef struct animtilestruct\r
-{\r
- unsigned x,y,tile;\r
- tiletype *chain;\r
- unsigned far *mapplane;\r
- struct animtilestruct **prevptr,*nexttile;\r
-} animtiletype;\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-unsigned tics;\r
-long lasttimecount;\r
-\r
-boolean compatability; // crippled refresh for wierdo SVGAs\r
-\r
-unsigned mapwidth,mapheight,mapbyteswide,mapwordswide\r
- ,mapbytesextra,mapwordsextra;\r
-unsigned mapbwidthtable[MAXMAPHEIGHT];\r
-\r
-//\r
-// Global : Actor coordinates are in this, at 1/16 th of a pixel, to allow\r
-// for fractional movement and acceleration.\r
-//\r
-// Tiles : Tile offsets from the upper left corner of the current map.\r
-//\r
-// Screen : Graphics level offsets from map origin, x in bytes, y in pixels.\r
-// originxscreen is the same spot as originxtile, just with extra precision\r
-// so graphics don't need to be done in tile boundaries.\r
-//\r
-\r
-unsigned originxglobal,originyglobal;\r
-unsigned originxtile,originytile;\r
-unsigned originxscreen,originyscreen;\r
-unsigned originmap;\r
-unsigned originxmin,originxmax,originymin,originymax;\r
-\r
-unsigned masterofs;\r
-\r
-//\r
-// Table of the offsets from bufferofs of each tile spot in the\r
-// view port. The extra wide tile should never be drawn, but the space\r
-// is needed to account for the extra 0 in the update arrays. Built by\r
-// RF_Startup\r
-//\r
-\r
-unsigned blockstarts[UPDATEWIDE*UPDATEHIGH];\r
-unsigned updatemapofs[UPDATEWIDE*UPDATEHIGH];\r
-\r
-unsigned uwidthtable[PORTTILESHIGH]; // lookup instead of multiply\r
-\r
-byte update[2][UPDATESIZE];\r
-byte *updateptr,*baseupdateptr, // current start of update window\r
- *updatestart[2],\r
- *baseupdatestart[2];\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-static char scratch[20],str[80];\r
-\r
-tiletype allanims[MAXANIMTYPES];\r
-unsigned numanimchains;\r
-\r
-void (*refreshvector) (void);\r
-\r
-unsigned screenstart[3] =\r
- {0,SCREENSPACE,SCREENSPACE*2};\r
-\r
-unsigned xpanmask; // prevent panning to odd pixels\r
-\r
-unsigned screenpage; // screen currently being displayed\r
-unsigned otherpage;\r
-\r
-\r
-spritelisttype spritearray[MAXSPRITES],*prioritystart[PRIORITIES],\r
- *spritefreeptr;\r
-\r
-animtiletype animarray[MAXANIMTILES],*animhead,*animfreeptr;\r
-\r
-int animfreespot;\r
-\r
-eraseblocktype eraselist[2][MAXSPRITES],*eraselistptr[2];\r
-\r
-int hscrollblocks,vscrollblocks;\r
-int hscrolledge[MAXSCROLLEDGES],vscrolledge[MAXSCROLLEDGES];\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL PROTOTYPES\r
-\r
-=============================================================================\r
-*/\r
-\r
-void RFL_NewTile (unsigned updateoffset);\r
-void RFL_MaskForegroundTiles (void);\r
-void RFL_UpdateTiles (void);\r
-\r
-void RFL_BoundScroll (int x, int y);\r
-void RFL_CalcOriginStuff (long x, long y);\r
-void RFL_ClearScrollBlocks (void);\r
-void RFL_InitSpriteList (void);\r
-void RFL_InitAnimList (void);\r
-void RFL_CheckForAnimTile (unsigned x, unsigned y);\r
-void RFL_AnimateTiles (void);\r
-void RFL_RemoveAnimsOnX (unsigned x);\r
-void RFL_RemoveAnimsOnY (unsigned y);\r
-void RFL_EraseBlocks (void);\r
-void RFL_UpdateSprites (void);\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- GRMODE INDEPENDANT ROUTINES\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_Startup\r
-=\r
-=====================\r
-*/\r
-\r
-static char *ParmStrings[] = {"comp",""};\r
-\r
-void RF_Startup (void)\r
-{\r
- int i,x,y;\r
- unsigned *blockstart;\r
-\r
- if (grmode == EGAGR)\r
- for (i = 1;i < _argc;i++)\r
- if (US_CheckParm(_argv[i],ParmStrings) == 0)\r
- {\r
- compatability = true;\r
- break;\r
- }\r
-\r
- for (i=0;i<PORTTILESHIGH;i++)\r
- uwidthtable[i] = UPDATEWIDE*i;\r
-\r
- originxmin = originymin = MAPBORDER*TILEGLOBAL;\r
-\r
- eraselistptr[0] = &eraselist[0][0];\r
- eraselistptr[1] = &eraselist[1][0];\r
-\r
-\r
-\r
- if (grmode == EGAGR)\r
- {\r
- SX_T_SHIFT = 1;\r
-\r
- baseupdatestart[0] = &update[0][UPDATESPARESIZE];\r
- baseupdatestart[1] = &update[1][UPDATESPARESIZE];\r
-\r
- screenpage = 0;\r
- otherpage = 1;\r
- displayofs = screenstart[screenpage];\r
- bufferofs = screenstart[otherpage];\r
- masterofs = screenstart[2];\r
-\r
- updateptr = baseupdatestart[otherpage];\r
-\r
- blockstart = &blockstarts[0];\r
- for (y=0;y<UPDATEHIGH;y++)\r
- for (x=0;x<UPDATEWIDE;x++)\r
- *blockstart++ = SCREENWIDTH*16*y+x*TILEWIDTH;\r
-\r
- xpanmask = 6; // dont pan to odd pixels\r
- }\r
-\r
- else if (grmode == CGAGR)\r
- {\r
- SX_T_SHIFT = 2;\r
-\r
- updateptr = baseupdateptr = &update[0][UPDATESPARESIZE];\r
-\r
- bufferofs = 0;\r
- masterofs = 0x8000;\r
-\r
- blockstart = &blockstarts[0];\r
- for (y=0;y<UPDATEHIGH;y++)\r
- for (x=0;x<UPDATEWIDE;x++)\r
- *blockstart++ = SCREENWIDTH*16*y+x*TILEWIDTH;\r
- }\r
-}\r
-\r
-\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_Shutdown\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_Shutdown (void)\r
-{\r
-\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_FixOfs\r
-=\r
-= Sets bufferofs,displayofs, and masterofs to regular values, for the\r
-= occasions when you have moved them around manually\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_FixOfs (void)\r
-{\r
- if (grmode == EGAGR)\r
- {\r
- screenpage = 0;\r
- otherpage = 1;\r
- panx = pany = pansx = pansy = panadjust = 0;\r
- displayofs = screenstart[screenpage];\r
- bufferofs = screenstart[otherpage];\r
- masterofs = screenstart[2];\r
- VW_SetScreen (displayofs,0);\r
- }\r
- else\r
- {\r
- bufferofs = 0;\r
- masterofs = 0x8000;\r
- }\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_NewMap\r
-=\r
-= Makes some convienient calculations based on maphead->\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_NewMap (void)\r
-{\r
- int i,x,y;\r
- unsigned spot,*table;\r
-\r
- mapwidth = mapheaderseg[mapon]->width;\r
- mapbyteswide = 2*mapwidth;\r
- mapheight = mapheaderseg[mapon]->height;\r
- mapwordsextra = mapwidth-PORTTILESWIDE;\r
- mapbytesextra = 2*mapwordsextra;\r
-\r
-//\r
-// make a lookup table for the maps left edge\r
-//\r
- if (mapheight > MAXMAPHEIGHT)\r
- Quit ("RF_NewMap: Map too tall!");\r
- spot = 0;\r
- for (i=0;i<mapheight;i++)\r
- {\r
- mapbwidthtable[i] = spot;\r
- spot += mapbyteswide;\r
- }\r
-\r
-//\r
-// fill in updatemapofs with the new width info\r
-//\r
- table = &updatemapofs[0];\r
- for (y=0;y<PORTTILESHIGH;y++)\r
- for (x=0;x<UPDATEWIDE;x++)\r
- *table++ = mapbwidthtable[y]+x*2;\r
-\r
-//\r
-// the y max value clips off the bottom half of a tile so a map that is\r
-// 13 + MAPBORDER*2 tile high will not scroll at all vertically\r
-//\r
- originxmax = (mapwidth-MAPBORDER-SCREENTILESWIDE)*TILEGLOBAL;\r
- originymax = (mapheight-MAPBORDER-SCREENTILESHIGH)*TILEGLOBAL;\r
- if (originxmax<originxmin) // for very small maps\r
- originxmax=originxmin;\r
- if (originymax<originymin)\r
- originymax=originymin;\r
-\r
-//\r
-// clear out the lists\r
-//\r
- RFL_InitSpriteList ();\r
- RFL_InitAnimList ();\r
- RFL_ClearScrollBlocks ();\r
- RF_SetScrollBlock (0,MAPBORDER-1,true);\r
- RF_SetScrollBlock (0,mapheight-MAPBORDER,true);\r
- RF_SetScrollBlock (MAPBORDER-1,0,false);\r
- RF_SetScrollBlock (mapwidth-MAPBORDER,0,false);\r
-\r
-\r
- lasttimecount = TimeCount; // setup for adaptive timing\r
- tics = 1;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-==========================\r
-=\r
-= RF_MarkTileGraphics\r
-=\r
-= Goes through mapplane[0/1] and marks all background/foreground tiles\r
-= needed, then follows all animation sequences to make sure animated\r
-= tiles get all the stages. Every unique animating tile is given an\r
-= entry in allanims[], so every instance of that tile will animate at the\r
-= same rate. The info plane for each animating tile will hold a pointer\r
-= into allanims[], therefore you can't have both an animating foreground\r
-= and background tile in the same spot!\r
-=\r
-==========================\r
-*/\r
-\r
-void RF_MarkTileGraphics (void)\r
-{\r
- unsigned size;\r
- int tile,next,anims,change;\r
- unsigned far *start,far *end,far *info;\r
- unsigned i,tilehigh;\r
- char str[80],str2[10];\r
-\r
- memset (allanims,0,sizeof(allanims));\r
- numanimchains = 0;\r
-\r
- size = mapwidth*mapheight;\r
-\r
-//\r
-// background plane\r
-//\r
- start = mapsegs[0];\r
- info = mapsegs[2];\r
- end = start+size;\r
- do\r
- {\r
- tile = *start++;\r
- if (tile>=0) // <0 is a tile that is never drawn\r
- {\r
- CA_MarkGrChunk(STARTTILE16+tile);\r
- if (tinf[ANIM+tile])\r
- {\r
- // this tile will animated\r
-\r
- if (tinf[SPEED+tile])\r
- {\r
- if (!tinf[ANIM+tile])\r
- {\r
- strcpy (str,"RF_MarkTileGraphics: Background anim of 0:");\r
- itoa (tile,str2,10);\r
- strcat (str,str2);\r
- Quit (str);\r
- }\r
- for (i=0;i<numanimchains;i++)\r
- if (allanims[i].current == tile)\r
- {\r
- *info = (unsigned)&allanims[i];\r
- goto nextback;\r
- }\r
-\r
- // new chain of animating tiles\r
-\r
- if (i>=MAXANIMTYPES)\r
- Quit ("RF_MarkTileGraphics: Too many unique animated tiles!");\r
- allanims[i].current = tile;\r
- allanims[i].count = tinf[SPEED+tile];\r
- *info = (unsigned)&allanims[i];\r
- numanimchains++;\r
- }\r
-\r
- anims = 0;\r
- change = (signed char)(tinf[ANIM+tile]);\r
- next = tile+change;\r
- while (change && next != tile)\r
- {\r
- CA_MarkGrChunk(STARTTILE16+next);\r
- change = (signed char)(tinf[ANIM+next]);\r
- next += change;\r
- if (++anims > 20)\r
- {\r
- strcpy (str,"RF_MarkTileGraphics: Unending background animation:");\r
- itoa (next,str2,10);\r
- strcat (str,str2);\r
- Quit (str);\r
- }\r
- }\r
-\r
- }\r
- }\r
-nextback:\r
- info++;\r
- } while (start<end);\r
-\r
-//\r
-// foreground plane\r
-//\r
- start = mapsegs[1];\r
- info = mapsegs[2];\r
- end = start+size;\r
- do\r
- {\r
- tile = *start++;\r
- if (tile>=0) // <0 is a tile that is never drawn\r
- {\r
- CA_MarkGrChunk(STARTTILE16M+tile);\r
- if (tinf[MANIM+tile])\r
- {\r
- // this tile will animated\r
-\r
- if (tinf[MSPEED+tile])\r
- {\r
- if (!tinf[MANIM+tile])\r
- {\r
- strcpy (str,"RF_MarkTileGraphics: Foreground anim of 0:");\r
- itoa (tile,str2,10);\r
- strcat (str,str2);\r
- Quit (str);\r
- }\r
- tilehigh = tile | 0x8000; // foreground tiles have high bit\r
- for (i=0;i<numanimchains;i++)\r
- if (allanims[i].current == tilehigh)\r
- {\r
- *info = (unsigned)&allanims[i];\r
- goto nextfront;\r
- }\r
-\r
- // new chain of animating tiles\r
-\r
- if (i>=MAXANIMTYPES)\r
- Quit ("RF_MarkTileGraphics: Too many unique animated tiles!");\r
- allanims[i].current = tilehigh;\r
- allanims[i].count = tinf[MSPEED+tile];\r
-\r
- *info = (unsigned)&allanims[i];\r
- numanimchains++;\r
- }\r
-\r
- anims = 0;\r
- change = (signed char)(tinf[MANIM+tile]);\r
- next = tile+change;\r
- while (change && next != tile)\r
- {\r
- CA_MarkGrChunk(STARTTILE16M+next);\r
- change = (signed char)(tinf[MANIM+next]);\r
- next += change;\r
- if (++anims > 20)\r
- {\r
- strcpy (str,"RF_MarkTileGraphics: Unending foreground animation:");\r
- itoa (next,str2,10);\r
- strcat (str,str2);\r
- Quit (str);\r
- }\r
- }\r
-\r
- }\r
- }\r
-nextfront:\r
- info++;\r
- } while (start<end);\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=========================\r
-=\r
-= RFL_InitAnimList\r
-=\r
-= Call to clear out the entire animating tile list and return all of them to\r
-= the free list.\r
-=\r
-=========================\r
-*/\r
-\r
-void RFL_InitAnimList (void)\r
-{\r
- int i;\r
-\r
- animfreeptr = &animarray[0];\r
-\r
- for (i=0;i<MAXANIMTILES-1;i++)\r
- animarray[i].nexttile = &animarray[i+1];\r
-\r
- animarray[i].nexttile = NULL;\r
-\r
- animhead = NULL; // nothing in list\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= RFL_CheckForAnimTile\r
-=\r
-====================\r
-*/\r
-\r
-void RFL_CheckForAnimTile (unsigned x, unsigned y)\r
-{\r
- unsigned tile,offset,speed,lasttime,thistime,timemissed;\r
- unsigned far *map;\r
- animtiletype *anim,*next;\r
-\r
-// the info plane of each animating tile has a near pointer into allanims[]\r
-// which gives the current state of all concurrently animating tiles\r
-\r
- offset = mapbwidthtable[y]/2+x;\r
-\r
-//\r
-// background\r
-//\r
- map = mapsegs[0]+offset;\r
- tile = *map;\r
- if (tinf[ANIM+tile] && tinf[SPEED+tile])\r
- {\r
- if (!animfreeptr)\r
- Quit ("RF_CheckForAnimTile: No free spots in tilearray!");\r
- anim = animfreeptr;\r
- animfreeptr = animfreeptr->nexttile;\r
- next = animhead; // stick it at the start of the list\r
- animhead = anim;\r
- if (next)\r
- next->prevptr = &anim->nexttile;\r
- anim->nexttile = next;\r
- anim->prevptr = &animhead;\r
-\r
- anim->x = x;\r
- anim->y = y;\r
- anim->tile = tile;\r
- anim->mapplane = map;\r
- anim->chain = (tiletype *)*(mapsegs[2]+offset);\r
- }\r
-\r
-//\r
-// foreground\r
-//\r
- map = mapsegs[1]+offset;\r
- tile = *map;\r
- if (tinf[MANIM+tile] && tinf[MSPEED+tile])\r
- {\r
- if (!animfreeptr)\r
- Quit ("RF_CheckForAnimTile: No free spots in tilearray!");\r
- anim = animfreeptr;\r
- animfreeptr = animfreeptr->nexttile;\r
- next = animhead; // stick it at the start of the list\r
- animhead = anim;\r
- if (next)\r
- next->prevptr = &anim->nexttile;\r
- anim->nexttile = next;\r
- anim->prevptr = &animhead;\r
-\r
- anim->x = x;\r
- anim->y = y;\r
- anim->tile = tile;\r
- anim->mapplane = map;\r
- anim->chain = (tiletype *)*(mapsegs[2]+offset);\r
- }\r
-\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= RFL_RemoveAnimsOnX\r
-=\r
-====================\r
-*/\r
-\r
-void RFL_RemoveAnimsOnX (unsigned x)\r
-{\r
- animtiletype *current,*next;\r
-\r
- current = animhead;\r
- while (current)\r
- {\r
- if (current->x == x)\r
- {\r
- *(void **)current->prevptr = current->nexttile;\r
- if (current->nexttile)\r
- current->nexttile->prevptr = current->prevptr;\r
- next = current->nexttile;\r
- current->nexttile = animfreeptr;\r
- animfreeptr = current;\r
- current = next;\r
- }\r
- else\r
- current = current->nexttile;\r
- }\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= RFL_RemoveAnimsOnY\r
-=\r
-====================\r
-*/\r
-\r
-void RFL_RemoveAnimsOnY (unsigned y)\r
-{\r
- animtiletype *current,*next;\r
-\r
- current = animhead;\r
- while (current)\r
- {\r
- if (current->y == y)\r
- {\r
- *(void **)current->prevptr = current->nexttile;\r
- if (current->nexttile)\r
- current->nexttile->prevptr = current->prevptr;\r
- next = current->nexttile;\r
- current->nexttile = animfreeptr;\r
- animfreeptr = current;\r
- current = next;\r
- }\r
- else\r
- current = current->nexttile;\r
- }\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= RFL_RemoveAnimsInBlock\r
-=\r
-====================\r
-*/\r
-\r
-void RFL_RemoveAnimsInBlock (unsigned x, unsigned y, unsigned width, unsigned height)\r
-{\r
- animtiletype *current,*next;\r
-\r
- current = animhead;\r
- while (current)\r
- {\r
- if (current->x - x < width && current->y - y < height)\r
- {\r
- *(void **)current->prevptr = current->nexttile;\r
- if (current->nexttile)\r
- current->nexttile->prevptr = current->prevptr;\r
- next = current->nexttile;\r
- current->nexttile = animfreeptr;\r
- animfreeptr = current;\r
- current = next;\r
- }\r
- else\r
- current = current->nexttile;\r
- }\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= RFL_AnimateTiles\r
-=\r
-====================\r
-*/\r
-\r
-void RFL_AnimateTiles (void)\r
-{\r
- animtiletype *current;\r
- unsigned updateofs,tile,x,y;\r
- tiletype *anim;\r
-\r
-//\r
-// animate the lists of tiles\r
-//\r
- anim = &allanims[0];\r
- while (anim->current)\r
- {\r
- anim->count-=tics;\r
- while ( anim->count < 1)\r
- {\r
- if (anim->current & 0x8000)\r
- {\r
- tile = anim->current & 0x7fff;\r
- tile += (signed char)tinf[MANIM+tile];\r
- anim->count += tinf[MSPEED+tile];\r
- tile |= 0x8000;\r
- }\r
- else\r
- {\r
- tile = anim->current;\r
- tile += (signed char)tinf[ANIM+tile];\r
- anim->count += tinf[SPEED+tile];\r
- }\r
- anim->current = tile;\r
- }\r
- anim++;\r
- }\r
-\r
-\r
-//\r
-// traverse the list of animating tiles\r
-//\r
- current = animhead;\r
- while (current)\r
- {\r
- tile =current->chain->current;\r
- if ( tile != current->tile)\r
- {\r
- // tile has animated\r
- //\r
- // remove tile from master screen cache,\r
- // change a tile to its next state, set the structure up for\r
- // next animation, and post an update region to both update pages\r
- //\r
- current->tile = tile;\r
-\r
- *(current->mapplane) = tile & 0x7fff; // change in map\r
-\r
- x = current->x-originxtile;\r
- y = current->y-originytile;\r
-\r
- if (x>=PORTTILESWIDE || y>=PORTTILESHIGH)\r
- Quit ("RFL_AnimateTiles: Out of bounds!");\r
-\r
- updateofs = uwidthtable[y] + x;\r
- RFL_NewTile(updateofs); // puts "1"s in both pages\r
- }\r
- current = current->nexttile;\r
- }\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=========================\r
-=\r
-= RFL_InitSpriteList\r
-=\r
-= Call to clear out the entire sprite list and return all of them to\r
-= the free list.\r
-=\r
-=========================\r
-*/\r
-\r
-void RFL_InitSpriteList (void)\r
-{\r
- int i;\r
-\r
- spritefreeptr = &spritearray[0];\r
- for (i=0;i<MAXSPRITES-1;i++)\r
- spritearray[i].nextsprite = &spritearray[i+1];\r
-\r
- spritearray[i].nextsprite = NULL;\r
-\r
-// NULL in all priority levels\r
-\r
- memset (prioritystart,0,sizeof(prioritystart));\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=================\r
-=\r
-= RFL_CalcOriginStuff\r
-=\r
-= Calculate all the global variables for a new position\r
-= Long parms so position can be clipped to a maximum near 64k\r
-=\r
-=================\r
-*/\r
-\r
-void RFL_CalcOriginStuff (long x, long y)\r
-{\r
- originxglobal = x;\r
- originyglobal = y;\r
- originxtile = originxglobal>>G_T_SHIFT;\r
- originytile = originyglobal>>G_T_SHIFT;\r
- originxscreen = originxtile<<SX_T_SHIFT;\r
- originyscreen = originytile<<SY_T_SHIFT;\r
- originmap = mapbwidthtable[originytile] + originxtile*2;\r
-\r
-#if GRMODE == EGAGR\r
- panx = (originxglobal>>G_P_SHIFT) & 15;\r
- pansx = panx & 8;\r
- pany = pansy = (originyglobal>>G_P_SHIFT) & 15;\r
- panadjust = panx/8 + ylookup[pany];\r
-#endif\r
-\r
-#if GRMODE == CGAGR\r
- panx = (originxglobal>>G_P_SHIFT) & 15;\r
- pansx = panx & 12;\r
- pany = pansy = (originyglobal>>G_P_SHIFT) & 15;\r
- panadjust = pansx/4 + ylookup[pansy];\r
-#endif\r
-\r
-}\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= RFL_ClearScrollBlocks\r
-=\r
-=================\r
-*/\r
-\r
-void RFL_ClearScrollBlocks (void)\r
-{\r
- hscrollblocks = vscrollblocks = 0;\r
-}\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= RF_SetScrollBlock\r
-=\r
-= Sets a horizontal or vertical scroll block\r
-= a horizontal block is ----, meaning it blocks up/down movement\r
-=\r
-=================\r
-*/\r
-\r
-void RF_SetScrollBlock (int x, int y, boolean horizontal)\r
-{\r
- if (horizontal)\r
- {\r
- hscrolledge[hscrollblocks] = y;\r
- if (hscrollblocks++ == MAXSCROLLEDGES)\r
- Quit ("RF_SetScrollBlock: Too many horizontal scroll blocks");\r
- }\r
- else\r
- {\r
- vscrolledge[vscrollblocks] = x;\r
- if (vscrollblocks++ == MAXSCROLLEDGES)\r
- Quit ("RF_SetScrollBlock: Too many vertical scroll blocks");\r
- }\r
-}\r
-\r
-\r
-/*\r
-=================\r
-=\r
-= RFL_BoundScroll\r
-=\r
-= Bound a given x/y movement to scroll blocks\r
-=\r
-=================\r
-*/\r
-\r
-void RFL_BoundScroll (int x, int y)\r
-{\r
- int check,newxtile,newytile;\r
-\r
- originxglobal += x;\r
- originyglobal += y;\r
-\r
- newxtile= originxglobal >> G_T_SHIFT;\r
- newytile = originyglobal >> G_T_SHIFT;\r
-\r
- if (x>0)\r
- {\r
- newxtile+=SCREENTILESWIDE;\r
- for (check=0;check<vscrollblocks;check++)\r
- if (vscrolledge[check] == newxtile)\r
- {\r
- originxglobal = originxglobal&0xff00;\r
- break;\r
- }\r
- }\r
- else if (x<0)\r
- {\r
- for (check=0;check<vscrollblocks;check++)\r
- if (vscrolledge[check] == newxtile)\r
- {\r
- originxglobal = (originxglobal&0xff00)+0x100;\r
- break;\r
- }\r
- }\r
-\r
-\r
- if (y>0)\r
- {\r
- newytile+=SCREENTILESHIGH;\r
- for (check=0;check<hscrollblocks;check++)\r
- if (hscrolledge[check] == newytile)\r
- {\r
- originyglobal = originyglobal&0xff00;\r
- break;\r
- }\r
- }\r
- else if (y<0)\r
- {\r
- for (check=0;check<hscrollblocks;check++)\r
- if (hscrolledge[check] == newytile)\r
- {\r
- originyglobal = (originyglobal&0xff00)+0x100;\r
- break;\r
- }\r
- }\r
-\r
-\r
- RFL_CalcOriginStuff (originxglobal, originyglobal);\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_SetRefreshHook\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_SetRefreshHook (void (*func) (void) )\r
-{\r
- refreshvector = func;\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=================\r
-=\r
-= RFL_NewRow\r
-=\r
-= Bring a new row of tiles onto the port, spawning animating tiles\r
-=\r
-=================\r
-*/\r
-\r
-void RFL_NewRow (int dir)\r
-{\r
- unsigned count,updatespot,updatestep;\r
- int x,y,xstep,ystep;\r
-\r
- switch (dir)\r
- {\r
- case 0: // top row\r
- updatespot = 0;\r
- updatestep = 1;\r
- x = originxtile;\r
- y = originytile;\r
- xstep = 1;\r
- ystep = 0;\r
- count = PORTTILESWIDE;\r
- break;\r
-\r
- case 1: // right row\r
- updatespot = PORTTILESWIDE-1;\r
- updatestep = UPDATEWIDE;\r
- x = originxtile + PORTTILESWIDE-1;\r
- y = originytile;\r
- xstep = 0;\r
- ystep = 1;\r
- count = PORTTILESHIGH;\r
- break;\r
-\r
- case 2: // bottom row\r
- updatespot = UPDATEWIDE*(PORTTILESHIGH-1);\r
- updatestep = 1;\r
- x = originxtile;\r
- y = originytile + PORTTILESHIGH-1;\r
- xstep = 1;\r
- ystep = 0;\r
- count = PORTTILESWIDE;\r
- break;\r
-\r
- case 3: // left row\r
- updatespot = 0;\r
- updatestep = UPDATEWIDE;\r
- x = originxtile;\r
- y = originytile;\r
- xstep = 0;\r
- ystep = 1;\r
- count = PORTTILESHIGH;\r
- break;\r
- default:\r
- Quit ("RFL_NewRow: Bad dir!");\r
- }\r
-\r
- while (count--)\r
- {\r
- RFL_NewTile(updatespot);\r
- RFL_CheckForAnimTile (x,y);\r
- updatespot+=updatestep;\r
- x+=xstep;\r
- y+=ystep;\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_ForceRefresh\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_ForceRefresh (void)\r
-{\r
- RF_NewPosition (originxglobal,originyglobal);\r
- RF_Refresh ();\r
- RF_Refresh ();\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_MapToMap\r
-=\r
-= Copies a block of tiles (all three planes) from one point\r
-= in the map to another, accounting for animating tiles\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_MapToMap (unsigned srcx, unsigned srcy,\r
- unsigned destx, unsigned desty,\r
- unsigned width, unsigned height)\r
-{\r
- int x,y;\r
- unsigned source,destofs,xspot,yspot;\r
- unsigned linedelta,p0,p1,p2,updatespot;\r
- unsigned far *source0, far *source1, far *source2;\r
- unsigned far *dest0, far *dest1, far *dest2;\r
- boolean changed;\r
-\r
- RFL_RemoveAnimsInBlock (destx,desty,width,height);\r
-\r
- source = mapbwidthtable[srcy]/2 + srcx;\r
-\r
- source0 = mapsegs[0]+source;\r
- source1 = mapsegs[1]+source;\r
- source2 = mapsegs[2]+source;\r
-\r
- destofs = mapbwidthtable[desty]/2 + destx;\r
- destofs -= source;\r
-\r
- linedelta = mapwidth - width;\r
-\r
- for (y=0;y<height;y++,source0+=linedelta,source1+=linedelta,source2+=linedelta)\r
- for (x=0;x<width;x++,source0++,source1++,source2++)\r
- {\r
- p0 = *source0;\r
- p1 = *source1;\r
- p2 = *source2;\r
-\r
- dest0 = source0 + destofs;\r
- dest1 = source1 + destofs;\r
- dest2 = source2 + destofs;\r
-\r
-//\r
-// only make a new tile if it is different\r
-//\r
- if (p0 != *dest0 || p1 != *dest1 || p2 != *dest2)\r
- {\r
- *dest0 = p0;\r
- *dest1 = p1;\r
- *dest2 = p2;\r
- changed = true;\r
- }\r
- else\r
- changed = false;\r
-\r
-//\r
-// if tile is on the view port\r
-//\r
- xspot = destx+x-originxtile;\r
- yspot = desty+y-originytile;\r
- if (yspot < PORTTILESHIGH && xspot < PORTTILESWIDE)\r
- {\r
- if (changed)\r
- {\r
- updatespot = uwidthtable[yspot]+xspot;\r
- RFL_NewTile(updatespot);\r
- }\r
- RFL_CheckForAnimTile (destx+x,desty+y);\r
- }\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_MemToMap\r
-=\r
-= Copies a string of tiles from main memory to the map,\r
-= accounting for animating tiles\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_MemToMap (unsigned far *source, unsigned plane,\r
- unsigned destx, unsigned desty,\r
- unsigned width, unsigned height)\r
-{\r
- int x,y;\r
- unsigned xspot,yspot;\r
- unsigned linedelta,updatespot;\r
- unsigned far *dest,old,new;\r
- boolean changed;\r
-\r
- RFL_RemoveAnimsInBlock (destx,desty,width,height);\r
-\r
- dest = mapsegs[plane] + mapbwidthtable[desty]/2 + destx;\r
-\r
- linedelta = mapwidth - width;\r
-\r
- for (y=0;y<height;y++,dest+=linedelta)\r
- for (x=0;x<width;x++)\r
- {\r
- old = *dest;\r
- new = *source++;\r
- if (old != new)\r
- {\r
- *dest = new;\r
- changed = true;\r
- }\r
- else\r
- changed = false;\r
-\r
- dest++;\r
- xspot = destx+x-originxtile;\r
- yspot = desty+y-originytile;\r
- if (yspot < PORTTILESHIGH && xspot < PORTTILESWIDE)\r
- {\r
- if (changed)\r
- {\r
- updatespot = uwidthtable[yspot]+xspot;\r
- RFL_NewTile(updatespot);\r
- }\r
- RFL_CheckForAnimTile (destx+x,desty+y);\r
- }\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RFL_BoundNewOrigin\r
-=\r
-= Copies a string of tiles from main memory to the map,\r
-= accounting for animating tiles\r
-=\r
-=====================\r
-*/\r
-\r
-void RFL_BoundNewOrigin (unsigned orgx,unsigned orgy)\r
-{\r
- int check,edge;\r
-\r
-//\r
-// calculate new origin related globals\r
-//\r
- if (orgx<originxmin)\r
- orgx=originxmin;\r
- else if (orgx>originxmax)\r
- orgx=originxmax;\r
-\r
- if (orgy<originymin)\r
- orgy=originymin;\r
- else if (orgy>originymax)\r
- orgy=originymax;\r
-\r
- originxtile = orgx>>G_T_SHIFT;\r
- originytile = orgy>>G_T_SHIFT;\r
-\r
- for (check=0;check<vscrollblocks;check++)\r
- {\r
- edge = vscrolledge[check];\r
- if (edge>=originxtile && edge <=originxtile+10)\r
- {\r
- orgx = (edge+1)*TILEGLOBAL;\r
- break;\r
- }\r
- if (edge>=originxtile+11 && edge <=originxtile+20)\r
- {\r
- orgx = (edge-20)*TILEGLOBAL;\r
- break;\r
- }\r
- }\r
-\r
- for (check=0;check<hscrollblocks;check++)\r
- {\r
- edge = hscrolledge[check];\r
- if (edge>=originytile && edge <=originytile+6)\r
- {\r
- orgy = (edge+1)*TILEGLOBAL;\r
- break;\r
- }\r
- if (edge>=originytile+7 && edge <=originytile+13)\r
- {\r
- orgy = (edge-13)*TILEGLOBAL;\r
- break;\r
- }\r
- }\r
-\r
-\r
- RFL_CalcOriginStuff (orgx,orgy);\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_ClearBlock\r
-=\r
-= Posts erase blocks to clear a certain area of the screen to the master\r
-= screen, to erase text or something draw directly to the screen\r
-=\r
-= Parameters in pixels, but erasure is byte bounded\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_ClearBlock (int x, int y, int width, int height)\r
-{\r
- eraseblocktype block;\r
-\r
-#if GRMODE == EGAGR\r
- block.screenx = x/8+originxscreen;\r
- block.screeny = y+originyscreen;\r
- block.width = (width+(x&7)+7)/8;\r
- block.height = height;\r
- memcpy (eraselistptr[0]++,&block,sizeof(block));\r
- memcpy (eraselistptr[1]++,&block,sizeof(block));\r
-#endif\r
-\r
-#if GRMODE == CGAGR\r
- block.screenx = x/4+originxscreen;\r
- block.screeny = y+originyscreen;\r
- block.width = (width+(x&3)+3)/4;\r
- block.height = height;\r
- memcpy (eraselistptr[0]++,&block,sizeof(block));\r
-#endif\r
-\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_RedrawBlock\r
-=\r
-= Causes a number of tiles to be redrawn to the master screen and updated\r
-=\r
-= Parameters in pixels, but erasure is tile bounded\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_RedrawBlock (int x, int y, int width, int height)\r
-{\r
- int xx,yy,xl,xh,yl,yh;\r
-\r
- xl=(x+panx)/16;\r
- xh=(x+panx+width+15)/16;\r
- yl=(y+pany)/16;\r
- yh=(y+pany+height+15)/16;\r
- for (yy=yl;yy<=yh;yy++)\r
- for (xx=xl;xx<=xh;xx++)\r
- RFL_NewTile (yy*UPDATEWIDE+xx);\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_CalcTics\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_CalcTics (void)\r
-{\r
- long newtime,oldtimecount;\r
-\r
-//\r
-// calculate tics since last refresh for adaptive timing\r
-//\r
- if (lasttimecount > TimeCount)\r
- TimeCount = lasttimecount; // if the game was paused a LONG time\r
-\r
- if (DemoMode) // demo recording and playback needs\r
- { // to be constant\r
-//\r
-// take DEMOTICS or more tics, and modify Timecount to reflect time taken\r
-//\r
- oldtimecount = lasttimecount;\r
- while (TimeCount<oldtimecount+DEMOTICS*2)\r
- ;\r
- lasttimecount = oldtimecount + DEMOTICS;\r
- TimeCount = lasttimecount + DEMOTICS;\r
- tics = DEMOTICS;\r
- }\r
- else\r
- {\r
-//\r
-// non demo, so report actual time\r
-//\r
- do\r
- {\r
- newtime = TimeCount;\r
- tics = newtime-lasttimecount;\r
- } while (tics<MINTICS);\r
- lasttimecount = newtime;\r
-\r
-#ifdef PROFILE\r
- strcpy (scratch,"\tTics:");\r
- itoa (tics,str,10);\r
- strcat (scratch,str);\r
- strcat (scratch,"\n");\r
- write (profilehandle,scratch,strlen(scratch));\r
-#endif\r
-\r
- if (tics>MAXTICS)\r
- {\r
- TimeCount -= (tics-MAXTICS);\r
- tics = MAXTICS;\r
- }\r
- }\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- EGA specific routines\r
-\r
-=============================================================================\r
-*/\r
-\r
-#if GRMODE == EGAGR\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_FindFreeBuffer\r
-=\r
-= Finds the start of unused, non visable buffer space\r
-=\r
-=====================\r
-*/\r
-\r
-unsigned RF_FindFreeBuffer (void)\r
-{\r
- unsigned spot,i,j;\r
- boolean ok;\r
-\r
- for (i=0;i<3;i++)\r
- {\r
- spot = screenstart[i]+SCREENSPACE;\r
- ok = true;\r
- for (j=0;j<3;j++)\r
- if (spot == screenstart[j])\r
- {\r
- ok = false;\r
- break;\r
- }\r
- if (ok)\r
- return spot;\r
- }\r
-\r
- return 0; // never get here...\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_NewPosition EGA\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_NewPosition (unsigned x, unsigned y)\r
-{\r
- int mx,my;\r
- byte *page0ptr,*page1ptr;\r
- unsigned updatenum;\r
-\r
- RFL_BoundNewOrigin (x,y);\r
-//\r
-// clear out all animating tiles\r
-//\r
- RFL_InitAnimList ();\r
-\r
-//\r
-// set up the new update arrays at base position\r
-//\r
- updatestart[0] = baseupdatestart[0];\r
- updatestart[1] = baseupdatestart[1];\r
- updateptr = updatestart[otherpage];\r
-\r
- page0ptr = updatestart[0]+PORTTILESWIDE; // used to stick "0"s after rows\r
- page1ptr = updatestart[1]+PORTTILESWIDE;\r
-\r
- updatenum = 0; // start at first visable tile\r
-\r
- for (my=0;my<PORTTILESHIGH;my++)\r
- {\r
- for (mx=0;mx<PORTTILESWIDE;mx++)\r
- {\r
- RFL_NewTile(updatenum); // puts "1"s in both pages\r
- RFL_CheckForAnimTile(mx+originxtile,my+originytile);\r
- updatenum++;\r
- }\r
- updatenum++;\r
- *page0ptr = *page1ptr = 0; // set a 0 at end of a line of tiles\r
- page0ptr+=(PORTTILESWIDE+1);\r
- page1ptr+=(PORTTILESWIDE+1);\r
- }\r
- *(word *)(page0ptr-PORTTILESWIDE)\r
- = *(word *)(page1ptr-PORTTILESWIDE) = UPDATETERMINATE;\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_Scroll EGA\r
-=\r
-= Move the origin x/y global coordinates, readjust the screen panning, and\r
-= scroll if needed. If the scroll distance is greater than one tile, the\r
-= entire screen will be redrawn (this could be generalized, but scrolling\r
-= more than one tile per refresh is a bad idea!).\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_Scroll (int x, int y)\r
-{\r
- long neworgx,neworgy;\r
- int i,deltax,deltay,absdx,absdy;\r
- int oldxt,oldyt,move,yy;\r
- unsigned updatespot;\r
- byte *update0,*update1;\r
- unsigned oldpanx,oldpanadjust,oldscreen,newscreen,screencopy;\r
- int screenmove;\r
-\r
- oldxt = originxtile;\r
- oldyt = originytile;\r
- oldpanadjust = panadjust;\r
- oldpanx = panx;\r
-\r
- RFL_BoundScroll (x,y);\r
-\r
- deltax = originxtile - oldxt;\r
- absdx = abs(deltax);\r
- deltay = originytile - oldyt;\r
- absdy = abs(deltay);\r
-\r
- if (absdx>1 || absdy>1)\r
- {\r
- //\r
- // scrolled more than one tile, so start from scratch\r
- //\r
- RF_NewPosition(originxglobal,originyglobal);\r
- return;\r
- }\r
-\r
- if (!absdx && !absdy)\r
- return; // the screen has not scrolled an entire tile\r
-\r
-\r
-//\r
-// adjust screens and handle SVGA crippled compatability mode\r
-//\r
- screenmove = deltay*16*SCREENWIDTH + deltax*TILEWIDTH;\r
- for (i=0;i<3;i++)\r
- {\r
- screenstart[i]+= screenmove;\r
- if (compatability && screenstart[i] > (0x10000l-SCREENSPACE) )\r
- {\r
- //\r
- // move the screen to the opposite end of the buffer\r
- //\r
- screencopy = screenmove>0 ? FREEEGAMEM : -FREEEGAMEM;\r
- oldscreen = screenstart[i] - screenmove;\r
- newscreen = oldscreen + screencopy;\r
- screenstart[i] = newscreen + screenmove;\r
- VW_ScreenToScreen (oldscreen,newscreen,\r
- PORTTILESWIDE*2,PORTTILESHIGH*16);\r
-\r
- if (i==screenpage)\r
- VW_SetScreen(newscreen+oldpanadjust,oldpanx & xpanmask);\r
- }\r
- }\r
- bufferofs = screenstart[otherpage];\r
- displayofs = screenstart[screenpage];\r
- masterofs = screenstart[2];\r
-\r
-\r
-//\r
-// float the update regions\r
-//\r
- move = deltax;\r
- if (deltay==1)\r
- move += UPDATEWIDE;\r
- else if (deltay==-1)\r
- move -= UPDATEWIDE;\r
-\r
- updatestart[0]+=move;\r
- updatestart[1]+=move;\r
-\r
-//\r
-// draw the new tiles just scrolled on to the master screen, and\r
-// mark them as needing to be copied to each screen next refreshes\r
-// Make sure a zero is at the end of each row in update\r
-//\r
-\r
- if (deltax)\r
- {\r
- if (deltax==1)\r
- {\r
- RFL_NewRow (1); // new right row\r
- RFL_RemoveAnimsOnX (originxtile-1);\r
- }\r
- else\r
- {\r
- RFL_NewRow (3); // new left row\r
- RFL_RemoveAnimsOnX (originxtile+PORTTILESWIDE);\r
- }\r
-\r
- update0 = updatestart[0]+PORTTILESWIDE;\r
- update1 = updatestart[1]+PORTTILESWIDE;\r
- for (yy=0;yy<PORTTILESHIGH;yy++)\r
- {\r
- *update0 = *update1 = 0; // drop a 0 at end of each row\r
- update0+=UPDATEWIDE;\r
- update1+=UPDATEWIDE;\r
- }\r
- }\r
-\r
-//----------------\r
-\r
- if (deltay)\r
- {\r
- if (deltay==1)\r
- {\r
- updatespot = UPDATEWIDE*(PORTTILESHIGH-1);\r
- RFL_NewRow (2); // new bottom row\r
- RFL_RemoveAnimsOnY (originytile-1);\r
- }\r
- else\r
- {\r
- updatespot = 0;\r
- RFL_NewRow (0); // new top row\r
- RFL_RemoveAnimsOnY (originytile+PORTTILESHIGH);\r
- }\r
-\r
- *(updatestart[0]+updatespot+PORTTILESWIDE) =\r
- *(updatestart[1]+updatespot+PORTTILESWIDE) = 0;\r
- }\r
-\r
-//----------------\r
-\r
- //\r
- // place a new terminator\r
- //\r
- update0 = updatestart[0]+UPDATEWIDE*PORTTILESHIGH-1;\r
- update1 = updatestart[1]+UPDATEWIDE*PORTTILESHIGH-1;\r
- *update0++ = *update1++ = 0;\r
- *(unsigned *)update0 = *(unsigned *)update1 = UPDATETERMINATE;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_PlaceSprite EGA\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_PlaceSprite (void **user,unsigned globalx,unsigned globaly,\r
- unsigned spritenumber, drawtype draw, int priority)\r
-{\r
- spritelisttype register *sprite,*next;\r
- spritetabletype far *spr;\r
- spritetype _seg *block;\r
- unsigned shift,pixx;\r
- char str[80],str2[10];\r
-\r
- if (!spritenumber || spritenumber == (unsigned)-1)\r
- {\r
- RF_RemoveSprite (user);\r
- return;\r
- }\r
-\r
- sprite = (spritelisttype *)*user;\r
-\r
- if (sprite)\r
- {\r
- // sprite allready exists in the list, so we can use it's block\r
-\r
- //\r
- // post an erase block to both pages by copying screenx,screeny,width,height\r
- // both pages may not need to be erased if the sprite just changed last frame\r
- //\r
- if (sprite->updatecount<2)\r
- {\r
- if (!sprite->updatecount)\r
- memcpy (eraselistptr[otherpage]++,sprite,sizeof(eraseblocktype));\r
- memcpy (eraselistptr[screenpage]++,sprite,sizeof(eraseblocktype));\r
- }\r
-\r
- if (priority != sprite->priority)\r
- {\r
- // sprite mvoed to another priority, so unlink the old one and\r
- // relink it in the new priority\r
-\r
- next = sprite->nextsprite; // cut old links\r
- if (next)\r
- next->prevptr = sprite->prevptr;\r
- *sprite->prevptr = next;\r
- goto linknewspot;\r
- }\r
- }\r
- else\r
- {\r
- // this is a brand new sprite, so allocate a block from the array\r
-\r
- if (!spritefreeptr)\r
- Quit ("RF_PlaceSprite: No free spots in spritearray!");\r
-\r
- sprite = spritefreeptr;\r
- spritefreeptr = spritefreeptr->nextsprite;\r
-\r
-linknewspot:\r
- next = prioritystart[priority]; // stick it in new spot\r
- if (next)\r
- next->prevptr = &sprite->nextsprite;\r
- sprite->nextsprite = next;\r
- prioritystart[priority] = sprite;\r
- sprite->prevptr = &prioritystart[priority];\r
- }\r
-\r
-//\r
-// write the new info to the sprite\r
-//\r
- spr = &spritetable[spritenumber-STARTSPRITES];\r
- block = (spritetype _seg *)grsegs[spritenumber];\r
-\r
- if (!block)\r
- {\r
- strcpy (str,"RF_PlaceSprite: Placed an uncached sprite:");\r
- itoa (spritenumber,str2,10);\r
- strcat (str,str2);\r
- Quit (str);\r
- }\r
-\r
- globaly+=spr->orgy;\r
- globalx+=spr->orgx;\r
-\r
- pixx = globalx >> G_SY_SHIFT;\r
- shift = (pixx&7)/2;\r
-\r
- sprite->screenx = pixx >> (G_EGASX_SHIFT-G_SY_SHIFT);\r
- sprite->screeny = globaly >> G_SY_SHIFT;\r
- sprite->width = block->width[shift];\r
- sprite->height = spr->height;\r
- sprite->grseg = spritenumber;\r
- sprite->sourceofs = block->sourceoffset[shift];\r
- sprite->planesize = block->planesize[shift];\r
- sprite->draw = draw;\r
- sprite->priority = priority;\r
- sprite->tilex = sprite->screenx >> SX_T_SHIFT;\r
- sprite->tiley = sprite->screeny >> SY_T_SHIFT;\r
- sprite->tilewide = ( (sprite->screenx + sprite->width -1) >> SX_T_SHIFT )\r
- - sprite->tilex + 1;\r
- sprite->tilehigh = ( (sprite->screeny + sprite->height -1) >> SY_T_SHIFT )\r
- - sprite->tiley + 1;\r
-\r
- sprite->updatecount = 2; // draw on next two refreshes\r
-\r
-// save the sprite pointer off in the user's pointer so it can be moved\r
-// again later\r
-\r
- *user = sprite;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_RemoveSprite EGA\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_RemoveSprite (void **user)\r
-{\r
- spritelisttype *sprite,*next;\r
-\r
- sprite = (spritelisttype *)*user;\r
- if (!sprite)\r
- return;\r
-\r
-//\r
-// post an erase block to both pages by copying screenx,screeny,width,height\r
-// both pages may not need to be erased if the sprite just changed last frame\r
-//\r
- if (sprite->updatecount<2)\r
- {\r
- if (!sprite->updatecount)\r
- memcpy (eraselistptr[otherpage]++,sprite,sizeof(eraseblocktype));\r
- memcpy (eraselistptr[screenpage]++,sprite,sizeof(eraseblocktype));\r
- }\r
-\r
-//\r
-// unlink the sprite node\r
-//\r
- next = sprite->nextsprite;\r
- if (next) // if (!next), sprite is last in chain\r
- next->prevptr = sprite->prevptr;\r
- *sprite->prevptr = next;\r
-\r
-//\r
-// add it back to the free list\r
-//\r
- sprite->nextsprite = spritefreeptr;\r
- spritefreeptr = sprite;\r
-\r
-//\r
-// null the users pointer, so next time that actor gets placed, it will\r
-// allocate a new block\r
-//\r
-\r
- *user = 0;\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= RFL_EraseBlocks EGA\r
-=\r
-= Write mode 1 should be set\r
-=\r
-====================\r
-*/\r
-\r
-void RFL_EraseBlocks (void)\r
-{\r
- eraseblocktype *block,*done;\r
- int screenxh,screenyh;\r
- unsigned pos,xtl,ytl,xth,yth,x,y;\r
- byte *updatespot;\r
- unsigned updatedelta;\r
- unsigned erasecount;\r
-\r
-#ifdef PROFILE\r
- erasecount = 0;\r
-#endif\r
-\r
- block = otherpage ? &eraselist[1][0] : &eraselist[0][0];\r
-\r
- done = eraselistptr[otherpage];\r
-\r
- while (block != done)\r
- {\r
-\r
- //\r
- // clip the block to the current screen view\r
- //\r
- block->screenx -= originxscreen;\r
- block->screeny -= originyscreen;\r
-\r
- if (block->screenx < 0)\r
- {\r
- block->width += block->screenx;\r
- if (block->width<1)\r
- goto next;\r
- block->screenx = 0;\r
- }\r
-\r
- if (block->screeny < 0)\r
- {\r
- block->height += block->screeny;\r
- if (block->height<1)\r
- goto next;\r
- block->screeny = 0;\r
- }\r
-\r
- screenxh = block->screenx + block->width;\r
- screenyh = block->screeny + block->height;\r
-\r
- if (screenxh > EGAPORTSCREENWIDE)\r
- {\r
- block->width = EGAPORTSCREENWIDE-block->screenx;\r
- screenxh = block->screenx + block->width;\r
- }\r
-\r
- if (screenyh > PORTSCREENHIGH)\r
- {\r
- block->height = PORTSCREENHIGH-block->screeny;\r
- screenyh = block->screeny + block->height;\r
- }\r
-\r
- if (block->width<1 || block->height<1)\r
- goto next;\r
-\r
- //\r
- // erase the block by copying from the master screen\r
- //\r
- pos = ylookup[block->screeny]+block->screenx;\r
- VW_ScreenToScreen (masterofs+pos,bufferofs+pos,\r
- block->width,block->height);\r
-\r
- //\r
- // put 2s in update where the block was, to force sprites to update\r
- //\r
- xtl = block->screenx >> SX_T_SHIFT;\r
- xth = (block->screenx+block->width-1) >> SX_T_SHIFT;\r
- ytl = block->screeny >> SY_T_SHIFT;\r
- yth = (block->screeny+block->height-1) >> SY_T_SHIFT;\r
-\r
- updatespot = updateptr + uwidthtable[ytl] + xtl;\r
- updatedelta = UPDATEWIDE - (xth-xtl+1);\r
-\r
- for (y=ytl;y<=yth;y++)\r
- {\r
- for (x=xtl;x<=xth;x++)\r
- *updatespot++ = 2;\r
- updatespot += updatedelta; // down to next line\r
- }\r
-#ifdef PROFILE\r
- erasecount++;\r
-#endif\r
-\r
-next:\r
- block++;\r
- }\r
- eraselistptr[otherpage] = otherpage ? &eraselist[1][0] : &eraselist[0][0];\r
-#ifdef PROFILE\r
- strcpy (scratch,"\tErase:");\r
- itoa (erasecount,str,10);\r
- strcat (scratch,str);\r
- write (profilehandle,scratch,strlen(scratch));\r
-#endif\r
-\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= RFL_UpdateSprites EGA\r
-=\r
-= NOTE: Implement vertical clipping!\r
-=\r
-====================\r
-*/\r
-\r
-void RFL_UpdateSprites (void)\r
-{\r
- spritelisttype *sprite;\r
- int portx,porty,x,y,xtl,xth,ytl,yth;\r
- int priority;\r
- unsigned dest;\r
- byte *updatespot,*baseupdatespot;\r
- unsigned updatedelta;\r
- unsigned updatecount;\r
- unsigned height,sourceofs;\r
-\r
-#ifdef PROFILE\r
- updatecount = 0;\r
-#endif\r
-\r
- for (priority=0;priority<PRIORITIES;priority++)\r
- {\r
- if (priority==MASKEDTILEPRIORITY)\r
- RFL_MaskForegroundTiles ();\r
-\r
- for (sprite = prioritystart[priority]; sprite ;\r
- sprite = (spritelisttype *)sprite->nextsprite)\r
- {\r
- //\r
- // see if the sprite has any visable area in the port\r
- //\r
-\r
- portx = sprite->screenx - originxscreen;\r
- porty = sprite->screeny - originyscreen;\r
- xtl = portx >> SX_T_SHIFT;\r
- xth = (portx + sprite->width-1) >> SX_T_SHIFT;\r
- ytl = porty >> SY_T_SHIFT;\r
- yth = (porty + sprite->height-1) >> SY_T_SHIFT;\r
-\r
- if (xtl<0)\r
- xtl = 0;\r
- if (xth>=PORTTILESWIDE)\r
- xth = PORTTILESWIDE-1;\r
- if (ytl<0)\r
- ytl = 0;\r
- if (yth>=PORTTILESHIGH)\r
- yth = PORTTILESHIGH-1;\r
-\r
- if (xtl>xth || ytl>yth)\r
- continue;\r
-\r
- //\r
- // see if it's visable area covers any non 0 update tiles\r
- //\r
- updatespot = baseupdatespot = updateptr + uwidthtable[ytl] + xtl;\r
- updatedelta = UPDATEWIDE - (xth-xtl+1);\r
-\r
- if (sprite->updatecount)\r
- {\r
- sprite->updatecount--; // the sprite was just placed,\r
- goto redraw; // so draw it for sure\r
- }\r
-\r
- for (y=ytl;y<=yth;y++)\r
- {\r
- for (x=xtl;x<=xth;x++)\r
- if (*updatespot++)\r
- goto redraw;\r
- updatespot += updatedelta; // down to next line\r
- }\r
- continue; // no need to update\r
-\r
-redraw:\r
- //\r
- // set the tiles it covers to 3, because those tiles are being\r
- // updated\r
- //\r
- updatespot = baseupdatespot;\r
- for (y=ytl;y<=yth;y++)\r
- {\r
- for (x=xtl;x<=xth;x++)\r
- *updatespot++ = 3;\r
- updatespot += updatedelta; // down to next line\r
- }\r
- //\r
- // draw it!\r
- //\r
- height = sprite->height;\r
- sourceofs = sprite->sourceofs;\r
- if (porty<0)\r
- {\r
- height += porty; // clip top off\r
- sourceofs -= porty*sprite->width;\r
- porty = 0;\r
- }\r
- else if (porty+height>PORTSCREENHIGH)\r
- {\r
- height = PORTSCREENHIGH - porty; // clip bottom off\r
- }\r
-\r
- dest = bufferofs + ylookup[porty] + portx;\r
-\r
- switch (sprite->draw)\r
- {\r
- case spritedraw:\r
- VW_MaskBlock(grsegs[sprite->grseg], sourceofs,\r
- dest,sprite->width,height,sprite->planesize);\r
- break;\r
-\r
- case maskdraw:\r
- break;\r
-\r
- }\r
-#ifdef PROFILE\r
- updatecount++;\r
-#endif\r
-\r
-\r
- }\r
- }\r
-#ifdef PROFILE\r
- strcpy (scratch,"\tSprites:");\r
- itoa (updatecount,str,10);\r
- strcat (scratch,str);\r
- write (profilehandle,scratch,strlen(scratch));\r
-#endif\r
-\r
-}\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_Refresh EGA\r
-=\r
-= All routines will draw at the port at bufferofs, possibly copying from\r
-= the port at masterofs. The EGA version then page flips, while the\r
-= CGA version updates the screen from the buffer port.\r
-=\r
-= Screenpage is the currently displayed page, not the one being drawn\r
-= Otherpage is the page to be worked with now\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_Refresh (void)\r
-{\r
- byte *newupdate;\r
-\r
- updateptr = updatestart[otherpage];\r
-\r
- RFL_AnimateTiles (); // DEBUG\r
-\r
-//\r
-// update newly scrolled on tiles and animated tiles from the master screen\r
-//\r
- EGAWRITEMODE(1);\r
- EGAMAPMASK(15);\r
- RFL_UpdateTiles ();\r
- RFL_EraseBlocks ();\r
-\r
-//\r
-// Update is all 0 except where sprites have changed or new area has\r
-// been scrolled on. Go through all sprites and update the ones that cover\r
-// a non 0 update tile\r
-//\r
- EGAWRITEMODE(0);\r
- RFL_UpdateSprites ();\r
-\r
-//\r
-// if the main program has a refresh hook set, call their function before\r
-// displaying the new page\r
-//\r
- if (refreshvector)\r
- refreshvector();\r
-\r
-//\r
-// display the changed screen\r
-//\r
- VW_SetScreen(bufferofs+panadjust,panx & xpanmask);\r
-\r
-//\r
-// prepare for next refresh\r
-//\r
-// Set the update array to the middle position and clear it out to all "0"s\r
-// with an UPDATETERMINATE at the end\r
-//\r
- updatestart[otherpage] = newupdate = baseupdatestart[otherpage];\r
-asm mov ax,ds\r
-asm mov es,ax\r
-asm xor ax,ax\r
-asm mov cx,(UPDATESCREENSIZE-2)/2\r
-asm mov di,[newupdate]\r
-asm rep stosw\r
-asm mov [WORD PTR es:di],UPDATETERMINATE\r
-\r
- screenpage ^= 1;\r
- otherpage ^= 1;\r
- bufferofs = screenstart[otherpage];\r
- displayofs = screenstart[screenpage];\r
-\r
-//\r
-// calculate tics since last refresh for adaptive timing\r
-//\r
- RF_CalcTics ();\r
-}\r
-\r
-#endif // GRMODE == EGAGR\r
-\r
-/*\r
-=============================================================================\r
-\r
- CGA specific routines\r
-\r
-=============================================================================\r
-*/\r
-\r
-#if GRMODE == CGAGR\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_NewPosition CGA\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_NewPosition (unsigned x, unsigned y)\r
-{\r
- int mx,my;\r
- byte *spotptr;\r
- unsigned updatenum;\r
-\r
- RFL_BoundNewOrigin (x,y);\r
-\r
-//\r
-// clear out all animating tiles\r
-//\r
- RFL_InitAnimList ();\r
-\r
-//\r
-// set up the new update arrays at base position\r
-//\r
- updateptr = baseupdateptr;\r
-\r
- spotptr = updateptr + PORTTILESWIDE; // used to stick "0"s after rows\r
-\r
- updatenum = 0; // start at first visable tile\r
-\r
- for (my=0;my<PORTTILESHIGH;my++)\r
- {\r
- for (mx=0;mx<PORTTILESWIDE;mx++)\r
- {\r
- RFL_NewTile(updatenum); // puts "1"s in both pages\r
- RFL_CheckForAnimTile(mx+originxtile,my+originytile);\r
- updatenum++;\r
- }\r
- updatenum++;\r
- *spotptr = 0; // set a 0 at end of a line of tiles\r
- spotptr +=(PORTTILESWIDE+1);\r
- }\r
- *(word *)(spotptr-PORTTILESWIDE) = UPDATETERMINATE;\r
-}\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_Scroll CGA\r
-=\r
-= Move the origin x/y global coordinates, readjust the screen panning, and\r
-= scroll if needed. If the scroll distance is greater than one tile, the\r
-= entire screen will be redrawn (this could be generalized, but scrolling\r
-= more than one tile per refresh is a bad idea!).\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_Scroll (int x, int y)\r
-{\r
- long neworgx,neworgy;\r
- int i,deltax,deltay,absdx,absdy;\r
- int oldxt,oldyt,move,yy;\r
- unsigned updatespot;\r
- byte *spotptr;\r
- unsigned oldoriginmap,oldscreen,newscreen,screencopy;\r
- int screenmove;\r
-\r
- oldxt = originxtile;\r
- oldyt = originytile;\r
-\r
- RFL_BoundScroll (x,y);\r
-\r
- deltax = originxtile - oldxt;\r
- absdx = abs(deltax);\r
- deltay = originytile - oldyt;\r
- absdy = abs(deltay);\r
-\r
- if (absdx>1 || absdy>1)\r
- {\r
- //\r
- // scrolled more than one tile, so start from scratch\r
- //\r
- RF_NewPosition(originxglobal,originyglobal);\r
- return;\r
- }\r
-\r
- if (!absdx && !absdy)\r
- return; // the screen has not scrolled an entire tile\r
-\r
-\r
-//\r
-// float screens\r
-//\r
- screenmove = deltay*16*SCREENWIDTH + deltax*TILEWIDTH;\r
- bufferofs += screenmove;\r
- masterofs += screenmove;\r
-\r
-\r
-//\r
-// float the update regions\r
-//\r
- move = deltax;\r
- if (deltay==1)\r
- move += UPDATEWIDE;\r
- else if (deltay==-1)\r
- move -= UPDATEWIDE;\r
-\r
- updateptr+=move;\r
-\r
-//\r
-// draw the new tiles just scrolled on to the master screen, and\r
-// mark them as needing to be copied to each screen next refreshes\r
-// Make sure a zero is at the end of each row in update\r
-//\r
-\r
- if (deltax)\r
- {\r
- if (deltax==1)\r
- {\r
- RFL_NewRow (1); // new right row\r
- RFL_RemoveAnimsOnX (originxtile-1);\r
- }\r
- else\r
- {\r
- RFL_NewRow (3); // new left row\r
- RFL_RemoveAnimsOnX (originxtile+PORTTILESWIDE);\r
- }\r
-\r
- spotptr = updateptr+PORTTILESWIDE;\r
- for (yy=0;yy<PORTTILESHIGH;yy++)\r
- {\r
- *spotptr = 0; // drop a 0 at end of each row\r
- spotptr+=UPDATEWIDE;\r
- }\r
- }\r
-\r
-//----------------\r
-\r
- if (deltay)\r
- {\r
- if (deltay==1)\r
- {\r
- RFL_NewRow (2); // new bottom row\r
- *(updateptr+UPDATEWIDE*(PORTTILESHIGH-1)+PORTTILESWIDE) = 0;\r
- RFL_RemoveAnimsOnY (originytile-1);\r
- }\r
- else\r
- {\r
- RFL_NewRow (0); // new top row\r
- *(updateptr+PORTTILESWIDE) = 0;\r
- RFL_RemoveAnimsOnY (originytile+PORTTILESHIGH);\r
- }\r
- }\r
-\r
-//----------------\r
-\r
- //\r
- // place a new terminator\r
- //\r
- spotptr = updateptr+UPDATEWIDE*PORTTILESHIGH-1;\r
- *spotptr++ = 0;\r
- *(unsigned *)spotptr = UPDATETERMINATE;\r
-}\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_PlaceSprite CGA\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_PlaceSprite (void **user,unsigned globalx,unsigned globaly,\r
- unsigned spritenumber, drawtype draw, int priority)\r
-{\r
- spritelisttype register *sprite,*next;\r
- spritetabletype far *spr;\r
- spritetype _seg *block;\r
- unsigned shift,pixx;\r
- char str[80],str2[10];\r
-\r
- if (!spritenumber || spritenumber == (unsigned)-1)\r
- {\r
- RF_RemoveSprite (user);\r
- return;\r
- }\r
-\r
- sprite = (spritelisttype *)*user;\r
-\r
- if (sprite)\r
- {\r
- // sprite allready exists in the list, so we can use it's block\r
-\r
- //\r
- // post an erase block to erase the old position by copying\r
- // screenx,screeny,width,height\r
- //\r
- if (!sprite->updatecount) // may not have been drawn at all yet\r
- memcpy (eraselistptr[0]++,sprite,sizeof(eraseblocktype));\r
-\r
- if (priority != sprite->priority)\r
- {\r
- // sprite moved to another priority, so unlink the old one and\r
- // relink it in the new priority\r
-\r
- next = sprite->nextsprite; // cut old links\r
- if (next)\r
- next->prevptr = sprite->prevptr;\r
- *sprite->prevptr = next;\r
- goto linknewspot;\r
- }\r
- }\r
- else\r
- {\r
- // this is a brand new sprite, so allocate a block from the array\r
-\r
- if (!spritefreeptr)\r
- Quit ("RF_PlaceSprite: No free spots in spritearray!");\r
-\r
- sprite = spritefreeptr;\r
- spritefreeptr = spritefreeptr->nextsprite;\r
-\r
-linknewspot:\r
- next = prioritystart[priority]; // stick it in new spot\r
- if (next)\r
- next->prevptr = &sprite->nextsprite;\r
- sprite->nextsprite = next;\r
- prioritystart[priority] = sprite;\r
- sprite->prevptr = &prioritystart[priority];\r
- }\r
-\r
-//\r
-// write the new info to the sprite\r
-//\r
- spr = &spritetable[spritenumber-STARTSPRITES];\r
- block = (spritetype _seg *)grsegs[spritenumber];\r
-\r
- if (!block)\r
- {\r
- strcpy (str,"RF_PlaceSprite: Placed an uncached sprite!");\r
- itoa (spritenumber,str2,10);\r
- strcat (str,str2);\r
- Quit (str);\r
- }\r
-\r
-\r
- globaly+=spr->orgy;\r
- globalx+=spr->orgx;\r
-\r
- sprite->screenx = globalx >> G_CGASX_SHIFT;\r
- sprite->screeny = globaly >> G_SY_SHIFT;\r
- sprite->width = block->width[0];\r
- sprite->height = spr->height;\r
- sprite->grseg = spritenumber;\r
- sprite->sourceofs = block->sourceoffset[0];\r
- sprite->planesize = block->planesize[0];\r
- sprite->draw = draw;\r
- sprite->priority = priority;\r
- sprite->tilex = sprite->screenx >> SX_T_SHIFT;\r
- sprite->tiley = sprite->screeny >> SY_T_SHIFT;\r
- sprite->tilewide = ( (sprite->screenx + sprite->width -1) >> SX_T_SHIFT )\r
- - sprite->tilex + 1;\r
- sprite->tilehigh = ( (sprite->screeny + sprite->height -1) >> SY_T_SHIFT )\r
- - sprite->tiley + 1;\r
-\r
- sprite->updatecount = 1; // draw on next refresh\r
-\r
-// save the sprite pointer off in the user's pointer so it can be moved\r
-// again later\r
-\r
- *user = sprite;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_RemoveSprite CGA\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_RemoveSprite (void **user)\r
-{\r
- spritelisttype *sprite,*next;\r
-\r
- sprite = (spritelisttype *)*user;\r
- if (!sprite)\r
- return;\r
-\r
-//\r
-// post an erase block to erase the old position by copying\r
-// screenx,screeny,width,height\r
-//\r
- if (!sprite->updatecount)\r
- {\r
- memcpy (eraselistptr[0]++,sprite,sizeof(eraseblocktype));\r
- }\r
-\r
-//\r
-// unlink the sprite node\r
-//\r
- next = sprite->nextsprite;\r
- if (next) // if (!next), sprite is last in chain\r
- next->prevptr = sprite->prevptr;\r
- *sprite->prevptr = next;\r
-\r
-//\r
-// add it back to the free list\r
-//\r
- sprite->nextsprite = spritefreeptr;\r
- spritefreeptr = sprite;\r
-\r
-//\r
-// null the users pointer, so next time that actor gets placed, it will\r
-// allocate a new block\r
-//\r
-\r
- *user = 0;\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= RFL_EraseBlocks CGA\r
-=\r
-= Write mode 1 should be set\r
-=\r
-====================\r
-*/\r
-\r
-void RFL_EraseBlocks (void)\r
-{\r
- eraseblocktype *block,*done;\r
- int screenxh,screenyh;\r
- unsigned pos,xtl,ytl,xth,yth,x,y;\r
- byte *updatespot;\r
- unsigned updatedelta;\r
-\r
- block = &eraselist[0][0];\r
-\r
- done = eraselistptr[0];\r
-\r
- while (block != done)\r
- {\r
-\r
- //\r
- // clip the block to the current screen view\r
- //\r
- block->screenx -= originxscreen;\r
- block->screeny -= originyscreen;\r
-\r
- if (block->screenx < 0)\r
- {\r
- block->width += block->screenx;\r
- if (block->width<1)\r
- goto next;\r
- block->screenx = 0;\r
- }\r
-\r
- if (block->screeny < 0)\r
- {\r
- block->height += block->screeny;\r
- if (block->height<1)\r
- goto next;\r
- block->screeny = 0;\r
- }\r
-\r
- screenxh = block->screenx + block->width;\r
- screenyh = block->screeny + block->height;\r
-\r
- if (screenxh > CGAPORTSCREENWIDE)\r
- {\r
- block->width = CGAPORTSCREENWIDE-block->screenx;\r
- screenxh = block->screenx + block->width;\r
- }\r
-\r
- if (screenyh > PORTSCREENHIGH)\r
- {\r
- block->height = PORTSCREENHIGH-block->screeny;\r
- screenyh = block->screeny + block->height;\r
- }\r
-\r
- if (block->width<1 || block->height<1)\r
- goto next;\r
-\r
- //\r
- // erase the block by copying from the master screen\r
- //\r
- pos = ylookup[block->screeny]+block->screenx;\r
- block->width = (block->width + (pos&1) + 1)& ~1;\r
- pos &= ~1; // make sure a word copy gets used\r
- VW_ScreenToScreen (masterofs+pos,bufferofs+pos,\r
- block->width,block->height);\r
-\r
- //\r
- // put 2s in update where the block was, to force sprites to update\r
- //\r
- xtl = block->screenx >> SX_T_SHIFT;\r
- xth = (block->screenx+block->width-1) >> SX_T_SHIFT;\r
- ytl = block->screeny >> SY_T_SHIFT;\r
- yth = (block->screeny+block->height-1) >> SY_T_SHIFT;\r
-\r
- updatespot = updateptr + uwidthtable[ytl] + xtl;\r
- updatedelta = UPDATEWIDE - (xth-xtl+1);\r
-\r
- for (y=ytl;y<=yth;y++)\r
- {\r
- for (x=xtl;x<=xth;x++)\r
- *updatespot++ = 2;\r
- updatespot += updatedelta; // down to next line\r
- }\r
-\r
-next:\r
- block++;\r
- }\r
- eraselistptr[0] = &eraselist[0][0];\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= RFL_UpdateSprites CGA\r
-=\r
-= NOTE: Implement vertical clipping!\r
-=\r
-====================\r
-*/\r
-\r
-void RFL_UpdateSprites (void)\r
-{\r
- spritelisttype *sprite;\r
- int portx,porty,x,y,xtl,xth,ytl,yth;\r
- int priority;\r
- unsigned dest;\r
- byte *updatespot,*baseupdatespot;\r
- unsigned updatedelta;\r
-\r
- unsigned updatecount;\r
- unsigned height,sourceofs;\r
-\r
-#ifdef PROFILE\r
- updatecount = 0;\r
-#endif\r
-\r
-\r
- for (priority=0;priority<PRIORITIES;priority++)\r
- {\r
- if (priority==MASKEDTILEPRIORITY)\r
- RFL_MaskForegroundTiles ();\r
-\r
- for (sprite = prioritystart[priority]; sprite ;\r
- sprite = (spritelisttype *)sprite->nextsprite)\r
- {\r
- //\r
- // see if the sprite has any visable area in the port\r
- //\r
-\r
- portx = sprite->screenx - originxscreen;\r
- porty = sprite->screeny - originyscreen;\r
- xtl = portx >> SX_T_SHIFT;\r
- xth = (portx + sprite->width-1) >> SX_T_SHIFT;\r
- ytl = porty >> SY_T_SHIFT;\r
- yth = (porty + sprite->height-1) >> SY_T_SHIFT;\r
-\r
- if (xtl<0)\r
- xtl = 0;\r
- if (xth>=PORTTILESWIDE)\r
- xth = PORTTILESWIDE-1;\r
- if (ytl<0)\r
- ytl = 0;\r
- if (yth>=PORTTILESHIGH)\r
- yth = PORTTILESHIGH-1;\r
-\r
- if (xtl>xth || ytl>yth)\r
- continue;\r
-\r
- //\r
- // see if it's visable area covers any non 0 update tiles\r
- //\r
- updatespot = baseupdatespot = updateptr + uwidthtable[ytl] + xtl;\r
- updatedelta = UPDATEWIDE - (xth-xtl+1);\r
-\r
- if (sprite->updatecount)\r
- {\r
- sprite->updatecount--; // the sprite was just placed,\r
- goto redraw; // so draw it for sure\r
- }\r
-\r
- for (y=ytl;y<=yth;y++)\r
- {\r
- for (x=xtl;x<=xth;x++)\r
- if (*updatespot++)\r
- goto redraw;\r
- updatespot += updatedelta; // down to next line\r
- }\r
- continue; // no need to update\r
-\r
-redraw:\r
- //\r
- // set the tiles it covers to 3, because those tiles are being\r
- // updated\r
- //\r
- updatespot = baseupdatespot;\r
- for (y=ytl;y<=yth;y++)\r
- {\r
- for (x=xtl;x<=xth;x++)\r
- *updatespot++ = 3;\r
- updatespot += updatedelta; // down to next line\r
- }\r
- //\r
- // draw it!\r
- //\r
- height = sprite->height;\r
- sourceofs = sprite->sourceofs;\r
- if (porty<0)\r
- {\r
- height += porty; // clip top off\r
- sourceofs -= porty*sprite->width;\r
- porty = 0;\r
- }\r
- else if (porty+height>PORTSCREENHIGH)\r
- {\r
- height = PORTSCREENHIGH - porty; // clip bottom off\r
- }\r
-\r
- dest = bufferofs + ylookup[porty] + portx;\r
-\r
- switch (sprite->draw)\r
- {\r
- case spritedraw:\r
- VW_MaskBlock(grsegs[sprite->grseg], sourceofs,\r
- dest,sprite->width,height,sprite->planesize);\r
- break;\r
-\r
- case maskdraw:\r
- break;\r
-\r
- }\r
-#ifdef PROFILE\r
- updatecount++;\r
-#endif\r
-\r
-\r
- }\r
- }\r
-}\r
-\r
-\r
-/*\r
-=====================\r
-=\r
-= RF_Refresh CGA\r
-=\r
-= All routines will draw at the port at bufferofs, possibly copying from\r
-= the port at masterofs. The EGA version then page flips, while the\r
-= CGA version updates the screen from the buffer port.\r
-=\r
-= Screenpage is the currently displayed page, not the one being drawn\r
-= Otherpage is the page to be worked with now\r
-=\r
-=====================\r
-*/\r
-\r
-void RF_Refresh (void)\r
-{\r
- long newtime,oldtimecount;\r
-\r
- RFL_AnimateTiles ();\r
-\r
-//\r
-// update newly scrolled on tiles and animated tiles from the master screen\r
-//\r
- RFL_UpdateTiles ();\r
- RFL_EraseBlocks ();\r
-\r
-//\r
-// Update is all 0 except where sprites have changed or new area has\r
-// been scrolled on. Go through all sprites and update the ones that cover\r
-// a non 0 update tile\r
-//\r
- RFL_UpdateSprites ();\r
-\r
-//\r
-// if the main program has a refresh hook set, call their function before\r
-// displaying the new page\r
-//\r
- if (refreshvector)\r
- refreshvector();\r
-\r
-//\r
-// update everything to the screen\r
-//\r
- VW_CGAFullUpdate ();\r
-\r
-//\r
-// calculate tics since last refresh for adaptive timing\r
-//\r
- RFL_CalcTics ();\r
-}\r
-\r
-#endif // GRMODE == CGAGR\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_RF.H\r
-\r
-#define __ID_RF__\r
-\r
-#ifndef __ID_MM__\r
-#include "ID_MM.H"\r
-#endif\r
-\r
-/*\r
-=============================================================================\r
-\r
- CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define MINTICS 2\r
-#define MAXTICS 6\r
-#define DEMOTICS 3\r
-\r
-#define MAPBORDER 2 // map border must be at least 1\r
-\r
-#define MAXSPRITES 50 // max tracked sprites\r
-#define MAXANIMTILES 90 // max animating tiles on screen\r
-#define MAXANIMTYPES 50 // max different unique anim tiles on map\r
-\r
-#define MAXMAPHEIGHT 200\r
-\r
-#define PRIORITIES 4\r
-#define MASKEDTILEPRIORITY 3 // planes go: 0,1,2,MTILES,3\r
-\r
-#define TILEGLOBAL 256\r
-#define PIXGLOBAL 16\r
-\r
-#define G_T_SHIFT 8 // global >> ?? = tile\r
-#define G_P_SHIFT 4 // global >> ?? = pixels\r
-#define P_T_SHIFT 4 // pixels >> ?? = tile\r
-\r
-#define PORTTILESWIDE 21 // all drawing takes place inside a\r
-#define PORTTILESHIGH 14 // non displayed port of this size\r
-\r
-//#define PORTGLOBALWIDE (21*TILEGLOBAL)\r
-//#define PORTGLOBALHIGH (14*TILEGLOBAL)\r
-\r
-#define UPDATEWIDE (PORTTILESWIDE+1)\r
-#define UPDATEHIGH PORTTILESHIGH\r
-\r
-\r
-//===========================================================================\r
-\r
-typedef enum {spritedraw,maskdraw} drawtype;\r
-\r
-/*\r
-=============================================================================\r
-\r
- PUBLIC VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-extern boolean compatability; // crippled refresh for wierdo SVGAs\r
-\r
-extern unsigned tics;\r
-extern long lasttimecount;\r
-\r
-extern unsigned originxglobal,originyglobal;\r
-extern unsigned originxtile,originytile;\r
-extern unsigned originxscreen,originyscreen;\r
-\r
-extern unsigned mapwidth,mapheight,mapbyteswide,mapwordswide\r
- ,mapbytesextra,mapwordsextra;\r
-extern unsigned mapbwidthtable[MAXMAPHEIGHT];\r
-\r
-extern unsigned originxmin,originxmax,originymin,originymax;\r
-\r
-extern unsigned masterofs;\r
-\r
-//\r
-// the floating update window is also used by the view manager for\r
-// double buffer tracking\r
-//\r
-\r
-extern byte *updateptr; // current start of update window\r
-\r
-#if GRMODE == CGAGR\r
-extern byte *baseupdateptr;\r
-#endif\r
-\r
-extern unsigned blockstarts[UPDATEWIDE*UPDATEHIGH];\r
-extern unsigned updatemapofs[UPDATEWIDE*UPDATEHIGH];\r
-extern unsigned uwidthtable[UPDATEHIGH]; // lookup instead of multiple\r
-\r
-#define UPDATETERMINATE 0x0301\r
-\r
-/*\r
-=============================================================================\r
-\r
- PUBLIC FUNCTIONS\r
-\r
-=============================================================================\r
-*/\r
-\r
-void RF_Startup (void);\r
-void RF_Shutdown (void);\r
-\r
-void RF_FixOfs (void);\r
-void RF_NewMap (void);\r
-void RF_MarkTileGraphics (void);\r
-void RF_SetScrollBlock (int x, int y, boolean horizontal);\r
-void RF_NewPosition (unsigned x, unsigned y);\r
-void RF_Scroll (int x, int y);\r
-\r
-void RF_MapToMap (unsigned srcx, unsigned srcy,\r
- unsigned destx, unsigned desty,\r
- unsigned width, unsigned height);\r
-void RF_MemToMap (unsigned far *source, unsigned plane,\r
- unsigned destx, unsigned desty,\r
- unsigned width, unsigned height);\r
-\r
-void RF_ClearBlock (int x, int y, int width, int height);\r
-void RF_RedrawBlock (int x, int y, int width, int height);\r
-\r
-void RF_PlaceSprite (void **user,unsigned globalx,unsigned globaly,\r
- unsigned spritenumber, drawtype draw, int priority);\r
-void RF_RemoveSprite (void **user);\r
-\r
-void RF_CalcTics (void);\r
-\r
-void RF_Refresh (void);\r
-void RF_ForceRefresh (void);\r
-void RF_SetRefreshHook (void (*func) (void) );\r
-\r
-unsigned RF_FindFreeBuffer (void);\r
-\r
+++ /dev/null
-; Catacomb Armageddon Source Code\r
-; Copyright (C) 1993-2014 Flat Rock Software\r
-;\r
-; This program is free software; you can redistribute it and/or modify\r
-; it under the terms of the GNU General Public License as published by\r
-; the Free Software Foundation; either version 2 of the License, or\r
-; (at your option) any later version.\r
-;\r
-; This program is distributed in the hope that it will be useful,\r
-; but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-; GNU General Public License for more details.\r
-;\r
-; You should have received a copy of the GNU General Public License along\r
-; with this program; if not, write to the Free Software Foundation, Inc.,\r
-; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-\r
-; ID_RF_A.ASM\r
-\r
-IDEAL\r
-MODEL MEDIUM,C\r
-\r
-INCLUDE "ID_ASM.EQU"\r
-\r
-;============================================================================\r
-\r
-TILESWIDE = 21\r
-TILESHIGH = 14\r
-\r
-UPDATESIZE = (TILESWIDE+1)*TILESHIGH+1\r
-\r
-DATASEG\r
-\r
-EXTRN screenseg:WORD\r
-EXTRN updateptr:WORD\r
-EXTRN updatestart:WORD\r
-EXTRN masterofs:WORD ;start of master tile port\r
-EXTRN bufferofs:WORD ;start of current buffer port\r
-EXTRN screenstart:WORD ;starts of three screens (0/1/master) in EGA mem\r
-EXTRN grsegs:WORD\r
-EXTRN mapsegs:WORD\r
-EXTRN originmap:WORD\r
-EXTRN updatemapofs:WORD\r
-EXTRN tinf:WORD ;seg pointer to map header and tile info\r
-EXTRN blockstarts:WORD ;offsets from bufferofs for each update block\r
-\r
-planemask db ?\r
-planenum db ?\r
-\r
-CODESEG\r
-\r
-screenstartcs dw ? ;in code segment for accesability\r
-\r
-\r
-\r
-\r
-IFE GRMODE-CGAGR\r
-;============================================================================\r
-;\r
-; CGA refresh routines\r
-;\r
-;============================================================================\r
-\r
-TILEWIDTH = 4\r
-\r
-;=================\r
-;\r
-; RFL_NewTile\r
-;\r
-; Draws a composit two plane tile to the master screen and sets the update\r
-; spot to 1 in both update pages, forcing the tile to be copied to the\r
-; view pages the next two refreshes\r
-;\r
-; Called to draw newlly scrolled on strips and animating tiles\r
-;\r
-;=================\r
-\r
-PROC RFL_NewTile updateoffset:WORD\r
-PUBLIC RFL_NewTile\r
-USES SI,DI\r
-\r
-;\r
-; mark both update lists at this spot\r
-;\r
- mov di,[updateoffset]\r
-\r
- mov bx,[updateptr] ;start of update matrix\r
- mov [BYTE bx+di],1\r
-\r
- mov dx,SCREENWIDTH-TILEWIDTH ;add to get to start of next line\r
-\r
-;\r
-; set di to the location in screenseg to draw the tile\r
-;\r
- shl di,1\r
- mov si,[updatemapofs+di] ;offset in map from origin\r
- add si,[originmap]\r
- mov di,[blockstarts+di] ;screen location for tile\r
- add di,[masterofs]\r
-\r
-;\r
-; set BX to the foreground tile number and SI to the background number\r
-; If either BX or SI = 0xFFFF, the tile does not need to be masked together\r
-; as one of the planes totally eclipses the other\r
-;\r
- mov es,[mapsegs+2] ;foreground plane\r
- mov bx,[es:si]\r
- mov es,[mapsegs] ;background plane\r
- mov si,[es:si]\r
-\r
- mov es,[screenseg]\r
-\r
- or bx,bx\r
- jz @@singletile\r
- jmp @@maskeddraw ;draw both together\r
-\r
-;=============\r
-;\r
-; Draw single background tile from main memory\r
-;\r
-;=============\r
-\r
-@@singletile:\r
- shl si,1\r
- mov ds,[grsegs+STARTTILE16*2+si]\r
-\r
- xor si,si ;block is segment aligned\r
-\r
-REPT 15\r
- movsw\r
- movsw\r
- add di,dx\r
-ENDM\r
- movsw\r
- movsw\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
- ret\r
-\r
-\r
-;=========\r
-;\r
-; Draw a masked tile combo\r
-; Interupts are disabled and the stack segment is reassigned\r
-;\r
-;=========\r
-@@maskeddraw:\r
- cli ; don't allow ints when SS is set\r
- shl bx,1\r
- mov ss,[grsegs+STARTTILE16M*2+bx]\r
- shl si,1\r
- mov ds,[grsegs+STARTTILE16*2+si]\r
-\r
- xor si,si ;first word of tile data\r
-\r
-REPT 16\r
- mov ax,[si] ;background tile\r
- and ax,[ss:si] ;mask\r
- or ax,[ss:si+64] ;masked data\r
- stosw\r
- mov ax,[si+2] ;background tile\r
- and ax,[ss:si+2] ;mask\r
- or ax,[ss:si+66] ;masked data\r
- stosw\r
- add si,4\r
- add di,dx\r
-ENDM\r
-\r
- mov ax,@DATA\r
- mov ss,ax\r
- sti\r
- mov ds,ax\r
- ret\r
-ENDP\r
-\r
-ENDIF\r
-\r
-\r
-\r
-IFE GRMODE-EGAGR\r
-;===========================================================================\r
-;\r
-; EGA refresh routines\r
-;\r
-;===========================================================================\r
-\r
-TILEWIDTH = 2\r
-\r
-;=================\r
-;\r
-; RFL_NewTile\r
-;\r
-; Draws a composit two plane tile to the master screen and sets the update\r
-; spot to 1 in both update pages, forcing the tile to be copied to the\r
-; view pages the next two refreshes\r
-;\r
-; Called to draw newlly scrolled on strips and animating tiles\r
-;\r
-; Assumes write mode 0\r
-;\r
-;=================\r
-\r
-PROC RFL_NewTile updateoffset:WORD\r
-PUBLIC RFL_NewTile\r
-USES SI,DI\r
-\r
-;\r
-; mark both update lists at this spot\r
-;\r
- mov di,[updateoffset]\r
-\r
- mov bx,[updatestart] ;page 0 pointer\r
- mov [BYTE bx+di],1\r
- mov bx,[updatestart+2] ;page 1 pointer\r
- mov [BYTE bx+di],1\r
-\r
-;\r
-; set screenstartcs to the location in screenseg to draw the tile\r
-;\r
- shl di,1\r
- mov si,[updatemapofs+di] ;offset in map from origin\r
- add si,[originmap]\r
- mov di,[blockstarts+di] ;screen location for tile\r
- add di,[masterofs]\r
- mov [cs:screenstartcs],di\r
-\r
-;\r
-; set BX to the foreground tile number and SI to the background number\r
-; If either BX or SI = 0xFFFF, the tile does not need to be masked together\r
-; as one of the planes totally eclipses the other\r
-;\r
- mov es,[mapsegs+2] ;foreground plane\r
- mov bx,[es:si]\r
- mov es,[mapsegs] ;background plane\r
- mov si,[es:si]\r
-\r
- mov es,[screenseg]\r
- mov dx,SC_INDEX ;for stepping through map mask planes\r
-\r
- or bx,bx\r
- jz @@singletile\r
- jmp @@maskeddraw ;draw both together\r
-\r
-;=========\r
-;\r
-; No foreground tile, so draw a single background tile.\r
-;\r
-;=========\r
-@@singletile:\r
-\r
- mov bx,SCREENWIDTH-2 ;add to get to start of next line\r
- shl si,1\r
-\r
- mov ax,[cs:screenstartcs]\r
- mov ds,[grsegs+STARTTILE16*2+si]\r
-\r
- xor si,si ;block is segment aligned\r
-\r
- mov ax,SC_MAPMASK+0001b*256 ;map mask for plane 0\r
-\r
- mov cx,4 ;draw four planes\r
-@@planeloop:\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[cs:screenstartcs] ;start at same place in all planes\r
-\r
-REPT 15\r
- movsw\r
- add di,bx\r
-ENDM\r
- movsw\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- loop @@planeloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
- ret\r
-\r
-\r
-;=========\r
-;\r
-; Draw a masked tile combo\r
-; Interupts are disabled and the stack segment is reassigned\r
-;\r
-;=========\r
-@@maskeddraw:\r
- cli ; don't allow ints when SS is set\r
- shl bx,1\r
- mov ss,[grsegs+STARTTILE16M*2+bx]\r
- shl si,1\r
- mov ds,[grsegs+STARTTILE16*2+si]\r
-\r
- xor si,si ;first word of tile data\r
-\r
- mov ax,SC_MAPMASK+0001b*256 ;map mask for plane 0\r
-\r
- mov di,[cs:screenstartcs]\r
-@@planeloopm:\r
- WORDOUT\r
-tileofs = 0\r
-lineoffset = 0\r
-REPT 16\r
- mov bx,[si+tileofs] ;background tile\r
- and bx,[ss:tileofs] ;mask\r
- or bx,[ss:si+tileofs+32] ;masked data\r
- mov [es:di+lineoffset],bx\r
-tileofs = tileofs + 2\r
-lineoffset = lineoffset + SCREENWIDTH\r
-ENDM\r
- add si,32\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b\r
- je @@done ;drawn all four planes\r
- jmp @@planeloopm\r
-\r
-@@done:\r
- mov ax,@DATA\r
- mov ss,ax\r
- sti\r
- mov ds,ax\r
- ret\r
-ENDP\r
-\r
-ENDIF\r
-\r
-IFE GRMODE-VGAGR\r
-;============================================================================\r
-;\r
-; VGA refresh routines\r
-;\r
-;============================================================================\r
-\r
-\r
-ENDIF\r
-\r
-\r
-;============================================================================\r
-;\r
-; reasonably common refresh routines\r
-;\r
-;============================================================================\r
-\r
-\r
-;=================\r
-;\r
-; RFL_UpdateTiles\r
-;\r
-; Scans through the update matrix pointed to by updateptr, looking for 1s.\r
-; A 1 represents a tile that needs to be copied from the master screen to the\r
-; current screen (a new row or an animated tiled). If more than one adjacent\r
-; tile in a horizontal row needs to be copied, they will be copied as a group.\r
-;\r
-; Assumes write mode 1\r
-;\r
-;=================\r
-\r
-\r
-; AX 0/1 for scasb, temp for segment register transfers\r
-; BX width for block copies\r
-; CX REP counter\r
-; DX line width deltas\r
-; SI source for copies\r
-; DI scas dest / movsb dest\r
-; BP pointer to UPDATETERMINATE\r
-;\r
-; DS\r
-; ES\r
-; SS\r
-\r
-PROC RFL_UpdateTiles\r
-PUBLIC RFL_UpdateTiles\r
-USES SI,DI,BP\r
-\r
- jmp SHORT @@realstart\r
-@@done:\r
-;\r
-; all tiles have been scanned\r
-;\r
- ret\r
-\r
-@@realstart:\r
- mov di,[updateptr]\r
- mov bp,(TILESWIDE+1)*TILESHIGH+1\r
- add bp,di ; when di = bx, all tiles have been scanned\r
- push di\r
- mov cx,-1 ; definately scan the entire thing\r
-\r
-;\r
-; scan for a 1 in the update list, meaning a tile needs to be copied\r
-; from the master screen to the current screen\r
-;\r
-@@findtile:\r
- pop di ; place to continue scaning from\r
- mov ax,ss\r
- mov es,ax ; search in the data segment\r
- mov ds,ax\r
- mov al,1\r
- repne scasb\r
- cmp di,bp\r
- je @@done\r
-\r
- cmp [BYTE di],al\r
- jne @@singletile\r
- jmp @@tileblock\r
-\r
-;============\r
-;\r
-; copy a single tile\r
-;\r
-;============\r
-EVEN\r
-@@singletile:\r
- inc di ; we know the next tile is nothing\r
- push di ; save off the spot being scanned\r
- sub di,[updateptr]\r
- shl di,1\r
- mov di,[blockstarts-4+di] ; start of tile location on screen\r
- mov si,di\r
- add di,[bufferofs] ; dest in current screen\r
- add si,[masterofs] ; source in master screen\r
-\r
- mov dx,SCREENWIDTH-TILEWIDTH\r
- mov ax,[screenseg]\r
- mov ds,ax\r
- mov es,ax\r
-\r
-;--------------------------\r
-\r
-IFE GRMODE-CGAGR\r
-\r
-REPT 15\r
- movsw\r
- movsw\r
- add si,dx\r
- add di,dx\r
-ENDM\r
- movsw\r
- movsw\r
-\r
-ENDIF\r
-\r
-;--------------------------\r
-\r
-IFE GRMODE-EGAGR\r
-\r
-REPT 15\r
- movsb\r
- movsb\r
- add si,dx\r
- add di,dx\r
-ENDM\r
- movsb\r
- movsb\r
-\r
-ENDIF\r
-\r
-;--------------------------\r
-\r
- jmp @@findtile\r
-\r
-;============\r
-;\r
-; more than one tile in a row needs to be updated, so do it as a group\r
-;\r
-;============\r
-EVEN\r
-@@tileblock:\r
- mov dx,di ; hold starting position + 1 in dx\r
- inc di ; we know the next tile also gets updated\r
- repe scasb ; see how many more in a row\r
- push di ; save off the spot being scanned\r
-\r
- mov bx,di\r
- sub bx,dx ; number of tiles in a row\r
- shl bx,1 ; number of bytes / row\r
-\r
- mov di,dx ; lookup position of start tile\r
- sub di,[updateptr]\r
- shl di,1\r
- mov di,[blockstarts-2+di] ; start of tile location\r
- mov si,di\r
- add di,[bufferofs] ; dest in current screen\r
- add si,[masterofs] ; source in master screen\r
-\r
- mov dx,SCREENWIDTH\r
- sub dx,bx ; offset to next line on screen\r
-IFE GRMODE-CGAGR\r
- sub dx,bx ; bx is words wide in CGA tiles\r
-ENDIF\r
-\r
- mov ax,[screenseg]\r
- mov ds,ax\r
- mov es,ax\r
-\r
-REPT 15\r
- mov cx,bx\r
-IFE GRMODE-CGAGR\r
- rep movsw\r
-ENDIF\r
-IFE GRMODE-EGAGR\r
- rep movsb\r
-ENDIF\r
- add si,dx\r
- add di,dx\r
-ENDM\r
- mov cx,bx\r
-IFE GRMODE-CGAGR\r
- rep movsw\r
-ENDIF\r
-IFE GRMODE-EGAGR\r
- rep movsb\r
-ENDIF\r
-\r
- dec cx ; was 0 from last rep movsb, now $ffff for scasb\r
- jmp @@findtile\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-\r
-\r
-;=================\r
-;\r
-; RFL_MaskForegroundTiles\r
-;\r
-; Scan through update looking for 3's. If the foreground tile there is a\r
-; masked foreground tile, draw it to the screen\r
-;\r
-;=================\r
-\r
-PROC RFL_MaskForegroundTiles\r
-PUBLIC RFL_MaskForegroundTiles\r
-USES SI,DI,BP\r
- jmp SHORT @@realstart\r
-@@done:\r
-;\r
-; all tiles have been scanned\r
-;\r
- ret\r
-\r
-@@realstart:\r
- mov di,[updateptr]\r
- mov bp,(TILESWIDE+1)*TILESHIGH+2\r
- add bp,di ; when di = bx, all tiles have been scanned\r
- push di\r
- mov cx,-1 ; definately scan the entire thing\r
-;\r
-; scan for a 3 in the update list\r
-;\r
-@@findtile:\r
- mov ax,ss\r
- mov es,ax ; scan in the data segment\r
- mov al,3\r
- pop di ; place to continue scaning from\r
- repne scasb\r
- cmp di,bp\r
- je @@done\r
-\r
-;============\r
-;\r
-; found a tile, see if it needs to be masked on\r
-;\r
-;============\r
-\r
- push di\r
-\r
- sub di,[updateptr]\r
- shl di,1\r
- mov si,[updatemapofs-2+di] ; offset from originmap\r
- add si,[originmap]\r
-\r
- mov es,[mapsegs+2] ; foreground map plane segment\r
- mov si,[es:si] ; foreground tile number\r
-\r
- or si,si\r
- jz @@findtile ; 0 = no foreground tile\r
-\r
- mov bx,si\r
- add bx,INTILE ;INTILE tile info table\r
- mov es,[tinf]\r
- test [BYTE PTR es:bx],80h ;high bit = masked tile\r
- jz @@findtile\r
-\r
-;-------------------\r
-\r
-IFE GRMODE-CGAGR\r
-;=================\r
-;\r
-; mask the tile CGA\r
-;\r
-;=================\r
-\r
- mov di,[blockstarts-2+di]\r
- add di,[bufferofs]\r
- mov es,[screenseg]\r
- shl si,1\r
- mov ds,[grsegs+STARTTILE16M*2+si]\r
-\r
- mov bx,64 ;data starts 64 bytes after mask\r
-\r
- xor si,si\r
-\r
-lineoffset = 0\r
-REPT 16\r
- mov ax,[es:di+lineoffset] ;background\r
- and ax,[si] ;mask\r
- or ax,[si+bx] ;masked data\r
- mov [es:di+lineoffset],ax ;background\r
- inc si\r
- inc si\r
- mov ax,[es:di+lineoffset+2] ;background\r
- and ax,[si] ;mask\r
- or ax,[si+bx] ;masked data\r
- mov [es:di+lineoffset+2],ax ;background\r
- inc si\r
- inc si\r
-lineoffset = lineoffset + SCREENWIDTH\r
-ENDM\r
-ENDIF\r
-\r
-;-------------------\r
-\r
-IFE GRMODE-EGAGR\r
-;=================\r
-;\r
-; mask the tile\r
-;\r
-;=================\r
-\r
- mov [BYTE planemask],1\r
- mov [BYTE planenum],0\r
-\r
- mov di,[blockstarts-2+di]\r
- add di,[bufferofs]\r
- mov [cs:screenstartcs],di\r
- mov es,[screenseg]\r
- shl si,1\r
- mov ds,[grsegs+STARTTILE16M*2+si]\r
-\r
- mov bx,32 ;data starts 32 bytes after mask\r
-\r
-@@planeloopm:\r
- mov dx,SC_INDEX\r
- mov al,SC_MAPMASK\r
- mov ah,[ss:planemask]\r
- WORDOUT\r
- mov dx,GC_INDEX\r
- mov al,GC_READMAP\r
- mov ah,[ss:planenum]\r
- WORDOUT\r
-\r
- xor si,si\r
- mov di,[cs:screenstartcs]\r
-lineoffset = 0\r
-REPT 16\r
- mov cx,[es:di+lineoffset] ;background\r
- and cx,[si] ;mask\r
- or cx,[si+bx] ;masked data\r
- inc si\r
- inc si\r
- mov [es:di+lineoffset],cx\r
-lineoffset = lineoffset + SCREENWIDTH\r
-ENDM\r
- add bx,32 ;the mask is now further away\r
- inc [ss:planenum]\r
- shl [ss:planemask],1 ;shift plane mask over for next plane\r
- cmp [ss:planemask],10000b ;done all four planes?\r
- je @@drawn ;drawn all four planes\r
- jmp @@planeloopm\r
-\r
-@@drawn:\r
-ENDIF\r
-\r
-;-------------------\r
-\r
- mov ax,ss\r
- mov ds,ax\r
- mov cx,-1 ;definately scan the entire thing\r
-\r
- jmp @@findtile\r
-\r
-ENDP\r
-\r
-\r
-END\r
-\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_SD.c - Sound Manager\r
-// v1.1d1\r
-// By Jason Blochowiak\r
-//\r
-\r
-//\r
-// This module handles dealing with generating sound on the appropriate\r
-// hardware\r
-//\r
-// Depends on: User Mgr (for parm checking)\r
-//\r
-// Globals:\r
-// For User Mgr:\r
-// SoundSourcePresent - Sound Source thingie present?\r
-// SoundBlasterPresent - SoundBlaster card present?\r
-// AdLibPresent - AdLib card present?\r
-// SoundMode - What device is used for sound effects\r
-// (Use SM_SetSoundMode() to set)\r
-// MusicMode - What device is used for music\r
-// (Use SM_SetMusicMode() to set)\r
-// For Cache Mgr:\r
-// NeedsDigitized - load digitized sounds?\r
-// NeedsMusic - load music?\r
-//\r
-\r
-#define USE_MUSIC 0\r
-\r
-#pragma hdrstop // Wierdo thing with MUSE\r
-\r
-#include <dos.h>\r
-\r
-#ifdef _MUSE_ // Will be defined in ID_Types.h\r
-#include "ID_SD.h"\r
-#else\r
-#include "ID_HEADS.H"\r
-#endif\r
-#pragma hdrstop\r
-#pragma warn -pia\r
-\r
-#define SDL_SoundFinished() {SoundNumber = SoundPriority = 0;}\r
-\r
-// Macros for AdLib stuff\r
-#define selreg(n) outportb(0x388,n)\r
-#define writereg(n) outportb(0x389,n)\r
-#define readstat() inportb(0x388)\r
-\r
-// Global variables\r
- boolean SoundSourcePresent,SoundBlasterPresent,AdLibPresent,\r
- NeedsDigitized,NeedsMusic;\r
- SDMode SoundMode;\r
- SMMode MusicMode;\r
- longword TimeCount;\r
- word HackCount;\r
- word *SoundTable; // Really * _seg *SoundTable, but that don't work\r
- boolean ssIsTandy;\r
- word ssPort = 2;\r
-\r
-// Internal variables\r
-static boolean SD_Started;\r
-static boolean TimerDone;\r
-static word TimerVal,TimerDelay10,TimerDelay25,TimerDelay100;\r
-static longword TimerDivisor,TimerCount;\r
-static char *ParmStrings[] =\r
- {\r
- "noal",\r
- nil\r
- };\r
-static void (*SoundUserHook)(void);\r
-static word SoundNumber,SoundPriority;\r
-static void interrupt (*t0OldService)(void);\r
-//static word t0CountTable[] = {8,8,8,8,40,40};\r
-static long LocalTime;\r
-\r
-// PC Sound variables\r
-static byte pcLastSample,far *pcSound;\r
-static longword pcLengthLeft;\r
-static word pcSoundLookup[255];\r
-\r
-// AdLib variables\r
-static boolean alNoCheck;\r
-static byte far *alSound;\r
-static word alBlock;\r
-static longword alLengthLeft;\r
-static longword alTimeCount;\r
-static Instrument alZeroInst;\r
-\r
-// This table maps channel numbers to carrier and modulator op cells\r
-static byte carriers[9] = { 3, 4, 5,11,12,13,19,20,21},\r
- modifiers[9] = { 0, 1, 2, 8, 9,10,16,17,18},\r
-// This table maps percussive voice numbers to op cells\r
- pcarriers[5] = {19,0xff,0xff,0xff,0xff},\r
- pmodifiers[5] = {16,17,18,20,21};\r
-\r
-// Sequencer variables\r
-static boolean sqActive;\r
-static word alFXReg;\r
-static ActiveTrack *tracks[sqMaxTracks],\r
- mytracks[sqMaxTracks];\r
-static word sqMode,sqFadeStep;\r
-static word far *sqHack,far *sqHackPtr,sqHackLen,sqHackSeqLen;\r
-static long sqHackTime;\r
-\r
-// Internal routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_SetTimer0() - Sets system timer 0 to the specified speed\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#pragma argsused\r
-static void\r
-SDL_SetTimer0(word speed)\r
-{\r
-#ifndef TPROF // If using Borland's profiling, don't screw with the timer\r
- outportb(0x43,0x36); // Change timer 0\r
- outportb(0x40,speed);\r
- outportb(0x40,speed >> 8);\r
- TimerDivisor = speed;\r
-#else\r
- TimerDivisor = 0x10000;\r
-#endif\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_SetIntsPerSec() - Uses SDL_SetTimer0() to set the number of\r
-// interrupts generated by system timer 0 per second\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_SetIntsPerSec(word ints)\r
-{\r
- SDL_SetTimer0(1192030 / ints);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_TimingService() - Used by SDL_InitDelay() to determine a timing\r
-// value for the current system that we're running on\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void interrupt\r
-SDL_TimingService(void)\r
-{\r
- TimerVal = _CX;\r
- TimerDone++;\r
-\r
- outportb(0x20,0x20); // Ack interrupt\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_InitDelay() - Sets up TimerDelay's for SDL_Delay()\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_InitDelay(void)\r
-{\r
- int i;\r
- word timer;\r
-\r
- setvect(8,SDL_TimingService); // Set to my timer 0 ISR\r
-\r
- SDL_SetIntsPerSec(1000); // Time 1ms\r
-\r
- for (i = 0,timer = 0;i < 10;i++) // Do timing test 10 times\r
- {\r
- asm xor dx,dx // Zero DX\r
- asm mov cx,0xffff // Put starting value in CX\r
- asm mov [TimerDone],cx // TimerDone = false - 1\r
-startloop:\r
- asm or [TimerDone],0\r
- asm jnz startloop // Make sure we're at the start\r
-loop:\r
- asm test [TimerDone],1 // See if TimerDone flag got hit\r
- asm jnz done // Yep - drop out of the loop\r
- asm loop loop\r
-done:\r
-\r
- if (0xffff - TimerVal > timer)\r
- timer = 0xffff - TimerVal;\r
- }\r
- timer += timer / 2; // Use some slop\r
- TimerDelay10 = timer / (1000 / 10);\r
- TimerDelay25 = timer / (1000 / 25);\r
- TimerDelay100 = timer / (1000 / 100);\r
-\r
- SDL_SetTimer0(0); // Reset timer 0\r
-\r
- setvect(8,t0OldService); // Set back to old ISR\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_Delay() - Delays the specified amount of time\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_Delay(word delay)\r
-{\r
- if (!delay)\r
- return;\r
-\r
-asm mov cx,[delay]\r
-loop:\r
-asm test [TimerDone],0 // Useless code - just for timing equivilency\r
-asm jnz done\r
-asm loop loop\r
-done:;\r
-}\r
-\r
-//\r
-// PC Sound code\r
-//\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_PCPlaySound() - Plays the specified sound on the PC speaker\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#ifdef _MUSE_\r
-void\r
-#else\r
-static void\r
-#endif\r
-SDL_PCPlaySound(PCSound far *sound)\r
-{\r
-asm pushf\r
-asm cli\r
-\r
- pcLastSample = -1;\r
- pcLengthLeft = sound->common.length;\r
- pcSound = sound->data;\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_PCStopSound() - Stops the current sound playing on the PC Speaker\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#ifdef _MUSE_\r
-void\r
-#else\r
-static void\r
-#endif\r
-SDL_PCStopSound(void)\r
-{\r
-asm pushf\r
-asm cli\r
-\r
- (long)pcSound = 0;\r
-\r
-asm in al,0x61 // Turn the speaker off\r
-asm and al,0xfd // ~2\r
-asm out 0x61,al\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_PCService() - Handles playing the next sample in a PC sound\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_PCService(void)\r
-{\r
- byte s;\r
- word t;\r
-\r
- if (pcSound)\r
- {\r
- s = *pcSound++;\r
- if (s != pcLastSample)\r
- {\r
- asm pushf\r
- asm cli\r
-\r
- pcLastSample = s;\r
- if (s) // We have a frequency!\r
- {\r
- t = pcSoundLookup[s];\r
- asm mov bx,[t]\r
-\r
- asm mov al,0xb6 // Write to channel 2 (speaker) timer\r
- asm out 43h,al\r
- asm mov al,bl\r
- asm out 42h,al // Low byte\r
- asm mov al,bh\r
- asm out 42h,al // High byte\r
-\r
- asm in al,0x61 // Turn the speaker & gate on\r
- asm or al,3\r
- asm out 0x61,al\r
- }\r
- else // Time for some silence\r
- {\r
- asm in al,0x61 // Turn the speaker & gate off\r
- asm and al,0xfc // ~3\r
- asm out 0x61,al\r
- }\r
-\r
- asm popf\r
- }\r
-\r
- if (!(--pcLengthLeft))\r
- {\r
- SDL_PCStopSound();\r
- SDL_SoundFinished();\r
- }\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_ShutPC() - Turns off the pc speaker\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_ShutPC(void)\r
-{\r
-asm pushf\r
-asm cli\r
-\r
- pcSound = 0;\r
-\r
-asm in al,0x61 // Turn the speaker & gate off\r
-asm and al,0xfc // ~3\r
-asm out 0x61,al\r
-\r
-asm popf\r
-}\r
-\r
-// AdLib Code\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// alOut(n,b) - Puts b in AdLib card register n\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-alOut(byte n,byte b)\r
-{\r
-asm pushf\r
-asm cli\r
-\r
-asm mov dx,0x388\r
-asm mov al,[n]\r
-asm out dx,al\r
-#if 0\r
- SDL_Delay(TimerDelay10);\r
-#else\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-#endif\r
-\r
-asm mov dx,0x389\r
-asm mov al,[b]\r
-asm out dx,al\r
-\r
-asm popf\r
-\r
-#if 0\r
- SDL_Delay(TimerDelay25);\r
-#else\r
-asm mov dx,0x388\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-asm in al, dx\r
-#endif\r
-}\r
-\r
-#if 0\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_SetInstrument() - Puts an instrument into a generator\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_SetInstrument(int track,int which,Instrument far *inst,boolean percussive)\r
-{\r
- byte c,m;\r
-\r
- if (percussive)\r
- {\r
- c = pcarriers[which];\r
- m = pmodifiers[which];\r
- }\r
- else\r
- {\r
- c = carriers[which];\r
- m = modifiers[which];\r
- }\r
-\r
- tracks[track - 1]->inst = *inst;\r
- tracks[track - 1]->percussive = percussive;\r
-\r
- alOut(m + alChar,inst->mChar);\r
- alOut(m + alScale,inst->mScale);\r
- alOut(m + alAttack,inst->mAttack);\r
- alOut(m + alSus,inst->mSus);\r
- alOut(m + alWave,inst->mWave);\r
-\r
- // Most percussive instruments only use one cell\r
- if (c != 0xff)\r
- {\r
- alOut(c + alChar,inst->cChar);\r
- alOut(c + alScale,inst->cScale);\r
- alOut(c + alAttack,inst->cAttack);\r
- alOut(c + alSus,inst->cSus);\r
- alOut(c + alWave,inst->cWave);\r
- }\r
-\r
- alOut(which + alFeedCon,inst->nConn); // DEBUG - I think this is right\r
-}\r
-#endif\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_ALStopSound() - Turns off any sound effects playing through the\r
-// AdLib card\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#ifdef _MUSE_\r
-void\r
-#else\r
-static void\r
-#endif\r
-SDL_ALStopSound(void)\r
-{\r
-asm pushf\r
-asm cli\r
-\r
- (long)alSound = 0;\r
- alOut(alFreqH + 0,0);\r
-\r
-asm popf\r
-}\r
-\r
-static void\r
-SDL_AlSetFXInst(Instrument far *inst)\r
-{\r
- byte c,m;\r
-\r
- m = modifiers[0];\r
- c = carriers[0];\r
- alOut(m + alChar,inst->mChar);\r
- alOut(m + alScale,inst->mScale);\r
- alOut(m + alAttack,inst->mAttack);\r
- alOut(m + alSus,inst->mSus);\r
- alOut(m + alWave,inst->mWave);\r
- alOut(c + alChar,inst->cChar);\r
- alOut(c + alScale,inst->cScale);\r
- alOut(c + alAttack,inst->cAttack);\r
- alOut(c + alSus,inst->cSus);\r
- alOut(c + alWave,inst->cWave);\r
- // DEBUG!!! - I just put this in\r
-// alOut(alFeedCon,inst->nConn);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_ALPlaySound() - Plays the specified sound on the AdLib card\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#ifdef _MUSE_\r
-void\r
-#else\r
-static void\r
-#endif\r
-SDL_ALPlaySound(AdLibSound far *sound)\r
-{\r
- Instrument far *inst;\r
-\r
- SDL_ALStopSound();\r
-\r
-asm pushf\r
-asm cli\r
-\r
- alLengthLeft = sound->common.length;\r
- alSound = sound->data;\r
- alBlock = ((sound->block & 7) << 2) | 0x20;\r
- inst = &sound->inst;\r
-\r
- if (!(inst->mSus | inst->cSus))\r
- {\r
- asm popf\r
- Quit("SDL_ALPlaySound() - Bad instrument");\r
- }\r
-\r
- SDL_AlSetFXInst(inst);\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_ALSoundService() - Plays the next sample out through the AdLib card\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_ALSoundService(void)\r
-{\r
- byte s;\r
-\r
- if (alSound)\r
- {\r
- s = *alSound++;\r
- if (!s)\r
- alOut(alFreqH + 0,0);\r
- else\r
- {\r
- alOut(alFreqL + 0,s);\r
- alOut(alFreqH + 0,alBlock);\r
- }\r
-\r
- if (!(--alLengthLeft))\r
- {\r
- (long)alSound = 0;\r
- alOut(alFreqH + 0,0);\r
- SDL_SoundFinished();\r
- }\r
- }\r
-}\r
-\r
-#if 0\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_SelectMeasure() - sets up sequencing variables for a given track\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_SelectMeasure(ActiveTrack *track)\r
-{\r
- track->seq = track->moods[track->mood];\r
- track->nextevent = 0;\r
-}\r
-#endif\r
-\r
-static void\r
-SDL_ALService(void)\r
-{\r
- byte a,v;\r
- word w;\r
-\r
- if (!sqActive)\r
- return;\r
-\r
- while (sqHackLen && (sqHackTime <= alTimeCount))\r
- {\r
- w = *sqHackPtr++;\r
- sqHackTime = alTimeCount + *sqHackPtr++;\r
- asm mov dx,[w]\r
- asm mov [a],dl\r
- asm mov [v],dh\r
- alOut(a,v);\r
- sqHackLen -= 4;\r
- }\r
- alTimeCount++;\r
- if (!sqHackLen)\r
- {\r
- sqHackPtr = (word far *)sqHack;\r
- sqHackLen = sqHackSeqLen;\r
- alTimeCount = sqHackTime = 0;\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_ShutAL() - Shuts down the AdLib card for sound effects\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_ShutAL(void)\r
-{\r
-asm pushf\r
-asm cli\r
-\r
- alOut(alEffects,0);\r
- alOut(alFreqH + 0,0);\r
- SDL_AlSetFXInst(&alZeroInst);\r
- alSound = 0;\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_CleanAL() - Totally shuts down the AdLib card\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_CleanAL(void)\r
-{\r
- int i;\r
-\r
-asm pushf\r
-asm cli\r
-\r
- alOut(alEffects,0);\r
- for (i = 1;i < 0xf5;i++)\r
- alOut(i,0);\r
-\r
-asm popf\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_StartAL() - Starts up the AdLib card for sound effects\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_StartAL(void)\r
-{\r
- alFXReg = 0;\r
- alOut(alEffects,alFXReg);\r
- SDL_AlSetFXInst(&alZeroInst);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_DetectAdLib() - Determines if there's an AdLib (or SoundBlaster\r
-// emulating an AdLib) present\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-SDL_DetectAdLib(void)\r
-{\r
- byte status1,status2;\r
- int i;\r
-\r
- alOut(4,0x60); // Reset T1 & T2\r
- alOut(4,0x80); // Reset IRQ\r
- status1 = readstat();\r
- alOut(2,0xff); // Set timer 1\r
- alOut(4,0x21); // Start timer 1\r
- SDL_Delay(TimerDelay100);\r
-\r
- status2 = readstat();\r
- alOut(4,0x60);\r
- alOut(4,0x80);\r
-\r
- if (((status1 & 0xe0) == 0x00) && ((status2 & 0xe0) == 0xc0))\r
- {\r
- for (i = 1;i <= 0xf5;i++) // Zero all the registers\r
- alOut(i,0);\r
-\r
- alOut(1,0x20); // Set WSE=1\r
- alOut(8,0); // Set CSM=0 & SEL=0\r
-\r
- return(true);\r
- }\r
- else\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_t0Service() - My timer 0 ISR which handles the different timings and\r
-// dispatches to whatever other routines are appropriate\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void interrupt\r
-SDL_t0Service(void)\r
-{\r
-static word count = 1;\r
-\r
-#if 0 // for debugging\r
-asm mov dx,STATUS_REGISTER_1\r
-asm in al,dx\r
-asm mov dx,ATR_INDEX\r
-asm mov al,ATR_OVERSCAN\r
-asm out dx,al\r
-asm mov al,4 // red\r
-asm out dx,al\r
-#endif\r
-\r
- HackCount++;\r
-\r
-#if USE_MUSIC\r
- if (MusicMode == smm_AdLib)\r
- {\r
- SDL_ALService();\r
- if (!(++count & 7))\r
- {\r
- LocalTime++;\r
- TimeCount++;\r
- if (SoundUserHook)\r
- SoundUserHook();\r
- }\r
- if (!(count & 3))\r
- {\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- SDL_PCService();\r
- break;\r
- case sdm_AdLib:\r
- SDL_ALSoundService();\r
- break;\r
- }\r
- }\r
- }\r
- else\r
-#endif\r
- {\r
- if (!(++count & 1))\r
- {\r
- LocalTime++;\r
- TimeCount++;\r
- if (SoundUserHook)\r
- SoundUserHook();\r
- }\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- SDL_PCService();\r
- break;\r
- case sdm_AdLib:\r
- SDL_ALSoundService();\r
- break;\r
- }\r
- }\r
-\r
-asm mov ax,[WORD PTR TimerCount]\r
-asm add ax,[WORD PTR TimerDivisor]\r
-asm mov [WORD PTR TimerCount],ax\r
-asm jnc myack\r
- t0OldService(); // If we overflow a word, time to call old int handler\r
-asm jmp olddone\r
-myack:;\r
- outportb(0x20,0x20); // Ack the interrupt\r
-olddone:;\r
-\r
-#if 0 // for debugging\r
-asm mov dx,STATUS_REGISTER_1\r
-asm in al,dx\r
-asm mov dx,ATR_INDEX\r
-asm mov al,ATR_OVERSCAN\r
-asm out dx,al\r
-asm mov al,3 // blue\r
-asm out dx,al\r
-asm mov al,0x20 // normal\r
-asm out dx,al\r
-#endif\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_ShutDevice() - turns off whatever device was being used for sound fx\r
-//\r
-////////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_ShutDevice(void)\r
-{\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- SDL_ShutPC();\r
- break;\r
- case sdm_AdLib:\r
- SDL_ShutAL();\r
- break;\r
- }\r
- SoundMode = sdm_Off;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_CleanDevice() - totally shuts down all sound devices\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_CleanDevice(void)\r
-{\r
- if ((SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib))\r
- SDL_CleanAL();\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SDL_StartDevice() - turns on whatever device is to be used for sound fx\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-SDL_StartDevice(void)\r
-{\r
- switch (SoundMode)\r
- {\r
- case sdm_AdLib:\r
- SDL_StartAL();\r
- break;\r
- }\r
- SoundNumber = SoundPriority = 0;\r
-}\r
-\r
-static void\r
-SDL_SetTimerSpeed(void)\r
-{\r
- word rate;\r
-\r
-#if USE_MUSIC\r
- if (MusicMode == smm_AdLib)\r
- rate = TickBase * 8;\r
- else\r
-#endif\r
- rate = TickBase * 2;\r
- SDL_SetIntsPerSec(rate);\r
-}\r
-\r
-// Public routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_SetSoundMode() - Sets which sound hardware to use for sound effects\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-SD_SetSoundMode(SDMode mode)\r
-{\r
- boolean result;\r
- word tableoffset;\r
-\r
- SD_StopSound();\r
-\r
-#ifndef _MUSE_\r
- switch (mode)\r
- {\r
- case sdm_Off:\r
- NeedsDigitized = false;\r
- result = true;\r
- break;\r
- case sdm_PC:\r
- tableoffset = STARTPCSOUNDS;\r
- NeedsDigitized = false;\r
- result = true;\r
- break;\r
- case sdm_AdLib:\r
- if (AdLibPresent)\r
- {\r
- tableoffset = STARTADLIBSOUNDS;\r
- NeedsDigitized = false;\r
- result = true;\r
- }\r
- break;\r
- default:\r
- result = false;\r
- break;\r
- }\r
-#endif\r
-\r
- if (result && (mode != SoundMode))\r
- {\r
- SDL_ShutDevice();\r
- SoundMode = mode;\r
-#ifndef _MUSE_\r
- SoundTable = (word *)(&audiosegs[tableoffset]);\r
-#endif\r
- SDL_StartDevice();\r
- }\r
-\r
- SDL_SetTimerSpeed();\r
-\r
- return(result);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_SetMusicMode() - sets the device to use for background music\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-SD_SetMusicMode(SMMode mode)\r
-{\r
-#if USE_MUSIC\r
- boolean result;\r
-\r
- SD_FadeOutMusic();\r
- while (SD_MusicPlaying())\r
- ;\r
-\r
- switch (mode)\r
- {\r
- case smm_Off:\r
- NeedsMusic = false;\r
- result = true;\r
- break;\r
- case smm_AdLib:\r
- if (AdLibPresent)\r
- {\r
- NeedsMusic = true;\r
- result = true;\r
- }\r
- break;\r
- default:\r
- result = false;\r
- break;\r
- }\r
-\r
- if (result)\r
- MusicMode = mode;\r
-\r
- SDL_SetTimerSpeed();\r
-\r
- return(result);\r
-#endif\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_Startup() - starts up the Sound Mgr\r
-// Detects all additional sound hardware and installs my ISR\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_Startup(void)\r
-{\r
- int i;\r
-\r
- if (SD_Started)\r
- return;\r
-\r
- ssIsTandy = false;\r
- alNoCheck = false;\r
-#ifndef _MUSE_\r
- for (i = 1;i < _argc;i++)\r
- {\r
- switch (US_CheckParm(_argv[i],ParmStrings))\r
- {\r
- case 0: // No AdLib detection\r
- alNoCheck = true;\r
- break;\r
- }\r
- }\r
-#endif\r
-\r
- SoundUserHook = 0;\r
-\r
- t0OldService = getvect(8); // Get old timer 0 ISR\r
-\r
- SDL_InitDelay(); // SDL_InitDelay() uses t0OldService\r
-\r
- setvect(8,SDL_t0Service); // Set to my timer 0 ISR\r
- LocalTime = TimeCount = alTimeCount = 0;\r
-\r
- SD_SetSoundMode(sdm_Off);\r
-#if USE_MUSIC\r
- SD_SetMusicMode(smm_Off);\r
-#endif\r
-\r
- if (!alNoCheck)\r
- AdLibPresent = SDL_DetectAdLib();\r
-\r
- for (i = 0;i < 255;i++)\r
- pcSoundLookup[i] = i * 60;\r
-\r
- SD_Started = true;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_Default() - Sets up the default behaviour for the Sound Mgr whether\r
-// the config file was present or not.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_Default(boolean gotit,SDMode sd,SMMode sm)\r
-{\r
- boolean gotsd,gotsm;\r
-\r
- gotsd = gotsm = gotit;\r
-\r
- if (gotsd) // Make sure requested sound hardware is available\r
- {\r
- switch (sd)\r
- {\r
- case sdm_AdLib:\r
- gotsd = AdLibPresent;\r
- break;\r
- }\r
- }\r
- if (!gotsd)\r
- {\r
- if (AdLibPresent)\r
- sd = sdm_AdLib;\r
- else\r
- sd = sdm_PC;\r
- }\r
- if (sd != SoundMode)\r
- SD_SetSoundMode(sd);\r
-\r
-\r
- if (gotsm) // Make sure requested music hardware is available\r
- {\r
- switch (sm)\r
- {\r
- case sdm_AdLib:\r
- gotsm = AdLibPresent;\r
- break;\r
- }\r
- }\r
- if (!gotsm)\r
- {\r
- if (AdLibPresent)\r
- sm = smm_AdLib;\r
- }\r
-#if USE_MUSIC\r
- if (sm != MusicMode)\r
- SD_SetMusicMode(sm);\r
-#endif\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_Shutdown() - shuts down the Sound Mgr\r
-// Removes sound ISR and turns off whatever sound hardware was active\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_Shutdown(void)\r
-{\r
- if (!SD_Started)\r
- return;\r
-\r
-#if USE_MUSIC\r
- SD_MusicOff();\r
-#endif\r
- SDL_ShutDevice();\r
- SDL_CleanDevice();\r
-\r
- asm pushf\r
- asm cli\r
-\r
- SDL_SetTimer0(0);\r
-\r
- setvect(8,t0OldService);\r
-\r
- asm popf\r
-\r
- SD_Started = false;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_SetUserHook() - sets the routine that the Sound Mgr calls every 1/70th\r
-// of a second from its timer 0 ISR\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_SetUserHook(void (* hook)(void))\r
-{\r
- SoundUserHook = hook;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_PlaySound() - plays the specified sound on the appropriate hardware\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_PlaySound(soundnames sound)\r
-{\r
- SoundCommon far *s;\r
-\r
- if ((SoundMode == sdm_Off) || (sound == -1))\r
- return;\r
-\r
- s = MK_FP(SoundTable[sound],0);\r
- if (!s)\r
- Quit("SD_PlaySound() - Uncached sound");\r
- if (!s->length)\r
- Quit("SD_PlaySound() - Zero length sound");\r
- if (s->priority < SoundPriority)\r
- return;\r
-\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- SDL_PCPlaySound((void far *)s);\r
- break;\r
- case sdm_AdLib:\r
- SDL_ALPlaySound((void far *)s);\r
- break;\r
- }\r
-\r
- SoundNumber = sound;\r
- SoundPriority = s->priority;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_SoundPlaying() - returns the sound number that's playing, or 0 if\r
-// no sound is playing\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-word\r
-SD_SoundPlaying(void)\r
-{\r
- boolean result = false;\r
-\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- result = pcSound? true : false;\r
- break;\r
- case sdm_AdLib:\r
- result = alSound? true : false;\r
- break;\r
- }\r
-\r
- if (result)\r
- return(SoundNumber);\r
- else\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_StopSound() - if a sound is playing, stops it\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_StopSound(void)\r
-{\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- SDL_PCStopSound();\r
- break;\r
- case sdm_AdLib:\r
- SDL_ALStopSound();\r
- break;\r
- }\r
-\r
- SDL_SoundFinished();\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_WaitSoundDone() - waits until the current sound is done playing\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_WaitSoundDone(void)\r
-{\r
- while (SD_SoundPlaying())\r
- ;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_MusicOn() - turns on the sequencer\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_MusicOn(void)\r
-{\r
-#if USE_MUSIC\r
- sqActive = true;\r
-#endif\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_MusicOff() - turns off the sequencer and any playing notes\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_MusicOff(void)\r
-{\r
-#if USE_MUSIC\r
- word i;\r
-\r
-\r
- switch (MusicMode)\r
- {\r
- case smm_AdLib:\r
- alFXReg = 0;\r
- alOut(alEffects,0);\r
- for (i = 0;i < sqMaxTracks;i++)\r
- alOut(alFreqH + i + 1,0);\r
- break;\r
- }\r
- sqActive = false;\r
-#endif\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_StartMusic() - starts playing the music pointed to\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_StartMusic(MusicGroup far *music)\r
-{\r
-#if USE_MUSIC\r
- SD_MusicOff();\r
-asm pushf\r
-asm cli\r
-\r
- if (MusicMode == smm_AdLib)\r
- {\r
- sqHackPtr = sqHack = music->values;\r
- sqHackSeqLen = sqHackLen = music->length;\r
- sqHackTime = 0;\r
- alTimeCount = 0;\r
- SD_MusicOn();\r
- }\r
-\r
-asm popf\r
-#endif\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_FadeOutMusic() - starts fading out the music. Call SD_MusicPlaying()\r
-// to see if the fadeout is complete\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-SD_FadeOutMusic(void)\r
-{\r
-#if USE_MUSIC\r
- switch (MusicMode)\r
- {\r
- case smm_AdLib:\r
- // DEBUG - quick hack to turn the music off\r
- SD_MusicOff();\r
- break;\r
- }\r
-#endif\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// SD_MusicPlaying() - returns true if music is currently playing, false if\r
-// not\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-SD_MusicPlaying(void)\r
-{\r
-#if USE_MUSIC\r
- boolean result;\r
-\r
- switch (MusicMode)\r
- {\r
- case smm_AdLib:\r
- result = false;\r
- // DEBUG - not written\r
- break;\r
- default:\r
- result = false;\r
- }\r
-\r
- return(result);\r
-#endif\r
-}\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_SD.h - Sound Manager Header\r
-// v1.0d1\r
-// By Jason Blochowiak\r
-//\r
-\r
-#ifndef __TYPES__\r
-#include "ID_Types.h"\r
-#endif\r
-\r
-#ifndef __ID_SD__\r
-#define __ID_SD__\r
-\r
-#ifdef __DEBUG__\r
-#define __DEBUG_SoundMgr__\r
-#endif\r
-\r
-#define TickBase 70 // 70Hz per tick - used as a base for timer 0\r
-\r
-typedef enum {\r
- sdm_Off,\r
- sdm_PC,sdm_AdLib,\r
- } SDMode;\r
-typedef enum {\r
- smm_Off,smm_AdLib\r
- } SMMode;\r
-\r
-typedef struct\r
- {\r
- longword length;\r
- word priority;\r
- } SoundCommon;\r
-\r
-// PC Sound stuff\r
-#define pcTimer 0x42\r
-#define pcTAccess 0x43\r
-#define pcSpeaker 0x61\r
-\r
-#define pcSpkBits 3\r
-\r
-typedef struct\r
- {\r
- SoundCommon common;\r
- byte data[1];\r
- } PCSound;\r
-\r
-// Registers for the Sound Blaster card - needs to be offset by n0\r
-#define sbReset 0x206\r
-#define sbReadData 0x20a\r
-#define sbWriteCmd 0x20c\r
-#define sbWriteData 0x20c\r
-#define sbWriteStat 0x20c\r
-#define sbDataAvail 0x20e\r
-\r
-typedef struct\r
- {\r
- SoundCommon common;\r
- word hertz;\r
- byte bits,\r
- reference,\r
- data[1];\r
- } SampledSound;\r
-\r
-// Registers for the AdLib card\r
-// Operator stuff\r
-#define alChar 0x20\r
-#define alScale 0x40\r
-#define alAttack 0x60\r
-#define alSus 0x80\r
-#define alWave 0xe0\r
-// Channel stuff\r
-#define alFreqL 0xa0\r
-#define alFreqH 0xb0\r
-#define alFeedCon 0xc0\r
-// Global stuff\r
-#define alEffects 0xbd\r
-\r
-typedef struct\r
- {\r
- byte mChar,cChar,\r
- mScale,cScale,\r
- mAttack,cAttack,\r
- mSus,cSus,\r
- mWave,cWave,\r
- nConn,\r
-\r
- // These are only for Muse - these bytes are really unused\r
- voice,\r
- mode,\r
- unused[3];\r
- } Instrument;\r
-\r
-typedef struct\r
- {\r
- SoundCommon common;\r
- Instrument inst;\r
- byte block,\r
- data[1];\r
- } AdLibSound;\r
-\r
-//\r
-// Sequencing stuff\r
-//\r
-#define sqMaxTracks 10\r
-#define sqMaxMoods 1 // DEBUG\r
-\r
-#define sev_Null 0 // Does nothing\r
-#define sev_NoteOff 1 // Turns a note off\r
-#define sev_NoteOn 2 // Turns a note on\r
-#define sev_NotePitch 3 // Sets the pitch of a currently playing note\r
-#define sev_NewInst 4 // Installs a new instrument\r
-#define sev_NewPerc 5 // Installs a new percussive instrument\r
-#define sev_PercOn 6 // Turns a percussive note on\r
-#define sev_PercOff 7 // Turns a percussive note off\r
-#define sev_SeqEnd -1 // Terminates a sequence\r
-\r
-// Flags for MusicGroup.flags\r
-#define sf_Melodic 0\r
-#define sf_Percussive 1\r
-\r
-#if 1\r
-typedef struct\r
- {\r
- word length,\r
- values[1];\r
- } MusicGroup;\r
-#else\r
-typedef struct\r
- {\r
- word flags,\r
- count,\r
- offsets[1];\r
- } MusicGroup;\r
-#endif\r
-\r
-typedef struct\r
- {\r
- /* This part needs to be set up by the user */\r
- word mood,far *moods[sqMaxMoods];\r
-\r
- /* The rest is set up by the code */\r
- Instrument inst;\r
- boolean percussive;\r
- word far *seq;\r
- longword nextevent;\r
- } ActiveTrack;\r
-\r
-#define sqmode_Normal 0\r
-#define sqmode_FadeIn 1\r
-#define sqmode_FadeOut 2\r
-\r
-#define sqMaxFade 64 // DEBUG\r
-\r
-\r
-// Global variables\r
-extern boolean AdLibPresent,\r
- NeedsMusic; // For Caching Mgr\r
-extern SDMode SoundMode;\r
-extern SMMode MusicMode;\r
-extern longword TimeCount; // Global time in ticks\r
-extern SDMode oldsoundmode;\r
-\r
-// Function prototypes\r
-extern void SD_Startup(void),\r
- SD_Shutdown(void),\r
- SD_Default(boolean gotit,SDMode sd,SMMode sm),\r
- SD_PlaySound(soundnames sound),\r
- SD_StopSound(void),\r
- SD_WaitSoundDone(void),\r
- SD_StartMusic(MusicGroup far *music),\r
- SD_MusicOn(void),\r
- SD_MusicOff(void),\r
- SD_FadeOutMusic(void),\r
- SD_SetUserHook(void (*hook)(void));\r
-extern boolean SD_MusicPlaying(void),\r
- SD_SetSoundMode(SDMode mode),\r
- SD_SetMusicMode(SMMode mode);\r
-extern word SD_SoundPlaying(void);\r
-\r
-#ifdef _MUSE_ // MUSE Goes directly to the lower level routines\r
-extern void SDL_PCPlaySound(PCSound far *sound),\r
- SDL_PCStopSound(void),\r
- SDL_ALPlaySound(AdLibSound far *sound),\r
- SDL_ALStopSound(void);\r
-#endif\r
-\r
-#endif\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#define S_LOADING "Loading"\r
-#define S_EMPTYSPOT "Empty"\r
-#define S_SVGACOMP "SVGA Compatibility Mode Enabled."\r
-#define S_READYPRESS " Ready - Press a Key "\r
-#define S_NOSFX "NO SOUND EFFECTS"\r
-#define S_PCSPKR "PC SPEAKER"\r
-#define S_ALSB "ADLIB/SOUNDBLASTER"\r
-#define S_QUIET "QUIET ADLIB/SOUNDBLASTER"\r
-#define S_NOMUSIC "NO MUSIC"\r
-#define S_BEGINE "BEGIN EASY GAME"\r
-#define S_BEGINN "BEGIN NORMAL GAME"\r
-#define S_BEGINH "BEGIN HARD GAME"\r
-#define S_UPLEFT "UP & LEFT"\r
-#define S_UP "UP"\r
-#define S_UPRIGHT "UP & RIGHT"\r
-#define S_RIGHT "RIGHT"\r
-#define S_DNRIGHT "DOWN & RIGHT"\r
-#define S_DN "DOWN"\r
-#define S_DNLEFT "DOWN & LEFT"\r
-#define S_LEFT "LEFT"\r
-\r
-#define S_JUMP "JUMP"\r
-#define S_POGO "POGO"\r
-#define S_FIRE "FIRE"\r
-#define S_MOVEMENT "MOVEMENT"\r
-#define S_BUTTONS "BUTTONS"\r
-\r
-#define S_SOUND "SOUND"\r
-#define S_MUSIC "MUSIC"\r
-#define S_OPTIONS "OPTIONS"\r
-#define S_USEKB "USE KEYBOARD"\r
-#define S_USEJOY1 "USE JOYSTICK #1"\r
-#define S_USEJOY2 "USE JOYSTICK #2"\r
-#define S_NEWGAME "NEW GAME"\r
-#define S_LOADGAME "LOAD GAME"\r
-#define S_SAVEGAME "SAVE GAME"\r
-#define S_CONFIG "CONFIGURE"\r
-#define S_ENDGAME "END GAME"\r
-#define S_PADDLEWAR "PADDLE WAR"\r
-#define S_QUIT "QUIT"\r
-\r
-#define S_ESCBACK "ESC TO BACK OUT"\r
-#define S_ESCBACK1 "ESC to back out"\r
-#define S_ESCQUIT "ESC to quit"\r
-#define S_F1HELP "F1 for help"\r
-#define S_REALLYEND "REALLY END CURRENT GAME?"\r
-#define S_PRESSY "PRESS Y TO END IT"\r
-#define S_REALLYQUIT "REALLY QUIT?"\r
-#define S_PRESSYQ "PRESS Y TO QUIT"\r
-#define S_INAGAME "YOU'RE IN A GAME"\r
-#define S_PRESSY2L "PRESS Y TO LOAD GAME"\r
-#define S_PRESSY4N "PRESS Y FOR NEW GAME"\r
-\r
-#define S_USLERROR "Error: "\r
-#define S_USLUNKNOWN "Unknown"\r
-#define S_USLDISKFULL "Disk is Full"\r
-#define S_USLFILEINC "File is Incomplete"\r
-#define S_PRESSKEY "PRESS ANY KEY"\r
-#define S_PRESSKEY1 "Press any key"\r
-\r
-#define S_SBOXON "SCORE BOX (ON)"\r
-#define S_SBOXOFF "SCORE BOX (OFF)"\r
-#define S_SVGAON "SVGA COMPATIBILITY (ON)"\r
-#define S_SVGAOFF "SVGA COMPATIBILITY (OFF)"\r
-#define S_2BON "TWO-BUTTON FIRING (ON)"\r
-#define S_2BOFF "TWO-BUTTON FIRING (OFF)"\r
-\r
-#define S_SBOXNOWON "Score box now on"\r
-#define S_SBOXNOWOFF "Score box now off"\r
-#define S_SVGANOWON "SVGA compatibility now on"\r
-#define S_SVGANOWOFF "SVGA compatibility now off"\r
-#define S_2BNOWON "Two-button firing now on"\r
-#define S_2BNOWOFF "Two-button firing now off"\r
-\r
-#define S_KEYBOARD "KEYBOARD"\r
-#define S_JOY1 "JOYSTICK #1"\r
-#define S_JOY2 "JOYSTICK #2"\r
-#define S_MOUSE "MOUSE"\r
-#define S_CONTROL "CONTROL: "\r
-#define S_KEYUSED "Key already used"\r
-#define S_PB1 "and press button #1"\r
-#define S_PB2 "and press button #2"\r
-#define S_MJUL "Move Joystick to upper left"\r
-#define S_MJLR "Move Joystick to lower right"\r
-\r
-#define S_USINGJ1 "USING "S_JOY1\r
-#define S_USINGJ2 "USING "S_JOY2\r
-#define S_TYPENAME "Type name"\r
-#define S_ENTERACC "Enter accepts"\r
-#define S_UNTITLED "Untitled"\r
-#define S_SAVING "Saving"\r
-#define S_YOULOST "You lost!"\r
-#define S_YOUWON "You won!"\r
-#define S_ARRMOVE "Arrows move"\r
-#define S_ENTERSEL "Enter selects"\r
-\r
-#define S_RETGAME "RETURN TO GAME"\r
-#define S_RETDEMO "RETURN TO DEMO"\r
-#define S_CTRLPANEL "Control Panel"\r
-#define S_QUITTING "Quitting..."\r
-\r
-#define S_WHATNAME "What is the name of this creature?"\r
-#define S_SORRY "Sorry, that's not quite right."\r
-#define S_CHECKMAN "Please check your manual and try again."\r
-\r
-#define S_BADCARD "Improper video card! If you really have an EGA/VGA card that I am not\n"\\r
- "detecting, use the -HIDDENCARD command line parameter!"\r
-#define S_BADCARD1 "Improper video card! If you really have a CGA card that I am not\n"\\r
- "detecting, use the -HIDDENCARD command line parameter!"\r
-\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_US.c - User Manager\r
-// v1.0d1\r
-// By Jason Blochowiak\r
-//\r
-\r
-//\r
-// This module handles dealing with user input & feedback\r
-//\r
-// Depends on: Input Mgr, View Mgr, some variables from the Sound, Caching,\r
-// and Refresh Mgrs, Memory Mgr for background save/restore\r
-//\r
-// Globals:\r
-// ingame - Flag set by game indicating if a game is in progress\r
-// abortgame - Flag set if the current game should be aborted (if a load\r
-// game fails)\r
-// loadedgame - Flag set if a game was loaded\r
-// abortprogram - Normally nil, this points to a terminal error message\r
-// if the program needs to abort\r
-// restartgame - Normally set to gd_Continue, this is set to one of the\r
-// difficulty levels if a new game should be started\r
-// PrintX, PrintY - Where the User Mgr will print (global coords)\r
-// WindowX,WindowY,WindowW,WindowH - The dimensions of the current\r
-// window\r
-//\r
-\r
-// DEBUG - handle LPT3 for Sound Source\r
-\r
-#include "ID_HEADS.H"\r
-\r
-#define CTL_M_ADLIBUPPIC CTL_S_ADLIBUPPIC\r
-#define CTL_M_ADLIBDNPIC CTL_S_ADLIBDNPIC\r
-\r
-#pragma hdrstop\r
-\r
-#pragma warn -pia\r
-\r
-#define MaxX 320\r
-#define MaxY 200\r
-\r
-#define MaxHelpLines 500\r
-\r
-#define MaxHighName 57\r
-#define MaxScores 10\r
-typedef struct\r
- {\r
- char name[MaxHighName + 1];\r
- long score;\r
- word completed;\r
- } HighScore;\r
-\r
-#define MaxGameName 32\r
-#define MaxSaveGames 7\r
-typedef struct\r
- {\r
- char signature[4];\r
- boolean present;\r
- char name[MaxGameName + 1];\r
- } SaveGame;\r
-\r
-// Hack import for TED launch support\r
-extern boolean tedlevel;\r
-extern word tedlevelnum;\r
-extern void TEDDeath(void);\r
-static char *ParmStrings[] = {"TEDLEVEL","NOWAIT",""};\r
-\r
-\r
-// Global variables\r
- boolean ingame,abortgame,loadedgame;\r
- char *abortprogram;\r
- GameDiff restartgame = gd_Continue;\r
- word PrintX,PrintY;\r
- word WindowX,WindowY,WindowW,WindowH;\r
-\r
-// Internal variables\r
-static boolean US_Started;\r
-static boolean GameIsDirty,\r
- HighScoresDirty,\r
- QuitToDos,\r
- ResumeGame,\r
- NoWait;\r
-\r
-static memptr LineOffsets;\r
-\r
-static boolean Button0,Button1,\r
- CursorBad;\r
-static int CursorX,CursorY;\r
-\r
-static void (*USL_MeasureString)(char far *,word *,word *) = VW_MeasurePropString,\r
- (*USL_DrawString)(char far *) = VWB_DrawPropString;\r
-\r
-static boolean (*USL_SaveGame)(int),(*USL_LoadGame)(int);\r
-static void (*USL_ResetGame)(void);\r
-static SaveGame Games[MaxSaveGames];\r
-static HighScore Scores[MaxScores] =\r
- {\r
- {"Sir Lancelot",500},\r
- {"",0},\r
- {"",0},\r
- {"",0},\r
- {"",0},\r
- {"",0},\r
- {"",0},\r
- {"",0},\r
- {"",0},\r
- {"",0}\r
- };\r
-\r
-// Internal routines\r
-\r
-// Public routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_HardError() - Handles the Abort/Retry/Fail sort of errors passed\r
-// from DOS.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#pragma warn -par\r
-#pragma warn -rch\r
-int\r
-USL_HardError(word errval,int ax,int bp,int si)\r
-{\r
-#define IGNORE 0\r
-#define RETRY 1\r
-#define ABORT 2\r
-extern void ShutdownId(void);\r
-\r
-static char buf[32];\r
-static WindowRec wr;\r
-static boolean oldleavedriveon;\r
- int di;\r
- char c,*s,*t;\r
-\r
-\r
- di = _DI;\r
-\r
- oldleavedriveon = LeaveDriveOn;\r
- LeaveDriveOn = false;\r
-\r
- if (ax < 0)\r
- s = "Device Error";\r
- else\r
- {\r
- if ((di & 0x00ff) == 0)\r
- s = "Drive ~ is Write Protected";\r
- else\r
- s = "Error on Drive ~";\r
- for (t = buf;*s;s++,t++) // Can't use sprintf()\r
- if ((*t = *s) == '~')\r
- *t = (ax & 0x00ff) + 'A';\r
- *t = '\0';\r
- s = buf;\r
- }\r
-\r
- c = peekb(0x40,0x49); // Get the current screen mode\r
- if ((c < 4) || (c == 7))\r
- goto oh_kill_me;\r
-\r
- // DEBUG - handle screen cleanup\r
-\r
- US_SaveWindow(&wr);\r
- US_CenterWindow(30,3);\r
- US_CPrint(s);\r
- US_CPrint("(R)etry or (A)bort?");\r
- VW_UpdateScreen();\r
- IN_ClearKeysDown();\r
-\r
-asm sti // Let the keyboard interrupts come through\r
-\r
- while (true)\r
- {\r
- switch (IN_WaitForASCII())\r
- {\r
- case key_Escape:\r
- case 'a':\r
- case 'A':\r
- goto oh_kill_me;\r
- break;\r
- case key_Return:\r
- case key_Space:\r
- case 'r':\r
- case 'R':\r
- US_ClearWindow();\r
- VW_UpdateScreen();\r
- US_RestoreWindow(&wr);\r
- LeaveDriveOn = oldleavedriveon;\r
- return(RETRY);\r
- break;\r
- }\r
- }\r
-\r
-oh_kill_me:\r
- abortprogram = s;\r
- ShutdownId();\r
- fprintf(stderr,"Terminal Error: %s\n",s);\r
- if (tedlevel)\r
- fprintf(stderr,"You launched from TED. I suggest that you reboot...\n");\r
-\r
- return(ABORT);\r
-#undef IGNORE\r
-#undef RETRY\r
-#undef ABORT\r
-}\r
-#pragma warn +par\r
-#pragma warn +rch\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_GiveSaveName() - Returns a pointer to a static buffer that contains\r
-// the filename to use for the specified save game\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static char *\r
-USL_GiveSaveName(word game)\r
-{\r
-static char filename[32];\r
- char *s,*t;\r
-\r
- for (s = "SAVEGM",t = filename;*s;)\r
- *t++ = *s++;\r
- *t++ = game + '0';\r
- for (s = "."EXTENSION;*s;)\r
- *t++ = *s++;\r
- *t = '\0';\r
-\r
- return(filename);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_SetLoadSaveHooks() - Sets the routines that the User Mgr calls after\r
-// reading or writing the save game headers\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_SetLoadSaveHooks(boolean (*load)(int),boolean (*save)(int),void (*reset)(void))\r
-{\r
- USL_LoadGame = load;\r
- USL_SaveGame = save;\r
- USL_ResetGame = reset;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_ReadConfig() - Reads the configuration file, if present, and sets\r
-// things up accordingly. If it's not present, uses defaults. This file\r
-// includes the high scores.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_ReadConfig(void)\r
-{\r
- boolean gotit;\r
- int file;\r
- SDMode sd;\r
- SMMode sm;\r
- ControlType ctl;\r
-\r
- if ((file = open("CONFIG."EXTENSION,O_BINARY | O_RDONLY)) != -1)\r
- {\r
- read(file,Scores,sizeof(HighScore) * MaxScores);\r
- read(file,&sd,sizeof(sd));\r
- read(file,&sm,sizeof(sm));\r
- read(file,&ctl,sizeof(ctl));\r
- read(file,&(KbdDefs[0]),sizeof(KbdDefs[0]));\r
- close(file);\r
-\r
- HighScoresDirty = false;\r
- gotit = true;\r
- }\r
- else\r
- {\r
- sd = sdm_Off;\r
- sm = smm_Off;\r
- ctl = ctrl_Keyboard;\r
-\r
- gotit = false;\r
- HighScoresDirty = true;\r
- }\r
-\r
- SD_Default(gotit,sd,sm);\r
- IN_Default(gotit,ctl);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_WriteConfig() - Writes out the current configuration, including the\r
-// high scores.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_WriteConfig(void)\r
-{\r
- int file;\r
-\r
- file = open("CONFIG."EXTENSION,O_CREAT | O_BINARY | O_WRONLY,\r
- S_IREAD | S_IWRITE | S_IFREG);\r
- if (file != -1)\r
- {\r
- write(file,Scores,sizeof(HighScore) * MaxScores);\r
- write(file,&SoundMode,sizeof(SoundMode));\r
- write(file,&MusicMode,sizeof(MusicMode));\r
- write(file,&(Controls[0]),sizeof(Controls[0]));\r
- write(file,&(KbdDefs[0]),sizeof(KbdDefs[0]));\r
- close(file);\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_CheckSavedGames() - Checks to see which saved games are present\r
-// & valid\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_CheckSavedGames(void)\r
-{\r
- boolean ok;\r
- char *filename;\r
- word i;\r
- int file;\r
- SaveGame *game;\r
-\r
- USL_SaveGame = 0;\r
- USL_LoadGame = 0;\r
-\r
- for (i = 0,game = Games;i < MaxSaveGames;i++,game++)\r
- {\r
- filename = USL_GiveSaveName(i);\r
- ok = false;\r
- if ((file = open(filename,O_BINARY | O_RDONLY)) != -1)\r
- {\r
- if\r
- (\r
- (read(file,game,sizeof(*game)) == sizeof(*game))\r
- && (!strcmp(game->signature,EXTENSION))\r
- )\r
- ok = true;\r
-\r
- close(file);\r
- }\r
-\r
- if (ok)\r
- game->present = true;\r
- else\r
- {\r
- strcpy(game->signature,EXTENSION);\r
- game->present = false;\r
- strcpy(game->name,"Empty");\r
- }\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_Startup() - Starts the User Mgr\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_Startup(void)\r
-{\r
- if (US_Started)\r
- return;\r
-\r
- harderr(USL_HardError); // Install the fatal error handler\r
-\r
- US_InitRndT(true); // Initialize the random number generator\r
-\r
- USL_ReadConfig(); // Read config file\r
-\r
- US_Started = true;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_Setup() - Does the disk access part of the User Mgr's startup\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_Setup(void)\r
-{\r
- USL_CheckSavedGames(); // Check which saved games are present\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_Shutdown() - Shuts down the User Mgr\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_Shutdown(void)\r
-{\r
- if (!US_Started)\r
- return;\r
-\r
- if (!abortprogram)\r
- USL_WriteConfig();\r
-\r
- US_Started = false;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_CheckParm() - checks to see if a string matches one of a set of\r
-// strings. The check is case insensitive. The routine returns the\r
-// index of the string that matched, or -1 if no matches were found\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-int\r
-US_CheckParm(char *parm,char **strings)\r
-{\r
- char cp,cs,\r
- *p,*s;\r
- int i;\r
-\r
- while (!isalpha(*parm)) // Skip non-alphas\r
- parm++;\r
-\r
- for (i = 0;*strings && **strings;i++)\r
- {\r
- for (s = *strings++,p = parm,cs = cp = 0;cs == cp;)\r
- {\r
- cs = *s++;\r
- if (!cs)\r
- return(i);\r
- cp = *p++;\r
-\r
- if (isupper(cs))\r
- cs = tolower(cs);\r
- if (isupper(cp))\r
- cp = tolower(cp);\r
- }\r
- }\r
- return(-1);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_ScreenDraw() - Draws a chunk of the text screen (called only by\r
-// US_TextScreen())\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_ScreenDraw(word x,word y,char *s,byte attr)\r
-{\r
- byte far *screen;\r
-\r
- screen = MK_FP(0xb800,(x * 2) + (y * 80 * 2));\r
- while (*s)\r
- {\r
- *screen++ = *s++;\r
- *screen++ = attr;\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_ClearTextScreen() - Makes sure the screen is in text mode, clears it,\r
-// and moves the cursor to the leftmost column of the bottom line\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_ClearTextScreen(void)\r
-{\r
- // Set to 80x25 color text mode\r
- _AL = 3; // Mode 3\r
- _AH = 0x00;\r
- geninterrupt(0x10);\r
-\r
- // Use BIOS to move the cursor to the bottom of the screen\r
- _AH = 0x0f;\r
- geninterrupt(0x10); // Get current video mode into _BH\r
- _DL = 0; // Lefthand side of the screen\r
- _DH = 24; // Bottom row\r
- _AH = 0x02;\r
- geninterrupt(0x10);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_TextScreen() - Puts up the startup text screen\r
-// Note: These are the only User Manager functions that can be safely called\r
-// before the User Mgr has been started up\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_TextScreen(void)\r
-{\r
- word i,n,\r
- sx,sy;\r
-extern char far introscn;\r
-\r
- USL_ClearTextScreen();\r
-\r
- _fmemcpy(MK_FP(0xb800,0),7 + &introscn,80 * 25 * 2);\r
-\r
- // Check for TED launching here\r
- for (i = 1;i < _argc;i++)\r
- {\r
- n = US_CheckParm(_argv[i],ParmStrings);\r
- if (n == 0)\r
- {\r
- tedlevelnum = atoi(_argv[i + 1]);\r
- if (tedlevelnum >= 0)\r
- {\r
- tedlevel = true;\r
- return;\r
- }\r
- else\r
- break;\r
- }\r
- else if (n == 1)\r
- {\r
- NoWait = true;\r
- return;\r
- }\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_Show() - Changes the appearance of one of the fields on the text\r
-// screen. Possibly adds a checkmark in front of it and highlights it\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_Show(word x,word y,word w,boolean show,boolean hilight)\r
-{\r
- byte far *screen;\r
-\r
- screen = MK_FP(0xb800,((x - 1) * 2) + (y * 80 * 2));\r
- *screen++ = show? 251 : ' '; // Checkmark char or space\r
- *screen = 0x48;\r
- if (show && hilight)\r
- {\r
- for (w++;w--;screen += 2)\r
- *screen = 0x4f;\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_ShowMem() - Right justifies a longword in one of the memory fields on\r
-// the text screen\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_ShowMem(word x,word y,long mem)\r
-{\r
- char buf[16];\r
- word i;\r
-\r
- for (i = strlen(ltoa(mem,buf,10));i < 5;i++)\r
- USL_ScreenDraw(x++,y," ",0x48);\r
- USL_ScreenDraw(x,y,buf,0x48);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_UpdateTextScreen() - Called after the ID libraries are started up.\r
-// Displays what hardware is present.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_UpdateTextScreen(void)\r
-{\r
- boolean b;\r
- byte far *screen;\r
- word i;\r
- longword totalmem;\r
-\r
- // Show video card info\r
- b = (grmode == CGAGR);\r
- USL_Show(21,7,4,(videocard >= CGAcard) && (videocard <= VGAcard),b);\r
- b = (grmode == EGAGR);\r
- USL_Show(21,8,4,(videocard >= EGAcard) && (videocard <= VGAcard),b);\r
- b = (grmode == VGAGR);\r
- USL_Show(21,9,4,videocard == VGAcard,b);\r
- if (compatability)\r
- USL_ScreenDraw(5,10,"SVGA Compatibility Mode Enabled.",0x4f);\r
-\r
- // Show input device info\r
- USL_Show(60,7,8,true,true);\r
- USL_Show(60,8,11,JoysPresent[0],true);\r
- USL_Show(60,9,11,JoysPresent[1],true);\r
- USL_Show(60,10,5,MousePresent,true);\r
-\r
- // Show sound hardware info\r
- USL_Show(21,14,11,true,SoundMode == sdm_PC);\r
- b = (SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib);\r
- USL_Show(21,15,5,AdLibPresent && !SoundBlasterPresent,\r
- b && !SoundBlasterPresent);\r
- USL_Show(21,16,13,SoundBlasterPresent,\r
- SoundBlasterPresent && (b || (SoundMode == sdm_SoundBlaster)));\r
- USL_Show(21,17,13,SoundSourcePresent,SoundMode == sdm_SoundSource);\r
-\r
- // Show memory available/used\r
- USL_ShowMem(63,15,mminfo.mainmem / 1024);\r
- USL_Show(53,15,23,true,true);\r
- USL_ShowMem(63,16,mminfo.EMSmem / 1024);\r
- USL_Show(53,16,23,mminfo.EMSmem? true : false,true);\r
- USL_ShowMem(63,17,mminfo.XMSmem / 1024);\r
- USL_Show(53,17,23,mminfo.XMSmem? true : false,true);\r
- totalmem = mminfo.mainmem + mminfo.EMSmem + mminfo.XMSmem;\r
- USL_ShowMem(63,18,totalmem / 1024);\r
- screen = MK_FP(0xb800,1 + (((63 - 1) * 2) + (18 * 80 * 2)));\r
- for (i = 0;i < 13;i++,screen += 2)\r
- *screen = 0x4f;\r
-\r
- // Change Initializing... to Loading...\r
- USL_ScreenDraw(27,22," Loading... ",0x9c);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_FinishTextScreen() - After the main program has finished its initial\r
-// loading, this routine waits for a keypress and then clears the screen\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_FinishTextScreen(void)\r
-{\r
- // Change Loading... to Press a Key\r
- USL_ScreenDraw(29,22," Ready - Press a Key ",0x9a);\r
-\r
- if (!(tedlevel || NoWait))\r
- {\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
- }\r
- IN_ClearKeysDown();\r
-\r
- USL_ClearTextScreen();\r
-}\r
-\r
-// Window/Printing routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_SetPrintRoutines() - Sets the routines used to measure and print\r
-// from within the User Mgr. Primarily provided to allow switching\r
-// between masked and non-masked fonts\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_SetPrintRoutines(void (*measure)(char far *,word *,word *),void (*print)(char far *))\r
-{\r
- USL_MeasureString = measure;\r
- USL_DrawString = print;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_Print() - Prints a string in the current window. Newlines are\r
-// supported.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_Print(char *s)\r
-{\r
- char c,*se;\r
- word w,h;\r
-\r
- while (*s)\r
- {\r
- se = s;\r
- while ((c = *se) && (c != '\n'))\r
- se++;\r
- *se = '\0';\r
-\r
- USL_MeasureString(s,&w,&h);\r
- px = PrintX;\r
- py = PrintY;\r
- USL_DrawString(s);\r
-\r
- s = se;\r
- if (c)\r
- {\r
- *se = c;\r
- s++;\r
-\r
- PrintX = WindowX;\r
- PrintY += h;\r
- }\r
- else\r
- PrintX += w;\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_PrintUnsigned() - Prints an unsigned long\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_PrintUnsigned(longword n)\r
-{\r
- char buffer[32];\r
-\r
- US_Print(ultoa(n,buffer,10));\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_PrintSigned() - Prints a signed long\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_PrintSigned(long n)\r
-{\r
- char buffer[32];\r
-\r
- US_Print(ltoa(n,buffer,10));\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_PrintInCenter() - Prints a string in the center of the given rect\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_PrintInCenter(char *s,Rect r)\r
-{\r
- word w,h,\r
- rw,rh;\r
-\r
- USL_MeasureString(s,&w,&h);\r
- rw = r.lr.x - r.ul.x;\r
- rh = r.lr.y - r.ul.y;\r
-\r
- px = r.ul.x + ((rw - w) / 2);\r
- py = r.ul.y + ((rh - h) / 2);\r
- USL_DrawString(s);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_PrintCentered() - Prints a string centered in the current window.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_PrintCentered(char *s)\r
-{\r
- Rect r;\r
-\r
- r.ul.x = WindowX;\r
- r.ul.y = WindowY;\r
- r.lr.x = r.ul.x + WindowW;\r
- r.lr.y = r.ul.y + WindowH;\r
-\r
- USL_PrintInCenter(s,r);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_CPrintLine() - Prints a string centered on the current line and\r
-// advances to the next line. Newlines are not supported.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_CPrintLine(char *s)\r
-{\r
- word w,h;\r
-\r
- USL_MeasureString(s,&w,&h);\r
-\r
- if (w > WindowW)\r
- Quit("US_CPrintLine() - String exceeds width");\r
- px = WindowX + ((WindowW - w) / 2);\r
- py = PrintY;\r
- USL_DrawString(s);\r
- PrintY += h;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_CPrint() - Prints a string in the current window. Newlines are\r
-// supported.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_CPrint(char *s)\r
-{\r
- char c,*se;\r
- word w,h;\r
-\r
- while (*s)\r
- {\r
- se = s;\r
- while ((c = *se) && (c != '\n'))\r
- se++;\r
- *se = '\0';\r
-\r
- US_CPrintLine(s);\r
-\r
- s = se;\r
- if (c)\r
- {\r
- *se = c;\r
- s++;\r
- }\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_ClearWindow() - Clears the current window to white and homes the\r
-// cursor\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_ClearWindow(void)\r
-{\r
- VWB_Bar(WindowX,WindowY,WindowW,WindowH,WHITE);\r
- PrintX = WindowX;\r
- PrintY = WindowY;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_DrawWindow() - Draws a frame and sets the current window parms\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_DrawWindow(word x,word y,word w,word h)\r
-{\r
- word i,\r
- sx,sy,sw,sh;\r
-\r
- WindowX = x * 8;\r
- WindowY = y * 8;\r
- WindowW = w * 8;\r
- WindowH = h * 8;\r
-\r
- PrintX = WindowX;\r
- PrintY = WindowY;\r
-\r
- sx = (x - 1) * 8;\r
- sy = (y - 1) * 8;\r
- sw = (w + 1) * 8;\r
- sh = (h + 1) * 8;\r
-\r
- US_ClearWindow();\r
-\r
- VWB_DrawTile8M(sx,sy,0),VWB_DrawTile8M(sx,sy + sh,6);\r
- for (i = sx + 8;i <= sx + sw - 8;i += 8)\r
- VWB_DrawTile8M(i,sy,1),VWB_DrawTile8M(i,sy + sh,7);\r
- VWB_DrawTile8M(i,sy,2),VWB_DrawTile8M(i,sy + sh,8);\r
-\r
- for (i = sy + 8;i <= sy + sh - 8;i += 8)\r
- VWB_DrawTile8M(sx,i,3),VWB_DrawTile8M(sx + sw,i,5);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_CenterWindow() - Generates a window of a given width & height in the\r
-// middle of the screen\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_CenterWindow(word w,word h)\r
-{\r
- US_DrawWindow(((MaxX / 8) - w) / 2,((MaxY / 8) - h) / 2,w,h);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_CenterSaveWindow() - Generates a window of a given width & height in\r
-// the middle of the screen, saving the background\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_CenterSaveWindow(word w,word h,memptr *save)\r
-{\r
- word x,y,\r
- screen;\r
-\r
- x = ((MaxX / 8) - w) / 2;\r
- y = ((MaxY / 8) - h) / 2;\r
- MM_GetPtr(save,(w * h) * CHARWIDTH);\r
- screen = bufferofs + panadjust + ylookup[y] + (x * CHARWIDTH);\r
- VW_ScreenToMem(screen,*save,w * CHARWIDTH,h);\r
- US_DrawWindow(((MaxX / 8) - w) / 2,((MaxY / 8) - h) / 2,w,h);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_RestoreSaveWindow() - Restores the background of the size of the\r
-// current window from the memory specified by save\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_RestoreSaveWindow(memptr *save)\r
-{\r
- word screen;\r
-\r
- screen = bufferofs + panadjust + ylookup[WindowY] + (WindowX * CHARWIDTH);\r
- VW_MemToScreen(*save,screen,WindowW * CHARWIDTH,WindowH);\r
- MM_FreePtr(save);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_SaveWindow() - Saves the current window parms into a record for\r
-// later restoration\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_SaveWindow(WindowRec *win)\r
-{\r
- win->x = WindowX;\r
- win->y = WindowY;\r
- win->w = WindowW;\r
- win->h = WindowH;\r
-\r
- win->px = PrintX;\r
- win->py = PrintY;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_RestoreWindow() - Sets the current window parms to those held in the\r
-// record\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_RestoreWindow(WindowRec *win)\r
-{\r
- WindowX = win->x;\r
- WindowY = win->y;\r
- WindowW = win->w;\r
- WindowH = win->h;\r
-\r
- PrintX = win->px;\r
- PrintY = win->py;\r
-}\r
-\r
-// Cursor routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_StartCursor() - Sets up the cursor for User Mgr use\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_StartCursor(void)\r
-{\r
- CursorInfo info;\r
-\r
- VW_SetCursor(CURSORARROWSPR);\r
- CursorX = MaxX / 2;\r
- CursorY = MaxY / 2;\r
- VW_MoveCursor(CursorX,CursorY);\r
- VW_ShowCursor();\r
-\r
- IN_ReadCursor(&info); // Dispose of any accumulated movement\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_ShutCursor() - Cleans up after US_StartCursor()\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_ShutCursor(void)\r
-{\r
- VW_HideCursor();\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_UpdateCursor() - Gets the new cursor position & button states from\r
-// the Input Mgr and tells the View Mgr where the cursor is\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-US_UpdateCursor(void)\r
-{\r
- CursorInfo info;\r
-\r
- IN_ReadCursor(&info);\r
- if (info.x || info.y || CursorBad)\r
- {\r
- CursorX += info.x;\r
- if (CursorX >= MaxX)\r
- CursorX = MaxX - 1;\r
- else if (CursorX < 0)\r
- CursorX = 0;\r
-\r
- CursorY += info.y;\r
- if (CursorY >= MaxY)\r
- CursorY = MaxY - 1;\r
- else if (CursorY < 0)\r
- CursorY = 0;\r
-\r
- VW_MoveCursor(CursorX,CursorY);\r
- CursorBad = false;\r
- }\r
- Button0 = info.button0;\r
- Button1 = info.button1;\r
- return(Button0 || Button1);\r
-}\r
-\r
-// Input routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_XORICursor() - XORs the I-bar text cursor. Used by US_LineInput()\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_XORICursor(int x,int y,char *s,word cursor)\r
-{\r
- char buf[MaxString];\r
- word w,h;\r
-\r
- strcpy(buf,s);\r
- buf[cursor] = '\0';\r
- USL_MeasureString(buf,&w,&h);\r
-\r
- px = x + w - 1;\r
- py = y;\r
- USL_DrawString("\x80");\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_LineInput() - Gets a line of user input at (x,y), the string defaults\r
-// to whatever is pointed at by def. Input is restricted to maxchars\r
-// chars or maxwidth pixels wide. If the user hits escape (and escok is\r
-// true), nothing is copied into buf, and false is returned. If the\r
-// user hits return, the current string is copied into buf, and true is\r
-// returned\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-US_LineInput(int x,int y,char *buf,char *def,boolean escok,\r
- int maxchars,int maxwidth)\r
-{\r
- boolean redraw,\r
- cursorvis,cursormoved,\r
- done,result;\r
- ScanCode sc;\r
- char c,\r
- s[MaxString],olds[MaxString];\r
- word i,\r
- cursor,\r
- w,h,\r
- len;\r
- longword lasttime;\r
-\r
- VW_HideCursor();\r
-\r
- if (def)\r
- strcpy(s,def);\r
- else\r
- *s = '\0';\r
- *olds = '\0';\r
- cursor = strlen(s);\r
- cursormoved = redraw = true;\r
-\r
- cursorvis = done = false;\r
- lasttime = TimeCount;\r
- LastASCII = key_None;\r
- LastScan = sc_None;\r
-\r
- while (!done)\r
- {\r
- if (cursorvis)\r
- USL_XORICursor(x,y,s,cursor);\r
-\r
- asm pushf\r
- asm cli\r
-\r
- sc = LastScan;\r
- LastScan = sc_None;\r
- c = LastASCII;\r
- LastASCII = key_None;\r
-\r
- asm popf\r
-\r
- switch (sc)\r
- {\r
- case sc_LeftArrow:\r
- if (cursor)\r
- cursor--;\r
- c = key_None;\r
- cursormoved = true;\r
- break;\r
- case sc_RightArrow:\r
- if (s[cursor])\r
- cursor++;\r
- c = key_None;\r
- cursormoved = true;\r
- break;\r
- case sc_Home:\r
- cursor = 0;\r
- c = key_None;\r
- cursormoved = true;\r
- break;\r
- case sc_End:\r
- cursor = strlen(s);\r
- c = key_None;\r
- cursormoved = true;\r
- break;\r
-\r
- case sc_Return:\r
- strcpy(buf,s);\r
- done = true;\r
- result = true;\r
- c = key_None;\r
- break;\r
- case sc_Escape:\r
- if (escok)\r
- {\r
- done = true;\r
- result = false;\r
- }\r
- c = key_None;\r
- break;\r
-\r
- case sc_BackSpace:\r
- if (cursor)\r
- {\r
- strcpy(s + cursor - 1,s + cursor);\r
- cursor--;\r
- redraw = true;\r
- }\r
- c = key_None;\r
- cursormoved = true;\r
- break;\r
- case sc_Delete:\r
- if (s[cursor])\r
- {\r
- strcpy(s + cursor,s + cursor + 1);\r
- redraw = true;\r
- }\r
- c = key_None;\r
- cursormoved = true;\r
- break;\r
-\r
- case 0x4c: // Keypad 5\r
- case sc_UpArrow:\r
- case sc_DownArrow:\r
- case sc_PgUp:\r
- case sc_PgDn:\r
- case sc_Insert:\r
- c = key_None;\r
- break;\r
- }\r
-\r
- if (c)\r
- {\r
- len = strlen(s);\r
- USL_MeasureString(s,&w,&h);\r
-\r
- if\r
- (\r
- isprint(c)\r
- && (len < MaxString - 1)\r
- && ((!maxchars) || (len < maxchars))\r
- && ((!maxwidth) || (w < maxwidth))\r
- )\r
- {\r
- for (i = len + 1;i > cursor;i--)\r
- s[i] = s[i - 1];\r
- s[cursor++] = c;\r
- redraw = true;\r
- }\r
- }\r
-\r
- if (redraw)\r
- {\r
- px = x;\r
- py = y;\r
- USL_DrawString(olds);\r
- strcpy(olds,s);\r
-\r
- px = x;\r
- py = y;\r
- USL_DrawString(s);\r
-\r
- redraw = false;\r
- }\r
-\r
- if (cursormoved)\r
- {\r
- cursorvis = false;\r
- lasttime = TimeCount - TickBase;\r
-\r
- cursormoved = false;\r
- }\r
- if (TimeCount - lasttime > TickBase / 2)\r
- {\r
- lasttime = TimeCount;\r
-\r
- cursorvis ^= true;\r
- }\r
- if (cursorvis)\r
- USL_XORICursor(x,y,s,cursor);\r
-\r
- VW_UpdateScreen();\r
- }\r
-\r
- if (cursorvis)\r
- USL_XORICursor(x,y,s,cursor);\r
- if (!result)\r
- {\r
- px = x;\r
- py = y;\r
- USL_DrawString(olds);\r
- }\r
- VW_ShowCursor();\r
- VW_UpdateScreen();\r
-\r
- IN_ClearKeysDown();\r
- return(result);\r
-}\r
-\r
-// Control panel routines\r
-\r
-static boolean FlushHelp;\r
-static WindowRec HelpWindow,BottomWindow;\r
-typedef enum\r
- {\r
- uic_Draw,uic_Hit\r
- } UserCall;\r
-typedef enum\r
- {\r
- uii_Bad,uii_Button,uii_RadioButton,uii_CheckBox,uii_KeyCap\r
- } UIType;\r
-#define ui_Normal 0\r
-#define ui_Selected 1\r
-#define ui_Disabled 2\r
-\r
- // Prototype the custom routines\r
-static boolean USL_CtlButtonCustom(UserCall,word,word),\r
- USL_CtlPButtonCustom(UserCall,word,word),\r
- USL_CtlPSButtonCustom(UserCall,word,word),\r
- USL_CtlPRButtonCustom(UserCall,word,word),\r
- USL_CtlHButtonCustom(UserCall,word,word),\r
- USL_CtlDButtonCustom(UserCall,word,word),\r
- USL_CtlDEButtonCustom(UserCall,word,word),\r
- USL_CtlDLButtonCustom(UserCall,word,word),\r
- USL_CtlDSButtonCustom(UserCall,word,word),\r
- USL_CtlSButtonCustom(UserCall,word,word),\r
- USL_CtlCButtonCustom(UserCall,word,word),\r
- USL_CtlCKbdButtonCustom(UserCall,word,word),\r
- USL_CtlCJoyButtonCustom(UserCall,word,word);\r
-\r
- // The structure of a user interaction item\r
-typedef struct {\r
- Rect r; // The enclosing rectangle\r
- UIType type; // The type of item\r
- int picup,picdown; // What to draw when up/down\r
- char *help; // Floating help string\r
- ScanCode key; // Key equiv\r
- word sel; // Interaction flags (ui_XXX)\r
- boolean (*custom)(UserCall,word,word); // Custom routine\r
- char *text; // Text for some items\r
- } UserItem;\r
-typedef struct {\r
- ScanCode key;\r
- word i,n, // Hit CtlPanels2[i][n]\r
- toi,ton; // Move to CtlPanels2[toi][ton]\r
- } HotKey; // MARK\r
-\r
-static ScanCode *KeyMaps[] =\r
- {\r
- &KbdDefs[0].button0,&KbdDefs[0].button1,\r
- &KbdDefs[0].upleft,&KbdDefs[0].up,&KbdDefs[0].upright,\r
- &KbdDefs[0].left, &KbdDefs[0].right,\r
- &KbdDefs[0].downleft,&KbdDefs[0].down,&KbdDefs[0].downright,\r
- };\r
-\r
-// Some macros to make rectangle definition quite a bit less unpleasant\r
-#define CtlPanelX 8\r
-#define CtlPanelY 4\r
-#define CtlPanel2X (8*8)\r
-#define CtlPanel2Y (2*8)\r
-#define CtlPanel3X (8*8)\r
-#define CtlPanel3Y (7*8)\r
-\r
-#define CtlPanelR(n) { CtlPanelX,CtlPanelY+(32 * (n)),\\r
- CtlPanelX+40,CtlPanelY+(32 * (n)) + 32}\r
-#define CtlPanel2R(x,y) { CtlPanel2X+(x)*8,CtlPanel2Y+(y)*8,\\r
- CtlPanel2X+32+(x)*8,CtlPanel2Y+24+(y)*8}\r
-#define CtlPanel3R(x,y) { CtlPanel3X+(x)*8,CtlPanel3Y+(y)*8,\\r
- CtlPanel3X+32+(x)*8,CtlPanel3Y+24+(y)*8}\r
-static UserItem CtlPanels[] =\r
- {\r
-{CtlPanelR(0),uii_RadioButton,CTL_STARTUPPIC,CTL_STARTDNPIC,"Start or Resume a Game",sc_None,ui_Normal,USL_CtlButtonCustom},\r
-{CtlPanelR(1),uii_RadioButton,CTL_HELPUPPIC,CTL_HELPDNPIC,"Get Help With Commander Keen",sc_None,ui_Normal,USL_CtlButtonCustom},\r
-{CtlPanelR(2),uii_RadioButton,CTL_DISKUPPIC,CTL_DISKDNPIC,"Load / Save / Quit",sc_None,ui_Normal,USL_CtlButtonCustom},\r
-{CtlPanelR(3),uii_RadioButton,CTL_CONTROLSUPPIC,CTL_CONTROLSDNPIC,"Choose Controls",sc_C,ui_Normal,USL_CtlButtonCustom},\r
-{CtlPanelR(4),uii_RadioButton,CTL_SOUNDUPPIC,CTL_SOUNDDNPIC,"Select Sound Device",sc_F2,ui_Normal,USL_CtlButtonCustom},\r
-{CtlPanelR(5),uii_RadioButton,CTL_MUSICUPPIC,CTL_MUSICDNPIC,"Turn Music On / Off",sc_F7,ui_Normal,USL_CtlButtonCustom},\r
-{-1,-1,-1,-1,uii_Bad}\r
- },\r
- CtlPPanels[] =\r
- {\r
-{CtlPanel2R(10,0),uii_RadioButton,CTL_P_NEWGAMEUPPIC,CTL_P_NEWGAMEDNPIC,"Choose Difficulty for the New Game",sc_F5,ui_Normal,USL_CtlPButtonCustom},\r
-{CtlPanel2R(15,0),uii_RadioButton,CTL_P_RESUMEUPPIC,CTL_P_RESUMEDNPIC,"Go Back to Current Game",sc_None,ui_Normal,USL_CtlPButtonCustom},\r
-{-1,-1,-1,-1,uii_Bad}\r
- },\r
- CtlPSPanels[] =\r
- {\r
-{CtlPanel3R(13,5),uii_Button,CTL_P_MEDUPPIC,CTL_P_MEDDNPIC,"Start New Game in Normal Mode",sc_None,ui_Normal,USL_CtlPSButtonCustom},\r
-{CtlPanel3R(8,5),uii_Button,CTL_P_EASYUPPIC,CTL_P_EASYDNPIC,"Start New Game in Easy Mode",sc_None,ui_Normal,USL_CtlPSButtonCustom},\r
-{CtlPanel3R(18,5),uii_Button,CTL_P_HARDUPPIC,CTL_P_HARDDNPIC,"Start New Game in Hard Mode",sc_None,ui_Normal,USL_CtlPSButtonCustom},\r
-{-1,-1,-1,-1,uii_Bad}\r
- },\r
- CtlPRPanels[] =\r
- {\r
-{CtlPanel3R(13,5),uii_Button,CTL_P_GORESUMEUPPIC,CTL_P_GORESUMEDNPIC,"Resume Current Game",sc_None,ui_Normal,USL_CtlPRButtonCustom},\r
-{-1,-1,-1,-1,uii_Bad}\r
- },\r
- CtlHPanels[] =\r
- {\r
-{CtlPanel2R(8,0),uii_Button,CTL_H_LOSTUPPIC,CTL_H_LOSTDNPIC,"Help Me, I'm Lost!",sc_F1,ui_Normal,USL_CtlHButtonCustom},\r
-{CtlPanel2R(13,0),uii_Button,CTL_H_CTRLUPPIC,CTL_H_CTRLDNPIC,"Get Help with Controls",sc_None,ui_Normal,USL_CtlHButtonCustom},\r
-{CtlPanel2R(18,0),uii_Button,CTL_H_STORYUPPIC,CTL_H_STORYDNPIC,"Read Story & Game Tips",sc_None,ui_Normal,USL_CtlHButtonCustom},\r
-{-1,-1,-1,-1,uii_Bad}\r
- },\r
- CtlDPanels[] =\r
- {\r
-{CtlPanel2R(9,0),uii_RadioButton,CTL_D_LSGAMEUPPIC,CTL_D_LSGAMEDNPIC,"Load or Save a Game",sc_F6,ui_Normal,USL_CtlDButtonCustom},\r
-{CtlPanel2R(15,0),uii_RadioButton,CTL_D_DOSUPPIC,CTL_D_DOSDNPIC,"Exit to DOS",sc_Q,ui_Normal,USL_CtlDButtonCustom},\r
-{-1,-1,-1,-1,uii_Bad}\r
- },\r
- CtlDLSPanels[] =\r
- {\r
-#define CtlPanel3LSR(x,y) { CtlPanel3X+(x)*8,CtlPanel3Y+(y)*8,\\r
- CtlPanel3X+32+(x)*8,CtlPanel3Y+16+(y)*8}\r
-{CtlPanel3LSR(1,0),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},\r
-{CtlPanel3LSR(6,0),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},\r
-{CtlPanel3LSR(1,2),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},\r
-{CtlPanel3LSR(6,2),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},\r
-{CtlPanel3LSR(1,4),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},\r
-{CtlPanel3LSR(6,4),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},\r
-{CtlPanel3LSR(1,6),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},\r
-{CtlPanel3LSR(6,6),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},\r
-{CtlPanel3LSR(1,8),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},\r
-{CtlPanel3LSR(6,8),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},\r
-{CtlPanel3LSR(1,10),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},\r
-{CtlPanel3LSR(6,10),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},\r
-{CtlPanel3LSR(1,12),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},\r
-{CtlPanel3LSR(6,12),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},\r
-{-1,-1,-1,-1,uii_Bad}\r
- },\r
- CtlDEPanels[] =\r
- {\r
-#define CtlPanel3ER(x,y) { CtlPanel3X+(x)*8,CtlPanel3Y+(y)*8,\\r
- CtlPanel3X+40+(x)*8,CtlPanel3Y+24+(y)*8}\r
-{CtlPanel3ER(12,5),uii_Button,CTL_D_EXITUPPIC,CTL_D_EXITDNPIC,"Really Exit to DOS",sc_None,ui_Normal,USL_CtlDEButtonCustom},\r
-{-1,-1,-1,-1,uii_Bad}\r
- },\r
- CtlCPanels[] =\r
- {\r
-{CtlPanel2R(8,0),uii_RadioButton,CTL_C_KBDUPPIC,CTL_C_KBDDNPIC,"Use / Configure Keyboard",sc_F3,ui_Normal,USL_CtlCButtonCustom},\r
-{CtlPanel2R(13,0),uii_RadioButton,CTL_C_JOY1UPPIC,CTL_C_JOY1DNPIC,"Use / Configure Joystick 1",sc_None,ui_Normal,USL_CtlCButtonCustom},\r
-{CtlPanel2R(18,0),uii_RadioButton,CTL_C_JOY2UPPIC,CTL_C_JOY2DNPIC,"Use / Configure Joystick 2",sc_None,ui_Normal,USL_CtlCButtonCustom},\r
-{-1,-1,-1,-1,uii_Bad}\r
- },\r
-#define CtlPanelKC3R(x,y) { CtlPanel3X+(x)*8,CtlPanel3Y+(y)*8,\\r
- CtlPanel3X+56+(x)*8,CtlPanel3Y+32+(y)*8}\r
- CtlCKbdPanels[] =\r
- {\r
-{CtlPanelKC3R(1,2),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key for Jumping",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
-{CtlPanelKC3R(1,6),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key for Throwing",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
-{CtlPanelKC3R(8,0),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Up & Left",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
-{CtlPanelKC3R(15,0),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Up",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
-{CtlPanelKC3R(22,0),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Up & Right",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
-{CtlPanelKC3R(8,4),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Left",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
-{CtlPanelKC3R(22,4),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Right",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
-{CtlPanelKC3R(8,8),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Down & Left",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
-{CtlPanelKC3R(15,8),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Down",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
-{CtlPanelKC3R(22,8),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Down & Right",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},\r
-{-1,-1,-1,-1,uii_Bad}\r
- },\r
- CtlCJoyPanels[] =\r
- {\r
-{CtlPanel3R(13,5),uii_Button,CTL_C_CALIBRATEUPPIC,CTL_C_CALIBRATEDNPIC,"Configure Joystick",sc_None,ui_Normal,USL_CtlCJoyButtonCustom},\r
-{-1,-1,-1,-1,uii_Bad}\r
- },\r
- CtlSPanels[] =\r
- {\r
-{CtlPanel2R(3,0),uii_RadioButton,CTL_S_NOSNDUPPIC,CTL_S_NOSNDDNPIC,"Turn Sound Off",sc_None,ui_Normal,USL_CtlSButtonCustom},\r
-{CtlPanel2R(8,0),uii_RadioButton,CTL_S_PCSNDUPPIC,CTL_S_PCSNDDNPIC,"Use PC Speaker",sc_None,ui_Normal,USL_CtlSButtonCustom},\r
-{CtlPanel2R(13,0),uii_RadioButton,CTL_S_ADLIBUPPIC,CTL_S_ADLIBDNPIC,"Use AdLib Sound Effects",sc_None,ui_Normal,USL_CtlSButtonCustom},\r
-{CtlPanel2R(18,0),uii_RadioButton,CTL_S_SNDBLUPPIC,CTL_S_SNDBLDNPIC,"Use SoundBlaster Sound Effects",sc_None,ui_Normal,USL_CtlSButtonCustom},\r
-{CtlPanel2R(23,0),uii_RadioButton,CTL_S_SNDSRCUPPIC,CTL_S_SNDSRCDNPIC,"Use Sound Source Sound Effects",sc_None,ui_Normal,USL_CtlSButtonCustom},\r
-{-1,-1,-1,-1,uii_Bad}\r
- },\r
- CtlSSSPanels[] =\r
- {\r
-{CtlPanel3R(7,2),uii_CheckBox,CTL_CHECKUPPIC,CTL_CHECKDNPIC,"Turn Tandy Mode On / Off",sc_None,ui_Normal,0,"Tandy Mode"},\r
-{CtlPanel3R(7,6),uii_CheckBox,CTL_CHECKUPPIC,CTL_CHECKDNPIC,"Switch between LPT1 & LPT2",sc_None,ui_Normal,0,"Use LPT2"},\r
-{-1,-1,-1,-1,uii_Bad}\r
- },\r
- CtlMPanels[] =\r
- {\r
-{CtlPanel2R(9,0),uii_RadioButton,CTL_M_NOMUSUPPIC,CTL_M_NOMUSDNPIC,"Background Music Off"},\r
-{CtlPanel2R(15,0),uii_RadioButton,CTL_M_ADLIBUPPIC,CTL_M_ADLIBDNPIC,"Use AdLib/SoundBlaster Music"},\r
-{-1,-1,-1,-1,uii_Bad}\r
- },\r
- *CtlPanels2[] =\r
- {\r
- CtlPPanels, // Start\r
- CtlHPanels, // Help\r
- CtlDPanels, // Disk\r
- CtlCPanels, // Controls\r
- CtlSPanels, // Sound\r
- CtlMPanels // Music\r
- },\r
- *TheItems[4] = {CtlPanels};\r
-static int CtlPanelButton;\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_TurnOff() - Goes through a list of UserItems and sets them all to\r
-// the normal state\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_TurnOff(UserItem *ip)\r
-{\r
- while (ip->type != uii_Bad)\r
- {\r
- ip->sel = ui_Normal;\r
- ip++;\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_FindDown() - Finds which UserItem, if any, is selected in the given\r
-// list\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static int\r
-USL_FindDown(UserItem *ip)\r
-{\r
- int i;\r
-\r
- for (i = 0;ip->type != uii_Bad;i++,ip++)\r
- if (ip->sel & ui_Selected)\r
- return(i);\r
- return(-1);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_ShowHelp() - Shows the specified string in the help window\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_ShowHelp(char *s)\r
-{\r
- WindowRec wr;\r
-\r
- if (!s)\r
- return;\r
-\r
- US_SaveWindow(&wr);\r
- US_RestoreWindow(&HelpWindow);\r
-\r
- US_ClearWindow();\r
- US_PrintCentered(s);\r
-\r
- US_RestoreWindow(&wr);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_HandleError() - Handles telling the user that there's been an error\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_HandleError(int num)\r
-{\r
- char buf[64];\r
-\r
- strcpy(buf,"Error: ");\r
- if (num < 0)\r
- strcat(buf,"Unknown");\r
- else if (num == ENOMEM)\r
- strcat(buf,"Disk is Full");\r
- else if (num == EINVFMT)\r
- strcat(buf,"File is Incomplete");\r
- else\r
- strcat(buf,sys_errlist[num]);\r
-\r
- VW_HideCursor();\r
-\r
- fontcolor = F_SECONDCOLOR;\r
- USL_ShowHelp(buf);\r
- fontcolor = F_BLACK;\r
- VW_UpdateScreen();\r
-\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- VW_ShowCursor();\r
- VW_UpdateScreen();\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_DrawItem() - Draws a UserItem. If there's a custom routine, this will\r
-// call it with a uic_Draw command. If the custom routine returns true,\r
-// then the routine handled all of the drawing. If it returns false,\r
-// then this routine does the default drawing.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_DrawItem(word hiti,word hitn)\r
-{\r
- boolean handled,centered;\r
- char *text;\r
- word w,h;\r
- int picup,picdown;\r
- Rect r;\r
- UserItem *ip;\r
-\r
- ip = &TheItems[hiti][hitn];\r
- if (ip->custom)\r
- handled = ip->custom(uic_Draw,hiti,hitn);\r
- else\r
- handled = false;\r
-\r
- if (!handled)\r
- {\r
- picup = ip->picup;\r
- picdown = ip->picdown;\r
- switch (ip->type)\r
- {\r
- case uii_CheckBox:\r
- px = ip->r.lr.x + 8;\r
- py = ip->r.ul.y + 8;\r
- text = ip->text;\r
- centered = false;\r
- break;\r
- case uii_KeyCap:\r
- if (!(ip->sel & ui_Selected))\r
- {\r
- text = ip->text;\r
- if (text)\r
- {\r
- r = ip->r;\r
- centered = true;\r
- }\r
- }\r
- else\r
- text = nil;\r
- break;\r
- default:\r
- text = nil;\r
- break;\r
- }\r
-\r
- VWB_DrawPic(ip->r.ul.x,ip->r.ul.y,\r
- (ip->sel & ui_Selected)? picdown : picup);\r
- if (text)\r
- {\r
- if (centered)\r
- USL_PrintInCenter(text,r);\r
- else\r
- {\r
- USL_MeasureString(text,&w,&h);\r
- VWB_Bar(px,py,w + 7,h,WHITE);\r
- USL_DrawString(text);\r
- }\r
- }\r
- if (ip->sel & ui_Disabled)\r
- {\r
- if ((picup == CTL_D_LOADUPPIC) || (picup == CTL_D_SAVEUPPIC))\r
- VWB_DrawMPic(ip->r.ul.x,ip->r.ul.y,CTL_LSMASKPICM);\r
- else\r
- VWB_DrawMPic(ip->r.ul.x,ip->r.ul.y,CTL_LITTLEMASKPICM);\r
- }\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_DoHit() - Handles a hit on a UserItem. If there's a custom routine,\r
-// it will be called. If it returns true, then don't do anything\r
-// more. If it returns false, then use the standard behaviour\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_DoHit(word hiti,word hitn)\r
-{\r
- boolean handled;\r
- word i;\r
- UserItem *ip;\r
-\r
- ip = &TheItems[hiti][hitn];\r
- if (ip->custom)\r
- handled = ip->custom(uic_Hit,hiti,hitn);\r
- else\r
- handled = false;\r
-\r
- if (!handled)\r
- {\r
- if (TheItems[hiti][hitn].sel & ui_Disabled)\r
- {\r
- fontcolor = F_SECONDCOLOR;\r
- USL_ShowHelp("This Item is Disabled");\r
- fontcolor = F_BLACK;\r
- return;\r
- }\r
-\r
- FlushHelp = true;\r
-\r
- switch (ip->type)\r
- {\r
- case uii_Button:\r
- // Must have a custom routine to handle hits - this just redraws\r
- ip->sel ^= ui_Selected;\r
- USL_DrawItem(hiti,hitn);\r
- case uii_CheckBox:\r
- ip->sel ^= ui_Selected;\r
- USL_DrawItem(hiti,hitn);\r
- break;\r
- case uii_RadioButton:\r
- for (i = 0,ip = TheItems[hiti];ip->type != uii_Bad;i++,ip++)\r
- {\r
- if\r
- (\r
- (i != hitn)\r
- && (ip->type == uii_RadioButton)\r
- && (ip->sel & ui_Selected)\r
- )\r
- {\r
- ip->sel &= ~ui_Selected;\r
- USL_DrawItem(hiti,i);\r
- }\r
- }\r
- TheItems[hiti][hitn].sel |= ui_Selected;\r
- USL_DrawItem(hiti,hitn);\r
- break;\r
- case uii_KeyCap:\r
- break;\r
- }\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_IsInRect() - Checks to see if the coordinates given are within any\r
-// of the Rects in the UserItem list. If so, returns true & sets the\r
-// index & number for lookup. If not, returns false.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-USL_IsInRect(word x,word y,word *index,word *number)\r
-{\r
- UserItem *item,**items;\r
-\r
- items = TheItems;\r
- *index = 0;\r
- while (*items)\r
- {\r
- item = *items;\r
- *number = 0;\r
- while (item->type != uii_Bad)\r
- {\r
- if\r
- (\r
- (x >= item->r.ul.x)\r
- && (x < item->r.lr.x)\r
- && (y >= item->r.ul.y)\r
- && (y < item->r.lr.y)\r
- )\r
- return(true);\r
- (*number)++;\r
- item++;\r
- }\r
-\r
- (*index)++;\r
- items++;\r
- }\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_TrackItem() - Tracks the given item. If the cursor is inside of the\r
-// item, it's redrawn as down. If the cursor is outside, the item is\r
-// drawn in its original state. Returns true if the button was released\r
-// while the cursor was inside the item, or false if it wasn't.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-USL_TrackItem(word hiti,word hitn)\r
-{\r
- boolean inside,last;\r
- word ini,inn,\r
- on,\r
- sel,othersel;\r
- UserItem *ip,*op;\r
-\r
- ip = &TheItems[hiti][hitn];\r
- sel = ip->sel;\r
- if (ip->type == uii_RadioButton)\r
- {\r
- inside = false;\r
- for (op = TheItems[hiti],on = 0;op->type != uii_Bad;op++,on++)\r
- {\r
- if (op->sel & ui_Selected)\r
- {\r
- inside = true;\r
- break;\r
- }\r
- }\r
- if (!inside)\r
- op = ip;\r
- othersel = op->sel;\r
- }\r
- else\r
- op = nil;\r
-\r
- if (ip->sel & ui_Disabled)\r
- {\r
- fontcolor = F_SECONDCOLOR;\r
- USL_ShowHelp("This item is disabled");\r
- fontcolor = F_BLACK;\r
-\r
- while (US_UpdateCursor())\r
- VW_UpdateScreen();\r
-\r
- FlushHelp = true;\r
- return(false);\r
- }\r
-\r
- last = false;\r
- do\r
- {\r
- USL_IsInRect(CursorX,CursorY,&ini,&inn);\r
- inside = (ini == hiti) && (inn == hitn);\r
- if (inside != last)\r
- {\r
- if (inside)\r
- {\r
- if (op)\r
- {\r
- op->sel &= ~ui_Selected;\r
- ip->sel |= ui_Selected;\r
- }\r
- else\r
- ip->sel = sel ^ ui_Selected;\r
- }\r
- else\r
- {\r
- if (op && (op != ip))\r
- {\r
- op->sel |= ui_Selected;\r
- ip->sel &= ~ui_Selected;\r
- }\r
- else\r
- ip->sel = sel;\r
- }\r
-\r
- USL_DrawItem(hiti,hitn);\r
- if (op && (op != ip))\r
- USL_DrawItem(hiti,on);\r
-\r
- last = inside;\r
- }\r
- VW_UpdateScreen();\r
- } while (US_UpdateCursor());\r
-\r
- if (op)\r
- op->sel = othersel;\r
- ip->sel = sel;\r
- if (!inside)\r
- {\r
- if (op && (op != ip))\r
- USL_DrawItem(hiti,on);\r
- USL_DrawItem(hiti,hitn);\r
- VW_UpdateScreen();\r
- }\r
-\r
- return(inside);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_GlideCursor() - Smoothly moves the cursor to the given location\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_GlideCursor(long newx,long newy)\r
-{\r
- word steps;\r
- long x,y,\r
- dx,dy;\r
-\r
- if (grmode == CGAGR)\r
- steps = 1;\r
- else\r
- steps = 8;\r
-\r
- x = (long)CursorX << 16;\r
- dx = ((newx << 16) - x) / steps;\r
- y = (long)CursorY << 16;\r
- dy = ((newy << 16) - y) / steps;\r
-\r
- while ((CursorX != newx) || (CursorY != newy))\r
- {\r
- x += dx;\r
- y += dy;\r
-\r
- CursorX = x >> 16;\r
- CursorY = y >> 16;\r
- VW_MoveCursor(CursorX,CursorY);\r
- VW_UpdateScreen();\r
- }\r
- CursorBad = true;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_FindRect() - Code so ugly you'll puke! Given a Rect and direction,\r
-// this routine will try to find a UserItem to move the cursor to\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_FindRect(Rect r,Motion xd,Motion yd)\r
-{\r
- word i,i1,i2,i3;\r
- Motion m1,m2;\r
- Point diffs[9],diff,*dp;\r
- Rect *rp,*good,*goods[9];\r
- UserItem *ip,**items;\r
-\r
- for (m1 = motion_Up,dp = diffs;m1 <= motion_Down;m1++)\r
- {\r
- for (m2 = motion_Left;m2 <= motion_Right;m2++,dp++)\r
- {\r
- dp->x = m2 * 1024;\r
- dp->y = m1 * 1024;\r
- }\r
- }\r
- for (i = 0;i < 9;i++)\r
- goods[i] = nil;\r
-\r
- // Find out which octants all of the rects (except r) are in\r
- for (items = TheItems;*items;items++)\r
- {\r
- for (ip = *items;ip->type != uii_Bad;ip++)\r
- {\r
- rp = &ip->r;\r
- diff.x = rp->ul.x - r.ul.x;\r
- diff.y = rp->ul.y - r.ul.y;\r
- if (!(diff.x || diff.y))\r
- continue;\r
-\r
- if // 1,4,7\r
- (\r
- ((rp->ul.x >= r.ul.x) && (rp->ul.x < r.lr.x))\r
- || ((rp->lr.x > r.ul.x) && (rp->lr.x <= r.lr.x))\r
- )\r
- {\r
- if (rp->lr.y <= r.ul.y)\r
- {\r
- if (!(goods[1] && (diff.y < diffs[1].y)))\r
- {\r
- goods[1] = rp;\r
- diffs[1] = diff;\r
- }\r
- }\r
- else if (rp->ul.y >= r.lr.y)\r
- {\r
- if (!(goods[7] && (diff.y > diffs[7].y)))\r
- {\r
- goods[7] = rp;\r
- diffs[7] = diff;\r
- }\r
- }\r
- }\r
-\r
- if // 3,4,5\r
- (\r
- ((rp->ul.y >= r.ul.y) && (rp->ul.y < r.lr.y))\r
- || ((rp->lr.y > r.ul.y) && (rp->lr.y <= r.lr.y))\r
- )\r
- {\r
- if (rp->lr.x <= r.ul.x)\r
- {\r
- if (!(goods[3] && (diff.x < diffs[3].x)))\r
- {\r
- goods[3] = rp;\r
- diffs[3] = diff;\r
- }\r
- }\r
- else if (rp->ul.x >= r.lr.x)\r
- {\r
- if (!(goods[5] && (diff.x > diffs[5].x)))\r
- {\r
- goods[5] = rp;\r
- diffs[5] = diff;\r
- }\r
- }\r
- }\r
-\r
- if (rp->ul.x < r.ul.x) // 0,6\r
- {\r
- if (rp->lr.y <= r.ul.y)\r
- {\r
- if\r
- (\r
- (!goods[0])\r
- || (diff.y > diffs[0].y)\r
- || (diff.x > diffs[6].x)\r
- )\r
- {\r
- goods[0] = rp;\r
- diffs[0] = diff;\r
- }\r
- }\r
- else if (rp->ul.y >= r.lr.y)\r
- {\r
- if\r
- (\r
- (!goods[6])\r
- || (diff.y < diffs[6].y)\r
- || (diff.x > diffs[6].x)\r
- )\r
- {\r
- goods[6] = rp;\r
- diffs[6] = diff;\r
- }\r
- }\r
- }\r
-\r
- if (rp->lr.x > r.lr.x) // 2,8\r
- {\r
- if (rp->lr.y <= r.ul.y)\r
- {\r
- if\r
- (\r
- (!goods[2])\r
- || (diff.y > diffs[2].y)\r
- || (diff.x < diffs[2].x)\r
- )\r
- {\r
- goods[2] = rp;\r
- diffs[2] = diff;\r
- }\r
- }\r
- else if (rp->ul.y >= r.lr.y)\r
- {\r
- if\r
- (\r
- (!goods[8])\r
- || (diff.y < diffs[8].y)\r
- || (diff.x < diffs[8].x)\r
- )\r
- {\r
- goods[8] = rp;\r
- diffs[8] = diff;\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- switch (yd)\r
- {\r
- case motion_Up:\r
- i1 = 1,i2 = 0,i3 = 2;\r
- break;\r
- case motion_None:\r
- switch (xd)\r
- {\r
- case motion_Left:\r
- i1 = 3,i2 = 0,i3 = 6;\r
- break;\r
- case motion_Right:\r
- i1 = 5,i2 = 8,i3 = 2;\r
- break;\r
- }\r
- break;\r
- case motion_Down:\r
- i1 = 7,i2 = 8,i3 = 6;\r
- break;\r
- }\r
-\r
- (\r
- (good = goods[i1])\r
- || (good = goods[i2])\r
- || (good = goods[i3])\r
- || (good = &r)\r
- );\r
-#if 0\r
- CursorX = good->lr.x - 8;\r
- CursorY = good->lr.y - 8;\r
- CursorBad = true;\r
- US_UpdateCursor();\r
-#endif\r
- USL_GlideCursor(good->lr.x - 8,good->lr.y - 8);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_CtlButtonCustom() - The custom routine for all of the Control Panel\r
-// (leftmost) buttons. Clears all of the other item lists, clears the\r
-// large area, and draws the line dividing the top and bottom areas.\r
-// Then it sets up and draws the appropriate top row of icons.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-USL_CtlButtonCustom(UserCall call,word i,word n)\r
-{\r
- word j;\r
- UserItem *ip;\r
-\r
- if (call != uic_Hit)\r
- return(false);\r
-\r
- if (n == CtlPanelButton)\r
- return(true);\r
-\r
- US_ClearWindow();\r
- for (j = 8;j < 38;j++)\r
- {\r
- VWB_DrawTile8M(j * 8,6 * 8,10);\r
- VWB_DrawTile8M(j * 8,21 * 8,10);\r
- }\r
- VWB_DrawTile8M(7 * 8,6 * 8,9);\r
- VWB_DrawTile8M(38 * 8,6 * 8,11);\r
- VWB_DrawTile8M(7 * 8,21 * 8,9);\r
- VWB_DrawTile8M(38 * 8,21 * 8,11);\r
-\r
- for (j = 1;j < 4;j++)\r
- TheItems[j] = nil;\r
-\r
- // Set to new button\r
- CtlPanelButton = n;\r
-\r
- // Draw new items\r
- TheItems[1] = ip = CtlPanels2[CtlPanelButton];\r
- j = 0;\r
- while (ip && (ip->type != uii_Bad))\r
- {\r
- USL_DrawItem(i + 1,j);\r
- if (ip->sel & ui_Selected)\r
- USL_DoHit(i + 1,j);\r
- j++;\r
- ip++;\r
- }\r
-\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_CtlCKbdButtonCustom() - The custom routine for the keyboard keycaps.\r
-// This routine gets a scancode and puts it in the appropriate\r
-// KbdDefs[0] member.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-USL_CtlCKbdButtonCustom(UserCall call,word i,word n)\r
-{\r
- boolean state;\r
- word j;\r
- ScanCode scan;\r
- longword time;\r
- UserItem *ip;\r
-\r
- if (call != uic_Hit)\r
- return(false);\r
-\r
- ip = &TheItems[i][n];\r
-\r
- fontcolor = F_SECONDCOLOR;\r
- USL_ShowHelp(ip->help);\r
- fontcolor = F_BLACK;\r
- VW_HideCursor();\r
- VWB_DrawPic(ip->r.ul.x,ip->r.ul.y,ip->picdown);\r
- VW_UpdateScreen();\r
-\r
- LastScan = sc_None;\r
- time = TimeCount;\r
- state = true;\r
- do\r
- {\r
- if (TimeCount - time > 35) // Half-second delays\r
- {\r
- state ^= true;\r
- VWB_DrawPic(ip->r.ul.x,ip->r.ul.y,state? ip->picdown : ip->picup);\r
- VW_UpdateScreen();\r
- time = TimeCount;\r
- }\r
- if (US_UpdateCursor())\r
- {\r
- while (US_UpdateCursor())\r
- ;\r
- scan = sc_Escape;\r
- break;\r
- }\r
-\r
- asm pushf\r
- asm cli\r
- if (LastScan == sc_LShift)\r
- LastScan = sc_None;\r
- asm popf\r
- } while (!(scan = LastScan));\r
- IN_ClearKey(scan);\r
- if (scan != sc_Escape)\r
- {\r
- for (j = 0,state = false;j < 10;j++)\r
- {\r
- if (j == n)\r
- continue;\r
- if (*(KeyMaps[j]) == scan)\r
- {\r
- state = true;\r
- break;\r
- }\r
- }\r
- if (state)\r
- {\r
- fontcolor = F_SECONDCOLOR;\r
- USL_ShowHelp("That Key is Already Used!");\r
- fontcolor = F_BLACK;\r
- }\r
- else\r
- {\r
- ip->text = IN_GetScanName(scan);\r
- *(KeyMaps[n]) = scan;\r
- FlushHelp = true;\r
- }\r
- }\r
-\r
- USL_DrawItem(i,n);\r
- VW_ShowCursor();\r
- VW_UpdateScreen();\r
-\r
- return(true);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_CtlCJoyButtonCustom() - The custom button routine for joystick\r
-// calibration\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-USL_CtlCJoyButtonCustom(UserCall call,word i,word n)\r
-{\r
- word joy,\r
- minx,maxx,\r
- miny,maxy;\r
-\r
- i++,n++; // Shut the compiler up\r
-\r
- if (call != uic_Hit)\r
- return(false);\r
-\r
- IN_ClearKeysDown();\r
- joy = USL_FindDown(CtlCPanels) - 1;\r
-\r
- VW_HideCursor();\r
- FlushHelp = true;\r
- fontcolor = F_SECONDCOLOR;\r
-\r
- USL_ShowHelp("Move Joystick to the Upper-Left");\r
- VW_UpdateScreen();\r
- while ((LastScan != sc_Escape) && !IN_GetJoyButtonsDB(joy))\r
- ;\r
- if (LastScan != sc_Escape)\r
- {\r
- IN_GetJoyAbs(joy,&minx,&miny);\r
- while (IN_GetJoyButtonsDB(joy))\r
- ;\r
-\r
- USL_ShowHelp("Move Joystick to the Lower-Right");\r
- VW_UpdateScreen();\r
- while ((LastScan != sc_Escape) && !IN_GetJoyButtonsDB(joy))\r
- ;\r
- if (LastScan != sc_Escape)\r
- {\r
- IN_GetJoyAbs(0,&maxx,&maxy);\r
- IN_SetupJoy(joy,minx,maxx,miny,maxy);\r
- }\r
- }\r
-\r
- if (LastScan != sc_Escape)\r
- while (IN_GetJoyButtonsDB(joy))\r
- ;\r
-\r
- if (LastScan)\r
- IN_ClearKeysDown();\r
-\r
- fontcolor = F_BLACK;\r
- VW_ShowCursor();\r
-\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_ClearBottom() - Clears the bottom part of the window\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_ClearBottom(void)\r
-{\r
- WindowRec wr;\r
-\r
- US_SaveWindow(&wr);\r
- US_RestoreWindow(&BottomWindow);\r
-\r
- US_ClearWindow();\r
-\r
- US_RestoreWindow(&wr);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_FormatHelp() - Formats helptext. Runs through and calculates the\r
-// number of lines, and the offset for the start of each line. Stops\r
-// after len bytes or when it hits a tilde ('~'). Munges the text.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static word\r
-USL_FormatHelp(char far *text,long len)\r
-{\r
- word line,\r
- w,h,\r
- far *off;\r
- char c,\r
- far *s,far *l,far *le;\r
-\r
- WindowX += 4;\r
- WindowW -= 4;\r
-\r
- MM_GetPtr(&LineOffsets,MaxHelpLines * sizeof(word));\r
- off = (word far *)LineOffsets;\r
- for (line = 0,le = l = s = text;(s - text < len) && (*s != '~');s++)\r
- {\r
- if ((c = *s) == '\n')\r
- {\r
- *s = '\0';\r
- *off++ = l - text; // Save offset of start of line\r
- line++; // Bump line number\r
- le = l = s + 1; // Set start of line ptr\r
- }\r
-\r
- if (c == '\r')\r
- c = *s = ' ';\r
- if // Strip orphaned spaces\r
- (\r
- (c == ' ')\r
- && (s == l)\r
- && (*(s - 1) == '\0')\r
- && (*(s + 1) != ' ')\r
- && (s > text)\r
- )\r
- le = l = s + 1;\r
- else if (c == ' ')\r
- {\r
- *s = '\0';\r
- USL_MeasureString(l,&w,&h);\r
- if (w >= WindowW) // If string width exceeds window,\r
- {\r
- *s = c; // Replace null char with proper char\r
- *le = '\0'; // Go back to last line end\r
- *off++ = l - text; // Save offset of start of line\r
- line++; // Bump line number\r
- l = s = le + 1; // Start next time through after last line end\r
- }\r
- else\r
- {\r
- *s = c; // Width still ok - put char back\r
- le = s; // And save ptr to last ok end of word\r
- }\r
- }\r
- }\r
-\r
- WindowX -= 4;\r
- WindowW += 4;\r
-\r
- return(line);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_DrawHelp() - Draws helptext in the current window\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_DrawHelp(char far *text,word start,word end,word line,word h,word far *lp)\r
-{\r
- px = WindowX + 4;\r
- py = WindowY + (line * h);\r
- for (lp += start;start < end;start++,px = WindowX + 4,py += h)\r
- USL_DrawString(text + *lp++);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_DoHelp() - Formats and displays the specified help\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_DoHelp(memptr text,long len)\r
-{\r
- boolean done,\r
- moved;\r
- int scroll;\r
- word i,\r
- pixdiv,\r
- w,h,\r
- lines,cur,page,\r
- top,num,loc,\r
- far *lp,\r
- base,srcbase,destbase;\r
- ScanCode waitkey;\r
- longword lasttime;\r
- WindowRec wr;\r
- CursorInfo info;\r
-\r
- USL_ShowHelp("Arrow Keys Move / Escape Exits");\r
- fontcolor = F_BLACK;\r
-\r
- US_SaveWindow(&wr);\r
- US_RestoreWindow(&BottomWindow);\r
- US_ClearWindow();\r
-\r
- VW_HideCursor();\r
- VW_UpdateScreen();\r
-\r
- lines = USL_FormatHelp((char far *)text,len);\r
- USL_MeasureString("",&w,&h);\r
- page = WindowH / h;\r
- cur = 0;\r
- lp = LineOffsets;\r
-\r
- IN_ClearKeysDown();\r
- moved = true;\r
- lasttime = 0;\r
- scroll = 0;\r
- done = false;\r
- waitkey = sc_None;\r
- while (!done)\r
- {\r
- if (moved)\r
- {\r
- while (TimeCount - lasttime < 5)\r
- ;\r
- lasttime = TimeCount;\r
-\r
- if (scroll == -1)\r
- {\r
- top = cur;\r
- num = 1;\r
- loc = 0;\r
- }\r
- else if (scroll == +1)\r
- {\r
- num = 1;\r
- loc = page - 1;\r
- top = cur + loc;\r
- }\r
- else\r
- {\r
- top = cur;\r
- num = (page < lines)? page : lines;\r
- loc = 0;\r
- }\r
- if (scroll)\r
- {\r
- if (grmode == CGAGR)\r
- {\r
- pixdiv = 4;\r
- base = bufferofs + panadjust + (WindowX / pixdiv);\r
- }\r
- else if (grmode == EGAGR)\r
- {\r
- VWB_Bar(WindowX,WindowY + (loc * h),WindowW,num * h,WHITE);\r
- USL_DrawHelp((char far *)text,top,top + num,loc,h,lp);\r
-\r
- pixdiv = 8;\r
- base = displayofs + panadjust + (WindowX / pixdiv);\r
- }\r
- else if (grmode == VGAGR)\r
- pixdiv = 1;\r
-\r
- if (scroll == 1)\r
- {\r
- srcbase = base + ylookup[WindowY + h];\r
- destbase = base + ylookup[WindowY];\r
- if (grmode == EGAGR)\r
- {\r
- EGAWRITEMODE(1);\r
- VW_WaitVBL(1);\r
- }\r
- VW_ScreenToScreen(srcbase,destbase,WindowW / pixdiv,\r
- WindowH - h);\r
- }\r
- else\r
- {\r
- i = WindowY + (h * (page - 1));\r
- srcbase = base + ylookup[i - h];\r
- destbase = base + ylookup[i];\r
- base = ylookup[h];\r
- for (i = page - 1;i;i--,srcbase -= base,destbase -= base)\r
- VW_ScreenToScreen(srcbase,destbase,WindowW / pixdiv,h);\r
- }\r
- if (grmode == CGAGR)\r
- {\r
- VWB_Bar(WindowX,WindowY + (loc * h),WindowW,num * h,WHITE);\r
- USL_DrawHelp((char far *)text,top,top + num,loc,h,lp);\r
- VW_UpdateScreen();\r
- }\r
- else if (grmode == EGAGR)\r
- {\r
- base = panadjust + (WindowX / pixdiv) +\r
- ylookup[WindowY + (loc * h)];\r
- VW_ScreenToScreen(base + bufferofs,base + displayofs,\r
- WindowW / pixdiv,h);\r
- }\r
- }\r
- else\r
- {\r
- US_ClearWindow();\r
- USL_DrawHelp((char far *)text,top,top + num,loc,h,lp);\r
- VW_UpdateScreen();\r
- }\r
-\r
- moved = false;\r
- scroll = 0;\r
- }\r
-\r
- if (waitkey)\r
- while (IN_KeyDown(waitkey))\r
- ;\r
- waitkey = sc_None;\r
-\r
- IN_ReadCursor(&info);\r
- if (info.y < 0)\r
- {\r
- if (cur > 0)\r
- {\r
- scroll = -1;\r
- cur--;\r
- moved = true;\r
- }\r
- }\r
- else if (info.y > 0)\r
- {\r
- if (cur + page < lines)\r
- {\r
- scroll = +1;\r
- cur++;\r
- moved = true;\r
- }\r
- }\r
- else if (info.button0 || info.button1)\r
- done = true;\r
- else if (IN_KeyDown(LastScan))\r
- {\r
- switch (LastScan)\r
- {\r
- case sc_Escape:\r
- done = true;\r
- break;\r
- case sc_UpArrow:\r
- if (cur > 0)\r
- {\r
- scroll = -1;\r
- cur--;\r
- moved = true;\r
- }\r
- break;\r
- case sc_DownArrow:\r
- if (cur + page < lines)\r
- {\r
- scroll = +1;\r
- cur++;\r
- moved = true;\r
- }\r
- break;\r
- case sc_PgUp:\r
- if (cur > page)\r
- cur -= page;\r
- else\r
- cur = 0;\r
- moved = true;\r
- waitkey = sc_PgUp;\r
- break;\r
- case sc_PgDn:\r
- if (cur + page < lines)\r
- {\r
- cur += page;\r
- if (cur + page >= lines)\r
- cur = lines - page;\r
- moved = true;\r
- }\r
- waitkey = sc_PgDn;\r
- break;\r
- }\r
- }\r
- }\r
- IN_ClearKeysDown();\r
- do\r
- {\r
- IN_ReadCursor(&info);\r
- } while (info.button0 || info.button1);\r
-\r
- VW_ShowCursor();\r
- US_ClearWindow();\r
- VW_UpdateScreen();\r
- US_RestoreWindow(&wr);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_CtlHButtonCustom() - The custom routine for all of the help buttons\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-USL_CtlHButtonCustom(UserCall call,word i,word n)\r
-{\r
- word j;\r
- UserItem *ip;\r
-\r
- if (call != uic_Hit)\r
- return(false);\r
-\r
- ip = &TheItems[i][n];\r
- if (ip->sel & ui_Disabled)\r
- return(false);\r
-\r
- ip->sel |= ui_Selected;\r
- USL_DrawItem(i,n);\r
-\r
- USL_ClearBottom();\r
-\r
- fontcolor = F_SECONDCOLOR;\r
- USL_ShowHelp("Loading & Formatting Text...");\r
- VW_UpdateScreen();\r
-\r
-#ifdef HELPTEXTLINKED // Ugly hack because of lack of disk space...\r
- {\r
-extern char far gametext,far context,far story;\r
- char far *buf;\r
- memptr dupe;\r
-\r
- switch (n)\r
- {\r
- case 0:\r
- buf = &gametext;\r
- break;\r
- case 1:\r
- buf = &context;\r
- break;\r
- case 2:\r
- buf = &story;\r
- break;\r
- }\r
-\r
- MM_GetPtr(&dupe,5000);\r
- _fmemcpy((char far *)dupe,buf,5000);\r
-\r
- USL_DoHelp(dupe,5000);\r
-\r
- MM_FreePtr(&dupe);\r
- if (LineOffsets)\r
- MM_FreePtr(&LineOffsets);\r
- }\r
-#else\r
- {\r
- char *name;\r
- int file;\r
- long len;\r
- memptr buf;\r
-\r
- switch (n)\r
- {\r
- case 0:\r
- name = "GAMETEXT."EXTENSION;\r
- break;\r
- case 1:\r
- name = "CONTEXT."EXTENSION;\r
- break;\r
- case 2:\r
- name = "STORY."EXTENSION;\r
- break;\r
- default:\r
- Quit("Bad help button number");\r
- }\r
-\r
- if ((file = open(name,O_RDONLY | O_TEXT)) == -1)\r
- USL_HandleError(errno);\r
- else\r
- {\r
- len = filelength(file);\r
- MM_GetPtr(&buf,len);\r
-\r
- if (CA_FarRead(file,(byte far *)buf,len))\r
- USL_DoHelp(buf,len);\r
- else\r
- USL_HandleError(errno);\r
-\r
- close(file);\r
- MM_FreePtr(&buf);\r
- }\r
-\r
- if (LineOffsets)\r
- MM_FreePtr(&LineOffsets);\r
- }\r
-#endif\r
-\r
- fontcolor = F_BLACK;\r
-\r
- ip->sel &= ~ui_Selected;\r
- USL_DrawItem(i,n);\r
-\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_CtlDButtonCustom() - The custom routine for all of the disk buttons.\r
-// Sets up the bottom area of the window with the appropriate buttons\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-USL_CtlDButtonCustom(UserCall call,word i,word n)\r
-{\r
- word j;\r
- UserItem *ip;\r
-\r
- if (call != uic_Hit)\r
- return(false);\r
-\r
- ip = &TheItems[i][n];\r
- if (ip->sel & ui_Disabled)\r
- return(false);\r
-\r
- USL_ClearBottom();\r
-\r
- j = 0;\r
- TheItems[i + 1] = ip = n? CtlDEPanels : CtlDLSPanels;\r
- while (ip && (ip->type != uii_Bad))\r
- {\r
- USL_DrawItem(i + 1,j++);\r
- ip++;\r
- }\r
-\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_DLSRect() - Draw the rectangle for the save game names\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static Rect\r
-USL_DLSRect(UserItem *ip)\r
-{\r
- Rect r;\r
-\r
- r.ul.x = ip->r.lr.x + 40 + 2;\r
- r.ul.y = ip->r.ul.y + 2;\r
- r.lr.x = WindowX + WindowW - 8 - 2;\r
- r.lr.y = ip->r.lr.y - 2;\r
-\r
- VWB_Bar(r.ul.x,r.ul.y,r.lr.x - r.ul.x,r.lr.y - r.ul.y,WHITE);\r
-\r
- VWB_Hlin(r.ul.x,r.lr.x,r.ul.y,BLACK);\r
- VWB_Hlin(r.ul.x,r.lr.x,r.lr.y,BLACK);\r
- VWB_Vlin(r.ul.y,r.lr.y,r.ul.x,BLACK);\r
- VWB_Vlin(r.ul.y,r.lr.y,r.lr.x,BLACK);\r
-\r
- px = r.ul.x + 2;\r
- py = r.ul.y + 2;\r
-\r
- return(r);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_CtlDLButtonCustom() - The load game custom routine\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-USL_CtlDLButtonCustom(UserCall call,word i,word n)\r
-{\r
- char *filename,\r
- msg[MaxGameName + 12];\r
- word err;\r
- int file;\r
- UserItem *ip;\r
- SaveGame *game;\r
- WindowRec wr;\r
-\r
- // DEBUG - deal with warning user about loading a game causing abort\r
-\r
- game = &Games[n / 2];\r
- ip = &TheItems[i][n];\r
-\r
- switch (call)\r
- {\r
- case uic_Draw:\r
- if (!loadedgame)\r
- {\r
- USL_DLSRect(ip);\r
- fontcolor = game->present? F_BLACK : F_FIRSTCOLOR;\r
- USL_DrawString(game->present? game->name : "Empty");\r
- fontcolor = F_BLACK;\r
- }\r
- break;\r
- case uic_Hit:\r
- if (ip->sel & ui_Disabled)\r
- return(false);\r
-\r
- LeaveDriveOn++;\r
- filename = USL_GiveSaveName(n / 2);\r
-\r
- US_SaveWindow(&wr);\r
- US_CenterWindow(30,3);\r
- strcpy(msg,"Loading `");\r
- strcat(msg,game->name);\r
- strcat(msg,"\'");\r
- US_PrintCentered(msg);\r
- VW_HideCursor();\r
- VW_UpdateScreen();\r
-\r
- err = 0;\r
- if ((file = open(filename,O_BINARY | O_RDONLY)) != -1)\r
- {\r
- if (read(file,game,sizeof(*game)) == sizeof(*game))\r
- {\r
- if (USL_LoadGame)\r
- if (!USL_LoadGame(file))\r
- USL_HandleError(err = errno);\r
- }\r
- else\r
- USL_HandleError(err = errno);\r
- close(file);\r
- }\r
- else\r
- USL_HandleError(err = errno);\r
- if (err)\r
- abortgame = true;\r
- else\r
- loadedgame = true;\r
- game->present = true;\r
-\r
- if (loadedgame)\r
- Paused = true;\r
-\r
- VW_ShowCursor();\r
- US_RestoreWindow(&wr);\r
-\r
- LeaveDriveOn--;\r
- break;\r
- }\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_CtlDSButtonCustom() - The save game custom routine\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-USL_CtlDSButtonCustom(UserCall call,word i,word n)\r
-{\r
- boolean ok;\r
- char *filename;\r
- word err;\r
- int file;\r
- Rect r;\r
- UserItem *ip;\r
- SaveGame *game;\r
- WindowRec wr;\r
-\r
- if (call != uic_Hit)\r
- return(false);\r
-\r
- game = &Games[n / 2];\r
- ip = &TheItems[i][n];\r
- if (ip->sel & ui_Disabled)\r
- return(false);\r
-\r
- FlushHelp = true;\r
- fontcolor = F_SECONDCOLOR;\r
- USL_ShowHelp("Enter Game Name / Escape Aborts");\r
- fontcolor = F_BLACK;\r
-\r
- r = USL_DLSRect(ip - 1);\r
- ok = US_LineInput(px,py,game->name,game->present? game->name : nil,true,\r
- MaxGameName,r.lr.x - r.ul.x - 8);\r
- if (!strlen(game->name))\r
- strcpy(game->name,"Untitled");\r
- if (ok)\r
- {\r
- US_SaveWindow(&wr);\r
- US_CenterWindow(10,3);\r
- US_PrintCentered("Saving");\r
- VW_HideCursor();\r
- VW_UpdateScreen();\r
-\r
- LeaveDriveOn++;\r
- filename = USL_GiveSaveName(n / 2);\r
- err = 0;\r
- file = open(filename,O_CREAT | O_BINARY | O_WRONLY,\r
- S_IREAD | S_IWRITE | S_IFREG);\r
- if (file != -1)\r
- {\r
- if (write(file,game,sizeof(*game)) == sizeof(*game))\r
- {\r
- if (USL_SaveGame)\r
- ok = USL_SaveGame(file);\r
- if (!ok)\r
- USL_HandleError(err = errno);\r
- }\r
- else\r
- USL_HandleError(err = ((errno == ENOENT)? ENOMEM : errno));\r
- close(file);\r
- }\r
- else\r
- USL_HandleError(err = ((errno == ENOENT)? ENOMEM : errno));\r
- if (err)\r
- {\r
- remove(filename);\r
- ok = false;\r
- }\r
- LeaveDriveOn--;\r
-\r
- VW_ShowCursor();\r
- US_RestoreWindow(&wr);\r
- USL_DoHit(i - 1,0);\r
- VW_UpdateScreen();\r
- }\r
-\r
- if (!game->present)\r
- game->present = ok;\r
-\r
- if (ok)\r
- {\r
- GameIsDirty = false;\r
- (ip - 1)->sel &= ~ui_Disabled;\r
- }\r
-\r
- USL_DrawItem(i,n - 1);\r
-// USL_CtlDLButtonCustom(uic_Draw,i,n - 1);\r
-\r
- return(true);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_CtlSButtonCustom() - The custom routine for all of the sound buttons\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-USL_CtlSButtonCustom(UserCall call,word i,word n)\r
-{\r
- word j;\r
- UserItem *ip;\r
-\r
- if (call != uic_Hit)\r
- return(false);\r
-\r
- ip = &TheItems[i][n];\r
- if (ip->sel & ui_Disabled)\r
- return(false);\r
-\r
- USL_ClearBottom();\r
-\r
- if (n == sdm_SoundSource)\r
- {\r
- j = 0;\r
- TheItems[i + 1] = ip = CtlSSSPanels;\r
- while (ip && (ip->type != uii_Bad))\r
- {\r
- USL_DrawItem(i + 1,j++);\r
- ip++;\r
- }\r
- }\r
- else\r
- TheItems[i + 1] = nil;\r
-\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_CtlPButtonCustom() - The custom routine for all of the start game btns\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-USL_CtlPButtonCustom(UserCall call,word i,word n)\r
-{\r
- word j;\r
- UserItem *ip;\r
-\r
- if (call != uic_Hit)\r
- return(false);\r
-\r
- ip = &TheItems[i][n];\r
- if (ip->sel & ui_Disabled)\r
- return(false);\r
-\r
- USL_ClearBottom();\r
-\r
- j = 0;\r
- TheItems[i + 1] = ip = n? CtlPRPanels : CtlPSPanels;\r
- while (ip && (ip->type != uii_Bad))\r
- {\r
- USL_DrawItem(i + 1,j++);\r
- ip++;\r
- }\r
-\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_GiveAbortWarning() - Draws a string that warns the user that an\r
-// action they're about to take will abort the game in progress\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_GiveAbortWarning(void)\r
-{\r
- WindowRec wr;\r
-\r
- if (!GameIsDirty)\r
- return;\r
-\r
- US_SaveWindow(&wr);\r
- US_RestoreWindow(&BottomWindow);\r
- US_HomeWindow();\r
- PrintY += 5;\r
-\r
- VWB_Bar(WindowX,WindowY,WindowW,30,WHITE);\r
- fontcolor = F_SECONDCOLOR;\r
- US_CPrint("Warning! If you do this, you'll");\r
- US_CPrint("abort the current game.");\r
- fontcolor = F_BLACK;\r
-\r
- US_RestoreWindow(&wr);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_CtlPSButtonCustom() - The custom routine for the start game button\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-USL_CtlPSButtonCustom(UserCall call,word i,word n)\r
-{\r
- boolean result;\r
- UserItem *ip;\r
-\r
- i++; // Shut the compiler up\r
-\r
- switch (call)\r
- {\r
- case uic_Hit:\r
- switch (n)\r
- {\r
- case 0:\r
- restartgame = gd_Normal;\r
- break;\r
- case 1:\r
- restartgame = gd_Easy;\r
- break;\r
- case 2:\r
- restartgame = gd_Hard;\r
- break;\r
- }\r
- if (restartgame && ingame && USL_ResetGame)\r
- USL_ResetGame();\r
- result = false;\r
- break;\r
- case uic_Draw:\r
- USL_GiveAbortWarning();\r
- result = false;\r
- break;\r
- default:\r
- result = false;\r
- break;\r
- }\r
- return(result);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_CtlPRButtonCustom() - The custom routine for the resume game button\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-USL_CtlPRButtonCustom(UserCall call,word i,word n)\r
-{\r
- if (call != uic_Hit)\r
- return(false);\r
-\r
- i++,n++; // Shut the compiler up\r
- ResumeGame = true;\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_CtlDEButtonCustom() - The custom routine for the exit to DOS button\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-USL_CtlDEButtonCustom(UserCall call,word i,word n)\r
-{\r
- boolean result;\r
- UserItem *ip;\r
-\r
- i++,n++; // Shut the compiler up\r
-\r
- switch (call)\r
- {\r
- case uic_Hit:\r
- QuitToDos = true;\r
- break;\r
- case uic_Draw:\r
- USL_GiveAbortWarning();\r
- default:\r
- result = false;\r
- break;\r
- }\r
- return(result);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_CtlCButtonCustom() - The custom routine for all of the control\r
-// buttons\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-USL_CtlCButtonCustom(UserCall call,word i,word n)\r
-{\r
- word j;\r
- Point p;\r
- UserItem *ip;\r
-\r
- if (call != uic_Hit)\r
- return(false);\r
-\r
- ip = &TheItems[i][n];\r
- if (ip->sel & ui_Disabled)\r
- return(false);\r
-\r
- USL_ClearBottom();\r
- if (n == 0) // Keyboard\r
- {\r
- TheItems[i + 1] = ip = CtlCKbdPanels;\r
- p = CtlCKbdPanels[2].r.lr;\r
- VWB_DrawPic(p.x,p.y,CTL_DIRSPIC);\r
- }\r
- else\r
- TheItems[i + 1] = ip = CtlCJoyPanels;\r
-\r
- j = 0;\r
- while (ip && (ip->type != uii_Bad))\r
- {\r
- USL_DrawItem(i + 1,j++);\r
- ip++;\r
- }\r
-\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_HitHotKey() - After a hotkey was hit, move the cursor to the first\r
-// selected item in the group after the group containing the item\r
-// holding the hotkey\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_HitHotKey(int i,int n)\r
-{\r
- UserItem *ip;\r
-\r
- if (ip = TheItems[++i])\r
- {\r
- if ((n = USL_FindDown(TheItems[i])) == -1)\r
- n = 0;\r
- ip += n;\r
- CursorX = ip->r.lr.x - 8;\r
- CursorY = ip->r.lr.y - 8;\r
- CursorBad = true;\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_CheckScan() - Checks to see if the scancode in LastScan corresponds\r
-// to anything in the list of useritems. If so, selects the item.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static boolean\r
-USL_CheckScan(word *ci,word *cn)\r
-{\r
- word i,n;\r
- UserItem *ip;\r
-\r
- if (!LastScan)\r
- return(false);\r
-\r
-#if 1 // DEBUG - probably kill this code\r
- // Use 1..? for the items across the top row\r
- if (TheItems[1] && !IN_KeyDown(sc_RShift))\r
- {\r
- for (i = 0,ip = TheItems[1];(ip->type != uii_Bad) && (i < 9);i++,ip++)\r
- ;\r
- for (n = 0;n < i;n++)\r
- {\r
- if (LastScan == 2 + n) // Numbers from 1..9\r
- {\r
- if (!(TheItems[1][n].sel & ui_Disabled))\r
- {\r
- LastScan = sc_None;\r
- USL_DoHit(1,n);\r
- return(true);\r
- }\r
- }\r
- }\r
- }\r
-\r
- // Use Alt-1..6 for the items in the leftmost column\r
- if (IN_KeyDown(sc_RShift))\r
- {\r
- n = LastScan - 2;\r
- if (n < 6) // Numbers from 1..6\r
- {\r
- USL_DoHit(0,n);\r
- LastScan = sc_None;\r
- return(true);\r
- }\r
- }\r
-#endif\r
-\r
- // Check normal hotkeys for the leftmost column\r
- for (i = 0;CtlPanels[i].type != uii_Bad;i++)\r
- {\r
- if (CtlPanels[i].key == LastScan)\r
- {\r
- LastScan = sc_None;\r
- USL_DoHit(0,i);\r
- *ci = 0;\r
- *cn = i;\r
- USL_HitHotKey(0,i);\r
- return(true);\r
- }\r
- }\r
-\r
- // Check normal hotkeys for the top row\r
- for (i = 0;i < 6;i++)\r
- {\r
- for (n = 0,ip = CtlPanels2[i];ip && ip->type != uii_Bad;n++,ip++)\r
- {\r
- if ((ip->key == LastScan) && !(ip->sel & ui_Disabled))\r
- {\r
- LastScan = sc_None;\r
- USL_DoHit(0,i);\r
- USL_DoHit(1,n);\r
- *ci = 1;\r
- *cn = n;\r
- USL_HitHotKey(1,n);\r
- return(true);\r
- }\r
- }\r
- }\r
- return(false);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_SetUpCtlPanel() - Sets the states of the UserItems to reflect the\r
-// values of all the appropriate variables\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_SetUpCtlPanel(void)\r
-{\r
- word i,j;\r
-\r
- GameIsDirty = ingame;\r
-\r
- // Set up restart game\r
- USL_TurnOff(CtlPPanels);\r
- CtlPPanels[0].sel = ingame? ui_Normal : ui_Selected;\r
- CtlPPanels[1].sel = ingame? ui_Selected : ui_Disabled;\r
-\r
- // Set up disk stuff - default to load/save game\r
- USL_TurnOff(CtlDPanels);\r
- CtlDPanels[0].sel = ui_Selected;\r
-\r
- // Set up load/save buttons\r
- USL_TurnOff(CtlDLSPanels);\r
- for (i = 0;i < MaxSaveGames;i++)\r
- {\r
- if (!Games[i].present)\r
- CtlDLSPanels[i * 2].sel = ui_Disabled;\r
- if (!ingame)\r
- CtlDLSPanels[(i * 2) + 1].sel = ui_Disabled;\r
- }\r
-\r
- // Set up Controls\r
- USL_TurnOff(CtlCPanels);\r
- CtlCPanels[1].sel = JoysPresent[0]? ui_Normal : ui_Disabled;\r
- CtlCPanels[2].sel = JoysPresent[1]? ui_Normal : ui_Disabled;\r
- if (Controls[0] == ctrl_Keyboard)\r
- i = 0;\r
- else\r
- i = (Controls[0] == ctrl_Joystick1)? 1 : 2;\r
- CtlCPanels[i].sel |= ui_Selected;\r
- if (JoysPresent[1] && !JoysPresent[0])\r
- CtlCPanels[2].key = sc_F4;\r
- else\r
- CtlCPanels[1].key = sc_F4;\r
-\r
- // Set up Keyboard\r
- for (i = 0;i < 10;i++)\r
- CtlCKbdPanels[i].text = IN_GetScanName(*(KeyMaps[i]));\r
-\r
- // Set up Sounds\r
- USL_TurnOff(CtlSPanels);\r
- CtlSPanels[sdm_AdLib].sel = AdLibPresent? ui_Normal : ui_Disabled;\r
-#if 0 // DEBUG - hack because no space for digitized sounds on Keen Dreams\r
- CtlSPanels[sdm_SoundBlaster].sel =\r
- SoundBlasterPresent? ui_Normal : ui_Disabled;\r
- CtlSPanels[sdm_SoundSource].sel =\r
- SoundSourcePresent? ui_Normal : ui_Disabled;\r
-#else\r
- CtlSPanels[sdm_SoundBlaster].sel = ui_Disabled;\r
- CtlSPanels[sdm_SoundSource].sel = ui_Disabled;\r
-#endif\r
- CtlSPanels[SoundMode].sel |= ui_Selected;\r
-\r
- // Set up SoundSource\r
- USL_TurnOff(CtlSSSPanels);\r
- CtlSSSPanels[0].sel = ssIsTandy? ui_Selected : ui_Normal;\r
- CtlSSSPanels[1].sel = (ssPort == 2)? ui_Selected : ui_Normal;\r
-\r
- // Set up Music\r
- USL_TurnOff(CtlMPanels);\r
- CtlMPanels[smm_AdLib].sel = AdLibPresent? ui_Normal : ui_Disabled;\r
- CtlMPanels[MusicMode].sel |= ui_Selected;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_TearDownCtlPanel() - Given the state of the control panel, sets the\r
-// modes and values as appropriate\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_TearDownCtlPanel(void)\r
-{\r
- int i;\r
-\r
- i = USL_FindDown(CtlCPanels);\r
- if (i != -1)\r
- {\r
- i = i? (i == 1? ctrl_Joystick1 : ctrl_Joystick2) : ctrl_Keyboard;\r
- IN_SetControlType(0,i);\r
- }\r
-\r
- CtlCPanels[1].key = CtlCPanels[2].key = sc_None;\r
-\r
- i = USL_FindDown(CtlSPanels);\r
- if (i != -1)\r
- SD_SetSoundMode(i);\r
-\r
- ssIsTandy = CtlSSSPanels[0].sel & ui_Selected;\r
- ssPort = (CtlSSSPanels[1].sel & ui_Selected)? 2 : 1;\r
-\r
- i = USL_FindDown(CtlMPanels);\r
- if (i != -1)\r
- {\r
- SD_SetMusicMode(i);\r
-\r
- if (!QuitToDos)\r
- {\r
- US_CenterWindow(20,8);\r
- US_CPrint("Loading");\r
-#if 0\r
- fontcolor = F_SECONDCOLOR;\r
- US_CPrint("Sounds");\r
- fontcolor = F_BLACK;\r
-#endif\r
- VW_UpdateScreen();\r
-\r
- CA_LoadAllSounds();\r
- }\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_ControlPanel() - This is the main routine for the control panel\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_ControlPanel(void)\r
-{\r
- char gamename[MaxGameName + 10 + 1];\r
- ScanCode c;\r
- boolean done,\r
- buttondown,inrect;\r
- word hiti,hitn,\r
- i,n,\r
- lasti,lastn,\r
- lastx,lasty;\r
- longword lasttime;\r
- Point p;\r
- Rect userect;\r
- UserItem *ip;\r
-\r
- c = LastScan;\r
- if (c == sc_Escape) // Map escape from game to Exit to DOS\r
- c = sc_Q;\r
-\r
- CA_UpLevel();\r
- for (i = CONTROLS_LUMP_START;i <= CONTROLS_LUMP_END;i++)\r
- CA_MarkGrChunk(i);\r
- CA_MarkGrChunk(CTL_LITTLEMASKPICM);\r
- CA_MarkGrChunk(CTL_LSMASKPICM);\r
- CA_CacheMarks("Options Screen");\r
-\r
- USL_SetUpCtlPanel();\r
-\r
- US_SetPrintRoutines(VW_MeasurePropString,VWB_DrawPropString);\r
- fontcolor = F_BLACK;\r
-\r
- VW_InitDoubleBuffer();\r
-\r
- VWB_Bar(0,0,MaxX,MaxY,FIRSTCOLOR);\r
- US_DrawWindow(8,22,30,2);\r
- US_SaveWindow(&HelpWindow);\r
- US_DrawWindow(8,7,30,14);\r
- US_SaveWindow(&BottomWindow);\r
- US_DrawWindow(8,1,30,20);\r
-\r
- for (ip = CtlPanels;ip->type != uii_Bad;ip++)\r
- VWB_DrawPic(ip->r.ul.x,ip->r.ul.y,ip->picup);\r
-\r
- US_StartCursor();\r
- CursorX = (8 * 8) + ((MaxX - (8 * 8)) / 2);\r
- CursorBad = true;\r
-\r
- CtlPanelButton = -1;\r
- LastScan = c;\r
- USL_CheckScan(&i,&n);\r
- if (CtlPanelButton == -1)\r
- USL_DoHit(0,0);\r
-\r
- ResumeGame = false;\r
- done = false;\r
- FlushHelp = true;\r
- lastx = lasty = -1;\r
- while\r
- (\r
- (restartgame == gd_Continue)\r
- && !(done || loadedgame || ResumeGame)\r
- )\r
- {\r
- VW_UpdateScreen();\r
-\r
- buttondown = US_UpdateCursor();\r
- inrect = USL_IsInRect(CursorX,CursorY,&i,&n);\r
-\r
- if (FlushHelp)\r
- {\r
- lasti = -2;\r
- lasttime = TimeCount;\r
- FlushHelp = false;\r
- }\r
- if (inrect)\r
- {\r
- if ((lasti != i) || (lastn != n))\r
- {\r
- // If over a Load button\r
- if\r
- (\r
- (CtlPanelButton == 2)\r
- && (i == 2)\r
- && (TheItems[1][0].sel & ui_Selected)\r
- && (Games[n / 2].present)\r
- && !(n & 1)\r
- )\r
- {\r
- strcpy(gamename,"Load `");\r
- strcat(gamename,Games[n / 2].name);\r
- strcat(gamename,"'");\r
- USL_ShowHelp(gamename);\r
- }\r
- else\r
- USL_ShowHelp(TheItems[i][n].help);\r
- lasti = i;\r
- lastn = n;\r
- }\r
- }\r
- else if (lasti != (word)-1)\r
- {\r
- USL_ShowHelp("Select a Button");\r
- lasti = -1;\r
- }\r
-\r
- hiti = i;\r
- hitn = n;\r
-\r
- if (inrect)\r
- userect = TheItems[i][n].r;\r
- else\r
- {\r
- userect.ul.x = CursorX;\r
- userect.ul.y = CursorY;\r
- userect.lr = userect.ul;\r
- }\r
-\r
- if (IN_KeyDown(sc_UpArrow))\r
- {\r
- USL_FindRect(userect,motion_None,motion_Up);\r
- buttondown = false;\r
- IN_ClearKey(sc_UpArrow);\r
- }\r
- else if (IN_KeyDown(sc_DownArrow))\r
- {\r
- USL_FindRect(userect,motion_None,motion_Down);\r
- buttondown = false;\r
- IN_ClearKey(sc_DownArrow);\r
- }\r
- else if (IN_KeyDown(sc_LeftArrow))\r
- {\r
- USL_FindRect(userect,motion_Left,motion_None);\r
- buttondown = false;\r
- IN_ClearKey(sc_LeftArrow);\r
- }\r
- else if (IN_KeyDown(sc_RightArrow))\r
- {\r
- USL_FindRect(userect,motion_Right,motion_None);\r
- buttondown = false;\r
- IN_ClearKey(sc_RightArrow);\r
- }\r
- else if\r
- (\r
- IN_KeyDown(c = sc_Return)\r
- || IN_KeyDown(c = KbdDefs[0].button0)\r
- || IN_KeyDown(c = KbdDefs[0].button1)\r
- )\r
- {\r
- IN_ClearKey(c);\r
- if (inrect)\r
- {\r
- ip = &TheItems[hiti][hitn];\r
-\r
- if ((ip->type == uii_Button) && !(ip->sel & ui_Disabled))\r
- {\r
- lasttime = TimeCount;\r
-\r
- ip->sel |= ui_Selected;\r
- USL_DrawItem(hiti,hitn);\r
- VW_UpdateScreen();\r
-\r
- while (TimeCount - lasttime < TickBase / 4)\r
- ;\r
- lasttime = TimeCount;\r
-\r
- ip->sel &= ~ui_Selected;\r
- USL_DrawItem(hiti,hitn);\r
- VW_UpdateScreen();\r
-\r
- while (TimeCount - lasttime < TickBase / 4)\r
- ;\r
- }\r
-\r
- USL_DoHit(hiti,hitn);\r
- }\r
- }\r
- else if (USL_CheckScan(&i,&n))\r
- ;\r
- else if (buttondown && inrect && USL_TrackItem(hiti,hitn))\r
- USL_DoHit(hiti,hitn);\r
-\r
- if (LastScan == sc_Escape)\r
- {\r
- IN_ClearKey(sc_Escape);\r
- done = true;\r
- }\r
-\r
- if (QuitToDos)\r
- done = true;\r
-\r
- if ((lastx != CursorX) || (lasty != CursorY))\r
- {\r
- lastx = CursorX;\r
- lasty = CursorY;\r
- lasttime = TimeCount;\r
- }\r
- if (TimeCount - lasttime > TickBase * 10)\r
- {\r
- if (((TimeCount - lasttime) / TickBase) & 2)\r
- fontcolor = F_SECONDCOLOR;\r
- USL_ShowHelp("Press F1 for Help");\r
- fontcolor = F_BLACK;\r
- }\r
- }\r
-\r
- US_ShutCursor();\r
-\r
- USL_TearDownCtlPanel();\r
-\r
- if (restartgame && USL_ResetGame)\r
- USL_ResetGame();\r
-\r
- if (QuitToDos)\r
- {\r
- if (tedlevel)\r
- TEDDeath();\r
- else\r
- {\r
- US_CenterWindow(20,3);\r
- fontcolor = F_SECONDCOLOR;\r
- US_PrintCentered("Now Exiting to DOS...");\r
- fontcolor = F_BLACK;\r
- VW_UpdateScreen();\r
- Quit(nil);\r
- }\r
- }\r
-\r
- CA_DownLevel();\r
-}\r
-\r
-// High score routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_DisplayHighScores() - Assumes that double buffering has been started.\r
-// If passed a -1 will just display the high scores, but if passed\r
-// a non-negative number will display that entry in red and let the\r
-// user type in a name\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_DisplayHighScores(int which)\r
-{\r
- char buffer[16],*str;\r
- word i,\r
- w,h,\r
- x,y;\r
- HighScore *s;\r
-\r
- US_CenterWindow(30,MaxScores + (MaxScores / 2));\r
-\r
- x = WindowX + (WindowW / 2);\r
- US_Print(" Name");\r
- PrintX = x + 20;\r
- US_Print("Score");\r
- PrintX = x + 60;\r
- US_Print("Done\n\n");\r
- PrintY -= 3;\r
-\r
- for (i = WindowX;i < WindowX + WindowW;i += 8)\r
- VWB_DrawTile8M(i,WindowY + 8,10);\r
- VWB_DrawTile8M(WindowX - 8,WindowY + 8,9);\r
- VWB_DrawTile8M(WindowX + WindowW,WindowY + 8,11);\r
-\r
- for (i = 0,s = Scores;i < MaxScores;i++,s++)\r
- {\r
- fontcolor = (i == which)? F_SECONDCOLOR : F_BLACK;\r
-\r
- if (i != which)\r
- {\r
- US_Print(" ");\r
- if (strlen(s->name))\r
- US_Print(s->name);\r
- else\r
- US_Print("-");\r
- }\r
- else\r
- y = PrintY;\r
-\r
- PrintX = x + (7 * 8);\r
- ultoa(s->score,buffer,10);\r
- for (str = buffer;*str;str++)\r
- *str = *str + (129 - '0'); // Used fixed-width numbers (129...)\r
- USL_MeasureString(buffer,&w,&h);\r
- PrintX -= w;\r
- US_Print(buffer);\r
-\r
- PrintX = x + 60;\r
- if (s->completed)\r
- US_PrintUnsigned(s->completed);\r
- else\r
- US_Print("-");\r
-\r
- US_Print("\n");\r
- }\r
-\r
- if (which != -1)\r
- {\r
- fontcolor = F_SECONDCOLOR;\r
- PrintY = y;\r
- PrintX = WindowX;\r
- US_Print(" ");\r
- strcpy(Scores[which].name,"");\r
- US_LineInput(PrintX,PrintY,Scores[which].name,nil,true,MaxHighName,\r
- (WindowW / 2) - 8);\r
- }\r
- fontcolor = F_BLACK;\r
-\r
- VW_UpdateScreen();\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_CheckHighScore() - Checks gamestate to see if the just-ended game\r
-// should be entered in the high score list. If so, lets the user\r
-// enter their name\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_CheckHighScore(long score,word other)\r
-{\r
- word i,j,\r
- n;\r
- HighScore myscore;\r
-\r
- strcpy(myscore.name,"");\r
- myscore.score = score;\r
- myscore.completed = other;\r
-\r
- for (i = 0,n = -1;i < MaxScores;i++)\r
- {\r
- if\r
- (\r
- (myscore.score > Scores[i].score)\r
- || (\r
- (myscore.score == Scores[i].score)\r
- && (myscore.completed > Scores[i].completed)\r
- )\r
- )\r
- {\r
- for (j = MaxScores;--j > i;)\r
- Scores[j] = Scores[j - 1];\r
- Scores[i] = myscore;\r
-\r
- n = i;\r
- HighScoresDirty = true;\r
- break;\r
- }\r
- }\r
-\r
- VW_InitDoubleBuffer();\r
- VWB_Bar(0,0,MaxX,MaxY,FIRSTCOLOR);\r
-\r
- US_DisplayHighScores(n);\r
- IN_UserInput(5 * TickBase,false);\r
-}\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_US.h - Header file for the User Manager\r
-// v1.0d1\r
-// By Jason Blochowiak\r
-//\r
-\r
-#ifndef __TYPES__\r
-#include "ID_Types.h"\r
-#endif\r
-\r
-#ifndef __ID_US__\r
-#define __ID_US__\r
-\r
-#ifdef __DEBUG__\r
-#define __DEBUG_UserMgr__\r
-#endif\r
-\r
-//#define HELPTEXTLINKED\r
-\r
-#define MaxHelpLines 500\r
-\r
-#define MaxHighName 57\r
-#define MaxScores 7\r
-typedef struct\r
- {\r
- char name[MaxHighName + 1];\r
- long score;\r
- word completed;\r
- } HighScore;\r
-\r
-#define MaxGameName 32\r
-#define MaxSaveGames 6\r
-typedef struct\r
- {\r
- char signature[4];\r
- word *oldtest;\r
- boolean present;\r
- char name[MaxGameName + 1];\r
- } SaveGame;\r
-\r
-#define MaxString 128 // Maximum input string size\r
-\r
-typedef struct\r
- {\r
- int x,y,\r
- w,h,\r
- px,py;\r
- } WindowRec; // Record used to save & restore screen windows\r
-\r
-typedef enum\r
- {\r
- gd_Continue,\r
- gd_Easy,\r
- gd_Normal,\r
- gd_Hard\r
- } GameDiff;\r
-\r
-// Hack import for TED launch support\r
-extern boolean tedlevel;\r
-extern word tedlevelnum;\r
-extern void TEDDeath(void);\r
-\r
-extern word MaxX,MaxY; // MDM (GAMERS EDGE)\r
-\r
-extern boolean ingame, // Set by game code if a game is in progress\r
- abortgame, // Set if a game load failed\r
- loadedgame, // Set if the current game was loaded\r
- NoWait,\r
- HighScoresDirty;\r
-extern char *abortprogram; // Set to error msg if program is dying\r
-extern GameDiff restartgame; // Normally gd_Continue, else starts game\r
-extern word PrintX,PrintY; // Current printing location in the window\r
-extern word WindowX,WindowY,// Current location of window\r
- WindowW,WindowH;// Current size of window\r
-\r
-extern boolean Button0,Button1,\r
- CursorBad;\r
-extern int CursorX,CursorY;\r
-\r
-extern void (*USL_MeasureString)(char far *,word *,word *),\r
- (*USL_DrawString)(char far *);\r
-\r
-extern boolean (*USL_SaveGame)(int),(*USL_LoadGame)(int);\r
-extern void (*USL_ResetGame)(void);\r
-extern SaveGame Games[MaxSaveGames];\r
-extern HighScore Scores[];\r
-\r
-#define US_HomeWindow() {PrintX = WindowX; PrintY = WindowY;}\r
-\r
-extern void US_Startup(void),\r
- US_Setup(void),\r
- US_Shutdown(void),\r
- US_InitRndT(boolean randomize),\r
- US_SetLoadSaveHooks(boolean (*load)(int),\r
- boolean (*save)(int),\r
- void (*reset)(void)),\r
- US_TextScreen(void),\r
- US_UpdateTextScreen(void),\r
- US_FinishTextScreen(void),\r
- US_ControlPanel(void),\r
- US_DrawWindow(word x,word y,word w,word h),\r
- US_CenterWindow(word,word),\r
- US_SaveWindow(WindowRec *win),\r
- US_RestoreWindow(WindowRec *win),\r
- US_ClearWindow(void),\r
- US_SetPrintRoutines(void (*measure)(char far *,word *,word *),\r
- void (*print)(char far *)),\r
- US_PrintCentered(char *s),\r
- US_CPrint(char *s),\r
- US_CPrintLine(char *s),\r
- US_Print(char *s),\r
- US_PrintUnsigned(longword n),\r
- US_PrintSigned(long n),\r
- US_StartCursor(void),\r
- US_ShutCursor(void),\r
- US_ControlPanel(void),\r
- US_CheckHighScore(long score,word other),\r
- US_DisplayHighScores(int which);\r
-extern boolean US_UpdateCursor(void),\r
- US_LineInput(int x,int y,char *buf,char *def,boolean escok,\r
- int maxchars,int maxwidth);\r
-extern int US_CheckParm(char *parm,char **strings),\r
- US_RndT(void);\r
-\r
- void USL_PrintInCenter(char *s,Rect r);\r
- char *USL_GiveSaveName(word game);\r
-#endif\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_US_1.c - User Manager - General routines\r
-// v1.1d1\r
-// By Jason Blochowiak\r
-// Hacked up for Catacomb 3D\r
-//\r
-\r
-//\r
-// This module handles dealing with user input & feedback\r
-//\r
-// Depends on: Input Mgr, View Mgr, some variables from the Sound, Caching,\r
-// and Refresh Mgrs, Memory Mgr for background save/restore\r
-//\r
-// Globals:\r
-// ingame - Flag set by game indicating if a game is in progress\r
-// abortgame - Flag set if the current game should be aborted (if a load\r
-// game fails)\r
-// loadedgame - Flag set if a game was loaded\r
-// abortprogram - Normally nil, this points to a terminal error message\r
-// if the program needs to abort\r
-// restartgame - Normally set to gd_Continue, this is set to one of the\r
-// difficulty levels if a new game should be started\r
-// PrintX, PrintY - Where the User Mgr will print (global coords)\r
-// WindowX,WindowY,WindowW,WindowH - The dimensions of the current\r
-// window\r
-//\r
-\r
-#include "ID_HEADS.H"\r
-\r
-#pragma hdrstop\r
-\r
-#pragma warn -pia\r
-\r
-\r
-// Special imports\r
-extern boolean showscorebox;\r
-#ifdef KEEN\r
-extern boolean oldshooting;\r
-extern ScanCode firescan;\r
-#else\r
- ScanCode firescan;\r
-#endif\r
-\r
-// Global variables\r
- char *abortprogram;\r
- boolean NoWait,\r
- HighScoresDirty;\r
- word PrintX,PrintY;\r
- word WindowX,WindowY,WindowW,WindowH;\r
-\r
- word MaxX=320,MaxY=200; // MDM (GAMERS EDGE)\r
-\r
-// Internal variables\r
-#define ConfigVersion 1\r
-\r
-static char *ParmStrings[] = {"TEDLEVEL","NOWAIT"},\r
- *ParmStrings2[] = {"COMP","NOCOMP"};\r
-static boolean US_Started;\r
-\r
- boolean Button0,Button1,\r
- CursorBad;\r
- int CursorX,CursorY;\r
-\r
- void (*USL_MeasureString)(char far *,word *,word *) = VW_MeasurePropString,\r
- (*USL_DrawString)(char far *) = VWB_DrawPropString;\r
-\r
- boolean (*USL_SaveGame)(int),(*USL_LoadGame)(int);\r
- void (*USL_ResetGame)(void);\r
- SaveGame Games[MaxSaveGames];\r
- HighScore Scores[MaxScores] =\r
- {\r
- {"Sir Lancelot",500,3},\r
- {"",0},\r
- {"",0},\r
- {"",0},\r
- {"",0},\r
- {"",0},\r
- {"",0},\r
- };\r
-\r
-// Internal routines\r
-\r
-// Public routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_HardError() - Handles the Abort/Retry/Fail sort of errors passed\r
-// from DOS.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#pragma warn -par\r
-#pragma warn -rch\r
-int\r
-USL_HardError(word errval,int ax,int bp,int si)\r
-{\r
-#define IGNORE 0\r
-#define RETRY 1\r
-#define ABORT 2\r
-extern void ShutdownId(void);\r
-\r
-static char buf[32];\r
-static WindowRec wr;\r
- int di;\r
- char c,*s,*t;\r
-\r
-\r
- di = _DI;\r
-\r
- if (ax < 0)\r
- s = "Device Error";\r
- else\r
- {\r
- if ((di & 0x00ff) == 0)\r
- s = "Drive ~ is Write Protected";\r
- else\r
- s = "Error on Drive ~";\r
- for (t = buf;*s;s++,t++) // Can't use sprintf()\r
- if ((*t = *s) == '~')\r
- *t = (ax & 0x00ff) + 'A';\r
- *t = '\0';\r
- s = buf;\r
- }\r
-\r
- c = peekb(0x40,0x49); // Get the current screen mode\r
- if ((c < 4) || (c == 7))\r
- goto oh_kill_me;\r
-\r
- // DEBUG - handle screen cleanup\r
-\r
- US_SaveWindow(&wr);\r
- US_CenterWindow(30,3);\r
- US_CPrint(s);\r
- US_CPrint("(R)etry or (A)bort?");\r
- VW_UpdateScreen();\r
- IN_ClearKeysDown();\r
-\r
-asm sti // Let the keyboard interrupts come through\r
-\r
- while (true)\r
- {\r
- switch (IN_WaitForASCII())\r
- {\r
- case key_Escape:\r
- case 'a':\r
- case 'A':\r
- goto oh_kill_me;\r
- break;\r
- case key_Return:\r
- case key_Space:\r
- case 'r':\r
- case 'R':\r
- US_ClearWindow();\r
- VW_UpdateScreen();\r
- US_RestoreWindow(&wr);\r
- return(RETRY);\r
- break;\r
- }\r
- }\r
-\r
-oh_kill_me:\r
- abortprogram = s;\r
- ShutdownId();\r
- fprintf(stderr,"Terminal Error: %s\n",s);\r
- if (tedlevel)\r
- fprintf(stderr,"You launched from TED. I suggest that you reboot...\n");\r
-\r
- return(ABORT);\r
-#undef IGNORE\r
-#undef RETRY\r
-#undef ABORT\r
-}\r
-#pragma warn +par\r
-#pragma warn +rch\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_GiveSaveName() - Returns a pointer to a static buffer that contains\r
-// the filename to use for the specified save game\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-char *\r
-USL_GiveSaveName(word game)\r
-{\r
-static char name[] = "SAVEGAMx."EXT;\r
-\r
- name[7] = '0' + game;\r
- return(name);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_SetLoadSaveHooks() - Sets the routines that the User Mgr calls after\r
-// reading or writing the save game headers\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_SetLoadSaveHooks(boolean (*load)(int),boolean (*save)(int),void (*reset)(void))\r
-{\r
- USL_LoadGame = load;\r
- USL_SaveGame = save;\r
- USL_ResetGame = reset;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_ReadConfig() - Reads the configuration file, if present, and sets\r
-// things up accordingly. If it's not present, uses defaults. This file\r
-// includes the high scores.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_ReadConfig(void)\r
-{\r
- boolean gotit;\r
- char sig[sizeof(EXT)];\r
- word version;\r
- int file;\r
- SDMode sd;\r
- SMMode sm;\r
- ControlType ctl;\r
-\r
- if ((file = open("CONFIG."EXT,O_BINARY | O_RDONLY)) != -1)\r
- {\r
- read(file,sig,sizeof(EXT));\r
- read(file,&version,sizeof(version));\r
- if (strcmp(sig,EXT) || (version != ConfigVersion))\r
- {\r
- close(file);\r
- goto rcfailed;\r
- }\r
- read(file,Scores,sizeof(HighScore) * MaxScores);\r
- read(file,&sd,sizeof(sd));\r
- read(file,&sm,sizeof(sm));\r
- read(file,&ctl,sizeof(ctl));\r
- read(file,&(KbdDefs[0]),sizeof(KbdDefs[0]));\r
- read(file,&showscorebox,sizeof(showscorebox));\r
- read(file,&compatability,sizeof(compatability));\r
-#ifdef KEEN\r
- read(file,&oldshooting,sizeof(oldshooting));\r
- read(file,&firescan,sizeof(firescan));\r
-#endif\r
- close(file);\r
-\r
- HighScoresDirty = false;\r
- gotit = true;\r
- }\r
- else\r
- {\r
-rcfailed:\r
- sd = sdm_Off;\r
- sm = smm_Off;\r
- ctl = ctrl_Keyboard;\r
- showscorebox = true;\r
-#ifdef KEEN\r
- oldshooting = false;\r
-#endif\r
-\r
- gotit = false;\r
- HighScoresDirty = true;\r
- }\r
-\r
- SD_Default(gotit,sd,sm);\r
- IN_Default(gotit,ctl);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_WriteConfig() - Writes out the current configuration, including the\r
-// high scores.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_WriteConfig(void)\r
-{\r
- word version;\r
- int file;\r
-\r
- version = ConfigVersion;\r
- file = open("CONFIG."EXT,O_CREAT | O_BINARY | O_WRONLY,\r
- S_IREAD | S_IWRITE | S_IFREG);\r
- if (file != -1)\r
- {\r
- write(file,EXT,sizeof(EXT));\r
- write(file,&version,sizeof(version));\r
- write(file,Scores,sizeof(HighScore) * MaxScores);\r
- write(file,&SoundMode,sizeof(SoundMode));\r
- write(file,&MusicMode,sizeof(MusicMode));\r
- if // Hack\r
- (\r
- (Controls[0] == ctrl_Joystick1)\r
- || (Controls[0] == ctrl_Joystick2)\r
- )\r
- Controls[0] = ctrl_Keyboard;\r
- write(file,&(Controls[0]),sizeof(Controls[0]));\r
- write(file,&(KbdDefs[0]),sizeof(KbdDefs[0]));\r
- write(file,&showscorebox,sizeof(showscorebox));\r
- write(file,&compatability,sizeof(compatability));\r
-#ifdef KEEN\r
- write(file,&oldshooting,sizeof(oldshooting));\r
- write(file,&firescan,sizeof(firescan));\r
-#endif\r
- close(file);\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_CheckSavedGames() - Checks to see which saved games are present\r
-// & valid\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_CheckSavedGames(void)\r
-{\r
- boolean ok;\r
- char *filename;\r
- word i;\r
- int file;\r
- SaveGame *game;\r
-\r
- USL_SaveGame = 0;\r
- USL_LoadGame = 0;\r
-\r
- for (i = 0,game = Games;i < MaxSaveGames;i++,game++)\r
- {\r
- filename = USL_GiveSaveName(i);\r
- ok = false;\r
- if ((file = open(filename,O_BINARY | O_RDONLY)) != -1)\r
- {\r
- if\r
- (\r
- (read(file,game,sizeof(*game)) == sizeof(*game))\r
- && (!strcmp(game->signature,EXT))\r
- && (game->oldtest == &PrintX)\r
- )\r
- ok = true;\r
-\r
- close(file);\r
- }\r
-\r
- if (ok)\r
- game->present = true;\r
- else\r
- {\r
- strcpy(game->signature,EXT);\r
- game->present = false;\r
- strcpy(game->name,"Empty");\r
- }\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_Startup() - Starts the User Mgr\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_Startup(void)\r
-{\r
- int i;\r
-\r
- if (US_Started)\r
- return;\r
-\r
- harderr(USL_HardError); // Install the fatal error handler\r
-\r
- US_InitRndT(true); // Initialize the random number generator\r
-\r
- USL_ReadConfig(); // Read config file\r
-\r
- for (i = 1;i < _argc;i++)\r
- {\r
- switch (US_CheckParm(_argv[i],ParmStrings2))\r
- {\r
- case 0:\r
- if (grmode == EGAGR)\r
- compatability = true;\r
- break;\r
- case 1:\r
- compatability = false;\r
- break;\r
- }\r
- }\r
-\r
- US_Started = true;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_Setup() - Does the disk access part of the User Mgr's startup\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_Setup(void)\r
-{\r
- USL_CheckSavedGames(); // Check which saved games are present\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_Shutdown() - Shuts down the User Mgr\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_Shutdown(void)\r
-{\r
- if (!US_Started)\r
- return;\r
-\r
- if (!abortprogram)\r
- USL_WriteConfig();\r
-\r
- US_Started = false;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_CheckParm() - checks to see if a string matches one of a set of\r
-// strings. The check is case insensitive. The routine returns the\r
-// index of the string that matched, or -1 if no matches were found\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-int\r
-US_CheckParm(char *parm,char **strings)\r
-{\r
- char cp,cs,\r
- *p,*s;\r
- int i;\r
-\r
- while (!isalpha(*parm)) // Skip non-alphas\r
- parm++;\r
-\r
- for (i = 0;*strings && **strings;i++)\r
- {\r
- for (s = *strings++,p = parm,cs = cp = 0;cs == cp;)\r
- {\r
- cs = *s++;\r
- if (!cs)\r
- return(i);\r
- cp = *p++;\r
-\r
- if (isupper(cs))\r
- cs = tolower(cs);\r
- if (isupper(cp))\r
- cp = tolower(cp);\r
- }\r
- }\r
- return(-1);\r
-}\r
-\r
-#if 0\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_ScreenDraw() - Draws a chunk of the text screen (called only by\r
-// US_TextScreen())\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_ScreenDraw(word x,word y,char *s,byte attr)\r
-{\r
- byte far *screen,far *oscreen;\r
-\r
- screen = MK_FP(0xb800,(x * 2) + (y * 80 * 2));\r
- oscreen = (&introscn + 7) + ((x - 1) * 2) + (y * 80 * 2) + 1;\r
- while (*s)\r
- {\r
- *screen++ = *s++;\r
- if (attr != 0xff)\r
- {\r
- *screen++ = (attr & 0x8f) | (*oscreen & 0x70);\r
- oscreen += 2;\r
- }\r
- else\r
- screen++;\r
- }\r
-}\r
-#endif\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_ClearTextScreen() - Makes sure the screen is in text mode, clears it,\r
-// and moves the cursor to the leftmost column of the bottom line\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_ClearTextScreen(void)\r
-{\r
- // Set to 80x25 color text mode\r
- _AL = 3; // Mode 3\r
- _AH = 0x00;\r
- geninterrupt(0x10);\r
-\r
- // Use BIOS to move the cursor to the bottom of the screen\r
- _AH = 0x0f;\r
- geninterrupt(0x10); // Get current video mode into _BH\r
- _DL = 0; // Lefthand side of the screen\r
- _DH = 24; // Bottom row\r
- _AH = 0x02;\r
- geninterrupt(0x10);\r
-}\r
-\r
-#if 0\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_TextScreen() - Puts up the startup text screen\r
-// Note: These are the only User Manager functions that can be safely called\r
-// before the User Mgr has been started up\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_TextScreen(void)\r
-{\r
- word i,n;\r
-\r
- USL_ClearTextScreen();\r
-\r
- _fmemcpy(MK_FP(0xb800,0),7 + &introscn,80 * 25 * 2);\r
-\r
- // Check for TED launching here\r
- for (i = 1;i < _argc;i++)\r
- {\r
- n = US_CheckParm(_argv[i],ParmStrings);\r
- if (n == 0)\r
- {\r
- tedlevelnum = atoi(_argv[i + 1]);\r
- if (tedlevelnum >= 0)\r
- {\r
- tedlevel = true;\r
- return;\r
- }\r
- else\r
- break;\r
- }\r
- else if (n == 1)\r
- {\r
- NoWait = true;\r
- return;\r
- }\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_Show() - Changes the appearance of one of the fields on the text\r
-// screen. Possibly adds a checkmark in front of it and highlights it\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_Show(word x,word y,word w,boolean show,boolean hilight)\r
-{\r
- byte far *screen,far *oscreen;\r
-\r
- screen = MK_FP(0xb800,((x - 1) * 2) + (y * 80 * 2));\r
- oscreen = (&introscn + 7) + ((x - 1) * 2) + (y * 80 * 2) - 1;\r
- *screen++ = show? 251 : ' '; // Checkmark char or space\r
-// *screen = 0x48;\r
-// *screen = (*oscreen & 0xf0) | 8;\r
- oscreen += 2;\r
- if (show && hilight)\r
- {\r
- for (w++;w--;screen += 2,oscreen += 2)\r
- *screen = (*oscreen & 0xf0) | 0x0f;\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_ShowMem() - Right justifies a longword in one of the memory fields on\r
-// the text screen\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_ShowMem(word x,word y,long mem)\r
-{\r
- char buf[16];\r
- word i;\r
-\r
- for (i = strlen(ltoa(mem,buf,10));i < 5;i++)\r
- USL_ScreenDraw(x++,y," ",0xff);\r
- USL_ScreenDraw(x,y,buf,0xff);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_UpdateTextScreen() - Called after the ID libraries are started up.\r
-// Displays what hardware is present.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_UpdateTextScreen(void)\r
-{\r
- boolean b;\r
- longword totalmem;\r
-\r
- // Show video card info\r
- b = (grmode == CGAGR);\r
- USL_Show(21,7,4,(videocard >= CGAcard) && (videocard <= VGAcard),b);\r
- b = (grmode == EGAGR);\r
- USL_Show(21,8,4,(videocard >= EGAcard) && (videocard <= VGAcard),b);\r
- b = (grmode == VGAGR);\r
- USL_Show(21,9,4,videocard == VGAcard,b);\r
- if (compatability)\r
- USL_ScreenDraw(5,10,"SVGA Compatibility Mode Enabled.",0x4f);\r
-\r
- // Show input device info\r
- USL_Show(60,7,8,true,true);\r
- USL_Show(60,8,11,JoysPresent[0],true);\r
- USL_Show(60,9,11,JoysPresent[1],true);\r
- USL_Show(60,10,5,MousePresent,true);\r
-\r
- // Show sound hardware info\r
- USL_Show(21,14,11,true,SoundMode == sdm_PC);\r
- b = (SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib);\r
- USL_Show(21,15,14,AdLibPresent,b);\r
- if (b && AdLibPresent) // Hack because of two lines\r
- {\r
- byte far *screen,far *oscreen;\r
- word x,y,w;\r
-\r
- x = 21;\r
- y = 16;\r
- w = 14;\r
- screen = MK_FP(0xb800,(x * 2) + (y * 80 * 2) - 1);\r
- oscreen = (&introscn + 7) + (x * 2) + (y * 80 * 2) - 1;\r
- oscreen += 2;\r
- for (w++;w--;screen += 2,oscreen += 2)\r
- *screen = (*oscreen & 0xf0) | 0x0f;\r
- }\r
-\r
- // Show memory available/used\r
- USL_ShowMem(63,15,mminfo.mainmem / 1024);\r
- USL_Show(53,15,23,true,true);\r
- USL_ShowMem(63,16,mminfo.EMSmem / 1024);\r
- USL_Show(53,16,23,mminfo.EMSmem? true : false,true);\r
- USL_ShowMem(63,17,mminfo.XMSmem / 1024);\r
- USL_Show(53,17,23,mminfo.XMSmem? true : false,true);\r
- totalmem = mminfo.mainmem + mminfo.EMSmem + mminfo.XMSmem;\r
- USL_ShowMem(63,18,totalmem / 1024);\r
- USL_Show(53,18,23,true,true); // DEBUG\r
- USL_ScreenDraw(52,18," ",0xff);\r
-\r
- // Change Initializing... to Loading...\r
- USL_ScreenDraw(27,22," Loading... ",0x9c);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_FinishTextScreen() - After the main program has finished its initial\r
-// loading, this routine waits for a keypress and then clears the screen\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_FinishTextScreen(void)\r
-{\r
-static byte colors[] = {4,6,13,15,15,15,15,15,15};\r
- boolean up;\r
- int i,c;\r
-\r
- // Change Loading... to Press a Key\r
-\r
- if (!(tedlevel || NoWait))\r
- {\r
- IN_ClearKeysDown();\r
- for (i = 0,up = true;!IN_UserInput(4,true);)\r
- {\r
- c = colors[i];\r
- if (up)\r
- {\r
- if (++i == 9)\r
- i = 8,up = false;\r
- }\r
- else\r
- {\r
- if (--i < 0)\r
- i = 1,up = true;\r
- }\r
-\r
- USL_ScreenDraw(29,22," Ready - Press a Key ",0x00 + c);\r
- }\r
- }\r
- else\r
- USL_ScreenDraw(29,22," Ready - Press a Key ",0x9a);\r
- IN_ClearKeysDown();\r
-\r
- USL_ClearTextScreen();\r
-}\r
-#endif\r
-\r
-// Window/Printing routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_SetPrintRoutines() - Sets the routines used to measure and print\r
-// from within the User Mgr. Primarily provided to allow switching\r
-// between masked and non-masked fonts\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_SetPrintRoutines(void (*measure)(char far *,word *,word *),void (*print)(char far *))\r
-{\r
- USL_MeasureString = measure;\r
- USL_DrawString = print;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_Print() - Prints a string in the current window. Newlines are\r
-// supported.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_Print(char *s)\r
-{\r
- char c,*se;\r
- word w,h;\r
-\r
- while (*s)\r
- {\r
- se = s;\r
- while ((c = *se) && (c != '\n'))\r
- se++;\r
- *se = '\0';\r
-\r
- USL_MeasureString(s,&w,&h);\r
- px = PrintX;\r
- py = PrintY;\r
- USL_DrawString(s);\r
-\r
- s = se;\r
- if (c)\r
- {\r
- *se = c;\r
- s++;\r
-\r
- PrintX = WindowX;\r
- PrintY += h;\r
- }\r
- else\r
- PrintX += w;\r
- }\r
-}\r
-\r
-// MDM - (GAMERS EDGE) begin\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_Printxy()\r
-//\r
-void US_Printxy(word x, word y, char *text)\r
-{\r
- word orgx, orgy;\r
-\r
- orgx = PrintX;\r
- orgy = PrintY;\r
-\r
-// PrintX = WindowX+x;\r
-// PrintY = WindowY+y;\r
- PrintX = x;\r
- PrintY = y;\r
- US_Print(text);\r
-\r
- PrintX = orgx;\r
- PrintY = orgy;\r
-}\r
-\r
-// MDM - (GAMERS EDGE) end\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_PrintUnsigned() - Prints an unsigned long\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_PrintUnsigned(longword n)\r
-{\r
- char buffer[32];\r
-\r
- US_Print(ultoa(n,buffer,10));\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_PrintSigned() - Prints a signed long\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_PrintSigned(long n)\r
-{\r
- char buffer[32];\r
-\r
- US_Print(ltoa(n,buffer,10));\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_PrintInCenter() - Prints a string in the center of the given rect\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-USL_PrintInCenter(char *s,Rect r)\r
-{\r
- word w,h,\r
- rw,rh;\r
-\r
- USL_MeasureString(s,&w,&h);\r
- rw = r.lr.x - r.ul.x;\r
- rh = r.lr.y - r.ul.y;\r
-\r
- px = r.ul.x + ((rw - w) / 2);\r
- py = r.ul.y + ((rh - h) / 2);\r
- USL_DrawString(s);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_PrintCentered() - Prints a string centered in the current window.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_PrintCentered(char *s)\r
-{\r
- Rect r;\r
-\r
- r.ul.x = WindowX;\r
- r.ul.y = WindowY;\r
- r.lr.x = r.ul.x + WindowW;\r
- r.lr.y = r.ul.y + WindowH;\r
-\r
- USL_PrintInCenter(s,r);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_CPrintLine() - Prints a string centered on the current line and\r
-// advances to the next line. Newlines are not supported.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_CPrintLine(char *s)\r
-{\r
- word w,h;\r
-\r
- USL_MeasureString(s,&w,&h);\r
-\r
- if (w > WindowW)\r
- Quit("US_CPrintLine() - String exceeds width");\r
- px = WindowX + ((WindowW - w) / 2);\r
- py = PrintY;\r
- USL_DrawString(s);\r
- PrintY += h;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_CPrint() - Prints a string in the current window. Newlines are\r
-// supported.\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_CPrint(char *s)\r
-{\r
- char c,*se;\r
-\r
- while (*s)\r
- {\r
- se = s;\r
- while ((c = *se) && (c != '\n'))\r
- se++;\r
- *se = '\0';\r
-\r
- US_CPrintLine(s);\r
-\r
- s = se;\r
- if (c)\r
- {\r
- *se = c;\r
- s++;\r
- }\r
- }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_ClearWindow() - Clears the current window to white and homes the\r
-// cursor\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_ClearWindow(void)\r
-{\r
- VWB_Bar(WindowX,WindowY,WindowW,WindowH,LT_GREY);\r
- PrintX = WindowX;\r
- PrintY = WindowY;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_DrawWindow() - Draws a frame and sets the current window parms\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_DrawWindow(word x,word y,word w,word h)\r
-{\r
- word i,\r
- sx,sy,sw,sh;\r
-\r
- WindowX = x * 8;\r
- WindowY = y * 8;\r
- WindowW = w * 8;\r
- WindowH = h * 8;\r
-\r
- PrintX = WindowX;\r
- PrintY = WindowY;\r
-\r
- sx = (x - 1) * 8;\r
- sy = (y - 1) * 8;\r
- sw = (w + 1) * 8;\r
- sh = (h + 1) * 8;\r
-\r
- US_ClearWindow();\r
-\r
- VWB_DrawTile8M(sx,sy,0),VWB_DrawTile8M(sx,sy + sh,6);\r
- for (i = sx + 8;i <= sx + sw - 8;i += 8)\r
- VWB_DrawTile8M(i,sy,1),VWB_DrawTile8M(i,sy + sh,7);\r
- VWB_DrawTile8M(i,sy,2),VWB_DrawTile8M(i,sy + sh,8);\r
-\r
- for (i = sy + 8;i <= sy + sh - 8;i += 8)\r
- VWB_DrawTile8M(sx,i,3),VWB_DrawTile8M(sx + sw,i,5);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_CenterWindow() - Generates a window of a given width & height in the\r
-// middle of the screen\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_CenterWindow(word w,word h)\r
-{\r
- US_DrawWindow(((MaxX / 8) - w) / 2,((MaxY / 8) - h) / 2,w,h);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_CenterSaveWindow() - Generates a window of a given width & height in\r
-// the middle of the screen, saving the background\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_CenterSaveWindow(word w,word h,memptr *save)\r
-{\r
- word x,y,\r
- screen;\r
-\r
- x = ((MaxX / 8) - w) / 2;\r
- y = ((MaxY / 8) - h) / 2;\r
- MM_GetPtr(save,(w * h) * CHARWIDTH);\r
- screen = bufferofs + panadjust + ylookup[y] + (x * CHARWIDTH);\r
- VW_ScreenToMem(screen,*save,w * CHARWIDTH,h);\r
- US_DrawWindow(((MaxX / 8) - w) / 2,((MaxY / 8) - h) / 2,w,h);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_RestoreSaveWindow() - Restores the background of the size of the\r
-// current window from the memory specified by save\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_RestoreSaveWindow(memptr *save)\r
-{\r
- word screen;\r
-\r
- screen = bufferofs + panadjust + ylookup[WindowY] + (WindowX * CHARWIDTH);\r
- VW_MemToScreen(*save,screen,WindowW * CHARWIDTH,WindowH);\r
- MM_FreePtr(save);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_SaveWindow() - Saves the current window parms into a record for\r
-// later restoration\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_SaveWindow(WindowRec *win)\r
-{\r
- win->x = WindowX;\r
- win->y = WindowY;\r
- win->w = WindowW;\r
- win->h = WindowH;\r
-\r
- win->px = PrintX;\r
- win->py = PrintY;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_RestoreWindow() - Sets the current window parms to those held in the\r
-// record\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_RestoreWindow(WindowRec *win)\r
-{\r
- WindowX = win->x;\r
- WindowY = win->y;\r
- WindowW = win->w;\r
- WindowH = win->h;\r
-\r
- PrintX = win->px;\r
- PrintY = win->py;\r
-}\r
-\r
-// Cursor routines\r
-\r
-#if 0\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_StartCursor() - Sets up the cursor for User Mgr use\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_StartCursor(void)\r
-{\r
- CursorInfo info;\r
-\r
- VW_SetCursor(CURSORARROWSPR);\r
- CursorX = MaxX / 2;\r
- CursorY = MaxY / 2;\r
- VW_MoveCursor(CursorX,CursorY);\r
- VW_ShowCursor();\r
-\r
- IN_ReadCursor(&info); // Dispose of any accumulated movement\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_ShutCursor() - Cleans up after US_StartCursor()\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-void\r
-US_ShutCursor(void)\r
-{\r
- VW_HideCursor();\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_UpdateCursor() - Gets the new cursor position & button states from\r
-// the Input Mgr and tells the View Mgr where the cursor is\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-US_UpdateCursor(void)\r
-{\r
- CursorInfo info;\r
-\r
- IN_ReadCursor(&info);\r
- if (info.x || info.y || CursorBad)\r
- {\r
- CursorX += info.x;\r
- if (CursorX >= MaxX)\r
- CursorX = MaxX - 1;\r
- else if (CursorX < 0)\r
- CursorX = 0;\r
-\r
- CursorY += info.y;\r
- if (CursorY >= MaxY)\r
- CursorY = MaxY - 1;\r
- else if (CursorY < 0)\r
- CursorY = 0;\r
-\r
- VW_MoveCursor(CursorX,CursorY);\r
- CursorBad = false;\r
- }\r
- Button0 = info.button0;\r
- Button1 = info.button1;\r
- return(Button0 || Button1);\r
-}\r
-#endif\r
-\r
-// Input routines\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_XORICursor() - XORs the I-bar text cursor. Used by US_LineInput()\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_XORICursor(int x,int y,char *s,word cursor)\r
-{\r
- char buf[MaxString];\r
- word w,h;\r
-\r
- strcpy(buf,s);\r
- buf[cursor] = '\0';\r
- USL_MeasureString(buf,&w,&h);\r
-\r
- px = x + w - 1;\r
- py = y;\r
- USL_DrawString("\x80");\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_LineInput() - Gets a line of user input at (x,y), the string defaults\r
-// to whatever is pointed at by def. Input is restricted to maxchars\r
-// chars or maxwidth pixels wide. If the user hits escape (and escok is\r
-// true), nothing is copied into buf, and false is returned. If the\r
-// user hits return, the current string is copied into buf, and true is\r
-// returned\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-boolean\r
-US_LineInput(int x,int y,char *buf,char *def,boolean escok,\r
- int maxchars,int maxwidth)\r
-{\r
- boolean redraw,\r
- cursorvis,cursormoved,\r
- done,result;\r
- ScanCode sc;\r
- char c,\r
- s[MaxString],olds[MaxString];\r
- word i,\r
- cursor,\r
- w,h,\r
- len;\r
- longword lasttime;\r
-\r
- VW_HideCursor();\r
-\r
- if (def)\r
- strcpy(s,def);\r
- else\r
- *s = '\0';\r
- *olds = '\0';\r
- cursor = strlen(s);\r
- cursormoved = redraw = true;\r
-\r
- cursorvis = done = false;\r
- lasttime = TimeCount;\r
- LastASCII = key_None;\r
- LastScan = sc_None;\r
-\r
- while (!done)\r
- {\r
- if (cursorvis)\r
- USL_XORICursor(x,y,s,cursor);\r
-\r
- asm pushf\r
- asm cli\r
-\r
- sc = LastScan;\r
- LastScan = sc_None;\r
- c = LastASCII;\r
- LastASCII = key_None;\r
-\r
- asm popf\r
-\r
- switch (sc)\r
- {\r
- case sc_LeftArrow:\r
- if (cursor)\r
- cursor--;\r
- c = key_None;\r
- cursormoved = true;\r
- break;\r
- case sc_RightArrow:\r
- if (s[cursor])\r
- cursor++;\r
- c = key_None;\r
- cursormoved = true;\r
- break;\r
- case sc_Home:\r
- cursor = 0;\r
- c = key_None;\r
- cursormoved = true;\r
- break;\r
- case sc_End:\r
- cursor = strlen(s);\r
- c = key_None;\r
- cursormoved = true;\r
- break;\r
-\r
- case sc_Return:\r
- strcpy(buf,s);\r
- done = true;\r
- result = true;\r
- c = key_None;\r
- break;\r
- case sc_Escape:\r
- if (escok)\r
- {\r
- done = true;\r
- result = false;\r
- }\r
- c = key_None;\r
- break;\r
-\r
- case sc_BackSpace:\r
- if (cursor)\r
- {\r
- strcpy(s + cursor - 1,s + cursor);\r
- cursor--;\r
- redraw = true;\r
- }\r
- c = key_None;\r
- cursormoved = true;\r
- break;\r
- case sc_Delete:\r
- if (s[cursor])\r
- {\r
- strcpy(s + cursor,s + cursor + 1);\r
- redraw = true;\r
- }\r
- c = key_None;\r
- cursormoved = true;\r
- break;\r
-\r
- case 0x4c: // Keypad 5\r
- case sc_UpArrow:\r
- case sc_DownArrow:\r
- case sc_PgUp:\r
- case sc_PgDn:\r
- case sc_Insert:\r
- c = key_None;\r
- break;\r
- }\r
-\r
- if (c)\r
- {\r
- len = strlen(s);\r
- USL_MeasureString(s,&w,&h);\r
-\r
- if\r
- (\r
- isprint(c)\r
- && (len < MaxString - 1)\r
- && ((!maxchars) || (len < maxchars))\r
- && ((!maxwidth) || (w < maxwidth))\r
- )\r
- {\r
- for (i = len + 1;i > cursor;i--)\r
- s[i] = s[i - 1];\r
- s[cursor++] = c;\r
- redraw = true;\r
- }\r
- }\r
-\r
- if (redraw)\r
- {\r
- px = x;\r
- py = y;\r
- USL_DrawString(olds);\r
- strcpy(olds,s);\r
-\r
- px = x;\r
- py = y;\r
- USL_DrawString(s);\r
-\r
- redraw = false;\r
- }\r
-\r
- if (cursormoved)\r
- {\r
- cursorvis = false;\r
- lasttime = TimeCount - TickBase;\r
-\r
- cursormoved = false;\r
- }\r
- if (TimeCount - lasttime > TickBase / 2)\r
- {\r
- lasttime = TimeCount;\r
-\r
- cursorvis ^= true;\r
- }\r
- if (cursorvis)\r
- USL_XORICursor(x,y,s,cursor);\r
-\r
- VW_UpdateScreen();\r
- }\r
-\r
- if (cursorvis)\r
- USL_XORICursor(x,y,s,cursor);\r
- if (!result)\r
- {\r
- px = x;\r
- py = y;\r
- USL_DrawString(olds);\r
- }\r
- VW_ShowCursor();\r
- VW_UpdateScreen();\r
-\r
- IN_ClearKeysDown();\r
- return(result);\r
-}\r
-\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//\r
-// ID Engine\r
-// ID_US.c - User Manager - User interface\r
-// v1.1d1\r
-// By Jason Blochowiak\r
-// Hacked up for Catacomb 3D\r
-//\r
-\r
-#include "ID_HEADS.H"\r
-#pragma hdrstop\r
-\r
-#pragma warn -pia\r
-\r
-// Special imports\r
-extern boolean showscorebox;\r
-#ifdef KEEN\r
-extern boolean oldshooting;\r
-extern ScanCode firescan;\r
-#else\r
- ScanCode firescan;\r
-#endif\r
-\r
-// Global variables\r
- boolean ingame,abortgame,loadedgame;\r
- GameDiff restartgame = gd_Continue;\r
-\r
-// Internal variables\r
-static boolean GameIsDirty,\r
- QuitToDos,\r
- CtlPanelDone;\r
-\r
-// Forward reference prototypes\r
-static void USL_SetupCard(void);\r
-\r
-// Control panel data\r
-\r
-#define CtlPanelSX 74\r
-#define CtlPanelSY 48\r
-#define CtlPanelEX 234\r
-#define CtlPanelEY 150\r
-#define CtlPanelW (CtlPanelEX - CtlPanelSX)\r
-#define CtlPanelH (CtlPanelEY - CtlPanelSY)\r
-\r
-#define TileBase 92\r
-\r
-// DEBUG - CGA\r
-#define BackColor 0\r
-#define HiliteColor (BackColor ^ 12)\r
-#define NohiliteColor (BackColor ^ 4)\r
-\r
-typedef enum\r
- {\r
- uc_None,\r
- uc_Return,\r
- uc_Abort,\r
- uc_Quit,\r
- uc_Loaded,\r
- uc_SEasy,\r
- uc_SNormal,\r
- uc_SHard,\r
- } UComm;\r
-typedef enum\r
- {\r
- uii_Bad,\r
- uii_Button,uii_RadioButton,uii_Folder\r
- } UIType;\r
-typedef enum\r
- {\r
- ui_Normal = 0,\r
- ui_Pushed = 1,\r
- ui_Selected = 2,\r
- ui_Disabled = 4,\r
- ui_Separated = 8\r
- } UIFlags;\r
-#define UISelectFlags (ui_Pushed | ui_Selected | ui_Disabled)\r
-\r
-typedef enum\r
- {\r
- uic_SetupCard,uic_DrawCard,uic_TouchupCard,\r
- uic_DrawIcon,uic_Draw,uic_Hit\r
- } UserCall;\r
-\r
-typedef struct UserItem\r
- {\r
- UIType type;\r
- UIFlags flags;\r
- ScanCode hotkey;\r
- char *text;\r
- UComm comm;\r
- void far *child; // Should be (UserItemGroup *)\r
-\r
- word x,y;\r
- } UserItem;\r
-typedef struct UserItemGroup\r
- {\r
- word x,y;\r
- graphicnums title;\r
- ScanCode hotkey;\r
- UserItem far *items;\r
- boolean (*custom)(UserCall,struct UserItem far *); // Custom routine\r
-\r
- word cursor;\r
- struct UserItemGroup far *parent;\r
- } UserItemGroup;\r
-\r
-static char *BottomS1,*BottomS2,*BottomS3;\r
-static UComm Communication;\r
-static ScanCode *KeyMaps[] =\r
- {\r
- &KbdDefs[0].button0,\r
- &KbdDefs[0].button1,\r
- &firescan,\r
- &KbdDefs[0].upleft,\r
- &KbdDefs[0].up,\r
- &KbdDefs[0].upright,\r
- &KbdDefs[0].right,\r
- &KbdDefs[0].downright,\r
- &KbdDefs[0].down,\r
- &KbdDefs[0].downleft,\r
- &KbdDefs[0].left\r
- };\r
-\r
-// Custom routine prototypes\r
-static boolean USL_ConfigCustom(UserCall call,struct UserItem far *item),\r
- USL_KeyCustom(UserCall call,struct UserItem far *item),\r
- USL_KeySCustom(UserCall call,struct UserItem far *item),\r
- USL_Joy1Custom(UserCall call,struct UserItem far *item),\r
- USL_Joy2Custom(UserCall call,struct UserItem far *item),\r
- USL_LoadCustom(UserCall call,struct UserItem far *item),\r
- USL_SaveCustom(UserCall call,struct UserItem far *item),\r
- USL_ScoreCustom(UserCall call,struct UserItem far *item),\r
- USL_CompCustom(UserCall call,struct UserItem far *item);\r
-#ifdef KEEN\r
- USL_TwoCustom(UserCall call,struct UserItem far *item),\r
-#endif\r
-// USL_PongCustom(UserCall call,struct UserItem far *item);\r
-\r
-#define DefButton(key,text) uii_Button,ui_Normal,key,text\r
-#define DefRButton(key,text) uii_RadioButton,ui_Normal,key,text\r
-#define DefFolder(key,text,child) uii_Folder,ui_Normal,key,text,uc_None,child\r
-#define CustomGroup(title,key,custom) 0,0,title,key,0,custom\r
- UserItem far holder[] =\r
- {\r
- {DefButton(sc_None,"DEBUG")},\r
- {uii_Bad}\r
- };\r
- UserItemGroup far holdergroup = {0,0,CP_MAINMENUPIC,sc_None,holder};\r
-\r
- // Sound menu\r
- UserItem far soundi[] =\r
- {\r
- {DefRButton(sc_N,"NO SOUND EFFECTS")},\r
- {DefRButton(sc_P,"PC SPEAKER")},\r
- {DefRButton(sc_A,"ADLIB/SOUNDBLASTER")},\r
- {uii_Bad}\r
- };\r
- UserItemGroup far soundgroup = {8,0,CP_SOUNDMENUPIC,sc_None,soundi};\r
-\r
- // Music menu\r
- UserItem far musici[] =\r
- {\r
- {DefRButton(sc_N,"NO MUSIC")},\r
- {DefRButton(sc_A,"ADLIB/SOUNDBLASTER")},\r
- {uii_Bad}\r
- };\r
- UserItemGroup far musicgroup = {8,0,CP_MUSICMENUPIC,sc_None,musici};\r
-\r
- // New game menu\r
- UserItem far newgamei[] =\r
- {\r
- {DefButton(sc_E,"BEGIN EASY GAME"),uc_SEasy},\r
- {DefButton(sc_N,"BEGIN NORMAL GAME"),uc_SNormal},\r
- {DefButton(sc_H,"BEGIN HARD GAME"),uc_SHard},\r
- {uii_Bad}\r
- };\r
- UserItemGroup far newgamegroup = {8,0,CP_NEWGAMEMENUPIC,sc_None,newgamei,0,1};\r
-\r
- // Load/Save game menu\r
- UserItem far loadsavegamei[] =\r
- {\r
- {uii_Button,ui_Normal,sc_None},\r
- {uii_Button,ui_Normal,sc_None},\r
- {uii_Button,ui_Normal,sc_None},\r
- {uii_Button,ui_Normal,sc_None},\r
- {uii_Button,ui_Normal,sc_None},\r
- {uii_Button,ui_Normal,sc_None},\r
- {uii_Bad}\r
- };\r
- UserItemGroup far loadgamegroup = {4,3,CP_LOADMENUPIC,sc_None,loadsavegamei,USL_LoadCustom};\r
- UserItemGroup far savegamegroup = {4,3,CP_SAVEMENUPIC,sc_None,loadsavegamei,USL_SaveCustom};\r
-\r
- // Options menu\r
- UserItemGroup far scoregroup = {0,0,0,sc_None,0,USL_ScoreCustom};\r
- UserItemGroup far compgroup = {0,0,0,sc_None,0,USL_CompCustom};\r
-#ifdef KEEN\r
- UserItemGroup far twogroup = {0,0,0,sc_None,0,USL_TwoCustom};\r
-#endif\r
- UserItem far optionsi[] =\r
- {\r
- {DefFolder(sc_S,"",&scoregroup)},\r
- {DefFolder(sc_C,"",&compgroup)},\r
-#ifdef KEEN\r
- {DefFolder(sc_T,"",&twogroup)},\r
-#endif\r
- {uii_Bad}\r
- };\r
- UserItemGroup far optionsgroup = {8,0,CP_OPTIONSMENUPIC,sc_None,optionsi};\r
-\r
- // Keyboard menu\r
- UserItem far keyi[] =\r
- {\r
- {DefButton(sc_None,"UP & LEFT")},\r
- {DefButton(sc_None,"UP")},\r
- {DefButton(sc_None,"UP & RIGHT")},\r
- {DefButton(sc_None,"RIGHT")},\r
- {DefButton(sc_None,"DOWN & RIGHT")},\r
- {DefButton(sc_None,"DOWN")},\r
- {DefButton(sc_None,"DOWN & LEFT")},\r
- {DefButton(sc_None,"LEFT")},\r
- {uii_Bad}\r
- };\r
- UserItemGroup far keygroup = {0,0,CP_KEYMOVEMENTPIC,sc_None,keyi,USL_KeyCustom};\r
- UserItem far keybi[] =\r
- {\r
-#ifdef KEEN\r
- {DefButton(sc_J,"JUMP")},\r
- {DefButton(sc_P,"POGO")},\r
- {DefButton(sc_F,"FIRE")},\r
-#endif\r
-#ifdef CAT3D\r
- {DefButton(sc_J,"FIRE")},\r
- {DefButton(sc_P,"STRAFE")},\r
-#endif\r
-#ifdef CPD\r
- {DefButton(sc_J,"SHOOT")},\r
- {DefButton(sc_P,"BOMB")},\r
-#endif\r
- {uii_Bad}\r
- };\r
- UserItemGroup far keybgroup = {0,0,CP_KEYBUTTONPIC,sc_None,keybi,USL_KeyCustom};\r
- UserItem far keysi[] =\r
- {\r
- {DefFolder(sc_M,"MOVEMENT",&keygroup)},\r
- {DefFolder(sc_B,"BUTTONS",&keybgroup)},\r
- {uii_Bad}\r
- };\r
- UserItemGroup far keysgroup = {8,0,CP_KEYBOARDMENUPIC,sc_None,keysi,USL_KeySCustom};\r
-\r
- // Joystick #1 & #2\r
- UserItemGroup far joy1group = {CustomGroup(CP_JOYSTICKMENUPIC,sc_None,USL_Joy1Custom)};\r
- UserItemGroup far joy2group = {CustomGroup(CP_JOYSTICKMENUPIC,sc_None,USL_Joy2Custom)};\r
-\r
- // Config menu\r
- UserItem far configi[] =\r
- {\r
- {DefFolder(sc_S,"SOUND",&soundgroup)},\r
- {DefFolder(sc_M,"MUSIC",&musicgroup)},\r
- {uii_Folder,ui_Separated,sc_K,"USE KEYBOARD",uc_None,&keysgroup},\r
- {DefFolder(sc_None,"USE JOYSTICK #1",&joy1group)},\r
- {DefFolder(sc_None,"USE JOYSTICK #2",&joy2group)},\r
- {uii_Bad}\r
- };\r
- UserItemGroup far configgroup = {8,0,CP_CONFIGMENUPIC,sc_None,configi,USL_ConfigCustom};\r
-\r
- // Main menu\r
-// UserItemGroup far ponggroup = {0,0,0,sc_None,0,USL_PongCustom};\r
- UserItem far rooti[] =\r
- {\r
- {DefFolder(sc_N,"NEW GAME",&newgamegroup)},\r
- {DefFolder(sc_L,"LOAD GAME",&loadgamegroup)},\r
- {DefFolder(sc_S,"SAVE GAME",&savegamegroup)},\r
- {DefFolder(sc_C,"CONFIGURE",&configgroup)},\r
- {DefButton(sc_R,nil),uc_Return}, // Return to Game/Demo\r
- {DefButton(sc_E,"END GAME"),uc_Abort},\r
-// {DefFolder(sc_B,"SKULL 'N' BONES",&ponggroup)},\r
- {DefButton(sc_Q,"QUIT"),uc_Quit},\r
- {uii_Bad}\r
- };\r
- UserItemGroup far rootgroup = {32,4,CP_MAINMENUPIC,sc_None,rooti};\r
-#undef DefButton\r
-#undef DefFolder\r
-\r
-#define MaxCards 7\r
- word cstackptr;\r
- UserItemGroup far *cardstack[MaxCards],\r
- far *topcard;\r
-\r
-// Card stack code\r
-static void\r
-USL_SetupStack(void)\r
-{\r
- cstackptr = 0;\r
- cardstack[0] = topcard = &rootgroup;\r
-}\r
-\r
-static void\r
-USL_PopCard(void)\r
-{\r
- if (!cstackptr)\r
- return;\r
-\r
- topcard = cardstack[--cstackptr];\r
-}\r
-\r
-static void\r
-USL_PushCard(UserItemGroup far *card)\r
-{\r
- if (cstackptr == MaxCards - 1)\r
- return;\r
-\r
- topcard = cardstack[++cstackptr] = card;\r
-}\r
-\r
-static void\r
-USL_DrawItemIcon(UserItem far *item)\r
-{\r
- word flags,tile;\r
-\r
- if (topcard->custom && topcard->custom(uic_DrawIcon,item))\r
- return;\r
-\r
- flags = item->flags;\r
- if (flags & ui_Disabled)\r
- tile = TileBase + ((flags & ui_Selected)? 5 : 4);\r
- else if ((item->type == uii_RadioButton) && (!(flags & ui_Pushed)))\r
- tile = TileBase + ((flags & ui_Selected)? 3 : 2);\r
- else\r
- tile = TileBase + ((flags & ui_Selected)? 1 : 0);\r
- VWB_DrawTile8(item->x,item->y,tile);\r
-}\r
-\r
-static void\r
-USL_DrawItem(UserItem far *item)\r
-{\r
- if (topcard->custom && topcard->custom(uic_Draw,item))\r
- return;\r
-\r
- VWB_Bar(CtlPanelSX + 1,item->y,\r
- CtlPanelEX - CtlPanelSX - 1,8,BackColor); // Clear out background\r
- USL_DrawItemIcon(item);\r
- if ((item->flags & ui_Selected) && !(item->flags & ui_Disabled))\r
- fontcolor = HiliteColor;\r
- else\r
- fontcolor = NohiliteColor;\r
- px = item->x + 8;\r
- py = item->y + 1;\r
- USL_DrawString(item->text);\r
- fontcolor = F_BLACK;\r
-}\r
-\r
-#define MyLine(y) VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,y,12);\r
-\r
-static void\r
-USL_DrawBottom(void)\r
-{\r
- word w,h;\r
-\r
- fontcolor = NohiliteColor;\r
-\r
- px = CtlPanelSX + 4;\r
- py = CtlPanelEY - 15;\r
- USL_DrawString(BottomS1);\r
-\r
- USL_MeasureString(BottomS2,&w,&h);\r
- px = CtlPanelEX - 4 - w;\r
- USL_DrawString(BottomS2);\r
-\r
- USL_MeasureString(BottomS3,&w,&h);\r
- px = CtlPanelSX + ((CtlPanelEX - CtlPanelSX - w) / 2);\r
- py += h + 1;\r
- USL_DrawString(BottomS3);\r
-\r
- fontcolor = F_WHITE;\r
- MyLine(CtlPanelEY - 17);\r
-}\r
-\r
-static void\r
-USL_DrawCtlPanelContents(void)\r
-{\r
- int x,y;\r
- UserItem far *item;\r
-\r
- if (topcard->custom && topcard->custom(uic_DrawCard,nil))\r
- return;\r
-\r
- if (topcard->title)\r
- {\r
- // Draw the title\r
- MyLine(CtlPanelSY + 7);\r
- VWB_DrawPic(CtlPanelSX + 6,CtlPanelSY,topcard->title);\r
- }\r
-\r
- USL_DrawBottom();\r
-\r
- if (!topcard->items)\r
- return;\r
-\r
- x = topcard->x + CtlPanelSX;\r
- if (x % 8)\r
- x += 8 - (x % 8);\r
- y = topcard->y + CtlPanelSY + 12;\r
- for (item = topcard->items;item->type != uii_Bad;item++)\r
- {\r
- if (item->flags & ui_Separated)\r
- y += 8;\r
-\r
- item->x = x;\r
- item->y = y;\r
- USL_DrawItem(item);\r
- y += 8;\r
- }\r
- if (topcard->custom)\r
- topcard->custom(uic_TouchupCard,nil);\r
-}\r
-\r
-static void\r
-USL_DrawCtlPanel(void)\r
-{\r
- if (topcard->items || topcard->title)\r
- {\r
- // Draw the backdrop\r
- VWB_DrawPic(0,0,CP_MENUSCREENPIC);\r
-\r
- // Draw the contents\r
- USL_DrawCtlPanelContents();\r
- }\r
-\r
- // Refresh the screen\r
- VW_UpdateScreen();\r
-}\r
-\r
-static void\r
-USL_DialogSetup(word w,word h,word *x,word *y)\r
-{\r
- VWB_DrawMPic(CtlPanelSX,CtlPanelSY,CP_MENUMASKPICM);\r
-\r
- *x = CtlPanelSX + ((CtlPanelW - w) / 2);\r
- *y = CtlPanelSY + ((CtlPanelH - h) / 2);\r
- VWB_Bar(*x,*y,w + 1,h + 1,BackColor);\r
- VWB_Hlin(*x - 1,*x + w + 1,*y - 1,NohiliteColor);\r
- VWB_Hlin(*x - 1,*x + w + 1,*y + h + 1,NohiliteColor);\r
- VWB_Vlin(*y - 1,*y + h + 1,*x - 1,NohiliteColor);\r
- VWB_Vlin(*y - 1,*y + h + 1,*x + w + 1,NohiliteColor);\r
-}\r
-\r
-static void\r
-USL_ShowLoadSave(char *s,char *name)\r
-{\r
- word x,y,\r
- w,h,\r
- tw,sw;\r
- char msg[MaxGameName + 4];\r
-\r
- strcpy(msg,"'");\r
- strcat(msg,name);\r
- strcat(msg,"'");\r
- USL_MeasureString(s,&sw,&h);\r
- USL_MeasureString(msg,&w,&h);\r
- tw = ((sw > w)? sw : w) + 6;\r
- USL_DialogSetup(tw,(h * 2) + 2,&x,&y);\r
- py = y + 2;\r
- px = x + ((tw - sw) / 2);\r
- USL_DrawString(s);\r
- py += h;\r
- px = x + ((tw - w) / 2);\r
- USL_DrawString(msg);\r
-\r
- VW_UpdateScreen();\r
-\r
- IN_UserInput(100, true);\r
-}\r
-\r
-static boolean\r
-USL_CtlDialog(char *s1,char *s2,char *s3)\r
-{\r
- word w,h,sh,\r
- w1,w2,w3,\r
- x,y;\r
- ScanCode c;\r
- CursorInfo cursorinfo;\r
-\r
- USL_MeasureString(s1,&w1,&h);\r
- USL_MeasureString(s2,&w2,&h);\r
- if (s3)\r
- USL_MeasureString(s3,&w3,&h);\r
- else\r
- w3 = 0;\r
- w = (w1 > w2)? ((w1 > w3)? w1 : w3) : ((w2 > w3)? w2 : w3);\r
- w += 7;\r
- sh = h;\r
- h *= s3? 5 : 4;\r
-\r
- USL_DialogSetup(w,h,&x,&y);\r
-\r
- fontcolor = HiliteColor;\r
- px = x + ((w - w1) / 2);\r
- py = y + sh + 1;\r
- USL_DrawString(s1);\r
- py += (sh * 2) - 1;\r
-\r
- VWB_Hlin(x + 3,x + w - 3,py,NohiliteColor);\r
- py += 2;\r
-\r
- fontcolor = NohiliteColor;\r
- px = x + ((w - w2) / 2);\r
- USL_DrawString(s2);\r
- py += sh;\r
-\r
- if (s3)\r
- {\r
- px = x + ((w - w3) / 2);\r
- USL_DrawString(s3);\r
- }\r
-\r
- VW_UpdateScreen();\r
-\r
- IN_ClearKeysDown();\r
- do\r
- {\r
- IN_ReadCursor(&cursorinfo);\r
- if (cursorinfo.button0)\r
- c = sc_Y;\r
- else if (cursorinfo.button1)\r
- c = sc_Escape;\r
- else\r
- c = LastScan;\r
- } while (c == sc_None);\r
- do\r
- {\r
- IN_ReadCursor(&cursorinfo);\r
- } while (cursorinfo.button0 || cursorinfo.button1);\r
-\r
- IN_ClearKeysDown();\r
- USL_DrawCtlPanel();\r
- return(c == sc_Y);\r
-}\r
-\r
-static boolean\r
-USL_ConfirmComm(UComm comm)\r
-{\r
- boolean confirm,dialog;\r
- char *s1,*s2,*s3;\r
-\r
- if (!comm)\r
- Quit("USL_ConfirmComm() - empty comm");\r
-\r
- confirm = true;\r
- dialog = false;\r
- s3 = "ESC TO BACK OUT";\r
- switch (comm)\r
- {\r
- case uc_Abort:\r
- s1 = "REALLY END CURRENT GAME?";\r
- s2 = "PRESS Y TO END IT";\r
- if (ingame && GameIsDirty)\r
- dialog = true;\r
- break;\r
- case uc_Quit:\r
- s1 = "REALLY QUIT?";\r
- s2 = "PRESS Y TO QUIT";\r
- dialog = true;\r
- break;\r
- case uc_Loaded:\r
- s1 = "YOU'RE IN A GAME";\r
- s2 = "PRESS Y TO LOAD GAME";\r
- if (ingame && GameIsDirty)\r
- dialog = true;\r
- break;\r
- case uc_SEasy:\r
- case uc_SNormal:\r
- case uc_SHard:\r
- s1 = "YOU'RE IN A GAME";\r
- s2 = "PRESS Y FOR NEW GAME";\r
- if (ingame && GameIsDirty)\r
- dialog = true;\r
- break;\r
- }\r
-\r
- confirm = dialog? USL_CtlDialog(s1,s2,s3) : true;\r
- if (confirm)\r
- {\r
- Communication = comm;\r
- CtlPanelDone = true;\r
- }\r
- return(confirm);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_HandleError() - Handles telling the user that there's been an error\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_HandleError(int num)\r
-{\r
- char buf[64];\r
-\r
- strcpy(buf,"Error: ");\r
- if (num < 0)\r
- strcat(buf,"Unknown");\r
- else if (num == ENOMEM)\r
- strcat(buf,"Disk is Full");\r
- else if (num == EINVFMT)\r
- strcat(buf,"File is Incomplete");\r
- else\r
- strcat(buf,sys_errlist[num]);\r
-\r
- VW_HideCursor();\r
-\r
- USL_CtlDialog(buf,"PRESS ANY KEY",nil);\r
- VW_UpdateScreen();\r
-\r
- IN_ClearKeysDown();\r
- IN_Ack();\r
-\r
- VW_ShowCursor();\r
- VW_UpdateScreen();\r
-}\r
-\r
-// Custom routines\r
-#if 0\r
-static boolean\r
-USL_GenericCustom(UserCall call,UserItem far *item)\r
-{\r
- boolean result;\r
-\r
- result = false;\r
- switch (call)\r
- {\r
- }\r
- return(result);\r
-}\r
-#endif\r
-\r
-static void\r
-USL_SetOptionsText(void)\r
-{\r
- optionsi[0].text = showscorebox? "SCORE BOX (ON)" : "SCORE BOX (OFF)";\r
- optionsi[1].text = compatability? "SVGA COMPATIBILITY (ON)" : "SVGA COMPATIBILITY (OFF)";\r
-#ifdef KEEN\r
- optionsi[2].text = oldshooting? "TWO-BUTTON FIRING (ON)" : "TWO-BUTTON FIRING (OFF)";\r
-\r
- keybi[2].flags &= ~ui_Disabled;\r
- if (oldshooting)\r
- keybi[2].flags |= ui_Disabled;\r
-#endif\r
-}\r
-\r
-#pragma argsused\r
-static boolean\r
-USL_ScoreCustom(UserCall call,UserItem far *item)\r
-{\r
- if (call != uic_SetupCard)\r
- return(false);\r
-\r
- showscorebox ^= true;\r
- USL_CtlDialog(showscorebox? "Score box now on" : "Score box now off",\r
- "Press any key",nil);\r
- USL_SetOptionsText();\r
- return(true);\r
-}\r
-\r
-#pragma argsused\r
-static boolean\r
-USL_CompCustom(UserCall call,UserItem far *item)\r
-{\r
- if (call != uic_SetupCard)\r
- return(false);\r
-\r
- compatability ^= true;\r
- USL_CtlDialog(compatability? "SVGA compatibility now on" : "SVGA compatibility now off",\r
- "Press any key",nil);\r
- USL_SetOptionsText();\r
- return(true);\r
-}\r
-\r
-#ifdef KEEN\r
-#pragma argsused\r
-static boolean\r
-USL_TwoCustom(UserCall call,UserItem far *item)\r
-{\r
- if (call != uic_SetupCard)\r
- return(false);\r
-\r
- oldshooting ^= true;\r
- USL_CtlDialog(oldshooting? "Two-button firing now on" : "Two-button firing now off",\r
- "Press any key",nil);\r
- USL_SetOptionsText();\r
- return(true);\r
-}\r
-#endif\r
-\r
-static boolean\r
-USL_ConfigCustom(UserCall call,UserItem far *item)\r
-{\r
-static char *CtlNames[] = {"KEYBOARD","KEYBOARD","JOYSTICK #1","JOYSTICK #2","MOUSE"};\r
- char *s;\r
- word w,h,\r
- tw;\r
-\r
- if (call == uic_TouchupCard)\r
- {\r
- s = "CONTROL: ";\r
- USL_MeasureString(s,&w,&h);\r
- tw = w;\r
- USL_MeasureString(CtlNames[Controls[0]],&w,&h);\r
- tw += w;\r
- py = CtlPanelEY - 18 - h;\r
- px = CtlPanelSX + ((CtlPanelW - tw) / 2);\r
- fontcolor = NohiliteColor;\r
- USL_DrawString(s);\r
- USL_DrawString(CtlNames[Controls[0]]);\r
- }\r
- item++; // Shut the compiler up\r
- return(false);\r
-}\r
-\r
-static void\r
-USL_CKSetKey(UserItem far *item,word i)\r
-{\r
- boolean on;\r
- word j;\r
- ScanCode scan;\r
- longword time;\r
- CursorInfo cursorinfo;\r
-\r
- on = false;\r
- time = 0;\r
- LastScan = sc_None;\r
- fontcolor = HiliteColor;\r
- do\r
- {\r
- if (TimeCount >= time)\r
- {\r
- on ^= true;\r
- VWB_Bar(item->x + 90,item->y,40,8,fontcolor ^ BackColor);\r
- VWB_Bar(item->x + 90 + 1,item->y + 1,40 - 2,8 - 2,BackColor);\r
- if (on)\r
- VWB_DrawTile8(item->x + 90 + 16,item->y,TileBase + 8);\r
- VW_UpdateScreen();\r
-\r
- time = TimeCount + (TickBase / 2);\r
- }\r
-\r
- IN_ReadCursor(&cursorinfo);\r
- while (cursorinfo.button0 || cursorinfo.button1)\r
- {\r
- IN_ReadCursor(&cursorinfo);\r
- LastScan = sc_Escape;\r
- }\r
-\r
- asm pushf\r
- asm cli\r
- if (LastScan == sc_LShift)\r
- LastScan = sc_None;\r
- asm popf\r
- } while (!(scan = LastScan));\r
-\r
- if (scan != sc_Escape)\r
- {\r
- for (j = 0,on = false;j < 11;j++)\r
- {\r
- if (j == i)\r
- continue;\r
- if (*(KeyMaps[j]) == scan)\r
- {\r
- on = true;\r
- break;\r
- }\r
- }\r
- if (on)\r
- USL_CtlDialog("Key already used","Press a key",nil);\r
- else\r
- *(KeyMaps[i]) = scan;\r
- }\r
- IN_ClearKeysDown();\r
-}\r
-\r
-#pragma argsused\r
-static boolean\r
-USL_KeySCustom(UserCall call,UserItem far *item)\r
-{\r
- if (call == uic_SetupCard)\r
- Controls[0] = ctrl_Keyboard;\r
- return(false);\r
-}\r
-\r
-#pragma argsused\r
-static boolean\r
-USL_KeyCustom(UserCall call,UserItem far *item)\r
-{\r
- boolean result;\r
- word i;\r
-\r
- result = false;\r
- i = (topcard == &keygroup)? (3 + (item - keyi)) : (item - keybi);\r
- switch (call)\r
- {\r
- case uic_SetupCard:\r
- Controls[0] = ctrl_Keyboard;\r
- break;\r
- case uic_Draw:\r
- VWB_Bar(CtlPanelSX + 1,item->y,\r
- CtlPanelEX - CtlPanelSX - 1,8,BackColor); // Clear out background\r
- USL_DrawItemIcon(item);\r
- fontcolor = (item->flags & ui_Selected)? HiliteColor : NohiliteColor;\r
- px = item->x + 8;\r
- py = item->y + 1;\r
- USL_DrawString(item->text);\r
- VWB_Bar(item->x + 90,item->y,40,8,fontcolor ^ BackColor);\r
- VWB_Bar(item->x + 90 + 1,item->y + 1,40 - 2,8 - 2,BackColor);\r
- px = item->x + 90 + 6;\r
- py = item->y + 1;\r
- USL_DrawString(IN_GetScanName(*KeyMaps[i]));\r
- result = true;\r
- break;\r
- case uic_Hit:\r
- USL_KeyCustom(uic_Draw,item);\r
- USL_CKSetKey(item,i);\r
- USL_DrawCtlPanel();\r
- result = true;\r
- break;\r
- }\r
- return(result);\r
-}\r
-\r
-static void\r
-USL_CJDraw(char *s1,char *s2)\r
-{\r
- word w,h;\r
-\r
- USL_MeasureString(s1,&w,&h);\r
- px = CtlPanelSX + ((CtlPanelW - w) / 2);\r
- py = CtlPanelEY - 34;\r
- VWB_Bar(CtlPanelSX + 1,py,CtlPanelW - 2,h * 2,BackColor);\r
- fontcolor = HiliteColor;\r
- USL_DrawString(s1);\r
- py += h;\r
- USL_MeasureString(s2,&w,&h);\r
- px = CtlPanelSX + ((CtlPanelW - w) / 2);\r
- USL_DrawString(s2);\r
-}\r
-\r
-static boolean\r
-USL_CJGet(word joy,word button,word x,word y,word *xaxis,word *yaxis)\r
-{\r
- boolean on;\r
- longword time;\r
-\r
- while (IN_GetJoyButtonsDB(joy))\r
- if (LastScan == sc_Escape)\r
- return(false);\r
-\r
- on = false;\r
- time = 0;\r
- while (!(IN_GetJoyButtonsDB(joy) & (1 << button)))\r
- {\r
- if (TimeCount >= time)\r
- {\r
- on ^= true;\r
- time = TimeCount + (TickBase / 2);\r
- VWB_DrawTile8(x,y,TileBase + on);\r
- VW_UpdateScreen();\r
- }\r
-\r
- if (LastScan == sc_Escape)\r
- return(false);\r
- }\r
- IN_GetJoyAbs(joy,xaxis,yaxis);\r
- return(true);\r
-}\r
-\r
-static boolean\r
-USL_ConfigJoystick(word joy)\r
-{\r
- word x,y,\r
- minx,miny,\r
- maxx,maxy;\r
-\r
- BottomS1 = BottomS2 = "";\r
- BottomS3 = "Esc to back out";\r
- USL_DrawCtlPanel();\r
- x = CtlPanelSX + 60;\r
- y = CtlPanelSY + 19;\r
- VWB_DrawPic(x,y,CP_JOYSTICKPIC);\r
-\r
- USL_CJDraw("Move Joystick to upper left","and press button #1");\r
- VWB_DrawTile8(x + 24,y + 8,TileBase + 6);\r
- VWB_DrawTile8(x + 8,y + 8,TileBase + 1);\r
- VWB_DrawTile8(x + 8,y + 24,TileBase + 0);\r
- VW_UpdateScreen();\r
- if (!USL_CJGet(joy,0,x + 8,y + 8,&minx,&miny))\r
- return(false);\r
-\r
- USL_CJDraw("Move Joystick to lower right","and press button #2");\r
- VWB_DrawTile8(x + 24,y + 8,TileBase - 25);\r
- VWB_DrawTile8(x + 40,y + 24,TileBase + 7);\r
- VWB_DrawTile8(x + 8,y + 8,TileBase + 0);\r
- VWB_DrawTile8(x + 8,y + 24,TileBase + 1);\r
- VW_UpdateScreen();\r
- if (!USL_CJGet(joy,1,x + 8,y + 24,&maxx,&maxy))\r
- return(false);\r
-\r
- while (IN_GetJoyButtonsDB(joy))\r
- ;\r
-\r
- IN_SetupJoy(joy,minx,maxx,miny,maxy);\r
- return(true);\r
-}\r
-\r
-#pragma argsused\r
-static boolean\r
-USL_Joy1Custom(UserCall call,UserItem far *item)\r
-{\r
- if (call == uic_SetupCard)\r
- {\r
- if (USL_ConfigJoystick(0))\r
- {\r
- Controls[0] = ctrl_Joystick1;\r
- USL_CtlDialog("USING JOYSTICK #1","PRESS ANY KEY",nil);\r
- }\r
- return(true);\r
- }\r
- else\r
- return(false);\r
-}\r
-\r
-#pragma argsused\r
-static boolean\r
-USL_Joy2Custom(UserCall call,UserItem far *item)\r
-{\r
- if (call == uic_SetupCard)\r
- {\r
- if (USL_ConfigJoystick(1))\r
- {\r
- Controls[0] = ctrl_Joystick2;\r
- USL_CtlDialog("USING JOYSTICK #2","PRESS ANY KEY",nil);\r
- }\r
- return(true);\r
- }\r
- else\r
- return(false);\r
-}\r
-\r
-static void\r
-USL_DrawFileIcon(UserItem far *item)\r
-{\r
- word color;\r
-\r
- item->y = topcard->y + CtlPanelSY + 12;\r
- item->y += (item - loadsavegamei) * 11;\r
-\r
- fontcolor = (item->flags & ui_Selected)? HiliteColor : NohiliteColor;\r
- color = fontcolor ^ BackColor; // Blech!\r
- VWB_Hlin(item->x,item->x + (CtlPanelW - 12),item->y,color);\r
- VWB_Hlin(item->x,item->x + (CtlPanelW - 12),item->y + 9,color);\r
- VWB_Vlin(item->y,item->y + 9,item->x,color);\r
- VWB_Vlin(item->y,item->y + 9,item->x + (CtlPanelW - 12),color);\r
-}\r
-\r
-static void\r
-USL_DoLoadGame(UserItem far *item)\r
-{\r
- char *filename;\r
- word n,\r
- err;\r
- int file;\r
- SaveGame *game;\r
-\r
- if (!USL_ConfirmComm(uc_Loaded))\r
- return;\r
-\r
- n = item - loadsavegamei;\r
- game = &Games[n];\r
-\r
- USL_ShowLoadSave("Loading",game->name);\r
-\r
- err = 0;\r
- filename = USL_GiveSaveName(n);\r
- if ((file = open(filename,O_BINARY | O_RDONLY)) != -1)\r
- {\r
- if (read(file,game,sizeof(*game)) == sizeof(*game))\r
- {\r
- if (USL_LoadGame)\r
- if (!USL_LoadGame(file))\r
- USL_HandleError(err = errno);\r
- }\r
- else\r
- USL_HandleError(err = errno);\r
- close(file);\r
- }\r
- else\r
- USL_HandleError(err = errno);\r
- if (err)\r
- {\r
- abortgame = true;\r
- Communication = uc_None;\r
- CtlPanelDone = false;\r
- }\r
- else\r
- loadedgame = true;\r
- game->present = true;\r
-\r
- if (loadedgame)\r
- Paused = true;\r
-\r
- USL_DrawCtlPanel();\r
-}\r
-\r
-static boolean\r
-USL_LoadCustom(UserCall call,UserItem far *item)\r
-{\r
- boolean result;\r
- word i;\r
-\r
- result = false;\r
- switch (call)\r
- {\r
- case uic_SetupCard:\r
- for (i = 0;i < MaxSaveGames;i++)\r
- {\r
- if (Games[i].present)\r
- loadsavegamei[i].flags &= ~ui_Disabled;\r
- else\r
- loadsavegamei[i].flags |= ui_Disabled;\r
- }\r
- break;\r
- case uic_DrawIcon:\r
- USL_DrawFileIcon(item);\r
- result = true;\r
- break;\r
- case uic_Draw:\r
- USL_DrawFileIcon(item);\r
- VWB_Bar(item->x + 1,item->y + 2,CtlPanelW - 12 - 2,7,BackColor);\r
-\r
- i = item - loadsavegamei;\r
- if (Games[i].present)\r
- px = item->x + 2;\r
- else\r
- px = item->x + 60;\r
- py = item->y + 2;\r
- USL_DrawString(Games[i].present? Games[i].name : "Empty");\r
- result = true;\r
- break;\r
- case uic_Hit:\r
- USL_DoLoadGame(item);\r
- result = true;\r
- break;\r
- }\r
- return(result);\r
-}\r
-\r
-static void\r
-USL_DoSaveGame(UserItem far *item)\r
-{\r
- boolean ok;\r
- char *filename;\r
- word n,err;\r
- int file;\r
- SaveGame *game;\r
-\r
- BottomS1 = "Type name";\r
- BottomS2 = "Enter accepts";\r
- USL_DrawCtlPanel();\r
-\r
- n = item - loadsavegamei;\r
- game = &Games[n];\r
- fontcolor = HiliteColor;\r
- VWB_Bar(item->x + 1,item->y + 2,CtlPanelW - 12 - 2,7,BackColor);\r
- game->oldtest = &PrintX;\r
- ok = US_LineInput(item->x + 2,item->y + 2,\r
- game->name,game->present? game->name : nil,\r
- true,MaxGameName,\r
- CtlPanelW - 22);\r
- if (!strlen(game->name))\r
- strcpy(game->name,"Untitled");\r
- if (ok)\r
- {\r
- USL_ShowLoadSave("Saving",game->name);\r
-\r
- filename = USL_GiveSaveName(n);\r
- err = 0;\r
- file = open(filename,O_CREAT | O_BINARY | O_WRONLY,\r
- S_IREAD | S_IWRITE | S_IFREG);\r
- if (file != -1)\r
- {\r
- if (write(file,game,sizeof(*game)) == sizeof(*game))\r
- {\r
- if (USL_SaveGame)\r
- ok = USL_SaveGame(file);\r
- if (!ok)\r
- USL_HandleError(err = errno);\r
- }\r
- else\r
- USL_HandleError(err = ((errno == ENOENT)? ENOMEM : errno));\r
- close(file);\r
- }\r
- else\r
- USL_HandleError(err = ((errno == ENOENT)? ENOMEM : errno));\r
- if (err)\r
- {\r
- remove(filename);\r
- ok = false;\r
- }\r
-\r
- }\r
-\r
- if (!game->present)\r
- game->present = ok;\r
-\r
- if (ok)\r
- GameIsDirty = false;\r
- USL_SetupCard();\r
-}\r
-\r
-static boolean\r
-USL_SaveCustom(UserCall call,UserItem far *item)\r
-{\r
- word i;\r
-\r
- switch (call)\r
- {\r
- case uic_SetupCard:\r
- for (i = 0;i < MaxSaveGames;i++)\r
- loadsavegamei[i].flags &= ~ui_Disabled;\r
- return(false);\r
- case uic_Hit:\r
- USL_DoSaveGame(item);\r
- return(true);\r
-// break;\r
- }\r
- return(USL_LoadCustom(call,item));\r
-}\r
-\r
-#if 0\r
-\r
-#define PaddleMinX (CtlPanelSX + 3)\r
-#define PaddleMaxX (CtlPanelEX - 15)\r
-#define BallMinX (CtlPanelSX + 2)\r
-#define BallMinY (CtlPanelSY + 12 + 2)\r
-#define BallMaxX (CtlPanelEX - 6)\r
-#define BallMaxY (CtlPanelEY - 13)\r
-#define CPaddleY (BallMinY + 4)\r
-#define KPaddleY (BallMaxY - 2)\r
-void\r
-USL_DrawPongScore(word k,word c)\r
-{\r
- fontcolor = HiliteColor;\r
- PrintY = py = CtlPanelSY + 4;\r
- px = CtlPanelSX + 6;\r
- VWB_Bar(px,py,42,6,BackColor);\r
- USL_DrawString("YOU:");\r
- PrintX = px;\r
- US_PrintUnsigned(k);\r
- px = CtlPanelSX + 108;\r
- VWB_Bar(px,py,50,6,BackColor);\r
- USL_DrawString("COMP:");\r
- PrintX = px;\r
- US_PrintUnsigned(c);\r
-}\r
-\r
-void\r
-USL_PlayPong(void)\r
-{\r
- boolean ball,killball,revdir,done,lastscore;\r
- word cycle,\r
- x,y,\r
- kx,cx,\r
- rx,\r
- bx,by,\r
- kscore,cscore,\r
- speedup;\r
- int bdx,bdy;\r
- longword balltime,waittime;\r
- CursorInfo cursorinfo;\r
-\r
- kx = cx = PaddleMinX + ((PaddleMaxX - PaddleMinX) / 2);\r
- bx = by = bdx = bdy = 0;\r
- kscore = cscore = 0;\r
- USL_DrawPongScore(0,0);\r
- cycle = 0;\r
- revdir = false;\r
- killball = true;\r
- done = false;\r
- lastscore = false;\r
- do\r
- {\r
- waittime = TimeCount;\r
-\r
- IN_ReadCursor(&cursorinfo);\r
- if (((cursorinfo.x < 0) || IN_KeyDown(sc_LeftArrow)) && (kx > PaddleMinX))\r
- kx -= 2;\r
- else if (((cursorinfo.x > 0) || IN_KeyDown(sc_RightArrow)) && (kx < PaddleMaxX))\r
- kx += 2;\r
-\r
- if (killball)\r
- {\r
- ball = false;\r
- balltime = TimeCount + TickBase;\r
- speedup = 10;\r
- killball = false;\r
- }\r
-\r
- if (ball && (cycle++ % 3))\r
- {\r
- x = (bx >> 2);\r
- if (!(x & 1))\r
- x += (US_RndT() & 1);\r
-\r
- if ((cx + 6 < x) && (cx < PaddleMaxX))\r
- cx += 1;\r
- else if ((cx + 6 > x) && (cx > PaddleMinX))\r
- cx -= 1;\r
- }\r
-\r
- VWB_Bar(BallMinX,BallMinY - 1,\r
- BallMaxX - BallMinX + 5,BallMaxY - BallMinY + 7,\r
- BackColor);\r
- VWB_DrawSprite(cx,CPaddleY,PADDLESPR);\r
- VWB_DrawSprite(kx,KPaddleY,PADDLESPR);\r
- if (ball)\r
- {\r
- if\r
- (\r
- (((bx + bdx) >> 2) > BallMaxX)\r
- || (((bx + bdx) >> 2) < BallMinX)\r
- )\r
- {\r
- SD_PlaySound(BALLBOUNCESND);\r
- bdx = -bdx;\r
- }\r
- bx += bdx;\r
-\r
- if (((by + bdy) >> 2) > BallMaxY)\r
- {\r
- killball = true;\r
- lastscore = false;\r
- cscore++;\r
- SD_PlaySound(COMPSCOREDSND);\r
- USL_DrawPongScore(kscore,cscore);\r
- if (cscore == 21)\r
- {\r
- USL_CtlDialog("You lost!","Press any key",nil);\r
- done = true;\r
- continue;\r
- }\r
- }\r
- else if (((by + bdy) >> 2) < BallMinY)\r
- {\r
- killball = true;\r
- lastscore = true;\r
- kscore++;\r
- SD_PlaySound(KEENSCOREDSND);\r
- USL_DrawPongScore(kscore,cscore);\r
- if (kscore == 21)\r
- {\r
- USL_CtlDialog("You won!","Press any key",nil);\r
- done = true;\r
- continue;\r
- }\r
- }\r
- by += bdy;\r
-\r
- x = bx >> 2;\r
- y = by >> 2;\r
- if (!killball)\r
- {\r
- if\r
- (\r
- (bdy < 0)\r
- && ((y >= CPaddleY) && (y < CPaddleY + 3))\r
- && ((x >= (cx - 5)) && (x < (cx + 11)))\r
- )\r
- {\r
- rx = cx;\r
- revdir = true;\r
- SD_PlaySound(COMPPADDLESND);\r
- }\r
- else if\r
- (\r
- (bdy > 0)\r
- && ((y >= (KPaddleY - 3)) && (y < KPaddleY))\r
- && ((x >= (kx - 5)) && (x < (kx + 11)))\r
- )\r
- {\r
- if (((bdy >> 2) < 3) && !(--speedup))\r
- {\r
- bdy++;\r
- speedup = 10;\r
- }\r
- rx = kx;\r
- revdir = true;\r
- SD_PlaySound(KEENPADDLESND);\r
- }\r
- if (revdir)\r
- {\r
- bdy = -bdy;\r
- bdx = ((x + 5 - rx) >> 1) - (1 << 2);\r
- if (!bdx)\r
- bdx--;\r
- revdir = false;\r
- }\r
- }\r
- VWB_DrawSprite(x,y,(x & 1)? BALL1PIXELTOTHERIGHTSPR : BALLSPR);\r
- }\r
- else if (TimeCount >= balltime)\r
- {\r
- ball = true;\r
- bdx = 1 - (US_RndT() % 3);\r
- bdy = 2;\r
- if (lastscore)\r
- bdy = -bdy;\r
- bx = (BallMinX + ((BallMaxX - BallMinX) / 2)) << 2;\r
- by = (BallMinY + ((BallMaxY - BallMinY) / 2)) << 2;\r
- }\r
- VW_UpdateScreen();\r
- while (waittime == TimeCount)\r
- ; // DEBUG - do adaptiveness\r
- } while ((LastScan != sc_Escape) && !done);\r
- IN_ClearKeysDown();\r
-}\r
-\r
-#pragma argsused\r
-static boolean\r
-USL_PongCustom(UserCall call,struct UserItem far *item)\r
-{\r
- if (call != uic_SetupCard)\r
- return(false);\r
-\r
- VWB_DrawPic(0,0,CP_MENUSCREENPIC);\r
- VWB_DrawPic(CtlPanelSX + 56,CtlPanelSY,CP_PADDLEWARPIC);\r
- VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,CtlPanelSY + 12,HiliteColor ^ BackColor);\r
- VWB_Hlin(CtlPanelSX + 3,CtlPanelEX - 3,CtlPanelEY - 7,HiliteColor ^ BackColor);\r
- USL_PlayPong();\r
-\r
- return(true);\r
-}\r
-\r
-#endif\r
-\r
-// Flag management stuff\r
-static void\r
-USL_ClearFlags(UserItemGroup far *node)\r
-{\r
- UserItem far *i;\r
-\r
- if (!node->items)\r
- return;\r
-\r
- for (i = node->items;i->type != uii_Bad;i++)\r
- {\r
- i->flags &= ~UISelectFlags;\r
- if (i->child)\r
- USL_ClearFlags((UserItemGroup far *)i->child);\r
- }\r
-}\r
-\r
-static int\r
-USL_FindPushedItem(UserItemGroup far *group)\r
-{\r
- word i;\r
- UserItem far *item;\r
-\r
- for (item = group->items,i = 0;item->type != uii_Bad;item++,i++)\r
- if (item->flags & ui_Pushed)\r
- return(i);\r
- return(-1);\r
-}\r
-\r
-static void\r
-USL_SelectItem(UserItemGroup far *group,word index,boolean draw)\r
-{\r
- UserItem far *item;\r
-\r
- if (index != group->cursor)\r
- {\r
- item = &group->items[group->cursor];\r
- item->flags &= ~ui_Selected;\r
- if (draw)\r
- USL_DrawItem(item);\r
- }\r
-\r
- group->cursor = index;\r
- item = &group->items[group->cursor];\r
- group->items[group->cursor].flags |= ui_Selected;\r
- if (draw)\r
- USL_DrawItem(item);\r
-}\r
-\r
-static void\r
-USL_PushItem(UserItemGroup far *group,word index,boolean draw)\r
-{\r
- word i;\r
- UserItem far *item;\r
-\r
- USL_SelectItem(group,index,draw);\r
- for (item = group->items,i = 0;item->type != uii_Bad;item++,i++)\r
- {\r
- if (item->type != uii_RadioButton)\r
- continue;\r
-\r
- if (i == index)\r
- {\r
- item->flags |= ui_Pushed;\r
- if (draw)\r
- USL_DrawItem(item);\r
- }\r
- else if (item->flags & ui_Pushed)\r
- {\r
- item->flags &= ~ui_Pushed;\r
- if (draw)\r
- USL_DrawItem(item);\r
- }\r
- }\r
-}\r
-\r
-static void\r
-USL_NextItem(void)\r
-{\r
- if (topcard->items[topcard->cursor + 1].type == uii_Bad)\r
- return;\r
- USL_SelectItem(topcard,topcard->cursor + 1,true);\r
-}\r
-\r
-static void\r
-USL_PrevItem(void)\r
-{\r
- if (!topcard->cursor)\r
- return;\r
- USL_SelectItem(topcard,topcard->cursor - 1,true);\r
-}\r
-\r
-static void\r
-USL_SetupCard(void)\r
-{\r
- BottomS1 = "Arrows move";\r
- BottomS2 = "Enter selects";\r
- BottomS3 = cstackptr? "ESC to back out" : "ESC to quit";\r
-\r
- USL_SelectItem(topcard,topcard->cursor,false);\r
- USL_DrawCtlPanel(); // Contents?\r
-}\r
-\r
-static void\r
-USL_DownLevel(UserItemGroup far *group)\r
-{\r
- if (!group)\r
- Quit("USL_DownLevel() - nil card");\r
- USL_PushCard(group);\r
- if (group->custom && group->custom(uic_SetupCard,nil))\r
- USL_PopCard();\r
- USL_SetupCard();\r
-}\r
-\r
-static void\r
-USL_UpLevel(void)\r
-{\r
- if (!cstackptr)\r
- {\r
- USL_ConfirmComm(uc_Quit);\r
- return;\r
- }\r
-\r
- if (topcard->items)\r
- topcard->items[topcard->cursor].flags &= ~ui_Selected;\r
- USL_PopCard();\r
- USL_SetupCard();\r
-}\r
-\r
-static void\r
-USL_DoItem(void)\r
-{\r
- // DEBUG - finish this routine\r
- UserItem far *item;\r
-\r
- item = &topcard->items[topcard->cursor];\r
- if (item->flags & ui_Disabled)\r
- SD_PlaySound(NOWAYSND);\r
- else\r
- {\r
- switch (item->type)\r
- {\r
- case uii_Button:\r
- if (!(topcard->custom && topcard->custom(uic_Hit,item)))\r
- USL_ConfirmComm(item->comm);\r
- break;\r
- case uii_RadioButton:\r
- USL_PushItem(topcard,topcard->cursor,true);\r
- break;\r
- case uii_Folder:\r
- USL_DownLevel(item->child);\r
- break;\r
- }\r
- }\r
-}\r
-\r
-static void\r
-USL_SetControlValues(void)\r
-{\r
- USL_PushItem(&soundgroup,SoundMode,false);\r
- USL_PushItem(&musicgroup,MusicMode,false);\r
- if (!AdLibPresent)\r
- {\r
- soundi[2].flags |= ui_Disabled; // AdLib sound effects\r
- musici[1].flags |= ui_Disabled; // AdLib music\r
- }\r
-\r
- if (!JoysPresent[0])\r
- configi[3].flags |= ui_Disabled;\r
- if (!JoysPresent[1])\r
- configi[4].flags |= ui_Disabled;\r
-\r
- rooti[4].text = ingame? "RETURN TO GAME" : "RETURN TO DEMO";\r
- if (!ingame)\r
- {\r
- rooti[2].flags |= ui_Disabled; // Save Game\r
- rooti[5].flags |= ui_Disabled; // End Game\r
- }\r
- rootgroup.cursor = ingame? 4 : 0;\r
- USL_SetOptionsText();\r
- // DEBUG - write the rest of this\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_SetUpCtlPanel() - Sets the states of the UserItems to reflect the\r
-// values of all the appropriate variables\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_SetUpCtlPanel(void)\r
-{\r
- int i;\r
-\r
- // Cache in all of the stuff for the control panel\r
- CA_UpLevel();\r
- for (i = CONTROLS_LUMP_START;i <= CONTROLS_LUMP_END;i++)\r
- CA_MarkGrChunk(i);\r
-// for (i = PADDLE_LUMP_START;i <= PADDLE_LUMP_END;i++)\r
-// CA_MarkGrChunk(i);\r
- CA_MarkGrChunk(STARTFONT+1); // Little font\r
- CA_MarkGrChunk(CP_MENUMASKPICM); // Mask for dialogs\r
- CA_CacheMarks("Control Panel");\r
- CA_LoadAllSounds();\r
-\r
- // Do some other setup\r
- fontnumber = 1;\r
- US_SetPrintRoutines(VW_MeasurePropString,VWB_DrawPropString);\r
- fontcolor = F_BLACK;\r
- VW_Bar (0,0,320,200,3); // CAT3D patch\r
- RF_FixOfs();\r
- VW_InitDoubleBuffer();\r
-\r
- Communication = uc_None;\r
- USL_ClearFlags(&rootgroup);\r
- USL_SetControlValues();\r
- USL_SetupStack();\r
- USL_SetupCard();\r
-\r
- if (ingame)\r
- GameIsDirty = true;\r
-\r
- IN_ClearKeysDown();\r
-}\r
-\r
-static void\r
-USL_HandleComm(UComm comm)\r
-{\r
- switch (comm)\r
- {\r
- case uc_Loaded:\r
- case uc_Return:\r
- break;\r
- case uc_Abort:\r
- abortgame = true;\r
- break;\r
- case uc_Quit:\r
- QuitToDos = true;\r
- break;\r
- case uc_SEasy:\r
- restartgame = gd_Easy;\r
- break;\r
- case uc_SNormal:\r
- restartgame = gd_Normal;\r
- break;\r
- case uc_SHard:\r
- restartgame = gd_Hard;\r
- break;\r
-\r
- default:\r
- Quit("USL_HandleComm() - unknown");\r
- break;\r
- }\r
-}\r
-\r
-static void\r
-USL_GetControlValues(void)\r
-{\r
- int i;\r
-\r
- // DEBUG - write the rest of this\r
- i = USL_FindPushedItem(&soundgroup);\r
- if (i != SoundMode)\r
- SD_SetSoundMode(i);\r
-\r
- i = USL_FindPushedItem(&musicgroup);\r
- if (i != MusicMode)\r
- SD_SetMusicMode(i);\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// USL_TearDownCtlPanel() - Given the state of the control panel, sets the\r
-// modes and values as appropriate\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-static void\r
-USL_TearDownCtlPanel(void)\r
-{\r
- USL_GetControlValues();\r
- if (Communication)\r
- USL_HandleComm(Communication);\r
-\r
- fontnumber = 0; // Normal font\r
- fontcolor = F_BLACK;\r
- if (restartgame && USL_ResetGame)\r
- USL_ResetGame();\r
- else if (QuitToDos)\r
- {\r
- if (tedlevel)\r
- TEDDeath();\r
- else\r
- {\r
- US_CenterWindow(20,3);\r
- fontcolor = F_SECONDCOLOR;\r
- US_PrintCentered("Quitting...");\r
- fontcolor = F_BLACK;\r
- VW_UpdateScreen();\r
- Quit(nil);\r
- }\r
- }\r
-\r
- IN_ClearKeysDown();\r
- SD_WaitSoundDone();\r
- VW_Bar (0,0,320,200,3); // CAT3D patch\r
- CA_DownLevel();\r
- CA_LoadAllSounds();\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_ControlPanel() - This is the main routine for the control panel\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-#define MoveMin 40\r
-void\r
-US_ControlPanel(void)\r
-{\r
-extern void HelpScreens(void);\r
-\r
- boolean resetitem,on;\r
- word i;\r
- int ydelta;\r
- longword flashtime;\r
- UserItem far *item;\r
- CursorInfo cursorinfo;\r
-\r
-#if 0\r
- // DEBUG!!!\r
- {\r
- USL_SetUpCtlPanel();\r
- Communication = uc_Loaded;\r
- CtlPanelDone = true;\r
- loadedgame = true;\r
- USL_TearDownCtlPanel();\r
- return;\r
- }\r
-#endif\r
-\r
- if ((LastScan < sc_F1) || (LastScan > sc_F10))\r
- IN_ClearKeysDown();\r
-\r
- USL_SetUpCtlPanel();\r
- USL_DrawCtlPanel();\r
-\r
- ydelta = 0;\r
- for (CtlPanelDone = false,resetitem = on = true;!CtlPanelDone;)\r
- {\r
- item = &(topcard->items[topcard->cursor]);\r
-\r
- if (resetitem)\r
- {\r
- flashtime = TimeCount + (TickBase / 2);\r
- resetitem = false;\r
- }\r
-\r
- if (TimeCount >= flashtime)\r
- {\r
- on ^= true;\r
- resetitem = true;\r
- if (!on)\r
- item->flags &= ~ui_Selected;\r
- USL_DrawItemIcon(item);\r
- item->flags |= ui_Selected;\r
- }\r
-\r
- VW_UpdateScreen();\r
-\r
- if (LastScan)\r
- {\r
- switch (LastScan)\r
- {\r
- case sc_UpArrow:\r
- USL_PrevItem();\r
- resetitem = true;\r
- break;\r
- case sc_DownArrow:\r
- USL_NextItem();\r
- resetitem = true;\r
- break;\r
- case sc_Return:\r
- USL_DoItem();\r
- resetitem = true;\r
- break;\r
- case sc_Escape:\r
- USL_UpLevel();\r
- resetitem = true;\r
- break;\r
-#ifndef KEEN6\r
- case sc_F1:\r
- HelpScreens();\r
- USL_DrawCtlPanel();\r
- resetitem = true;\r
- break;\r
-#endif\r
- }\r
-\r
- if\r
- (\r
- (!resetitem)\r
- && (\r
- (LastScan == KbdDefs[0].button0)\r
- || (LastScan == KbdDefs[0].button1)\r
- )\r
- )\r
- {\r
- USL_DoItem();\r
- resetitem = true;\r
- }\r
-\r
- if (!resetitem)\r
- {\r
- for (item = topcard->items,i = 0;item->type != uii_Bad;item++,i++)\r
- {\r
- if (item->hotkey == LastScan)\r
- {\r
- USL_SelectItem(topcard,i,true);\r
- resetitem = true;\r
- break;\r
- }\r
- }\r
- }\r
-\r
- IN_ClearKeysDown();\r
- }\r
- else\r
- {\r
- IN_ReadCursor(&cursorinfo);\r
- ydelta += cursorinfo.y;\r
- if (cursorinfo.button0)\r
- {\r
- do\r
- {\r
- IN_ReadCursor(&cursorinfo);\r
- } while (cursorinfo.button0);\r
- USL_DoItem();\r
- resetitem = true;\r
- }\r
- else if (cursorinfo.button1)\r
- {\r
- do\r
- {\r
- IN_ReadCursor(&cursorinfo);\r
- } while (cursorinfo.button1);\r
- USL_UpLevel();\r
- resetitem = true;\r
- }\r
- else if (ydelta < -MoveMin)\r
- {\r
- ydelta += MoveMin;\r
- USL_PrevItem();\r
- resetitem = true;\r
- }\r
- else if (ydelta > MoveMin)\r
- {\r
- ydelta -= MoveMin;\r
- USL_NextItem();\r
- resetitem = true;\r
- }\r
- }\r
- }\r
-\r
- USL_TearDownCtlPanel();\r
-}\r
+++ /dev/null
-; Catacomb Armageddon Source Code\r
-; Copyright (C) 1993-2014 Flat Rock Software\r
-;\r
-; This program is free software; you can redistribute it and/or modify\r
-; it under the terms of the GNU General Public License as published by\r
-; the Free Software Foundation; either version 2 of the License, or\r
-; (at your option) any later version.\r
-;\r
-; This program is distributed in the hope that it will be useful,\r
-; but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-; GNU General Public License for more details.\r
-;\r
-; You should have received a copy of the GNU General Public License along\r
-; with this program; if not, write to the Free Software Foundation, Inc.,\r
-; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-\r
-IDEAL\r
-MODEL MEDIUM,C\r
-\r
-; Assembly portion of the User Mgr. This is just John Carmack's table\r
-; driven pseudo-random number generator, and we put it in the User Mgr\r
-; because we couldn't figure out where it should go\r
-\r
-\r
-;============================================================================\r
-;\r
-; RANDOM ROUTINES\r
-;\r
-;============================================================================\r
-\r
- FARDATA\r
-\r
-rndindex dw ?\r
-\r
-rndtable db 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66\r
- db 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36\r
- db 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188\r
- db 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224\r
- db 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242\r
- db 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0\r
- db 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235\r
- db 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113\r
- db 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75\r
- db 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196\r
- db 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113\r
- db 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241\r
- db 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224\r
- db 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95\r
- db 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226\r
- db 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36\r
- db 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106\r
- db 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136\r
- db 120, 163, 236, 249\r
-\r
-\r
- CODESEG\r
-\r
-LastRnd dw ?\r
-\r
-;=================================================\r
-;\r
-; void US_InitRndT (boolean randomize)\r
-; Init table based RND generator\r
-; if randomize is false, the counter is set to 0\r
-;\r
-;=================================================\r
-\r
-PROC US_InitRndT randomize:word\r
- uses si,di\r
- public US_InitRndT\r
-\r
- mov ax,SEG rndtable\r
- mov es,ax\r
- mov ax,[randomize]\r
- or ax,ax\r
- jne @@timeit ;if randomize is true, really random\r
-\r
- mov dx,0 ;set to a definite value\r
- jmp @@setit\r
-\r
-@@timeit:\r
- mov ah,2ch\r
- int 21h ;GetSystemTime\r
- and dx,0ffh\r
-\r
-@@setit:\r
- mov [es:rndindex],dx\r
- ret\r
-\r
-ENDP\r
-\r
-;=================================================\r
-;\r
-; int US_RndT (void)\r
-; Return a random # between 0-255\r
-; Exit : AX = value\r
-;\r
-;=================================================\r
-PROC US_RndT\r
- public US_RndT\r
-\r
- mov ax,SEG rndtable\r
- mov es,ax\r
- mov bx,[es:rndindex]\r
- inc bx\r
- and bx,0ffh\r
- mov [es:rndindex],bx\r
- mov al,[es:rndtable+BX]\r
- xor ah,ah\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-END\r
-\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_VW.C\r
-\r
-#include "ID_HEADS.H"\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define VIEWWIDTH 40\r
-\r
-#define PIXTOBLOCK 4 // 16 pixels to an update block\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-cardtype videocard; // set by VW_Startup\r
-grtype grmode; // CGAgr, EGAgr, VGAgr\r
-\r
-unsigned bufferofs; // hidden area to draw to before displaying\r
-unsigned displayofs; // origin of the visable screen\r
-unsigned panx,pany; // panning adjustments inside port in pixels\r
-unsigned pansx,pansy; // panning adjustments inside port in screen\r
- // block limited pixel values (ie 0/8 for ega x)\r
-unsigned panadjust; // panx/pany adjusted by screen resolution\r
-\r
-unsigned screenseg; // normally 0xa000 / 0xb800\r
-unsigned linewidth;\r
-unsigned ylookup[VIRTUALHEIGHT];\r
-\r
-unsigned fontnumber; // 0 based font number for drawing\r
-\r
-boolean screenfaded;\r
-\r
-pictabletype _seg *pictable;\r
-pictabletype _seg *picmtable;\r
-spritetabletype _seg *spritetable;\r
-\r
-int bordercolor;\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-void VWL_MeasureString (char far *string, word *width, word *height,\r
- fontstruct _seg *font);\r
-void VWL_DrawCursor (void);\r
-void VWL_EraseCursor (void);\r
-void VWL_DBSetup (void);\r
-void VWL_UpdateScreenBlocks (void);\r
-\r
-\r
-int bordercolor;\r
-int cursorvisible;\r
-int cursornumber,cursorwidth,cursorheight,cursorx,cursory;\r
-memptr cursorsave;\r
-unsigned cursorspot;\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-=======================\r
-=\r
-= VW_Startup\r
-=\r
-=======================\r
-*/\r
-\r
-static char *ParmStrings[] = {"HIDDENCARD",""};\r
-\r
-void VW_Startup (void)\r
-{\r
- int i;\r
-\r
- asm cld;\r
-\r
- videocard = 0;\r
-\r
- for (i = 1;i < _argc;i++)\r
- if (US_CheckParm(_argv[i],ParmStrings) == 0)\r
- {\r
- videocard = EGAcard;\r
- break;\r
- }\r
-\r
- if (!videocard)\r
- videocard = VW_VideoID ();\r
-\r
-#if GRMODE == EGAGR\r
- grmode = EGAGR;\r
- if (videocard != EGAcard && videocard != VGAcard)\r
-Quit ("Improper video card! If you really have an EGA/VGA card that I am not \n"\r
- "detecting, use the -HIDDENCARD command line parameter!");\r
- EGAWRITEMODE(0);\r
-#endif\r
-\r
-#if GRMODE == CGAGR\r
- grmode = CGAGR;\r
- if (videocard < CGAcard || videocard > VGAcard)\r
-Quit ("Improper video card! If you really have a CGA card that I am not \n"\r
- "detecting, use the -HIDDENCARD command line parameter!");\r
- MM_GetPtr (&(memptr)screenseg,0x10000l); // grab 64k for floating screen\r
-#endif\r
-\r
- cursorvisible = 0;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-=======================\r
-=\r
-= VW_Shutdown\r
-=\r
-=======================\r
-*/\r
-\r
-void VW_Shutdown (void)\r
-{\r
- VW_SetScreenMode (TEXTGR);\r
-#if GRMODE == EGAGR\r
- VW_SetLineWidth (80);\r
-#endif\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-========================\r
-=\r
-= VW_SetScreenMode\r
-= Call BIOS to set TEXT / CGAgr / EGAgr / VGAgr\r
-=\r
-========================\r
-*/\r
-\r
-void VW_SetScreenMode (int grmode)\r
-{\r
- switch (grmode)\r
- {\r
- case TEXTGR: _AX = 3;\r
- geninterrupt (0x10);\r
- screenseg=0xb000;\r
- break;\r
- case CGAGR: _AX = 4;\r
- geninterrupt (0x10); // screenseg is actually a main mem buffer\r
- break;\r
-\r
- case EGA320GR: // MDM start (GAMERS EDGE)\r
- MaxX=320;\r
- MaxY=200;\r
- _AX = 0xd|128;\r
- geninterrupt (0x10);\r
- screenseg=0xa000;\r
- break;\r
-\r
- case EGA640GR:\r
- MaxX=640;\r
- MaxY=200;\r
- _AX = 0xe|128;\r
- geninterrupt (0x10);\r
- screenseg=0xa000;\r
- break; // MDM end (GAMERS EDGE)\r
-\r
- case EGAGR: _AX = 0xd;\r
- MaxX=320;\r
- MaxY=200;\r
- geninterrupt (0x10);\r
- screenseg=0xa000;\r
- break;\r
-#ifdef VGAGAME\r
- case VGAGR:{\r
- char extern VGAPAL; // deluxepaint vga pallet .OBJ file\r
- void far *vgapal = &VGAPAL;\r
- SetCool256 (); // custom 256 color mode\r
- screenseg=0xa000;\r
- _ES = FP_SEG(vgapal);\r
- _DX = FP_OFF(vgapal);\r
- _BX = 0;\r
- _CX = 0x100;\r
- _AX = 0x1012;\r
- geninterrupt(0x10); // set the deluxepaint pallet\r
-\r
- break;\r
-#endif\r
- }\r
- VW_SetLineWidth(SCREENWIDTH);\r
-}\r
-\r
-/*\r
-=============================================================================\r
-\r
- SCREEN FADES\r
-\r
-=============================================================================\r
-*/\r
-\r
-char colors[7][17]=\r
-{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},\r
- {0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,0},\r
- {0,0,0,0,0,0,0,0,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0},\r
- {0,1,2,3,4,5,6,7,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0},\r
- {0,1,2,3,4,5,6,7,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0},\r
- {0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f}};\r
-\r
-\r
-void VW_ColorBorder (int color)\r
-{\r
- _AH=0x10;\r
- _AL=1;\r
- _BH=color;\r
- geninterrupt (0x10);\r
- bordercolor = color;\r
-}\r
-\r
-void VW_SetPalette(byte *palette)\r
-{\r
- byte p;\r
- word i;\r
-\r
- for (i = 0;i < 15;i++)\r
- {\r
- p = palette[i];\r
- colors[0][i] = 0;\r
- colors[1][i] = (p > 0x10)? (p & 0x0f) : 0;\r
- colors[2][i] = (p > 0x10)? p : 0;\r
- colors[3][i] = p;\r
- colors[4][i] = (p > 0x10)? 0x1f : p;\r
- colors[5][i] = 0x1f;\r
- }\r
-}\r
-\r
-void VW_SetDefaultColors(void)\r
-{\r
-#if GRMODE == EGAGR\r
- colors[3][16] = bordercolor;\r
- _ES=FP_SEG(&colors[3]);\r
- _DX=FP_OFF(&colors[3]);\r
- _AX=0x1002;\r
- geninterrupt(0x10);\r
- screenfaded = false;\r
-#endif\r
-}\r
-\r
-\r
-void VW_FadeOut(void)\r
-{\r
-#if GRMODE == EGAGR\r
- int i;\r
-\r
- for (i=3;i>=0;i--)\r
- {\r
- colors[i][16] = bordercolor;\r
- _ES=FP_SEG(&colors[i]);\r
- _DX=FP_OFF(&colors[i]);\r
- _AX=0x1002;\r
- geninterrupt(0x10);\r
- VW_WaitVBL(6);\r
- }\r
- screenfaded = true;\r
-#endif\r
-}\r
-\r
-\r
-void VW_FadeIn(void)\r
-{\r
-#if GRMODE == EGAGR\r
- int i;\r
-\r
- for (i=0;i<4;i++)\r
- {\r
- colors[i][16] = bordercolor;\r
- _ES=FP_SEG(&colors[i]);\r
- _DX=FP_OFF(&colors[i]);\r
- _AX=0x1002;\r
- geninterrupt(0x10);\r
- VW_WaitVBL(6);\r
- }\r
- screenfaded = false;\r
-#endif\r
-}\r
-\r
-void VW_FadeUp(void)\r
-{\r
-#if GRMODE == EGAGR\r
- int i;\r
-\r
- for (i=3;i<6;i++)\r
- {\r
- colors[i][16] = bordercolor;\r
- _ES=FP_SEG(&colors[i]);\r
- _DX=FP_OFF(&colors[i]);\r
- _AX=0x1002;\r
- geninterrupt(0x10);\r
- VW_WaitVBL(6);\r
- }\r
- screenfaded = true;\r
-#endif\r
-}\r
-\r
-void VW_FadeDown(void)\r
-{\r
-#if GRMODE == EGAGR\r
- int i;\r
-\r
- for (i=5;i>2;i--)\r
- {\r
- colors[i][16] = bordercolor;\r
- _ES=FP_SEG(&colors[i]);\r
- _DX=FP_OFF(&colors[i]);\r
- _AX=0x1002;\r
- geninterrupt(0x10);\r
- VW_WaitVBL(6);\r
- }\r
- screenfaded = false;\r
-#endif\r
-}\r
-\r
-\r
-/*\r
-========================\r
-=\r
-= VW_SetAtrReg\r
-=\r
-= Sets an attribute (pallete / border) register\r
-= Does NOT vsync!\r
-=\r
-========================\r
-*/\r
-\r
-void VW_SetAtrReg (int reg, int value)\r
-{\r
- asm cli\r
- asm mov dx,STATUS_REGISTER_1\r
- asm in al,dx\r
- asm mov dx,ATR_INDEX\r
-\r
- asm mov al,BYTE PTR [reg]\r
- asm out dx,al\r
- asm mov al,BYTE PTR [value]\r
- asm out dx,al\r
- asm mov dx,0x3da\r
- asm in al,dx\r
- asm mov dx,ATR_INDEX\r
- asm mov al,0x20\r
- asm out dx,al\r
- asm sti\r
-}\r
-\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= VW_SetLineWidth\r
-=\r
-= Must be an even number of bytes\r
-=\r
-====================\r
-*/\r
-\r
-void VW_SetLineWidth (int width)\r
-{\r
- int i,offset;\r
-\r
-#if GRMODE == EGAGR\r
-//\r
-// set wide virtual screen\r
-//\r
-asm mov dx,CRTC_INDEX\r
-asm mov al,CRTC_OFFSET\r
-asm mov ah,[BYTE PTR width]\r
-asm shr ah,1\r
-asm out dx,ax\r
-#endif\r
-\r
-//\r
-// set up lookup tables\r
-//\r
- linewidth = width;\r
-\r
- offset = 0;\r
-\r
- for (i=0;i<VIRTUALHEIGHT;i++)\r
- {\r
- ylookup[i]=offset;\r
- offset += width;\r
- }\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= VW_SetSplitScreen\r
-=\r
-====================\r
-*/\r
-\r
-void VW_SetSplitScreen (int linenum)\r
-{\r
- VW_WaitVBL (1);\r
- if (videocard==VGAcard)\r
- linenum=linenum*2-1;\r
- outportb (CRTC_INDEX,CRTC_LINECOMPARE);\r
- outportb (CRTC_INDEX+1,linenum % 256);\r
- outportb (CRTC_INDEX,CRTC_OVERFLOW);\r
- outportb (CRTC_INDEX+1, 1+16*(linenum/256));\r
- if (videocard==VGAcard)\r
- {\r
- outportb (CRTC_INDEX,CRTC_MAXSCANLINE);\r
- outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1) & (255-64));\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= VW_ClearVideo\r
-=\r
-====================\r
-*/\r
-\r
-void VW_ClearVideo (int color)\r
-{\r
-#if GRMODE == EGAGR\r
- EGAWRITEMODE(2);\r
- EGAMAPMASK(15);\r
-#endif\r
-\r
-asm mov es,[screenseg]\r
-asm xor di,di\r
-asm mov cx,0xffff\r
-asm mov al,[BYTE PTR color]\r
-asm rep stosb\r
-asm stosb\r
-\r
-#if GRMODE == EGAGR\r
- EGAWRITEMODE(0);\r
-#endif\r
-}\r
-\r
-//===========================================================================\r
-\r
-#if NUMPICS>0\r
-\r
-/*\r
-====================\r
-=\r
-= VW_DrawPic\r
-=\r
-= X in bytes, y in pixels, chunknum is the #defined picnum\r
-=\r
-====================\r
-*/\r
-\r
-void VW_DrawPic(unsigned x, unsigned y, unsigned chunknum)\r
-{\r
- int picnum = chunknum - STARTPICS;\r
- memptr source;\r
- unsigned dest,width,height;\r
-\r
- source = grsegs[chunknum];\r
- dest = ylookup[y]+x+bufferofs;\r
- width = pictable[picnum].width;\r
- height = pictable[picnum].height;\r
-\r
- VW_MemToScreen(source,dest,width,height);\r
-}\r
-\r
-\r
-// MDM (GAMERS EDGE) begin\r
-/*\r
-====================\r
-=\r
-= VW_DrawPic2x - Same as VW_DrawPic, but doubles pixels horizontally\r
-= (Great for drawing 320 graphics on 640 screen!)\r
-=\r
-= X in bytes, y in pixels, chunknum is the #defined picnum\r
-=\r
-====================\r
-*/\r
-\r
-void VW_DrawPic2x(unsigned x, unsigned y, unsigned chunknum)\r
-{\r
- int picnum = chunknum - STARTPICS;\r
- memptr source;\r
- unsigned dest,width,height;\r
-\r
- source = grsegs[chunknum];\r
- dest = ylookup[y]+x+bufferofs;\r
- width = pictable[picnum].width;\r
- height = pictable[picnum].height;\r
-\r
- VW_MemToScreen2x(source,dest,width,height);\r
-}\r
-// MDM (GAMERS EDGE) end\r
-\r
-#endif\r
-\r
-#if NUMPICM>0\r
-\r
-/*\r
-====================\r
-=\r
-= VW_DrawMPic\r
-=\r
-= X in bytes, y in pixels, chunknum is the #defined picnum\r
-=\r
-====================\r
-*/\r
-\r
-void VW_DrawMPic(unsigned x, unsigned y, unsigned chunknum)\r
-{\r
- int picnum = chunknum - STARTPICM;\r
- memptr source;\r
- unsigned dest,width,height;\r
-\r
- source = grsegs[chunknum];\r
- dest = ylookup[y]+x+bufferofs;\r
- width = picmtable[picnum].width;\r
- height = picmtable[picnum].height;\r
-\r
- VW_MaskBlock(source,0,dest,width,height,width*height);\r
-}\r
-\r
-void VW_ClipDrawMPic(unsigned x, int y, unsigned chunknum)\r
-{\r
- int picnum = chunknum - STARTPICM;\r
- memptr source;\r
- unsigned dest,width,ofs,plane;\r
- int height;\r
-\r
- source = grsegs[chunknum];\r
- width = picmtable[picnum].width;\r
- height = picmtable[picnum].height;\r
- plane = width*height;\r
-\r
- ofs = 0;\r
- if (y<0)\r
- {\r
- ofs= -y*width;\r
- height+=y;\r
- y=0;\r
- }\r
- else if (y+height>216)\r
- {\r
- height-=(y-216);\r
- }\r
- dest = ylookup[y]+x+bufferofs;\r
- if (height<1)\r
- return;\r
-\r
- VW_MaskBlock(source,ofs,dest,width,height,plane);\r
-}\r
-\r
-\r
-#endif\r
-\r
-//===========================================================================\r
-\r
-#if NUMSPRITES>0\r
-\r
-/*\r
-====================\r
-=\r
-= VW_DrawSprite\r
-=\r
-= X and Y in pixels, it will match the closest shift possible\r
-=\r
-= To do:\r
-= Add vertical clipping!\r
-= Make the shifts act as center points, rather than break points\r
-=\r
-====================\r
-*/\r
-\r
-void VW_DrawSprite(int x, int y, unsigned chunknum)\r
-{\r
- spritetabletype far *spr;\r
- spritetype _seg *block;\r
- unsigned dest,shift;\r
-\r
- spr = &spritetable[chunknum-STARTSPRITES];\r
- block = (spritetype _seg *)grsegs[chunknum];\r
-\r
- y+=spr->orgy>>G_P_SHIFT;\r
- x+=spr->orgx>>G_P_SHIFT;\r
-\r
-#if GRMODE == EGAGR\r
- shift = (x&7)/2;\r
-#endif\r
-#if GRMODE == CGAGR\r
- shift = 0;\r
-#endif\r
-\r
- dest = bufferofs + ylookup[y];\r
- if (x>=0)\r
- dest += x/SCREENXDIV;\r
- else\r
- dest += (x+1)/SCREENXDIV;\r
-\r
- VW_MaskBlock (block,block->sourceoffset[shift],dest,\r
- block->width[shift],spr->height,block->planesize[shift]);\r
-}\r
-\r
-#endif\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= VW_Hlin\r
-=\r
-==================\r
-*/\r
-\r
-\r
-#if GRMODE == EGAGR\r
-\r
-unsigned char leftmask[8] = {0xff,0x7f,0x3f,0x1f,0xf,7,3,1};\r
-unsigned char rightmask[8] = {0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff};\r
-\r
-void VW_Hlin(unsigned xl, unsigned xh, unsigned y, unsigned color)\r
-{\r
- unsigned dest,xlb,xhb,maskleft,maskright,mid;\r
-\r
- xlb=xl/8;\r
- xhb=xh/8;\r
-\r
- EGAWRITEMODE(2);\r
- EGAMAPMASK(15);\r
-\r
- maskleft = leftmask[xl&7];\r
- maskright = rightmask[xh&7];\r
-\r
- mid = xhb-xlb-1;\r
- dest = bufferofs+ylookup[y]+xlb;\r
-\r
- if (xlb==xhb)\r
- {\r
- //\r
- // entire line is in one byte\r
- //\r
-\r
- maskleft&=maskright;\r
-\r
- asm mov es,[screenseg]\r
- asm mov di,[dest]\r
-\r
- asm mov dx,GC_INDEX\r
- asm mov al,GC_BITMASK\r
- asm mov ah,[BYTE PTR maskleft]\r
- asm out dx,ax // mask off pixels\r
-\r
- asm mov al,[BYTE PTR color]\r
- asm xchg al,[es:di] // load latches and write pixels\r
-\r
- goto done;\r
- }\r
-\r
-asm mov es,[screenseg]\r
-asm mov di,[dest]\r
-asm mov dx,GC_INDEX\r
-asm mov bh,[BYTE PTR color]\r
-\r
-//\r
-// draw left side\r
-//\r
-asm mov al,GC_BITMASK\r
-asm mov ah,[BYTE PTR maskleft]\r
-asm out dx,ax // mask off pixels\r
-\r
-asm mov al,bh\r
-asm mov bl,[es:di] // load latches\r
-asm stosb\r
-\r
-//\r
-// draw middle\r
-//\r
-asm mov ax,GC_BITMASK + 255*256\r
-asm out dx,ax // no masking\r
-\r
-asm mov al,bh\r
-asm mov cx,[mid]\r
-asm rep stosb\r
-\r
-//\r
-// draw right side\r
-//\r
-asm mov al,GC_BITMASK\r
-asm mov ah,[BYTE PTR maskright]\r
-asm out dx,ax // mask off pixels\r
-\r
-asm xchg bh,[es:di] // load latches and write pixels\r
-\r
-done:\r
- EGABITMASK(255);\r
- EGAWRITEMODE(0);\r
-}\r
-#endif\r
-\r
-\r
-#if GRMODE == CGAGR\r
-\r
-unsigned char pixmask[4] = {0xc0,0x30,0x0c,0x03};\r
-unsigned char leftmask[4] = {0xff,0x3f,0x0f,0x03};\r
-unsigned char rightmask[4] = {0xc0,0xf0,0xfc,0xff};\r
-unsigned char colorbyte[4] = {0,0x55,0xaa,0xff};\r
-\r
-//\r
-// could be optimized for rep stosw\r
-//\r
-void VW_Hlin(unsigned xl, unsigned xh, unsigned y, unsigned color)\r
-{\r
- unsigned dest,xlb,xhb,mid;\r
- byte maskleft,maskright;\r
-\r
- color = colorbyte[color]; // expand 2 color bits to 8\r
-\r
- xlb=xl/4;\r
- xhb=xh/4;\r
-\r
- maskleft = leftmask[xl&3];\r
- maskright = rightmask[xh&3];\r
-\r
- mid = xhb-xlb-1;\r
- dest = bufferofs+ylookup[y]+xlb;\r
-asm mov es,[screenseg]\r
-\r
- if (xlb==xhb)\r
- {\r
- //\r
- // entire line is in one byte\r
- //\r
- maskleft&=maskright;\r
-\r
- asm mov ah,[maskleft]\r
- asm mov bl,[BYTE PTR color]\r
- asm and bl,[maskleft]\r
- asm not ah\r
-\r
- asm mov di,[dest]\r
-\r
- asm mov al,[es:di]\r
- asm and al,ah // mask out pixels\r
- asm or al,bl // or in color\r
- asm mov [es:di],al\r
- return;\r
- }\r
-\r
-asm mov di,[dest]\r
-asm mov bh,[BYTE PTR color]\r
-\r
-//\r
-// draw left side\r
-//\r
-asm mov ah,[maskleft]\r
-asm mov bl,bh\r
-asm and bl,[maskleft]\r
-asm not ah\r
-asm mov al,[es:di]\r
-asm and al,ah // mask out pixels\r
-asm or al,bl // or in color\r
-asm stosb\r
-\r
-//\r
-// draw middle\r
-//\r
-asm mov al,bh\r
-asm mov cx,[mid]\r
-asm rep stosb\r
-\r
-//\r
-// draw right side\r
-//\r
-asm mov ah,[maskright]\r
-asm mov bl,bh\r
-asm and bl,[maskright]\r
-asm not ah\r
-asm mov al,[es:di]\r
-asm and al,ah // mask out pixels\r
-asm or al,bl // or in color\r
-asm stosb\r
-}\r
-#endif\r
-\r
-\r
-/*\r
-==================\r
-=\r
-= VW_Bar\r
-=\r
-= Pixel addressable block fill routine\r
-=\r
-==================\r
-*/\r
-\r
-#if GRMODE == CGAGR\r
-\r
-void VW_Bar (unsigned x, unsigned y, unsigned width, unsigned height,\r
- unsigned color)\r
-{\r
- unsigned xh = x+width-1;\r
-\r
- while (height--)\r
- VW_Hlin (x,xh,y++,color);\r
-}\r
-\r
-#endif\r
-\r
-\r
-#if GRMODE == EGAGR\r
-\r
-void VW_Bar (unsigned x, unsigned y, unsigned width, unsigned height,\r
- unsigned color)\r
-{\r
- unsigned dest,xh,xlb,xhb,maskleft,maskright,mid;\r
-\r
- xh = x+width-1;\r
- xlb=x/8;\r
- xhb=xh/8;\r
-\r
- EGAWRITEMODE(2);\r
- EGAMAPMASK(15);\r
-\r
- maskleft = leftmask[x&7];\r
- maskright = rightmask[xh&7];\r
-\r
- mid = xhb-xlb-1;\r
- dest = bufferofs+ylookup[y]+xlb;\r
-\r
- if (xlb==xhb)\r
- {\r
- //\r
- // entire line is in one byte\r
- //\r
-\r
- maskleft&=maskright;\r
-\r
- asm mov es,[screenseg]\r
- asm mov di,[dest]\r
-\r
- asm mov dx,GC_INDEX\r
- asm mov al,GC_BITMASK\r
- asm mov ah,[BYTE PTR maskleft]\r
- asm out dx,ax // mask off pixels\r
-\r
- asm mov ah,[BYTE PTR color]\r
- asm mov dx,[linewidth]\r
-yloop1:\r
- asm mov al,ah\r
- asm xchg al,[es:di] // load latches and write pixels\r
- asm add di,dx // down to next line\r
- asm dec [height]\r
- asm jnz yloop1\r
-\r
- goto done;\r
- }\r
-\r
-asm mov es,[screenseg]\r
-asm mov di,[dest]\r
-asm mov bh,[BYTE PTR color]\r
-asm mov dx,GC_INDEX\r
-asm mov si,[linewidth]\r
-asm sub si,[mid] // add to di at end of line to get to next scan\r
-asm dec si\r
-\r
-//\r
-// draw left side\r
-//\r
-yloop2:\r
-asm mov al,GC_BITMASK\r
-asm mov ah,[BYTE PTR maskleft]\r
-asm out dx,ax // mask off pixels\r
-\r
-asm mov al,bh\r
-asm mov bl,[es:di] // load latches\r
-asm stosb\r
-\r
-//\r
-// draw middle\r
-//\r
-asm mov ax,GC_BITMASK + 255*256\r
-asm out dx,ax // no masking\r
-\r
-asm mov al,bh\r
-asm mov cx,[mid]\r
-asm rep stosb\r
-\r
-//\r
-// draw right side\r
-//\r
-asm mov al,GC_BITMASK\r
-asm mov ah,[BYTE PTR maskright]\r
-asm out dx,ax // mask off pixels\r
-\r
-asm mov al,bh\r
-asm xchg al,[es:di] // load latches and write pixels\r
-\r
-asm add di,si // move to start of next line\r
-asm dec [height]\r
-asm jnz yloop2\r
-\r
-done:\r
- EGABITMASK(255);\r
- EGAWRITEMODE(0);\r
-}\r
-\r
-#endif\r
-\r
-//==========================================================================\r
-\r
-/*\r
-==================\r
-=\r
-= VW_MeasureString\r
-=\r
-==================\r
-*/\r
-\r
-#if NUMFONT+NUMFONTM>0\r
-void\r
-VWL_MeasureString (char far *string, word *width, word *height, fontstruct _seg *font)\r
-{\r
- *height = font->height-1; // MDM (GAMERS EDGE) - squeeze font vertically...\r
- for (*width = 0;*string;string++)\r
- *width += font->width[*((byte far *)string)]; // proportional width\r
-}\r
-\r
-void VW_MeasurePropString (char far *string, word *width, word *height)\r
-{\r
- VWL_MeasureString(string,width,height,(fontstruct _seg *)grsegs[STARTFONT+fontnumber]);\r
-}\r
-\r
-void VW_MeasureMPropString (char far *string, word *width, word *height)\r
-{\r
- VWL_MeasureString(string,width,height,(fontstruct _seg *)grsegs[STARTFONTM+fontnumber]);\r
-}\r
-\r
-\r
-#endif\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- CGA stuff\r
-\r
-=============================================================================\r
-*/\r
-\r
-#if GRMODE == CGAGR\r
-\r
-#define CGACRTCWIDTH 40\r
-\r
-/*\r
-==========================\r
-=\r
-= VW_CGAFullUpdate\r
-=\r
-==========================\r
-*/\r
-\r
-void VW_CGAFullUpdate (void)\r
-{\r
- byte *update;\r
- boolean halftile;\r
- unsigned x,y,middlerows,middlecollumns;\r
-\r
- displayofs = bufferofs+panadjust;\r
-\r
-asm mov ax,0xb800\r
-asm mov es,ax\r
-\r
-asm mov si,[displayofs]\r
-asm xor di,di\r
-\r
-asm mov bx,100 // pairs of scan lines to copy\r
-asm mov dx,[linewidth]\r
-asm sub dx,80\r
-\r
-asm mov ds,[screenseg]\r
-asm test si,1\r
-asm jz evenblock\r
-\r
-//\r
-// odd source\r
-//\r
-asm mov ax,39 // words accross screen\r
-copytwolineso:\r
-asm movsb\r
-asm mov cx,ax\r
-asm rep movsw\r
-asm movsb\r
-asm add si,dx\r
-asm add di,0x2000-80 // go to the interlaced bank\r
-asm movsb\r
-asm mov cx,ax\r
-asm rep movsw\r
-asm movsb\r
-asm add si,dx\r
-asm sub di,0x2000 // go to the non interlaced bank\r
-\r
-asm dec bx\r
-asm jnz copytwolineso\r
-asm jmp blitdone\r
-\r
-//\r
-// even source\r
-//\r
-evenblock:\r
-asm mov ax,40 // words accross screen\r
-copytwolines:\r
-asm mov cx,ax\r
-asm rep movsw\r
-asm add si,dx\r
-asm add di,0x2000-80 // go to the interlaced bank\r
-asm mov cx,ax\r
-asm rep movsw\r
-asm add si,dx\r
-asm sub di,0x2000 // go to the non interlaced bank\r
-\r
-asm dec bx\r
-asm jnz copytwolines\r
-\r
-blitdone:\r
-asm mov ax,ss\r
-asm mov ds,ax\r
-asm mov es,ax\r
-\r
-asm xor ax,ax // clear out the update matrix\r
-asm mov cx,UPDATEWIDE*UPDATEHIGH/2\r
-\r
-asm mov di,[baseupdateptr]\r
-asm rep stosw\r
-\r
- updateptr = baseupdateptr;\r
- *(unsigned *)(updateptr + UPDATEWIDE*PORTTILESHIGH) = UPDATETERMINATE;\r
-}\r
-\r
-\r
-#endif\r
-\r
-/*\r
-=============================================================================\r
-\r
- CURSOR ROUTINES\r
-\r
-These only work in the context of the double buffered update routines\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-====================\r
-=\r
-= VWL_DrawCursor\r
-=\r
-= Background saves, then draws the cursor at cursorspot\r
-=\r
-====================\r
-*/\r
-\r
-void VWL_DrawCursor (void)\r
-{\r
- cursorspot = bufferofs + ylookup[cursory+pansy]+(cursorx+pansx)/SCREENXDIV;\r
- VW_ScreenToMem(cursorspot,cursorsave,cursorwidth,cursorheight);\r
- VWB_DrawSprite(cursorx,cursory,cursornumber);\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= VWL_EraseCursor\r
-=\r
-====================\r
-*/\r
-\r
-void VWL_EraseCursor (void)\r
-{\r
- VW_MemToScreen(cursorsave,cursorspot,cursorwidth,cursorheight);\r
- VW_MarkUpdateBlock ((cursorx+pansx)&SCREENXMASK,cursory+pansy,\r
- ( (cursorx+pansx)&SCREENXMASK)+cursorwidth*SCREENXDIV-1,\r
- cursory+pansy+cursorheight-1);\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= VW_ShowCursor\r
-=\r
-====================\r
-*/\r
-\r
-void VW_ShowCursor (void)\r
-{\r
- cursorvisible++;\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= VW_HideCursor\r
-=\r
-====================\r
-*/\r
-\r
-void VW_HideCursor (void)\r
-{\r
- cursorvisible--;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= VW_MoveCursor\r
-=\r
-====================\r
-*/\r
-#define MAXCURSORX (319-24)\r
-#define MAXCURSORY (199-24)\r
-\r
-void VW_MoveCursor (int x, int y)\r
-{\r
- if (x>MAXCURSORX)\r
- x=MAXCURSORX;\r
- if (y>MAXCURSORY)\r
- y=MAXCURSORY; // catacombs hack to keep cursor on screen\r
-\r
- cursorx = x;\r
- cursory = y;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= VW_SetCursor\r
-=\r
-= Load in a sprite to be used as a cursor, and allocate background save space\r
-=\r
-====================\r
-*/\r
-\r
-void VW_SetCursor (int spritenum)\r
-{\r
- VW_FreeCursor ();\r
-\r
- cursornumber = spritenum;\r
-\r
- CA_CacheGrChunk (spritenum);\r
- MM_SetLock (&grsegs[spritenum],true);\r
-\r
- cursorwidth = spritetable[spritenum-STARTSPRITES].width+1;\r
- cursorheight = spritetable[spritenum-STARTSPRITES].height;\r
-\r
- MM_GetPtr (&cursorsave,cursorwidth*cursorheight*5);\r
- MM_SetLock (&cursorsave,true);\r
-}\r
-\r
-\r
-/*\r
-====================\r
-=\r
-= VW_FreeCursor\r
-=\r
-= Frees the memory used by the cursor and its background save\r
-=\r
-====================\r
-*/\r
-\r
-void VW_FreeCursor (void)\r
-{\r
- if (cursornumber)\r
- {\r
- MM_SetLock (&grsegs[cursornumber],false);\r
- MM_SetPurge (&grsegs[cursornumber],3);\r
- MM_SetLock (&cursorsave,false);\r
- MM_FreePtr (&cursorsave);\r
- cursornumber = 0;\r
- }\r
-}\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- Double buffer management routines\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-======================\r
-=\r
-= VW_InitDoubleBuffer\r
-=\r
-======================\r
-*/\r
-\r
-void VW_InitDoubleBuffer (void)\r
-{\r
-#if GRMODE == EGAGR\r
- VW_SetScreen (displayofs+panadjust,0); // no pel pan\r
-#endif\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= VW_FixRefreshBuffer\r
-=\r
-= Copies the view page to the buffer page on page flipped refreshes to\r
-= avoid a one frame shear around pop up windows\r
-=\r
-======================\r
-*/\r
-\r
-void VW_FixRefreshBuffer (void)\r
-{\r
-#if GRMODE == EGAGR\r
- VW_ScreenToScreen (displayofs,bufferofs,PORTTILESWIDE*4*CHARWIDTH,\r
- (PORTTILESHIGH-1)*16);\r
-#endif\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= VW_QuitDoubleBuffer\r
-=\r
-======================\r
-*/\r
-\r
-void VW_QuitDoubleBuffer (void)\r
-{\r
-}\r
-\r
-\r
-/*\r
-=======================\r
-=\r
-= VW_MarkUpdateBlock\r
-=\r
-= Takes a pixel bounded block and marks the tiles in bufferblocks\r
-= Returns 0 if the entire block is off the buffer screen\r
-=\r
-=======================\r
-*/\r
-\r
-int VW_MarkUpdateBlock (int x1, int y1, int x2, int y2)\r
-{\r
-// MDM (GAMERS EDGE) begin - NOT NEEDED FOR 3D ENGINE\r
-#if 0\r
- int x,y,xt1,yt1,xt2,yt2,nextline;\r
- byte *mark;\r
-\r
- xt1 = x1>>PIXTOBLOCK;\r
- yt1 = y1>>PIXTOBLOCK;\r
-\r
- xt2 = x2>>PIXTOBLOCK;\r
- yt2 = y2>>PIXTOBLOCK;\r
-\r
- if (xt1<0)\r
- xt1=0;\r
- else if (xt1>=UPDATEWIDE-1)\r
- return 0;\r
-\r
- if (yt1<0)\r
- yt1=0;\r
- else if (yt1>UPDATEHIGH)\r
- return 0;\r
-\r
- if (xt2<0)\r
- return 0;\r
- else if (xt2>=UPDATEWIDE-1)\r
- xt2 = UPDATEWIDE-2;\r
-\r
- if (yt2<0)\r
- return 0;\r
- else if (yt2>=UPDATEHIGH)\r
- yt2 = UPDATEHIGH-1;\r
-\r
- mark = updateptr + uwidthtable[yt1] + xt1;\r
- nextline = UPDATEWIDE - (xt2-xt1) - 1;\r
-\r
- for (y=yt1;y<=yt2;y++)\r
- {\r
- for (x=xt1;x<=xt2;x++)\r
- *mark++ = 1; // this tile will need to be updated\r
-\r
- mark += nextline;\r
- }\r
-#endif\r
-// MDM (GAMERS EDGE) end\r
-\r
- return 1;\r
-}\r
-\r
-\r
-/*\r
-===========================\r
-=\r
-= VW_UpdateScreen\r
-=\r
-= Updates any changed areas of the double buffer and displays the cursor\r
-=\r
-===========================\r
-*/\r
-\r
-void VW_UpdateScreen (void)\r
-{\r
- if (cursorvisible>0)\r
- VWL_DrawCursor();\r
-\r
-#if GRMODE == EGAGR\r
- VWL_UpdateScreenBlocks();\r
-\r
-asm mov ax,ds\r
-asm mov es,ax\r
-asm mov di,[updateptr] // cat3d patch\r
-asm xor ax,ax // clear out the update matrix\r
-asm mov cx,UPDATEWIDE*UPDATEHIGH/2\r
-asm rep stosw\r
- *(unsigned *)(updateptr + UPDATEWIDE*PORTTILESHIGH) = UPDATETERMINATE;\r
-\r
-asm cli\r
-asm mov cx,[displayofs]\r
-asm add cx,[panadjust]\r
-asm mov dx,CRTC_INDEX\r
-asm mov al,0ch // start address high register\r
-asm out dx,al\r
-asm inc dx\r
-asm mov al,ch\r
-asm out dx,al\r
-asm dec dx\r
-asm mov al,0dh // start address low register\r
-asm out dx,al\r
-asm mov al,cl\r
-asm inc dx\r
-asm out dx,al\r
-asm sti\r
-\r
-#endif\r
-#if GRMODE == CGAGR\r
- VW_CGAFullUpdate();\r
-#endif\r
-\r
- if (cursorvisible>0)\r
- VWL_EraseCursor();\r
-}\r
-\r
-\r
-\r
-void VWB_DrawTile8 (int x, int y, int tile)\r
-{\r
- x+=pansx;\r
- y+=pansy;\r
- if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+7,y+7))\r
- VW_DrawTile8 (x/SCREENXDIV,y,tile);\r
-}\r
-\r
-void VWB_DrawTile8M (int x, int y, int tile)\r
-{\r
- int xb;\r
-\r
- x+=pansx;\r
- y+=pansy;\r
- xb = x/SCREENXDIV; // use intermediate because VW_DT8M is macro\r
-// if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+7,y+7)) // MDM (GAMER EDGE)\r
- VW_DrawTile8M (xb,y,tile); // statement prevents drawing chars past 42\r
-}\r
-\r
-void VWB_DrawTile16 (int x, int y, int tile)\r
-{\r
- x+=pansx;\r
- y+=pansy;\r
- if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+15,y+15))\r
- VW_DrawTile16 (x/SCREENXDIV,y,tile);\r
-}\r
-\r
-void VWB_DrawTile16M (int x, int y, int tile)\r
-{\r
- int xb;\r
-\r
- x+=pansx;\r
- y+=pansy;\r
- xb = x/SCREENXDIV; // use intermediate because VW_DT16M is macro\r
- if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+15,y+15))\r
- VW_DrawTile16M (xb,y,tile);\r
-}\r
-\r
-#if NUMPICS\r
-void VWB_DrawPic (int x, int y, int chunknum)\r
-{\r
-// mostly copied from drawpic\r
- int picnum = chunknum - STARTPICS;\r
- memptr source;\r
- unsigned dest,width,height;\r
-\r
- x+=pansx;\r
- y+=pansy;\r
- x/= SCREENXDIV;\r
-\r
- source = grsegs[chunknum];\r
- dest = ylookup[y]+x+bufferofs;\r
- width = pictable[picnum].width;\r
- height = pictable[picnum].height;\r
-\r
- if (VW_MarkUpdateBlock (x*SCREENXDIV,y,(x+width)*SCREENXDIV-1,y+height-1))\r
- VW_MemToScreen(source,dest,width,height);\r
-}\r
-#endif\r
-\r
-#if NUMPICM>0\r
-void VWB_DrawMPic(int x, int y, int chunknum)\r
-{\r
-// mostly copied from drawmpic\r
- int picnum = chunknum - STARTPICM;\r
- memptr source;\r
- unsigned dest,width,height;\r
-\r
- x+=pansx;\r
- y+=pansy;\r
- x/=SCREENXDIV;\r
-\r
- source = grsegs[chunknum];\r
- dest = ylookup[y]+x+bufferofs;\r
- width = picmtable[picnum].width;\r
- height = picmtable[picnum].height;\r
-\r
- if (VW_MarkUpdateBlock (x*SCREENXDIV,y,(x+width)*SCREENXDIV-1,y+height-1))\r
- VW_MaskBlock(source,0,dest,width,height,width*height);\r
-}\r
-#endif\r
-\r
-\r
-void VWB_Bar (int x, int y, int width, int height, int color)\r
-{\r
- x+=pansx;\r
- y+=pansy;\r
- if (VW_MarkUpdateBlock (x,y,x+width,y+height-1) )\r
- VW_Bar (x,y,width,height,color);\r
-}\r
-\r
-\r
-#if NUMFONT\r
-void VWB_DrawPropString (char far *string)\r
-{\r
- int x,y;\r
- x = px+pansx;\r
- y = py+pansy;\r
- VW_DrawPropString (string);\r
- VW_MarkUpdateBlock(x,y,x+bufferwidth*8-1,y+bufferheight-1);\r
-}\r
-#endif\r
-\r
-\r
-#if NUMFONTM\r
-void VWB_DrawMPropString (char far *string)\r
-{\r
- int x,y;\r
- x = px+pansx;\r
- y = py+pansy;\r
- VW_DrawMPropString (string);\r
- VW_MarkUpdateBlock(x,y,x+bufferwidth*8-1,y+bufferheight-1);\r
-}\r
-#endif\r
-\r
-#if NUMSPRITES\r
-void VWB_DrawSprite(int x, int y, int chunknum)\r
-{\r
- spritetabletype far *spr;\r
- spritetype _seg *block;\r
- unsigned dest,shift,width,height;\r
-\r
- x+=pansx;\r
- y+=pansy;\r
-\r
- spr = &spritetable[chunknum-STARTSPRITES];\r
- block = (spritetype _seg *)grsegs[chunknum];\r
-\r
- y+=spr->orgy>>G_P_SHIFT;\r
- x+=spr->orgx>>G_P_SHIFT;\r
-\r
-\r
-#if GRMODE == EGAGR\r
- shift = (x&7)/2;\r
-#endif\r
-#if GRMODE == CGAGR\r
- shift = 0;\r
-#endif\r
-\r
- dest = bufferofs + ylookup[y];\r
- if (x>=0)\r
- dest += x/SCREENXDIV;\r
- else\r
- dest += (x+1)/SCREENXDIV;\r
-\r
- width = block->width[shift];\r
- height = spr->height;\r
-\r
- if (VW_MarkUpdateBlock (x&SCREENXMASK,y,(x&SCREENXMASK)+width*SCREENXDIV-1\r
- ,y+height-1))\r
- VW_MaskBlock (block,block->sourceoffset[shift],dest,\r
- width,height,block->planesize[shift]);\r
-}\r
-#endif\r
-\r
-void VWB_Plot (int x, int y, int color)\r
-{\r
- x+=pansx;\r
- y+=pansy;\r
- if (VW_MarkUpdateBlock (x,y,x,y))\r
- VW_Plot(x,y,color);\r
-}\r
-\r
-void VWB_Hlin (int x1, int x2, int y, int color)\r
-{\r
- x1+=pansx;\r
- x2+=pansx;\r
- y+=pansy;\r
- if (VW_MarkUpdateBlock (x1,y,x2,y))\r
- VW_Hlin(x1,x2,y,color);\r
-}\r
-\r
-void VWB_Vlin (int y1, int y2, int x, int color)\r
-{\r
- x+=pansx;\r
- y1+=pansy;\r
- y2+=pansy;\r
- if (VW_MarkUpdateBlock (x,y1,x,y2))\r
- VW_Vlin(y1,y2,x,color);\r
-}\r
-\r
-\r
-//===========================================================================\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_VW.H\r
-\r
-#ifndef __TYPES__\r
-#include "ID_TYPES.H"\r
-#endif\r
-\r
-#ifndef __ID_MM__\r
-#include "ID_MM.H"\r
-#endif\r
-\r
-#ifndef __ID_GLOB__\r
-#include "ID_GLOB.H"\r
-#endif\r
-\r
-#define __ID_VW__\r
-\r
-//===========================================================================\r
-\r
-#define G_P_SHIFT 4 // global >> ?? = pixels\r
-\r
-#if GRMODE == EGAGR\r
-#define SCREENWIDTH 40\r
-#define CHARWIDTH 1\r
-#define TILEWIDTH 2\r
-#define GRPLANES 4\r
-#define BYTEPIXELS 8\r
-#endif\r
-\r
-#if GRMODE == CGAGR\r
-#define SCREENWIDTH 128\r
-#define CHARWIDTH 2\r
-#define TILEWIDTH 4\r
-#define GRPLANES 1\r
-#define BYTEPIXELS 4\r
-#endif\r
-\r
-#define VIRTUALHEIGHT 300\r
-#define VIRTUALWIDTH 512\r
-\r
-\r
-#if GRMODE == CGAGR\r
-\r
-#define MAXSHIFTS 1\r
-\r
-#define WHITE 3 // graphics mode independant colors\r
-#define BLACK 0\r
-#define FIRSTCOLOR 1\r
-#define SECONDCOLOR 2\r
-#define F_WHITE 0 // for XOR font drawing\r
-#define F_BLACK 3\r
-#define F_FIRSTCOLOR 2\r
-#define F_SECONDCOLOR 1\r
-\r
-#endif\r
-\r
-#if GRMODE == EGAGR\r
-\r
-#define MAXSHIFTS 4\r
-\r
-#define WHITE 15 // graphics mode independant colors\r
-#define BLACK 0\r
-#define LT_GREY 7\r
-#define FIRSTCOLOR 1\r
-#define SECONDCOLOR 12\r
-#define F_WHITE 0 // for XOR font drawing\r
-#define F_BLACK 15\r
-#define F_FIRSTCOLOR 14\r
-#define F_SECONDCOLOR 3\r
-\r
-#endif\r
-\r
-#if GRMODE == EGAGR\r
-#define SCREENXMASK (~7)\r
-#define SCREENXPLUS (7)\r
-#define SCREENXDIV (8)\r
-#endif\r
-\r
-#if GRMODE == CGAGR\r
-#define SCREENXMASK (~3)\r
-#define SCREENXDIV (4)\r
-#endif\r
-\r
-//===========================================================================\r
-\r
-\r
-#define SC_INDEX 0x3C4\r
-#define SC_RESET 0\r
-#define SC_CLOCK 1\r
-#define SC_MAPMASK 2\r
-#define SC_CHARMAP 3\r
-#define SC_MEMMODE 4\r
-\r
-#define CRTC_INDEX 0x3D4\r
-#define CRTC_H_TOTAL 0\r
-#define CRTC_H_DISPEND 1\r
-#define CRTC_H_BLANK 2\r
-#define CRTC_H_ENDBLANK 3\r
-#define CRTC_H_RETRACE 4\r
-#define CRTC_H_ENDRETRACE 5\r
-#define CRTC_V_TOTAL 6\r
-#define CRTC_OVERFLOW 7\r
-#define CRTC_ROWSCAN 8\r
-#define CRTC_MAXSCANLINE 9\r
-#define CRTC_CURSORSTART 10\r
-#define CRTC_CURSOREND 11\r
-#define CRTC_STARTHIGH 12\r
-#define CRTC_STARTLOW 13\r
-#define CRTC_CURSORHIGH 14\r
-#define CRTC_CURSORLOW 15\r
-#define CRTC_V_RETRACE 16\r
-#define CRTC_V_ENDRETRACE 17\r
-#define CRTC_V_DISPEND 18\r
-#define CRTC_OFFSET 19\r
-#define CRTC_UNDERLINE 20\r
-#define CRTC_V_BLANK 21\r
-#define CRTC_V_ENDBLANK 22\r
-#define CRTC_MODE 23\r
-#define CRTC_LINECOMPARE 24\r
-\r
-\r
-#define GC_INDEX 0x3CE\r
-#define GC_SETRESET 0\r
-#define GC_ENABLESETRESET 1\r
-#define GC_COLORCOMPARE 2\r
-#define GC_DATAROTATE 3\r
-#define GC_READMAP 4\r
-#define GC_MODE 5\r
-#define GC_MISCELLANEOUS 6\r
-#define GC_COLORDONTCARE 7\r
-#define GC_BITMASK 8\r
-\r
-#define ATR_INDEX 0x3c0\r
-#define ATR_MODE 16\r
-#define ATR_OVERSCAN 17\r
-#define ATR_COLORPLANEENABLE 18\r
-#define ATR_PELPAN 19\r
-#define ATR_COLORSELECT 20\r
-\r
-#define STATUS_REGISTER_1 0x3da\r
-\r
-//===========================================================================\r
-\r
-typedef enum {NOcard,MDAcard,CGAcard,EGAcard,MCGAcard,VGAcard,\r
- HGCcard=0x80,HGCPcard,HICcard} cardtype;\r
-\r
-typedef struct\r
-{\r
- int width,\r
- height,\r
- orgx,orgy,\r
- xl,yl,xh,yh,\r
- shifts;\r
-} spritetabletype;\r
-\r
-typedef struct\r
-{\r
- unsigned sourceoffset[MAXSHIFTS];\r
- unsigned planesize[MAXSHIFTS];\r
- unsigned width[MAXSHIFTS];\r
- byte data[];\r
-} spritetype; // the memptr for each sprite points to this\r
-\r
-typedef struct\r
-{\r
- int width,height;\r
-} pictabletype;\r
-\r
-\r
-typedef struct\r
-{\r
- int height;\r
- int location[256];\r
- char width[256];\r
-} fontstruct;\r
-\r
-\r
-typedef enum {CGAgr,EGAgr,VGAgr} grtype;\r
-\r
-//===========================================================================\r
-\r
-extern cardtype videocard; // set by VW_Startup\r
-extern grtype grmode; // CGAgr, EGAgr, VGAgr\r
-\r
-extern unsigned bufferofs; // hidden port to draw to before displaying\r
-extern unsigned displayofs; // origin of port on visable screen\r
-extern unsigned panx,pany; // panning adjustments inside port in pixels\r
-extern unsigned pansx,pansy;\r
-extern unsigned panadjust; // panx/pany adjusted by screen resolution\r
-\r
-extern unsigned screenseg; // normally 0xa000 or buffer segment\r
-\r
-extern unsigned linewidth;\r
-extern unsigned ylookup[VIRTUALHEIGHT];\r
-\r
-extern boolean screenfaded;\r
-extern char colors[7][17]; // pallets for fades\r
-\r
-extern pictabletype _seg *pictable;\r
-extern pictabletype _seg *picmtable;\r
-extern spritetabletype _seg *spritetable;\r
-\r
-extern unsigned fontnumber; // 0 based font number for drawing\r
-extern int px,py;\r
-extern byte pdrawmode,fontcolor;\r
-\r
-extern int bordercolor;\r
-\r
-//\r
-// asm globals\r
-//\r
-\r
-extern unsigned *shifttabletable[8];\r
-extern unsigned bufferwidth,bufferheight,screenspot; // used by font drawing stuff\r
-\r
-\r
-\r
-//===========================================================================\r
-\r
-\r
-void VW_Startup (void);\r
-void VW_Shutdown (void);\r
-\r
-cardtype VW_VideoID (void);\r
-\r
-//\r
-// EGA hardware routines\r
-//\r
-\r
-#define EGAWRITEMODE(x) asm{cli;mov dx,GC_INDEX;mov ax,GC_MODE+256*x;out dx,ax;sti;}\r
-#define EGABITMASK(x) asm{cli;mov dx,GC_INDEX;mov ax,GC_BITMASK+256*x;out dx,ax;sti;}\r
-#define EGAMAPMASK(x) asm{cli;mov dx,SC_INDEX;mov ax,SC_MAPMASK+x*256;out dx,ax;sti;}\r
-#define EGAREADMAP(x) asm{cli;mov dx,GC_INDEX;mov ax,GC_READMAP+x*256;out dx,ax;sti;}\r
-\r
-void VW_SetLineWidth(int width);\r
-void VW_SetSplitScreen(int width);\r
-void VW_SetScreen (unsigned CRTC, unsigned pelpan);\r
-\r
-void VW_SetScreenMode (int grmode);\r
-void VW_ClearVideo (int color);\r
-void VW_WaitVBL (int number);\r
-\r
-void VW_ColorBorder (int color);\r
-void VW_SetPalette(byte *palette);\r
-void VW_SetDefaultColors(void);\r
-void VW_FadeOut(void);\r
-void VW_FadeIn(void);\r
-void VW_FadeUp(void);\r
-void VW_FadeDown(void);\r
-\r
-void VW_SetAtrReg (int reg, int value);\r
-\r
-//\r
-// block primitives\r
-//\r
-\r
-void VW_MaskBlock(memptr segm,unsigned ofs,unsigned dest,\r
- unsigned wide,unsigned height,unsigned planesize);\r
-void VW_MemToScreen(memptr source,unsigned dest,unsigned width,unsigned height);\r
-void VW_MemToScreen2x(memptr source,unsigned dest,unsigned width,unsigned height);\r
-void VW_ScreenToMem(unsigned source,memptr dest,unsigned width,unsigned height);\r
-void VW_ScreenToScreen(unsigned source,unsigned dest,unsigned width,unsigned height);\r
-\r
-\r
-//\r
-// block addressable routines\r
-//\r
-\r
-void VW_DrawTile8(unsigned x, unsigned y, unsigned tile);\r
-\r
-#if GRMODE == EGAGR\r
-\r
-#define VW_DrawTile8M(x,y,t) \\r
- VW_MaskBlock(grsegs[STARTTILE8M],(t)*40,bufferofs+ylookup[y]+(x),1,8,8)\r
-#define VW_DrawTile16(x,y,t) \\r
- VW_MemToScreen(grsegs[STARTTILE16+t],bufferofs+ylookup[y]+(x),2,16)\r
-#define VW_DrawTile16M(x,y,t) \\r
- VW_MaskBlock(grsegs[STARTTILE16M],(t)*160,bufferofs+ylookup[y]+(x),2,16,32)\r
-\r
-#endif\r
-\r
-#if GRMODE == CGAGR\r
-\r
-#define VW_DrawTile8M(x,y,t) \\r
- VW_MaskBlock(grsegs[STARTTILE8M],(t)*32,bufferofs+ylookup[y]+(x),2,8,16)\r
-#define VW_DrawTile16(x,y,t) \\r
- VW_MemToScreen(grsegs[STARTTILE16+t],bufferofs+ylookup[y]+(x),4,16)\r
-#define VW_DrawTile16M(x,y,t) \\r
- VW_MaskBlock(grsegs[STARTTILE16M],(t)*128,bufferofs+ylookup[y]+(x),4,16,64)\r
-\r
-#endif\r
-\r
-void VW_DrawPic(unsigned x, unsigned y, unsigned chunknum);\r
-void VW_DrawPic2x(unsigned x, unsigned y, unsigned chunknum);\r
-void VW_DrawMPic(unsigned x, unsigned y, unsigned chunknum);\r
-void VW_ClipDrawMPic(unsigned x, int y, unsigned chunknum);\r
-\r
-//\r
-// pixel addressable routines\r
-//\r
-void VW_MeasurePropString (char far *string, word *width, word *height);\r
-void VW_MeasureMPropString (char far *string, word *width, word *height);\r
-\r
-void VW_DrawPropString (char far *string);\r
-void VW_DrawMPropString (char far *string);\r
-void VW_DrawSprite(int x, int y, unsigned sprite);\r
-void VW_Plot(unsigned x, unsigned y, unsigned color);\r
-void VW_Hlin(unsigned xl, unsigned xh, unsigned y, unsigned color);\r
-void VW_Vlin(unsigned yl, unsigned yh, unsigned x, unsigned color);\r
-void VW_Bar (unsigned x, unsigned y, unsigned width, unsigned height,\r
- unsigned color);\r
-\r
-//===========================================================================\r
-\r
-//\r
-// Double buffer management routines\r
-//\r
-\r
-void VW_InitDoubleBuffer (void);\r
-void VW_FixRefreshBuffer (void);\r
-int VW_MarkUpdateBlock (int x1, int y1, int x2, int y2);\r
-void VW_UpdateScreen (void);\r
-void VW_CGAFullUpdate (void);\r
-\r
-//\r
-// cursor\r
-//\r
-\r
-void VW_ShowCursor (void);\r
-void VW_HideCursor (void);\r
-void VW_MoveCursor (int x, int y);\r
-void VW_SetCursor (int spritenum);\r
-void VW_FreeCursor (void);\r
-\r
-//\r
-// mode independant routines\r
-// coordinates in pixels, rounded to best screen res\r
-// regions marked in double buffer\r
-//\r
-\r
-void VWB_DrawTile8 (int x, int y, int tile);\r
-void VWB_DrawTile8M (int x, int y, int tile);\r
-void VWB_DrawTile16 (int x, int y, int tile);\r
-void VWB_DrawTile16M (int x, int y, int tile);\r
-void VWB_DrawPic (int x, int y, int chunknum);\r
-void VWB_DrawMPic(int x, int y, int chunknum);\r
-void VWB_Bar (int x, int y, int width, int height, int color);\r
-\r
-void VWB_DrawPropString (char far *string);\r
-void VWB_DrawMPropString (char far *string);\r
-void VWB_DrawSprite (int x, int y, int chunknum);\r
-void VWB_Plot (int x, int y, int color);\r
-void VWB_Hlin (int x1, int x2, int y, int color);\r
-void VWB_Vlin (int y1, int y2, int x, int color);\r
-\r
-void VWL_MeasureString (char far *string, word *width, word *height, fontstruct _seg *font);\r
-//===========================================================================\r
+++ /dev/null
-; Catacomb Armageddon Source Code\r
-; Copyright (C) 1993-2014 Flat Rock Software\r
-;\r
-; This program is free software; you can redistribute it and/or modify\r
-; it under the terms of the GNU General Public License as published by\r
-; the Free Software Foundation; either version 2 of the License, or\r
-; (at your option) any later version.\r
-;\r
-; This program is distributed in the hope that it will be useful,\r
-; but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-; GNU General Public License for more details.\r
-;\r
-; You should have received a copy of the GNU General Public License along\r
-; with this program; if not, write to the Free Software Foundation, Inc.,\r
-; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-\r
-; ID_VW_A.ASM\r
-\r
-IDEAL\r
-MODEL MEDIUM,C\r
-\r
-INCLUDE "ID_ASM.EQU"\r
-\r
-WAITFORVBL = 1 ; setting to 0 causes setscreen and waitvbl\r
- ; to skip waiting for VBL (for timing things)\r
-\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-EXTRN screenseg :WORD\r
-EXTRN drawofs :WORD\r
-EXTRN bufferofs :WORD\r
-EXTRN displayofs :WORD\r
-EXTRN drawofs :WORD\r
-EXTRN panadjust :WORD\r
-EXTRN ylookup :WORD\r
-EXTRN linewidth :WORD\r
-EXTRN grsegs :WORD\r
-EXTRN updateptr :WORD\r
-EXTRN blockstarts :WORD ;offsets from drawofs for each update block\r
-EXTRN fontspace :WORD\r
-EXTRN fontnumber :WORD\r
-\r
-\r
-planemask db ?\r
-planenum db ?\r
-screendest dw ?\r
-linedelta dw ?\r
-\r
-LABEL shiftdata0 WORD\r
-; dw 0\r
-\r
-if 1\r
- dw 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13\r
- dw 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27\r
- dw 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41\r
- dw 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55\r
- dw 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69\r
- dw 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83\r
- dw 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97\r
- dw 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111\r
- dw 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125\r
- dw 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139\r
- dw 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153\r
- dw 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167\r
- dw 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181\r
- dw 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195\r
- dw 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209\r
- dw 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223\r
- dw 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237\r
- dw 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251\r
- dw 252, 253, 254, 255\r
-endif\r
-\r
-LABEL shiftdata1 WORD\r
-; dw 0\r
-\r
-if 1\r
- dw 0,32768, 1,32769, 2,32770, 3,32771, 4,32772, 5,32773, 6,32774\r
- dw 7,32775, 8,32776, 9,32777, 10,32778, 11,32779, 12,32780, 13,32781\r
- dw 14,32782, 15,32783, 16,32784, 17,32785, 18,32786, 19,32787, 20,32788\r
- dw 21,32789, 22,32790, 23,32791, 24,32792, 25,32793, 26,32794, 27,32795\r
- dw 28,32796, 29,32797, 30,32798, 31,32799, 32,32800, 33,32801, 34,32802\r
- dw 35,32803, 36,32804, 37,32805, 38,32806, 39,32807, 40,32808, 41,32809\r
- dw 42,32810, 43,32811, 44,32812, 45,32813, 46,32814, 47,32815, 48,32816\r
- dw 49,32817, 50,32818, 51,32819, 52,32820, 53,32821, 54,32822, 55,32823\r
- dw 56,32824, 57,32825, 58,32826, 59,32827, 60,32828, 61,32829, 62,32830\r
- dw 63,32831, 64,32832, 65,32833, 66,32834, 67,32835, 68,32836, 69,32837\r
- dw 70,32838, 71,32839, 72,32840, 73,32841, 74,32842, 75,32843, 76,32844\r
- dw 77,32845, 78,32846, 79,32847, 80,32848, 81,32849, 82,32850, 83,32851\r
- dw 84,32852, 85,32853, 86,32854, 87,32855, 88,32856, 89,32857, 90,32858\r
- dw 91,32859, 92,32860, 93,32861, 94,32862, 95,32863, 96,32864, 97,32865\r
- dw 98,32866, 99,32867, 100,32868, 101,32869, 102,32870, 103,32871, 104,32872\r
- dw 105,32873, 106,32874, 107,32875, 108,32876, 109,32877, 110,32878, 111,32879\r
- dw 112,32880, 113,32881, 114,32882, 115,32883, 116,32884, 117,32885, 118,32886\r
- dw 119,32887, 120,32888, 121,32889, 122,32890, 123,32891, 124,32892, 125,32893\r
- dw 126,32894, 127,32895\r
-endif\r
-\r
-LABEL shiftdata2 WORD\r
- dw 0,16384,32768,49152, 1,16385,32769,49153, 2,16386,32770,49154, 3,16387\r
- dw 32771,49155, 4,16388,32772,49156, 5,16389,32773,49157, 6,16390,32774,49158\r
- dw 7,16391,32775,49159, 8,16392,32776,49160, 9,16393,32777,49161, 10,16394\r
- dw 32778,49162, 11,16395,32779,49163, 12,16396,32780,49164, 13,16397,32781,49165\r
- dw 14,16398,32782,49166, 15,16399,32783,49167, 16,16400,32784,49168, 17,16401\r
- dw 32785,49169, 18,16402,32786,49170, 19,16403,32787,49171, 20,16404,32788,49172\r
- dw 21,16405,32789,49173, 22,16406,32790,49174, 23,16407,32791,49175, 24,16408\r
- dw 32792,49176, 25,16409,32793,49177, 26,16410,32794,49178, 27,16411,32795,49179\r
- dw 28,16412,32796,49180, 29,16413,32797,49181, 30,16414,32798,49182, 31,16415\r
- dw 32799,49183, 32,16416,32800,49184, 33,16417,32801,49185, 34,16418,32802,49186\r
- dw 35,16419,32803,49187, 36,16420,32804,49188, 37,16421,32805,49189, 38,16422\r
- dw 32806,49190, 39,16423,32807,49191, 40,16424,32808,49192, 41,16425,32809,49193\r
- dw 42,16426,32810,49194, 43,16427,32811,49195, 44,16428,32812,49196, 45,16429\r
- dw 32813,49197, 46,16430,32814,49198, 47,16431,32815,49199, 48,16432,32816,49200\r
- dw 49,16433,32817,49201, 50,16434,32818,49202, 51,16435,32819,49203, 52,16436\r
- dw 32820,49204, 53,16437,32821,49205, 54,16438,32822,49206, 55,16439,32823,49207\r
- dw 56,16440,32824,49208, 57,16441,32825,49209, 58,16442,32826,49210, 59,16443\r
- dw 32827,49211, 60,16444,32828,49212, 61,16445,32829,49213, 62,16446,32830,49214\r
- dw 63,16447,32831,49215\r
-\r
-LABEL shiftdata3 WORD\r
-; dw 0\r
-\r
-if 1\r
- dw 0, 8192,16384,24576,32768,40960,49152,57344, 1, 8193,16385,24577,32769,40961\r
- dw 49153,57345, 2, 8194,16386,24578,32770,40962,49154,57346, 3, 8195,16387,24579\r
- dw 32771,40963,49155,57347, 4, 8196,16388,24580,32772,40964,49156,57348, 5, 8197\r
- dw 16389,24581,32773,40965,49157,57349, 6, 8198,16390,24582,32774,40966,49158,57350\r
- dw 7, 8199,16391,24583,32775,40967,49159,57351, 8, 8200,16392,24584,32776,40968\r
- dw 49160,57352, 9, 8201,16393,24585,32777,40969,49161,57353, 10, 8202,16394,24586\r
- dw 32778,40970,49162,57354, 11, 8203,16395,24587,32779,40971,49163,57355, 12, 8204\r
- dw 16396,24588,32780,40972,49164,57356, 13, 8205,16397,24589,32781,40973,49165,57357\r
- dw 14, 8206,16398,24590,32782,40974,49166,57358, 15, 8207,16399,24591,32783,40975\r
- dw 49167,57359, 16, 8208,16400,24592,32784,40976,49168,57360, 17, 8209,16401,24593\r
- dw 32785,40977,49169,57361, 18, 8210,16402,24594,32786,40978,49170,57362, 19, 8211\r
- dw 16403,24595,32787,40979,49171,57363, 20, 8212,16404,24596,32788,40980,49172,57364\r
- dw 21, 8213,16405,24597,32789,40981,49173,57365, 22, 8214,16406,24598,32790,40982\r
- dw 49174,57366, 23, 8215,16407,24599,32791,40983,49175,57367, 24, 8216,16408,24600\r
- dw 32792,40984,49176,57368, 25, 8217,16409,24601,32793,40985,49177,57369, 26, 8218\r
- dw 16410,24602,32794,40986,49178,57370, 27, 8219,16411,24603,32795,40987,49179,57371\r
- dw 28, 8220,16412,24604,32796,40988,49180,57372, 29, 8221,16413,24605,32797,40989\r
- dw 49181,57373, 30, 8222,16414,24606,32798,40990,49182,57374, 31, 8223,16415,24607\r
- dw 32799,40991,49183,57375\r
-endif\r
-\r
-LABEL shiftdata4 WORD\r
- dw 0, 4096, 8192,12288,16384,20480,24576,28672,32768,36864,40960,45056,49152,53248\r
- dw 57344,61440, 1, 4097, 8193,12289,16385,20481,24577,28673,32769,36865,40961,45057\r
- dw 49153,53249,57345,61441, 2, 4098, 8194,12290,16386,20482,24578,28674,32770,36866\r
- dw 40962,45058,49154,53250,57346,61442, 3, 4099, 8195,12291,16387,20483,24579,28675\r
- dw 32771,36867,40963,45059,49155,53251,57347,61443, 4, 4100, 8196,12292,16388,20484\r
- dw 24580,28676,32772,36868,40964,45060,49156,53252,57348,61444, 5, 4101, 8197,12293\r
- dw 16389,20485,24581,28677,32773,36869,40965,45061,49157,53253,57349,61445, 6, 4102\r
- dw 8198,12294,16390,20486,24582,28678,32774,36870,40966,45062,49158,53254,57350,61446\r
- dw 7, 4103, 8199,12295,16391,20487,24583,28679,32775,36871,40967,45063,49159,53255\r
- dw 57351,61447, 8, 4104, 8200,12296,16392,20488,24584,28680,32776,36872,40968,45064\r
- dw 49160,53256,57352,61448, 9, 4105, 8201,12297,16393,20489,24585,28681,32777,36873\r
- dw 40969,45065,49161,53257,57353,61449, 10, 4106, 8202,12298,16394,20490,24586,28682\r
- dw 32778,36874,40970,45066,49162,53258,57354,61450, 11, 4107, 8203,12299,16395,20491\r
- dw 24587,28683,32779,36875,40971,45067,49163,53259,57355,61451, 12, 4108, 8204,12300\r
- dw 16396,20492,24588,28684,32780,36876,40972,45068,49164,53260,57356,61452, 13, 4109\r
- dw 8205,12301,16397,20493,24589,28685,32781,36877,40973,45069,49165,53261,57357,61453\r
- dw 14, 4110, 8206,12302,16398,20494,24590,28686,32782,36878,40974,45070,49166,53262\r
- dw 57358,61454, 15, 4111, 8207,12303,16399,20495,24591,28687,32783,36879,40975,45071\r
- dw 49167,53263,57359,61455\r
-\r
-LABEL shiftdata5 WORD\r
-; dw 0\r
-\r
-if 1\r
- dw 0, 2048, 4096, 6144, 8192,10240,12288,14336,16384,18432,20480,22528,24576,26624\r
- dw 28672,30720,32768,34816,36864,38912,40960,43008,45056,47104,49152,51200,53248,55296\r
- dw 57344,59392,61440,63488, 1, 2049, 4097, 6145, 8193,10241,12289,14337,16385,18433\r
- dw 20481,22529,24577,26625,28673,30721,32769,34817,36865,38913,40961,43009,45057,47105\r
- dw 49153,51201,53249,55297,57345,59393,61441,63489, 2, 2050, 4098, 6146, 8194,10242\r
- dw 12290,14338,16386,18434,20482,22530,24578,26626,28674,30722,32770,34818,36866,38914\r
- dw 40962,43010,45058,47106,49154,51202,53250,55298,57346,59394,61442,63490, 3, 2051\r
- dw 4099, 6147, 8195,10243,12291,14339,16387,18435,20483,22531,24579,26627,28675,30723\r
- dw 32771,34819,36867,38915,40963,43011,45059,47107,49155,51203,53251,55299,57347,59395\r
- dw 61443,63491, 4, 2052, 4100, 6148, 8196,10244,12292,14340,16388,18436,20484,22532\r
- dw 24580,26628,28676,30724,32772,34820,36868,38916,40964,43012,45060,47108,49156,51204\r
- dw 53252,55300,57348,59396,61444,63492, 5, 2053, 4101, 6149, 8197,10245,12293,14341\r
- dw 16389,18437,20485,22533,24581,26629,28677,30725,32773,34821,36869,38917,40965,43013\r
- dw 45061,47109,49157,51205,53253,55301,57349,59397,61445,63493, 6, 2054, 4102, 6150\r
- dw 8198,10246,12294,14342,16390,18438,20486,22534,24582,26630,28678,30726,32774,34822\r
- dw 36870,38918,40966,43014,45062,47110,49158,51206,53254,55302,57350,59398,61446,63494\r
- dw 7, 2055, 4103, 6151, 8199,10247,12295,14343,16391,18439,20487,22535,24583,26631\r
- dw 28679,30727,32775,34823,36871,38919,40967,43015,45063,47111,49159,51207,53255,55303\r
- dw 57351,59399,61447,63495\r
-endif\r
-\r
-LABEL shiftdata6 WORD\r
- dw 0, 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192, 9216,10240,11264,12288,13312\r
- dw 14336,15360,16384,17408,18432,19456,20480,21504,22528,23552,24576,25600,26624,27648\r
- dw 28672,29696,30720,31744,32768,33792,34816,35840,36864,37888,38912,39936,40960,41984\r
- dw 43008,44032,45056,46080,47104,48128,49152,50176,51200,52224,53248,54272,55296,56320\r
- dw 57344,58368,59392,60416,61440,62464,63488,64512, 1, 1025, 2049, 3073, 4097, 5121\r
- dw 6145, 7169, 8193, 9217,10241,11265,12289,13313,14337,15361,16385,17409,18433,19457\r
- dw 20481,21505,22529,23553,24577,25601,26625,27649,28673,29697,30721,31745,32769,33793\r
- dw 34817,35841,36865,37889,38913,39937,40961,41985,43009,44033,45057,46081,47105,48129\r
- dw 49153,50177,51201,52225,53249,54273,55297,56321,57345,58369,59393,60417,61441,62465\r
- dw 63489,64513, 2, 1026, 2050, 3074, 4098, 5122, 6146, 7170, 8194, 9218,10242,11266\r
- dw 12290,13314,14338,15362,16386,17410,18434,19458,20482,21506,22530,23554,24578,25602\r
- dw 26626,27650,28674,29698,30722,31746,32770,33794,34818,35842,36866,37890,38914,39938\r
- dw 40962,41986,43010,44034,45058,46082,47106,48130,49154,50178,51202,52226,53250,54274\r
- dw 55298,56322,57346,58370,59394,60418,61442,62466,63490,64514, 3, 1027, 2051, 3075\r
- dw 4099, 5123, 6147, 7171, 8195, 9219,10243,11267,12291,13315,14339,15363,16387,17411\r
- dw 18435,19459,20483,21507,22531,23555,24579,25603,26627,27651,28675,29699,30723,31747\r
- dw 32771,33795,34819,35843,36867,37891,38915,39939,40963,41987,43011,44035,45059,46083\r
- dw 47107,48131,49155,50179,51203,52227,53251,54275,55299,56323,57347,58371,59395,60419\r
- dw 61443,62467,63491,64515\r
-\r
-LABEL shiftdata7 WORD\r
-; dw 0\r
-\r
-if 1\r
- dw 0, 512, 1024, 1536, 2048, 2560, 3072, 3584, 4096, 4608, 5120, 5632, 6144, 6656\r
- dw 7168, 7680, 8192, 8704, 9216, 9728,10240,10752,11264,11776,12288,12800,13312,13824\r
- dw 14336,14848,15360,15872,16384,16896,17408,17920,18432,18944,19456,19968,20480,20992\r
- dw 21504,22016,22528,23040,23552,24064,24576,25088,25600,26112,26624,27136,27648,28160\r
- dw 28672,29184,29696,30208,30720,31232,31744,32256,32768,33280,33792,34304,34816,35328\r
- dw 35840,36352,36864,37376,37888,38400,38912,39424,39936,40448,40960,41472,41984,42496\r
- dw 43008,43520,44032,44544,45056,45568,46080,46592,47104,47616,48128,48640,49152,49664\r
- dw 50176,50688,51200,51712,52224,52736,53248,53760,54272,54784,55296,55808,56320,56832\r
- dw 57344,57856,58368,58880,59392,59904,60416,60928,61440,61952,62464,62976,63488,64000\r
- dw 64512,65024, 1, 513, 1025, 1537, 2049, 2561, 3073, 3585, 4097, 4609, 5121, 5633\r
- dw 6145, 6657, 7169, 7681, 8193, 8705, 9217, 9729,10241,10753,11265,11777,12289,12801\r
- dw 13313,13825,14337,14849,15361,15873,16385,16897,17409,17921,18433,18945,19457,19969\r
- dw 20481,20993,21505,22017,22529,23041,23553,24065,24577,25089,25601,26113,26625,27137\r
- dw 27649,28161,28673,29185,29697,30209,30721,31233,31745,32257,32769,33281,33793,34305\r
- dw 34817,35329,35841,36353,36865,37377,37889,38401,38913,39425,39937,40449,40961,41473\r
- dw 41985,42497,43009,43521,44033,44545,45057,45569,46081,46593,47105,47617,48129,48641\r
- dw 49153,49665,50177,50689,51201,51713,52225,52737,53249,53761,54273,54785,55297,55809\r
- dw 56321,56833,57345,57857,58369,58881,59393,59905,60417,60929,61441,61953,62465,62977\r
- dw 63489,64001,64513,65025\r
-endif\r
-\r
-shifttabletable dw shiftdata0,shiftdata1,shiftdata2,shiftdata3\r
- dw shiftdata4,shiftdata5,shiftdata6,shiftdata7\r
-\r
-PUBLIC shifttabletable\r
-\r
-\r
-;============================================================================\r
-\r
-CODESEG\r
-\r
-IFE GRMODE-CGAGR\r
-INCLUDE "ID_VW_AC.ASM"\r
-ENDIF\r
-\r
-IFE GRMODE-EGAGR\r
-INCLUDE "ID_VW_AE.ASM"\r
-ENDIF\r
-\r
-IFE GRMODE-VGAGR\r
-INCLUDE "ID_VW_AV.ASM"\r
-ENDIF\r
-\r
-;============================================================================\r
-;\r
-; MISC VIDEO ROUTINES\r
-;\r
-;============================================================================\r
-\r
-;========\r
-;\r
-; VW_WaitVBL (int number)\r
-;\r
-;========\r
-\r
-PROC VW_WaitVBL number:WORD\r
-PUBLIC VW_WaitVBL\r
-\r
-if WAITFORVBL ; skip wait if profiling\r
-\r
- mov dx,STATUS_REGISTER_1\r
-\r
- mov cx,[number]\r
-\r
-waitvbl1:\r
- in al,dx\r
- test al,00001000b ;look for vbl\r
- jnz waitvbl1\r
-\r
-waitvbl2:\r
- in al,dx\r
- test al,00001000b ;look for vbl\r
- jz waitvbl2\r
-\r
- loop waitvbl1\r
-\r
-endif\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;===========================================================================\r
-\r
-\r
- MASM\r
-;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ\r
-;\r
-; Name: VW_VideoID\r
-;\r
-; Function: Detects the presence of various video subsystems\r
-;\r
-; int VideoID;\r
-;\r
-; Subsystem ID values:\r
-; 0 = (none)\r
-; 1 = MDA\r
-; 2 = CGA\r
-; 3 = EGA\r
-; 4 = MCGA\r
-; 5 = VGA\r
-; 80h = HGC\r
-; 81h = HGC+\r
-; 82h = Hercules InColor\r
-;\r
-;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ\r
-\r
-;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ\r
-;\r
-; Equates\r
-;\r
-;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ\r
-VIDstruct STRUC ; corresponds to C data structure\r
-\r
-Video0Type DB ? ; first subsystem type\r
-Display0Type DB ? ; display attached to first subsystem\r
-\r
-Video1Type DB ? ; second subsystem type\r
-Display1Type DB ? ; display attached to second subsystem\r
-\r
-VIDstruct ENDS\r
-\r
-\r
-Device0 EQU word ptr Video0Type[di]\r
-Device1 EQU word ptr Video1Type[di]\r
-\r
-\r
-MDA EQU 1 ; subsystem types\r
-CGA EQU 2\r
-EGA EQU 3\r
-MCGA EQU 4\r
-VGA EQU 5\r
-HGC EQU 80h\r
-HGCPlus EQU 81h\r
-InColor EQU 82h\r
-\r
-MDADisplay EQU 1 ; display types\r
-CGADisplay EQU 2\r
-EGAColorDisplay EQU 3\r
-PS2MonoDisplay EQU 4\r
-PS2ColorDisplay EQU 5\r
-\r
-TRUE EQU 1\r
-FALSE EQU 0\r
-\r
-;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ\r
-;\r
-; Program\r
-;\r
-;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ\r
-\r
-Results VIDstruct <> ;results go here!\r
-\r
-EGADisplays DB CGADisplay ; 0000b, 0001b (EGA switch values)\r
- DB EGAColorDisplay ; 0010b, 0011b\r
- DB MDADisplay ; 0100b, 0101b\r
- DB CGADisplay ; 0110b, 0111b\r
- DB EGAColorDisplay ; 1000b, 1001b\r
- DB MDADisplay ; 1010b, 1011b\r
-\r
-DCCtable DB 0,0 ; translate table for INT 10h func 1Ah\r
- DB MDA,MDADisplay\r
- DB CGA,CGADisplay\r
- DB 0,0\r
- DB EGA,EGAColorDisplay\r
- DB EGA,MDADisplay\r
- DB 0,0\r
- DB VGA,PS2MonoDisplay\r
- DB VGA,PS2ColorDisplay\r
- DB 0,0\r
- DB MCGA,EGAColorDisplay\r
- DB MCGA,PS2MonoDisplay\r
- DB MCGA,PS2ColorDisplay\r
-\r
-TestSequence DB TRUE ; this list of flags and addresses\r
- DW FindPS2 ; determines the order in which this\r
- ; program looks for the various\r
-EGAflag DB ? ; subsystems\r
- DW FindEGA\r
-\r
-CGAflag DB ?\r
- DW FindCGA\r
-\r
-Monoflag DB ?\r
- DW FindMono\r
-\r
-NumberOfTests EQU ($-TestSequence)/3\r
-\r
-\r
-PUBLIC VW_VideoID\r
-VW_VideoID PROC\r
-\r
- push bp ; preserve caller registers\r
- mov bp,sp\r
- push ds\r
- push si\r
- push di\r
-\r
- push cs\r
- pop ds\r
- ASSUME DS:@Code\r
-\r
-; initialize the data structure that will contain the results\r
-\r
- lea di,Results ; DS:DI -> start of data structure\r
-\r
- mov Device0,0 ; zero these variables\r
- mov Device1,0\r
-\r
-; look for the various subsystems using the subroutines whose addresses are\r
-; tabulated in TestSequence; each subroutine sets flags in TestSequence\r
-; to indicate whether subsequent subroutines need to be called\r
-\r
- mov byte ptr CGAflag,TRUE\r
- mov byte ptr EGAflag,TRUE\r
- mov byte ptr Monoflag,TRUE\r
-\r
- mov cx,NumberOfTests\r
- mov si,offset TestSequence\r
-\r
-@@L01: lodsb ; AL := flag\r
- test al,al\r
- lodsw ; AX := subroutine address\r
- jz @@L02 ; skip subroutine if flag is false\r
-\r
- push si\r
- push cx\r
- call ax ; call subroutine to detect subsystem\r
- pop cx\r
- pop si\r
-\r
-@@L02: loop @@L01\r
-\r
-; determine which subsystem is active\r
-\r
- call FindActive\r
-\r
- mov al,Results.Video0Type\r
- mov ah,0 ; was: Results.Display0Type\r
-\r
- pop di ; restore caller registers and return\r
- pop si\r
- pop ds\r
- mov sp,bp\r
- pop bp\r
- ret\r
-\r
-VW_VideoID ENDP\r
-\r
-\r
-;\r
-; FindPS2\r
-;\r
-; This subroutine uses INT 10H function 1Ah to determine the video BIOS\r
-; Display Combination Code (DCC) for each video subsystem present.\r
-;\r
-\r
-FindPS2 PROC near\r
-\r
- mov ax,1A00h\r
- int 10h ; call video BIOS for info\r
-\r
- cmp al,1Ah\r
- jne @@L13 ; exit if function not supported (i.e.,\r
- ; no MCGA or VGA in system)\r
-\r
-; convert BIOS DCCs into specific subsystems & displays\r
-\r
- mov cx,bx\r
- xor bh,bh ; BX := DCC for active subsystem\r
-\r
- or ch,ch\r
- jz @@L11 ; jump if only one subsystem present\r
-\r
- mov bl,ch ; BX := inactive DCC\r
- add bx,bx\r
- mov ax,[bx+offset DCCtable]\r
-\r
- mov Device1,ax\r
-\r
- mov bl,cl\r
- xor bh,bh ; BX := active DCC\r
-\r
-@@L11: add bx,bx\r
- mov ax,[bx+offset DCCtable]\r
-\r
- mov Device0,ax\r
-\r
-; reset flags for subsystems that have been ruled out\r
-\r
- mov byte ptr CGAflag,FALSE\r
- mov byte ptr EGAflag,FALSE\r
- mov byte ptr Monoflag,FALSE\r
-\r
- lea bx,Video0Type[di] ; if the BIOS reported an MDA ...\r
- cmp byte ptr [bx],MDA\r
- je @@L12\r
-\r
- lea bx,Video1Type[di]\r
- cmp byte ptr [bx],MDA\r
- jne @@L13\r
-\r
-@@L12: mov word ptr [bx],0 ; ... Hercules can't be ruled out\r
- mov byte ptr Monoflag,TRUE\r
-\r
-@@L13: ret\r
-\r
-FindPS2 ENDP\r
-\r
-\r
-;\r
-; FindEGA\r
-;\r
-; Look for an EGA. This is done by making a call to an EGA BIOS function\r
-; which doesn't exist in the default (MDA, CGA) BIOS.\r
-\r
-FindEGA PROC near ; Caller: AH = flags\r
- ; Returns: AH = flags\r
- ; Video0Type and\r
- ; Display0Type updated\r
-\r
- mov bl,10h ; BL := 10h (return EGA info)\r
- mov ah,12h ; AH := INT 10H function number\r
- int 10h ; call EGA BIOS for info\r
- ; if EGA BIOS is present,\r
- ; BL <> 10H\r
- ; CL = switch setting\r
- cmp bl,10h\r
- je @@L22 ; jump if EGA BIOS not present\r
-\r
- mov al,cl\r
- shr al,1 ; AL := switches/2\r
- mov bx,offset EGADisplays\r
- xlat ; determine display type from switches\r
- mov ah,al ; AH := display type\r
- mov al,EGA ; AL := subystem type\r
- call FoundDevice\r
-\r
- cmp ah,MDADisplay\r
- je @@L21 ; jump if EGA has a monochrome display\r
-\r
- mov CGAflag,FALSE ; no CGA if EGA has color display\r
- jmp short @@L22\r
-\r
-@@L21: mov Monoflag,FALSE ; EGA has a mono display, so MDA and\r
- ; Hercules are ruled out\r
-@@L22: ret\r
-\r
-FindEGA ENDP\r
-\r
-;\r
-; FindCGA\r
-;\r
-; This is done by looking for the CGA's 6845 CRTC at I/O port 3D4H.\r
-;\r
-FindCGA PROC near ; Returns: VIDstruct updated\r
-\r
- mov dx,3D4h ; DX := CRTC address port\r
- call Find6845\r
- jc @@L31 ; jump if not present\r
-\r
- mov al,CGA\r
- mov ah,CGADisplay\r
- call FoundDevice\r
-\r
-@@L31: ret\r
-\r
-FindCGA ENDP\r
-\r
-;\r
-; FindMono\r
-;\r
-; This is done by looking for the MDA's 6845 CRTC at I/O port 3B4H. If\r
-; a 6845 is found, the subroutine distinguishes between an MDA\r
-; and a Hercules adapter by monitoring bit 7 of the CRT Status byte.\r
-; This bit changes on Hercules adapters but does not change on an MDA.\r
-;\r
-; The various Hercules adapters are identified by bits 4 through 6 of\r
-; the CRT Status value:\r
-;\r
-; 000b = HGC\r
-; 001b = HGC+\r
-; 101b = InColor card\r
-;\r
-\r
-FindMono PROC near ; Returns: VIDstruct updated\r
-\r
- mov dx,3B4h ; DX := CRTC address port\r
- call Find6845\r
- jc @@L44 ; jump if not present\r
-\r
- mov dl,0BAh ; DX := 3BAh (status port)\r
- in al,dx\r
- and al,80h\r
- mov ah,al ; AH := bit 7 (vertical sync on HGC)\r
-\r
- mov cx,8000h ; do this 32768 times\r
-@@L41: in al,dx\r
- and al,80h ; isolate bit 7\r
- cmp ah,al\r
- loope @@L41 ; wait for bit 7 to change\r
- jne @@L42 ; if bit 7 changed, it's a Hercules\r
-\r
- mov al,MDA ; if bit 7 didn't change, it's an MDA\r
- mov ah,MDADisplay\r
- call FoundDevice\r
- jmp short @@L44\r
-\r
-@@L42: in al,dx\r
- mov dl,al ; DL := value from status port\r
- and dl,01110000b ; mask bits 4 thru 6\r
-\r
- mov ah,MDADisplay ; assume it's a monochrome display\r
-\r
- mov al,HGCPlus ; look for an HGC+\r
- cmp dl,00010000b\r
- je @@L43 ; jump if it's an HGC+\r
-\r
- mov al,HGC ; look for an InColor card or HGC\r
- cmp dl,01010000b\r
- jne @@L43 ; jump if it's not an InColor card\r
-\r
- mov al,InColor ; it's an InColor card\r
- mov ah,EGAColorDisplay\r
-\r
-@@L43: call FoundDevice\r
-\r
-@@L44: ret\r
-\r
-FindMono ENDP\r
-\r
-;\r
-; Find6845\r
-;\r
-; This routine detects the presence of the CRTC on a MDA, CGA or HGC.\r
-; The technique is to write and read register 0Fh of the chip (cursor\r
-; low). If the same value is read as written, assume the chip is\r
-; present at the specified port addr.\r
-;\r
-\r
-Find6845 PROC near ; Caller: DX = port addr\r
- ; Returns: cf set if not present\r
- mov al,0Fh\r
- out dx,al ; select 6845 reg 0Fh (Cursor Low)\r
- inc dx\r
- in al,dx ; AL := current Cursor Low value\r
- mov ah,al ; preserve in AH\r
- mov al,66h ; AL := arbitrary value\r
- out dx,al ; try to write to 6845\r
-\r
- mov cx,100h\r
-@@L51: loop @@L51 ; wait for 6845 to respond\r
-\r
- in al,dx\r
- xchg ah,al ; AH := returned value\r
- ; AL := original value\r
- out dx,al ; restore original value\r
-\r
- cmp ah,66h ; test whether 6845 responded\r
- je @@L52 ; jump if it did (cf is reset)\r
-\r
- stc ; set carry flag if no 6845 present\r
-\r
-@@L52: ret\r
-\r
-Find6845 ENDP\r
-\r
-\r
-;\r
-; FindActive\r
-;\r
-; This subroutine stores the currently active device as Device0. The\r
-; current video mode determines which subsystem is active.\r
-;\r
-\r
-FindActive PROC near\r
-\r
- cmp word ptr Device1,0\r
- je @@L63 ; exit if only one subsystem\r
-\r
- cmp Video0Type[di],4 ; exit if MCGA or VGA present\r
- jge @@L63 ; (INT 10H function 1AH\r
- cmp Video1Type[di],4 ; already did the work)\r
- jge @@L63\r
-\r
- mov ah,0Fh\r
- int 10h ; AL := current BIOS video mode\r
-\r
- and al,7\r
- cmp al,7 ; jump if monochrome\r
- je @@L61 ; (mode 7 or 0Fh)\r
-\r
- cmp Display0Type[di],MDADisplay\r
- jne @@L63 ; exit if Display0 is color\r
- jmp short @@L62\r
-\r
-@@L61: cmp Display0Type[di],MDADisplay\r
- je @@L63 ; exit if Display0 is monochrome\r
-\r
-@@L62: mov ax,Device0 ; make Device0 currently active\r
- xchg ax,Device1\r
- mov Device0,ax\r
-\r
-@@L63: ret\r
-\r
-FindActive ENDP\r
-\r
-\r
-;\r
-; FoundDevice\r
-;\r
-; This routine updates the list of subsystems.\r
-;\r
-\r
-FoundDevice PROC near ; Caller: AH = display #\r
- ; AL = subsystem #\r
- ; Destroys: BX\r
- lea bx,Video0Type[di]\r
- cmp byte ptr [bx],0\r
- je @@L71 ; jump if 1st subsystem\r
-\r
- lea bx,Video1Type[di] ; must be 2nd subsystem\r
-\r
-@@L71: mov [bx],ax ; update list entry\r
- ret\r
-\r
-FoundDevice ENDP\r
-\r
-IDEAL\r
-\r
-\r
-\r
-END\r
+++ /dev/null
-; Catacomb Armageddon Source Code\r
-; Copyright (C) 1993-2014 Flat Rock Software\r
-;\r
-; This program is free software; you can redistribute it and/or modify\r
-; it under the terms of the GNU General Public License as published by\r
-; the Free Software Foundation; either version 2 of the License, or\r
-; (at your option) any later version.\r
-;\r
-; This program is distributed in the hope that it will be useful,\r
-; but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-; GNU General Public License for more details.\r
-;\r
-; You should have received a copy of the GNU General Public License along\r
-; with this program; if not, write to the Free Software Foundation, Inc.,\r
-; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-\r
-;=================================\r
-;\r
-; CGA view manager routines\r
-;\r
-;=================================\r
-\r
-;============================================================================\r
-;\r
-; All of these routines draw into a floating virtual screen segment in main\r
-; memory. bufferofs points to the origin of the drawing page in screenseg.\r
-; The routines that write out words must take into account buffer wrapping\r
-; and not write a word at 0xffff (which causes an exception on 386s).\r
-;\r
-; The direction flag should be clear\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-plotpixels db 0c0h,030h,0ch,03h\r
-colorbyte db 000000b,01010101b,10101010b,11111111b\r
-colorword dw 0,5555h,0aaaah,0ffffh\r
-\r
-CODESEG\r
-\r
-;============================================================================\r
-;\r
-; VW_Plot (int x,y,color)\r
-;\r
-;============================================================================\r
-\r
-\r
-PROC VW_Plot x:WORD, y:WORD, color:WORD\r
-PUBLIC VW_Plot\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov di,[bufferofs]\r
- mov bx,[y]\r
- shl bx,1\r
- add di,[ylookup+bx]\r
- mov bx,[x]\r
- mov ax,bx\r
- shr ax,1\r
- shr ax,1\r
- add di,ax ; di = byte on screen\r
-\r
- and bx,3\r
- mov ah,[plotpixels+bx]\r
- mov bx,[color]\r
- mov cl,[colorbyte+bx]\r
- and cl,ah\r
- not ah\r
-\r
- mov al,[es:di]\r
- and al,ah ; mask off other pixels\r
- or al,cl\r
- stosb\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_Vlin (int yl,yh,x,color)\r
-;\r
-;============================================================================\r
-\r
-PROC VW_Vlin yl:WORD, yh:WORD, x:WORD, color:WORD\r
-PUBLIC VW_Vlin\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov di,[bufferofs]\r
- mov bx,[yl]\r
- shl bx,1\r
- add di,[ylookup+bx]\r
- mov bx,[x]\r
- mov ax,bx\r
- shr ax,1\r
- shr ax,1\r
- add di,ax ; di = byte on screen\r
-\r
- and bx,3\r
- mov ah,[plotpixels+bx]\r
- mov bx,[color]\r
- mov bl,[colorbyte+bx]\r
- and bl,ah\r
- not ah\r
-\r
- mov cx,[yh]\r
- sub cx,[yl]\r
- inc cx ;number of pixels to plot\r
-\r
- mov dx,[linewidth]\r
-\r
-@@plot:\r
- mov al,[es:di]\r
- and al,ah ; mask off other pixels\r
- or al,bl\r
- mov [es:di],al\r
- add di,dx\r
- loop @@plot\r
-\r
- ret\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-\r
-\r
-;===================\r
-;\r
-; VW_DrawTile8\r
-;\r
-; xcoord in bytes (8 pixels), ycoord in pixels\r
-; All Tile8s are in one grseg, so an offset is calculated inside it\r
-;\r
-; DONE\r
-;\r
-;===================\r
-\r
-PROC VW_DrawTile8 xcoord:WORD, ycoord:WORD, tile:WORD\r
-PUBLIC VW_DrawTile8\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov di,[bufferofs]\r
- add di,[xcoord]\r
- mov bx,[ycoord]\r
- shl bx,1\r
- add di,[ylookup+bx]\r
-\r
- mov bx,[linewidth]\r
- sub bx,2\r
-\r
- mov si,[tile]\r
- shl si,1\r
- shl si,1\r
- shl si,1\r
- shl si,1\r
-\r
- mov ds,[grsegs+STARTTILE8*2] ; segment for all tile8s\r
-\r
-;\r
-; start drawing\r
-;\r
-\r
-REPT 7\r
- movsb ;no word moves because of segment wrapping\r
- movsb\r
- add di,bx\r
-ENDM\r
- movsb\r
- movsb\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_MaskBlock\r
-;\r
-; Draws a masked block shape to the screen. bufferofs is NOT accounted for.\r
-; The mask comes first, then the data. Seperate unwound routines are used\r
-; to speed drawing.\r
-;\r
-; Mask blocks will allways be an even width because of the way IGRAB works\r
-;\r
-; DONE\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-UNWOUNDMASKS = 18\r
-\r
-\r
-maskroutines dw mask0,mask0,mask2E,mask2O,mask4E,mask4O\r
- dw mask6E,mask6O,mask8E,mask8O,mask10E,mask10O\r
- dw mask12E,mask12O,mask14E,mask14O,mask16E,mask16O\r
- dw mask18E,mask18O\r
-\r
-\r
-routinetouse dw ?\r
-\r
-CODESEG\r
-\r
-PROC VW_MaskBlock segm:WORD, ofs:WORD, dest:WORD, wide:WORD, height:WORD, planesize:WORD\r
-PUBLIC VW_MaskBlock\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov di,[wide]\r
- mov dx,[linewidth]\r
- sub dx,di ;dx = delta to start of next line\r
-\r
- mov bx,[planesize] ; si+bx = data location\r
-\r
- cmp di,UNWOUNDMASKS\r
- jbe @@unwoundroutine\r
-\r
-;==============\r
-;\r
-; General purpose masked block drawing. This could be optimised into\r
-; four routines to use words, but few play loop sprites should be this big!\r
-;\r
-;==============\r
-\r
- mov [ss:linedelta],dx\r
- mov ds,[segm]\r
- mov si,[ofs]\r
- mov di,[dest]\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloopgen:\r
- mov cx,[wide]\r
-@@byteloop:\r
- mov al,[es:di]\r
- and al,[si]\r
- or al,[bx+si]\r
- inc si\r
- stosb\r
- loop @@byteloop\r
-\r
- add di,[ss:linedelta]\r
- dec dx\r
- jnz @@lineloopgen\r
-\r
-mask0:\r
- mov ax,ss\r
- mov ds,ax\r
- ret ;width of 0 = no drawing\r
-\r
-\r
-;=================\r
-;\r
-; use the unwound routines\r
-;\r
-;=================\r
-\r
-@@unwoundroutine:\r
- shr di,1 ;we only have even width unwound routines\r
- mov cx,[dest]\r
- shr cx,1\r
- rcl di,1 ;shift a 1 in if destination is odd\r
- shl di,1\r
- mov ax,[maskroutines+di] ;call the right routine\r
-\r
- mov ds,[segm]\r
- mov si,[ofs]\r
- mov di,[dest]\r
- mov cx,[height] ;scan lines to draw\r
-\r
- jmp ax ;draw it\r
-\r
-;=================\r
-;\r
-; Horizontally unwound routines to draw certain masked blocks faster\r
-;\r
-;=================\r
-\r
-MACRO MASKBYTE\r
- mov al,[es:di]\r
- and al,[si]\r
- or al,[bx+si]\r
- inc si\r
- stosb\r
-ENDM\r
-\r
-MACRO MASKWORD\r
- mov ax,[es:di]\r
- and ax,[si]\r
- or ax,[bx+si]\r
- inc si\r
- inc si\r
- stosw\r
-ENDM\r
-\r
-MACRO SPRITELOOP addr\r
- add di,dx\r
- loop addr\r
- mov ax,ss\r
- mov ds,ax\r
- ret\r
-ENDM\r
-\r
-\r
-EVEN\r
-mask2E:\r
- MASKWORD\r
- SPRITELOOP mask2E\r
-\r
-EVEN\r
-mask2O:\r
- MASKBYTE\r
- MASKBYTE\r
- SPRITELOOP mask2O\r
-\r
-EVEN\r
-mask4E:\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask4E\r
-\r
-EVEN\r
-mask4O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask4O\r
-\r
-EVEN\r
-mask6E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask6E\r
-\r
-EVEN\r
-mask6O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask6O\r
-\r
-EVEN\r
-mask8E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask8E\r
-\r
-EVEN\r
-mask8O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask8O\r
-\r
-EVEN\r
-mask10E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask10E\r
-\r
-EVEN\r
-mask10O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask10O\r
-\r
-EVEN\r
-mask12E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask12E\r
-\r
-EVEN\r
-mask12O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask12O\r
-\r
-EVEN\r
-mask14E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask14E\r
-\r
-EVEN\r
-mask14O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask14O\r
-\r
-EVEN\r
-mask16E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask16E\r
-\r
-EVEN\r
-mask16O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask16O\r
-\r
-EVEN\r
-mask18E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask18E\r
-\r
-EVEN\r
-mask18O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask18O\r
-\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_ScreenToScreen\r
-;\r
-; Basic block copy routine. Copies one block of screen memory to another,\r
-; bufferofs is NOT accounted for.\r
-;\r
-; DONE\r
-;\r
-;============================================================================\r
-\r
-PROC VW_ScreenToScreen source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_ScreenToScreen\r
-USES SI,DI\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
-\r
- mov ax,[screenseg]\r
- mov es,ax\r
- mov ds,ax\r
-\r
- mov si,[source]\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
- mov ax,[wide]\r
-;\r
-; if the width, source, and dest are all even, use word moves\r
-; This is allways the case in the CGA refresh\r
-;\r
- test ax,1\r
- jnz @@bytelineloop\r
- test si,1\r
- jnz @@bytelineloop\r
- test di,1\r
- jnz @@bytelineloop\r
-\r
- shr ax,1\r
-@@wordlineloop:\r
- mov cx,ax\r
- rep movsw\r
- add si,bx\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@wordlineloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-@@bytelineloop:\r
- mov cx,ax\r
- rep movsb\r
- add si,bx\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@bytelineloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_MemToScreen\r
-;\r
-; Basic block drawing routine. Takes a block shape at segment pointer source\r
-; of width by height data, and draws it to dest in the virtual screen,\r
-; based on linewidth. bufferofs is NOT accounted for.\r
-; There are four drawing routines to provide the best optimized code while\r
-; accounting for odd segment wrappings due to the floating screens.\r
-;\r
-; DONE\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-memtoscreentable dw eventoeven,eventoodd,oddtoeven,oddtoodd\r
-\r
-CODESEG\r
-\r
-\r
-PROC VW_MemToScreen source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_MemToScreen\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
-\r
- mov ds,[source]\r
-\r
- xor si,si ;block is segment aligned\r
-\r
- xor di,di\r
- shr [wide],1 ;change wide to words, and see if carry is set\r
- rcl di,1 ;1 if wide is odd\r
- mov ax,[dest]\r
- shr ax,1\r
- rcl di,1 ;shift a 1 in if destination is odd\r
- shl di,1 ;to index into a word width table\r
- mov dx,[height] ;scan lines to draw\r
- mov ax,[wide]\r
- jmp [ss:memtoscreentable+di] ;call the right routine\r
-\r
-;==============\r
-;\r
-; Copy an even width block to an even destination address\r
-;\r
-;==============\r
-\r
-eventoeven:\r
- mov di,[dest] ;start at same place in all planes\r
-EVEN\r
-@@lineloopEE:\r
- mov cx,ax\r
- rep movsw\r
- add di,bx\r
- dec dx\r
- jnz @@lineloopEE\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-;==============\r
-;\r
-; Copy an odd width block to an even video address\r
-;\r
-;==============\r
-\r
-oddtoeven:\r
- mov di,[dest] ;start at same place in all planes\r
-EVEN\r
-@@lineloopOE:\r
- mov cx,ax\r
- rep movsw\r
- movsb ;copy the last byte\r
- add di,bx\r
- dec dx\r
- jnz @@lineloopOE\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-;==============\r
-;\r
-; Copy an even width block to an odd video address\r
-;\r
-;==============\r
-\r
-eventoodd:\r
- mov di,[dest] ;start at same place in all planes\r
- dec ax ;one word has to be handled seperately\r
-EVEN\r
-@@lineloopEO:\r
- movsb\r
- mov cx,ax\r
- rep movsw\r
- movsb\r
- add di,bx\r
- dec dx\r
- jnz @@lineloopEO\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-;==============\r
-;\r
-; Copy an odd width block to an odd video address\r
-;\r
-;==============\r
-\r
-oddtoodd:\r
- mov di,[dest] ;start at same place in all planes\r
-EVEN\r
-@@lineloopOO:\r
- movsb\r
- mov cx,ax\r
- rep movsw\r
- add di,bx\r
- dec dx\r
- jnz @@lineloopOO\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
- ret\r
-\r
-\r
-ENDP\r
-\r
-;===========================================================================\r
-;\r
-; VW_ScreenToMem\r
-;\r
-; Copies a block of video memory to main memory, in order from planes 0-3.\r
-; This could be optimized along the lines of VW_MemToScreen to take advantage\r
-; of word copies, but this is an infrequently called routine.\r
-;\r
-; DONE\r
-;\r
-;===========================================================================\r
-\r
-PROC VW_ScreenToMem source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_ScreenToMem\r
-USES SI,DI\r
-\r
- mov es,[dest]\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
-\r
- mov ds,[screenseg]\r
-\r
- xor di,di\r
-\r
- mov si,[source]\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloop:\r
- mov cx,[wide]\r
- rep movsb\r
-\r
- add si,bx\r
-\r
- dec dx\r
- jnz @@lineloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;===========================================================================\r
-;\r
-; MISC CGA ROUTINES\r
-;\r
-;===========================================================================\r
-\r
-;==============\r
-;\r
-; VW_SetScreen\r
-;\r
-; DONE\r
-;\r
-;==============\r
-\r
-PROC VW_SetScreen crtc:WORD\r
-PUBLIC VW_SetScreen\r
-\r
-;\r
-; for some reason, my XT's EGA card doesn't like word outs to the CRTC\r
-; index...\r
-;\r
- cli\r
-\r
- mov cx,[crtc]\r
- mov dx,CRTC_INDEX\r
- mov al,0ch ;start address high register\r
- out dx,al\r
- inc dx\r
- mov al,ch\r
- out dx,al\r
- dec dx\r
- mov al,0dh ;start address low register\r
- out dx,al\r
- mov al,cl\r
- inc dx\r
- out dx,al\r
-\r
- sti\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-if NUMFONT+NUMFONTM\r
-\r
-;===========================================================================\r
-;\r
-; GENERAL FONT DRAWING ROUTINES\r
-;\r
-;===========================================================================\r
-\r
-DATASEG\r
-\r
-px dw ? ; proportional character drawing coordinates\r
-py dw ?\r
-pdrawmode db 11000b ; 8 = OR, 24 = XOR, put in GC_DATAROTATE\r
-fontcolor db 15 ;0-15 mapmask value\r
-\r
-PUBLIC px,py,pdrawmode,fontcolor\r
-\r
-;\r
-; offsets in font structure\r
-;\r
-pcharheight = 0 ;lines high\r
-charloc = 2 ;pointers to every character\r
-charwidth = 514 ;every character's width in pixels\r
-\r
-\r
-propchar dw ? ; the character number to shift\r
-stringptr dw ?,?\r
-\r
-fontcolormask dw ? ; font color expands into this\r
-\r
-BUFFWIDTH = 100\r
-BUFFHEIGHT = 32 ; must be twice as high as font for masked fonts\r
-\r
-databuffer db BUFFWIDTH*BUFFHEIGHT dup (?)\r
-\r
-bufferwidth dw ? ; bytes with valid info / line\r
-bufferheight dw ? ; number of lines currently used\r
-\r
-bufferbyte dw ?\r
-bufferbit dw ?\r
-PUBLIC bufferwidth,bufferheight,bufferbyte,bufferbit\r
-\r
-screenspot dw ? ; where the buffer is going\r
-\r
-bufferextra dw ? ; add at end of a line copy\r
-screenextra dw ?\r
-\r
-CODESEG\r
-\r
-;======================\r
-;\r
-; Macros to table shift a byte of font\r
-;\r
-;======================\r
-\r
-MACRO SHIFTNOXOR\r
- mov al,[es:bx] ; source\r
- xor ah,ah\r
- shl ax,1\r
- mov si,ax\r
- mov ax,[bp+si] ; table shift into two bytes\r
- or [di],al ; or with first byte\r
- inc di\r
- mov [di],ah ; replace next byte\r
- inc bx ; next source byte\r
-ENDM\r
-\r
-MACRO SHIFTWITHXOR\r
- mov al,[es:bx] ; source\r
- xor ah,ah\r
- shl ax,1\r
- mov si,ax\r
- mov ax,[bp+si] ; table shift into two bytes\r
- not ax\r
- and [di],al ; and with first byte\r
- inc di\r
- mov [di],ah ; replace next byte\r
- inc bx ; next source byte\r
-ENDM\r
-\r
-\r
-;=======================\r
-;\r
-; VWL_XORBuffer\r
-;\r
-; Pass buffer start in SI (somewhere in databuffer)\r
-; Draws the buffer to the screen buffer\r
-;\r
-;========================\r
-\r
-PROC VWL_XORBuffer NEAR\r
-USES BP\r
- mov bl,[fontcolor]\r
- xor bh,bh\r
- shl bx,1\r
- mov ax,[colorword+bx]\r
- mov [fontcolormask],ax\r
-\r
- mov es,[screenseg]\r
- mov di,[screenspot]\r
-\r
- mov bx,[bufferwidth] ;calculate offsets for end of each line\r
- mov [bufferwidth],bx\r
-\r
- or bx,bx\r
- jnz @@isthere\r
- ret ;nothing to draw\r
-\r
-@@isthere:\r
- test bx,1\r
- jnz @@odd\r
- jmp @@even\r
-;\r
-; clear the last byte so word draws can be used\r
-;\r
-@@odd:\r
- mov al,0\r
-line = 0\r
-REPT BUFFHEIGHT\r
- mov [BYTE databuffer+BUFFWIDTH*line+bx],al\r
-line = line+1\r
-ENDM\r
-\r
- inc bx\r
-@@even:\r
- mov ax,[linewidth]\r
- sub ax,bx\r
- mov [screenextra],ax\r
- mov ax,BUFFWIDTH\r
- sub ax,bx\r
- mov [bufferextra],ax\r
- mov dx,bx\r
- shr dx,1 ;word to copy\r
-\r
- mov bx,[bufferheight] ;lines to copy\r
- mov bp,[fontcolormask]\r
-@@lineloop:\r
- mov cx,dx\r
-@@wordloop:\r
- lodsw ;get a word from the buffer\r
- and ax,bp\r
- xor [es:di],ax ;draw it\r
- add di,2\r
- loop @@wordloop\r
-\r
- add si,[bufferextra]\r
- add di,[screenextra]\r
-\r
- dec bx\r
- jnz @@lineloop\r
-\r
- ret\r
-ENDP\r
-\r
-\r
-DATASEG\r
-\r
-;============================================================================\r
-;\r
-; NON MASKED FONT DRAWING ROUTINES\r
-;\r
-;============================================================================\r
-\r
-if numfont\r
-\r
-DATASEG\r
-\r
-shiftdrawtable dw 0,shift1wide,shift2wide,shift3wide,shift4wide\r
- dw shift5wide,shift6wide\r
-\r
-CODESEG\r
-\r
-;==================\r
-;\r
-; ShiftPropChar\r
-;\r
-; Call with BX = character number (0-255)\r
-; Draws one character to the buffer at bufferbyte/bufferbit, and adjusts\r
-; them to the new position\r
-;\r
-;==================\r
-\r
-PROC ShiftPropChar NEAR\r
-\r
- mov es,[grsegs+STARTFONT*2] ;segment of font to use\r
-\r
-;\r
-; find character location, width, and height\r
-;\r
- mov si,[es:charwidth+bx]\r
- and si,0ffh ;SI hold width in pixels\r
- shl bx,1\r
- mov bx,[es:charloc+bx] ;BX holds pointer to character data\r
-\r
-;\r
-; look up which shift table to use, based on bufferbit\r
-;\r
- mov di,[bufferbit]\r
- shl di,1\r
- mov bp,[shifttabletable+di] ;BP holds pointer to shift table\r
-\r
- mov di,OFFSET databuffer\r
- add di,[bufferbyte] ;DI holds pointer to buffer\r
-\r
- mov cx,[bufferbit]\r
- add cx,si ;add twice because pixel == two bits\r
- add cx,si ;new bit position\r
- mov ax,cx\r
- and ax,7\r
- mov [bufferbit],ax ;new bit position\r
- mov ax,cx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add [bufferbyte],ax ;new byte position\r
-\r
- add si,3\r
- shr si,1\r
- shr si,1 ;bytes the character is wide\r
- shl si,1 ;*2 to look up in shiftdrawtable\r
-\r
- mov cx,[es:pcharheight]\r
- mov dx,BUFFWIDTH\r
- jmp [ss:shiftdrawtable+si] ;procedure to draw this width\r
-\r
-;\r
-; one byte character\r
-;\r
-shift1wide:\r
- dec dx\r
-EVEN\r
-@@loop1:\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop1\r
-\r
- ret\r
-\r
-;\r
-; two byte character\r
-;\r
-shift2wide:\r
- dec dx\r
- dec dx\r
-EVEN\r
-@@loop2:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop2\r
-\r
- ret\r
-\r
-;\r
-; three byte character\r
-;\r
-shift3wide:\r
- sub dx,3\r
-EVEN\r
-@@loop3:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop3\r
-\r
- ret\r
-\r
-\r
-;\r
-; four byte character\r
-;\r
-shift4wide:\r
- sub dx,4\r
-EVEN\r
-@@loop4:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop4\r
-\r
- ret\r
-\r
-\r
-;\r
-; five byte character\r
-;\r
-shift5wide:\r
- sub dx,5\r
-EVEN\r
-@@loop5:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop5\r
-\r
- ret\r
-\r
-;\r
-; six byte character\r
-;\r
-shift6wide:\r
- sub dx,6\r
-EVEN\r
-@@loop6:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop6\r
-\r
- ret\r
-\r
-\r
-\r
-ENDP\r
-\r
-;============================================================================\r
-\r
-;==================\r
-;\r
-; VW_DrawPropString\r
-;\r
-; Draws a C string of characters at px/py and advances px\r
-;\r
-;==================\r
-\r
-CODESEG\r
-\r
-PROC VW_DrawPropString string:DWORD\r
-PUBLIC VW_DrawPropString\r
-USES SI,DI\r
-\r
-;\r
-; proportional spaceing, which clears the buffer ahead of it, so only\r
-; clear the first collumn\r
-;\r
- mov al,0\r
-line = 0\r
-REPT BUFFHEIGHT\r
- mov [BYTE databuffer+BUFFWIDTH*line],al\r
-line = line+1\r
-ENDM\r
-\r
-;\r
-; shift the characters into the buffer\r
-;\r
-@@shiftchars:\r
- mov ax,[px]\r
- and ax,3\r
- shl ax,1 ;one pixel == two bits\r
- mov [bufferbit],ax\r
- mov [bufferbyte],0\r
-\r
- mov ax,[WORD string]\r
- mov [stringptr],ax\r
- mov ax,[WORD string+2]\r
- mov [stringptr+2],ax\r
-\r
-@@shiftone:\r
- mov es,[stringptr+2]\r
- mov bx,[stringptr]\r
- inc [stringptr]\r
- mov bx,[es:bx]\r
- xor bh,bh\r
- or bl,bl\r
- jz @@allshifted\r
- call ShiftPropChar\r
- jmp @@shiftone\r
-\r
-@@allshifted:\r
-;\r
-; calculate position to draw buffer on screen\r
-;\r
- mov bx,[py]\r
- shl bx,1\r
- mov di,[ylookup+bx]\r
- add di,[bufferofs]\r
- add di,[panadjust]\r
-\r
- mov ax,[px]\r
- shr ax,1\r
- shr ax,1 ;x location in bytes\r
- add di,ax\r
- mov [screenspot],di\r
-\r
-;\r
-; advance px\r
-;\r
- mov ax,[bufferbyte]\r
- shl ax,1\r
- shl ax,1\r
- mov bx,[bufferbit]\r
- shr bx,1 ;two bits == one pixel\r
- or ax,bx\r
- add [px],ax\r
-\r
-;\r
-; draw it\r
-;\r
- mov ax,[bufferbyte]\r
- test [bufferbit],7\r
- jz @@go\r
- inc ax ;so the partial byte also gets drawn\r
-@@go:\r
- mov [bufferwidth],ax\r
- mov es,[grsegs+STARTFONT*2]\r
- mov ax,[es:pcharheight]\r
- mov [bufferheight],ax\r
-\r
- mov si,OFFSET databuffer\r
- call VWL_XORBuffer\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-endif ;numfont\r
-\r
-;============================================================================\r
-;\r
-; MASKED FONT DRAWING ROUTINES\r
-;\r
-;============================================================================\r
-\r
-if numfontm\r
-\r
-DATASEG\r
-\r
-mshiftdrawtable dw 0,mshift1wide,mshift2wide,mshift3wide\r
-\r
-\r
-CODESEG\r
-\r
-;==================\r
-;\r
-; ShiftMPropChar\r
-;\r
-; Call with BX = character number (0-255)\r
-; Draws one character to the buffer at bufferbyte/bufferbit, and adjusts\r
-; them to the new position\r
-;\r
-;==================\r
-\r
-PROC ShiftMPropChar NEAR\r
-\r
- mov es,[grsegs+STARTFONTM*2] ;segment of font to use\r
-\r
-;\r
-; find character location, width, and height\r
-;\r
- mov si,[es:charwidth+bx]\r
- and si,0ffh ;SI hold width in pixels\r
- shl bx,1\r
- mov bx,[es:charloc+bx] ;BX holds pointer to character data\r
-\r
-;\r
-; look up which shift table to use, based on bufferbit\r
-;\r
- mov di,[bufferbit]\r
- shl di,1\r
- mov bp,[shifttabletable+di] ;BP holds pointer to shift table\r
-\r
- mov di,OFFSET databuffer\r
- add di,[bufferbyte] ;DI holds pointer to buffer\r
-\r
-;\r
-; advance position by character width\r
-;\r
- mov cx,[bufferbit]\r
- add cx,si ;new bit position\r
- mov ax,cx\r
- and ax,7\r
- mov [bufferbit],ax ;new bit position\r
- mov ax,cx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add [bufferbyte],ax ;new byte position\r
-\r
- add si,7\r
- shr si,1\r
- shr si,1\r
- shr si,1 ;bytes the character is wide\r
- shl si,1 ;*2 to look up in shiftdrawtable\r
-\r
- mov cx,[es:pcharheight]\r
- mov dx,BUFFWIDTH\r
- jmp [ss:mshiftdrawtable+si] ;procedure to draw this width\r
-\r
-;\r
-; one byte character\r
-;\r
-mshift1wide:\r
- dec dx\r
-\r
-EVEN\r
-@@loop1m:\r
- SHIFTWITHXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop1m\r
-\r
- mov cx,[es:pcharheight]\r
-\r
-EVEN\r
-@@loop1:\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop1\r
-\r
- ret\r
-\r
-;\r
-; two byte character\r
-;\r
-mshift2wide:\r
- dec dx\r
- dec dx\r
-EVEN\r
-@@loop2m:\r
- SHIFTWITHXOR\r
- SHIFTWITHXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop2m\r
-\r
- mov cx,[es:pcharheight]\r
-\r
-EVEN\r
-@@loop2:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop2\r
-\r
- ret\r
-\r
-;\r
-; three byte character\r
-;\r
-mshift3wide:\r
- sub dx,3\r
-EVEN\r
-@@loop3m:\r
- SHIFTWITHXOR\r
- SHIFTWITHXOR\r
- SHIFTWITHXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop3m\r
-\r
- mov cx,[es:pcharheight]\r
-\r
-EVEN\r
-@@loop3:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop3\r
-\r
- ret\r
-\r
-\r
-ENDP\r
-\r
-;============================================================================\r
-\r
-;==================\r
-;\r
-; VW_DrawMPropString\r
-;\r
-; Draws a C string of characters at px/py and advances px\r
-;\r
-;==================\r
-\r
-\r
-\r
-PROC VW_DrawMPropString string:DWORD\r
-PUBLIC VW_DrawMPropString\r
-USES SI,DI\r
-\r
-;\r
-; clear out the first byte of the buffer, the rest will automatically be\r
-; cleared as characters are drawn into it\r
-;\r
- mov es,[grsegs+STARTFONTM*2]\r
- mov dx,[es:pcharheight]\r
- mov di,OFFSET databuffer\r
- mov ax,ds\r
- mov es,ax\r
- mov bx,BUFFWIDTH-1\r
-\r
- mov cx,dx\r
- mov al,0ffh\r
-@@maskfill:\r
- stosb ; fill the mask part with $ff\r
- add di,bx\r
- loop @@maskfill\r
-\r
- mov cx,dx\r
- xor al,al\r
-@@datafill:\r
- stosb ; fill the data part with $0\r
- add di,bx\r
- loop @@datafill\r
-\r
-;\r
-; shift the characters into the buffer\r
-;\r
- mov ax,[px]\r
- and ax,7\r
- mov [bufferbit],ax\r
- mov [bufferbyte],0\r
-\r
- mov ax,[WORD string]\r
- mov [stringptr],ax\r
- mov ax,[WORD string+2]\r
- mov [stringptr+2],ax\r
-\r
-@@shiftone:\r
- mov es,[stringptr+2]\r
- mov bx,[stringptr]\r
- inc [stringptr]\r
- mov bx,[es:bx]\r
- xor bh,bh\r
- or bl,bl\r
- jz @@allshifted\r
- call ShiftMPropChar\r
- jmp @@shiftone\r
-\r
-@@allshifted:\r
-;\r
-; calculate position to draw buffer on screen\r
-;\r
- mov bx,[py]\r
- shl bx,1\r
- mov di,[ylookup+bx]\r
- add di,[bufferofs]\r
-\r
- mov ax,[px]\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1 ;x location in bytes\r
- add di,ax\r
- mov [screenspot],di\r
-\r
-;\r
-; advance px\r
-;\r
- mov ax,[bufferbyte]\r
- shl ax,1\r
- shl ax,1\r
- shl ax,1\r
- or ax,[bufferbit]\r
- add [px],ax\r
-\r
-;\r
-; draw it\r
-;\r
- mov ax,[bufferbyte]\r
- test [bufferbit],7\r
- jz @@go\r
- inc ax ;so the partial byte also gets drawn\r
-@@go:\r
- mov [bufferwidth],ax\r
- mov es,[grsegs+STARTFONTM*2]\r
- mov ax,[es:pcharheight]\r
- mov [bufferheight],ax\r
-\r
- mov si,OFFSET databuffer\r
- call BufferToScreen ; cut out mask\r
- ; or in data\r
- call BufferToScreen ; SI is still in the right position in buffer\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-endif ; if numfontm\r
-\r
-endif ; if fonts\r
+++ /dev/null
-; Catacomb Armageddon Source Code\r
-; Copyright (C) 1993-2014 Flat Rock Software\r
-;\r
-; This program is free software; you can redistribute it and/or modify\r
-; it under the terms of the GNU General Public License as published by\r
-; the Free Software Foundation; either version 2 of the License, or\r
-; (at your option) any later version.\r
-;\r
-; This program is distributed in the hope that it will be useful,\r
-; but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-; GNU General Public License for more details.\r
-;\r
-; You should have received a copy of the GNU General Public License along\r
-; with this program; if not, write to the Free Software Foundation, Inc.,\r
-; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-\r
-;=================================\r
-;\r
-; EGA view manager routines\r
-;\r
-;=================================\r
-\r
-;============================================================================\r
-;\r
-; All EGA drawing routines that write out words need to have alternate forms\r
-; for starting on even and odd addresses, because writing a word at segment\r
-; offset 0xffff causes an exception! To work around this, write a single\r
-; byte out to make the address even, so it wraps cleanly at the end.\r
-;\r
-; All of these routines assume read/write mode 0, and will allways return\r
-; in that state.\r
-; The direction flag should be clear\r
-; readmap/writemask is left in an undefined state\r
-;\r
-;============================================================================\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_Plot (int x,y,color)\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-plotpixels db 128,64,32,16,8,4,2,1\r
-\r
-CODESEG\r
-\r
-PROC VW_Plot x:WORD, y:WORD, color:WORD\r
-PUBLIC VW_Plot\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
-\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+2*256 ;write mode 2\r
- WORDOUT\r
-\r
- mov di,[bufferofs]\r
- mov bx,[y]\r
- shl bx,1\r
- add di,[ylookup+bx]\r
- mov bx,[x]\r
- mov ax,bx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add di,ax ; di = byte on screen\r
-\r
- and bx,7\r
- mov ah,[plotpixels+bx]\r
- mov al,GC_BITMASK ;mask off other pixels\r
- WORDOUT\r
-\r
- mov bl,[BYTE color]\r
- xchg bl,[es:di] ; load latches and write pixel\r
-\r
- mov dx,GC_INDEX\r
- mov ah,0ffh ;no bit mask\r
- WORDOUT\r
- mov ax,GC_MODE+0*256 ;write mode 0\r
- WORDOUT\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_Vlin (int yl,yh,x,color)\r
-;\r
-;============================================================================\r
-\r
-PROC VW_Vlin yl:WORD, yh:WORD, x:WORD, color:WORD\r
-PUBLIC VW_Vlin\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
-\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+2*256 ;write mode 2\r
- WORDOUT\r
-\r
- mov di,[bufferofs]\r
- mov bx,[yl]\r
- shl bx,1\r
- add di,[ylookup+bx]\r
- mov bx,[x]\r
- mov ax,bx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add di,ax ; di = byte on screen\r
-\r
- and bx,7\r
- mov ah,[plotpixels+bx]\r
- mov al,GC_BITMASK ;mask off other pixels\r
- WORDOUT\r
-\r
- mov cx,[yh]\r
- sub cx,[yl]\r
- inc cx ;number of pixels to plot\r
-\r
- mov bh,[BYTE color]\r
- mov dx,[linewidth]\r
-\r
-@@plot:\r
- mov bl,bh\r
- xchg bl,[es:di] ; load latches and write pixel\r
- add di,dx\r
-\r
- loop @@plot\r
-\r
- mov dx,GC_INDEX\r
- mov ah,0ffh ;no bit mask\r
- WORDOUT\r
- mov ax,GC_MODE+0*256 ;write mode 0\r
- WORDOUT\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-\r
-\r
-;===================\r
-;\r
-; VW_DrawTile8\r
-;\r
-; xcoord in bytes (8 pixels), ycoord in pixels\r
-; All Tile8s are in one grseg, so an offset is calculated inside it\r
-;\r
-;===================\r
-\r
-PROC VW_DrawTile8 xcoord:WORD, ycoord:WORD, tile:WORD\r
-PUBLIC VW_DrawTile8\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov di,[bufferofs]\r
- add di,[xcoord]\r
- mov bx,[ycoord]\r
- shl bx,1\r
- add di,[ylookup+bx]\r
- mov [ss:screendest],di ;screen destination\r
-\r
- mov bx,[linewidth]\r
- dec bx\r
-\r
- mov si,[tile]\r
- shl si,1\r
- shl si,1\r
- shl si,1\r
- shl si,1\r
- shl si,1\r
-\r
- mov ds,[grsegs+STARTTILE8*2] ; segment for all tile8s\r
-\r
- mov cx,4 ;planes to draw\r
- mov ah,0001b ;map mask\r
-\r
- mov dx,SC_INDEX\r
- mov al,SC_MAPMASK\r
-\r
-;\r
-; start drawing\r
-;\r
-\r
-@@planeloop:\r
- WORDOUT\r
- shl ah,1 ;shift plane mask over for next plane\r
-\r
- mov di,[ss:screendest] ;start at same place in all planes\r
-\r
-REPT 7\r
- movsb\r
- add di,bx\r
-ENDM\r
- movsb\r
-\r
- loop @@planeloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_MaskBlock\r
-;\r
-; Draws a masked block shape to the screen. bufferofs is NOT accounted for.\r
-; The mask comes first, then four planes of data.\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-UNWOUNDMASKS = 10\r
-\r
-\r
-maskroutines dw mask0,mask0,mask1E,mask1E,mask2E,mask2O,mask3E,mask3O\r
- dw mask4E,mask4O,mask5E,mask5O,mask6E,mask6O\r
- dw mask7E,mask7O,mask8E,mask8O,mask9E,mask9O\r
- dw mask10E,mask10O\r
-\r
-\r
-routinetouse dw ?\r
-\r
-CODESEG\r
-\r
-PROC VW_MaskBlock segm:WORD, ofs:WORD, dest:WORD, wide:WORD, height:WORD, planesize:WORD\r
-PUBLIC VW_MaskBlock\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov [BYTE planemask],1\r
- mov [BYTE planenum],0\r
-\r
- mov di,[wide]\r
- mov dx,[linewidth]\r
- sub dx,[wide]\r
- mov [linedelta],dx ;amount to add after drawing each line\r
-\r
- mov bx,[planesize] ; si+bx = data location\r
-\r
- cmp di,UNWOUNDMASKS\r
- jbe @@unwoundroutine\r
- mov [routinetouse],OFFSET generalmask\r
- jmp NEAR @@startloop\r
-\r
-;=================\r
-;\r
-; use the unwound routines\r
-;\r
-;=================\r
-\r
-@@unwoundroutine:\r
- mov cx,[dest]\r
- shr cx,1\r
- rcl di,1 ;shift a 1 in if destination is odd\r
- shl di,1 ;to index into a word width table\r
- mov ax,[maskroutines+di] ;call the right routine\r
- mov [routinetouse],ax\r
-\r
-@@startloop:\r
- mov ds,[segm]\r
-\r
-@@drawplane:\r
- mov dx,SC_INDEX\r
- mov al,SC_MAPMASK\r
- mov ah,[ss:planemask]\r
- WORDOUT\r
- mov dx,GC_INDEX\r
- mov al,GC_READMAP\r
- mov ah,[ss:planenum]\r
- WORDOUT\r
-\r
- mov si,[ofs] ;start back at the top of the mask\r
- mov di,[dest] ;start at same place in all planes\r
- mov cx,[height] ;scan lines to draw\r
- mov dx,[ss:linedelta]\r
-\r
- jmp [ss:routinetouse] ;draw one plane\r
-planereturn: ;routine jmps back here\r
-\r
- add bx,[ss:planesize] ;start of mask = start of next plane\r
-\r
- inc [ss:planenum]\r
- shl [ss:planemask],1 ;shift plane mask over for next plane\r
- cmp [ss:planemask],10000b ;done all four planes?\r
- jne @@drawplane\r
-\r
-mask0:\r
- mov ax,ss\r
- mov ds,ax\r
- ret ;width of 0 = no drawing\r
-\r
-;==============\r
-;\r
-; General purpose masked block drawing. This could be optimised into\r
-; four routines to use words, but few play loop sprites should be this big!\r
-;\r
-;==============\r
-\r
-generalmask:\r
- mov dx,cx\r
-\r
-@@lineloopgen:\r
- mov cx,[wide]\r
-@@byteloop:\r
- mov al,[es:di]\r
- and al,[si]\r
- or al,[bx+si]\r
- inc si\r
- stosb\r
- loop @@byteloop\r
-\r
- add di,[ss:linedelta]\r
- dec dx\r
- jnz @@lineloopgen\r
- jmp planereturn\r
-\r
-;=================\r
-;\r
-; Horizontally unwound routines to draw certain masked blocks faster\r
-;\r
-;=================\r
-\r
-MACRO MASKBYTE\r
- mov al,[es:di]\r
- and al,[si]\r
- or al,[bx+si]\r
- inc si\r
- stosb\r
-ENDM\r
-\r
-MACRO MASKWORD\r
- mov ax,[es:di]\r
- and ax,[si]\r
- or ax,[bx+si]\r
- inc si\r
- inc si\r
- stosw\r
-ENDM\r
-\r
-MACRO SPRITELOOP addr\r
- add di,dx\r
- loop addr\r
- jmp planereturn\r
-ENDM\r
-\r
-\r
-EVEN\r
-mask1E:\r
- MASKBYTE\r
- SPRITELOOP mask1E\r
-\r
-EVEN\r
-mask2E:\r
- MASKWORD\r
- SPRITELOOP mask2E\r
-\r
-EVEN\r
-mask2O:\r
- MASKBYTE\r
- MASKBYTE\r
- SPRITELOOP mask2O\r
-\r
-EVEN\r
-mask3E:\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask3E\r
-\r
-EVEN\r
-mask3O:\r
- MASKBYTE\r
- MASKWORD\r
- SPRITELOOP mask3O\r
-\r
-EVEN\r
-mask4E:\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask4E\r
-\r
-EVEN\r
-mask4O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask4O\r
-\r
-EVEN\r
-mask5E:\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask5E\r
-\r
-EVEN\r
-mask5O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask5O\r
-\r
-EVEN\r
-mask6E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask6E\r
-\r
-EVEN\r
-mask6O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask6O\r
-\r
-EVEN\r
-mask7E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask7E\r
-\r
-EVEN\r
-mask7O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask7O\r
-\r
-EVEN\r
-mask8E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask8E\r
-\r
-EVEN\r
-mask8O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask8O\r
-\r
-EVEN\r
-mask9E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask9E\r
-\r
-EVEN\r
-mask9O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask9O\r
-\r
-EVEN\r
-mask10E:\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- SPRITELOOP mask10E\r
-\r
-EVEN\r
-mask10O:\r
- MASKBYTE\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKWORD\r
- MASKBYTE\r
- SPRITELOOP mask10O\r
-\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_ScreenToScreen\r
-;\r
-; Basic block copy routine. Copies one block of screen memory to another,\r
-; using write mode 1 (sets it and returns with write mode 0). bufferofs is\r
-; NOT accounted for.\r
-;\r
-;============================================================================\r
-\r
-PROC VW_ScreenToScreen source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_ScreenToScreen\r
-USES SI,DI\r
-\r
- pushf\r
- cli\r
-\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+1*256\r
- WORDOUT\r
-\r
- popf\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
-\r
- mov ax,[screenseg]\r
- mov es,ax\r
- mov ds,ax\r
-\r
- mov si,[source]\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
- mov ax,[wide]\r
-\r
-@@lineloop:\r
- mov cx,ax\r
- rep movsb\r
- add si,bx\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloop\r
-\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+0*256\r
- WORDOUT\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_MemToScreen\r
-;\r
-; Basic block drawing routine. Takes a block shape at segment pointer source\r
-; with four planes of width by height data, and draws it to dest in the\r
-; virtual screen, based on linewidth. bufferofs is NOT accounted for.\r
-; There are four drawing routines to provide the best optimized code while\r
-; accounting for odd segment wrappings due to the floating screens.\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-memtoscreentable dw eventoeven,eventoodd,oddtoeven,oddtoodd\r
-\r
-CODESEG\r
-\r
-\r
-PROC VW_MemToScreen source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_MemToScreen\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
-\r
- mov ds,[source]\r
-\r
-\r
- xor si,si ;block is segment aligned\r
-\r
- xor di,di\r
- shr [wide],1 ;change wide to words, and see if carry is set\r
- rcl di,1 ;1 if wide is odd\r
- mov ax,[dest]\r
- shr ax,1\r
- rcl di,1 ;shift a 1 in if destination is odd\r
- shl di,1 ;to index into a word width table\r
- mov ax,SC_MAPMASK+0001b*256 ;map mask for plane 0\r
- jmp [ss:memtoscreentable+di] ;call the right routine\r
-\r
-;==============\r
-;\r
-; Copy an even width block to an even video address\r
-;\r
-;==============\r
-\r
-eventoeven:\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloopEE:\r
- mov cx,[wide]\r
- rep movsw\r
-\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloopEE\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b ;done all four planes?\r
- jne eventoeven\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-;==============\r
-;\r
-; Copy an odd width block to an even video address\r
-;\r
-;==============\r
-\r
-oddtoeven:\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloopOE:\r
- mov cx,[wide]\r
- rep movsw\r
- movsb ;copy the last byte\r
-\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloopOE\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b ;done all four planes?\r
- jne oddtoeven\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-;==============\r
-;\r
-; Copy an even width block to an odd video address\r
-;\r
-;==============\r
-\r
-eventoodd:\r
- dec [wide] ;one word has to be handled seperately\r
-EOplaneloop:\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloopEO:\r
- movsb\r
- mov cx,[wide]\r
- rep movsw\r
- movsb\r
-\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloopEO\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b ;done all four planes?\r
- jne EOplaneloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-;==============\r
-;\r
-; Copy an odd width block to an odd video address\r
-;\r
-;==============\r
-\r
-oddtoodd:\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloopOO:\r
- movsb\r
- mov cx,[wide]\r
- rep movsw\r
-\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@lineloopOO\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b ;done all four planes?\r
- jne oddtoodd\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-\r
-ENDP\r
-\r
-; MDM (GAMERS EDGE) begin\r
-\r
-\r
-MACRO XPAND_BYTE\r
- test al,128 ; handle bit 7\r
- jne @@over7\r
- or [BYTE PTR es:di],11000000b\r
-@@over7:\r
-\r
- test al,64 ; handle bit 6\r
- jne @@over6\r
- or [BYTE PTR es:di],00110000b\r
-@@over6:\r
-\r
- test al,32 ; handle bit 5\r
- jne @@over5\r
- or [BYTE PTR es:di],00001100b\r
-@@over5:\r
-\r
- test al,16 ; handle bit 4\r
- jne @@over4\r
- or [BYTE PTR es:di],00000011b\r
-@@over4:\r
-\r
- inc di ; inc destination\r
-\r
- test al,8 ; handle bit 3\r
- jne @@over3\r
- or [BYTE PTR es:di],11000000b\r
-@@over3:\r
-\r
- test al,4 ; handle bit 2\r
- jne @@over2\r
- or [BYTE PTR es:di],00110000b\r
-@@over2:\r
-\r
- test al,2 ; handle bit 1\r
- jne @@over1\r
- or [BYTE PTR es:di],00001100b\r
-@@over1:\r
-\r
- test al,1 ; handle bit 0\r
- jne @@over0\r
- or [BYTE PTR es:di],00000011b\r
-@@over0:\r
-\r
- inc si ; inc source\r
- inc di ; inc destination\r
-ENDM\r
-\r
-\r
-;============================================================================\r
-;\r
-; VW_MemToScreen2x\r
-;\r
-; Basic block drawing routine. Takes a block shape at segment pointer source\r
-; with four planes of width by height data, and draws it to dest in the\r
-; virtual screen, based on linewidth. bufferofs is NOT accounted for.\r
-; There are four drawing routines to provide the best optimized code while\r
-; accounting for odd segment wrappings due to the floating screens.\r
-;\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-xpandhorz db 00000000b,00000011b,00001100b,00001111b\r
- db 00110000b,00110011b,00111100b,00111111b\r
- db 11000000b,11000011b,11001100b,11001111b\r
- db 11110000b,11110011b,11111100b,11111111b\r
-\r
-CODESEG\r
-\r
-\r
-PROC VW_MemToScreen2x source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_MemToScreen2x\r
-USES SI,DI\r
-\r
- mov es,[screenseg]\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
- sub bx,[wide]\r
-\r
- mov ds,[source]\r
-\r
-\r
- xor si,si ;block is segment aligned\r
-\r
- mov ah,0001b ;map mask for plane 0\r
-\r
-@@depthloop:\r
- mov al,SC_MAPMASK ;restore map mask in al\r
- mov dx,SC_INDEX\r
- WORDOUT\r
-\r
- mov di,[dest] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@heightloop:\r
- mov cx,[wide]\r
-@@widthloop:\r
-\r
-; handle first nybble\r
-;\r
- push di\r
- mov di,[si]\r
- shr di,1\r
- shr di,1\r
- shr di,1\r
- shr di,1\r
- and di,15\r
- mov al,[ss:xpandhorz+di]\r
- pop di\r
- mov [es:di],al\r
- inc di\r
-\r
-; handle second nybble\r
-;\r
- push di\r
- mov di,[si]\r
- and di,15\r
- mov al,[ss:xpandhorz+di]\r
- pop di\r
- mov [es:di],al\r
- inc si\r
- inc di\r
-\r
-\r
- dec cx\r
- jne @@widthloop\r
-\r
- add di,bx\r
-\r
- dec dx\r
- jnz @@heightloop\r
-\r
- shl ah,1 ;shift plane mask over for next plane\r
- cmp ah,10000b ;done all four planes?\r
- jne @@depthloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-; MDM (GAMERS EDGE) end\r
-\r
-;===========================================================================\r
-;\r
-; VW_ScreenToMem\r
-;\r
-; Copies a block of video memory to main memory, in order from planes 0-3.\r
-; This could be optimized along the lines of VW_MemToScreen to take advantage\r
-; of word copies, but this is an infrequently called routine.\r
-;\r
-;===========================================================================\r
-\r
-PROC VW_ScreenToMem source:WORD, dest:WORD, wide:WORD, height:WORD\r
-PUBLIC VW_ScreenToMem\r
-USES SI,DI\r
-\r
- mov es,[dest]\r
-\r
- mov bx,[linewidth]\r
- sub bx,[wide]\r
-\r
- mov ds,[screenseg]\r
-\r
- mov ax,GC_READMAP ;read map for plane 0\r
-\r
- xor di,di\r
-\r
-@@planeloop:\r
- mov dx,GC_INDEX\r
- WORDOUT\r
-\r
- mov si,[source] ;start at same place in all planes\r
- mov dx,[height] ;scan lines to draw\r
-\r
-@@lineloop:\r
- mov cx,[wide]\r
- rep movsb\r
-\r
- add si,bx\r
-\r
- dec dx\r
- jnz @@lineloop\r
-\r
- inc ah\r
- cmp ah,4 ;done all four planes?\r
- jne @@planeloop\r
-\r
- mov ax,ss\r
- mov ds,ax ;restore turbo's data segment\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; VWL_UpdateScreenBlocks\r
-;\r
-; Scans through the update matrix and copies any areas that have changed\r
-; to the visable screen, then zeros the update array\r
-;\r
-;============================================================================\r
-\r
-\r
-\r
-; AX 0/1 for scasb, temp for segment register transfers\r
-; BX width for block copies\r
-; CX REP counter\r
-; DX line width deltas\r
-; SI source for copies\r
-; DI scas dest / movsb dest\r
-; BP pointer to end of bufferblocks\r
-\r
-PROC VWL_UpdateScreenBlocks\r
-PUBLIC VWL_UpdateScreenBlocks\r
-USES SI,DI,BP\r
-\r
- jmp SHORT @@realstart\r
-@@done:\r
-;\r
-; all tiles have been scanned\r
-;\r
- mov dx,GC_INDEX ; restore write mode 0\r
- mov ax,GC_MODE+0*256\r
- WORDOUT\r
-\r
- xor ax,ax ; clear out the update matrix\r
- mov cx,UPDATEWIDE*UPDATEHIGH/2\r
-\r
- mov di,[updateptr]\r
- rep stosw\r
-\r
- ret\r
-\r
-@@realstart:\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK+15*256\r
- WORDOUT\r
- mov dx,GC_INDEX\r
- mov ax,GC_MODE+1*256\r
- WORDOUT\r
-\r
- mov di,[updateptr] ; start of floating update screen\r
- mov bp,di\r
- add bp,UPDATEWIDE*UPDATEHIGH+1 ; when di = bp, all tiles have been scanned\r
-\r
- push di\r
- mov cx,-1 ; definately scan the entire thing\r
-\r
-;\r
-; scan for a 1 in the update list, meaning a tile needs to be copied\r
-; from the master screen to the current screen\r
-;\r
-@@findtile:\r
- pop di ; place to continue scaning from\r
- mov ax,ss\r
- mov es,ax ; search in the data segment\r
- mov ds,ax\r
- mov al,1\r
- repne scasb\r
- cmp di,bp\r
- jae @@done\r
-\r
- cmp [BYTE di],al\r
- jne @@singletile\r
- jmp @@tileblock\r
-\r
-;============\r
-;\r
-; copy a single tile\r
-;\r
-;============\r
-@@singletile:\r
- inc di ; we know the next tile is nothing\r
- push di ; save off the spot being scanned\r
- sub di,[updateptr]\r
- shl di,1\r
- mov di,[blockstarts-4+di] ; start of tile location on screen\r
- mov si,di\r
- add si,[bufferofs]\r
- add di,[displayofs]\r
-\r
- mov dx,[linewidth]\r
- sub dx,2\r
- mov ax,[screenseg]\r
- mov ds,ax\r
- mov es,ax\r
-\r
-REPT 15\r
- movsb\r
- movsb\r
- add si,dx\r
- add di,dx\r
-ENDM\r
- movsb\r
- movsb\r
-\r
- jmp @@findtile\r
-\r
-;============\r
-;\r
-; more than one tile in a row needs to be updated, so do it as a group\r
-;\r
-;============\r
-EVEN\r
-@@tileblock:\r
- mov dx,di ; hold starting position + 1 in dx\r
- inc di ; we know the next tile also gets updated\r
- repe scasb ; see how many more in a row\r
- push di ; save off the spot being scanned\r
-\r
- mov bx,di\r
- sub bx,dx ; number of tiles in a row\r
- shl bx,1 ; number of bytes / row\r
-\r
- mov di,dx ; lookup position of start tile\r
- sub di,[updateptr]\r
- shl di,1\r
- mov di,[blockstarts-2+di] ; start of tile location\r
- mov si,di\r
- add si,[bufferofs]\r
- add di,[displayofs]\r
-\r
- mov dx,[linewidth]\r
- sub dx,bx ; offset to next line on screen\r
-\r
- mov ax,[screenseg]\r
- mov ds,ax\r
- mov es,ax\r
-\r
-REPT 15\r
- mov cx,bx\r
- rep movsb\r
- add si,dx\r
- add di,dx\r
-ENDM\r
- mov cx,bx\r
- rep movsb\r
-\r
- dec cx ; was 0 from last rep movsb, now $ffff for scasb\r
- jmp @@findtile\r
-\r
-ENDP\r
-\r
-\r
-;===========================================================================\r
-;\r
-; MISC EGA ROUTINES\r
-;\r
-;===========================================================================\r
-\r
-;==============\r
-;\r
-; VW_SetScreen\r
-;\r
-;==============\r
-\r
-PROC VW_SetScreen crtc:WORD, pel:WORD\r
-PUBLIC VW_SetScreen\r
-\r
-if waitforvbl\r
-\r
- mov dx,STATUS_REGISTER_1\r
-\r
-;\r
-; wait util the CRTC just starts scaning a diplayed line to set the CRTC start\r
-;\r
- cli\r
-\r
-@@waitnodisplay:\r
- in al,dx\r
- test al,1\r
- jz @@waitnodisplay\r
-\r
-; the display is now disabled (in a HBL / VBL)\r
-\r
-@@waitdisplay:\r
- in al,dx\r
- test al,1 ;1 = display is disabled (HBL / VBL)\r
- jnz @@waitdisplay\r
-\r
-; the display was just enabled, so a full scan line is available for CRTC set\r
-\r
-endif\r
-\r
-;\r
-; set CRTC start\r
-;\r
-; for some reason, my XT's EGA card doesn't like word outs to the CRTC\r
-; index...\r
-;\r
- mov cx,[crtc]\r
- mov dx,CRTC_INDEX\r
- mov al,0ch ;start address high register\r
- out dx,al\r
- inc dx\r
- mov al,ch\r
- out dx,al\r
- dec dx\r
- mov al,0dh ;start address low register\r
- out dx,al\r
- mov al,cl\r
- inc dx\r
- out dx,al\r
-\r
-if waitforvbl\r
-\r
-;\r
-; wait for a vertical retrace to set pel panning\r
-;\r
- mov dx,STATUS_REGISTER_1\r
-@@waitvbl:\r
- sti ;service interrupts\r
- jmp $+2\r
- cli\r
- in al,dx\r
- test al,00001000b ;look for vertical retrace\r
- jz @@waitvbl\r
-\r
-endif\r
-\r
-;\r
-; set horizontal panning\r
-;\r
-\r
- mov dx,ATR_INDEX\r
- mov al,ATR_PELPAN or 20h\r
- out dx,al\r
- jmp $+2\r
- mov al,[BYTE pel] ;pel pan value\r
- out dx,al\r
-\r
- sti\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-\r
-if NUMFONT+NUMFONTM\r
-\r
-;===========================================================================\r
-;\r
-; GENERAL FONT DRAWING ROUTINES\r
-;\r
-;===========================================================================\r
-\r
-DATASEG\r
-\r
-px dw ? ; proportional character drawing coordinates\r
-py dw ?\r
-pdrawmode db 11000b ; 8 = OR, 24 = XOR, put in GC_DATAROTATE\r
-fontcolor db 15 ;0-15 mapmask value\r
-\r
-PUBLIC px,py,pdrawmode,fontcolor\r
-\r
-;\r
-; offsets in font structure\r
-;\r
-pcharheight = 0 ;lines high\r
-charloc = 2 ;pointers to every character\r
-charwidth = 514 ;every character's width in pixels\r
-\r
-\r
-propchar dw ? ; the character number to shift\r
-stringptr dw ?,?\r
-\r
-\r
-BUFFWIDTH = 82 ; MDM (GAMERS EDGE) - increased from 50\r
-BUFFHEIGHT = 20 ; must be twice as high as font for masked fonts\r
-\r
-databuffer db BUFFWIDTH*BUFFHEIGHT dup (?)\r
-\r
-bufferwidth dw ? ; bytes with valid info / line\r
-bufferheight dw ? ; number of lines currently used\r
-\r
-bufferbyte dw ?\r
-bufferbit dw ?\r
-\r
-screenspot dw ? ; where the buffer is going\r
-\r
-bufferextra dw ? ; add at end of a line copy\r
-screenextra dw ?\r
-\r
-PUBLIC bufferwidth,bufferheight,screenspot\r
-\r
-CODESEG\r
-\r
-;======================\r
-;\r
-; Macros to table shift a byte of font\r
-;\r
-;======================\r
-\r
-MACRO SHIFTNOXOR\r
- mov al,[es:bx] ; source\r
- xor ah,ah\r
- shl ax,1\r
- mov si,ax\r
- mov ax,[bp+si] ; table shift into two bytes\r
- or [di],al ; or with first byte\r
- inc di\r
- mov [di],ah ; replace next byte\r
- inc bx ; next source byte\r
-ENDM\r
-\r
-MACRO SHIFTWITHXOR\r
- mov al,[es:bx] ; source\r
- xor ah,ah\r
- shl ax,1\r
- mov si,ax\r
- mov ax,[bp+si] ; table shift into two bytes\r
- not ax\r
- and [di],al ; and with first byte\r
- inc di\r
- mov [di],ah ; replace next byte\r
- inc bx ; next source byte\r
-ENDM\r
-\r
-\r
-;=======================\r
-;\r
-; BufferToScreen\r
-;\r
-; Pass buffer start in SI (somewhere in databuffer)\r
-; Draws the buffer to the EGA screen in the current write mode\r
-;\r
-;========================\r
-\r
-PROC BufferToScreen NEAR\r
-\r
- mov es,[screenseg]\r
- mov di,[screenspot]\r
-\r
- mov bx,[bufferwidth] ;calculate offsets for end of each line\r
- or bx,bx\r
- jnz @@isthere\r
- ret ;nothing to draw\r
-\r
-@@isthere:\r
- mov ax,[linewidth]\r
- sub ax,bx\r
- mov [screenextra],ax\r
- mov ax,BUFFWIDTH\r
- sub ax,bx\r
- mov [bufferextra],ax\r
-\r
- mov bx,[bufferheight] ;lines to copy\r
-@@lineloop:\r
- mov cx,[bufferwidth] ;bytes to copy\r
-@@byteloop:\r
- lodsb ;get a byte from the buffer\r
- xchg [es:di],al ;load latches and store back to screen\r
- inc di\r
-\r
- loop @@byteloop\r
-\r
- add si,[bufferextra]\r
- add di,[screenextra]\r
-\r
- dec bx\r
- jnz @@lineloop\r
-\r
- ret\r
-ENDP\r
-\r
-\r
-;============================================================================\r
-;\r
-; NON MASKED FONT DRAWING ROUTINES\r
-;\r
-;============================================================================\r
-\r
-if numfont\r
-\r
-DATASEG\r
-\r
-shiftdrawtable dw 0,shift1wide,shift2wide,shift3wide,shift4wide\r
- dw shift5wide\r
-\r
-CODESEG\r
-\r
-;==================\r
-;\r
-; ShiftPropChar\r
-;\r
-; Call with BX = character number (0-255)\r
-; Draws one character to the buffer at bufferbyte/bufferbit, and adjusts\r
-; them to the new position\r
-;\r
-;==================\r
-\r
-PROC ShiftPropChar NEAR\r
-\r
- mov si,[fontnumber]\r
- shl si,1\r
- mov es,[grsegs+STARTFONT*2+si] ;segment of font to use\r
-\r
-;\r
-; find character location, width, and height\r
-;\r
- mov si,[es:charwidth+bx]\r
- and si,0ffh ;SI hold width in pixels\r
- shl bx,1\r
- mov bx,[es:charloc+bx] ;BX holds pointer to character data\r
-\r
-;\r
-; look up which shift table to use, based on bufferbit\r
-;\r
- mov di,[bufferbit]\r
- shl di,1\r
- mov bp,[shifttabletable+di] ;BP holds pointer to shift table\r
-\r
- mov di,OFFSET databuffer\r
- add di,[bufferbyte] ;DI holds pointer to buffer\r
-\r
-;\r
-; advance position by character width\r
-;\r
- mov cx,[bufferbit]\r
- add cx,si ;new bit position\r
- mov ax,cx\r
- and ax,7\r
- mov [bufferbit],ax ;new bit position\r
- mov ax,cx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add [bufferbyte],ax ;new byte position\r
-\r
- add si,7\r
- shr si,1\r
- shr si,1\r
- shr si,1 ;bytes the character is wide\r
- shl si,1 ;*2 to look up in shiftdrawtable\r
-\r
- mov cx,[es:pcharheight]\r
- mov dx,BUFFWIDTH\r
- jmp [ss:shiftdrawtable+si] ;procedure to draw this width\r
-\r
-;\r
-; one byte character\r
-;\r
-shift1wide:\r
- dec dx\r
-EVEN\r
-@@loop1:\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop1\r
- ret\r
-\r
-;\r
-; two byte character\r
-;\r
-shift2wide:\r
- dec dx\r
- dec dx\r
-EVEN\r
-@@loop2:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop2\r
- ret\r
-\r
-;\r
-; three byte character\r
-;\r
-shift3wide:\r
- sub dx,3\r
-EVEN\r
-@@loop3:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop3\r
- ret\r
-\r
-;\r
-; four byte character\r
-;\r
-shift4wide:\r
- sub dx,4\r
-EVEN\r
-@@loop4:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop4\r
- ret\r
-\r
-;\r
-; five byte character\r
-;\r
-shift5wide:\r
- sub dx,5\r
-EVEN\r
-@@loop5:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop5\r
- ret\r
-\r
-\r
-\r
-ENDP\r
-\r
-;============================================================================\r
-\r
-;==================\r
-;\r
-; VW_DrawPropString\r
-;\r
-; Draws a C string of characters at px/py and advances px\r
-;\r
-; Assumes write mode 0\r
-;\r
-;==================\r
-\r
-CODESEG\r
-\r
-PROC VW_DrawPropString string:DWORD\r
-PUBLIC VW_DrawPropString\r
-USES SI,DI\r
-\r
-;\r
-; proportional spaceing, which clears the buffer ahead of it, so only\r
-; clear the first collumn\r
-;\r
- mov al,0\r
-line = 0\r
-REPT BUFFHEIGHT\r
- mov [BYTE databuffer+BUFFWIDTH*line],al\r
-line = line+1\r
-ENDM\r
-\r
-;\r
-; shift the characters into the buffer\r
-;\r
-@@shiftchars:\r
- mov ax,[px]\r
- and ax,7\r
- mov [bufferbit],ax\r
- mov [bufferbyte],0\r
-\r
- mov ax,[WORD string]\r
- mov [stringptr],ax\r
- mov ax,[WORD string+2]\r
- mov [stringptr+2],ax\r
-\r
-@@shiftone:\r
- mov es,[stringptr+2]\r
- mov bx,[stringptr]\r
- inc [stringptr]\r
- mov bx,[es:bx]\r
- xor bh,bh\r
- or bl,bl\r
- jz @@allshifted\r
- call ShiftPropChar\r
- jmp @@shiftone\r
-\r
-@@allshifted:\r
-;\r
-; calculate position to draw buffer on screen\r
-;\r
- mov bx,[py]\r
- shl bx,1\r
- mov di,[ylookup+bx]\r
- add di,[bufferofs]\r
- add di,[panadjust]\r
-\r
- mov ax,[px]\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1 ;x location in bytes\r
- add di,ax\r
- mov [screenspot],di\r
-\r
-;\r
-; advance px\r
-;\r
- mov ax,[bufferbyte]\r
- shl ax,1\r
- shl ax,1\r
- shl ax,1\r
- or ax,[bufferbit]\r
- add [px],ax\r
-\r
-;\r
-; draw it\r
-;\r
-\r
-; set xor/or mode\r
- mov dx,GC_INDEX\r
- mov al,GC_DATAROTATE\r
- mov ah,[pdrawmode]\r
- WORDOUT\r
-\r
-; set mapmask to color\r
- mov dx,SC_INDEX\r
- mov al,SC_MAPMASK\r
- mov ah,[fontcolor]\r
- WORDOUT\r
-\r
- mov ax,[bufferbyte]\r
- test [bufferbit],7\r
- jz @@go\r
- inc ax ;so the partial byte also gets drawn\r
-@@go:\r
- mov [bufferwidth],ax\r
- mov si,[fontnumber]\r
- shl si,1\r
- mov es,[grsegs+STARTFONT*2+si]\r
- mov ax,[es:pcharheight]\r
- mov [bufferheight],ax\r
-\r
- mov si,OFFSET databuffer\r
- call BufferToScreen\r
-\r
-; set copy mode\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE\r
- WORDOUT\r
-\r
-; set mapmask to all\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK + 15*256\r
- WORDOUT\r
-\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-endif ;numfont\r
-\r
-;============================================================================\r
-;\r
-; MASKED FONT DRAWING ROUTINES\r
-;\r
-;============================================================================\r
-\r
-if numfontm\r
-\r
-DATASEG\r
-\r
-mshiftdrawtable dw 0,mshift1wide,mshift2wide,mshift3wide\r
-\r
-\r
-CODESEG\r
-\r
-;==================\r
-;\r
-; ShiftMPropChar\r
-;\r
-; Call with BX = character number (0-255)\r
-; Draws one character to the buffer at bufferbyte/bufferbit, and adjusts\r
-; them to the new position\r
-;\r
-;==================\r
-\r
-PROC ShiftMPropChar NEAR\r
-\r
- mov si,[fontnumber]\r
- shl si,1\r
- mov es,[grsegs+STARTFONTM*2+si] ;segment of font to use\r
-\r
-;\r
-; find character location, width, and height\r
-;\r
- mov si,[es:charwidth+bx]\r
- and si,0ffh ;SI hold width in pixels\r
- shl bx,1\r
- mov bx,[es:charloc+bx] ;BX holds pointer to character data\r
-\r
-;\r
-; look up which shift table to use, based on bufferbit\r
-;\r
- mov di,[bufferbit]\r
- shl di,1\r
- mov bp,[shifttabletable+di] ;BP holds pointer to shift table\r
-\r
- mov di,OFFSET databuffer\r
- add di,[bufferbyte] ;DI holds pointer to buffer\r
-\r
- mov cx,[bufferbit]\r
- add cx,si ;new bit position\r
- mov ax,cx\r
- and ax,7\r
- mov [bufferbit],ax ;new bit position\r
- mov ax,cx\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1\r
- add [bufferbyte],ax ;new byte position\r
-\r
- add si,7\r
- shr si,1\r
- shr si,1\r
- shr si,1 ;bytes the character is wide\r
- shl si,1 ;*2 to look up in shiftdrawtable\r
-\r
- mov cx,[es:pcharheight]\r
- mov dx,BUFFWIDTH\r
- jmp [ss:mshiftdrawtable+si] ;procedure to draw this width\r
-\r
-;\r
-; one byte character\r
-;\r
-mshift1wide:\r
- dec dx\r
-\r
-EVEN\r
-@@loop1m:\r
- SHIFTWITHXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop1m\r
-\r
- mov cx,[es:pcharheight]\r
-\r
-EVEN\r
-@@loop1:\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop1\r
-\r
- ret\r
-\r
-;\r
-; two byte character\r
-;\r
-mshift2wide:\r
- dec dx\r
- dec dx\r
-EVEN\r
-@@loop2m:\r
- SHIFTWITHXOR\r
- SHIFTWITHXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop2m\r
-\r
- mov cx,[es:pcharheight]\r
-\r
-EVEN\r
-@@loop2:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop2\r
-\r
- ret\r
-\r
-;\r
-; three byte character\r
-;\r
-mshift3wide:\r
- sub dx,3\r
-EVEN\r
-@@loop3m:\r
- SHIFTWITHXOR\r
- SHIFTWITHXOR\r
- SHIFTWITHXOR\r
- add di,dx ; next line in buffer\r
-\r
- loop @@loop3m\r
-\r
- mov cx,[es:pcharheight]\r
-\r
-EVEN\r
-@@loop3:\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- SHIFTNOXOR\r
- add di,dx ; next line in buffer\r
- loop @@loop3\r
-\r
- ret\r
-\r
-\r
-ENDP\r
-\r
-;============================================================================\r
-\r
-;==================\r
-;\r
-; VW_DrawMPropString\r
-;\r
-; Draws a C string of characters at px/py and advances px\r
-;\r
-; Assumes write mode 0\r
-;\r
-;==================\r
-\r
-\r
-\r
-PROC VW_DrawMPropString string:DWORD\r
-PUBLIC VW_DrawMPropString\r
-USES SI,DI\r
-\r
-;\r
-; clear out the first byte of the buffer, the rest will automatically be\r
-; cleared as characters are drawn into it\r
-;\r
- mov si,[fontnumber]\r
- shl si,1\r
- mov es,[grsegs+STARTFONTM*2+si]\r
- mov dx,[es:pcharheight]\r
- mov di,OFFSET databuffer\r
- mov ax,ds\r
- mov es,ax\r
- mov bx,BUFFWIDTH-1\r
-\r
- mov cx,dx\r
- mov al,0ffh\r
-@@maskfill:\r
- stosb ; fill the mask part with $ff\r
- add di,bx\r
- loop @@maskfill\r
-\r
- mov cx,dx\r
- xor al,al\r
-@@datafill:\r
- stosb ; fill the data part with $0\r
- add di,bx\r
- loop @@datafill\r
-\r
-;\r
-; shift the characters into the buffer\r
-;\r
- mov ax,[px]\r
- and ax,7\r
- mov [bufferbit],ax\r
- mov [bufferbyte],0\r
-\r
- mov ax,[WORD string]\r
- mov [stringptr],ax\r
- mov ax,[WORD string+2]\r
- mov [stringptr+2],ax\r
-\r
-@@shiftone:\r
- mov es,[stringptr+2]\r
- mov bx,[stringptr]\r
- inc [stringptr]\r
- mov bx,[es:bx]\r
- xor bh,bh\r
- or bl,bl\r
- jz @@allshifted\r
- call ShiftMPropChar\r
- jmp @@shiftone\r
-\r
-@@allshifted:\r
-;\r
-; calculate position to draw buffer on screen\r
-;\r
- mov bx,[py]\r
- shl bx,1\r
- mov di,[ylookup+bx]\r
- add di,[bufferofs]\r
- add di,[panadjust]\r
-\r
- mov ax,[px]\r
- shr ax,1\r
- shr ax,1\r
- shr ax,1 ;x location in bytes\r
- add di,ax\r
- mov [screenspot],di\r
-\r
-;\r
-; advance px\r
-;\r
- mov ax,[bufferbyte]\r
- shl ax,1\r
- shl ax,1\r
- shl ax,1\r
- or ax,[bufferbit]\r
- add [px],ax\r
-\r
-;\r
-; draw it\r
-;\r
- mov ax,[bufferbyte]\r
- test [bufferbit],7\r
- jz @@go\r
- inc ax ;so the partial byte also gets drawn\r
-@@go:\r
- mov [bufferwidth],ax\r
- mov es,[grsegs+STARTFONTM*2]\r
- mov ax,[es:pcharheight]\r
- mov [bufferheight],ax\r
-\r
-; set AND mode to punch out the mask\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE + 8*256\r
- WORDOUT\r
-\r
-; set mapmask to all\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK + 15*256\r
- WORDOUT\r
-\r
- mov si,OFFSET databuffer\r
- call BufferToScreen\r
-\r
-; set OR mode to fill in the color\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE + 16*256\r
- WORDOUT\r
-\r
-; set mapmask to color\r
- mov dx,SC_INDEX\r
- mov al,SC_MAPMASK\r
- mov ah,[fontcolor]\r
- WORDOUT\r
-\r
- call BufferToScreen ; SI is still in the right position in buffer\r
-\r
-; set copy mode\r
- mov dx,GC_INDEX\r
- mov ax,GC_DATAROTATE\r
- WORDOUT\r
-\r
-; set mapmask to all\r
- mov dx,SC_INDEX\r
- mov ax,SC_MAPMASK + 15*256\r
- WORDOUT\r
-\r
-\r
- ret\r
-\r
-ENDP\r
-\r
-endif ; if numfontm\r
-\r
-endif ; if fonts\r
+++ /dev/null
-; Catacomb Armageddon Source Code\r
-; Copyright (C) 1993-2014 Flat Rock Software\r
-;\r
-; This program is free software; you can redistribute it and/or modify\r
-; it under the terms of the GNU General Public License as published by\r
-; the Free Software Foundation; either version 2 of the License, or\r
-; (at your option) any later version.\r
-;\r
-; This program is distributed in the hope that it will be useful,\r
-; but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-; GNU General Public License for more details.\r
-;\r
-; You should have received a copy of the GNU General Public License along\r
-; with this program; if not, write to the Free Software Foundation, Inc.,\r
-; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-\r
-; JABHACK.ASM\r
-\r
-.386C\r
-IDEAL\r
-MODEL MEDIUM\r
-\r
-EXTRN LDIV@:far\r
-\r
-;============================================================================\r
-\r
-DATASEG\r
-\r
-EXTRN _intaddr:word\r
-\r
-;============================================================================\r
-\r
-CODESEG\r
-\r
-; Hacked up Juan Jimenez's code a bit to just return 386/not 386\r
-PROC _CheckIs386\r
-PUBLIC _CheckIs386\r
-\r
- pushf ; Save flag registers, we use them here\r
- xor ax,ax ; Clear AX and...\r
- push ax ; ...push it onto the stack\r
- popf ; Pop 0 into flag registers (all bits to 0),\r
- pushf ; attempting to set bits 12-15 of flags to 0's\r
- pop ax ; Recover the save flags\r
- and ax,08000h ; If bits 12-15 of flags are set to\r
- cmp ax,08000h ; zero then it's 8088/86 or 80188/186\r
- jz not386\r
-\r
- mov ax,07000h ; Try to set flag bits 12-14 to 1's\r
- push ax ; Push the test value onto the stack\r
- popf ; Pop it into the flag register\r
- pushf ; Push it back onto the stack\r
- pop ax ; Pop it into AX for check\r
- and ax,07000h ; if bits 12-14 are cleared then\r
- jz not386 ; the chip is an 80286\r
-\r
- mov ax,1 ; We now assume it's a 80386 or better\r
- popf\r
- retf\r
-\r
-not386:\r
- xor ax,ax\r
- popf\r
- retf\r
-\r
- ENDP\r
-\r
-\r
-PROC _jabhack2\r
-PUBLIC _jabhack2\r
-\r
- jmp @@skip\r
-\r
-@@where:\r
- int 060h\r
- retf\r
-\r
-@@skip:\r
- push es\r
-\r
- mov ax,seg LDIV@\r
- mov es,ax\r
- mov ax,[WORD PTR @@where]\r
- mov [WORD FAR es:LDIV@],ax\r
- mov ax,[WORD PTR @@where+2]\r
- mov [WORD FAR es:LDIV@+2],ax\r
-\r
- mov ax,offset @@jabdiv\r
- mov [_intaddr],ax\r
- mov ax,seg @@jabdiv\r
- mov [_intaddr+2],ax\r
-\r
- pop es\r
- retf\r
-\r
-@@jabdiv:\r
- add sp,4 ;Nuke IRET address, but leave flags\r
- push bp\r
- mov bp,sp ;Save BP, and set it equal to stack\r
- cli\r
-\r
- mov eax,[bp+8]\r
- cdq\r
- idiv [DWORD PTR bp+12]\r
- mov edx,eax\r
- shr edx,16\r
-\r
- pop bp ;Restore BP\r
- popf ;Restore flags (from INT)\r
- retf 8 ;Return to original caller\r
-\r
- ENDP\r
-\r
- END\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#pragma inline\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <ctype.h>\r
-#include <alloc.h>\r
-#include <fcntl.h>\r
-#include <dos.h>\r
-#include <io.h>\r
-\r
-#include "def.h"\r
-#include "gelib.h"\r
-#include "jampak.h"\r
-\r
-\r
-\r
-//=========================================================================\r
-//\r
-//\r
-// LOCAL DEFINATIONS\r
-//\r
-//\r
-//=========================================================================\r
-\r
-//#define COMPRESSION_CODE // Comment define in for COMPRESS routines\r
-\r
-\r
-\r
-\r
-\r
-\r
-//=========================================================================\r
-//\r
-//\r
-// LOCAL VARIABLES\r
-//\r
-//\r
-//=========================================================================\r
-\r
-\r
-unsigned char far LZW_ring_buffer[LZW_N + LZW_F - 1];\r
-\r
- // ring buffer of size LZW_N, with extra LZW_F-1 bytes to facilitate\r
- // string comparison\r
-\r
-\r
-#ifdef COMPRESSION_CODE\r
-\r
-int LZW_match_pos,\r
- LZW_match_len,\r
-\r
- // MAtchLength of longest match. These are set by the InsertNode()\r
- // procedure.\r
-\r
- // left & right children & parents -- These constitute binary search trees. */\r
-\r
- far LZW_left_child[LZW_N + 1],\r
- far LZW_right_child[LZW_N + 257],\r
- far LZW_parent[LZW_N + 1];\r
-\r
-#endif\r
-\r
-memptr segptr;\r
-BufferedIO lzwBIO;\r
-\r
-\r
-\r
-\r
-\r
-//=========================================================================\r
-//\r
-//\r
-// COMPRESSION SUPPORT ROUTINES\r
-//\r
-//\r
-//=========================================================================\r
-\r
-\r
-#ifdef COMPRESSION_CODE\r
-\r
-//---------------------------------------------------------------------------\r
-// InitLZWTree()\r
-//---------------------------------------------------------------------------\r
-void InitLZWTree(void) /* initialize trees */\r
-{\r
- int i;\r
-\r
- /* For i = 0 to LZW_N - 1, LZW_right_child[i] and LZW_left_child[i] will be the right and\r
- left children of node i. These nodes need not be initialized.\r
- Also, LZW_parent[i] is the parent of node i. These are initialized to\r
- LZW_NIL (= LZW_N), which stands for 'not used.'\r
- For i = 0 to 255, LZW_right_child[LZW_N + i + 1] is the root of the tree\r
- for strings that begin with character i. These are initialized\r
- to LZW_NIL. Note there are 256 trees. */\r
-\r
- for (i = LZW_N + 1; i <= LZW_N + 256; i++)\r
- LZW_right_child[i] = LZW_NIL;\r
-\r
- for (i = 0; i < LZW_N; i++)\r
- LZW_parent[i] = LZW_NIL;\r
-}\r
-\r
-\r
-\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// InsertLZWNode()\r
-//---------------------------------------------------------------------------\r
-void InsertLZWNode(unsigned long r)\r
-\r
- /* Inserts string of length LZW_F, LZW_ring_buffer[r..r+LZW_F-1], into one of the\r
- trees (LZW_ring_buffer[r]'th tree) and returns the longest-match position\r
- and length via the global variables LZW_match_pos and LZW_match_len.\r
- If LZW_match_len = LZW_F, then removes the old node in favor of the new\r
- one, because the old one will be deleted sooner.\r
- Note r plays double role, as tree node and position in buffer. */\r
-{\r
- int i, p, cmp;\r
- unsigned char *key;\r
-\r
- cmp = 1;\r
- key = &LZW_ring_buffer[r];\r
- p = LZW_N + 1 + key[0];\r
- LZW_right_child[r] = LZW_left_child[r] = LZW_NIL;\r
- LZW_match_len = 0;\r
-\r
- for ( ; ; )\r
- {\r
- if (cmp >= 0)\r
- {\r
- if (LZW_right_child[p] != LZW_NIL)\r
- p = LZW_right_child[p];\r
- else\r
- {\r
- LZW_right_child[p] = r;\r
- LZW_parent[r] = p;\r
- return;\r
- }\r
- }\r
- else\r
- {\r
- if (LZW_left_child[p] != LZW_NIL)\r
- p = LZW_left_child[p];\r
- else\r
- {\r
- LZW_left_child[p] = r;\r
- LZW_parent[r] = p;\r
- return;\r
- }\r
- }\r
-\r
- for (i = 1; i < LZW_F; i++)\r
- if ((cmp = key[i] - LZW_ring_buffer[p + i]) != 0)\r
- break;\r
-\r
- if (i > LZW_match_len)\r
- {\r
- LZW_match_pos = p;\r
- if ((LZW_match_len = i) >= LZW_F)\r
- break;\r
- }\r
- }\r
-\r
- LZW_parent[r] = LZW_parent[p];\r
- LZW_left_child[r] = LZW_left_child[p];\r
- LZW_right_child[r] = LZW_right_child[p];\r
- LZW_parent[LZW_left_child[p]] = r;\r
- LZW_parent[LZW_right_child[p]] = r;\r
-\r
- if (LZW_right_child[LZW_parent[p]] == p)\r
- LZW_right_child[LZW_parent[p]] = r;\r
- else\r
- LZW_left_child[LZW_parent[p]] = r;\r
-\r
- LZW_parent[p] = LZW_NIL; /* remove p */\r
-}\r
-\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// DeleteLZWNode()\r
-//---------------------------------------------------------------------------\r
-void DeleteLZWNode(unsigned long p) /* deletes node p from tree */\r
-{\r
- int q;\r
-\r
- if (LZW_parent[p] == LZW_NIL)\r
- return; /* not in tree */\r
-\r
- if (LZW_right_child[p] == LZW_NIL)\r
- q = LZW_left_child[p];\r
- else\r
- if (LZW_left_child[p] == LZW_NIL)\r
- q = LZW_right_child[p];\r
- else\r
- {\r
- q = LZW_left_child[p];\r
- if (LZW_right_child[q] != LZW_NIL)\r
- {\r
- do {\r
-\r
- q = LZW_right_child[q];\r
-\r
- } while (LZW_right_child[q] != LZW_NIL);\r
-\r
- LZW_right_child[LZW_parent[q]] = LZW_left_child[q];\r
- LZW_parent[LZW_left_child[q]] = LZW_parent[q];\r
- LZW_left_child[q] = LZW_left_child[p];\r
- LZW_parent[LZW_left_child[p]] = q;\r
- }\r
-\r
- LZW_right_child[q] = LZW_right_child[p];\r
- LZW_parent[LZW_right_child[p]] = q;\r
- }\r
-\r
- LZW_parent[q] = LZW_parent[p];\r
- if (LZW_right_child[LZW_parent[p]] == p)\r
- LZW_right_child[LZW_parent[p]] = q;\r
- else\r
- LZW_left_child[LZW_parent[p]] = q;\r
-\r
- LZW_parent[p] = LZW_NIL;\r
-}\r
-#endif\r
-\r
-\r
-\r
-\r
-//=========================================================================\r
-//\r
-//\r
-// GENERAL FILE to FILE compression routines\r
-//\r
-// * Mainly for example usage of PTR/PTR (de)compression routines.\r
-//\r
-//\r
-//=========================================================================\r
-\r
-\r
-\r
-//////////////////////////////////////////////////////////////////////\r
-//\r
-// CompressFILEtoFILE() -- Compresses one file stream to another file stream\r
-//\r
-\r
-#ifdef COMPRESSION_CODE\r
-\r
-unsigned long CompressFILEtoFILE(FILE *infile, FILE *outfile,unsigned long DataLength)\r
-{\r
- unsigned long returnval;\r
-\r
- fwrite(COMP,4,1,outfile);\r
- fwrite((char *)&DataLength,4,1,outfile);\r
-\r
- returnval = 8+lzwCompress(infile,outfile,DataLength,(SRC_FFILE|DEST_FFILE));\r
-\r
- return(returnval);\r
-}\r
-\r
-#endif\r
-\r
-#if 0\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// DecompressFILEtoFILE()\r
-//\r
-void DecompressFILEtoFILE(FILE *infile, FILE *outfile)\r
-{\r
- unsigned char Buffer[8];\r
- unsigned long DataLength;\r
-\r
- fread(Buffer,1,4,infile);\r
-\r
- if (strncmp(Buffer,COMP,4))\r
- {\r
- printf("\nNot a JAM Compressed File!\n");\r
- return;\r
- }\r
-\r
- fread((void *)&DataLength,1,4,infile);\r
-\r
- lzwDecompress(infile,outfile,DataLength,(SRC_FFILE|DEST_FFILE));\r
-}\r
-#endif\r
-\r
-\r
-\r
-\r
-\r
-//==========================================================================\r
-//\r
-//\r
-// WRITE/READ PTR ROUTINES\r
-//\r
-//\r
-//==========================================================================\r
-\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// WritePtr() -- Outputs data to a particular ptr type\r
-//\r
-// PtrType MUST be of type DEST_TYPE.\r
-//\r
-// NOTE : For PtrTypes DEST_MEM a ZERO (0) is always returned.\r
-//\r
-//---------------------------------------------------------------------------\r
-int WritePtr(long outfile, unsigned char data, unsigned PtrType)\r
-{\r
- int returnval = 0;\r
-\r
- switch (PtrType & DEST_TYPES)\r
- {\r
- case DEST_FILE:\r
- write(*(int far *)outfile,(char *)&data,1);\r
- break;\r
-\r
- case DEST_FFILE:\r
- returnval = putc(data, *(FILE **)outfile);\r
- break;\r
-\r
- case DEST_MEM:\r
-// *(*(char far **)outfile++) = data; // Do NOT delete\r
- *((char far *)*(char far **)outfile)++ = data;\r
- break;\r
-\r
- default:\r
- TrashProg("WritePtr() : Unknown DEST_PTR type");\r
- break;\r
- }\r
-\r
- return(returnval);\r
-\r
-}\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// ReadPtr() -- Reads data from a particular ptr type\r
-//\r
-// PtrType MUST be of type SRC_TYPE.\r
-//\r
-// RETURNS :\r
-// The char read in or EOF for SRC_FFILE type of reads.\r
-//\r
-//\r
-//---------------------------------------------------------------------------\r
-int ReadPtr(long infile, unsigned PtrType)\r
-{\r
- int returnval = 0;\r
-\r
- switch (PtrType & SRC_TYPES)\r
- {\r
- case SRC_FILE:\r
- read(*(int far *)infile,(char *)&returnval,1);\r
- break;\r
-\r
- case SRC_FFILE:\r
-// JIM - JTR - is the following correct? "fgetc()" uses a near pointer.\r
-//\r
- returnval = fgetc((FILE far *)*(FILE far **)infile);\r
- break;\r
-\r
- case SRC_BFILE:\r
- returnval = bio_readch((BufferedIO *)*(void far **)infile);\r
- break;\r
-\r
- case SRC_MEM:\r
- returnval = (char)*(*(char far **)infile++);\r
-// returnval = *((char far *)*(char far **)infile)++; // DO NOT DELETE!\r
- break;\r
-\r
- default:\r
- TrashProg("ReadPtr() : Unknown SRC_PTR type");\r
- break;\r
- }\r
-\r
- return(returnval);\r
-}\r
-\r
-\r
-\r
-\r
-//=========================================================================\r
-//\r
-//\r
-// COMPRESSION & DECOMPRESSION ROUTINES\r
-//\r
-//\r
-//=========================================================================\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-//\r
-// lzwCompress() - Compresses data from an input ptr to a dest ptr\r
-//\r
-// PARAMS:\r
-// infile - Pointer at the BEGINNING of the data to compress\r
-// outfile - Pointer to the destination (no header).\r
-// DataLength - Number of bytes to compress.\r
-// PtrTypes - Type of pointers being used (SRC_FILE,DEST_FILE,SRC_MEM etc).\r
-//\r
-// RETURNS:\r
-// Length of compressed data.\r
-//\r
-// COMPTYPE : ct_LZW\r
-//\r
-// NOTES : Does not write ANY header information!\r
-//\r
-#ifdef COMPRESSION_CODE\r
-unsigned long lzwCompress(void far *infile, void far *outfile,unsigned long DataLength,unsigned PtrTypes)\r
-{\r
- short i;\r
- short c, len, r, s, last_LZW_match_len, code_buf_ptr;\r
- unsigned char far code_buf[17], mask;\r
- unsigned long complen = 0;\r
-\r
- // initialize trees\r
-\r
- InitLZWTree();\r
-\r
- code_buf[0] = 0;\r
-\r
- //\r
- // code_buf[1..16] saves eight units of code, and code_buf[0] works\r
- // as eight flags, "1" representing that the unit is an unencoded\r
- // letter (1 byte), "0" a position-and-length pair (2 bytes). Thus,\r
- // eight units require at most 16 bytes of code.\r
- //\r
-\r
- code_buf_ptr = mask = 1;\r
- s = 0;\r
- r = LZW_N - LZW_F;\r
-\r
- // Clear the buffer with any character that will appear often.\r
- //\r
-\r
- for (i = s; i < r; i++)\r
- LZW_ring_buffer[i] = ' ';\r
-\r
- // Read LZW_F bytes into the last LZW_F bytes of the buffer\r
- //\r
-\r
- for (len = 0; (len < LZW_F) && DataLength; len++)\r
- {\r
- c = ReadPtr((long)&infile,PtrTypes);\r
- DataLength--;\r
-\r
- // text of size zero\r
-\r
- LZW_ring_buffer[r + len] = c;\r
- }\r
-\r
- if (!(len && DataLength))\r
- return(0);\r
-\r
- //\r
- // Insert the LZW_F strings, each of which begins with one or more\r
- // 'space' characters. Note the order in which these strings\r
- // are inserted. This way, degenerate trees will be less likely\r
- // to occur.\r
- //\r
-\r
- for (i = 1; i <= LZW_F; i++)\r
- InsertLZWNode(r - i);\r
-\r
- //\r
- // Finally, insert the whole string just read. The global\r
- // variables LZW_match_len and LZW_match_pos are set. */\r
- //\r
-\r
- InsertLZWNode(r);\r
-\r
- do {\r
- // LZW_match_len may be spuriously long near the end of text.\r
- //\r
-\r
- if (LZW_match_len > len)\r
- LZW_match_len = len;\r
-\r
- if (LZW_match_len <= LZW_THRESHOLD)\r
- {\r
- // Not long enough match. Send one byte.\r
- //\r
-\r
- LZW_match_len = 1;\r
-\r
- // 'send one byte' flag\r
- //\r
-\r
- code_buf[0] |= mask;\r
-\r
- // Send uncoded.\r
- //\r
-\r
- code_buf[code_buf_ptr++] = LZW_ring_buffer[r];\r
- }\r
- else\r
- {\r
- code_buf[code_buf_ptr++] = (unsigned char) LZW_match_pos;\r
- code_buf[code_buf_ptr++] = (unsigned char) (((LZW_match_pos >> 4) & 0xf0) | (LZW_match_len - (LZW_THRESHOLD + 1)));\r
-\r
- // Send position and length pair.\r
- // Note LZW_match_len > LZW_THRESHOLD.\r
- }\r
-\r
- if ((mask <<= 1) == 0)\r
- {\r
- // Shift mask left one bit.\r
- // Send at most 8 units of data\r
-\r
- for (i = 0; i < code_buf_ptr; i++)\r
- WritePtr((long)&outfile,code_buf[i],PtrTypes);\r
-\r
- complen += code_buf_ptr;\r
- code_buf[0] = 0;\r
- code_buf_ptr = mask = 1;\r
- }\r
-\r
- last_LZW_match_len = LZW_match_len;\r
-\r
- for (i = 0; i < last_LZW_match_len && DataLength; i++)\r
- {\r
- c = ReadPtr((long)&infile,PtrTypes);\r
- DataLength--;\r
-\r
- DeleteLZWNode(s); // Delete old strings and\r
- LZW_ring_buffer[s] = c; // read new bytes\r
-\r
- // If the position is near the end of buffer, extend the\r
- // buffer to make string comparison easier.\r
-\r
- if (s < LZW_F - 1)\r
- LZW_ring_buffer[s + LZW_N] = c;\r
-\r
- // Since this is a ring buffer, inc the position modulo LZW_N.\r
- //\r
-\r
- s = (s + 1) & (LZW_N - 1);\r
- r = (r + 1) & (LZW_N - 1);\r
-\r
- // Register the string in LZW_ring_buffer[r..r+LZW_F-1]\r
- //\r
-\r
- InsertLZWNode(r);\r
- }\r
-\r
- while (i++ < last_LZW_match_len)\r
- {\r
- // After the end of text,\r
- DeleteLZWNode(s); // no need to read, but\r
-\r
- s = (s + 1) & (LZW_N - 1);\r
- r = (r + 1) & (LZW_N - 1);\r
-\r
- if (--len)\r
- InsertLZWNode(r); // buffer may not be empty.\r
- }\r
-\r
- } while (len > 0); // until length of string to be processed is zero\r
-\r
-\r
- if (code_buf_ptr > 1)\r
- {\r
- // Send remaining code.\r
- //\r
-\r
- for (i = 0; i < code_buf_ptr; i++)\r
- WritePtr((long)&outfile,code_buf[i],PtrTypes);\r
-\r
- complen += code_buf_ptr;\r
- }\r
-\r
- return(complen);\r
-}\r
-#endif\r
-\r
-\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-//\r
-// lzwDecompress() - Compresses data from an input ptr to a dest ptr\r
-//\r
-// PARAMS:\r
-// infile - Pointer at the BEGINNING of the compressed data (no header!)\r
-// outfile - Pointer to the destination.\r
-// DataLength - Length of compressed data.\r
-// PtrTypes - Type of pointers being used (SRC_FILE,DEST_FILE,SRC_MEM etc).\r
-//\r
-// RETURNS:\r
-// Length of compressed data.\r
-//\r
-// COMPTYPE : ct_LZW\r
-//\r
-// NOTES : Does not write ANY header information!\r
-//\r
-void far lzwDecompress(void far *infile, void far *outfile,unsigned long DataLength,unsigned PtrTypes)\r
-{\r
- int i, j, k, r, c;\r
- unsigned int flags;\r
-\r
- for (i = 0; i < LZW_N - LZW_F; i++)\r
- LZW_ring_buffer[i] = ' ';\r
-\r
- r = LZW_N - LZW_F;\r
- flags = 0;\r
-\r
- for ( ; ; )\r
- {\r
- if (((flags >>= 1) & 256) == 0)\r
- {\r
- c = ReadPtr((long)&infile,PtrTypes);\r
- if (!DataLength--)\r
- return;\r
-\r
- flags = c | 0xff00; // uses higher byte cleverly to count 8\r
- }\r
-\r
- if (flags & 1)\r
- {\r
- c = ReadPtr((long)&infile,PtrTypes); // Could test for EOF iff FFILE type\r
- if (!DataLength--)\r
- return;\r
-\r
- WritePtr((long)&outfile,c,PtrTypes);\r
-\r
- LZW_ring_buffer[r++] = c;\r
- r &= (LZW_N - 1);\r
- }\r
- else\r
- {\r
- i = ReadPtr((long)&infile,PtrTypes);\r
- if (!DataLength--)\r
- return;\r
-\r
- j = ReadPtr((long)&infile,PtrTypes);\r
- if (!DataLength--)\r
- return;\r
-\r
- i |= ((j & 0xf0) << 4);\r
- j = (j & 0x0f) + LZW_THRESHOLD;\r
-\r
- for (k = 0; k <= j; k++)\r
- {\r
- c = LZW_ring_buffer[(i + k) & (LZW_N - 1)];\r
-\r
- WritePtr((long)&outfile,c,PtrTypes);\r
-\r
- LZW_ring_buffer[r++] = c;\r
- r &= (LZW_N - 1);\r
- }\r
- }\r
- }\r
-}\r
-\r
-\r
-\r
-#if 0\r
-//=========================================================================\r
-//\r
-//\r
-// BUFFERED I/O ROUTINES\r
-//\r
-//\r
-//=========================================================================\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-// InitBufferedIO()\r
-//--------------------------------------------------------------------------\r
-memptr InitBufferedIO(int handle, BufferedIO *bio)\r
-{\r
- bio->handle = handle;\r
- bio->offset = BIO_BUFFER_LEN;\r
- bio->status = 0;\r
- MM_GetPtr(&bio->buffer,BIO_BUFFER_LEN);\r
-\r
- return(bio->buffer);\r
-}\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-// FreeBufferedIO()\r
-//--------------------------------------------------------------------------\r
-void FreeBufferedIO(BufferedIO *bio)\r
-{\r
- if (bio->buffer)\r
- MM_FreePtr(&bio->buffer);\r
-}\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-// bio_readch()\r
-//--------------------------------------------------------------------------\r
-byte bio_readch(BufferedIO *bio)\r
-{\r
- byte far *buffer;\r
-\r
- if (bio->offset == BIO_BUFFER_LEN)\r
- {\r
- bio->offset = 0;\r
- bio_fillbuffer(bio);\r
- }\r
-\r
- buffer = MK_FP(bio->buffer,bio->offset++);\r
-\r
- return(*buffer);\r
-}\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-// bio_fillbuffer()\r
-//\r
-// BUGS (Not really bugs... More like RULES!)\r
-//\r
-// 1) This code assumes BIO_BUFFER_LEN is no smaller than\r
-// NEAR_BUFFER_LEN!!\r
-//\r
-// 2) BufferedIO.status should be altered by this code to report\r
-// read errors, end of file, etc... If you know how big the file\r
-// is you're reading, determining EOF should be no problem.\r
-//\r
-//--------------------------------------------------------------------------\r
-void bio_fillbuffer(BufferedIO *bio)\r
-{\r
- #define NEAR_BUFFER_LEN (64)\r
- byte near_buffer[NEAR_BUFFER_LEN];\r
- short bio_length,bytes_read,bytes_requested;\r
-\r
- bytes_read = 0;\r
- bio_length = BIO_BUFFER_LEN;\r
- while (bio_length)\r
- {\r
- if (bio_length > NEAR_BUFFER_LEN-1)\r
- bytes_requested = NEAR_BUFFER_LEN;\r
- else\r
- bytes_requested = bio_length;\r
-\r
- read(bio->handle,near_buffer,bytes_requested);\r
- _fmemcpy(MK_FP(bio->buffer,bytes_read),near_buffer,bytes_requested);\r
-\r
- bio_length -= bytes_requested;\r
- bytes_read += bytes_requested;\r
- }\r
-}\r
-\r
-\r
-#endif\r
-\r
-//=========================================================================\r
-//\r
-//\r
-// GENERAL LOAD ROUTINES\r
-//\r
-//\r
-//=========================================================================\r
-\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-// BLoad()\r
-//--------------------------------------------------------------------------\r
-unsigned long BLoad(char *SourceFile, memptr *DstPtr)\r
-{\r
- int handle;\r
-\r
- memptr SrcPtr;\r
- longword i, j, k, r, c;\r
- word flags;\r
- byte Buffer[8];\r
- longword DstLen, SrcLen;\r
- boolean comp;\r
-\r
- if ((handle = open(SourceFile, O_RDONLY|O_BINARY)) == -1)\r
- return(0);\r
-\r
- // Look for 'COMP' header\r
- //\r
- read(handle,Buffer,4);\r
- comp = !strncmp(Buffer,COMP,4);\r
-\r
- // Get source and destination length.\r
- //\r
- if (comp)\r
- {\r
- SrcLen = Verify(SourceFile);\r
- read(handle,(void *)&DstLen,4);\r
- MM_GetPtr(DstPtr,DstLen);\r
- if (!*DstPtr)\r
- return(0);\r
- }\r
- else\r
- DstLen = Verify(SourceFile);\r
-\r
- // LZW decompress OR simply load the file.\r
- //\r
- if (comp)\r
- {\r
-\r
- if (MM_TotalFree() < SrcLen)\r
- {\r
- if (!InitBufferedIO(handle,&lzwBIO))\r
- TrashProg("No memory for buffered I/O.");\r
- lzwDecompress(&lzwBIO,MK_FP(*DstPtr,0),SrcLen,(SRC_BFILE|DEST_MEM));\r
- FreeBufferedIO(&lzwBIO);\r
- }\r
- else\r
- {\r
- CA_LoadFile(SourceFile,&SrcPtr);\r
- lzwDecompress(MK_FP(SrcPtr,8),MK_FP(*DstPtr,0),SrcLen,(SRC_MEM|DEST_MEM));\r
- MM_FreePtr(&SrcPtr);\r
- }\r
- }\r
- else\r
- CA_LoadFile(SourceFile,DstPtr);\r
-\r
- close(handle);\r
- return(DstLen);\r
-}\r
-\r
-\r
-\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// LoadLIBShape()\r
-//\r
-int LoadLIBShape(char *SLIB_Filename, char *Filename,struct Shape *SHP)\r
-{\r
- #define CHUNK(Name) (*ptr == *Name) && \\r
- (*(ptr+1) == *(Name+1)) && \\r
- (*(ptr+2) == *(Name+2)) && \\r
- (*(ptr+3) == *(Name+3))\r
-\r
-\r
- int RT_CODE;\r
- FILE *fp;\r
- char CHUNK[5];\r
- char far *ptr;\r
- memptr IFFfile = NULL;\r
- unsigned long FileLen, size, ChunkLen;\r
- int loop;\r
-\r
-\r
- RT_CODE = 1;\r
-\r
- // Decompress to ram and return ptr to data and return len of data in\r
- // passed variable...\r
-\r
- if (!LoadLIBFile(SLIB_Filename,Filename,&IFFfile))\r
- TrashProg("Error Loading Compressed lib shape!");\r
-\r
- // Evaluate the file\r
- //\r
- ptr = MK_FP(IFFfile,0);\r
- if (!CHUNK("FORM"))\r
- goto EXIT_FUNC;\r
- ptr += 4;\r
-\r
- FileLen = *(long far *)ptr;\r
- SwapLong((long far *)&FileLen);\r
- ptr += 4;\r
-\r
- if (!CHUNK("ILBM"))\r
- goto EXIT_FUNC;\r
- ptr += 4;\r
-\r
- FileLen += 4;\r
- while (FileLen)\r
- {\r
- ChunkLen = *(long far *)(ptr+4);\r
- SwapLong((long far *)&ChunkLen);\r
- ChunkLen = (ChunkLen+1) & 0xFFFFFFFE;\r
-\r
- if (CHUNK("BMHD"))\r
- {\r
- ptr += 8;\r
- SHP->bmHdr.w = ((struct BitMapHeader far *)ptr)->w;\r
- SHP->bmHdr.h = ((struct BitMapHeader far *)ptr)->h;\r
- SHP->bmHdr.x = ((struct BitMapHeader far *)ptr)->x;\r
- SHP->bmHdr.y = ((struct BitMapHeader far *)ptr)->y;\r
- SHP->bmHdr.d = ((struct BitMapHeader far *)ptr)->d;\r
- SHP->bmHdr.trans = ((struct BitMapHeader far *)ptr)->trans;\r
- SHP->bmHdr.comp = ((struct BitMapHeader far *)ptr)->comp;\r
- SHP->bmHdr.pad = ((struct BitMapHeader far *)ptr)->pad;\r
- SwapWord(&SHP->bmHdr.w);\r
- SwapWord(&SHP->bmHdr.h);\r
- SwapWord(&SHP->bmHdr.x);\r
- SwapWord(&SHP->bmHdr.y);\r
- ptr += ChunkLen;\r
- }\r
- else\r
- if (CHUNK("BODY"))\r
- {\r
- ptr += 4;\r
- size = *((long far *)ptr);\r
- ptr += 4;\r
- SwapLong((long far *)&size);\r
- SHP->BPR = (SHP->bmHdr.w+7) >> 3;\r
- MM_GetPtr(&SHP->Data,size);\r
- if (!SHP->Data)\r
- goto EXIT_FUNC;\r
- movedata(FP_SEG(ptr),FP_OFF(ptr),FP_SEG(SHP->Data),0,size);\r
- ptr += ChunkLen;\r
-\r
- break;\r
- }\r
- else\r
- ptr += ChunkLen+8;\r
-\r
- FileLen -= ChunkLen+8;\r
- }\r
-\r
- RT_CODE = 0;\r
-\r
-EXIT_FUNC:;\r
- if (IFFfile)\r
- {\r
-// segptr = (memptr)FP_SEG(IFFfile);\r
- MM_FreePtr(&IFFfile);\r
- }\r
-\r
- return (RT_CODE);\r
-}\r
-\r
-\r
-\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-// LoadLIBFile() -- Copies a file from an existing archive to dos.\r
-//\r
-// PARAMETERS :\r
-//\r
-// LibName - Name of lib file created with SoftLib V1.0\r
-//\r
-// FileName - Name of file to load from lib file.\r
-//\r
-// MemPtr - (IF !NULL) - Pointer to memory to load into ..\r
-// (IF NULL) - Routine allocates necessary memory and\r
-// returns a MEM(SEG) pointer to memory allocated.\r
-//\r
-// RETURN :\r
-//\r
-// (IF !NULL) - A pointer to the loaded data.\r
-// (IF NULL) - Error!\r
-//\r
-//----------------------------------------------------------------------------\r
-memptr LoadLIBFile(char *LibName,char *FileName,memptr *MemPtr)\r
-{\r
- int handle;\r
- unsigned long header;\r
- struct ChunkHeader Header;\r
- unsigned long ChunkLen;\r
- short x;\r
- struct FileEntryHdr FileEntry; // Storage for file once found\r
- struct FileEntryHdr FileEntryHeader; // Header used durring searching\r
- struct SoftLibHdr LibraryHeader; // Library header - Version Checking\r
- boolean FileFound = false;\r
- unsigned long id_slib = ID_SLIB;\r
- unsigned long id_chunk = ID_CHUNK;\r
-\r
-\r
- //\r
- // OPEN SOFTLIB FILE\r
- //\r
-\r
- if ((handle = open(LibName,O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- return(NULL);\r
-\r
-\r
- //\r
- // VERIFY it is a SOFTLIB (SLIB) file\r
- //\r
-\r
- if (read(handle,&header,4) == -1)\r
- {\r
- close(handle);\r
- return(NULL);\r
- }\r
-\r
- if (header != id_slib)\r
- {\r
- close(handle);\r
- return(NULL);\r
- }\r
-\r
-\r
- //\r
- // CHECK LIBRARY HEADER VERSION NUMBER\r
- //\r
-\r
- if (read(handle, &LibraryHeader,sizeof(struct SoftLibHdr)) == -1)\r
- TrashProg("read error in LoadSLIBFile()\n%c",7);\r
-\r
- if (LibraryHeader.Version > SOFTLIB_VER)\r
- TrashProg("Unsupported file ver %d",LibraryHeader.Version);\r
-\r
-\r
- //\r
- // MANAGE FILE ENTRY HEADERS...\r
- //\r
-\r
- for (x = 1;x<=LibraryHeader.FileCount;x++)\r
- {\r
- if (read(handle, &FileEntryHeader,sizeof(struct FileEntryHdr)) == -1)\r
- {\r
- close(handle);\r
- return(NULL);\r
- }\r
-\r
- if (!stricmp(FileEntryHeader.FileName,FileName))\r
- {\r
- FileEntry = FileEntryHeader;\r
- FileFound = true;\r
- }\r
- }\r
-\r
- //\r
- // IF FILE HAS BEEN FOUND THEN SEEK TO POSITION AND EXTRACT\r
- // ELSE RETURN WITH ERROR CODE...\r
- //\r
-\r
- if (FileFound)\r
- {\r
- if (lseek(handle,FileEntry.Offset,SEEK_CUR) == -1)\r
- {\r
- close(handle);\r
- return(NULL);\r
- }\r
-\r
- //\r
- // READ CHUNK HEADER - Verify we are at the beginning of a chunk..\r
- //\r
-\r
- if (read(handle,(char *)&Header,sizeof(struct ChunkHeader)) == -1)\r
- TrashProg("LIB File - Unable to read Header!");\r
-\r
- if (Header.HeaderID != id_chunk)\r
- TrashProg("LIB File - BAD HeaderID!");\r
-\r
- //\r
- // Allocate memory if Necessary...\r
- //\r
-\r
-\r
- if (!*MemPtr)\r
- MM_GetPtr(MemPtr,FileEntry.OrginalLength);\r
-\r
- //\r
- // Calculate the length of the data (without the chunk header).\r
- //\r
-\r
- ChunkLen = FileEntry.ChunkLen - sizeof(struct ChunkHeader);\r
-\r
-\r
- //\r
- // Extract Data from file\r
- //\r
-\r
- switch (Header.Compression)\r
- {\r
- case ct_LZW:\r
- if (!InitBufferedIO(handle,&lzwBIO))\r
- TrashProg("No memory for buffered I/O.");\r
- lzwDecompress(&lzwBIO,MK_FP(*MemPtr,0),ChunkLen,(SRC_BFILE|DEST_MEM));\r
- FreeBufferedIO(&lzwBIO);\r
- break;\r
-\r
- case ct_NONE:\r
- if (!CA_FarRead(handle,MK_FP(*MemPtr,0),ChunkLen))\r
- {\r
- close(handle);\r
- *MemPtr = NULL;\r
- }\r
- break;\r
-\r
- default:\r
- close(handle);\r
- TrashProg("Uknown Chunk.Compression Type!");\r
- break;\r
- }\r
- }\r
- else\r
- *MemPtr = NULL;\r
-\r
- close(handle);\r
- return(*MemPtr);\r
-}\r
-\r
-\r
-\r
-\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//\r
-//\r
-//\r
-//\r
-//\r
-\r
-\r
-#define LZW_N 4096\r
-#define LZW_F 18\r
-\r
-\r
-// LZW_THRESHOLD :encode string into position and length if match_length is\r
-// greater than this\r
-\r
-#define LZW_THRESHOLD 2\r
-\r
-// index for root of binary search trees\r
-//\r
-\r
-#define LZW_NIL LZW_N\r
-\r
-\r
-//\r
-// FILE CHUNK IDs\r
-//\r
-// NOTE: The only reason for changing from COMP to CMP2 and having multi\r
-// comp header structs is for downward compatablity.\r
-//\r
-\r
-#define COMP ("COMP") // Comp type is ct_LZW ALWAYS!\r
-#define CMP2 ("CMP2") // Comp type is determined in header.\r
-\r
-\r
-//\r
-// COMPRESSION TYPES\r
-//\r
-\r
-#if 0\r
-//\r
-// FILE CHUNK HEADER FORMATS\r
-//\r
-\r
-struct COMPStruct\r
-{\r
- unsigned long DecompLen;\r
-\r
-};\r
-\r
-\r
-struct CMP2Header\r
-{\r
- unsigned CompType;\r
- unsigned long DecompLen;\r
-\r
-};\r
-#endif\r
-\r
-memptr segptr;\r
-extern BufferedIO lzwBIO;\r
-\r
-\r
-//\r
-// PARAMETER PASSING TYPES (POINTER TYPES)\r
-//\r
-\r
-#define SRC_FILE (0x0001) // C's non-buffered file i/o\r
-#define SRC_FFILE (0x0002) // C's buffered ffile i/o\r
-#define SRC_MEM (0x0004) // FAR memory Ptrs\r
-#define SRC_BFILE (0x0008) // Buffered File I/O\r
-\r
-#define SRC_TYPES (SRC_FILE | SRC_FFILE | SRC_MEM | SRC_BFILE)\r
-\r
-#define DEST_FILE (0x0100) // C's non-buffered file i/o\r
-#define DEST_FFILE (0x0200) // C's buffered ffile i/o\r
-#define DEST_MEM (0x0400) // FAR memory Ptrs\r
-\r
-#define DEST_TYPES (DEST_FILE | DEST_FFILE | DEST_MEM)\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// FUNCTION PROTOTYPEING\r
-//---------------------------------------------------------------------------\r
-\r
-//void DecompressFILEtoFILE(FILE *infile, FILE *outfile);\r
-//unsigned long CompressFILEtoFILE(FILE *infile, FILE *outfile,unsigned long DataLength);\r
-\r
-\r
-unsigned long lzwCompress(void far *infile, void far *outfile,unsigned long DataLength,unsigned PtrTypes);\r
-void lzwDecompress(void far *infile, void far *outfile,unsigned long DataLength,unsigned PtrTypes);\r
-\r
-int WritePtr(long outfile, unsigned char data, unsigned PtrType);\r
-int ReadPtr(long infile, unsigned PtrType);\r
-\r
-//memptr InitBufferedIO(int handle, BufferedIO *bio);\r
-//void FreeBufferedIO(BufferedIO *bio);\r
-//byte bio_readch(BufferedIO *bio);\r
-\r
-unsigned long BLoad(char *SourceFile, memptr *DstPtr);\r
-memptr LoadLIBFile(char *LibName,char *FileName,memptr *MemPtr);\r
-int LoadLIBShape(char *SLIB_Filename, char *Filename,struct Shape *SHP);\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <ctype.h>\r
-#include <alloc.h>\r
-#include <fcntl.h>\r
-#include <dos.h>\r
-#include <io.h>\r
-\r
-#include "def.h"\r
-#include "gelib.h"\r
-#include "jam_io.h"\r
-\r
-//----------------------------------------------------------------------------\r
-//\r
-// PTR/PTR COMPRESSION ROUTINES\r
-//\r
-//\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// WritePtr() -- Outputs data to a particular ptr type\r
-//\r
-// PtrType MUST be of type DEST_TYPE.\r
-//\r
-// NOTE : For PtrTypes DEST_MEM a ZERO (0) is always returned.\r
-//\r
-//---------------------------------------------------------------------------\r
-char WritePtr(long outfile, unsigned char data, unsigned PtrType)\r
-{\r
- int returnval = 0;\r
-\r
- switch (PtrType & DEST_TYPES)\r
- {\r
- case DEST_FILE:\r
- write(*(int far *)outfile,(char *)&data,1);\r
- break;\r
-\r
- case DEST_FFILE:\r
- returnval = putc(data, *(FILE **)outfile);\r
- break;\r
-\r
- case DEST_IMEM:\r
- printf("WritePtr - unsupported ptr type\n");\r
- exit(0);\r
- break;\r
-\r
- case DEST_MEM:\r
- *((char far *)*(char far **)outfile)++ = data;\r
- break;\r
- }\r
-\r
- return(returnval);\r
-\r
-}\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// ReadPtr() -- Reads data from a particular ptr type\r
-//\r
-// PtrType MUST be of type SRC_TYPE.\r
-//\r
-// RETURNS :\r
-// The char read in or EOF for SRC_FFILE type of reads.\r
-//\r
-//\r
-//---------------------------------------------------------------------------\r
-int ReadPtr(long infile, unsigned PtrType)\r
-{\r
- int returnval = 0;\r
-\r
- switch (PtrType & SRC_TYPES)\r
- {\r
- case SRC_FILE:\r
- read(*(int far *)infile,(char *)&returnval,1);\r
- break;\r
-\r
- case SRC_FFILE:\r
- returnval = getc(*(FILE far **)infile\r
- );\r
- break;\r
-\r
- case SRC_BFILE:\r
- returnval = bio_readch((BufferedIO *)*(void far **)infile);\r
- break;\r
-\r
-// case SRC_IMEM:\r
-// printf("WritePtr - unsupported ptr type\n");\r
-// exit(0);\r
-// break;\r
-\r
- case SRC_MEM:\r
- returnval = (unsigned char)*((char far *)*(char far **)infile)++;\r
- break;\r
- }\r
-\r
- return(returnval);\r
-}\r
-\r
-\r
-\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//\r
-// UNIT : JAM_IO.h\r
-//\r
-// FUNCTION : General defines, prototypes, typedefs used in all the\r
-// supported compression techniques used in JAMPAK Ver x.x\r
-//\r
-//\r
-\r
-\r
-\r
-\r
-//==========================================================================\r
-//\r
-// PARAMETER PASSING TYPES\r
-//\r
-//\r
- // SOURCE PARAMS (LO BYTE)\r
-\r
-#define SRC_FILE (0x0001) // GE Buffered IO\r
-#define SRC_FFILE (0x0002) // Stdio File IO (fwrite etc.)\r
-#define SRC_MEM (0x0004) // Std void ptr (alloc etc)\r
-#define SRC_BFILE (0x0008) // Buffered File I/O\r
-\r
-#define SRC_TYPES (SRC_FILE | SRC_FFILE | SRC_MEM | SRC_BFILE)\r
-\r
- // DESTINATION PARAMS (HI BYTE)\r
-\r
-#define DEST_FILE (0x0100) // GE Buffered IO\r
-#define DEST_FFILE (0x0200) // Stdio File IO (fwrite etc.)\r
-#define DEST_MEM (0x0400) // Std void ptr (alloc etc)\r
-#define DEST_IMEM (0x0800) // ID Memory alloc\r
-\r
-#define DEST_TYPES (DEST_FILE | DEST_FFILE | DEST_MEM | DEST_IMEM)\r
-\r
-\r
-\r
-//=========================================================================\r
-//\r
-// FILE CHUNK IDs\r
-//\r
-// NOTE: The only reason for changing from COMP to CMP1 and having multi\r
-// comp header structs is for downward compatablity.\r
-//\r
-\r
-#define COMP ("COMP") // Comp type is ct_LZW ALWAYS!\r
-#define CMP1 ("CMP1") // Comp type is determined in header.\r
-\r
-\r
-//\r
-// COMPRESSION TYPES\r
-//\r
-typedef enum ct_TYPES\r
-{\r
- ct_NONE = 0, // No compression - Just data..Rarely used!\r
- ct_LZW, // LZW data compression\r
- ct_LZH,\r
-\r
-} ct_TYPES;\r
-\r
-//\r
-// FILE CHUNK HEADER FORMATS\r
-//\r
-\r
-struct COMPStruct\r
-{\r
- unsigned long DecompLen;\r
-\r
-};\r
-\r
-\r
-struct CMP1Header\r
-{\r
- unsigned CompType; // SEE: ct_TYPES above for list of pos.\r
- unsigned long OrginalLen; // Orginal FileLength of compressed Data.\r
- unsigned long CompressLen; // Length of data after compression (A MUST for LZHUFF!)\r
-};\r
-\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-//\r
-// FUNCTION PROTOTYPEING\r
-//\r
-//---------------------------------------------------------------------------\r
-\r
-char WritePtr(long outfile, unsigned char data, unsigned PtrType);\r
-int ReadPtr(long infile, unsigned PtrType);\r
-\r
-\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//===========================================================================\r
-//\r
-// LZHUFF COMPRESSION ROUTINES\r
-// VERSION 1.0\r
-//\r
-// Compression algrythim by Haruhiko OKUMURA\r
-// Implementation by Jim T. Row\r
-//\r
-//\r
-// Copyright (c) 1992 - Softdisk Publishing inc. - All rights reserved\r
-//\r
-//===========================================================================\r
-//\r
-// Compiler #ifdef switches\r
-//\r
-// LZHUFF_COMPRESSION & LZHUFF_DECOMPRESSION - not yet functional!\r
-//\r
-// Usage Explanition :\r
-//\r
-// if LZHUFF_COMPRESSION is defined then the compression code & data is\r
-// compiled and so-forth for the decompression code.\r
-//\r
-//---------------------------------------------------------------------------\r
-\r
-\r
-\r
-#include <fcntl.h>\r
-#include <io.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <ctype.h>\r
-#include <alloc.h>\r
-#include <dos.h>\r
-\r
-#include "lzhuff.h"\r
-#include "jam_io.h"\r
-\r
-\r
-\r
-//===========================================================================\r
-//\r
-// SWITCHES\r
-//\r
-// NOTE : Make sure the appropriate switches are set in SOFT.c for Softlib\r
-// archive support.\r
-//\r
-//===========================================================================\r
-\r
-\r
-#define INCLUDE_LZH_COMP 0\r
-#define INCLUDE_LZH_DECOMP 1\r
-\r
-\r
-\r
-\r
-\r
-//===========================================================================\r
-//\r
-// DEFINES\r
-//\r
-//===========================================================================\r
-\r
-\r
-#define EXIT_OK 0\r
-#define EXIT_FAILED -1\r
-\r
-/* LZSS Parameters */\r
-\r
-#define N 4096 /* Size of string buffer */\r
-#define F 30 /* Size of look-ahead buffer */\r
-#define THRESHOLD 2\r
-#define NIL N /* End of tree's node */\r
-\r
-/* Huffman coding parameters */\r
-\r
-#define N_CHAR (256 - THRESHOLD + F) /* character code (= 0..N_CHAR-1) */\r
-#define T (N_CHAR * 2 - 1) /* Size of table */\r
-#define R (T - 1) /* root position */\r
-#define MAX_FREQ 0x8000 /* update when cumulative frequency */\r
- /* reaches to this value */\r
-\r
-\r
-//==========================================================================\r
-//\r
-// LOCAL PROTOTYPES\r
-//\r
-//==========================================================================\r
-\r
-\r
-static void StartHuff();\r
-static void reconst();\r
-static void update(int c);\r
-\r
-\r
-static void DeleteNode(int p); /* Deleting node from the tree */\r
-static void InsertNode(int r); /* Inserting node to the tree */\r
-static void InitTree(void); /* Initializing tree */\r
-static void Putcode(long outfile_ptr, int l, unsigned c,unsigned PtrTypes); /* output c bits */\r
-static void EncodeChar(long outfile_ptr, unsigned c, unsigned PtrTypes);\r
-static void EncodePosition(long outfile_ptr, unsigned c, unsigned PtrTypes);\r
-static void EncodeEnd(long outfile_ptr,unsigned PtrTypes);\r
-\r
-\r
-static int GetByte(long infile_ptr, unsigned long *CompressLength, unsigned PtrTypes);\r
-static int GetBit(long infile_ptr, unsigned long *CompressLength, unsigned PtrTypes); /* get one bit */\r
-static int DecodeChar(long infile_ptr, unsigned long *CompressLength, unsigned PtrTypes);\r
-static int DecodePosition(long infile_ptr,unsigned long *CompressLength, unsigned PtrTypes);\r
-\r
-\r
-\r
-\r
-//==========================================================================\r
-//\r
-// USER AVAILABLE VECTORS\r
-//\r
-//==========================================================================\r
-\r
-\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-//\r
-// LZHUFF DISPLAY VECTORS\r
-//\r
-// These vectors allow you to hook up any form of display you desire for\r
-// displaying the compression/decompression status.\r
-//\r
-// These routines are called inside of the compression/decompression routines\r
-// and pass the orginal size of data and current position within that\r
-// data. This allows for any kind of "% Done" messages.\r
-//\r
-// Your functions MUST have the following parameters in this order...\r
-//\r
-// void VectorRoutine(unsigned long OrginalSize,unsigned long CurPosition)\r
-//\r
-//\r
-\r
-#if INCLUDE_LZH_COMP\r
-void (*LZH_CompressDisplayVector)() = NULL;\r
-#endif\r
-\r
-#if INCLUDE_LZH_DECOMP\r
-void (*LZH_DecompressDisplayVector)() = NULL;\r
-#endif\r
-\r
-\r
-\r
-\r
-//===========================================================================\r
-//\r
-// GLOBAL VARIABLES\r
-//\r
-//===========================================================================\r
- /* pointing children nodes (son[], son[] + 1)*/\r
-\r
-int far son[T];\r
-unsigned code, len;\r
-\r
- //\r
- // pointing parent nodes.\r
- // area [T..(T + N_CHAR - 1)] are pointers for leaves\r
- //\r
-\r
-int far prnt[T + N_CHAR];\r
-\r
-unsigned far freq[T + 1]; /* cumulative freq table */\r
-\r
-unsigned long textsize = 0, codesize = 0, printcount = 0,datasize;\r
-unsigned char far text_buf[N + F - 1];\r
-\r
-\r
-\r
- //\r
- // COMPRESSION VARIABLES\r
- //\r
-\r
-#if INCLUDE_LZH_COMP\r
-\r
-static int match_position,match_length, lson[N + 1], rson[N + 257], dad[N + 1];\r
-unsigned putbuf = 0;\r
-unsigned char putlen = 0;\r
-\r
- //\r
- // Tables for encoding/decoding upper 6 bits of\r
- // sliding dictionary pointer\r
- //\r
-\r
- //\r
- // encoder table\r
- //\r
-\r
-unsigned char far p_len[64] = {\r
- 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,\r
- 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,\r
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,\r
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,\r
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,\r
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,\r
- 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,\r
- 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08\r
-};\r
-\r
-unsigned char far p_code[64] = {\r
- 0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,\r
- 0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,\r
- 0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,\r
- 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,\r
- 0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,\r
- 0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,\r
- 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,\r
- 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF\r
-};\r
-#endif\r
-\r
-\r
- //\r
- // DECOMPRESSION VARIABLES\r
- //\r
-\r
-\r
- //\r
- // decoder table\r
- //\r
-\r
-#if INCLUDE_LZH_DECOMP\r
-\r
-unsigned char far d_code[256] = {\r
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\r
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\r
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\r
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,\r
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,\r
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,\r
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,\r
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\r
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,\r
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,\r
- 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,\r
- 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,\r
- 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,\r
- 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,\r
- 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,\r
- 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,\r
- 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,\r
- 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,\r
- 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,\r
- 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,\r
- 0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,\r
- 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,\r
- 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,\r
- 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,\r
- 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,\r
- 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,\r
- 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,\r
- 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,\r
-};\r
-\r
-unsigned char far d_len[256] = {\r
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,\r
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,\r
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,\r
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,\r
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,\r
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,\r
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,\r
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,\r
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,\r
- 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,\r
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\r
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\r
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\r
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\r
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\r
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\r
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\r
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,\r
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,\r
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,\r
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,\r
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,\r
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,\r
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,\r
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,\r
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,\r
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,\r
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,\r
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,\r
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,\r
- 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,\r
- 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,\r
-};\r
-\r
-unsigned getbuf = 0;\r
-unsigned char getlen = 0;\r
-\r
-#endif\r
-\r
-\r
-\r
-//===========================================================================\r
-//\r
-// COMPRESSION & DECOMPRESSION ROUTINES\r
-//\r
-//===========================================================================\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// StartHuff /* initialize freq tree */\r
-//---------------------------------------------------------------------------\r
-static void StartHuff()\r
-{\r
- int i, j;\r
-\r
- for (i = 0; i < N_CHAR; i++) {\r
- freq[i] = 1;\r
- son[i] = i + T;\r
- prnt[i + T] = i;\r
- }\r
- i = 0; j = N_CHAR;\r
- while (j <= R) {\r
- freq[j] = freq[i] + freq[i + 1];\r
- son[j] = i;\r
- prnt[i] = prnt[i + 1] = j;\r
- i += 2; j++;\r
- }\r
- freq[T] = 0xffff;\r
- prnt[R] = 0;\r
-}\r
-\r
-\r
-\r
-\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// reconst /* reconstruct freq tree */\r
-//---------------------------------------------------------------------------\r
-static void reconst()\r
-{\r
- int i, j, k;\r
- unsigned f, l;\r
-\r
- /* halven cumulative freq for leaf nodes */\r
-\r
- j = 0;\r
-\r
- for (i = 0; i < T; i++)\r
- {\r
- if (son[i] >= T)\r
- {\r
- freq[j] = (freq[i] + 1) / 2;\r
- son[j] = son[i];\r
- j++;\r
- }\r
- }\r
-\r
- /* make a tree : first, connect children nodes */\r
-\r
- for (i = 0, j = N_CHAR; j < T; i += 2, j++)\r
- {\r
- k = i + 1;\r
- f = freq[j] = freq[i] + freq[k];\r
-\r
- for (k = j - 1;f < freq[k]; k--);\r
-\r
- k++;\r
- l = (j - k) * 2;\r
-\r
- (void)memmove(&freq[k + 1], &freq[k], l);\r
- freq[k] = f;\r
-\r
- (void)memmove(&son[k + 1], &son[k], l);\r
- son[k] = i;\r
- }\r
-\r
- /* connect parent nodes */\r
-\r
- for (i = 0; i < T; i++)\r
- {\r
- if ((k = son[i]) >= T)\r
- {\r
- prnt[k] = i;\r
- }\r
- else\r
- {\r
- prnt[k] = prnt[k + 1] = i;\r
- }\r
- }\r
-}\r
-\r
-\r
-\r
-\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// update() update freq tree\r
-//---------------------------------------------------------------------------\r
-static void update(int c)\r
-{\r
- int i, j, k, l;\r
-\r
- if (freq[R] == MAX_FREQ)\r
- {\r
- reconst();\r
- }\r
-\r
- c = prnt[c + T];\r
-\r
- do {\r
- k = ++freq[c];\r
-\r
- //\r
- // swap nodes to keep the tree freq-ordered\r
- //\r
-\r
- if (k > freq[l = c + 1])\r
- {\r
- while (k > freq[++l]);\r
-\r
- l--;\r
- freq[c] = freq[l];\r
- freq[l] = k;\r
-\r
- i = son[c];\r
- prnt[i] = l;\r
- if (i < T)\r
- prnt[i + 1] = l;\r
-\r
- j = son[l];\r
- son[l] = i;\r
-\r
- prnt[j] = c;\r
- if (j < T)\r
- prnt[j + 1] = c;\r
-\r
- son[c] = j;\r
-\r
- c = l;\r
- }\r
- } while ((c = prnt[c]) != 0); /* do it until reaching the root */\r
-}\r
-\r
-\r
-\r
-\r
-//===========================================================================\r
-//\r
-// COMPRESSION ROUTINES\r
-//\r
-//===========================================================================\r
-\r
-\r
-\r
-\r
-\r
-\r
-#if INCLUDE_LZH_COMP\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// DeleteNode\r
-//---------------------------------------------------------------------------\r
-static void DeleteNode(int p) /* Deleting node from the tree */\r
-{\r
- int q;\r
-\r
- if (dad[p] == NIL)\r
- return; /* unregistered */\r
-\r
- if (rson[p] == NIL)\r
- q = lson[p];\r
- else\r
- if (lson[p] == NIL)\r
- q = rson[p];\r
- else\r
- {\r
- q = lson[p];\r
- if (rson[q] != NIL)\r
- {\r
- do {\r
- q = rson[q];\r
- } while (rson[q] != NIL);\r
-\r
- rson[dad[q]] = lson[q];\r
- dad[lson[q]] = dad[q];\r
- lson[q] = lson[p];\r
- dad[lson[p]] = q;\r
- }\r
-\r
- rson[q] = rson[p];\r
- dad[rson[p]] = q;\r
- }\r
-\r
- dad[q] = dad[p];\r
-\r
- if (rson[dad[p]] == p)\r
- rson[dad[p]] = q;\r
- else\r
- lson[dad[p]] = q;\r
-\r
- dad[p] = NIL;\r
-}\r
-\r
-\r
-\r
-\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// InsertNode\r
-//---------------------------------------------------------------------------\r
-static void InsertNode(int r) /* Inserting node to the tree */\r
-{\r
- int i, p, cmp;\r
- unsigned char *key;\r
- unsigned c;\r
-\r
- cmp = 1;\r
- key = &text_buf[r];\r
- p = N + 1 + key[0];\r
- rson[r] = lson[r] = NIL;\r
- match_length = 0;\r
- for ( ; ; )\r
- {\r
- if (cmp >= 0)\r
- {\r
- if (rson[p] != NIL)\r
- p = rson[p];\r
- else\r
- {\r
- rson[p] = r;\r
- dad[r] = p;\r
- return;\r
- }\r
- }\r
- else\r
- {\r
- if (lson[p] != NIL)\r
- p = lson[p];\r
- else\r
- {\r
- lson[p] = r;\r
- dad[r] = p;\r
- return;\r
- }\r
- }\r
-\r
-\r
- for (i = 1; i < F; i++)\r
- if ((cmp = key[i] - text_buf[p + i]) != 0)\r
- break;\r
-\r
- if (i > THRESHOLD)\r
- {\r
- if (i > match_length)\r
- {\r
- match_position = ((r - p) & (N - 1)) - 1;\r
- if ((match_length = i) >= F)\r
- break;\r
- }\r
-\r
- if (i == match_length)\r
- {\r
- if ((c = ((r - p) & (N - 1)) - 1) < match_position)\r
- {\r
- match_position = c;\r
- }\r
- }\r
- }\r
- }\r
-\r
- dad[r] = dad[p];\r
- lson[r] = lson[p];\r
- rson[r] = rson[p];\r
- dad[lson[p]] = r;\r
- dad[rson[p]] = r;\r
-\r
- if (rson[dad[p]] == p)\r
- rson[dad[p]] = r;\r
- else\r
- lson[dad[p]] = r;\r
-\r
- dad[p] = NIL; /* remove p */\r
-}\r
-\r
-\r
-\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// InitTree\r
-//---------------------------------------------------------------------------\r
-static void InitTree(void) /* Initializing tree */\r
-{\r
- int i;\r
-\r
- for (i = N + 1; i <= N + 256; i++)\r
- rson[i] = NIL; /* root */\r
-\r
- for (i = 0; i < N; i++)\r
- dad[i] = NIL; /* node */\r
-}\r
-\r
-\r
-\r
-\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// Putcode\r
-//---------------------------------------------------------------------------\r
-static void Putcode(long outfile_ptr, int l, unsigned c,unsigned PtrTypes) /* output c bits */\r
-{\r
- putbuf |= c >> putlen;\r
-\r
- if ((putlen += l) >= 8)\r
- {\r
- WritePtr(outfile_ptr, putbuf >> 8, PtrTypes);\r
- codesize++;\r
-\r
- if ((putlen -= 8) >= 8)\r
- {\r
- WritePtr(outfile_ptr, putbuf, PtrTypes);\r
- codesize++;\r
-\r
- putlen -= 8;\r
- putbuf = c << (l - putlen);\r
- }\r
- else\r
- {\r
- putbuf <<= 8;\r
- }\r
- }\r
-}\r
-\r
-\r
-\r
-\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// EncodeChar\r
-//---------------------------------------------------------------------------\r
-static void EncodeChar(long outfile_ptr, unsigned c, unsigned PtrTypes)\r
-{\r
- unsigned i;\r
- int j, k;\r
-\r
- i = 0;\r
- j = 0;\r
- k = prnt[c + T];\r
-\r
- /* search connections from leaf node to the root */\r
-\r
- do {\r
- i >>= 1;\r
-\r
- //\r
- // if node's address is odd, output 1 else output 0\r
- //\r
-\r
- if (k & 1)\r
- i += 0x8000;\r
-\r
- j++;\r
- } while ((k = prnt[k]) != R);\r
-\r
- Putcode(outfile_ptr, j, i, PtrTypes);\r
-\r
- code = i;\r
- len = j;\r
- update(c);\r
-}\r
-\r
-\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// EncodePosition\r
-//---------------------------------------------------------------------------\r
-static void EncodePosition(long outfile_ptr, unsigned c, unsigned PtrTypes)\r
-{\r
- unsigned i;\r
-\r
- //\r
- // output upper 6 bits with encoding\r
- //\r
-\r
- i = c >> 6;\r
- Putcode(outfile_ptr, p_len[i], (unsigned)p_code[i] << 8,PtrTypes);\r
-\r
- //\r
- // output lower 6 bits directly\r
- //\r
-\r
- Putcode(outfile_ptr, 6, (c & 0x3f) << 10,PtrTypes);\r
-}\r
-\r
-\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// EncodeEnd\r
-//---------------------------------------------------------------------------\r
-static void EncodeEnd(long outfile_ptr,unsigned PtrTypes)\r
-{\r
- if (putlen)\r
- {\r
- WritePtr(outfile_ptr,(putbuf >> 8),PtrTypes);\r
- codesize++;\r
- }\r
-}\r
-\r
-#endif\r
-\r
-\r
-\r
-\r
-\r
-//===========================================================================\r
-//\r
-// DECOMPRESSION ROUTINES\r
-//\r
-//===========================================================================\r
-\r
-\r
-\r
-#if INCLUDE_LZH_DECOMP\r
-\r
-//---------------------------------------------------------------------------\r
-// GetByte\r
-//---------------------------------------------------------------------------\r
-static int GetByte(long infile_ptr, unsigned long *CompressLength, unsigned PtrTypes)\r
-{\r
- unsigned i;\r
-\r
- while (getlen <= 8)\r
- {\r
- if (*CompressLength)\r
- {\r
- i = ReadPtr(infile_ptr,PtrTypes);\r
- (*CompressLength)--;\r
- }\r
- else\r
- i = 0;\r
-\r
- getbuf |= i << (8 - getlen);\r
- getlen += 8;\r
- }\r
-\r
- i = getbuf;\r
- getbuf <<= 8;\r
- getlen -= 8;\r
- return i>>8;\r
-}\r
-\r
-\r
-\r
-\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// GetBit\r
-//---------------------------------------------------------------------------\r
-static int GetBit(long infile_ptr, unsigned long *CompressLength, unsigned PtrTypes) /* get one bit */\r
-{\r
- int i;\r
-\r
- while (getlen <= 8)\r
- {\r
- if (*CompressLength)\r
- {\r
- i = ReadPtr(infile_ptr,PtrTypes);\r
- (*CompressLength)--;\r
- }\r
- else\r
- i = 0;\r
-\r
- getbuf |= i << (8 - getlen);\r
- getlen += 8;\r
- }\r
-\r
- i = getbuf;\r
- getbuf <<= 1;\r
- getlen--;\r
- return (i < 0);\r
-}\r
-\r
-\r
-\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// DecodeChar\r
-//---------------------------------------------------------------------------\r
-static int DecodeChar(long infile_ptr, unsigned long *CompressLength, unsigned PtrTypes)\r
-{\r
- unsigned c;\r
-\r
- c = son[R];\r
-\r
- /*\r
- * start searching tree from the root to leaves.\r
- * choose node #(son[]) if input bit == 0\r
- * else choose #(son[]+1) (input bit == 1)\r
- */\r
-\r
- while (c < T)\r
- {\r
- c += GetBit(infile_ptr,CompressLength,PtrTypes);\r
- c = son[c];\r
- }\r
-\r
- c -= T;\r
- update(c);\r
- return c;\r
-}\r
-\r
-\r
-\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-// DecodePosition\r
-//---------------------------------------------------------------------------\r
-static int DecodePosition(long infile_ptr,unsigned long *CompressLength, unsigned PtrTypes)\r
-{\r
- unsigned i, j, c;\r
-\r
- //\r
- // decode upper 6 bits from given table\r
- //\r
-\r
- i = GetByte(infile_ptr, CompressLength, PtrTypes);\r
- c = (unsigned)d_code[i] << 6;\r
- j = d_len[i];\r
-\r
- //\r
- // input lower 6 bits directly\r
- //\r
-\r
- j -= 2;\r
- while (j--)\r
- {\r
- i = (i << 1) + GetBit(infile_ptr, CompressLength, PtrTypes);\r
- }\r
-\r
- return c | i & 0x3f;\r
-}\r
-\r
-#endif\r
-\r
-\r
-\r
-\r
-\r
-//===========================================================================\r
-//\r
-// EXTERNAL REFERENCED\r
-// COMPRESSION & DECOMPRESSION\r
-// ROUTINES\r
-//\r
-//===========================================================================\r
-\r
-\r
-\r
-\r
-#if INCLUDE_LZH_DECOMP\r
-\r
-//---------------------------------------------------------------------------\r
-// lzhDecompress()\r
-//---------------------------------------------------------------------------\r
-long lzhDecompress(void far *infile, void far *outfile, unsigned long OrginalLength, unsigned long CompressLength, unsigned PtrTypes)\r
-{\r
- int i, j, k, r, c;\r
- long count;\r
-\r
- datasize = textsize = OrginalLength;\r
- getbuf = 0;\r
- getlen = 0;\r
-\r
- if (textsize == 0)\r
- return;\r
-\r
- StartHuff();\r
- for (i = 0; i < N - F; i++)\r
- text_buf[i] = ' ';\r
-\r
- r = N - F;\r
-\r
- for (count = 0; count < textsize; )\r
- {\r
- c = DecodeChar((long)&infile,&CompressLength,PtrTypes);\r
-\r
- if (c < 256)\r
- {\r
- WritePtr((long)&outfile,c,PtrTypes);\r
- datasize--; // Dec # of bytes to write\r
-\r
- text_buf[r++] = c;\r
- r &= (N - 1);\r
- count++; // inc count of bytes written\r
- }\r
- else\r
- {\r
- i = (r - DecodePosition((long)&infile,&CompressLength,PtrTypes) - 1) & (N - 1);\r
- j = c - 255 + THRESHOLD;\r
-\r
- for (k = 0; k < j; k++)\r
- {\r
- c = text_buf[(i + k) & (N - 1)];\r
-\r
- WritePtr((long)&outfile,c,PtrTypes);\r
- datasize--; // dec count of bytes to write\r
-\r
- text_buf[r++] = c;\r
- r &= (N - 1);\r
- count++; // inc count of bytes written\r
- }\r
- }\r
-\r
- if (LZH_DecompressDisplayVector && (count > printcount))\r
- {\r
- LZH_DecompressDisplayVector(OrginalLength,OrginalLength-datasize);\r
- printcount += 1024;\r
- }\r
- }\r
-\r
-// printf("%12ld\n", count);\r
-\r
- return(count);\r
-}\r
-\r
-#endif\r
-\r
-\r
-\r
-\r
-\r
-#if INCLUDE_LZH_COMP\r
-\r
-//---------------------------------------------------------------------------\r
-// lzhCompress()\r
-//---------------------------------------------------------------------------\r
-long lzhCompress(void far *infile, void far *outfile,unsigned long DataLength,unsigned PtrTypes)\r
-{\r
- int i, c, len, r, s, last_match_length;\r
-\r
- textsize = DataLength;\r
-\r
- if (textsize == 0)\r
- return;\r
-\r
- getbuf = 0;\r
- getlen = 0;\r
- textsize = 0; /* rewind and rescan */\r
- codesize = 0;\r
- datasize = 0; // Init our counter of ReadData...\r
- StartHuff();\r
- InitTree();\r
-\r
- s = 0;\r
- r = N - F;\r
-\r
- for (i = s; i < r; i++)\r
- text_buf[i] = ' ';\r
-\r
- for (len = 0; len < F && (DataLength > datasize); len++)\r
- {\r
- c = ReadPtr((long)&infile,PtrTypes);\r
- datasize++; // Dec num of bytes to compress\r
- text_buf[r + len] = c;\r
- }\r
-\r
- textsize = len;\r
-\r
- for (i = 1; i <= F; i++)\r
- InsertNode(r - i);\r
-\r
- InsertNode(r);\r
-\r
- do {\r
- if (match_length > len)\r
- match_length = len;\r
-\r
- if (match_length <= THRESHOLD)\r
- {\r
- match_length = 1;\r
- EncodeChar((long)&outfile,text_buf[r],PtrTypes);\r
- }\r
- else\r
- {\r
- EncodeChar((long)&outfile, 255 - THRESHOLD + match_length,PtrTypes);\r
- EncodePosition((long)&outfile, match_position,PtrTypes);\r
- }\r
-\r
- last_match_length = match_length;\r
-\r
- for (i = 0; i < last_match_length && (DataLength > datasize); i++)\r
- {\r
- c = ReadPtr((long)&infile,PtrTypes);\r
- datasize++;\r
-\r
- DeleteNode(s);\r
- text_buf[s] = c;\r
-\r
- if (s < F - 1)\r
- text_buf[s + N] = c;\r
-\r
- s = (s + 1) & (N - 1);\r
- r = (r + 1) & (N - 1);\r
- InsertNode(r);\r
- }\r
-\r
- if (LZH_CompressDisplayVector && ((textsize += i) > printcount))\r
- {\r
- LZH_CompressDisplayVector(DataLength,datasize);\r
- printcount += 1024;\r
- }\r
-\r
-\r
- while (i++ < last_match_length)\r
- {\r
- DeleteNode(s);\r
- s = (s + 1) & (N - 1);\r
- r = (r + 1) & (N - 1);\r
- if (--len)\r
- InsertNode(r);\r
- }\r
-\r
- } while (len > 0);\r
-\r
- EncodeEnd((long)&outfile,PtrTypes);\r
-\r
- return(codesize);\r
-\r
-}\r
-\r
-\r
-#endif
\ No newline at end of file
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-extern void (*LZH_CompressDisplayVector)();\r
-extern void (*LZH_DecompressDisplayVector)();\r
-\r
-\r
-\r
-//===========================================================================\r
-//\r
-// PROTOTYPES\r
-//\r
-//===========================================================================\r
-\r
-\r
-long lzhCompress(void far *infile, void far *outfile,unsigned long DataLength,unsigned PtrTypes);\r
-long lzhDecompress(void far *infile, void far *outfile, unsigned long OrginalLength, unsigned long CompressLength, unsigned PtrTypes);\r
-\r
-\r
-\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//===========================================================================\r
-//\r
-// LZW COMPRESSION ROUTINES\r
-// VERSION 1.1\r
-//\r
-// Compression algrythim by Haruhiko OKUMURA\r
-// Implementation by Jim T. Row\r
-//\r
-//\r
-// Copyright (c) 1992 - Softdisk Publishing inc. - All rights reserved\r
-//\r
-//===========================================================================\r
-//\r
-//\r
-//---------------------------------------------------------------------------\r
-\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <ctype.h>\r
-#include <alloc.h>\r
-#include <fcntl.h>\r
-#include <dos.h>\r
-#include <io.h>\r
-\r
-#include "lzw.h"\r
-#include "jam_io.h"\r
-\r
-\r
-//===========================================================================\r
-//\r
-// SWITCHES\r
-//\r
-// NOTE : Make sure the appropriate switches are set in SOFT.c for Softlib\r
-// archive support.\r
-//\r
-//===========================================================================\r
-\r
-#define INCLUDE_LZW_COMP 0\r
-#define INCLUDE_LZW_DECOMP 1\r
-\r
-\r
-//===========================================================================\r
-//\r
-// DEFINES\r
-//\r
-//===========================================================================\r
-\r
-\r
-#define LZW_N 4096\r
-#define LZW_F 18\r
-\r
-#define LZW_THRESHOLD 2 // encode string into position and\r
- // length if match_length is greater\r
- // than this\r
-\r
-#define LZW_NIL LZW_N // index for root of bin search trees\r
-\r
-\r
-//============================================================================\r
-//\r
-// GLOBAL VARIABLES NECESSARY FOR\r
-//\r
-// COMP/DECOMP ROUTINES.\r
-//\r
-//============================================================================\r
-\r
-\r
-\r
-unsigned char far LZW_ring_buffer[LZW_N + LZW_F - 1]; // ring buffer of size\r
- // LZW_N, with extra\r
- // LZW_F-1 bytes to\r
- // facilitate\r
- // string comparison\r
-\r
-#if INCLUDE_LZW_COMP\r
-\r
-int LZW_match_pos, // MAtchLength of longest match. These are set by the\r
- // InsertNode() procedure.\r
- LZW_match_len,\r
-\r
- // left & right children & parents -- These constitute binary search trees. */\r
-\r
- LZW_left_child[LZW_N + 1],\r
- LZW_right_child[LZW_N + 257],\r
- LZW_parent[LZW_N + 1];\r
-\r
-#endif\r
-\r
-\r
-//============================================================================\r
-//\r
-// LZW DISPLAY VECTORS\r
-//\r
-// These vectors allow you to hook up any form of display you desire for\r
-// displaying the compression/decompression status.\r
-//\r
-// These routines are called inside of the compression/decompression routines\r
-// and pass the orginal size of data and current position within that\r
-// data. This allows for any kind of "% Done" messages.\r
-//\r
-// Your functions MUST have the following parameters in this order...\r
-//\r
-// void VectorRoutine(unsigned long OrginalSize,unsigned long CurPosition)\r
-//\r
-//\r
-\r
-void (*LZW_CompressDisplayVector)() = NULL;\r
-void (*LZW_DecompressDisplayVector)() = NULL;\r
-\r
-\r
-\r
-\r
-//============================================================================\r
-//\r
-// SUPPORT ROUTINES FOR LZW COMPRESSION\r
-//\r
-//============================================================================\r
-\r
-\r
-#if INCLUDE_LZW_COMP\r
-\r
-static void InitLZWTree(void) /* initialize trees */\r
-{\r
- int i;\r
-\r
- /* For i = 0 to LZW_N - 1, LZW_right_child[i] and LZW_left_child[i] will be the right and\r
- left children of node i. These nodes need not be initialized.\r
- Also, LZW_parent[i] is the parent of node i. These are initialized to\r
- LZW_NIL (= LZW_N), which stands for 'not used.'\r
- For i = 0 to 255, LZW_right_child[LZW_N + i + 1] is the root of the tree\r
- for strings that begin with character i. These are initialized\r
- to LZW_NIL. Note there are 256 trees. */\r
-\r
- for (i = LZW_N + 1; i <= LZW_N + 256; i++)\r
- LZW_right_child[i] = LZW_NIL;\r
-\r
- for (i = 0; i < LZW_N; i++)\r
- LZW_parent[i] = LZW_NIL;\r
-}\r
-\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-\r
-static void InsertLZWNode(unsigned long r)\r
-\r
- /* Inserts string of length LZW_F, LZW_ring_buffer[r..r+LZW_F-1], into one of the\r
- trees (LZW_ring_buffer[r]'th tree) and returns the longest-match position\r
- and length via the global variables LZW_match_pos and LZW_match_len.\r
- If LZW_match_len = LZW_F, then removes the old node in favor of the new\r
- one, because the old one will be deleted sooner.\r
- Note r plays double role, as tree node and position in buffer. */\r
-{\r
- int i, p, cmp;\r
- unsigned char *key;\r
-\r
- cmp = 1;\r
- key = &LZW_ring_buffer[r];\r
- p = LZW_N + 1 + key[0];\r
- LZW_right_child[r] = LZW_left_child[r] = LZW_NIL;\r
- LZW_match_len = 0;\r
-\r
- for ( ; ; )\r
- {\r
- if (cmp >= 0)\r
- {\r
- if (LZW_right_child[p] != LZW_NIL)\r
- p = LZW_right_child[p];\r
- else\r
- {\r
- LZW_right_child[p] = r;\r
- LZW_parent[r] = p;\r
- return;\r
- }\r
- }\r
- else\r
- {\r
- if (LZW_left_child[p] != LZW_NIL)\r
- p = LZW_left_child[p];\r
- else\r
- {\r
- LZW_left_child[p] = r;\r
- LZW_parent[r] = p;\r
- return;\r
- }\r
- }\r
-\r
- for (i = 1; i < LZW_F; i++)\r
- if ((cmp = key[i] - LZW_ring_buffer[p + i]) != 0)\r
- break;\r
-\r
- if (i > LZW_match_len)\r
- {\r
- LZW_match_pos = p;\r
- if ((LZW_match_len = i) >= LZW_F)\r
- break;\r
- }\r
- }\r
-\r
- LZW_parent[r] = LZW_parent[p];\r
- LZW_left_child[r] = LZW_left_child[p];\r
- LZW_right_child[r] = LZW_right_child[p];\r
- LZW_parent[LZW_left_child[p]] = r;\r
- LZW_parent[LZW_right_child[p]] = r;\r
-\r
- if (LZW_right_child[LZW_parent[p]] == p)\r
- LZW_right_child[LZW_parent[p]] = r;\r
- else\r
- LZW_left_child[LZW_parent[p]] = r;\r
-\r
- LZW_parent[p] = LZW_NIL; /* remove p */\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-\r
-static void DeleteLZWNode(unsigned long p) /* deletes node p from tree */\r
-{\r
- int q;\r
-\r
- if (LZW_parent[p] == LZW_NIL)\r
- return; /* not in tree */\r
-\r
- if (LZW_right_child[p] == LZW_NIL)\r
- q = LZW_left_child[p];\r
- else\r
- if (LZW_left_child[p] == LZW_NIL)\r
- q = LZW_right_child[p];\r
- else\r
- {\r
- q = LZW_left_child[p];\r
- if (LZW_right_child[q] != LZW_NIL)\r
- {\r
- do {\r
-\r
- q = LZW_right_child[q];\r
-\r
- } while (LZW_right_child[q] != LZW_NIL);\r
-\r
- LZW_right_child[LZW_parent[q]] = LZW_left_child[q];\r
- LZW_parent[LZW_left_child[q]] = LZW_parent[q];\r
- LZW_left_child[q] = LZW_left_child[p];\r
- LZW_parent[LZW_left_child[p]] = q;\r
- }\r
-\r
- LZW_right_child[q] = LZW_right_child[p];\r
- LZW_parent[LZW_right_child[p]] = q;\r
- }\r
-\r
- LZW_parent[q] = LZW_parent[p];\r
- if (LZW_right_child[LZW_parent[p]] == p)\r
- LZW_right_child[LZW_parent[p]] = q;\r
- else\r
- LZW_left_child[LZW_parent[p]] = q;\r
-\r
- LZW_parent[p] = LZW_NIL;\r
-}\r
-\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-//\r
-// lzwCompress() - Compresses data from an input ptr to a dest ptr\r
-//\r
-// PARAMS:\r
-// infile - Pointer at the BEGINNING of the data to compress\r
-// outfile - Pointer to the destination (no header).\r
-// DataLength - Number of bytes to compress.\r
-// PtrTypes - Type of pointers being used (SRC_FILE,DEST_FILE,SRC_MEM etc).\r
-//\r
-// RETURNS:\r
-// Length of compressed data.\r
-//\r
-// COMPTYPE : ct_LZW\r
-//\r
-// NOTES : Does not write ANY header information!\r
-//\r
-unsigned long lzwCompress(void far *infile, void far *outfile,unsigned long DataLength,unsigned PtrTypes)\r
-{\r
- short i;\r
- short c, len, r, s, last_LZW_match_len, code_buf_ptr;\r
- unsigned char code_buf[17], mask;\r
- unsigned long complen = 0;\r
-\r
- unsigned CodeCount = 0;\r
- unsigned long OrgDataLen = DataLength;\r
-\r
- // initialize trees\r
-\r
- InitLZWTree();\r
-\r
- code_buf[0] = 0;\r
-\r
- //\r
- // code_buf[1..16] saves eight units of code, and code_buf[0] works\r
- // as eight flags, "1" representing that the unit is an unencoded\r
- // letter (1 byte), "0" a position-and-length pair (2 bytes). Thus,\r
- // eight units require at most 16 bytes of code.\r
- //\r
-\r
- code_buf_ptr = mask = 1;\r
- s = 0;\r
- r = LZW_N - LZW_F;\r
-\r
- // Clear the buffer with any character that will appear often.\r
- //\r
-\r
- for (i = s; i < r; i++)\r
- LZW_ring_buffer[i] = ' ';\r
-\r
- // Read LZW_F bytes into the last LZW_F bytes of the buffer\r
- //\r
-\r
- for (len = 0; (len < LZW_F) && DataLength; len++)\r
- {\r
- c = ReadPtr((long)&infile,PtrTypes);\r
- DataLength--;\r
-\r
- // text of size zero\r
-\r
- LZW_ring_buffer[r + len] = c;\r
- }\r
-\r
- if (!(len && DataLength))\r
- return(0);\r
-\r
- //\r
- // Insert the LZW_F strings, each of which begins with one or more\r
- // 'space' characters. Note the order in which these strings\r
- // are inserted. This way, degenerate trees will be less likely\r
- // to occur.\r
- //\r
-\r
- for (i = 1; i <= LZW_F; i++)\r
- InsertLZWNode(r - i);\r
-\r
- //\r
- // Finally, insert the whole string just read. The global\r
- // variables LZW_match_len and LZW_match_pos are set. */\r
- //\r
-\r
- InsertLZWNode(r);\r
-\r
- do {\r
- // LZW_match_len may be spuriously long near the end of text.\r
- //\r
-\r
- if (LZW_match_len > len)\r
- LZW_match_len = len;\r
-\r
- if (LZW_match_len <= LZW_THRESHOLD)\r
- {\r
- // Not long enough match. Send one byte.\r
- //\r
-\r
- LZW_match_len = 1;\r
-\r
- // 'send one byte' flag\r
- //\r
-\r
- code_buf[0] |= mask;\r
-\r
- // Send uncoded.\r
- //\r
-\r
- code_buf[code_buf_ptr++] = LZW_ring_buffer[r];\r
- }\r
- else\r
- {\r
- code_buf[code_buf_ptr++] = (unsigned char) LZW_match_pos;\r
- code_buf[code_buf_ptr++] = (unsigned char) (((LZW_match_pos >> 4) & 0xf0) | (LZW_match_len - (LZW_THRESHOLD + 1)));\r
-\r
- // Send position and length pair.\r
- // Note LZW_match_len > LZW_THRESHOLD.\r
- }\r
-\r
- if ((mask <<= 1) == 0)\r
- {\r
- // Shift mask left one bit.\r
- // Send at most 8 units of data\r
-\r
- for (i = 0; i < code_buf_ptr; i++)\r
- WritePtr((long)&outfile,code_buf[i],PtrTypes);\r
-\r
- complen += code_buf_ptr;\r
- code_buf[0] = 0;\r
- code_buf_ptr = mask = 1;\r
- }\r
-\r
- last_LZW_match_len = LZW_match_len;\r
-\r
- for (i = 0; i < last_LZW_match_len && DataLength; i++)\r
- {\r
- c = ReadPtr((long)&infile,PtrTypes);\r
- DataLength--;\r
-\r
- DeleteLZWNode(s); // Delete old strings and\r
- LZW_ring_buffer[s] = c; // read new bytes\r
-\r
- // If the position is near the end of buffer, extend the\r
- // buffer to make string comparison easier.\r
-\r
- if (s < LZW_F - 1)\r
- LZW_ring_buffer[s + LZW_N] = c;\r
-\r
- // Since this is a ring buffer, inc the position modulo LZW_N.\r
- //\r
-\r
- s = (s + 1) & (LZW_N - 1);\r
- r = (r + 1) & (LZW_N - 1);\r
-\r
- // Register the string in LZW_ring_buffer[r..r+LZW_F-1]\r
- //\r
-\r
- InsertLZWNode(r);\r
- }\r
-\r
-\r
- //\r
- // MANAGE DISPLAY VECTOR\r
- //\r
-\r
- if (LZW_CompressDisplayVector)\r
- {\r
- // Update display every 1k!\r
- //\r
-\r
- if ((CodeCount += i) > 1024)\r
- {\r
- LZW_CompressDisplayVector(OrgDataLen,OrgDataLen-DataLength);\r
- CodeCount = 0;\r
- }\r
- }\r
-\r
-\r
- //\r
- // Manage Compression tree..\r
- //\r
-\r
- while (i++ < last_LZW_match_len)\r
- {\r
- // After the end of text,\r
- DeleteLZWNode(s); // no need to read, but\r
-\r
- s = (s + 1) & (LZW_N - 1);\r
- r = (r + 1) & (LZW_N - 1);\r
-\r
- if (--len)\r
- InsertLZWNode(r); // buffer may not be empty.\r
- }\r
-\r
- } while (len > 0); // until length of string to be processed is zero\r
-\r
-\r
- if (code_buf_ptr > 1)\r
- {\r
- // Send remaining code.\r
- //\r
-\r
- for (i = 0; i < code_buf_ptr; i++)\r
- WritePtr((long)&outfile,code_buf[i],PtrTypes);\r
-\r
- complen += code_buf_ptr;\r
- }\r
-\r
- if (LZW_CompressDisplayVector)\r
- {\r
- if ((CodeCount += i) > 1024)\r
- {\r
- LZW_CompressDisplayVector(OrgDataLen,OrgDataLen-DataLength);\r
- }\r
- }\r
-\r
- return(complen);\r
-}\r
-\r
-#endif\r
-\r
-\r
-\r
-\r
-//============================================================================\r
-//\r
-// SUPPORT ROUTINES FOR LZW DECOMPRESSION\r
-//\r
-//============================================================================\r
-\r
-#if INCLUDE_LZW_DECOMP\r
-\r
-//--------------------------------------------------------------------------\r
-//\r
-// lzwDecompress() - Compresses data from an input ptr to a dest ptr\r
-//\r
-// PARAMS:\r
-// infile - Pointer at the BEGINNING of the compressed data (no header!)\r
-// outfile - Pointer to the destination.\r
-// DataLength - Number of bytes to decompress.\r
-// PtrTypes - Type of pointers being used (SRC_FILE,DEST_FILE,SRC_MEM etc).\r
-//\r
-// RETURNS:\r
-// Length of compressed data.\r
-//\r
-// COMPTYPE : ct_LZW\r
-//\r
-// NOTES : Does not write ANY header information!\r
-//\r
-void lzwDecompress(void far *infile, void far *outfile,unsigned long DataLength,unsigned PtrTypes)\r
-{\r
- int i, j, k, r, c;\r
- unsigned int flags;\r
- unsigned char Buffer[8];\r
-// unsigned char LZW_ring_buffer[LZW_N + LZW_F - 1];\r
-\r
- unsigned CodeCount = 0;\r
- unsigned long OrgDataLen = DataLength;\r
-\r
- for (i = 0; i < LZW_N - LZW_F; i++)\r
- LZW_ring_buffer[i] = ' ';\r
-\r
- r = LZW_N - LZW_F;\r
- flags = 0;\r
-\r
- for ( ; ; )\r
- {\r
- if (((flags >>= 1) & 256) == 0)\r
- {\r
- c = ReadPtr((long)&infile,PtrTypes);\r
-\r
- flags = c | 0xff00; // uses higher byte cleverly to count 8\r
- }\r
-\r
- if (flags & 1)\r
- {\r
- c = ReadPtr((long)&infile,PtrTypes); // Could test for EOF iff FFILE type\r
-\r
- WritePtr((long)&outfile,c,PtrTypes);\r
-\r
- if (!--DataLength)\r
- return;\r
-\r
- LZW_ring_buffer[r++] = c;\r
- r &= (LZW_N - 1);\r
- }\r
- else\r
- {\r
- i = ReadPtr((long)&infile,PtrTypes);\r
-\r
- j = ReadPtr((long)&infile,PtrTypes);\r
-\r
- i |= ((j & 0xf0) << 4);\r
- j = (j & 0x0f) + LZW_THRESHOLD;\r
-\r
- for (k = 0; k <= j; k++)\r
- {\r
- c = LZW_ring_buffer[(i + k) & (LZW_N - 1)];\r
-\r
- WritePtr((long)&outfile,c,PtrTypes);\r
-\r
- if (!--DataLength)\r
- return;\r
-\r
- LZW_ring_buffer[r++] = c;\r
- r &= (LZW_N - 1);\r
- }\r
- }\r
-\r
-\r
-\r
- //\r
- // MANAGE DISPLAY VECTOR\r
- //\r
-\r
- if (LZW_DecompressDisplayVector)\r
- {\r
- //\r
- // Update DisplayVector every 1K\r
- //\r
-\r
- if ((CodeCount+=k) > 1024)\r
- {\r
- LZW_DecompressDisplayVector(OrgDataLen,OrgDataLen-DataLength);\r
- CodeCount = 0;\r
- }\r
- }\r
-\r
- }\r
-}\r
-\r
-#endif\r
-\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//--------------------------------------------------------------------------\r
-//\r
-// EXTERN DEFINITIONS FOR DISPLAY VEC ROUTINES\r
-//\r
-//--------------------------------------------------------------------------\r
-\r
-\r
-extern void (*LZW_CompressDisplayVector)();\r
-extern void (*LZW_DecompressDisplayVector)();\r
-\r
-\r
-//---------------------------------------------------------------------------\r
-//\r
-// FUNCTION PROTOTYPEING\r
-//\r
-//---------------------------------------------------------------------------\r
-\r
-\r
-\r
-unsigned long lzwCompress(void far *infile, void far *outfile,unsigned long DataLength,unsigned PtrTypes);\r
-void lzwDecompress(void far *infile, void far *outfile,unsigned long DataLength,unsigned PtrTypes);\r
-\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-///////////////////////////////////////\r
-//\r
-// TED5 Map Header for ARM\r
-//\r
-///////////////////////////////////////\r
-\r
-//\r
-// Map Names\r
-//\r
-typedef enum {\r
- TOWN_MORBIDITY_MAP, // 0\r
- DARK_FOREST_MAP, // 1\r
- GARDEN_OF_SOULS_MAP, // 2\r
- LOST_CITY_DAMND_MAP, // 3\r
- TEMPLE_OF_VIPER_MAP, // 4\r
- TORTURE_CHAMBER_MAP, // 5\r
- DEMONS_HOLD_MAP, // 6\r
- COLONY_FIRE_ANT_MAP, // 7\r
- HALL_WRETCH_POX_MAP, // 8\r
- LAIR_OF_SUCUBUS_MAP, // 9\r
- BLOOD_CHAMB_EYE_MAP, // 10\r
- FLAMING_INFERNO_MAP, // 11\r
- SUBTERR_RIVER_MAP, // 12\r
- CRYSTAL_MAZE_MG_MAP, // 13\r
- RAMPARTS_OF_NEM_MAP, // 14\r
- FORTRESS_OF_NEM_MAP, // 15\r
- PASSAGE_TO_SURF_MAP, // 16\r
- LASTMAP\r
- } mapnames;\r
-\r
-//\r
-// TILEINFO offsets\r
-//\r
-#define ANIM 402\r
-#define FLAGS (ANIM+NUMTILE16)\r
+++ /dev/null
-The Catacomb Armageddon
-=======================
-
-This repository contains the source code for The Catacomb Armageddon. The
-source code is designed for Borland C++ 2.0, but compiled fine with Borland C++
-3.1 at the time of this release.
-
-It is released under the GNU GPLv2. Please see COPYING for license details.
-
-This release does not affect the licensing for the game data files. You will
-need to legally acquire the game data in order to use the exe built from this
-source code.
-
-To run the executable, the following command must be used or the check must be
-disabled in C5_MAIN.C:
- armgame.exe ^(a@&r`
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#ifndef _SL_FILE_H\r
-#define _SL_FILE_H\r
-\r
-\r
-//==========================================================================\r
-//\r
-// DEFINES\r
-//\r
-//==========================================================================\r
-\r
-#ifndef MakeID\r
-#define MakeID(a,b,c,d) (((long)(d)<<24L)|((long)(c)<<16L)|((long)(b)<<8L)|(long)(a))\r
-#endif\r
-\r
-\r
-#define ID_SLIB MakeID('S','L','I','B')\r
-#define SLIB ("SLIB")\r
-#define SOFTLIB_VER 2\r
-#define ID_CHUNK MakeID('C','U','N','K')\r
-\r
-\r
-\r
-//==========================================================================\r
-//\r
-// TYPES\r
-//\r
-//==========================================================================\r
-\r
-\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-// SOFTLIB File Entry Types\r
-//--------------------------------------------------------------------------\r
-typedef enum LibFileTypes\r
-{\r
- lib_DATA =0, // Just streight raw data\r
-// lib_AUDIO, // Multi chunk audio file\r
-\r
-} LibFileTypes;\r
-\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-// SOFTLIB Library File header..\r
-//\r
-// * This header will NEVER change! *\r
-//--------------------------------------------------------------------------\r
-\r
-typedef struct SoftLibHdr\r
-{\r
- unsigned Version; // Library Version Num\r
- unsigned FileCount;\r
-} SoftlibHdr;\r
-\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-// SOFTLIB Directory Entry Hdr\r
-//\r
-// This can change according to Version of SoftLib (Make sure we are\r
-// always downward compatable!\r
-//--------------------------------------------------------------------------\r
-\r
-#define SL_FILENAMESIZE 16\r
-\r
-typedef struct FileEntryHdr\r
-{\r
- char FileName[SL_FILENAMESIZE]; // NOTE : May not be null terminated!\r
- unsigned long Offset;\r
- unsigned long ChunkLen;\r
- unsigned long OrginalLength;\r
- short Compression; // ct_TYPES\r
-} FileEntryHdr;\r
-\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-// SOFTLIB Entry Chunk Header\r
-//--------------------------------------------------------------------------\r
-\r
-typedef struct ChunkHeader\r
-{\r
- unsigned long HeaderID;\r
- unsigned long OrginalLength;\r
- short Compression; // ct_TYPES\r
-} ChunkHeader;\r
-\r
-\r
-\r
-#endif
\ No newline at end of file
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <ctype.h>\r
-#include <alloc.h>\r
-#include <fcntl.h>\r
-#include <dos.h>\r
-#include <io.h>\r
-\r
-#include "def.h"\r
-#include "gelib.h"\r
-#include "soft.h"\r
-#include "lzw.h"\r
-#include "lzhuff.h"\r
-#include "jam_io.h"\r
-\r
-\r
-\r
-\r
-\r
-\r
-//===========================================================================\r
-//\r
-// SWITCHES\r
-//\r
-//===========================================================================\r
-\r
-#define LZH_SUPPORT 1\r
-#define LZW_SUPPORT 0\r
-\r
-\r
-\r
-\r
-//=========================================================================\r
-//\r
-//\r
-// GENERAL LOAD ROUTINES\r
-//\r
-//\r
-//=========================================================================\r
-\r
-\r
-\r
-//--------------------------------------------------------------------------\r
-// BLoad() -- THIS HAS NOT BEEN FULLY TESTED!\r
-//\r
-// NOTICE : This version of BLOAD is compatable with JAMPak V3.0 and the\r
-// new fileformat...\r
-//--------------------------------------------------------------------------\r
-unsigned long BLoad(char *SourceFile, memptr *DstPtr)\r
-{\r
- int handle;\r
-\r
- memptr SrcPtr;\r
- unsigned long i, j, k, r, c;\r
- word flags;\r
- byte Buffer[8];\r
- unsigned long SrcLen,DstLen;\r
- struct CMP1Header CompHeader;\r
- boolean Compressed = false;\r
-\r
-\r
- memset((void *)&CompHeader,0,sizeof(struct CMP1Header));\r
-\r
- //\r
- // Open file to load....\r
- //\r
-\r
- if ((handle = open(SourceFile, O_RDONLY|O_BINARY)) == -1)\r
- return(0);\r
-\r
- //\r
- // Look for JAMPAK headers\r
- //\r
-\r
- read(handle,Buffer,4);\r
-\r
- if (!strncmp(Buffer,COMP,4))\r
- {\r
- //\r
- // Compressed under OLD file format\r
- //\r
-\r
- Compressed = true;\r
- SrcLen = Verify(SourceFile);\r
-\r
- read(handle,(void *)&CompHeader.OrginalLen,4);\r
- CompHeader.CompType = ct_LZW;\r
- MM_GetPtr(DstPtr,CompHeader.OrginalLen);\r
- if (!*DstPtr)\r
- return(0);\r
- }\r
- else\r
- if (!strncmp(Buffer,CMP1,4))\r
- {\r
- //\r
- // Compressed under new file format...\r
- //\r
-\r
- Compressed = true;\r
- SrcLen = Verify(SourceFile);\r
-\r
- read(handle,(void *)&CompHeader,sizeof(struct CMP1Header));\r
- MM_GetPtr(DstPtr,CompHeader.OrginalLen);\r
- if (!*DstPtr)\r
- return(0);\r
- }\r
- else\r
- DstLen = Verify(SourceFile);\r
-\r
-\r
- //\r
- // Load the file in memory...\r
- //\r
-\r
- if (Compressed)\r
- {\r
- DstLen = CompHeader.OrginalLen;\r
-\r
- if ((MM_TotalFree() < SrcLen) && (CompHeader.CompType))\r
- {\r
- if (!InitBufferedIO(handle,&lzwBIO))\r
- TrashProg("No memory for buffered I/O.");\r
-\r
- switch (CompHeader.CompType)\r
- {\r
- #if LZW_SUPPORT\r
- case ct_LZW:\r
- lzwDecompress(&lzwBIO,MK_FP(*DstPtr,0),CompHeader.OrginalLen,(SRC_BFILE|DEST_MEM));\r
- break;\r
- #endif\r
-\r
- #if LZH_SUPPORT\r
- case ct_LZH:\r
- lzhDecompress(&lzwBIO,MK_FP(*DstPtr,0),CompHeader.OrginalLen,CompHeader.CompressLen,(SRC_BFILE|DEST_MEM));\r
- break;\r
- #endif\r
-\r
- default:\r
- TrashProg("BLoad() - Unrecognized/Supported compression");\r
- break;\r
- }\r
-\r
- FreeBufferedIO(&lzwBIO);\r
- }\r
- else\r
- {\r
- CA_LoadFile(SourceFile,&SrcPtr);\r
- switch (CompHeader.CompType)\r
- {\r
- #if LZW_SUPPORT\r
- case ct_LZW:\r
- lzwDecompress(MK_FP(SrcPtr,8),MK_FP(*DstPtr,0),CompHeader.OrginalLen,(SRC_MEM|DEST_MEM));\r
- break;\r
- #endif\r
-\r
- #if LZH_SUPPORT\r
- case ct_LZH:\r
- lzhDecompress(MK_FP(SrcPtr,8),MK_FP(*DstPtr,0),CompHeader.OrginalLen,CompHeader.CompressLen,(SRC_MEM|DEST_MEM));\r
- break;\r
- #endif\r
-\r
- default:\r
- TrashProg("BLoad() - Unrecognized/Supported compression");\r
- break;\r
- }\r
- MM_FreePtr(&SrcPtr);\r
- }\r
- }\r
- else\r
- CA_LoadFile(SourceFile,DstPtr);\r
-\r
- close(handle);\r
- return(DstLen);\r
-}\r
-\r
-\r
-\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-//\r
-// LoadLIBShape()\r
-//\r
-int LoadLIBShape(char *SLIB_Filename, char *Filename,struct Shape *SHP)\r
-{\r
- #define CHUNK(Name) (*ptr == *Name) && \\r
- (*(ptr+1) == *(Name+1)) && \\r
- (*(ptr+2) == *(Name+2)) && \\r
- (*(ptr+3) == *(Name+3))\r
-\r
-\r
- int RT_CODE;\r
- FILE *fp;\r
- char CHUNK[5];\r
- char far *ptr;\r
- memptr IFFfile = NULL;\r
- unsigned long FileLen, size, ChunkLen;\r
- int loop;\r
-\r
-\r
- RT_CODE = 1;\r
-\r
- // Decompress to ram and return ptr to data and return len of data in\r
- // passed variable...\r
-\r
- if (!LoadLIBFile(SLIB_Filename,Filename,&IFFfile))\r
- TrashProg("Error Loading Compressed lib shape!");\r
-\r
- // Evaluate the file\r
- //\r
- ptr = MK_FP(IFFfile,0);\r
- if (!CHUNK("FORM"))\r
- goto EXIT_FUNC;\r
- ptr += 4;\r
-\r
- FileLen = *(long far *)ptr;\r
- SwapLong((long far *)&FileLen);\r
- ptr += 4;\r
-\r
- if (!CHUNK("ILBM"))\r
- goto EXIT_FUNC;\r
- ptr += 4;\r
-\r
- FileLen += 4;\r
- while (FileLen)\r
- {\r
- ChunkLen = *(long far *)(ptr+4);\r
- SwapLong((long far *)&ChunkLen);\r
- ChunkLen = (ChunkLen+1) & 0xFFFFFFFE;\r
-\r
- if (CHUNK("BMHD"))\r
- {\r
- ptr += 8;\r
- SHP->bmHdr.w = ((struct BitMapHeader far *)ptr)->w;\r
- SHP->bmHdr.h = ((struct BitMapHeader far *)ptr)->h;\r
- SHP->bmHdr.x = ((struct BitMapHeader far *)ptr)->x;\r
- SHP->bmHdr.y = ((struct BitMapHeader far *)ptr)->y;\r
- SHP->bmHdr.d = ((struct BitMapHeader far *)ptr)->d;\r
- SHP->bmHdr.trans = ((struct BitMapHeader far *)ptr)->trans;\r
- SHP->bmHdr.comp = ((struct BitMapHeader far *)ptr)->comp;\r
- SHP->bmHdr.pad = ((struct BitMapHeader far *)ptr)->pad;\r
- SwapWord(&SHP->bmHdr.w);\r
- SwapWord(&SHP->bmHdr.h);\r
- SwapWord(&SHP->bmHdr.x);\r
- SwapWord(&SHP->bmHdr.y);\r
- ptr += ChunkLen;\r
- }\r
- else\r
- if (CHUNK("BODY"))\r
- {\r
- ptr += 4;\r
- size = *((long far *)ptr);\r
- ptr += 4;\r
- SwapLong((long far *)&size);\r
- SHP->BPR = (SHP->bmHdr.w+7) >> 3;\r
- MM_GetPtr(&SHP->Data,size);\r
- if (!SHP->Data)\r
- goto EXIT_FUNC;\r
- movedata(FP_SEG(ptr),FP_OFF(ptr),FP_SEG(SHP->Data),0,size);\r
- ptr += ChunkLen;\r
-\r
- break;\r
- }\r
- else\r
- ptr += ChunkLen+8;\r
-\r
- FileLen -= ChunkLen+8;\r
- }\r
-\r
- RT_CODE = 0;\r
-\r
-EXIT_FUNC:;\r
- if (IFFfile)\r
- {\r
-// segptr = (memptr)FP_SEG(IFFfile);\r
- MM_FreePtr(&IFFfile);\r
- }\r
-\r
- return (RT_CODE);\r
-}\r
-\r
-\r
-\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-// LoadLIBFile() -- Copies a file from an existing archive to dos.\r
-//\r
-// PARAMETERS :\r
-//\r
-// LibName - Name of lib file created with SoftLib V1.0\r
-//\r
-// FileName - Name of file to load from lib file.\r
-//\r
-// MemPtr - (IF !NULL) - Pointer to memory to load into ..\r
-// (IF NULL) - Routine allocates necessary memory and\r
-// returns a MEM(SEG) pointer to memory allocated.\r
-//\r
-// RETURN :\r
-//\r
-// (IF !NULL) - A pointer to the loaded data.\r
-// (IF NULL) - Error!\r
-//\r
-//----------------------------------------------------------------------------\r
-memptr LoadLIBFile(char *LibName,char *FileName,memptr *MemPtr)\r
-{\r
- int handle;\r
- unsigned long header;\r
- struct ChunkHeader Header;\r
- unsigned long ChunkLen;\r
- short x;\r
- struct FileEntryHdr FileEntry; // Storage for file once found\r
- struct FileEntryHdr FileEntryHeader; // Header used durring searching\r
- struct SoftLibHdr LibraryHeader; // Library header - Version Checking\r
- boolean FileFound = false;\r
- unsigned long id_slib = ID_SLIB;\r
- unsigned long id_chunk = ID_CHUNK;\r
-\r
-\r
- //\r
- // OPEN SOFTLIB FILE\r
- //\r
-\r
- if ((handle = open(LibName,O_RDONLY|O_BINARY, S_IREAD)) == -1)\r
- return(NULL);\r
-\r
-\r
- //\r
- // VERIFY it is a SOFTLIB (SLIB) file\r
- //\r
-\r
- if (read(handle,&header,4) == -1)\r
- {\r
- close(handle);\r
- return(NULL);\r
- }\r
-\r
- if (header != id_slib)\r
- {\r
- close(handle);\r
- return(NULL);\r
- }\r
-\r
-\r
- //\r
- // CHECK LIBRARY HEADER VERSION NUMBER\r
- //\r
-\r
- if (read(handle, &LibraryHeader,sizeof(struct SoftLibHdr)) == -1)\r
- TrashProg("read error in LoadSLIBFile()\n%c",7);\r
-\r
- if (LibraryHeader.Version > SOFTLIB_VER)\r
- TrashProg("Unsupported file ver %d",LibraryHeader.Version);\r
-\r
-\r
- //\r
- // MANAGE FILE ENTRY HEADERS...\r
- //\r
-\r
- for (x = 1;x<=LibraryHeader.FileCount;x++)\r
- {\r
- if (read(handle, &FileEntryHeader,sizeof(struct FileEntryHdr)) == -1)\r
- {\r
- close(handle);\r
- return(NULL);\r
- }\r
-\r
- if (!stricmp(FileEntryHeader.FileName,FileName))\r
- {\r
- FileEntry = FileEntryHeader;\r
- FileFound = true;\r
- }\r
- }\r
-\r
- //\r
- // IF FILE HAS BEEN FOUND THEN SEEK TO POSITION AND EXTRACT\r
- // ELSE RETURN WITH ERROR CODE...\r
- //\r
-\r
- if (FileFound)\r
- {\r
- if (lseek(handle,FileEntry.Offset,SEEK_CUR) == -1)\r
- {\r
- close(handle);\r
- return(NULL);\r
- }\r
-\r
- //\r
- // READ CHUNK HEADER - Verify we are at the beginning of a chunk..\r
- //\r
-\r
- if (read(handle,(char *)&Header,sizeof(struct ChunkHeader)) == -1)\r
- TrashProg("LIB File - Unable to read Header!");\r
-\r
- if (Header.HeaderID != id_chunk)\r
- TrashProg("LIB File - BAD HeaderID!");\r
-\r
- //\r
- // Allocate memory if Necessary...\r
- //\r
-\r
-\r
- if (!*MemPtr)\r
- MM_GetPtr(MemPtr,FileEntry.OrginalLength);\r
-\r
- //\r
- // Calculate the length of the data (without the chunk header).\r
- //\r
-\r
- ChunkLen = FileEntry.ChunkLen - sizeof(struct ChunkHeader);\r
-\r
-\r
- //\r
- // Extract Data from file\r
- //\r
-\r
- switch (Header.Compression)\r
- {\r
-\r
- #if LZW_SUPPORT\r
- case ct_LZW:\r
- if (!InitBufferedIO(handle,&lzwBIO))\r
- TrashProg("No memory for buffered I/O.");\r
- lzwDecompress(&lzwBIO,MK_FP(*MemPtr,0),FileEntry.OrginalLength,(SRC_BFILE|DEST_MEM));\r
- FreeBufferedIO(&lzwBIO);\r
- break;\r
- #endif\r
-\r
- #if LZH_SUPPORT\r
- case ct_LZH:\r
- if (!InitBufferedIO(handle,&lzwBIO))\r
- TrashProg("No memory for buffered I/O.");\r
- lzhDecompress(&lzwBIO, MK_FP(*MemPtr,0), FileEntry.OrginalLength, ChunkLen, (SRC_BFILE|DEST_MEM));\r
- FreeBufferedIO(&lzwBIO);\r
- break;\r
- #endif\r
-\r
- case ct_NONE:\r
- if (!CA_FarRead(handle,MK_FP(*MemPtr,0),ChunkLen))\r
- {\r
-// close(handle);\r
- *MemPtr = NULL;\r
- }\r
- break;\r
-\r
- default:\r
- close(handle);\r
- TrashProg("Unknown Chunk.Compression Type!");\r
- break;\r
- }\r
- }\r
- else\r
- *MemPtr = NULL;\r
-\r
- close(handle);\r
- return(*MemPtr);\r
-}\r
-\r
-\r
-\r
-\r
+++ /dev/null
-/* Catacomb Armageddon Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-//memptr InitBufferedIO(int handle, BufferedIO *bio);\r
-//void FreeBufferedIO(BufferedIO *bio);\r
-//byte bio_readch(BufferedIO *bio);\r
-\r
-unsigned long BLoad(char *SourceFile, memptr *DstPtr);\r
-memptr LoadLIBFile(char *LibName,char *FileName,memptr *MemPtr);\r
-int LoadLIBShape(char *SLIB_Filename, char *Filename,struct Shape *SHP);\r
+++ /dev/null
-view_main_toolbar: 1
-bmarksearchmode: 0
-snr_scope: 0
-snr_type: 0
-view_cline: 0
-editor_indent_wspaces: 0
-c2e.convert_xml: 1
-snr_dotmatchall: 0
-htmlbar_view: 0
-filegloblist: *.txt
-filegloblist: *.shtml
-filegloblist: *.py
-filegloblist: *.pl
-filegloblist: *.php
-filegloblist: *.js
-filegloblist: *.java
-filegloblist: *.htm
-filegloblist: *.html
-filegloblist: *.h
-filegloblist: *.css
-filegloblist: *.cpp
-filegloblist: *.cgi
-filegloblist: *.c
-filegloblist: *
-fb_focus_follow: 1
-adv_open_recursive: 0
-recent_dirs: file:///dos/z/cawat
-encoding: UTF-8
-autoindent: 1
-e2c.convert_special: 0
-fb_viewmode: 0
-snippets_show_as_menu: 0
-bookmarks_show_mode: 0
-outputb_show_all_output: 0
-autocomplete: 1
-searchlist: ¥
-searchlist: _seg
-searchlist: _1seg
-searchlist: p_1seg
-searchlist: p1seg
-searchlist: pseg
-searchlist: peg
-searchlist: pg
-searchlist: _1
-searchlist: _seg
-spell_lang: en
-c2e.convert_symbol: 0
-snr_escape_chars: 1
-view_blockstack: 1
-htmlbar_notebooktab: 0
-last_filefilter:
-spell_insert_entities: 0
-spell_check_default: 1
-savedir: file:///dos/z/16/16/cawat
-files: /dos/z/16/16/cawat/16_in.c
-files: /dos/z/16/16/cawat/16_in.h
-files: /dos/fdos/watcom/h/PORTABLE.H
-files: /dos/fdos/watcom/h/P-WATCOM.H
-files: /dos/z/16/16/cawat/lib_head.h
-files: /dos/z/16/16/cawat/ID_MM.C
-snr_replacetype: 0
-recent_files: file:///dos/z/16/16/cawat/ID_MM.C
-recent_files: file:///dos/z/16/16/cawat/lib_head.h
-recent_files: file:///dos/z/16/16/cawat/16_in.h
-recent_files: file:///dos/fdos/watcom/h/P-WATCOM.H
-recent_files: file:///dos/fdos/watcom/h/PORTABLE.H
-recent_files: file:///dos/z/16/16/cawat/16_in.c
-recent_files: file:///dos/z/bakapee.asm
-recent_files: file:///dos/z/16/src/lib/ems.c
-recent_files: file:///dos/z/16/src/lib/ems.h
-recent_files: file:///dos/z/keen-src/id_mm.c
-recent_files: file:///dos/z/16/16/cawat/16_mm.err
-recent_files: file:///dos/z/16/16/cawat/16_mm.h
-recent_files: file:///dos/z/16/16/cawat/16_mm.c
-charmap_block: 1
-e2c.convert_iso: 0
-enable_syntax_scan: 1
-outputb_scroll_mode: 0
-leftpanel_active_tab: 0
-c2e.IE_apos_workaround: 0
-display_right_margin: 0
-replacelist: \\
-replacelist: /*_1seg*/
-replacelist: /*_1seg*/
-replacelist: \t\t
-editor_tab_width: 4
-view_statusbar: 1
-fb_show_hidden_f: 0
-name: cawatcom
-view_blocks: 1
-snr_casesens: 0
-c2e.convert_iso: 0
-bookmarks_filename_mode: 1
-wrap_text_default: 0
-opendir: file:///dos/z/16/16/cawat
-e2c.convert_xml: 1
-default_mime_type: text/plain
-view_left_panel: 0
-htmlbar_thumbnailwidth: 300
-fb_show_backup_f: 0
-view_line_numbers: 1
-show_mbhl: 1
-adv_open_matchname: 0
-convertcolumn_horizontally: 0
-snr_recursion_level: 0
-e2c.convert_symbol: 0
-e2c.convert_num: 0
-c2e.convert_special: 0
+++ /dev/null
-/*\r
- * Copyright (C) 2012-2015 sparky4 & pngwen & andrius4669\r
- *\r
- * This file is part of Project 16.\r
- *\r
- * Project 16 is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 3 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * Project 16 is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program. If not, see <http://www.gnu.org/licenses/>, or\r
- * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
- * Fifth Floor, Boston, MA 02110-1301 USA.\r
- *\r
- */\r
-/*\r
- * Just some handy typedefs that make it easier to think about the low\r
- * level code\r
- */\r
-\r
-#ifndef _LIB_HEAD_H_\r
-#define _LIB_HEAD_H_\r
-#include <i86.h>\r
-#include <dos.h>\r
-#include <conio.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <malloc.h>\r
-#include <strings.h>\r
-//#include <time.h>\r
-#include "../../src/lib/types.h"\r
-\r
-dword far* clockdw= (dword far*) 0x046C; /* 18.2hz clock */\r
-\r
-#define peekb(segm,ofs) (*(byte far*)MK_FP((segm),(ofs)))\r
-#define peekw(segm,ofs) (*(word far*)MK_FP((segm),(ofs)))\r
-#define pokeb(segm,ofs,value) (peekb((segm),(ofs)) = (byte)(value))\r
-#define pokew(segm,ofs,value) (peekw((segm),(ofs)) = (word)(value))\r
-\r
-#endif/*_LIB_HEAD_H_*/\r
+++ /dev/null
-#ifndef _TYPE_H_
-#define _TYPE_H_
-
-typedef enum {false,true} boolean;
-//typedef __segment pseg;
-#define nil ((void *)0)
-
-typedef unsigned char byte;
-typedef unsigned short word;
-typedef unsigned long dword;
-typedef signed char sbyte;
-typedef signed short sword;
-typedef signed long sdword;
-
-#endif
void\r
main(int argc, char *argv[])\r
{\r
- ControlInfo control;\r
+ CursorInfo control;\r
extern boolean Keyboard[NumCodes];\r
IN_Startup();\r
IN_Default(0,ctrl_Joystick);\r
-/* Catacomb Armageddon Source Code
- * Copyright (C) 1993-2014 Flat Rock Software
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+/* Catacomb Apocalypse Source Code\r
+ * Copyright (C) 1993-2014 Flat Rock Software\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License along\r
+ * with this program; if not, write to the Free Software Foundation, Inc.,\r
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
*/
//
// ID_IN.c - Input Manager
// v1.0d1w
// By Jason Blochowiak
-// Open Watcom port by sparky4
+// Open Watcom port by sparky4
//
//
=============================================================================\r
*/\r
// Global variables
- boolean JoystickCalibrated=false; // MDM (GAMERS EDGE) - added\r
- ControlType ControlTypeUsed; // MDM (GAMERS EDGE) - added\r
+// boolean JoystickCalibrated=false; // MDM (GAMERS EDGE) - added\r
+// ControlType ControlTypeUsed; // MDM (GAMERS EDGE) - added\r
boolean Keyboard[NumCodes];\r
boolean Paused;\r
char LastASCII;\r
}
}
-#ifndef DUMU
///////////////////////////////////////////////////////////////////////////
//
// IN_ReadControl() - Reads the device associated with the specified
//
///////////////////////////////////////////////////////////////////////////
void
-IN_ReadControl(int player,ControlInfo *info)
-{
- boolean realdelta=false; // MDM (GAMERS EDGE)
- byte dbyte;
- word buttons;
- int dx,dy;
- Motion mx,my;
- ControlType type;
-register KeyboardDef *def;
-
- dx = dy = 0;
- mx = my = motion_None;
- buttons = 0;
-
-#if DEMO0
- if (DemoMode == demo_Playback)
- {
- dbyte = DemoBuffer[DemoOffset + 1];
- my = (dbyte & 3) - 1;
- mx = ((dbyte >> 2) & 3) - 1;
- buttons = (dbyte >> 4) & 3;
-
- if (!(--DemoBuffer[DemoOffset]))
- {
- DemoOffset += 2;
- if (DemoOffset >= DemoSize)
- DemoMode = demo_PlayDone;
- }
-
- realdelta = false;
- }
- else if (DemoMode == demo_PlayDone)
- Quit("Demo playback exceeded");
- else
-#endif
- {
- // MDM begin (GAMERS EDGE) - added this block
- ControlTypeUsed = ctrl_None;
-
- // Handle mouse input...
- //
- if ((MousePresent) && (ControlTypeUsed == ctrl_None))
- {
- INL_GetMouseDelta(&dx,&dy);
- buttons = INL_GetMouseButtons();
- realdelta = true;
- if (dx || dy || buttons)
- ControlTypeUsed = ctrl_Mouse;
- }
-
- // Handle joystick input...
- //
- if ((JoystickCalibrated) && (ControlTypeUsed == ctrl_None))
- {
- type = ctrl_Joystick1;
- INL_GetJoyDelta(type - ctrl_Joystick,&dx,&dy,false);
- buttons = INL_GetJoyButtons(type - ctrl_Joystick);
- realdelta = true;
- if (dx || dy || buttons)
- ControlTypeUsed = ctrl_Joystick;
- }
-
- // Handle keyboard input...
- //
- if (ControlTypeUsed == ctrl_None)
- {
- type = ctrl_Keyboard1;
- def = &KbdDefs[type - ctrl_Keyboard];
-
-/* if (Keyboard[def->upleft])
- mx = motion_Left,my = motion_Up;
- else if (Keyboard[def->upright])
- mx = motion_Right,my = motion_Up;
- else if (Keyboard[def->downleft])
- mx = motion_Left,my = motion_Down;
- else if (Keyboard[def->downright])
- mx = motion_Right,my = motion_Down;*/
-
- if (Keyboard[def->up])
- my = motion_Up;
- else if (Keyboard[def->down])
- my = motion_Down;
-
- if (Keyboard[def->left])
- mx = motion_Left;
- else if (Keyboard[def->right])
- mx = motion_Right;
-
- if (Keyboard[def->button0])
- buttons += 1 << 0;
- if (Keyboard[def->button1])
- buttons += 1 << 1;
- realdelta = false;
- if (mx || my || buttons)
- ControlTypeUsed = ctrl_Keyboard;
- } // MDM end (GAMERS EDGE)
- }
-
- if (realdelta)
- {
- mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None);
- my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None);
- }
- else
- {
- dx = mx * 127;
- dy = my * 127;
- }
-
- info->x = dx;
- info->xaxis = mx;
- info->y = dy;
- info->yaxis = my;
- info->button0 = buttons & (1 << 0);
- info->button1 = buttons & (1 << 1);
- info->dir = DirTable[((my + 1) * 3) + (mx + 1)];
-
-#if DEMO0
- if (DemoMode == demo_Record)
- {
- // Pack the control info into a byte
- dbyte = (buttons << 4) | ((mx + 1) << 2) | (my + 1);
-
- if
- (
- (DemoBuffer[DemoOffset + 1] == dbyte)
- && (DemoBuffer[DemoOffset] < 255)
- )
- (DemoBuffer[DemoOffset])++;
- else
- {
- if (DemoOffset || DemoBuffer[DemoOffset])
- DemoOffset += 2;
-
- if (DemoOffset >= DemoSize)
- Quit("Demo buffer overflow");
-
- DemoBuffer[DemoOffset] = 1;
- DemoBuffer[DemoOffset + 1] = dbyte;
- }
- }
-#endif
-}
-
-#else
-///////////////////////////////////////////////////////////////////////////
-//
-// IN_ReadControl() - Reads the device associated with the specified
-// player and fills in the control info struct
-//
-///////////////////////////////////////////////////////////////////////////
-void
-IN_ReadControl(int player,ControlInfo *info)
+IN_ReadControl(int player,CursorInfo *info)
{
boolean realdelta;
byte dbyte;
else if (DemoMode == demo_PlayDone)
Quit("Demo playback exceeded");
else
-#endif
{
+#endif
switch (type = Controls[player])
{
case ctrl_Keyboard1:
buttons = INL_GetMouseButtons();
realdelta = true;
break;
+ case ctrl_Joypad1:
+ case ctrl_Joypad2:
+ printf("wwww");
+ break;
}
+#ifdef DEMO0
}
+#endif
if (realdelta)
{
info->yaxis = my;
info->button0 = buttons & (1 << 0);
info->button1 = buttons & (1 << 1);
+ info->button2 = buttons & (1 << 2);
+ info->button3 = buttons & (1 << 3);
info->dir = DirTable[((my + 1) * 3) + (mx + 1)];
#if DEMO0
}
#endif
}
-#endif
///////////////////////////////////////////////////////////////////////////
//
-/* Catacomb Armageddon Source Code\r
+/* Catacomb Apocalypse Source Code\r
* Copyright (C) 1993-2014 Flat Rock Software\r
*\r
* This program is free software; you can redistribute it and/or modify\r
// ID_IN.h - Header file for Input Manager\r
// v1.0d1w\r
// By Jason Blochowiak
-// Open Watcom port by sparky4\r
+// Open Watcom port by sparky4\r
//\r
\r
#ifndef __16_IN__\r
} Demo;\r
#endif\r
typedef enum {\r
- ctrl_None, // MDM (GAMERS EDGE) - added\r
+ //ctrl_None, // MDM (GAMERS EDGE) - added\r
ctrl_Keyboard,\r
ctrl_Keyboard1 = ctrl_Keyboard,ctrl_Keyboard2,\r
ctrl_Joystick,\r
ctrl_Joystick1 = ctrl_Joystick,ctrl_Joystick2,\r
ctrl_Mouse,
- ctrl_Joypad\r
+ ctrl_Joypad,
+ ctrl_Joypad1 = ctrl_Joypad,ctrl_Joypad2\r
} ControlType;\r
typedef enum {\r
motion_Left = -1,motion_Up = -1,\r
Motion xaxis,yaxis;\r
Direction dir;\r
} CursorInfo;\r
-typedef CursorInfo ControlInfo;\r
\r
typedef struct {\r
ScanCode button0,button1,\r
joyMaxX,joyMaxY,\r
joyMultXL,joyMultYL,\r
joyMultXH,joyMultYH;\r
- } JoystickDef;\r
+ } JoystickDef;
+
+/*typedef struct
+{
+ CursorInfo;
+} ControlInfo;*/\r
/*\r
=============================================================================\r
\r
extern ScanCode LastScan;\r
\r
//extern KeyboardDef KbdDefs[];
- static KeyboardDef KbdDefs[] = {0x1d,0x38,0x47,0x48,0x49,0x4b,0x4d,0x4f,0x50,0x51};\r
+ static KeyboardDef KbdDefs[MaxKbds] = {0x1d,0x38,0x47,0x48,0x49,0x4b,0x4d,0x4f,0x50,0x51};\r
extern JoystickDef JoyDefs[MaxJoys];\r
extern ControlType Controls[MaxPlayers];\r
\r
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5\r
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6\r
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7\r
- };\r
-\r
+ },\r
+ *ScanNames[] = // Scan code names with single chars\r
+ {\r
+ "?","?","1","2","3","4","5","6","7","8","9","0","-","+","?","?",\r
+ "Q","W","E","R","T","Y","U","I","O","P","[","]","|","?","A","S",\r
+ "D","F","G","H","J","K","L",";","\"","?","?","?","Z","X","C","V",\r
+ "B","N","M",",",".","/","?","?","?","?","?","?","?","?","?","?",\r
+ "?","?","?","?","?","?","?","?","\xf","?","-","\x15","5","\x11","+","?",\r
+ "\x13","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",\r
+ "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",\r
+ "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?"\r
+ }, // DEBUG - consolidate these\r
+ far ExtScanCodes[] = // Scan codes with >1 char names\r
+ {\r
+ 1,0xe,0xf,0x1d,0x2a,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,\r
+ 0x3f,0x40,0x41,0x42,0x43,0x44,0x57,0x59,0x46,0x1c,0x36,\r
+ 0x37,0x38,0x47,0x49,0x4f,0x51,0x52,0x53,0x45,0x48,\r
+ 0x50,0x4b,0x4d,0x00\r
+ },\r
+ *ExtScanNames[] = // Names corresponding to ExtScanCodes\r
+ {\r
+ "Esc","BkSp","Tab","Ctrl","LShft","Space","CapsLk","F1","F2","F3","F4",\r
+ "F5","F6","F7","F8","F9","F10","F11","F12","ScrlLk","Enter","RShft",\r
+ "PrtSc","Alt","Home","PgUp","End","PgDn","Ins","Del","NumLk","Up",\r
+ "Down","Left","Right",""\r
+ };
\r
static boolean IN_Started;\r
static boolean CapsLock;\r
// Function prototypes\r
#define IN_KeyDown(code) (Keyboard[(code)])\r
#define IN_ClearKey(code) {Keyboard[code] = false; if (code == LastScan) LastScan = sc_None;}\r
-\r
-// DEBUG - put names in prototypes
-/* Catacomb Armageddon Source Code
- * Copyright (C) 1993-2014 Flat Rock Software
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-//
-// ID Engine
-// ID_IN.c - Input Manager
-// v1.0d1w
-// By Jason Blochowiak
-// Open Watcom port by sparky4
-//
-
-//
-// This module handles dealing with the various input devices
-//
-// Depends on: Memory Mgr (for demo recording), Sound Mgr (for timing stuff),
-// User Mgr (for command line parms)
-//
-// Globals:
-// LastScan - The keyboard scan code of the last key pressed
-// LastASCII - The ASCII value of the last key pressed
-// DEBUG - there are more globals
-//
-
-#include "src/lib/16_in.h"
-
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-// Global variables
- boolean JoystickCalibrated=false; // MDM (GAMERS EDGE) - added\r
- ControlType ControlTypeUsed; // MDM (GAMERS EDGE) - added\r
- boolean Keyboard[NumCodes];\r
- boolean Paused;\r
- char LastASCII;\r
- ScanCode LastScan;\r
-\r
- //KeyboardDef KbdDefs = {0x1d,0x38,0x47,0x48,0x49,0x4b,0x4d,0x4f,0x50,0x51};\r
- JoystickDef JoyDefs[MaxJoys];\r
- ControlType Controls[MaxPlayers];\r
-\r
- dword MouseDownCount;
// Internal routines
void interrupt INL_KeyService(void);
void IN_ClearKeysDown(void);
//static void INL_AdjustCursor(CursorInfo *info,word buttons,int dx,int dy);
void IN_ReadCursor(CursorInfo *info);
-void IN_ReadControl(int player,ControlInfo *info);
+void IN_ReadControl(int player,CursorInfo *info);
void IN_SetControlType(int player,ControlType type);
#if DEMO0
boolean IN_StartDemoRecord(word bufsize);