OSDN Git Service

added keen 4-6 rebuild code for reference.... i need to stop doing this... xD
[proj16/16.git] / 16 / keen456 / KEEN4-6 / ID_RF.C
diff --git a/16/keen456/KEEN4-6/ID_RF.C b/16/keen456/KEEN4-6/ID_RF.C
deleted file mode 100755 (executable)
index a040c6b..0000000
+++ /dev/null
@@ -1,2965 +0,0 @@
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D 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
-#ifdef KEEN6\r
-       unsigned        soundtile;\r
-       unsigned        visible;\r
-       int             sound;\r
-#endif\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
-#ifndef KEEN\r
-       //\r
-       // Keen 4-6 store the compatability setting in the game's config file.\r
-       // The setting is loaded from that file AFTER RF_Startup is executed,\r
-       // making this check useless (unless the config file doesn't exist).\r
-       // Instead, US_Startup now checks for that parameter after the config\r
-       // file has been read.\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
-#endif\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
-       screenstart[0] = 0;\r
-       screenstart[1] = SCREENSPACE;\r
-       screenstart[2] = SCREENSPACE*2;\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
-               panx = pany = pansx = pansy = panadjust = 0;\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
-#ifdef KEEN6\r
-/*\r
-==========================\r
-=\r
-= RFL_CheckTileSound\r
-=\r
-= Checks if the tile plays a sound and if so adds that info to the animation\r
-=\r
-==========================\r
-*/\r
-\r
-#define NUMSOUNDTILES 2\r
-typedef struct {\r
-       unsigned tilenums[NUMSOUNDTILES];\r
-       int sounds[NUMSOUNDTILES];\r
-} tilesoundtype;\r
-\r
-tilesoundtype far soundtiles = {\r
-       {2152|0x8000, 2208|0x8000},\r
-       {SND_STOMP,   SND_FLAME}\r
-};\r
-\r
-void RFL_CheckTileSound(tiletype *anim, unsigned tile)\r
-{\r
-       int i;\r
-\r
-       for (i=0; i<NUMSOUNDTILES; i++)\r
-       {\r
-               if (soundtiles.tilenums[i] == tile)\r
-               {\r
-                       anim->soundtile = tile;\r
-                       anim->sound = soundtiles.sounds[i];\r
-                       break;\r
-               }\r
-       }\r
-}\r
-\r
-#endif\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
-#ifdef KEEN6\r
-                                       allanims[i].visible = 0;\r
-                                       allanims[i].sound = -1;\r
-#endif\r
-                                       *info = (unsigned)&allanims[i];\r
-                                       numanimchains++;\r
-                               }\r
-#ifdef KEEN6\r
-                               RFL_CheckTileSound(&allanims[i], tile);\r
-#endif\r
-\r
-                               anims = 0;\r
-                               change = (signed char)(tinf[ANIM+tile]);\r
-                               next = tile+change;\r
-                               while (change && next != tile)\r
-                               {\r
-#ifdef KEEN6\r
-                                       RFL_CheckTileSound(&allanims[i], next);\r
-#endif\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
-#ifdef KEEN6\r
-                                       allanims[i].visible = 0;\r
-                                       allanims[i].sound = -1;\r
-#endif\r
-                                       *info = (unsigned)&allanims[i];\r
-                                       numanimchains++;\r
-                               }\r
-\r
-#ifdef KEEN6\r
-                               RFL_CheckTileSound(&allanims[i], tilehigh);\r
-#endif\r
-                               anims = 0;\r
-                               change = (signed char)(tinf[MANIM+tile]);\r
-                               next = tile+change;\r
-                               while (change && next != tile)\r
-                               {\r
-#ifdef KEEN6\r
-                                       RFL_CheckTileSound(&allanims[i], next | 0x8000);        // foreground tiles have high bit\r
-#endif\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
-#ifdef KEEN6\r
-       {\r
-               tiletype *anim;\r
-\r
-               for (anim = allanims; anim->current != 0; anim++)\r
-                       anim->visible = 0;\r
-       }\r
-#endif\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
-#ifdef KEEN6\r
-               anim->chain->visible++;\r
-#endif\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
-#ifdef KEEN6\r
-               anim->chain->visible++;\r
-#endif\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
-#ifdef KEEN6\r
-                       current->chain->visible--;\r
-#endif\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
-#ifdef KEEN6\r
-                       current->chain->visible--;\r
-#endif\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
-#ifdef KEEN6\r
-                       current->chain->visible--;\r
-#endif\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
-#ifdef KEEN6\r
-                       if (anim->visible && anim->current == anim->soundtile && anim->sound != -1)\r
-                       {\r
-                               SD_PlaySound(anim->sound);\r
-                       }\r
-#endif\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
-=====================\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
-                                       EGA specific routines\r
-\r
-=============================================================================\r
-*/\r
-\r
-#if GRMODE == EGAGR\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
-       if (nopan)\r
-               shift = 0;\r
-       else\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
-                               VW_InverseMask(grsegs[sprite->grseg], sourceofs,\r
-                                       dest,sprite->width,height);\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
-                               VW_InverseMask(grsegs[sprite->grseg], sourceofs,\r
-                                       dest,sprite->width,height);\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
-       RF_CalcTics ();\r
-}\r
-\r
-#endif         // GRMODE == CGAGR\r