ref: 14fe6d1445b3679340a400c2c0ee1d32638ad22e
author: levesqu8 <levesqu8@msu.edu>
date: Thu Aug 17 21:38:40 EDT 2017
Everything from 6/2017 to now. First commit.
--- /dev/null
+++ b/README.txt
@@ -1,0 +1,56 @@
+Based off of the icculus Rise of the Triad source port (can be found here: https://icculus.org/rott/)
+
+This source port of Rise of the Triad features the following:
+
+New gameplay options including the following
+ Blitzguards being outfitted with anything from the missile arsenal!
+ You can now pick up ammo from dropped missile weapons!
+ A special respawning enemy game mode called ZomROTT, where you have to gib your enemies to keep them from coming back!
+ Toggalable Auto Aim
+ Auto Aim for Missile Weapons
+ ...and more
+
+Top Bar of the status bar isn't off to the side anymore!
+
+And all of the improvements made in the icculus source port...
+
+
+
+
+To run the game you'll need the following things:
+
+SDL.dll (https://www.libsdl.org/download-1.2.php)
+
+SDL_mixer.dll (https://www.libsdl.org/projects/SDL_mixer/release-1.2.html)
+
+And Either:
+
+DARKWAR.RTC
+DARKWAR.RTL
+DARKWAR.WAD
+DEMO1_3.DMO
+DEMO2_3.DMO
+DEMO3_3.DMO
+DEMO4_3.DMO
+REMOTE1.RTS
+
+Or
+
+HUNTBGIN.RTC
+HUNTBGIN.RTL
+HUNTBGIN.WAD
+DEMO1_3.DMO
+DEMO2_3.DMO
+DEMO3_3.DMO
+DEMO4_3.DMO
+REMOTE1.RTS
+
+Place all those files in the same directory as rott.exe.
+
+
+BUILDING:
+
+To build the project, you'll need the SDL1.2 development libraries (https://www.libsdl.org/download-1.2.php)
+as well as the SDL_mixer developement libaries (https://www.libsdl.org/projects/SDL_mixer/release-1.2.html, under Binary).
+
+I used MinGW with gcc to build the project.
--- /dev/null
+++ b/rott/LICENSE.DOC
@@ -1,0 +1,56 @@
+"Rise of the Triad: Dark War"
+Copyright 1994/1995 Apogee Software, Ltd.
+P.O. Box 496389, Garland, TX 75049, TEL: 214-271-2137 ("Apogee")
+
+BY COPYING OR USING THIS PROGRAM, YOU INDICATE YOUR AGREEMENT TO
+THE FOLLOWING TERMS, WHICH ARE THE ONLY ONES BY WHICH APOGEE
+PERMITS COPYING OR USE. THIS PROGRAM IS NOT SHAREWARE.
+DISTRIBUTING IT WITHOUT APOGEE'S PERMISSION IS ILLEGAL.
+
+[1] OWNERSHIP. Except to the extent expressly licensed by us,
+we have and reserve the exclusive copyright, trade secret and
+other rights to the Program, and the right to use the Trademarks
+"Apogee", the Apogee "comet", "Rise of the Triad", and "Dark War"
+in connection with it.
+
+[2] USE AND COPIES. You may use the Program only for your own
+purposes "just like a book". This permits use by any number of
+people on any number of machines to use it so long as -- just
+like a book -- there is NO POSSIBILITY that more than one copy
+will be used at a time. You have no right to copy this Program
+except for legal backups.
+
+[3] LIMITED WARRANTY AND LIMITATION OF REMEDIES
+
+If this Program (including any related written material)
+contained a physical defect, you may receive a replacement if
+you return it within 90 days of receiving it from Apogee. Aside
+from this, IT IS PROVIDED "AS-IS", AND NO WARRANTIES OF ANY KIND
+(INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR
+A PARTICULAR PURPOSE), EXPRESS OR IMPLIED, ARE MADE AS TO IT OR
+ANY MEDIUM IT MAY BE ON. OUR ENTIRE LIABILITY AND YOUR
+EXCLUSIVE REMEDY IS SUCH REPLACEMENT, AND UNDER NO CIRCUMSTANCES
+WILL WE PROVIDE ANY OTHER REMEDY FOR DIRECT, INDIRECT, SPECIAL,
+CONSEQUENTIAL, PUNITIVE, INCIDENTAL OR OTHER DAMAGES ARISING
+FROM IT, INCLUDING SUCH FROM NEGLIGENCE, STRICT LIABILITY, OR
+BREACH OF WARRANTY OR CONTRACT, EVEN AFTER NOTICE OF THE
+POSSIBILITY OF SUCH DAMAGES. Some states do not allow the
+exclusion or limitation of implied warranties or liability for
+incidental or consequential damages, so this may not apply to
+buyers of the Program. This gives you specific legal rights,
+and you may also have other rights which vary from state to
+state.
+
+[4] MISCELLANY
+
+ [A] With respect to every matter arising under this, you
+consent to the exclusive jurisdiction and venue of the state and
+federal courts sitting in Dallas, Texas and to service by
+certified mail, return receipt requested, or as otherwise
+permitted by law.
+
+ [B] You will not modify, reverse compile, disassemble, or
+reverse engineer the Program, or use or disclose any of our
+secret information that it contains.
+
+[V.07.15.94]
--- /dev/null
+++ b/rott/Makefile
@@ -1,0 +1,102 @@
+# Determine which version to build
+# Make sure only one of the following is set to 1 at once
+# Triple 0 will build the commercial/registered version
+
+SHAREWARE ?= 1
+SUPERROTT ?= 0
+SITELICENSE ?= 0
+
+CPPFLAGS += -DSHAREWARE=$(SHAREWARE)
+CPPFLAGS += -DSUPERROTT=$(SUPERROTT)
+CPPFLAGS += -DSITELICENSE=$(SITELICENSE)
+
+ROTT ?= rott
+
+# Regular build flags and rules
+
+CC ?= gcc
+
+CFLAGS ?= -g -O2
+CFLAGS += -Wall -Wno-unused
+CFLAGS += $(shell sdl-config --cflags)
+CFLAGS += $(EXTRACFLAGS)
+
+CPPFLAGS += -DUSE_SDL=1
+CPPFLAGS += -DPLATFORM_UNIX=1
+CPPFLAGS += $(EXTRACPPFLAGS)
+
+LDFLAGS += $(EXTRALDFLAGS)
+
+LDLIBS += $(shell sdl-config --libs)
+LDLIBS += -lSDL_mixer
+LDLIBS += $(EXTRALDLIBS)
+
+OBJS :=
+OBJS += cin_actr.o
+OBJS += cin_efct.o
+OBJS += cin_evnt.o
+OBJS += cin_glob.o
+OBJS += cin_main.o
+OBJS += cin_util.o
+OBJS += dosutil.o
+OBJS += engine.o
+OBJS += isr.o
+OBJS += modexlib.o
+OBJS += rt_actor.o
+OBJS += rt_battl.o
+OBJS += rt_build.o
+OBJS += rt_cfg.o
+OBJS += rt_crc.o
+OBJS += rt_com.o
+OBJS += rt_debug.o
+OBJS += rt_dmand.o
+OBJS += rt_door.o
+OBJS += rt_draw.o
+OBJS += rt_floor.o
+OBJS += rt_game.o
+OBJS += rt_in.o
+OBJS += rt_main.o
+OBJS += rt_map.o
+OBJS += rt_menu.o
+OBJS += rt_msg.o
+OBJS += rt_net.o
+OBJS += rt_playr.o
+OBJS += rt_rand.o
+OBJS += rt_scale.o
+OBJS += rt_sound.o
+OBJS += rt_spbal.o
+OBJS += rt_sqrt.o
+OBJS += rt_stat.o
+OBJS += rt_state.o
+OBJS += rt_str.o
+OBJS += rt_swift.o
+OBJS += rt_ted.o
+OBJS += rt_util.o
+OBJS += rt_view.o
+OBJS += rt_vid.o
+OBJS += rt_err.o
+OBJS += scriplib.o
+OBJS += w_wad.o
+OBJS += watcom.o
+OBJS += z_zone.o
+OBJS += byteordr.o
+OBJS += dukemusc.o
+OBJS += winrott.o
+
+AUDIOLIB := audiolib/audiolib.a
+
+all: $(ROTT)
+
+$(ROTT): $(OBJS) $(AUDIOLIB)
+ $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(OBJS): develop.h
+
+$(AUDIOLIB):
+ $(MAKE) -C audiolib
+
+tidy:
+ $(RM) $(OBJS) $(ROTT) $(ROTT).exe
+
+clean: tidy
+ $(MAKE) -C audiolib $@
\ No newline at end of file
binary files /dev/null b/rott/SDL.dll differ
binary files /dev/null b/rott/SDL_mixer.dll differ
--- /dev/null
+++ b/rott/WinRott.h
@@ -1,0 +1,58 @@
+
+
+// winrott.h
+
+
+//husk at rette i winrott.c
+
+extern int iGLOBAL_SCREENWIDTH;//bna val 800
+extern int iGLOBAL_SCREENHEIGHT;//bna val 600
+
+//extern int topBarCenterOffsetX;
+
+extern int iGLOBAL_SCREENBWIDE ;
+extern int iG_SCREENWIDTH;// default screen width in bytes
+
+extern int iGLOBAL_HEALTH_X;
+extern int iGLOBAL_HEALTH_Y;
+extern int iGLOBAL_AMMO_X;
+extern int iGLOBAL_AMMO_Y;
+
+extern int iGLOBAL_FOCALWIDTH;
+extern double dGLOBAL_FPFOCALWIDTH;
+
+void EnableScreenStretch(void);
+void DisableScreenStretch(void);
+
+/*
+double dYZANGLELIMIT;
+
+#define FOCALWIDTH 160//160
+#define FPFOCALWIDTH 160.0//160.0
+
+
+
+#define MAXSCREENHEIGHT 480//600// 200*2
+#define MAXSCREENWIDTH 640//800// 320*2
+#define SCREENBWIDE 640*(96/320)//800*(96/320)// 96*2
+#define MAXVIEWWIDTH 640// 320*2
+#define SCREENWIDTH 640*(96/320)//800*(96/320)// 96*2 // default screen width in bytes
+
+
+#define MAXSCREENHEIGHT 600
+#define MAXSCREENWIDTH 800
+#define SCREENBWIDE 800*(96/320)
+#define MAXVIEWWIDTH 800
+#define SCREENWIDTH 800*(96/320)// default screen width in bytes
+
+*/
+//#define VIEWWIDTH MAXSCREENWIDTH//320*2 // size of view window
+//#define VIEWHEIGHT MAXSCREENHEIGHT//200*2
+//#define MAXSCANLINES MAXSCREENHEIGHT//200*2 // size of ylookup table
+
+
+
+
+
+
+
--- /dev/null
+++ b/rott/_engine.h
@@ -1,0 +1,27 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _engine_private
+#define _engine_private
+
+#define NOTSAMETILE(x1,x2) ( (posts[(x1)].posttype!=posts[(x2)].posttype) || \
+ (posts[(x1)].offset!=posts[(x2)].offset))
+#define SGN(x) (x>0 ? 1 : -1)
+
+#endif
--- /dev/null
+++ b/rott/_isr.h
@@ -1,0 +1,32 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// ISR Constants
+//
+//***************************************************************************
+
+#ifndef _isr_private
+#define _isr_private
+
+#define TIMERINT 0x08
+#define KEYBOARDINT 0x09
+
+#endif
--- /dev/null
+++ b/rott/_rt_acto.h
@@ -1,0 +1,296 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_actor_private
+#define _rt_actor_private
+
+#define MAXGIBS 600
+#define HAAPT 24
+#define VAAPT 24
+#define GODHAPT 1024
+#define GODVAPT 1024
+#define MAXDELTAYZSHOOT (((5*FINEANGLES)/360))
+#define MAXDELTAYZSEE (((15*FINEANGLES)/360))
+#define MAXSHOOTOFFSET (((15*FINEANGLES)/360))
+#define MAXSHOOTSHIFT (1)
+#define MAXDAMAGE (64)
+#define MAXYZANGLE (((30*FINEANGLES)/360))
+#define SMOKEWALLOFFSET (0x800)
+#define MZADJUST 0x30000;
+#define MAXSTEPHEIGHT 24
+#define SIGN(x) ((x)>=0)?(1):(-1)
+#define MAXRAIN 128
+#define SG_PSTAT 0x4000
+#define SG_PSTATE 0x2000
+#define EXPLOSION_DAMAGE 50
+#define LOWFALLCLIPZ (maxheight - 96)
+#define HIGHFALLCLIPZ -5
+#define LOWRISECLIPZ (nominalheight)
+#define HIGHRISECLIPZ 64
+#define NORMALGIBSPEED 0x2f00
+
+#define FL_PLEADING 0x400
+#define FL_EYEBALL 0x400
+#define FL_UNDEAD 0x8000
+
+#define NME_DRUNKTYPE 0x01
+#define NME_HEATSEEKINGTYPE 0x02
+
+#define NUMSTATES 11
+
+enum {
+ STAND,
+ PATH,
+ COLLIDE1,
+ COLLIDE2,
+ CHASE,
+ USE,
+ AIM,
+ DIE,
+ FIRE,
+ WAIT,
+ CRUSH
+};
+
+#define SHOTMOM 0x200l
+#define NEXT 1
+#define PREV 0
+#define ANGLEMOVE 0x2b000l
+#define PAINTIME 5l
+#define LOOKAHEAD (20 << 16)
+#define DRAINTIME 70l
+#define EXPLOSION_IMPULSE 0x2600l
+#define ZEROMOM ob->momentumx = ob->momentumy = 0
+#define NOMOM ((!ob->momentumx) && (!ob->momentumy))
+#define WHICHACTOR (ob->obclass-lowguardobj)
+#define SPDPATROL 0x600l
+//#define ENEMYRUNSPEED (3*SPDPATROL)
+#define ENEMYRUNSPEED (0xc00)
+#define ENEMYFASTRUNSPEED (5*SPDPATROL)
+#define ENEMYINSANESPEED (7*SPDPATROL)
+#define MAXMOVE 0x2000l
+#define PROJECTILESIZE 0x6000l
+#define DEADFRICTION 0x6000l
+#define ROLLMOMENTUM 0x920l
+#define PROJSIZE 0x4000l
+#define PILLARMOM 0x800l
+#define HALFGLOBAL1 (TILEGLOBAL/2)
+#define TOUCHDIST 0xb000l
+#define STANDDIST 0x5000l
+#define SNAKERAD 0x4000l
+#define MINSIGHT 0x18000l
+#define HBM -2
+#define SNEAKY -3
+#define GIBVALUE -3
+#define DISKMOMZ 4
+
+//=========================== macros =============================
+
+#define M_ISWALL(x) ((x->which == WALL) || (x->which == PWALL) || (x->which == MWALL))
+#define M_DISTOK(p1,p2,d) (abs((p1)-(p2)) <= d)
+#define M_NONS(x) ((x->obclass == wallfireobj) || (x->obclass == pillarobj))
+#define M_CHOOSETIME(x) ((int)(TILEGLOBAL/((x->speed))))
+#define M_DIST(x1,x2,y1,y2) (((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)))
+#define M_S(x) (UPDATE_STATES[x][ob->obclass-lowguardobj])
+#define Fix(a) (a &= (FINEANGLES - 1))
+
+
+#define STOPACTOR(ob) \
+ { \
+ ob->momentumx = ob->momentumy = 0; \
+ ob->dirchoosetime = 0; \
+ }
+
+
+#define M_CHECKDIR(ob,tdir) \
+ { \
+ ob->dir = tdir; \
+ ParseMomentum(ob,dirangle8[tdir]); \
+ ActorMovement(ob); \
+ if (ob->momentumx || ob->momentumy) \
+ return; \
+ } \
+
+
+#define M_CHECKTURN(x,ndir) \
+ { \
+ if (ndir == olddir) \
+ ZEROMOM; \
+ ParseMomentum(x,dirangle8[ndir]); \
+ ActorMovement(x); \
+ if (!NOMOM) \
+ { \
+ if (ndir != olddir) \
+ { \
+ next = dirorder[olddir][NEXT]; \
+ prev = dirorder[olddir][PREV]; \
+ x->temp1 = ndir; \
+ if (dirdiff[ndir][next] < dirdiff[ndir][prev]) \
+ NewState(x,&s_kristleft); \
+ else \
+ NewState(x,&s_kristright); \
+ } \
+ return; \
+ } \
+ } \
+
+#define M_CheckDoor(ob) \
+ { \
+ door = ob->door_to_open; \
+ if (door != -1) \
+ { \
+ if ((ob->obclass > shurikenobj) && \
+ (ob->obclass != collectorobj) \
+ ) \
+ Error("you got it !!!"); \
+ LinkedOpenDoor(door); \
+ if (doorobjlist[door]->action != dr_open) \
+ return; \
+ ob->door_to_open = -1; \
+ } \
+ } \
+
+#define M_CheckBossSounds(ob) \
+ { \
+ if ((ob->obclass >= b_darianobj) && \
+ (ob->obclass <= b_darksnakeobj) && \
+ (ob->flags & FL_ATTACKMODE) && \
+ (ob->obclass != b_robobossobj) && \
+ (!(ob->flags & FL_DYING)) \
+ ) \
+ { \
+ if (MISCVARS->SOUNDTIME) \
+ MISCVARS->SOUNDTIME --; \
+ else \
+ { \
+ MISCVARS->SOUNDTIME = 5*VBLCOUNTER; \
+ if (GameRandomNumber("boss sound check",0)<160) \
+ { \
+ int rand,sound; \
+ \
+ rand = GameRandomNumber("boss sounds",0); \
+ sound = BAS[ob->obclass].operate; \
+ if (rand < 160) \
+ sound ++; \
+ if (rand < 80) \
+ sound ++; \
+ \
+ SD_PlaySoundRTP(sound,ob->x,ob->y); \
+ } \
+ } \
+ if (MISCVARS->REDTIME) \
+ { \
+ MISCVARS->REDTIME --; \
+ MISCVARS->redindex = ((MISCVARS->REDTIME >> 1) & 15);\
+ } \
+ } \
+ }
+
+
+
+
+#define SET_DEATH_SHAPEOFFSET(ob) \
+ { \
+ ob->flags |= FL_ALTERNATE; \
+ ob->shapeoffset += deathshapeoffset[ob->obclass]; \
+ }
+
+
+#define RESET_DEATH_SHAPEOFFSET(ob) \
+ { \
+ ob->flags &= ~FL_ALTERNATE; \
+ ob->shapeoffset -= deathshapeoffset[ob->obclass]; \
+ }
+
+#define LOW_VIOLENCE_DEATH_SHOULD_BE_SET(ob) \
+ ((gamestate.violence < vl_high) && \
+ (ob->obclass >= lowguardobj) && \
+ (ob->obclass <= triadenforcerobj) && \
+ (!(ob->flags & FL_ALTERNATE)) \
+ ) \
+
+#define LOW_VIOLENCE_DEATH_IS_SET(ob) (ob->flags & FL_ALTERNATE)
+
+#define LOW_VIOLENCE_PAIN_SHOULD_BE_SET LOW_VIOLENCE_DEATH_SHOULD_BE_SET
+
+#define LOW_VIOLENCE_PAIN_IS_SET LOW_VIOLENCE_DEATH_IS_SET
+
+#define SET_PAIN_SHAPEOFFSET SET_DEATH_SHAPEOFFSET
+
+#define RESET_PAIN_SHAPEOFFSET RESET_DEATH_SHAPEOFFSET
+
+
+// default = actor
+
+typedef struct sat
+{ int x,y,z;
+ unsigned flags;
+ int hitpoints;
+ int targetx,targety;
+ int angle;
+ int yzangle;
+ int speed;
+ int momentumx,momentumy,momentumz;
+ int temp1,temp2,temp3;
+ int whateverindex,targetindex;
+
+ short ticcount;
+ short shapeoffset;
+ short stateindex;
+ short dirchoosetime;
+
+ byte areanumber;
+ byte obclass;
+ signed char door_to_open;
+ signed char dir;
+
+} saved_actor_type;
+
+
+typedef struct
+{ thingtype which;
+ byte tilex,tiley;
+ fixed x,y,z;
+} tpoint;
+
+
+//========================== Function Prototypes ==============================
+
+void MissileMovement(objtype*);
+boolean MissileTryMove(objtype*,int,int,int);
+void T_DarkSnakeChase(objtype*);
+void HeatSeek(objtype*);
+boolean CheckDoor(objtype *ob,doorobj_t*,int,int);
+boolean NextToDoor(objtype*ob);
+void MissileHit (objtype *ob,void*);
+int Near(objtype*,void*,int);
+void FirstSighting(objtype*);
+void SelectOrobotChaseDir(objtype*);
+void SelectPathDir(objtype*);
+void SelectChaseDir(objtype*);
+void SelectRoboChaseDir(objtype*);
+void SelectDodgeDir(objtype*);
+void SelectRollDir (objtype*);
+void SelectTouchDir(objtype*);
+void SelectMineDir(objtype*);
+boolean WallCheck(int,int);
+boolean NMEspincheck(objtype*);
+void TurnActorIntoSprite(objtype*ob);
+void ActivateEnemy(objtype*);
+#endif
--- /dev/null
+++ b/rott/_rt_buil.h
@@ -1,0 +1,48 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_build_private
+#define _rt_build_private
+
+#define MAX(x,y) ((x>y) ? (x) : (y))
+#define MAXPLANES 10
+
+// Should be 10 with titles
+#define MENUOFFY (10)
+#define MENUBACKNAME ("plane")
+#define MENUTITLEY 10
+#define TEXTUREW (288)
+#define TEXTUREWIDTH ((TEXTUREW*1024)-1)
+#define TEXTUREHEIGHT (158)
+#define NORMALVIEW (0x40400L)
+#define NORMALHEIGHTDIVISOR (156000000)
+#define NORMALWIDTHMULTIPLIER (241)
+#define FLIPTIME 20//60
+
+
+typedef struct
+{
+ int x1, y1;
+ int x2, y2;
+ int texturewidth;
+ int texture;
+ int origheight;
+} plane_t;
+
+#endif
--- /dev/null
+++ b/rott/_rt_com.h
@@ -1,0 +1,53 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_com_private
+#define _rt_com_private
+
+
+#define SYNCPACKETSIZE 32
+
+#define SYNC_PHASE0 6
+#define SYNC_PHASE1 0
+#define SYNC_PHASE2 1
+#define SYNC_PHASE3 2
+#define SYNC_PHASE4 3
+#define SYNC_PHASE5 4
+#define SYNC_MEMO 99
+#define NUMSYNCPHASES 5
+
+#define SYNCTIME 15
+
+typedef struct
+{
+ byte type;
+ int phase;
+ int clocktime;
+ int delta;
+ byte data[SYNCPACKETSIZE];
+} syncpackettype;
+
+typedef struct
+{
+ int sendtime;
+ int deltatime;
+ syncpackettype pkt;
+} synctype;
+
+#endif
--- /dev/null
+++ b/rott/_rt_dman.h
@@ -1,0 +1,29 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_dmand_private
+#define _rt_dmand_private
+
+#define RECORDINGSAMPLERATE 7000
+#define RECORDINGBUFFERSIZE 16384
+#define PLAYBACKBUFFERSIZE 16384
+#define PLAYBACKDELTASIZE 256
+
+#endif
+
--- /dev/null
+++ b/rott/_rt_door.h
@@ -1,0 +1,48 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_door_private
+#define _rt_door_private
+
+#define OPENTICS 165
+
+typedef struct tp
+{
+ signed char actionindex;
+ signed char swapactionindex;
+ int whichobj;
+ byte tictime;
+ byte ticcount;
+ byte triggered;
+ byte complete;
+ byte done;
+} saved_touch_type;
+
+
+#define NUMTOUCHPLATEACTIONS 8
+
+#define FL_TACT 0x4000
+#define FL_TSTAT 0x8000
+
+#define PUSHWALLSPEED 10
+
+#define AMW_NUMFRAMES 9
+#define AMW_TICCOUNT 3
+
+#endif
--- /dev/null
+++ b/rott/_rt_draw.h
@@ -1,0 +1,74 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_draw_private
+#define _rt_draw_private
+
+#include "develop.h"
+
+#define MINZ 0x2700
+#define MAXBOB 0x9000
+
+#define GOLOWER 0x38000
+#define GOHIGHER 0x20000
+
+#define MAXVISIBLEDOORS 30
+
+#define DHEIGHTFRACTION 8
+
+#define MINZ 0x2700
+#define MAXDRAWNTICS 40
+
+#define W_CHANGE (WEAPONUPTICS || WEAPONDOWNTICS)
+
+#if (SHAREWARE == 0)
+#define NUMWEAPGRAPHICS 16
+#else
+#define NUMWEAPGRAPHICS 9
+#endif
+
+#define HFRACTION (6+HEIGHTFRACTION)
+
+#define FIXEDTRANSLEVEL (30)
+
+typedef struct
+{
+ int x;
+ int y;
+ int angle;
+ int scale;
+ int dx;
+ int dy;
+ int dangle;
+ int dscale;
+ int phase;
+ int time;
+ int pausetime;
+ int pausex;
+ int pausey;
+} screensaver_t;
+
+void DrawPlayerWeapon(void);
+boolean TransformPlane (int x1, int y1, int x2, int y2, visobj_t * plane);
+int CalcRotate (objtype *ob);
+void DrawScaleds (void);
+void FixOfs (void);
+void SetSpriteLightLevel (int x, int y, visobj_t * sprite, int dir, int fullbright);
+
+#endif
--- /dev/null
+++ b/rott/_rt_floo.h
@@ -1,0 +1,28 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_floor_private
+#define _rt_floor_private
+
+//#define MAXVIEWHEIGHT MAXSCREENHEIGHT
+#define MAXSKYSEGS 2048
+#define MAXSKYDATA 8
+#define MINSKYHEIGHT 148
+
+#endif
--- /dev/null
+++ b/rott/_rt_game.h
@@ -1,0 +1,165 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_game_private
+#define _rt_game_private
+
+//******************************************************************************
+//
+// Private header for RT_GAME.C
+//
+//******************************************************************************
+
+
+//******************************************************************************
+//
+// TYPEDEFS
+//
+//******************************************************************************
+
+typedef struct {
+ char str[10];
+ int length;
+} STR;
+
+//******************************************************************************
+//
+// DEFINES
+//
+//******************************************************************************
+
+#define MENUSHADELEVEL 105
+
+#define KILLS_X 0
+#define KILLS_Y 176
+#define KILLS_WIDTH 32
+#define KILLS_HEIGHT 24
+#define KILLS_OFFSET 14
+#define KILLS_NAME_Y ( KILLS_Y + 16 )
+#define MAXKILLBOXES 10
+#define PLAYERS_Y ( 107 + ( gamestate.teamplay ? 0 : 4 ) )
+#define PLAYERS_NAME_Y ( PLAYERS_Y + 16 )
+#define PLAYERS_TEAM_Y ( PLAYERS_Y + 24 )
+
+#define LEADER_X 0
+#define LEADER_Y 0
+#define LEADER_NUM_X 61
+#define LEADER_NUM_Y ( LEADER_Y )
+#define LEADER_NAME_X ( LEADER_X + 3 )
+#define LEADER_NAME_Y ( LEADER_Y + 2 )
+#define LEADER_WIDTH 88
+#define LEADER_HEIGHT 16
+/* bna++
+#define HEALTH_X 20
+#define HEALTH_Y 185
+
+#define AMMO_X 300
+#define AMMO_Y 184
+*/
+//--------------------
+#define HEALTH_X 20*2
+#define HEALTH_Y (185*2)+16
+
+#define AMMO_X 300*2
+#define AMMO_Y (184*2)+16
+//--------------------
+
+#define SCORE_X 4
+#define SCORE_Y 0
+
+/*
+#define KEY1_X 152
+#define KEY2_X 160
+#define KEY3_X 168
+#define KEY4_X 176
+#define KEY_Y 0
+
+#define POWER_X 184
+#define POWER_Y 0
+
+#define ARMOR_X 200
+#define ARMOR_Y 0
+
+#define MEN_X 216
+#define MEN_Y 0
+*/
+//--------------------
+#define KEY1_X 152
+#define KEY2_X 160
+#define KEY3_X 168
+#define KEY4_X 176
+#define KEY_Y 0
+
+#define POWER_X (184)
+#define POWER_Y 0
+
+#define ARMOR_X 200
+#define ARMOR_Y 0
+
+#define MEN_X 216
+#define MEN_Y 0
+//--------------------
+#define HOUR_X 7
+#define MIN_X 26
+#define SEC_X 45
+#define TIME_Y 0
+
+#define GAMETIME_X 88
+#define GAMETIME_Y 0
+
+#define TALLYTIME_X 130
+#define TALLYTIME_Y 8
+
+#define LIVES_X 288
+#define LIVES_Y 0
+
+#define TRIAD_X 308
+#define TRIAD_Y 6
+
+#define POWERUP1X 184
+#define POWERUP2X 200
+#define POWERUPY 0
+
+#define EXTRAPOINTS 50000
+#define ADRENALINEBONUS 5
+
+#define STR_SAVECHT1 "Your Save Game file is,"
+#define STR_SAVECHT2 "shall we say, \"corrupted\"."
+#define STR_SAVECHT3 "But I'll let you go on and"
+#define STR_SAVECHT4 "play anyway...."
+
+#define MAXSAVEDGAMESIZE 120000
+
+#if (SHAREWARE == 0)
+#define WEAPON_IS_MAGICAL(x) (((x) == wp_dog) || ((x) == wp_godhand))
+#else
+#define WEAPON_IS_MAGICAL(x) ((x) == wp_godhand)
+#endif
+
+//******************************************************************************
+//
+// PROTOTYPES
+//
+//******************************************************************************
+
+void DrawMPPic (int xpos, int ypos, int width, int height, int heightmod, byte *src, boolean bufferofsonly);
+void DrawHighScores (void);
+void GM_MemToScreen (byte *source, int width, int height, int x, int y);
+
+#endif
--- /dev/null
+++ b/rott/_rt_in.h
@@ -1,0 +1,61 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//****************************************************************************
+//
+// Private header for RT_IN.C
+//
+//****************************************************************************
+
+#ifndef _rt_in_private
+#define _rt_in_private
+
+
+//****************************************************************************
+//
+// TYPEDEFS
+//
+//****************************************************************************
+
+
+//****************************************************************************
+//
+// DEFINES
+//
+//****************************************************************************
+
+#define KeyInt 9 // The keyboard ISR number
+#define MReset 0
+#define MButtons 3
+#define MDelta 11
+#define MouseInt 0x33
+#define JoyScaleMax 32768
+#define JoyScaleShift 8
+#define MaxJoyValue 5000
+
+void Mouse (int x);
+
+#if defined(__WATCOMC__)
+#pragma aux Mouse = \
+ "int 33h" \
+ parm [EAX] \
+ modify [EAX]
+#endif
+
+#endif
--- /dev/null
+++ b/rott/_rt_main.h
@@ -1,0 +1,74 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_main_private
+#define _rt_main_private
+
+#include "develop.h"
+
+void GameLoop (void);
+void PlayLoop (void);
+void PollKeyboard(void);
+void FixColorMap( void );
+
+#define QUITTIMEINTERVAL ((35*6)-5)
+boolean CheckForQuickLoad ( void );
+
+#if SAVE_SCREEN
+
+void WriteLBMfile (char *filename, byte *data, int width, int height);
+void GetFileName (boolean saveLBM);
+void DrawRottTitle ( void );
+
+void WritePCX (char * file, byte * source);
+int PutBytes (unsigned char *ptr, unsigned int bytes);
+
+typedef struct
+{
+ unsigned short w,h;
+ short x,y;
+ unsigned char nPlanes;
+ unsigned char masking;
+ unsigned char compression;
+ unsigned char pad1;
+ unsigned short transparentColor;
+ unsigned char xAspect,yAspect;
+ short pageWidth,pageHeight;
+} bmhd_t;
+
+
+typedef struct {
+ unsigned char manufacturer;
+ unsigned char version;
+ unsigned char encoding;
+ unsigned char bitsperpixel;
+ unsigned short int xmin, ymin, xmax, ymax;
+ unsigned short int hres, vres;
+ unsigned char colormap[16][3];
+ unsigned char reserved;
+ unsigned char nplanes;
+ unsigned short int bytesperline;
+} PCX_HEADER;
+
+#define GAP_SIZE (128 - sizeof (PCX_HEADER))
+
+
+#endif
+
+#endif
--- /dev/null
+++ b/rott/_rt_map.h
@@ -1,0 +1,44 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_map_private
+#define _rt_map_private
+
+#if defined(__WATCOM__)
+#pragma aux FastFill = \
+ "rep stosb" \
+ parm [edi] [eax] [ecx] \
+ modify exact [ecx]
+#endif
+void FastFill(byte * buf, int color, int count);
+
+
+#define MAP_PLAYERCOLOR 4
+#define MAP_MWALLCOLOR 13
+#define MAP_PWALLCOLOR 8
+#define MAP_AWALLCOLOR 9
+#define MAP_WALLCOLOR 7
+#define MAP_DOORCOLOR 3
+#define MAP_SPRITECOLOR 2
+#define MAP_ACTORCOLOR 15
+#define MAP_SKYCOLOR 11
+
+#define FULLMAP_SCALE 5
+
+#endif
--- /dev/null
+++ b/rott/_rt_menu.h
@@ -1,0 +1,369 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_menu_private
+#define _rt_menu_private
+
+//******************************************************************************
+//
+// Private Header for RT_MENU.C
+//
+//******************************************************************************
+
+#include "rt_in.h"
+
+//
+// Specific Menu defines
+//
+
+#define BORDCOLOR 0x29
+#define BORD2COLOR 0x23
+#define DEACTIVE 0x2b
+#define BKGDCOLOR 0x2d
+#define STRIPE 0x2c
+
+
+#define SENSITIVE 60
+#define CENTER SENSITIVE*2
+
+
+#define MENU_X 32
+#define MENU_Y 16
+#define MENU_W 235
+#define MENU_H 14*9+4
+
+
+#define LSM_X 180 //32
+#define LSM_Y 16
+#define LSM_W 80 //176
+#define LSM_H 10*14+8
+
+#define LSA_X 96
+#define LSA_Y 80
+#define LSA_W 130
+#define LSA_H 42
+
+
+#define SM_X 32
+#define SM_Y 52
+#define SM_W 252
+#define SM_H 35
+
+#define SM_Y1 20
+#define SM_H1 4*14-9
+#define SM_Y2 SM_Y1+5*14
+#define SM_H2 4*14-9
+#define SM_Y3 SM_Y2+5*14
+#define SM_H3 3*14-9
+
+
+#define CTL_X 19
+#define CTL_Y 32
+#define CTL_W 284
+#define CTL_H 105
+
+
+#define CST_X 20
+#define CST_Y 43
+#define CST_START 60
+#define CST_SPC 60
+
+
+#define TUF_X 0
+#define TUF_Y 32
+
+
+#define HLP_X 34
+#define HLP_Y 63
+#define HLP_W 264
+#define HLP_H 51
+
+
+#define MU_X 32
+#define MU_Y 22
+#define MU_W 252
+#define MU_H 118
+
+
+#define FX_X 32
+#define FX_Y 16
+#define FX_W 252
+#define FX_H 130
+
+
+#define MP_X 55//32
+#define MP_Y 60
+#define MP_W 252
+#define MP_H 35
+
+
+#define X1_X 55
+#define X1_Y 25
+#define X1_W 252
+
+#define X2_X 55
+#define X2_Y 65
+#define X2_W 252
+#define X2_H 35
+
+#define X3_X 55
+#define X3_Y 65
+#define X3_W 252
+#define X3_H 35
+
+#define LEVSEL_X 32
+#define LEVSEL_Y 22
+#define LEVSEL_W 252
+#define LEVSEL_H 118
+#define MAXCUSTOM 12
+
+#define STARTITEM newgame
+
+//
+// General defines
+//
+#define CP_SemiActive 4
+#define CP_Highlight 5
+
+#define OUTOFRANGE 100
+#define ESCPRESSED -1
+#define PAGEUP -2
+#define PAGEDOWN -3
+#define NOTAVAILABLECOLOR 7
+#define NEXTPAGECOLOR 16
+#define NORMALCOLOR 21
+#define DIMMEDCOLOR 24
+#define ACTIVECOLOR 241
+#define HIGHLIGHTCOLOR 1
+
+#define MouseInt 0x33
+#define GAMESVD "There's already a game\n" \
+ "saved at this position.\n"\
+ "Overwrite?"
+#define COLOR 235
+
+#define CUSTOMX 76
+
+#define NUMSAVEGAMES 14
+
+#define PWORDX 58
+#define PWORDY 46
+//#define PBOXX 68
+#define PBOXX ( ( 288 - PBOXW ) / 2 )
+#define PBOXY 71
+#define PBOXW 115
+#define PSTRW 110
+#define PBOXH 12
+
+
+#define QUICKSAVEBACKUP ("rottgamf.rot")
+//******************************************************************************
+//
+// ENUMS
+//
+//******************************************************************************
+
+typedef struct
+{
+ int allowed[4];
+} CustomCtrls;
+
+// FOR INPUT TYPES
+enum {MOUSE, JOYSTICK, KEYBOARDBTNS, KEYBOARDMOVE, SPECIAL1, SPECIAL2};
+
+
+//******************************************************************************
+//
+// GLOBALS
+//
+//******************************************************************************
+
+static byte *ScanNames[] = // Scan code names with single chars
+{
+ "?","?","1","2","3","4","5","6","7","8","9","0","-","+","?","?",
+ "Q","W","E","R","T","Y","U","I","O","P","[","]","|","?","A","S",
+ "D","F","G","H","J","K","L",";","\"","?","?","?","Z","X","C","V",
+ "B","N","M",",",".","/","?","?","?","?","?","?","?","?","?","?",
+ "?","?","?","?","?","?","?","?","\xf","?","-","\x15","5","\x11","+","?",
+ "\x13","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
+ "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?",
+ "?","?","?","?","?","?","?","?","?","?","?","?","?","?","?","?"
+};
+
+
+static byte ExtScanCodes[] = // Scan codes with >1 char names
+{
+ 1, 0xe, 0xf, 0x1d, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
+ 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x57, 0x58, 0x46, 0x1c, 0x36,
+ 0x37, 0x38, 0x47, 0x49, 0x4f, 0x51, 0x52, 0x53, 0x45, 0x48,
+ 0x50, 0x4b, 0x4d, 0x00
+};
+
+static byte *ExtScanNames[] = // Names corresponding to ExtScanCodes
+{
+ "Esc","BkSp","Tab","Ctrl","Space","CapLk","F1","F2","F3","F4",
+ "F5","F6","F7","F8","F9","F10","F11","F12","SclLk","Enter","Shift",
+ "PrtSc","Alt","Home","PgUp","End","PgDn","Ins","Del","NumLk","Up",
+ "Down","Left","Right",""
+};
+
+
+//******************************************************************************
+//
+// PROTOTYPES
+//
+//******************************************************************************
+
+void MouseSensitivity (void);
+void DoThreshold (void);
+byte * IN_GetScanName (ScanCode scan);
+void DisplayInfo (int which);
+
+void PrintLSEntry (int w);
+
+void DrawHalfStep (int x, int y);
+
+void DrawCtlScreen (void);
+void DrawCtlButtons (void);
+void DrawSoundMenu (void);
+void DrawCustomScreen (void);
+void DrawLoadSaveScreen (int loadsave);
+void DrawLoadSaveScreenAlt (int loadsave);
+void DrawMusicMenu (void);
+void DrawNewGame (void);
+void DrawNewGameDiff (int w);
+void DrawNewPlayerDiff (int w);
+void DrawFXMenu (void);
+void DrawFXButtons (void);
+void DrawCustomJoystick (void);
+void DrawCustomMouse (void);
+void DrawCustomSpecial (void);
+void DrawCustomMenu (void);
+void DrawPlayerMenu (void);
+
+void DoMainMenu (void);
+
+boolean CP_DisplayMsg (char *s, int number);
+void CP_EndGame (void);
+int CP_SaveGame (void);
+void CP_Control (void);
+void CP_Sound (void);
+void CP_ChangeView (void);
+void CP_DoubleClickSpeed( void );
+void CP_ErrorMsg( char *title, char *error, int font );
+void CP_Quit (int which);
+void CP_NewGame (void);
+void CP_Music (void);
+void CP_FX (void);
+void CP_MCports (void);
+void CP_FXMenu (void);
+void CP_Custom (void);
+void CP_Keyboard (void);
+void CP_Mouse (void);
+void CP_Joystick (void);
+void CP_Special (void);
+void CP_OrderInfo( void );
+
+void DefineMouseBtns1 (void);
+void DefineMouseBtns2 (void);
+void DefineKeyBtns1 (void);
+void DefineKeyBtns2 (void);
+void DefineKeyMove1 (void);
+void DefineKeyMove2 (void);
+void DefineJoyBtns1 (void);
+void DefineJoyBtns2 (void);
+void DefineSpecialBtns1 (void);
+void DefineSpecialBtns2 (void);
+
+void DrawSTMenuBuf (int x, int y, int w, int h, boolean up);
+
+void MusicVolume (void);
+void FXVolume (void);
+
+void DefineKey( void );
+void DefineJoyBtn( void );
+void DefineMouseBtn( void );
+
+void DrawControlMenu (void);
+void CP_ControlMenu (void);
+void DrawOptionsMenu (void);
+void DrawExtOptionsMenu (void);
+void CP_ExtOptionsMenu (void);
+void CP_OptionsMenu (void);
+void DrawOptionsButtons (void);
+void DrawExtOptionsButtons (void);
+void MenuFlipSpeed (void);
+void DrawDetailMenu (void);
+void CP_DetailMenu (void);
+void DrawBattleMenu (void);
+void CP_BattleMenu (void);
+void MCERROR (void);
+
+void DrawKeyboardMenu (void);
+void CP_KeyboardMenu (void);
+boolean SliderMenu( int *number, int upperbound, int lowerbound, int erasex,
+ int erasey, int erasew, int numadjust, char *blockname,
+ void (*routine) (int w), char *title, char *left, char *right );
+
+void DrawF1Help (void);
+void CP_F1Help (void);
+void CP_ScreenSize( void );
+
+void CP_ViolenceMenu (void);
+void DrawViolenceLevelMenu (void);
+void DrawViolenceLevelPWord (void);
+
+void DrawViolenceLevel (void);
+void CP_ViolenceLevel (void);
+
+void DrawPWMenu (void);
+void CP_PWMenu (void);
+
+void DrawBattleModes (void);
+void CP_BattleModes (void);
+
+void DrawBattleOptions (void);
+void CP_BattleOptions (void);
+
+void DrawGravityMenu (void);
+void CP_GravityOptions (void);
+void DrawSpeedMenu (void);
+void CP_SpeedOptions (void);
+void DrawAmmoPerWeaponMenu (void);
+void CP_AmmoPerWeaponOptions (void);
+void DrawHitPointsMenu (void);
+void CP_HitPointsOptions (void);
+void DrawSpawnControlMenu (void);
+void DrawSpawnControlButtons (void);
+void CP_SpawnControlOptions (void);
+void DrawLightLevelMenu (void);
+void CP_LightLevelOptions (void);
+void DrawPointGoalMenu (void);
+void CP_PointGoalOptions (void);
+void DrawDangerMenu (void);
+void CP_DangerOptions (void);
+void DrawTimeLimitMenu (void);
+void CP_TimeLimitOptions (void);
+void PrintBattleOption( boolean inmenu, int x, int y, char *text );
+
+void CP_OnePlayerWarningMessage( void );
+
+void DrawMultiPageCustomMenu( char *title, void ( *redrawfunc )( void ) );
+
+#endif
--- /dev/null
+++ b/rott/_rt_msg.h
@@ -1,0 +1,25 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_msg_private
+#define _rt_msg_private
+
+#define MESSAGETIME (35*6)
+
+#endif
--- /dev/null
+++ b/rott/_rt_net.h
@@ -1,0 +1,122 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_net_private
+#define _rt_net_private
+
+#define DEMOBUFFSIZE 50000
+
+#define FASTSPEED (0xB000)
+
+#define SETUPTIME 15
+
+#define PlayerCommand(player,command) \
+ (PlayerCmds[(player)]->Commands[(command)])
+
+#define ClientCommand(player,command) \
+ (ClientCmds[(player)]->Commands[(command)])
+
+#define LocalCommand(command) \
+ (LocalCmds->Commands[(command)])
+
+#define ServerCommand(command) \
+ (ServerCmds->Commands[(command)])
+
+#define CommandAddress(time) \
+ (((time)-controlupdatestartedtime) & (MAXCMDS-1))
+
+#define NextLocalCommand() \
+ (LocalCommand(CommandAddress(controlupdatetime)))
+
+#define NextServerCommand() \
+ (ServerCommand(CommandAddress(serverupdatetime)))
+
+#define ClientTimeCommand(which,whichtime) \
+ (ClientCmds[(which)]->Commands[(CommandAddress((whichtime)))])
+
+#define ServerCommandStatus(whichtime) \
+ (CommandState[0]->CommandStates[(CommandAddress((whichtime)))])
+
+#define ServerCommandNumberStatus(command) \
+ (CommandState[0]->CommandStates[(command)])
+
+#define ClientCommandStatus(which, whichtime) \
+ (CommandState[(which+1)]->CommandStates[(CommandAddress((whichtime)))])
+
+#define ClientCommandNumberStatus(which, command) \
+ (CommandState[(which+1)]->CommandStates[(command)])
+
+/*
+#define PacketAddress(time) \
+ ((time) & (MAXCMDS-1))
+*/
+
+#define PacketAddress(time) \
+ (time)
+
+
+#define NETWORKTIMEOUT (VBLCOUNTER/3)
+#define MODEMTIMEOUT (VBLCOUNTER/2)
+#define SERVERTIMEOUT (VBLCOUNTER<<3)
+
+#define MAXPOLLTICS 3
+
+
+typedef enum {
+ scfp_nodata,
+ scfp_gameready,
+ scfp_data,
+ scfp_done
+} setupcheckforpacketstate;
+
+typedef enum {
+ cs_ready,
+ cs_notarrived,
+ cs_fixing
+} en_CommandStatus;
+
+typedef enum {
+ player_ingame,
+ player_quitgame,
+ player_leftgame
+} en_playerstatus;
+
+void PreparePacket (MoveType * pkt);
+int GetPacketSize (void * pkt);
+void SendPacket (void * pkt, int dest);
+void GetRemotePacket (int from, int delay);
+void ResendLocalPackets (int time, int dest, int numpackets);
+void ResendServerPackets (int time, int dest, int numpackets);
+void ResendPacket (void * pkt, int dest);
+void AddClientDelta (void * pkt, int src);
+void FixupPacket (void * pkt, int src);
+void ProcessPacket (void * pkt, int src);
+void AddServerPacket(void * pkt, int src);
+void AddClientPacket (void * pkt, int src);
+void AddPacket (void * pkt, int src);
+void RequestPacket (int time, int dest, int numpackets);
+boolean AllPlayersReady ( void );
+boolean AreClientsReady ( void );
+boolean IsServerCommandReady ( int time );
+void UpdatePlayerObj ( int player );
+void AddServerSubPacket(COM_ServerHeaderType * serverpkt);
+void AddSubPacket (void * pkt, int src);
+
+
+#endif
--- /dev/null
+++ b/rott/_rt_play.h
@@ -1,0 +1,125 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_playr_private
+#define _rt_playr_private
+
+#include "watcom.h"
+//double dTopYZANGLELIMIT; in winrott.c
+#define TopYZANGLELIMIT (44*FINEANGLES/360)//bna added
+#define YZANGLELIMIT (80*FINEANGLES/360)//bna--(30*FINEANGLES/360)
+/*
+//bna++ had to limit this or the sky would fuck up
+#define TopYZANGLELIMIT (6*FINEANGLES/360)//bna added
+#define YZANGLELIMIT (40*FINEANGLES/360)//bna--(30*FINEANGLES/360)
+//partly fixed you can now se up but not down very much see rt_playr.c TopYZANGLELIMIT
+*/
+
+
+#define YZTILTSPEED 20*4//*2 = bna added
+#define SNAPBACKSPEED 10*15//*2 = bna added
+#define YZHORIZONSPEED 4*5//*2 = bna added
+#define HORIZONYZOFFSET (FINEANGLES/4)
+#define SetPlayerHorizon(ps,hlevel) \
+ { \
+ if ((hlevel)>YZANGLELIMIT) \
+ (ps)->horizon=HORIZONYZOFFSET+YZANGLELIMIT;\
+ else if ((hlevel)<-YZANGLELIMIT) \
+ (ps)->horizon=HORIZONYZOFFSET-YZANGLELIMIT;\
+ else \
+ (ps)->horizon=HORIZONYZOFFSET+(hlevel);\
+ }
+
+#define StartWeaponChange \
+{\
+ SD_PlaySoundRTP(SD_SELECTWPNSND,ob->x,ob->y);\
+ pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/GMOVE;\
+ if ((ob==player) && SHOW_BOTTOM_STATUS_BAR() )\
+ DrawBarAmmo (false); \
+}
+
+
+#define BULLETHOLEOFFSET 0x700
+
+#define M_DIST(x1,x2,y1,y2) (((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)))
+
+#define W_CHANGE(x) ((x->weapondowntics) || (x->weaponuptics))
+#define NOMOM ((!ob->momentumx) && (!ob->momentumy))
+#define DISTOK(p1,p2,d) (abs((p1)-(p2)) <= d)
+#define Fix(a) (a &= (FINEANGLES-1))
+#define REMOTEPKTSIZE (sizeof(MoveType))
+#define BJRUNSPEED 2048
+#define BJJUMPSPEED 680
+#define PROJECTILESIZE 0xc000l
+
+#define MOVESCALE 150l
+#define BACKMOVESCALE 100l
+#define EXTRAPOINTS 40000
+#define JETPACKTHRUST (64)
+
+#define RUNMOVE 0xa00
+#define BASEMOVE 0x600
+#define ANGLEMOVE 0x100000
+
+#define SGN(x) (x>0 ? 1 : -1)
+#define NETMOM (BASEMOVE+0x10000)
+
+#define DISTANCE(x1,x2,y1,y2) (FixedMulShift((x1-x2),(x1-x2),16)+FixedMulShift((y1-y2),(y1-y2),16))
+
+#define TILTLIMIT 95
+#define PLAYERSTEPTIME 0xf000
+
+#define HITWALLSPEED 0x2800
+#define GODVIEWANGLE FINEANGLES/150
+#define GODOFFSET 10
+#define DOGOFFSET 46
+#define KESTICS 70
+#define BBTIME 105
+
+#define KEYBOARDNORMALTURNAMOUNT (0x160000)
+//#define KEYBOARDPREAMBLETURNAMOUNT (0xe0000)
+#define KEYBOARDPREAMBLETURNAMOUNT (0xa0000)
+#define TURBOTURNTIME (5)
+#define TURBOTURNAMOUNT (0x1e000)
+#define TURNAROUNDSPEED ((ANG180<<16)/15)
+
+#define VR_INPUT_SERVICE (0x30)
+#define VR_FEEDBACK_SERVICE (0x31)
+
+#define VR_RUNBUTTON (0)
+#define VR_STRAFELEFTBUTTON (1)
+#define VR_STRAFERIGHTBUTTON (2)
+#define VR_ATTACKBUTTON (3)
+#define VR_LOOKUPBUTTON (4)
+#define VR_LOOKDOWNBUTTON (5)
+#define VR_SWAPWEAPONBUTTON (6)
+#define VR_USEBUTTON (7)
+#define VR_HORIZONUPBUTTON (8)
+#define VR_HORIZONDOWNBUTTON (9)
+#define VR_MAPBUTTON (10)
+#define VR_PISTOLBUTTON (11)
+#define VR_DUALPISTOLBUTTON (12)
+#define VR_MP40BUTTON (13)
+#define VR_MISSILEWEAPONBUTTON (14)
+#define VR_RECORDBUTTON (15)
+
+#define STEPADJUST 3
+void BatAttack(objtype*ob);
+void T_DogLick (objtype *ob);
+#endif
--- /dev/null
+++ b/rott/_rt_rand.h
@@ -1,0 +1,291 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_rand_private
+#define _rt_rand_private
+
+//****************************************************************************
+//
+// Private header for RT_RAND.C
+//
+//****************************************************************************
+
+#define SIZE_OF_RANDOM_TABLE 2048
+
+static const unsigned char RandomTable[ SIZE_OF_RANDOM_TABLE ] =
+{
+ 107, 65, 179, 81, 212, 1, 34, 230,
+ 167, 142, 82, 27, 62, 88, 140, 119,
+ 222, 252, 254, 160, 26, 33, 30, 234,
+ 162, 216, 126, 42, 20, 108, 245, 150,
+ 167, 145, 215, 226, 153, 184, 251, 141,
+ 116, 225, 201, 114, 111, 92, 223, 185,
+ 199, 160, 244, 190, 113, 77, 217, 239,
+ 15, 239, 129, 243, 21, 242, 202, 183,
+ 49, 151, 38, 38, 147, 179, 234, 130,
+ 138, 110, 228, 118, 93, 81, 253, 98,
+ 246, 44, 75, 161, 189, 86, 85, 204,
+ 169, 95, 199, 178, 186, 123, 200, 250,
+ 118, 242, 86, 48, 7, 205, 71, 132,
+ 185, 214, 192, 68, 191, 236, 175, 197,
+ 199, 177, 163, 57, 220, 139, 133, 182,
+ 91, 196, 246, 29, 177, 82, 184, 226,
+ 209, 151, 206, 250, 195, 119, 193, 235,
+ 144, 146, 58, 61, 245, 83, 204, 214,
+ 249, 164, 212, 172, 90, 199, 242, 182,
+ 228, 159, 127, 37, 209, 165, 89, 122,
+ 87, 254, 222, 43, 148, 205, 155, 230,
+ 74, 127, 238, 181, 154, 170, 232, 47,
+ 105, 31, 96, 166, 208, 5, 201, 73,
+ 244, 67, 55, 168, 84, 221, 251, 85,
+ 44, 198, 8, 35, 229, 122, 229, 80,
+ 137, 28, 202, 135, 211, 69, 100, 250,
+ 224, 156, 75, 128, 176, 53, 207, 157,
+ 241, 216, 210, 124, 163, 248, 223, 174,
+ 241, 235, 97, 120, 25, 3, 218, 102,
+ 143, 187, 202, 116, 209, 253, 227, 151,
+ 203, 254, 223, 65, 146, 255, 231, 237,
+ 162, 187, 194, 90, 198, 81, 219, 94,
+ 70, 158, 106, 175, 81, 239, 181, 79,
+ 62, 184, 21, 30, 98, 245, 233, 8,
+ 57, 54, 133, 95, 43, 125, 161, 109,
+ 167, 130, 32, 46, 72, 3, 42, 34,
+ 147, 139, 19, 122, 49, 23, 253, 192,
+ 231, 116, 165, 8, 15, 16, 223, 140,
+ 29, 136, 2, 114, 248, 219, 214, 168,
+ 36, 241, 210, 63, 230, 42, 197, 100,
+ 134, 159, 179, 149, 17, 96, 152, 45,
+ 93, 151, 26, 202, 35, 58, 189, 220,
+ 74, 173, 250, 76, 57, 52, 55, 14,
+ 205, 80, 213, 190, 14, 108, 60, 89,
+ 236, 41, 53, 59, 249, 237, 88, 217,
+ 129, 252, 169, 123, 87, 23, 91, 79,
+ 36, 164, 89, 24, 102, 111, 104, 115,
+ 116, 221, 212, 82, 166, 16, 244, 18,
+ 68, 73, 64, 194, 82, 115, 121, 216,
+ 133, 47, 85, 124, 242, 144, 1, 65,
+ 0, 75, 91, 83, 137, 183, 132, 15,
+ 66, 227, 67, 98, 186, 100, 208, 150,
+ 74, 61, 69, 130, 120, 56, 39, 21,
+ 44, 166, 180, 145, 97, 101, 68, 19,
+ 243, 162, 222, 228, 9, 160, 185, 10,
+ 168, 64, 109, 198, 113, 75, 48, 52,
+ 119, 163, 176, 201, 12, 246, 20, 92,
+ 31, 175, 33, 4, 70, 169, 218, 86,
+ 240, 127, 7, 38, 102, 94, 112, 90,
+ 114, 63, 139, 119, 45, 5, 183, 224,
+ 155, 13, 141, 90, 93, 177, 118, 67,
+ 211, 117, 58, 158, 135, 83, 236, 194,
+ 72, 59, 131, 40, 196, 232, 247, 132,
+ 18, 73, 37, 207, 50, 187, 32, 174,
+ 13, 34, 135, 39, 46, 192, 51, 203,
+ 216, 3, 188, 99, 245, 112, 61, 206,
+ 127, 118, 136, 186, 153, 148, 140, 106,
+ 55, 201, 19, 9, 27, 97, 84, 24,
+ 48, 227, 108, 202, 5, 190, 6, 235,
+ 160, 146, 123, 222, 212, 147, 27, 28,
+ 50, 226, 200, 221, 180, 244, 34, 146,
+ 41, 104, 37, 217, 10, 238, 52, 198,
+ 4, 29, 126, 16, 45, 124, 64, 25,
+ 40, 20, 138, 225, 71, 247, 128, 62,
+ 62, 178, 31, 251, 197, 215, 226, 193,
+ 28, 25, 82, 15, 21, 43, 30, 86,
+ 50, 99, 199, 191, 80, 171, 250, 4,
+ 149, 61, 163, 128, 143, 95, 76, 56,
+ 14, 109, 54, 84, 137, 43, 77, 255,
+ 204, 151, 129, 8, 20, 26, 193, 38,
+ 205, 125, 203, 22, 78, 47, 101, 37,
+ 121, 113, 141, 36, 33, 23, 131, 55,
+ 78, 96, 123, 228, 69, 213, 51, 147,
+ 195, 195, 85, 54, 225, 65, 143, 13,
+ 152, 60, 110, 29, 146, 179, 164, 17,
+ 96, 67, 156, 7, 3, 92, 26, 104,
+ 157, 220, 211, 154, 103, 2, 174, 136,
+ 83, 229, 18, 116, 66, 87, 0, 74,
+ 98, 58, 75, 162, 254, 177, 89, 173,
+ 169, 107, 12, 90, 71, 193, 53, 255,
+ 138, 2, 233, 163, 11, 138, 183, 209,
+ 119, 210, 249, 112, 113, 30, 185, 180,
+ 11, 171, 164, 77, 5, 99, 35, 218,
+ 11, 159, 221, 148, 170, 137, 129, 188,
+ 231, 172, 191, 135, 176, 33, 189, 68,
+ 190, 152, 7, 220, 246, 203, 181, 63,
+ 199, 91, 251, 208, 217, 39, 170, 111,
+ 182, 209, 216, 247, 240, 165, 153, 118,
+ 238, 233, 204, 12, 126, 105, 168, 234,
+ 38, 184, 132, 110, 145, 227, 165, 92,
+ 241, 24, 251, 231, 213, 126, 240, 214,
+ 31, 11, 223, 46, 0, 35, 218, 242,
+ 211, 191, 48, 110, 253, 94, 161, 139,
+ 42, 148, 198, 246, 239, 107, 57, 5,
+ 117, 252, 9, 12, 73, 77, 58, 167,
+ 6, 142, 32, 34, 72, 31, 243, 170,
+ 0, 93, 182, 56, 254, 158, 250, 23,
+ 77, 81, 45, 69, 142, 237, 225, 44,
+ 232, 142, 209, 115, 61, 38, 224, 70,
+ 53, 82, 10, 229, 214, 224, 101, 42,
+ 100, 121, 133, 85, 67, 150, 116, 91,
+ 79, 79, 235, 22, 1, 244, 16, 101,
+ 88, 25, 43, 242, 53, 106, 128, 40,
+ 18, 2, 196, 22, 47, 96, 130, 249,
+ 49, 117, 178, 171, 132, 189, 95, 66,
+ 153, 200, 71, 71, 215, 113, 102, 131,
+ 172, 235, 192, 204, 107, 127, 60, 52,
+ 254, 84, 20, 27, 107, 44, 72, 149,
+ 230, 87, 64, 144, 140, 186, 154, 49,
+ 76, 156, 162, 219, 9, 146, 41, 80,
+ 59, 142, 147, 184, 115, 158, 103, 140,
+ 8, 234, 157, 17, 112, 22, 163, 187,
+ 47, 178, 207, 63, 125, 202, 156, 30,
+ 97, 193, 171, 173, 204, 28, 4, 195,
+ 109, 211, 105, 103, 179, 221, 203, 138,
+ 139, 172, 14, 44, 119, 150, 185, 180,
+ 205, 255, 152, 94, 205, 173, 40, 134,
+ 13, 65, 194, 196, 68, 124, 26, 134,
+ 85, 228, 50, 216, 159, 254, 237, 206,
+ 103, 69, 90, 187, 182, 183, 2, 114,
+ 3, 201, 1, 129, 212, 232, 81, 33,
+ 56, 182, 133, 176, 19, 6, 144, 84,
+ 145, 24, 243, 234, 35, 25, 89, 150,
+ 54, 143, 207, 104, 248, 102, 41, 253,
+ 46, 44, 197, 208, 200, 52, 219, 238,
+ 223, 241, 60, 230, 196, 42, 88, 51,
+ 170, 25, 40, 114, 39, 45, 57, 29,
+ 186, 54, 36, 167, 51, 249, 194, 108,
+ 250, 199, 67, 212, 123, 151, 92, 32,
+ 46, 12, 248, 165, 223, 24, 143, 189,
+ 120, 57, 38, 222, 169, 17, 188, 27,
+ 209, 176, 215, 108, 177, 96, 50, 154,
+ 41, 15, 32, 181, 99, 120, 73, 225,
+ 49, 200, 43, 177, 72, 202, 97, 92,
+ 240, 110, 252, 21, 28, 192, 70, 128,
+ 85, 60, 127, 63, 235, 100, 155, 65,
+ 241, 119, 34, 80, 75, 117, 148, 102,
+ 15, 90, 121, 206, 104, 164, 132, 98,
+ 36, 108, 214, 0, 84, 94, 107, 154,
+ 14, 26, 23, 93, 195, 224, 162, 171,
+ 245, 76, 125, 158, 120, 66, 80, 130,
+ 183, 120, 179, 118, 31, 176, 106, 184,
+ 164, 111, 59, 253, 118, 62, 114, 215,
+ 156, 161, 127, 210, 112, 122, 204, 86,
+ 29, 69, 187, 218, 233, 47, 188, 91,
+ 105, 153, 236, 116, 135, 19, 83, 175,
+ 88, 166, 156, 238, 245, 227, 248, 161,
+ 10, 180, 22, 230, 157, 205, 6, 37,
+ 3, 234, 155, 49, 239, 229, 122, 223,
+ 234, 206, 82, 135, 190, 77, 130, 197,
+ 144, 226, 123, 181, 143, 208, 169, 8,
+ 1, 174, 97, 177, 232, 201, 210, 193,
+ 192, 62, 211, 28, 252, 19, 189, 229,
+ 191, 246, 7, 202, 35, 20, 28, 30,
+ 70, 221, 55, 159, 237, 10, 15, 134,
+ 124, 103, 73, 172, 26, 201, 13, 117,
+ 35, 131, 136, 66, 33, 245, 159, 207,
+ 225, 147, 18, 248, 126, 131, 33, 153,
+ 101, 60, 186, 216, 250, 11, 30, 50,
+ 57, 58, 151, 178, 181, 227, 128, 253,
+ 10, 5, 224, 48, 160, 34, 7, 111,
+ 124, 27, 160, 75, 137, 17, 53, 39,
+ 243, 236, 39, 81, 217, 122, 79, 32,
+ 13, 115, 191, 167, 137, 87, 228, 91,
+ 86, 78, 18, 22, 40, 76, 94, 129,
+ 119, 87, 63, 197, 203, 21, 218, 185,
+ 166, 49, 161, 213, 38, 111, 209, 154,
+ 43, 152, 134, 132, 4, 133, 108, 83,
+ 145, 41, 97, 74, 251, 173, 42, 213,
+ 46, 118, 73, 68, 21, 244, 106, 158,
+ 11, 90, 252, 140, 44, 157, 194, 66,
+ 229, 58, 215, 251, 144, 125, 146, 172,
+ 165, 136, 105, 102, 173, 95, 150, 169,
+ 78, 230, 111, 160, 196, 112, 120, 231,
+ 168, 152, 149, 174, 128, 232, 194, 122,
+ 3, 74, 231, 105, 12, 239, 180, 239,
+ 89, 235, 95, 157, 149, 187, 6, 203,
+ 188, 71, 110, 8, 126, 242, 188, 249,
+ 71, 123, 162, 93, 59, 65, 16, 222,
+ 192, 24, 27, 142, 168, 114, 89, 220,
+ 226, 182, 207, 94, 195, 207, 174, 228,
+ 142, 130, 115, 175, 154, 106, 206, 48,
+ 185, 147, 155, 224, 239, 64, 88, 83,
+ 54, 247, 113, 248, 137, 96, 5, 110,
+ 240, 51, 1, 208, 166, 200, 233, 167,
+ 230, 14, 20, 198, 36, 13, 0, 220,
+ 165, 104, 85, 122, 1, 255, 212, 161,
+ 190, 37, 86, 226, 195, 105, 78, 244,
+ 236, 168, 48, 211, 121, 216, 25, 144,
+ 16, 237, 7, 75, 12, 99, 56, 109,
+ 218, 87, 35, 204, 155, 61, 191, 41,
+ 61, 57, 121, 236, 62, 22, 187, 95,
+ 92, 69, 210, 163, 205, 214, 34, 84,
+ 73, 184, 109, 124, 231, 103, 217, 241,
+ 77, 175, 183, 232, 198, 164, 14, 125,
+ 103, 197, 249, 241, 176, 59, 48, 50,
+ 25, 222, 134, 199, 252, 196, 23, 19,
+ 78, 0, 59, 120, 91, 121, 117, 228,
+ 52, 68, 113, 127, 141, 67, 65, 130,
+ 132, 243, 160, 138, 138, 116, 10, 98,
+ 170, 70, 246, 206, 219, 28, 94, 226,
+ 29, 58, 255, 31, 141, 82, 134, 152,
+ 251, 84, 52, 23, 154, 139, 74, 55,
+ 47, 198, 167, 162, 4, 16, 220, 53,
+ 37, 158, 135, 136, 190, 86, 151, 178,
+ 238, 161, 88, 171, 148, 169, 137, 212,
+ 181, 146, 189, 70, 49, 79, 142, 131,
+ 195, 126, 149, 156, 93, 55, 164, 174,
+ 87, 243, 66, 92, 207, 9, 126, 123,
+ 40, 51, 133, 143, 9, 55, 193, 173,
+ 56, 64, 210, 159, 6, 178, 145, 153,
+ 115, 215, 185, 238, 101, 210, 98, 157,
+ 95, 171, 235, 217, 240, 232, 107, 53,
+ 54, 211, 111, 236, 100, 37, 147, 64,
+ 60, 215, 174, 136, 128, 98, 79, 234,
+ 145, 76, 197, 165, 191, 141, 114, 109,
+ 148, 214, 93, 12, 163, 125, 222, 96,
+ 71, 220, 8, 225, 200, 14, 139, 166,
+ 155, 9, 237, 9, 172, 6, 229, 179,
+ 247, 76, 24, 213, 26, 248, 56, 247,
+ 106, 221, 63, 20, 206, 231, 168, 196,
+ 208, 36, 31, 175, 178, 255, 124, 156,
+ 129, 186, 45, 201, 7, 112, 189, 68,
+ 225, 64, 150, 74, 2, 218, 62, 159,
+ 4, 11, 213, 40, 23, 15, 67, 52,
+ 182, 203, 246, 194, 72, 33, 89, 104,
+ 16, 131, 60, 150, 243, 21, 59, 175,
+ 219, 149, 56, 224, 32, 105, 153, 99,
+ 80, 148, 107, 99, 108, 43, 106, 41,
+ 32, 244, 4, 186, 253, 27, 233, 104,
+ 245, 5, 2, 252, 170, 2, 101, 39,
+ 17, 166, 221, 11, 227, 129, 103, 45,
+ 144, 79, 17, 139, 70, 237, 176, 6,
+ 76, 134, 54, 30, 69, 13, 100, 149,
+ 141, 227, 255, 22, 179, 61, 88, 97,
+ 121, 29, 24, 77, 170, 190, 242, 109,
+ 152, 47, 81, 140, 45, 46, 249, 78,
+ 180, 143, 102, 19, 208, 177, 72, 72,
+ 247, 51, 115, 3, 141, 117, 39, 188,
+ 180, 171, 83, 1, 0, 51, 100, 112,
+ 172, 18, 219, 136, 155, 125, 200, 131,
+ 157, 217, 78, 63, 213, 238, 193, 173,
+ 145, 46, 101, 158, 42, 140, 110, 66,
+ 183, 181, 233, 188, 10, 133, 36, 135,
+ 17, 254, 138, 233, 117, 240, 184, 80,
+ 113, 18, 99, 219, 240, 50, 192, 247
+};
+
+#endif
--- /dev/null
+++ b/rott/_rt_scal.h
@@ -1,0 +1,25 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_scale_private
+#define _rt_scale_private
+
+#define PLAYERHEIGHT (260<<HEIGHTFRACTION)
+
+#endif
--- /dev/null
+++ b/rott/_rt_soun.h
@@ -1,0 +1,114 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_sound_private
+#define _rt_sound_private
+
+#define SOUNDTYPES 2
+
+typedef struct
+{
+ int snds[SOUNDTYPES];
+ byte flags;
+ byte priority;
+ byte count;
+ int prevhandle;
+ int prevdistance;
+} sound_t;
+
+#define SD_OVERWRITE 0x01
+#define SD_WRITE 0x02
+#define SD_LOOP 0x04
+#define SD_PITCHSHIFTOFF 0x08
+#define SD_PLAYONCE 0x10
+
+enum {
+ sd_prio0=17,
+ sd_prio1=16,
+ sd_prio2=15,
+ sd_prio3=14,
+ sd_prio4=13,
+ sd_prio5=12,
+ sd_prio6=11,
+ sd_prio7=10,
+ sd_prio8=9,
+ sd_prio9=8,
+ sd_prio10=7,
+ sd_prio11=6,
+ sd_prio12=5,
+ sd_prio13=4,
+ sd_prio14=3,
+ sd_prio15=2,
+ sd_prio16=1
+} ;
+
+#define SD_PRIOSECRET sd_prio1
+#define SD_PRIOREMOTE sd_prio1
+#define SD_PRIOPHURT sd_prio1
+#define SD_PRIOGAME sd_prio2
+#define SD_PRIOBOSS sd_prio2
+#define SD_PRIOGODDOG sd_prio2
+#define SD_PRIOEXPL sd_prio3
+#define SD_PRIOASNEAK sd_prio3
+#define SD_PRIOADEATH sd_prio3
+#define SD_PRIOPMISS sd_prio4
+#define SD_PRIOPGUNS sd_prio5
+#define SD_PRIOAFIRE sd_prio6
+#define SD_PRIOPMP40 sd_prio7
+#define SD_PRIOAHURT sd_prio8
+#define SD_PRIOGLASS sd_prio9
+#define SD_PRIOPSNDS sd_prio11
+#define SD_PRIOPCAUSD sd_prio12
+#define SD_PRIOAGREET sd_prio13
+#define SD_PRIOENVRON sd_prio14
+#define SD_PRIOQUIT sd_prio15
+#define SD_PRIOMENU sd_prio16
+
+#define SD_DISTANCESHIFT 12
+
+#define USEADLIB 255
+
+#define SD_RANDOMSHIFT 1
+
+#define PitchOffset() ((RandomNumber("Pitch Offset",0)-128)>>SD_RANDOMSHIFT)
+
+#define SoundOffset(x) (sounds[x].snds[soundtype])
+
+#define GUSMIDIINIFILE ("gusmidi.ini")
+
+
+typedef enum {
+ loop_yes,
+ loop_no
+} looptypes;
+
+
+typedef struct
+{
+ byte loopflag;
+ byte songtype;
+ char lumpname[9];
+ char songname[40];
+} song_t;
+
+int SD_PlayIt ( int sndnum, int angle, int distance, int pitch );
+boolean SD_SoundOkay ( int sndnum );
+
+#endif
+
--- /dev/null
+++ b/rott/_rt_spba.h
@@ -1,0 +1,27 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_spba_private
+#define _rt_spba_private
+
+#define SGN(x) (x>0 ? 1 : -1)
+
+#define NUMSPACEBALLBUTTONS 6
+
+#endif
--- /dev/null
+++ b/rott/_rt_stat.h
@@ -1,0 +1,58 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_stat_private
+#define _rt_stat_private
+
+void AddStatic(statobj_t*);
+void AddAnimStatic(statobj_t*);
+void PreCacheStaticSounds(int);
+
+#define SOLIDCOLORTICTIME 1
+#define SOLIDCOLORINCREMENT 1
+#define MAXFIRECOLOR 248
+#define INITIALFIRECOLOR 246
+#define IsLight(x,y) ( (x>=0) && (x<=127) && (y>=0) && (y<=127) && \
+ (sprites[x][y]) && (sprites[x][y]->flags & FL_LIGHT) )
+
+typedef struct
+{
+ int tictime,
+ numanims;
+ char firstlump[9];
+} awallinfo_t;
+
+
+typedef struct sas
+{
+ int x,y,z;
+ int flags;
+ signed char ticcount;
+ int hitpoints;
+ short int shapenum;
+ signed char ammo;
+ signed char count;
+ signed char itemnumber;
+ short int areanumber;
+ short int whichstat;
+ byte numanims;
+ int linked_to;
+} saved_stat_type;
+
+#endif
--- /dev/null
+++ b/rott/_rt_str.h
@@ -1,0 +1,44 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//******************************************************************************
+//
+// Private header for RT_STR.C
+//
+//******************************************************************************
+
+#ifndef _rt_str_private
+#define _rt_str_private
+
+//******************************************************************************
+//
+// PROTOTYPES
+//
+//******************************************************************************
+
+void VWB_DrawPropString (const char *string);
+void VW_MeasurePropString (const char *string, int *width, int *height );
+
+//void (*USL_MeasureString)(const char *, int *, int *, font_t *) = VW_MeasurePropString,
+// (*USL_DrawString)(const char *) = VWB_DrawPropString;
+void (*USL_MeasureString)(const char *, int *, int *, font_t *) = (void (*)(const char *, int *, int *, font_t *))VW_MeasurePropString,
+(*USL_DrawString)(const char *) = VWB_DrawPropString;
+
+
+#endif
--- /dev/null
+++ b/rott/_rt_swft.h
@@ -1,0 +1,109 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_swift_private
+#define _rt_swift_private
+
+#ifdef DOS
+//****************************************************************************
+//
+// Private header for RT_SWIFT.C.
+//
+//****************************************************************************
+
+
+
+//****************************************************************************
+//
+// DEFINES
+//
+//****************************************************************************
+
+#define DPMI_INT 0x31
+#define MOUSE_INT 0x33
+#define DOSMEMSIZE 64 // enough for any SWIFT structure
+
+//
+// device type codes, returned in deviceType field (SWIFT_StaticData)
+//
+#define SWIFT_DEV_NONE 0
+#define SWIFT_DEV_CYBERMAN 1
+
+//
+// Dynamic device data
+//
+#define SDD_EXTERNAL_POWER_CONNECTED 1
+#define SDD_EXTERNAL_POWER_TOO_HIGH 2
+
+#define AX(r) ((r).x.eax)
+#define BX(r) ((r).x.ebx)
+#define CX(r) ((r).x.ecx)
+#define DX(r) ((r).x.edx)
+#define SI(r) ((r).x.esi)
+#define DI(r) ((r).x.edi)
+
+
+//****************************************************************************
+//
+// TYPEDEFS
+//
+//****************************************************************************
+
+// Active flag:
+static int fActive; // TRUE after successful init
+// and before termination
+static int nAttached = SWIFT_DEV_NONE; // type of SWIFT device
+
+union REGS regs;
+struct SREGS sregs;
+
+short selector; // selector of DOS memory block
+short segment; // segment of DOS memory block
+void far *pdosmem; // pointer to DOS memory block
+
+// DPMI real mode interrupt structure
+static struct rminfo
+{
+ long di;
+ long si;
+ long bp;
+ long reserved_by_system;
+ long bx;
+ long dx;
+ long cx;
+ long ax;
+ short flags;
+ short es, ds, fs, gs, ip, cs, sp, ss;
+} RMI;
+
+
+//****************************************************************************
+//
+// PROTOTYPES
+//
+//****************************************************************************
+
+void MouseInt (struct rminfo *prmi);
+static void far *allocDOS (unsigned nbytes, short *pseg, short *psel);
+static void freeDOS (short sel);
+
+#endif
+
+#endif
+
--- /dev/null
+++ b/rott/_rt_ted.h
@@ -1,0 +1,90 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_ted_private
+#define _rt_ted_private
+
+#define MAXPRECACHE 3500
+
+#include "rt_actor.h"
+#include "develop.h"
+
+#define SHAREWARE_TAG 0x4d4b
+#define REGISTERED_TAG 0x4344
+#define RTL_VERSION ( 0x0101 )
+#define COMMBAT_SIGNATURE ( "RTC" )
+#define NORMAL_SIGNATURE ( "RTL" )
+#define RTL_HEADER_OFFSET 8
+
+typedef struct
+{
+ int lump;
+ int cachelevel;
+ int type; // To make precaching possible on big endian machines
+} cachetype;
+
+//========================================
+
+typedef struct
+{
+ short RLEWtag;
+ int headeroffsets[100];
+ byte tileinfo[1];
+} mapfiletype;
+
+
+typedef struct
+{
+ int planestart[3];
+ word planelength[3];
+ word width,height;
+ char name[16];
+} maptype;
+
+#define ActorIsPushWall(xx,yy) ((actorat[xx][yy])&&(((objtype *)actorat[xx][yy])->which==PWALL) )
+#define ActorIsWall(xx,yy) ((actorat[xx][yy])&&(((objtype *)actorat[xx][yy])->which==WALL) )
+#define ActorIsSpring(xx,yy) ((actorat[xx][yy])&&(((objtype *)actorat[xx][yy])->obclass==springobj) )
+#define StaticUndefined(xx,yy) ((sprites[xx][yy])&&(((statobj_t *)sprites[xx][yy])->z<-64) )
+
+#define PRECACHEASTRINGX 141
+#define PRECACHEASTRINGY 8
+
+#define PRECACHEESTRINGX 16
+#define PRECACHEESTRINGY 8
+
+#define PRECACHESTRINGX 16
+#define PRECACHESTRINGY 144
+
+#define PRECACHEBARX 28
+#define PRECACHEBARY 178
+
+#define PRECACHELED1X 9
+#define PRECACHELED1Y 8
+
+#define PRECACHELED2X 9
+#define PRECACHELED2Y 12
+
+#define MAXLEDS 57
+
+#define MAXSILLYSTRINGS 32
+
+
+
+
+#endif
--- /dev/null
+++ b/rott/_rt_util.h
@@ -1,0 +1,47 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_util_private
+#define _rt_util_private
+
+#ifdef DOS
+#define PEL_WRITE_ADR 0x3c8
+#define PEL_READ_ADR 0x3c7
+#define PEL_DATA 0x3c9
+#define PEL_MASK 0x3c6
+#endif
+
+#define ERRORROW 2
+#define ERRORCOL 11
+
+#define ERRORFILE ("rotterr.txt")
+#define SOFTERRORFILE ("error.txt")
+#define DEBUGFILE ("rott.dbg")
+#define MAPDEBUGFILE ("mapinfo.txt")
+
+#define SGN(x) ((x>0) ? (1) : ((x==0) ? (0) : (-1)))
+
+#define SLASHES ('\\')
+#define MAXCHARS 8
+
+#define WeightR 3
+#define WeightG 5
+#define WeightB 2
+
+#endif
--- /dev/null
+++ b/rott/_rt_vid.h
@@ -1,0 +1,45 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_vid_private
+#define _rt_vid_private
+
+//******************************************************************************
+//
+// Private header for RT_VID.C
+//
+//******************************************************************************
+
+
+//******************************************************************************
+//
+// DEFINES
+//
+//******************************************************************************
+
+#define PIXTOBLOCK 4
+
+#define VW_Hlin(x,z,y,c) VL_Hlin(x,y,(z)-(x)+1,c)
+#define VW_Vlin(y,z,x,c) VL_Vlin(x,y,(z)-(y)+1,c)
+
+#define VW_THlin(x,z,y,up) VL_THlin(x,y,(z)-(x)+1, up)
+#define VW_TVlin(y,z,x,up) VL_TVlin(x,y,(z)-(y)+1, up)
+
+
+#endif
--- /dev/null
+++ b/rott/_w_wad.h
@@ -1,0 +1,76 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _w_wad_private
+#define _w_wad_private
+
+#include "develop.h"
+
+#define CHECKPERIOD 20
+
+
+#if ( SHAREWARE == 1 )
+
+#if ( DELUXE == 1)
+#define WADCHECKSUM (54748)
+#elif ( LOWCOST == 1)
+#define WADCHECKSUM (12185)
+#else
+#ifdef DOS
+#define WADCHECKSUM (45677)
+#else
+#define WADCHECKSUM (20567)
+#endif
+#endif
+
+#else
+
+#define WADCHECKSUM (24222)
+
+#endif
+
+//===============
+// TYPES
+//===============
+
+
+typedef struct
+{
+ char name[8];
+ int handle,position,size;
+ int byteswapped;
+} lumpinfo_t;
+
+
+typedef struct
+{
+ char identification[4]; // should be IWAD
+ int numlumps;
+ int infotableofs;
+} wadinfo_t;
+
+
+typedef struct
+{
+ int filepos;
+ int size;
+ char name[8];
+} filelump_t;
+
+#endif
--- /dev/null
+++ b/rott/_z_zone.h
@@ -1,0 +1,57 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _z_zone_private
+#define _z_zone_private
+
+#include "develop.h"
+
+#define MINFRAGMENT 64
+#define DPMI_INT 0x31
+#define MAXMEMORYSIZE 9000000
+
+#define LEVELZONESIZE 250000
+
+// memory storage data types
+
+#define MEMORYPRETAG (0x1a2b3c4d)
+#define MEMORYPOSTTAG (0x9f8e7d6b)
+
+typedef struct memblock_s
+{
+#if (MEMORYCORRUPTIONTEST==1)
+ int pretag;
+#endif
+ int size; // including the header and possibly tiny fragments
+ void **user; // NULL if a free block
+ int tag; // purgelevel
+ struct memblock_s *next, *prev;
+#if (MEMORYCORRUPTIONTEST==1)
+ int posttag;
+#endif
+} memblock_t;
+
+typedef struct
+{
+ int size; // total bytes malloced, including header
+ memblock_t blocklist; // start / end cap for linked list
+ memblock_t *rover;
+} memzone_t;
+
+#endif
--- /dev/null
+++ b/rott/audiolib/Makefile
@@ -1,0 +1,31 @@
+AUDIOLIB ?= audiolib.a
+
+AR ?= ar
+CC ?= gcc
+RANLIB ?= ranlib
+
+ARFLAGS ?= rcT
+
+CFLAGS ?= -g -O2
+CFLAGS += -Wall
+CFLAGS += $(shell sdl-config --cflags)
+
+OBJS :=
+OBJS += fx_man.o
+OBJS += dsl.o
+OBJS += ll_man.o
+OBJS += multivoc.o
+OBJS += mv_mix.o
+OBJS += mvreverb.o
+OBJS += nodpmi.o
+OBJS += pitch.o
+OBJS += user.o
+OBJS += usrhooks.o
+
+$(AUDIOLIB): $(OBJS)
+ $(RM) $@
+ $(AR) $(ARFLAGS) $@ $^
+ $(RANLIB) $@
+
+clean:
+ $(RM) $(AUDIOLIB) $(OBJS)
--- /dev/null
+++ b/rott/audiolib/Makefile.am
@@ -1,0 +1,13 @@
+noinst_LIBRARIES = libaudiolib.a
+libaudiolib_a_SOURCES = \
+ dsl.c \
+ fx_man.c \
+ ll_man.c \
+ multivoc.c \
+ mv_mix.c \
+ mvreverb.c \
+ nodpmi.c \
+ pitch.c \
+ user.c \
+ usrhooks.c
+libaudiolib_a_CFLAGS = @SDL_CFLAGS@
--- /dev/null
+++ b/rott/audiolib/Makefile_old
@@ -1,0 +1,30 @@
+AUDIOLIB ?= audiolib.a
+
+AR ?= ar
+CC ?= gcc
+RANLIB ?= ranlib
+
+ARFLAGS ?= rcT
+CFLAGS ?= -g -O2
+CFLAGS += -Wall
+CFLAGS += $(shell sdl-config --cflags)
+
+OBJS :=
+OBJS += fx_man.o
+OBJS += dsl.o
+OBJS += ll_man.o
+OBJS += multivoc.o
+OBJS += mv_mix.o
+OBJS += mvreverb.o
+OBJS += nodpmi.o
+OBJS += pitch.o
+OBJS += user.o
+OBJS += usrhooks.o
+
+$(AUDIOLIB): $(OBJS)
+ $(RM) $@
+ $(AR) $(ARFLAGS) $@ $^
+ $(RANLIB) $@
+
+clean:
+ $(RM) $(AUDIOLIB) $(OBJS)
--- /dev/null
+++ b/rott/audiolib/_al_midi.h
@@ -1,0 +1,174 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef ___AL_MIDI_H
+#define ___AL_MIDI_H
+
+#define NO_ADLIB_DETECTION "NOAL"
+
+#define STEREO_DETUNE 5
+
+#define lobyte( num ) ( ( unsigned )*( ( char * )&( num ) ) )
+#define hibyte( num ) ( ( unsigned )*( ( ( char * )&( num ) ) + 1 ) )
+
+#define AL_VoiceNotFound -1
+
+#define alFreqH 0xb0
+#define alEffects 0xbd
+
+/* Number of slots for the voices on the chip */
+#define NumChipSlots 18
+
+#define NUM_VOICES 9
+#define NUM_CHANNELS 16
+
+#define NOTE_ON 0x2000 /* Used to turn note on or toggle note */
+#define NOTE_OFF 0x0000
+
+#define MAX_VELOCITY 0x7f
+#define MAX_OCTAVE 7
+#define MAX_NOTE ( MAX_OCTAVE * 12 + 11 )
+#define FINETUNE_MAX 31
+#define FINETUNE_RANGE ( FINETUNE_MAX + 1 )
+
+#define PITCHBEND_CENTER 1638400
+
+#define note_off 0x80
+#define note_on 0x90
+#define poly_aftertouch 0xa0
+#define control_change 0xb0
+#define program_chng 0xc0
+#define channel_aftertouch 0xd0
+#define pitch_wheel 0xe0
+
+#define MIDI_VOLUME 7
+#define MIDI_PAN 10
+#define MIDI_DETUNE 94
+#define MIDI_ALL_NOTES_OFF 0x7B
+#define MIDI_RESET_ALL_CONTROLLERS 0x79
+#define MIDI_RPN_MSB 100
+#define MIDI_RPN_LSB 101
+#define MIDI_DATAENTRY_MSB 6
+#define MIDI_DATAENTRY_LSB 38
+#define MIDI_PITCHBEND_RPN 0
+
+enum cromatic_scale
+ {
+ C = 0x157,
+ C_SHARP = 0x16B,
+ D_FLAT = 0x16B,
+ D = 0x181,
+ D_SHARP = 0x198,
+ E_FLAT = 0x198,
+ E = 0x1B0,
+ F_FLAT = 0x1B0,
+ E_SHARP = 0x1CA,
+ F = 0x1CA,
+ F_SHARP = 0x1E5,
+ G_FLAT = 0x1E5,
+ G = 0x202,
+ G_SHARP = 0x220,
+ A_FLAT = 0x220,
+ A = 0x241,
+ A_SHARP = 0x263,
+ B_FLAT = 0x263,
+ B = 0x287,
+ C_FLAT = 0x287,
+ B_SHARP = 0x2AE,
+ };
+
+/* Definition of octave information to be ORed onto F-Number */
+
+enum octaves
+ {
+ OCTAVE_0 = 0x0000,
+ OCTAVE_1 = 0x0400,
+ OCTAVE_2 = 0x0800,
+ OCTAVE_3 = 0x0C00,
+ OCTAVE_4 = 0x1000,
+ OCTAVE_5 = 0x1400,
+ OCTAVE_6 = 0x1800,
+ OCTAVE_7 = 0x1C00
+ };
+
+typedef struct VOICE
+ {
+ struct VOICE *next;
+ struct VOICE *prev;
+
+ unsigned num;
+ unsigned key;
+ unsigned velocity;
+ unsigned channel;
+ unsigned pitchleft;
+ unsigned pitchright;
+ int timbre;
+ int port;
+ unsigned status;
+ } VOICE;
+
+typedef struct
+ {
+ VOICE *start;
+ VOICE *end;
+ } VOICELIST;
+
+typedef struct
+ {
+ VOICELIST Voices;
+ int Timbre;
+ int Pitchbend;
+ int KeyOffset;
+ unsigned KeyDetune;
+ unsigned Volume;
+ unsigned EffectiveVolume;
+ int Pan;
+ int Detune;
+ unsigned RPN;
+ short PitchBendRange;
+ short PitchBendSemiTones;
+ short PitchBendHundreds;
+ } CHANNEL;
+
+typedef struct
+ {
+ unsigned char SAVEK[ 2 ];
+ unsigned char Level[ 2 ];
+ unsigned char Env1[ 2 ];
+ unsigned char Env2[ 2 ];
+ unsigned char Wave[ 2 ];
+ unsigned char Feedback;
+ signed char Transpose;
+ signed char Velocity;
+ } TIMBRE;
+
+extern TIMBRE ADLIB_TimbreBank[ 256 ];
+
+static void AL_ResetVoices( void );
+static void AL_CalcPitchInfo( void );
+static void AL_SetVoiceTimbre( int voice );
+static void AL_SetVoiceVolume( int voice );
+static int AL_AllocVoice( void );
+static int AL_GetVoice( int channel, int key );
+static void AL_SetVoicePitch( int voice );
+static void AL_SetChannelVolume( int channel, int volume );
+static void AL_SetChannelPan( int channel, int pan );
+static void AL_SetChannelDetune( int channel, int detune );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/_blaster.h
@@ -1,0 +1,133 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: _BLASTER.H
+
+ author: James R. Dose
+ date: February 4, 1994
+
+ Private header for for BLASTER.C
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef ___BLASTER_H
+#define ___BLASTER_H
+
+#define VALID ( 1 == 1 )
+#define INVALID ( !VALID )
+
+#define TRUE ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+#define YES ( 1 == 1 )
+#define NO ( !YES )
+
+#define lobyte( num ) ( ( int )*( ( char * )&( num ) ) )
+#define hibyte( num ) ( ( int )*( ( ( char * )&( num ) ) + 1 ) )
+
+#define BLASTER_MixerAddressPort 0x04
+#define BLASTER_MixerDataPort 0x05
+#define BLASTER_ResetPort 0x06
+#define BLASTER_ReadPort 0x0A
+#define BLASTER_WritePort 0x0C
+#define BLASTER_DataAvailablePort 0x0E
+#define BLASTER_Ready 0xAA
+#define BLASTER_16BitDMAAck 0x0F
+
+#define MIXER_DSP4xxISR_Ack 0x82
+#define MIXER_DSP4xxISR_Enable 0x83
+#define MIXER_MPU401_INT 0x4
+#define MIXER_16BITDMA_INT 0x2
+#define MIXER_8BITDMA_INT 0x1
+#define MIXER_DisableMPU401Interrupts 0xB
+#define MIXER_SBProOutputSetting 0x0E
+#define MIXER_SBProStereoFlag 0x02
+#define MIXER_SBProVoice 0x04
+#define MIXER_SBProMidi 0x26
+#define MIXER_SB16VoiceLeft 0x32
+#define MIXER_SB16VoiceRight 0x33
+#define MIXER_SB16MidiLeft 0x34
+#define MIXER_SB16MidiRight 0x35
+
+#define DSP_Version1xx 0x0100
+#define DSP_Version2xx 0x0200
+#define DSP_Version201 0x0201
+#define DSP_Version3xx 0x0300
+#define DSP_Version4xx 0x0400
+#define DSP_SB16Version DSP_Version4xx
+
+#define DSP_MaxNormalRate 22000
+#define DSP_MaxHighSpeedRate 44000
+
+#define DSP_8BitAutoInitRecord 0x2c
+#define DSP_8BitHighSpeedAutoInitRecord 0x98
+#define DSP_Old8BitADC 0x24
+#define DSP_8BitAutoInitMode 0x1c
+#define DSP_8BitHighSpeedAutoInitMode 0x90
+#define DSP_SetBlockLength 0x48
+#define DSP_Old8BitDAC 0x14
+#define DSP_16BitDAC 0xB6
+#define DSP_8BitDAC 0xC6
+#define DSP_8BitADC 0xCe
+#define DSP_SetTimeConstant 0x40
+#define DSP_Set_DA_Rate 0x41
+#define DSP_Set_AD_Rate 0x42
+#define DSP_Halt8bitTransfer 0xd0
+#define DSP_Continue8bitTransfer 0xd4
+#define DSP_Halt16bitTransfer 0xd5
+#define DSP_Continue16bitTransfer 0xd6
+#define DSP_SpeakerOn 0xd1
+#define DSP_SpeakerOff 0xd3
+#define DSP_GetVersion 0xE1
+#define DSP_Reset 0xFFFF
+
+#define DSP_SignedBit 0x10
+#define DSP_StereoBit 0x20
+
+#define DSP_UnsignedMonoData 0x00
+#define DSP_SignedMonoData ( DSP_SignedBit )
+#define DSP_UnsignedStereoData ( DSP_StereoBit )
+#define DSP_SignedStereoData ( DSP_SignedBit | DSP_StereoBit )
+
+#define BlasterEnv_Address 'A'
+#define BlasterEnv_Interrupt 'I'
+#define BlasterEnv_8bitDma 'D'
+#define BlasterEnv_16bitDma 'H'
+#define BlasterEnv_Type 'T'
+#define BlasterEnv_Midi 'P'
+#define BlasterEnv_EmuAddress 'E'
+
+#define CalcTimeConstant( rate, samplesize ) \
+ ( ( 65536L - ( 256000000L / ( ( samplesize ) * ( rate ) ) ) ) >> 8 )
+
+#define CalcSamplingRate( tc ) \
+ ( 256000000L / ( 65536L - ( tc << 8 ) ) )
+
+typedef struct
+ {
+ int IsSupported;
+ int HasMixer;
+ int MaxMixMode;
+ int MinSamplingRate;
+ int MaxSamplingRate;
+ } CARD_CAPABILITY;
+
+#endif
--- /dev/null
+++ b/rott/audiolib/_guswave.h
@@ -1,0 +1,164 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ file: _GUSWAVE.H
+
+ author: James R. Dose
+ date: March 23, 1994
+
+ Private header for GUSWAVE.C
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef ___GUSWAVE_H
+#define ___GUSWAVE_H
+
+#define TRUE ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+#define LOADDS _loadds
+
+#define VOC_8BIT 0x0
+#define VOC_CT4_ADPCM 0x1
+#define VOC_CT3_ADPCM 0x2
+#define VOC_CT2_ADPCM 0x3
+#define VOC_16BIT 0x4
+#define VOC_ALAW 0x6
+#define VOC_MULAW 0x7
+#define VOC_CREATIVE_ADPCM 0x200
+
+#define MAX_BLOCK_LENGTH 0x8000
+
+#define GF1BSIZE 896L /* size of buffer per wav on GUS */
+//#define GF1BSIZE 512L /* size of buffer per wav on GUS */
+
+//#define VOICES 8 /* maximum amount of concurrent wav files */
+#define VOICES 2 /* maximum amount of concurrent wav files */
+#define MAX_VOICES 32 /* This should always be 32 */
+#define MAX_VOLUME 4095
+#define BUFFER 2048U /* size of DMA buffer for patch loading */
+
+typedef enum
+ {
+ Raw,
+ VOC,
+ DemandFeed,
+ WAV
+ } wavedata;
+
+typedef enum
+ {
+ NoMoreData,
+ KeepPlaying,
+ SoundDone
+ } playbackstatus;
+
+
+typedef volatile struct VoiceNode
+ {
+ struct VoiceNode *next;
+ struct VoiceNode *prev;
+
+ wavedata wavetype;
+ int bits;
+ playbackstatus ( *GetSound )( struct VoiceNode *voice );
+
+ int num;
+
+ unsigned long mem; /* location in ultrasound memory */
+ int Active; /* this instance in use */
+ int GF1voice; /* handle to active voice */
+
+ char *NextBlock;
+ char *LoopStart;
+ char *LoopEnd;
+ unsigned LoopCount;
+ unsigned long LoopSize;
+ unsigned long BlockLength;
+
+ unsigned long PitchScale;
+
+ unsigned char *sound;
+ unsigned long length;
+ unsigned long SamplingRate;
+ unsigned long RateScale;
+ int Playing;
+
+ int handle;
+ int priority;
+
+ void ( *DemandFeed )( char **ptr, unsigned long *length );
+
+ unsigned long callbackval;
+
+ int Volume;
+ int Pan;
+ }
+VoiceNode;
+
+typedef struct
+ {
+ VoiceNode *start;
+ VoiceNode *end;
+ }
+voicelist;
+
+typedef volatile struct voicestatus
+ {
+ VoiceNode *Voice;
+ int playing;
+ }
+voicestatus;
+
+typedef struct
+ {
+ char RIFF[ 4 ];
+ unsigned long file_size;
+ char WAVE[ 4 ];
+ char fmt[ 4 ];
+ unsigned long format_size;
+ } riff_header;
+
+typedef struct
+ {
+ unsigned short wFormatTag;
+ unsigned short nChannels;
+ unsigned long nSamplesPerSec;
+ unsigned long nAvgBytesPerSec;
+ unsigned short nBlockAlign;
+ unsigned short nBitsPerSample;
+ } format_header;
+
+typedef struct
+ {
+ unsigned char DATA[ 4 ];
+ unsigned long size;
+ } data_header;
+
+playbackstatus GUSWAVE_GetNextVOCBlock( VoiceNode *voice );
+VoiceNode *GUSWAVE_GetVoice( int handle );
+
+int GUSWAVE_Play( VoiceNode *voice, int angle, int volume, int channels );
+
+VoiceNode *GUSWAVE_AllocVoice( int priority );
+static int GUSWAVE_InitVoices( void );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/_midi.h
@@ -1,0 +1,290 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: _MIDI.H
+
+ author: James R. Dose
+ date: May 25, 1994
+
+ Private header for MIDI.C. Midi song file playback routines.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef ___MIDI_H
+#define ___MIDI_H
+
+#define RELATIVE_BEAT( measure, beat, tick ) \
+ ( ( tick ) + ( ( beat ) << 9 ) + ( ( measure ) << 16 ) )
+
+//Bobby Prince thinks this may be 100
+//#define GENMIDI_DefaultVolume 100
+#define GENMIDI_DefaultVolume 90
+
+#define MAX_FORMAT 1
+
+#define NUM_MIDI_CHANNELS 16
+
+#define TIME_PRECISION 16
+
+#define MIDI_HEADER_SIGNATURE 0x6468544d // "MThd"
+#define MIDI_TRACK_SIGNATURE 0x6b72544d // "MTrk"
+
+#define MIDI_VOLUME 7
+#define MIDI_PAN 10
+#define MIDI_DETUNE 94
+#define MIDI_RHYTHM_CHANNEL 9
+#define MIDI_RPN_MSB 100
+#define MIDI_RPN_LSB 101
+#define MIDI_DATAENTRY_MSB 6
+#define MIDI_DATAENTRY_LSB 38
+#define MIDI_PITCHBEND_MSB 0
+#define MIDI_PITCHBEND_LSB 0
+#define MIDI_RUNNING_STATUS 0x80
+#define MIDI_NOTE_OFF 0x8
+#define MIDI_NOTE_ON 0x9
+#define MIDI_POLY_AFTER_TCH 0xA
+#define MIDI_CONTROL_CHANGE 0xB
+#define MIDI_PROGRAM_CHANGE 0xC
+#define MIDI_AFTER_TOUCH 0xD
+#define MIDI_PITCH_BEND 0xE
+#define MIDI_SPECIAL 0xF
+#define MIDI_SYSEX 0xF0
+#define MIDI_SYSEX_CONTINUE 0xF7
+#define MIDI_META_EVENT 0xFF
+#define MIDI_END_OF_TRACK 0x2F
+#define MIDI_TEMPO_CHANGE 0x51
+#define MIDI_TIME_SIGNATURE 0x58
+#define MIDI_RESET_ALL_CONTROLLERS 0x79
+#define MIDI_ALL_NOTES_OFF 0x7b
+#define MIDI_MONO_MODE_ON 0x7E
+#define MIDI_SYSTEM_RESET 0xFF
+
+#define GET_NEXT_EVENT( track, data ) \
+ ( data ) = *( track )->pos; \
+ ( track )->pos += 1
+
+#define GET_MIDI_CHANNEL( event ) ( ( event ) & 0xf )
+#define GET_MIDI_COMMAND( event ) ( ( event ) >> 4 )
+
+#define EMIDI_INFINITE -1
+#define EMIDI_END_LOOP_VALUE 127
+#define EMIDI_ALL_CARDS 127
+#define EMIDI_INCLUDE_TRACK 110
+#define EMIDI_EXCLUDE_TRACK 111
+#define EMIDI_PROGRAM_CHANGE 112
+#define EMIDI_VOLUME_CHANGE 113
+#define EMIDI_CONTEXT_START 114
+#define EMIDI_CONTEXT_END 115
+#define EMIDI_LOOP_START 116
+#define EMIDI_LOOP_END 117
+#define EMIDI_SONG_LOOP_START 118
+#define EMIDI_SONG_LOOP_END 119
+
+#define EMIDI_GeneralMIDI 0
+#define EMIDI_SoundCanvas 1
+#define EMIDI_AWE32 2
+#define EMIDI_WaveBlaster 3
+#define EMIDI_SoundBlaster 4
+#define EMIDI_ProAudio 5
+#define EMIDI_SoundMan16 6
+#define EMIDI_Adlib 7
+#define EMIDI_Soundscape 8
+#define EMIDI_Ultrasound 9
+
+#define EMIDI_AffectsCurrentCard( c, type ) \
+ ( ( ( c ) == EMIDI_ALL_CARDS ) || ( ( c ) == ( type ) ) )
+
+
+#define EMIDI_NUM_CONTEXTS 7
+typedef struct
+ {
+ unsigned char *pos;
+ unsigned char *loopstart;
+ short loopcount;
+ short RunningStatus;
+ unsigned time;
+ long FPSecondsPerTick;
+ short tick;
+ short beat;
+ short measure;
+ short BeatsPerMeasure;
+ short TicksPerBeat;
+ short TimeBase;
+ long delay;
+ short active;
+ } songcontext;
+
+typedef struct
+ {
+ unsigned char *start;
+ unsigned char *pos;
+
+ long delay;
+ short active;
+ short RunningStatus;
+
+ short currentcontext;
+ songcontext context[ EMIDI_NUM_CONTEXTS ];
+
+ char EMIDI_IncludeTrack;
+ char EMIDI_ProgramChange;
+ char EMIDI_VolumeChange;
+ } track;
+
+static long _MIDI_ReadNumber( void *from, size_t size );
+static long _MIDI_ReadDelta( track *ptr );
+static void _MIDI_ResetTracks( void );
+static void _MIDI_AdvanceTick( void );
+static void _MIDI_MetaEvent( track *Track );
+static void _MIDI_SysEx( track *Track );
+static int _MIDI_InterpretControllerInfo( track *Track, int TimeSet,
+ int channel, int c1, int c2 );
+//static
+ void _MIDI_ServiceRoutine( task *Task );
+static int _MIDI_SendControlChange( int channel, int c1, int c2 );
+static void _MIDI_SetChannelVolume( int channel, int volume );
+static void _MIDI_SendChannelVolumes( void );
+static int _MIDI_ProcessNextTick( void );
+static void _MIDI_InitEMIDI( void );
+
+/*
+ if ( c1 == EMIDI_LOOP_START )
+ {
+ if ( c2 == 0 )
+ {
+ Track->context[ 0 ].loopcount = EMIDI_INFINITE;
+ }
+ else
+ {
+ Track->context[ 0 ].loopcount = c2;
+ }
+
+ Track->context[ 0 ].pos = Track->pos;
+ Track->context[ 0 ].loopstart = Track->pos;
+ Track->context[ 0 ].RunningStatus = Track->RunningStatus;
+ Track->context[ 0 ].time = _MIDI_Time;
+ Track->context[ 0 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick;
+ Track->context[ 0 ].tick = _MIDI_Tick;
+ Track->context[ 0 ].beat = _MIDI_Beat;
+ Track->context[ 0 ].measure = _MIDI_Measure;
+ Track->context[ 0 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure;
+ Track->context[ 0 ].TicksPerBeat = _MIDI_TicksPerBeat;
+ Track->context[ 0 ].TimeBase = _MIDI_TimeBase;
+ break;
+ }
+
+ if ( ( c1 == EMIDI_LOOP_END ) &&
+ ( c2 == EMIDI_END_LOOP_VALUE ) )
+ {
+ if ( ( Track->context[ 0 ].loopstart != NULL ) &&
+ ( Track->context[ 0 ].loopcount != 0 ) )
+ {
+ if ( Track->context[ 0 ].loopcount != EMIDI_INFINITE )
+ {
+ Track->context[ 0 ].loopcount--;
+ }
+
+ Track->pos = Track->context[ 0 ].loopstart;
+ Track->RunningStatus = Track->context[ 0 ].RunningStatus;
+
+ if ( !TimeSet )
+ {
+ _MIDI_Time = Track->context[ 0 ].time;
+ _MIDI_FPSecondsPerTick = Track->context[ 0 ].FPSecondsPerTick;
+ _MIDI_Tick = Track->context[ 0 ].tick;
+ _MIDI_Beat = Track->context[ 0 ].beat;
+ _MIDI_Measure = Track->context[ 0 ].measure;
+ _MIDI_BeatsPerMeasure = Track->context[ 0 ].BeatsPerMeasure;
+ _MIDI_TicksPerBeat = Track->context[ 0 ].TicksPerBeat;
+ _MIDI_TimeBase = Track->context[ 0 ].TimeBase;
+ TimeSet = TRUE;
+ }
+ }
+ break;
+ }
+
+ if ( c1 == MIDI_MONO_MODE_ON )
+ {
+ Track->pos++;
+ }
+
+ if ( ( c1 == MIDI_VOLUME ) && ( !Track->EMIDI_VolumeChange ) )
+ {
+ _MIDI_SetChannelVolume( channel, c2 );
+ break;
+ }
+ else if ( ( c1 == EMIDI_VOLUME_CHANGE ) &&
+ ( Track->EMIDI_VolumeChange ) )
+ {
+ _MIDI_SetChannelVolume( channel, c2 );
+ break;
+ }
+
+ if ( ( c1 == EMIDI_PROGRAM_CHANGE ) &&
+ ( Track->EMIDI_ProgramChange ) )
+ {
+ _MIDI_Funcs->ProgramChange( channel, MIDI_PatchMap[ c2 & 0x7f ] );
+ break;
+ }
+
+ if ( c1 == EMIDI_CONTEXT_START )
+ {
+ break;
+ }
+
+ if ( c1 == EMIDI_CONTEXT_END )
+ {
+ if ( ( Track->currentcontext != _MIDI_Context ) ||
+ ( Track->context[ _MIDI_Context ].pos == NULL )
+ {
+ break;
+ }
+
+ Track->currentcontext = _MIDI_Context;
+ Track->context[ 0 ].loopstart = Track->context[ _MIDI_Context ].loopstart;
+ Track->context[ 0 ].loopcount = Track->context[ _MIDI_Context ].loopcount;
+ Track->pos = Track->context[ _MIDI_Context ].pos;
+ Track->RunningStatus = Track->context[ _MIDI_Context ].RunningStatus;
+
+ if ( TimeSet )
+ {
+ break;
+ }
+
+ _MIDI_Time = Track->context[ _MIDI_Context ].time;
+ _MIDI_FPSecondsPerTick = Track->context[ _MIDI_Context ].FPSecondsPerTick;
+ _MIDI_Tick = Track->context[ _MIDI_Context ].tick;
+ _MIDI_Beat = Track->context[ _MIDI_Context ].beat;
+ _MIDI_Measure = Track->context[ _MIDI_Context ].measure;
+ _MIDI_BeatsPerMeasure = Track->context[ _MIDI_Context ].BeatsPerMeasure;
+ _MIDI_TicksPerBeat = Track->context[ _MIDI_Context ].TicksPerBeat;
+ _MIDI_TimeBase = Track->context[ _MIDI_Context ].TimeBase;
+ TimeSet = TRUE;
+ break;
+ }
+
+ if ( _MIDI_Funcs->ControlChange )
+ {
+ _MIDI_Funcs->ControlChange( channel, c1, c2 );
+ }
+ */
+
+#endif
--- /dev/null
+++ b/rott/audiolib/_multivc.h
@@ -1,0 +1,286 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ file: _MULTIVC.H
+
+ author: James R. Dose
+ date: December 20, 1993
+
+ Private header for MULTIVOC.C
+
+ (c) Copyright 1993 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef ___MULTIVC_H
+#define ___MULTIVC_H
+
+#define TRUE ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+#define VOC_8BIT 0x0
+#define VOC_CT4_ADPCM 0x1
+#define VOC_CT3_ADPCM 0x2
+#define VOC_CT2_ADPCM 0x3
+#define VOC_16BIT 0x4
+#define VOC_ALAW 0x6
+#define VOC_MULAW 0x7
+#define VOC_CREATIVE_ADPCM 0x200
+
+#define T_SIXTEENBIT_STEREO 0
+#define T_8BITS 1
+#define T_MONO 2
+#define T_16BITSOURCE 4
+#define T_LEFTQUIET 8
+#define T_RIGHTQUIET 16
+#define T_DEFAULT T_SIXTEENBIT_STEREO
+
+#define MV_MaxPanPosition 31
+#define MV_NumPanPositions ( MV_MaxPanPosition + 1 )
+#define MV_MaxTotalVolume 255
+//#define MV_MaxVolume 63
+#define MV_NumVoices 8
+
+#define MIX_VOLUME( volume ) \
+ ( ( max( 0, min( ( volume ), 255 ) ) * ( MV_MaxVolume + 1 ) ) >> 8 )
+// ( ( max( 0, min( ( volume ), 255 ) ) ) >> 2 )
+
+//#define SILENCE_16BIT 0x80008000
+#define SILENCE_16BIT 0
+#define SILENCE_8BIT 0x80808080
+//#define SILENCE_16BIT_PAS 0
+
+#define MixBufferSize 256
+
+#define NumberOfBuffers 16
+#define TotalBufferSize ( MixBufferSize * NumberOfBuffers )
+
+#define PI 3.1415926536
+
+typedef enum
+ {
+ Raw,
+ VOC,
+ DemandFeed,
+ WAV
+ } wavedata;
+
+typedef enum
+ {
+ NoMoreData,
+ KeepPlaying
+ } playbackstatus;
+
+
+typedef struct VoiceNode
+ {
+ struct VoiceNode *next;
+ struct VoiceNode *prev;
+
+ wavedata wavetype;
+ char bits;
+
+ playbackstatus ( *GetSound )( struct VoiceNode *voice );
+
+ void ( *mix )( unsigned long position, unsigned long rate,
+ const char *start, unsigned long length );
+
+ char *NextBlock;
+ char *LoopStart;
+ char *LoopEnd;
+ unsigned LoopCount;
+ unsigned long LoopSize;
+ unsigned long BlockLength;
+
+ unsigned long PitchScale;
+ unsigned long FixedPointBufferSize;
+
+ char *sound;
+ unsigned long length;
+ unsigned long SamplingRate;
+ unsigned long RateScale;
+ unsigned long position;
+ int Playing;
+
+ int handle;
+ int priority;
+
+ void ( *DemandFeed )( char **ptr, unsigned long *length );
+
+ short *LeftVolume;
+ short *RightVolume;
+
+ unsigned long callbackval;
+
+ } VoiceNode;
+
+typedef struct
+ {
+ VoiceNode *start;
+ VoiceNode *end;
+ } VList;
+
+typedef struct
+ {
+ unsigned char left;
+ unsigned char right;
+ } Pan;
+
+typedef signed short MONO16;
+typedef signed char MONO8;
+
+typedef struct
+ {
+ MONO16 left;
+ MONO16 right;
+// unsigned short left;
+// unsigned short right;
+ } STEREO16;
+
+typedef struct
+ {
+ MONO16 left;
+ MONO16 right;
+ } SIGNEDSTEREO16;
+
+typedef struct
+ {
+// MONO8 left;
+// MONO8 right;
+ char left;
+ char right;
+ } STEREO8;
+
+typedef struct
+ {
+ char RIFF[ 4 ];
+ unsigned long file_size;
+ char WAVE[ 4 ];
+ char fmt[ 4 ];
+ unsigned long format_size;
+ } riff_header;
+
+typedef struct
+ {
+ unsigned short wFormatTag;
+ unsigned short nChannels;
+ unsigned long nSamplesPerSec;
+ unsigned long nAvgBytesPerSec;
+ unsigned short nBlockAlign;
+ unsigned short nBitsPerSample;
+ } format_header;
+
+typedef struct
+ {
+ unsigned char DATA[ 4 ];
+ unsigned long size;
+ } data_header;
+
+typedef MONO8 VOLUME8[ 256 ];
+typedef MONO16 VOLUME16[ 256 ];
+
+typedef char HARSH_CLIP_TABLE_8[ MV_NumVoices * 256 ];
+
+static void MV_Mix( VoiceNode *voice, int buffer );
+static void MV_PlayVoice( VoiceNode *voice );
+static void MV_StopVoice( VoiceNode *voice );
+static void MV_ServiceVoc( void );
+
+static playbackstatus MV_GetNextVOCBlock( VoiceNode *voice );
+static playbackstatus MV_GetNextDemandFeedBlock( VoiceNode *voice );
+static playbackstatus MV_GetNextRawBlock( VoiceNode *voice );
+static playbackstatus MV_GetNextWAVBlock( VoiceNode *voice );
+
+static void MV_ServiceRecord( void );
+static VoiceNode *MV_GetVoice( int handle );
+static VoiceNode *MV_AllocVoice( int priority );
+
+static short *MV_GetVolumeTable( int vol );
+
+static void MV_SetVoiceMixMode( VoiceNode *voice );
+
+static void MV_SetVoicePitch( VoiceNode *voice, unsigned long rate, int pitchoffset );
+static void MV_CalcVolume( int MaxLevel );
+static void MV_CalcPanTable( void );
+
+#ifdef PLAT_DOS
+#define ATR_INDEX 0x3c0
+#define STATUS_REGISTER_1 0x3da
+
+#define SetBorderColor(color) \
+ { \
+ inp (STATUS_REGISTER_1); \
+ outp (ATR_INDEX,0x31); \
+ outp (ATR_INDEX,color); \
+ }
+#endif
+
+void ClearBuffer_DW( void *ptr, unsigned data, int length );
+
+#ifdef PLAT_DOS
+#pragma aux ClearBuffer_DW = \
+ "cld", \
+ "push es", \
+ "push ds", \
+ "pop es", \
+ "rep stosd", \
+ "pop es", \
+parm [ edi ] [ eax ] [ ecx ] modify exact [ ecx edi ];
+#endif
+
+void MV_Mix8BitMono( unsigned long position, unsigned long rate,
+ const char *start, unsigned long length );
+
+void MV_Mix8BitStereo( unsigned long position,
+ unsigned long rate, const char *start, unsigned long length );
+
+void MV_Mix16BitMono( unsigned long position,
+ unsigned long rate, const char *start, unsigned long length );
+
+void MV_Mix16BitStereo( unsigned long position,
+ unsigned long rate, const char *start, unsigned long length );
+
+void MV_Mix16BitMono16( unsigned long position,
+ unsigned long rate, const char *start, unsigned long length );
+
+void MV_Mix8BitMono16( unsigned long position, unsigned long rate,
+ const char *start, unsigned long length );
+
+void MV_Mix8BitStereo16( unsigned long position,
+ unsigned long rate, const char *start, unsigned long length );
+
+void MV_Mix16BitStereo16( unsigned long position,
+ unsigned long rate, const char *start, unsigned long length );
+
+void MV_16BitReverb( const char *src, char *dest, const VOLUME16 *volume, int count );
+
+void MV_8BitReverb( const signed char *src, signed char *dest, const VOLUME16 *volume, int count );
+
+void MV_16BitReverbFast( const char *src, char *dest, int count, int shift );
+
+void MV_8BitReverbFast( const signed char *src, signed char *dest, int count, int shift );
+
+#ifdef PLAT_DOS
+#pragma aux MV_16BitReverb parm [eax] [edx] [ebx] [ecx] modify exact [eax ebx ecx edx esi edi]
+#pragma aux MV_8BitReverb parm [eax] [edx] [ebx] [ecx] modify exact [eax ebx ecx edx esi edi]
+#pragma aux MV_16BitReverbFast parm [eax] [edx] [ebx] [ecx] modify exact [eax ebx ecx edx esi edi]
+#pragma aux MV_8BitReverbFast parm [eax] [edx] [ebx] [ecx] modify exact [eax ebx ecx edx esi edi]
+#endif
+
+#endif
--- /dev/null
+++ b/rott/audiolib/_pas16.h
@@ -1,0 +1,250 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: _PAS16.H
+
+ author: James R. Dose
+ date: March 27, 1994
+
+ Private header for for PAS16.C
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef ___PAS16_H
+#define ___PAS16_H
+
+#define TRUE ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+#define VALID ( 1 == 1 )
+#define INVALID ( !VALID )
+
+#define lobyte( num ) ( ( int )*( ( char * )&( num ) ) )
+#define hibyte( num ) ( ( int )*( ( ( char * )&( num ) ) + 1 ) )
+
+#define STEREO 1
+#define SIXTEEN_BIT 2
+
+#define MONO_8BIT 0
+#define STEREO_8BIT ( STEREO )
+#define MONO_16BIT ( SIXTEEN_BIT )
+#define STEREO_16BIT ( STEREO | SIXTEEN_BIT )
+
+#define PAS_MaxMixMode STEREO_16BIT
+
+#define MONO_8BIT_SAMPLE_SIZE 1
+#define MONO_16BIT_SAMPLE_SIZE 2
+#define STEREO_8BIT_SAMPLE_SIZE ( 2 * MONO_8BIT_SAMPLE_SIZE )
+#define STEREO_16BIT_SAMPLE_SIZE ( 2 * MONO_16BIT_SAMPLE_SIZE )
+
+#define PAS_RevisionBits 0xe0
+
+#define AudioFilterControl 0xb8a
+#define InterruptControl 0xb8b
+#define InterruptStatus 0xb89
+#define PCMDataRegister 0xf88
+#define CrossChannelControl 0xf8a
+#define SampleRateTimer 0x1388
+#define SampleBufferCount 0x1389
+#define LocalSpeakerTimerCount 0x138a
+#define LocalTimerControl 0x138b
+#define SampleSizeConfiguration 0x8389
+
+#define AudioMuteFlag 0x20
+#define SampleRateTimerGateFlag 0x40
+#define SampleBufferCountGateFlag 0x80
+
+#define SampleRateInterruptFlag 0x04
+#define SampleBufferInterruptFlag 0x08
+
+#define PAS_SampleSizeMask 0xf3
+#define PAS_SignedSampleMask 0xe3
+#define PAS_16BitSampleFlag 0x04
+#define PAS_UnsignedSampleFlag 0x10
+//bSC2msbinv equ 00010000b ;; invert MSB from standard method
+
+#define PAS_OverSamplingMask 0xfc
+
+#define PAS_1xOverSampling 0x00
+#define PAS_2xOverSampling 0x01
+#define PAS_4xOverSampling 0x03
+
+#define PAS_StereoFlag 0x20
+
+#define PAS_AudioMuteFlag 0x20
+
+#define DEFAULT_BASE ( 0x0388 ^ 0x388 ) /* default base I/O address */
+#define ALT_BASE_1 ( 0x0384 ^ 0x388 ) /* first alternate address */
+#define ALT_BASE_2 ( 0x038C ^ 0x388 ) /* second alternate address */
+#define ALT_BASE_3 ( 0x0288 ^ 0x388 ) /* third alternate address */
+
+#define PAS_DMAEnable 0x80
+#define PAS_ChannelConnectMask 0x0f
+#define PAS_PCMStartDAC 0xD0
+#define PAS_PCMStartADC 0xC0
+#define PAS_PCMStopMask 0x3f
+
+#define RECORD 0
+#define PLAYBACK 1
+
+#define SelectSampleRateTimer 0x36 // 00110110b
+#define SelectSampleBufferCount 0x74 // 01110100b
+
+#define CalcTimeInterval( rate ) \
+ ( 1193180UL / ( rate ) )
+
+#define CalcSamplingRate( interval ) \
+ ( 1193180UL / ( interval ) )
+
+#define MV_Signature 0x4d56
+#define MV_SoundInt 0x2f
+#define MV_CheckForDriver 0xbc00
+#define MV_GetVersion 0xbc01
+#define MV_GetPointerToStateTable 0xbc02
+#define MV_GetPointerToFunctionTable 0xbc03
+#define MV_GetDmaIrqInt 0xbc04
+#define MV_SendCommandStructure 0xbc05
+#define MV_GetDriverMessage 0xbc06
+#define MV_SetHotkeyScanCodes 0xbc0a
+#define MV_GetPathToDriver 0xbc0b
+
+#define OUTPUTMIXER 0x00 /* output mixer H/W select */
+#define INPUTMIXER 0x40 /* input mixer select */
+#define DEFMIXER -1 /* use last mixer selected */
+
+/* left channel values */
+
+#define L_FM 0x01
+#define L_IMIXER 0x02
+#define L_EXT 0x03
+#define L_INT 0x04
+#define L_MIC 0x05
+#define L_PCM 0x06
+#define L_SPEAKER 0x07
+#define L_FREE 0x00
+#define L_SBDAC 0x00
+
+/* right channel values */
+
+#define R_FM 0x08
+#define R_IMIXER 0x09
+#define R_EXT 0x0A
+#define R_INT 0x0B
+#define R_MIC 0x0C
+#define R_PCM 0x0D
+#define R_SPEAKER 0x0E
+#define R_FREE 0x0F
+#define R_SBDAC 0x0F
+
+typedef struct
+ {
+ unsigned char sysspkrtmr; /* 42 System Speaker Timer Address */
+ unsigned char systmrctlr; /* 43 System Timer Control */
+ unsigned char sysspkrreg; /* 61 System Speaker Register */
+ unsigned char joystick; /* 201 Joystick Register */
+ unsigned char lfmaddr; /* 388 Left FM Synth Address */
+ unsigned char lfmdata; /* 389 Left FM Synth Data */
+ unsigned char rfmaddr; /* 38A Right FM Synth Address */
+ unsigned char rfmdata; /* 38B Right FM Synth Data */
+ unsigned char dfmaddr; /* 788 Dual FM Synth Address */
+ unsigned char dfmdata; /* 789 Dual FM Synth Data */
+ unsigned char RESRVD1[1]; /* reserved */
+ unsigned char paudiomixr; /* 78B Paralllel Audio Mixer Control*/
+ unsigned char audiomixr; /* B88 Audio Mixer Control */
+ unsigned char intrctlrst; /* B89 Interrupt Status */
+ unsigned char audiofilt; /* B8A Audio Filter Control */
+ unsigned char intrctlr; /* B8B Interrupt Control */
+ unsigned char pcmdata; /* F88 PCM Data I/O Register */
+ unsigned char RESRVD2; /* reserved */
+ unsigned char crosschannel; /* F8A Cross Channel */
+ unsigned char RESRVD3; /* reserved */
+ unsigned short samplerate; /* 1388 Sample Rate Timer */
+ unsigned short samplecnt; /* 1389 Sample Count Register */
+ unsigned short spkrtmr; /* 138A Shadow Speaker Timer Count */
+ unsigned char tmrctlr; /* 138B Shadow Speaker Timer Control */
+ unsigned char mdirqvect; /* 1788 MIDI IRQ Vector Register */
+ unsigned char mdsysctlr; /* 1789 MIDI System Control Register */
+ unsigned char mdsysstat; /* 178A MIDI IRQ Status Register */
+ unsigned char mdirqclr; /* 178B MIDI IRQ Clear Register */
+ unsigned char mdgroup1; /* 1B88 MIDI Group #1 Register */
+ unsigned char mdgroup2; /* 1B89 MIDI Group #2 Register */
+ unsigned char mdgroup3; /* 1B8A MIDI Group #3 Register */
+ unsigned char mdgroup4; /* 1B8B MIDI Group #4 Register */
+ } MVState;
+
+typedef struct
+ {
+ unsigned long SetMixer;
+ unsigned long SetVolume;
+ unsigned long SetFilter;
+ unsigned long SetCrossChannel;
+ unsigned long GetMixer;
+ unsigned long GetVolume;
+ unsigned long GetFilter;
+ unsigned long GetCrossChannel;
+ unsigned long ReadSound;
+ unsigned long FMSplit;
+ } MVFunc;
+
+int PAS_CheckForDriver( void );
+MVState *PAS_GetStateTable( void );
+MVFunc *PAS_GetFunctionTable( void );
+int PAS_GetCardSettings( void );
+void PAS_EnableInterrupt( void );
+void PAS_DisableInterrupt( void );
+void interrupt far PAS_ServiceInterrupt( void );
+//void interrupt PAS_ServiceInterrupt( void );
+void PAS_Write( int Register, int Data );
+int PAS_Read( int Register );
+void PAS_SetSampleRateTimer( void );
+void PAS_SetSampleBufferCount( void );
+int PAS_SetupDMABuffer( char *BufferPtr, int BufferSize, int mode );
+int PAS_GetFilterSetting( int rate );
+void PAS_BeginTransfer( int mode );
+int PAS_TestAddress( int address );
+int PAS_FindCard( void );
+int PAS_CallMVFunction( unsigned long function, int ebx, int ecx, int edx );
+void PAS_SaveState( void );
+void PAS_RestoreState( void );
+
+
+#pragma aux PAS_TestAddress = \
+ "mov dx, 0b8bh", \
+ "xor dx, ax", \
+ "in al, dx", \
+ "cmp al, 0ffh", \
+ "je TestExit", \
+ "mov ah, al", \
+ "xor al, 0e0h", \
+ "out dx, al", \
+ "jmp TestDelay1", \
+ "TestDelay1:", \
+ "jmp TestDelay2", \
+ "TestDelay2:", \
+ "in al, dx", \
+ "xchg al, ah", \
+ "out dx, al", \
+ "sub al, ah", \
+ "TestExit:", \
+ "and eax, 0ffh" \
+ parm [ eax ] modify exact [ eax dx ];
+
+#endif
--- /dev/null
+++ b/rott/audiolib/_sndscap.h
@@ -1,0 +1,136 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: _SNDSCAP.H
+
+ author: James R. Dose
+ date: October 26, 1994
+
+ Private header for SNDSCAPE.C
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef ___SNDSCAP_H
+#define ___SNDSCAP_H
+
+#define VALID ( 1 == 1 )
+#define INVALID ( !VALID )
+
+#define TRUE ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+#define lobyte( num ) ( ( int )*( ( char * )&( num ) ) )
+#define hibyte( num ) ( ( int )*( ( ( char * )&( num ) ) + 1 ) )
+
+#define STEREO 1
+#define SIXTEEN_BIT 2
+
+#define MONO_8BIT 0
+#define STEREO_8BIT ( STEREO )
+#define MONO_16BIT ( SIXTEEN_BIT )
+#define STEREO_16BIT ( STEREO | SIXTEEN_BIT )
+
+#define SOUNDSCAPE_MaxMixMode STEREO_16BIT
+
+#define MONO_8BIT_SAMPLE_SIZE 1
+#define MONO_16BIT_SAMPLE_SIZE 2
+#define STEREO_8BIT_SAMPLE_SIZE ( 2 * MONO_8BIT_SAMPLE_SIZE )
+#define STEREO_16BIT_SAMPLE_SIZE ( 2 * MONO_16BIT_SAMPLE_SIZE )
+
+#define SOUNDSCAPE_DefaultSampleRate 11000
+#define SOUNDSCAPE_DefaultMixMode MONO_8BIT
+#define SOUNDSCAPE_MaxIrq 15
+
+/* Ensoniq gate-array chip defines ... */
+#define ODIE 0 /* ODIE gate array */
+#define OPUS 1 /* OPUS gate array */
+#define MMIC 2 /* MiMIC gate array */
+
+/* relevant direct register defines - offsets from base address */
+#define GA_HOSTCSTAT 2 /* host port ctrl/stat reg */
+#define GA_HOSTDATA 3 /* host port data reg */
+#define GA_REGADDR 4 /* indirect address reg */
+#define GA_REGDATA 5 /* indirect data reg */
+#define SB_IACK 0x22e /* SoundBlaster IACK register */
+
+/* relevant indirect register defines */
+#define GA_DMACHB 3 /* DMA chan B assign reg */
+#define GA_INTCFG 4 /* interrupt configuration reg */
+#define GA_DMACFG 5 /* DMA config reg */
+#define GA_CDCFG 6 /* CD-ROM (AD-1848) config reg */
+#define GA_HMCTL 9 /* host master control reg */
+#define GA_CHIPSEL 10 /* programmable external chip select */
+
+/* AD-1848 chip defines ... */
+/* relevant direct register defines */
+#define AD_REGADDR 0 /* indirect address reg */
+#define AD_REGDATA 1 /* indirect data reg */
+#define AD_STATUS 2 /* status register */
+#define AD_OFFSET 8 /* for some boards, a fixed BasePort offset */
+
+/* relevant indirect register defines */
+#define AD_LEFTOUT 6 /* left DAC output control reg */
+#define AD_RIGHTOUT 7 /* right DAC output control reg */
+#define AD_FORMAT 8 /* clock and data format reg */
+#define AD_CONFIG 9 /* interface config register */
+#define AD_PINCTRL 10 /* external pin control reg */
+#define AD_UCOUNT 14 /* upper count reg */
+#define AD_LCOUNT 15 /* lower count reg */
+
+/* some firmware command and communication defines */
+#define SET_CTL 0x88 /* set a control value */
+#define GET_CTL 0x89 /* get a control value */
+#define SET_REV 0xb0 /* set synth reverb */
+#define SYNTH_VOL 0x04 /* Synth Vol control number */
+#define RXRDY 0x01 /* Receive-Ready bit mask */
+#define TXRDY 0x02 /* Transmit-Ready bit mask */
+
+/* some miscellaneous defines ... soundscape reg values, sytem int regs, ... */
+#define INTCONT1 0x20 /* Interrupt Controller 1 control register */
+#define INTCONT2 0xa0 /* Interrupt Controller 2 control register */
+#define INTMASK1 0x21 /* Interrupt Controller 1 mask register */
+#define INTMASK2 0xa1 /* Interrupt Controller 2 mask register */
+#define VECTBASE1 0x08 /* vector base for XT interrupts */
+#define VECTBASE2 0x70 /* vector base for AT extended interrupts */
+#define EOI 0x20 /* End Of Interrupt command */
+#define AUTO_OUT 0x58 /* DMA controller mode */
+
+static void SOUNDSCAPE_EnableInterrupt( void );
+static void SOUNDSCAPE_DisableInterrupt( void );
+static void __interrupt __far SOUNDSCAPE_ServiceInterrupt( void );
+static int ga_read( int rnum );
+static void ga_write( int rnum, int value );
+static int ad_read( int rnum );
+static void ad_write( int rnum, int value );
+static void tdelay( void );
+static void pcm_format( void );
+static int SOUNDSCAPE_SetupDMABuffer( char *BufferPtr, int BufferSize, int mode );
+static int SOUNDSCAPE_BeginPlayback( int length );
+static void SOUNDSCAPE_LockEnd( void );
+static void SOUNDSCAPE_UnlockMemory( void );
+static int SOUNDSCAPE_LockMemory( void );
+static unsigned short allocateTimerStack( unsigned short size );
+static void deallocateTimerStack( unsigned short selector );
+static int parse( char *val, char *str, FILE *p1 );
+static int SOUNDSCAPE_FindCard( void );
+static int SOUNDSCAPE_Setup( void );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/adlibfx.c
@@ -1,0 +1,552 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: ADLIBFX.C
+
+ author: James R. Dose
+ date: April 1, 1994
+
+ Low level routines to support Adlib sound effects created by Muse.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#include <dos.h>
+#include <stdlib.h>
+#include <conio.h>
+#include "dpmi.h"
+#include "task_man.h"
+#include "interrup.h"
+#include "al_midi.h"
+#include "adlibfx.h"
+
+#define TRUE ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+static void ADLIBFX_SendOutput( int reg, int data );
+static void ADLIBFX_Service( task *Task );
+
+static long ADLIBFX_LengthLeft;
+static int ADLIBFX_Block;
+static ALSound *ADLIBFX_Sound = NULL;
+static char *ADLIBFX_SoundPtr = NULL;
+static int ADLIBFX_Priority;
+static unsigned long ADLIBFX_CallBackVal;
+static void ( *ADLIBFX_CallBackFunc )( unsigned long ) = NULL;
+static int ADLIBFX_SoundVolume;
+static int ADLIBFX_TotalVolume = ADLIBFX_MaxVolume;
+static task *ADLIBFX_ServiceTask = NULL;
+static int ADLIBFX_VoiceHandle = ADLIBFX_MinVoiceHandle;
+
+int ADLIBFX_Installed = FALSE;
+
+int ADLIBFX_ErrorCode = ADLIBFX_Ok;
+
+#define ADLIBFX_SetErrorCode( status ) \
+ ADLIBFX_ErrorCode = ( status );
+
+
+/*---------------------------------------------------------------------
+ Function: ADLIBFX_ErrorString
+
+ Returns a pointer to the error message associated with an error
+ number. A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *ADLIBFX_ErrorString
+ (
+ int ErrorNumber
+ )
+
+ {
+ char *ErrorString;
+
+ switch( ErrorNumber )
+ {
+ case ADLIBFX_Warning :
+ case ADLIBFX_Error :
+ ErrorString = ADLIBFX_ErrorString( ADLIBFX_ErrorCode );
+ break;
+
+ case ADLIBFX_Ok :
+ ErrorString = "Adlib FX ok.";
+ break;
+
+ case ADLIBFX_NoVoices :
+ ErrorString = "No free voices available in Adlib FX.";
+ break;
+
+ case ADLIBFX_VoiceNotFound :
+ ErrorString = "No voice with matching handle found.";
+ break;
+
+ case ADLIBFX_DPMI_Error :
+ ErrorString = "DPMI Error in AdlibFX.";
+ break;
+
+ default :
+ ErrorString = "Unknown Adlib FX error code.";
+ break;
+ }
+
+ return( ErrorString );
+ }
+
+
+/**********************************************************************
+
+ Memory locked functions:
+
+**********************************************************************/
+
+
+#define ADLIBFX_LockStart ADLIBFX_SendOutput
+
+/*---------------------------------------------------------------------
+ Function: ADLIBFX_SendOutput
+
+ Writes a byte of data to the specified register on the Adlib card.
+---------------------------------------------------------------------*/
+
+static void ADLIBFX_SendOutput
+ (
+ int reg,
+ int data
+ )
+
+ {
+ int i;
+ int adlib_port = 0x388;
+ unsigned flags;
+
+ flags = DisableInterrupts();
+
+ outp( adlib_port, reg );
+
+ for( i = 6; i ; i-- )
+ {
+ inp( adlib_port );
+ }
+
+ outp( adlib_port + 1, data );
+
+ for( i = 35; i ; i-- )
+ {
+ inp( adlib_port );
+ }
+
+ RestoreInterrupts( flags );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: ADLIBFX_Stop
+
+ Halts playback of the currently playing sound effect.
+---------------------------------------------------------------------*/
+
+int ADLIBFX_Stop
+ (
+ int handle
+ )
+
+ {
+ unsigned flags;
+
+ if ( ( handle != ADLIBFX_VoiceHandle ) || ( ADLIBFX_Sound == NULL ) )
+ {
+ ADLIBFX_SetErrorCode( ADLIBFX_VoiceNotFound );
+ return( ADLIBFX_Warning );
+ }
+
+ flags = DisableInterrupts();
+
+ ADLIBFX_SendOutput( 0xb0, 0 );
+
+ ADLIBFX_Sound = NULL;
+ ADLIBFX_SoundPtr = NULL;
+ ADLIBFX_LengthLeft = 0;
+ ADLIBFX_Priority = 0;
+
+ RestoreInterrupts( flags );
+
+ if ( ADLIBFX_CallBackFunc )
+ {
+ ADLIBFX_CallBackFunc( ADLIBFX_CallBackVal );
+ }
+
+ return( ADLIBFX_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: ADLIBFX_Service
+
+ Task Manager routine to perform the playback of a sound effect.
+---------------------------------------------------------------------*/
+
+static void ADLIBFX_Service
+ (
+ task *Task
+ )
+
+ {
+ int value;
+
+ if ( ADLIBFX_SoundPtr )
+ {
+ value = *ADLIBFX_SoundPtr++;
+ if ( value != 0 )
+ {
+ ADLIBFX_SendOutput( 0xa0, value );
+ ADLIBFX_SendOutput( 0xb0, ADLIBFX_Block );
+ }
+ else
+ {
+ ADLIBFX_SendOutput( 0xb0, 0 );
+ }
+
+ ADLIBFX_LengthLeft--;
+ if ( ADLIBFX_LengthLeft <= 0 )
+ {
+ ADLIBFX_Stop( ADLIBFX_VoiceHandle );
+ }
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: ADLIBFX_SetVolume
+
+ Sets the volume of the currently playing sound effect.
+---------------------------------------------------------------------*/
+
+int ADLIBFX_SetVolume
+ (
+ int handle,
+ int volume
+ )
+
+ {
+ unsigned flags;
+ int carrierlevel;
+
+ flags = DisableInterrupts();
+ if ( ( handle != ADLIBFX_VoiceHandle ) || ( ADLIBFX_Sound == NULL ) )
+ {
+ RestoreInterrupts( flags );
+ ADLIBFX_SetErrorCode( ADLIBFX_VoiceNotFound );
+ return( ADLIBFX_Warning );
+ }
+
+ volume = min( volume, ADLIBFX_MaxVolume );
+ volume = max( volume, 0 );
+ ADLIBFX_SoundVolume = volume;
+
+ volume *= ADLIBFX_TotalVolume;
+ volume /= ADLIBFX_MaxVolume;
+
+ carrierlevel = ADLIBFX_Sound->cScale & 0x3f;
+ carrierlevel ^= 0x3f;
+ carrierlevel *= ( volume / 2 ) + 0x80;
+ carrierlevel /= ADLIBFX_MaxVolume;
+ carrierlevel ^= 0x3f;
+ carrierlevel |= ADLIBFX_Sound->cScale & 0xc0;
+
+ ADLIBFX_SendOutput( 0x43, carrierlevel );
+
+ RestoreInterrupts( flags );
+ return( ADLIBFX_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: ADLIBFX_SetTotalVolume
+
+ Sets the total volume of the sound effect.
+---------------------------------------------------------------------*/
+
+int ADLIBFX_SetTotalVolume
+ (
+ int volume
+ )
+
+ {
+ volume = max( volume, 0 );
+ volume = min( volume, ADLIBFX_MaxVolume );
+
+ ADLIBFX_TotalVolume = volume;
+ ADLIBFX_SetVolume( ADLIBFX_VoiceHandle, ADLIBFX_SoundVolume );
+
+ return( ADLIBFX_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: ADLIBFX_GetTotalVolume
+
+ Returns the total volume of the sound effect.
+---------------------------------------------------------------------*/
+
+int ADLIBFX_GetTotalVolume
+ (
+ void
+ )
+
+ {
+ return( ADLIBFX_TotalVolume );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: ADLIBFX_VoiceAvailable
+
+ Checks if a voice can be play at the specified priority.
+---------------------------------------------------------------------*/
+
+int ADLIBFX_VoiceAvailable
+ (
+ int priority
+ )
+
+ {
+ if ( priority < ADLIBFX_Priority )
+ {
+ return( FALSE );
+ }
+
+ return( TRUE );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: ADLIBFX_Play
+
+ Starts playback of a Muse sound effect.
+---------------------------------------------------------------------*/
+
+int ADLIBFX_Play
+ (
+ ALSound *sound,
+ int volume,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ unsigned flags;
+ int carrierlevel;
+
+ if ( priority < ADLIBFX_Priority )
+ {
+ ADLIBFX_SetErrorCode( ADLIBFX_NoVoices );
+ return( ADLIBFX_Warning );
+ }
+
+ ADLIBFX_Stop( ADLIBFX_VoiceHandle );
+
+ ADLIBFX_VoiceHandle++;
+ if ( ADLIBFX_VoiceHandle < ADLIBFX_MinVoiceHandle )
+ {
+ ADLIBFX_VoiceHandle = ADLIBFX_MinVoiceHandle;
+ }
+
+ flags = DisableInterrupts();
+
+ ADLIBFX_LengthLeft = sound->length;
+ ADLIBFX_Priority = priority;
+ ADLIBFX_Sound = sound;
+ ADLIBFX_SoundPtr = &sound->data;
+ ADLIBFX_CallBackVal = callbackval;
+
+ ADLIBFX_Block = ( ( sound->block & 7 ) << 2 ) | 0x20;
+
+ volume = min( volume, ADLIBFX_MaxVolume );
+ volume = max( volume, 0 );
+ ADLIBFX_SoundVolume = volume;
+
+ volume *= ADLIBFX_TotalVolume;
+ volume /= ADLIBFX_MaxVolume;
+
+ carrierlevel = sound->cScale & 0x3f;
+ carrierlevel ^= 0x3f;
+ carrierlevel *= ( volume / 2 ) + 0x80;
+ carrierlevel /= ADLIBFX_MaxVolume;
+ carrierlevel ^= 0x3f;
+ carrierlevel |= sound->cScale & 0xc0;
+
+ ADLIBFX_SendOutput( 0x20, sound->mChar );
+ ADLIBFX_SendOutput( 0x40, sound->mScale );
+ ADLIBFX_SendOutput( 0x60, sound->mAttack );
+ ADLIBFX_SendOutput( 0x80, sound->mSus );
+ ADLIBFX_SendOutput( 0xe0, sound->mWave );
+
+ ADLIBFX_SendOutput( 0x23, sound->cChar );
+ ADLIBFX_SendOutput( 0x43, carrierlevel );
+ ADLIBFX_SendOutput( 0x63, sound->cAttack );
+ ADLIBFX_SendOutput( 0x83, sound->cSus );
+ ADLIBFX_SendOutput( 0xe3, sound->cWave );
+
+ ADLIBFX_SendOutput( 0xc0, 0 );
+
+ RestoreInterrupts( flags );
+
+ return( ADLIBFX_VoiceHandle );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: ADLIBFX_SoundPlaying
+
+ Checks if a sound effect is currently playing.
+---------------------------------------------------------------------*/
+
+int ADLIBFX_SoundPlaying
+ (
+ int handle
+ )
+
+ {
+ int status;
+
+ status = FALSE;
+ if ( ( handle == ADLIBFX_VoiceHandle ) && ( ADLIBFX_LengthLeft > 0 ) )
+ {
+ status = TRUE;
+ }
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: ADLIBFX_LockEnd
+
+ Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void ADLIBFX_LockEnd
+ (
+ void
+ )
+
+ {
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: ADLIBFX_SetCallBack
+
+ Set the function to call when a voice stops.
+---------------------------------------------------------------------*/
+
+void ADLIBFX_SetCallBack
+ (
+ void ( *function )( unsigned long )
+ )
+
+ {
+ ADLIBFX_CallBackFunc = function;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: ADLIBFX_Init
+
+ Initializes the sound effect engine.
+---------------------------------------------------------------------*/
+
+int ADLIBFX_Init
+ (
+ void
+ )
+
+ {
+ int status;
+
+ if ( ADLIBFX_Installed )
+ {
+ ADLIBFX_Shutdown();
+ }
+
+ status = DPMI_LockMemoryRegion( ADLIBFX_LockStart, ADLIBFX_LockEnd );
+ status |= DPMI_Lock( ADLIBFX_VoiceHandle );
+ status |= DPMI_Lock( ADLIBFX_Sound );
+ status |= DPMI_Lock( ADLIBFX_ErrorCode );
+ status |= DPMI_Lock( ADLIBFX_SoundPtr );
+ status |= DPMI_Lock( ADLIBFX_LengthLeft );
+ status |= DPMI_Lock( ADLIBFX_Priority );
+ status |= DPMI_Lock( ADLIBFX_CallBackFunc );
+ status |= DPMI_Lock( ADLIBFX_Block );
+
+ if ( status != DPMI_Ok )
+ {
+ ADLIBFX_SetErrorCode( ADLIBFX_DPMI_Error );
+ return( ADLIBFX_Error );
+ }
+
+//JIM
+// AL_ReserveVoice( 0 );
+ ADLIBFX_Stop( ADLIBFX_VoiceHandle );
+ ADLIBFX_ServiceTask = TS_ScheduleTask( &ADLIBFX_Service, 140, 2, NULL );
+ TS_Dispatch();
+ ADLIBFX_Installed = TRUE;
+ ADLIBFX_CallBackFunc = NULL;
+
+ ADLIBFX_SetErrorCode( ADLIBFX_Ok );
+ return( ADLIBFX_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: ADLIBFX_Shutdown
+
+ Ends the use of the sound effect engine.
+---------------------------------------------------------------------*/
+
+int ADLIBFX_Shutdown
+ (
+ void
+ )
+
+ {
+ if ( ADLIBFX_Installed )
+ {
+ ADLIBFX_Stop( ADLIBFX_VoiceHandle );
+ TS_Terminate( ADLIBFX_ServiceTask );
+ ADLIBFX_ServiceTask = NULL;
+//JIM
+// AL_ReleaseVoice( 0 );
+ ADLIBFX_Installed = FALSE;
+
+ DPMI_UnlockMemoryRegion( ADLIBFX_LockStart, ADLIBFX_LockEnd );
+ DPMI_Unlock( ADLIBFX_VoiceHandle );
+ DPMI_Unlock( ADLIBFX_Sound );
+ DPMI_Unlock( ADLIBFX_ErrorCode );
+ DPMI_Unlock( ADLIBFX_SoundPtr );
+ DPMI_Unlock( ADLIBFX_LengthLeft );
+ DPMI_Unlock( ADLIBFX_Priority );
+ DPMI_Unlock( ADLIBFX_CallBackFunc );
+ DPMI_Unlock( ADLIBFX_Block );
+ }
+
+ ADLIBFX_SetErrorCode( ADLIBFX_Ok );
+ return( ADLIBFX_Ok );
+ }
--- /dev/null
+++ b/rott/audiolib/adlibfx.h
@@ -1,0 +1,80 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: ADLIBFX.H
+
+ author: James R. Dose
+ date: April 1, 1994
+
+ Public header for ADLIBFX.C
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __ADLIBFX_H
+#define __ADLIBFX_H
+
+enum ADLIBFX_Errors
+ {
+ ADLIBFX_Warning = -2,
+ ADLIBFX_Error = -1,
+ ADLIBFX_Ok = 0,
+ ADLIBFX_NoVoices,
+ ADLIBFX_VoiceNotFound,
+ ADLIBFX_DPMI_Error
+ };
+
+typedef struct
+ {
+ unsigned long length;
+ short int priority;
+ char mChar, cChar;
+ char mScale, cScale;
+ char mAttack, cAttack;
+ char mSus, cSus;
+ char mWave, cWave;
+ char nConn;
+ char voice;
+ char mode;
+ char unused[ 3 ];
+ char block;
+ char data[];
+ } ALSound;
+
+#define ADLIBFX_MaxVolume 255
+#define ADLIBFX_MinVoiceHandle 1
+
+char *ADLIBFX_ErrorString( int ErrorNumber );
+int ADLIBFX_Stop( int handle );
+int ADLIBFX_SetVolume( int handle, int volume );
+int ADLIBFX_SetTotalVolume( int volume );
+int ADLIBFX_GetTotalVolume( void );
+int ADLIBFX_VoiceAvailable( int priority );
+int ADLIBFX_Play( ALSound *sound, int volume, int priority, unsigned long callbackval );
+int ADLIBFX_SoundPlaying( int handle );
+void ADLIBFX_SetCallBack( void ( *function )( unsigned long ) );
+int ADLIBFX_Init( void );
+int ADLIBFX_Shutdown( void );
+ #pragma aux ADLIBFX_Shutdown frame;
+void PCFX_UnlockMemory( void );
+ #pragma aux ADLIBFX_UnlockMemory frame;
+int PCFX_LockMemory( void );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/al_midi.c
@@ -1,0 +1,1510 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: AL_MIDI.C
+
+ author: James R. Dose
+ date: April 1, 1994
+
+ Low level routines to support General MIDI music on Adlib compatible
+ cards.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#include <conio.h>
+#include <dos.h>
+#include <stddef.h>
+#include <stdlib.h>
+//#include <math.h>
+#include "dpmi.h"
+#include "interrup.h"
+#include "sndcards.h"
+#include "blaster.h"
+#include "user.h"
+#include "al_midi.h"
+#include "_al_midi.h"
+#include "ll_man.h"
+
+#define TRUE ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+static unsigned OctavePitch[ MAX_OCTAVE + 1 ] =
+ {
+ OCTAVE_0, OCTAVE_1, OCTAVE_2, OCTAVE_3,
+ OCTAVE_4, OCTAVE_5, OCTAVE_6, OCTAVE_7,
+ };
+
+static unsigned NoteMod12[ MAX_NOTE + 1 ];
+static unsigned NoteDiv12[ MAX_NOTE + 1 ];
+
+// Pitch table
+
+//static unsigned NotePitch[ FINETUNE_MAX + 1 ][ 12 ] =
+// {
+// { C, C_SHARP, D, D_SHARP, E, F, F_SHARP, G, G_SHARP, A, A_SHARP, B },
+// };
+
+static unsigned NotePitch[ FINETUNE_MAX + 1 ][ 12 ] =
+ {
+ { 0x157, 0x16b, 0x181, 0x198, 0x1b0, 0x1ca, 0x1e5, 0x202, 0x220, 0x241, 0x263, 0x287 },
+ { 0x157, 0x16b, 0x181, 0x198, 0x1b0, 0x1ca, 0x1e5, 0x202, 0x220, 0x242, 0x264, 0x288 },
+ { 0x158, 0x16c, 0x182, 0x199, 0x1b1, 0x1cb, 0x1e6, 0x203, 0x221, 0x243, 0x265, 0x289 },
+ { 0x158, 0x16c, 0x183, 0x19a, 0x1b2, 0x1cc, 0x1e7, 0x204, 0x222, 0x244, 0x266, 0x28a },
+ { 0x159, 0x16d, 0x183, 0x19a, 0x1b3, 0x1cd, 0x1e8, 0x205, 0x223, 0x245, 0x267, 0x28b },
+ { 0x15a, 0x16e, 0x184, 0x19b, 0x1b3, 0x1ce, 0x1e9, 0x206, 0x224, 0x246, 0x268, 0x28c },
+ { 0x15a, 0x16e, 0x185, 0x19c, 0x1b4, 0x1ce, 0x1ea, 0x207, 0x225, 0x247, 0x269, 0x28e },
+ { 0x15b, 0x16f, 0x185, 0x19d, 0x1b5, 0x1cf, 0x1eb, 0x208, 0x226, 0x248, 0x26a, 0x28f },
+ { 0x15b, 0x170, 0x186, 0x19d, 0x1b6, 0x1d0, 0x1ec, 0x209, 0x227, 0x249, 0x26b, 0x290 },
+ { 0x15c, 0x170, 0x187, 0x19e, 0x1b7, 0x1d1, 0x1ec, 0x20a, 0x228, 0x24a, 0x26d, 0x291 },
+ { 0x15d, 0x171, 0x188, 0x19f, 0x1b7, 0x1d2, 0x1ed, 0x20b, 0x229, 0x24b, 0x26e, 0x292 },
+ { 0x15d, 0x172, 0x188, 0x1a0, 0x1b8, 0x1d3, 0x1ee, 0x20c, 0x22a, 0x24c, 0x26f, 0x293 },
+ { 0x15e, 0x172, 0x189, 0x1a0, 0x1b9, 0x1d4, 0x1ef, 0x20d, 0x22b, 0x24d, 0x270, 0x295 },
+ { 0x15f, 0x173, 0x18a, 0x1a1, 0x1ba, 0x1d4, 0x1f0, 0x20e, 0x22c, 0x24e, 0x271, 0x296 },
+ { 0x15f, 0x174, 0x18a, 0x1a2, 0x1bb, 0x1d5, 0x1f1, 0x20f, 0x22d, 0x24f, 0x272, 0x297 },
+ { 0x160, 0x174, 0x18b, 0x1a3, 0x1bb, 0x1d6, 0x1f2, 0x210, 0x22e, 0x250, 0x273, 0x298 },
+ { 0x161, 0x175, 0x18c, 0x1a3, 0x1bc, 0x1d7, 0x1f3, 0x211, 0x22f, 0x251, 0x274, 0x299 },
+ { 0x161, 0x176, 0x18c, 0x1a4, 0x1bd, 0x1d8, 0x1f4, 0x212, 0x230, 0x252, 0x276, 0x29b },
+ { 0x162, 0x176, 0x18d, 0x1a5, 0x1be, 0x1d9, 0x1f5, 0x212, 0x231, 0x254, 0x277, 0x29c },
+ { 0x162, 0x177, 0x18e, 0x1a6, 0x1bf, 0x1d9, 0x1f5, 0x213, 0x232, 0x255, 0x278, 0x29d },
+ { 0x163, 0x178, 0x18f, 0x1a6, 0x1bf, 0x1da, 0x1f6, 0x214, 0x233, 0x256, 0x279, 0x29e },
+ { 0x164, 0x179, 0x18f, 0x1a7, 0x1c0, 0x1db, 0x1f7, 0x215, 0x235, 0x257, 0x27a, 0x29f },
+ { 0x164, 0x179, 0x190, 0x1a8, 0x1c1, 0x1dc, 0x1f8, 0x216, 0x236, 0x258, 0x27b, 0x2a1 },
+ { 0x165, 0x17a, 0x191, 0x1a9, 0x1c2, 0x1dd, 0x1f9, 0x217, 0x237, 0x259, 0x27c, 0x2a2 },
+ { 0x166, 0x17b, 0x192, 0x1aa, 0x1c3, 0x1de, 0x1fa, 0x218, 0x238, 0x25a, 0x27e, 0x2a3 },
+ { 0x166, 0x17b, 0x192, 0x1aa, 0x1c3, 0x1df, 0x1fb, 0x219, 0x239, 0x25b, 0x27f, 0x2a4 },
+ { 0x167, 0x17c, 0x193, 0x1ab, 0x1c4, 0x1e0, 0x1fc, 0x21a, 0x23a, 0x25c, 0x280, 0x2a6 },
+ { 0x168, 0x17d, 0x194, 0x1ac, 0x1c5, 0x1e0, 0x1fd, 0x21b, 0x23b, 0x25d, 0x281, 0x2a7 },
+ { 0x168, 0x17d, 0x194, 0x1ad, 0x1c6, 0x1e1, 0x1fe, 0x21c, 0x23c, 0x25e, 0x282, 0x2a8 },
+ { 0x169, 0x17e, 0x195, 0x1ad, 0x1c7, 0x1e2, 0x1ff, 0x21d, 0x23d, 0x260, 0x283, 0x2a9 },
+ { 0x16a, 0x17f, 0x196, 0x1ae, 0x1c8, 0x1e3, 0x1ff, 0x21e, 0x23e, 0x261, 0x284, 0x2ab },
+ { 0x16a, 0x17f, 0x197, 0x1af, 0x1c8, 0x1e4, 0x200, 0x21f, 0x23f, 0x262, 0x286, 0x2ac }
+ };
+
+// Slot numbers as a function of the voice and the operator.
+// ( melodic only)
+
+static int slotVoice[ NUM_VOICES ][ 2 ] =
+ {
+ { 0, 3 }, // voice 0
+ { 1, 4 }, // 1
+ { 2, 5 }, // 2
+ { 6, 9 }, // 3
+ { 7, 10 }, // 4
+ { 8, 11 }, // 5
+ { 12, 15 }, // 6
+ { 13, 16 }, // 7
+ { 14, 17 }, // 8
+ };
+
+static int VoiceLevel[ NumChipSlots ][ 2 ];
+static int VoiceKsl[ NumChipSlots ][ 2 ];
+
+// This table gives the offset of each slot within the chip.
+// offset = fn( slot)
+
+static char offsetSlot[ NumChipSlots ] =
+ {
+ 0, 1, 2, 3, 4, 5,
+ 8, 9, 10, 11, 12, 13,
+ 16, 17, 18, 19, 20, 21
+ };
+
+static int VoiceReserved[ NUM_VOICES * 2 ] =
+ {
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
+ FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE
+ };
+
+static VOICE Voice[ NUM_VOICES * 2 ];
+static VOICELIST Voice_Pool;
+
+static CHANNEL Channel[ NUM_CHANNELS ];
+
+static int AL_LeftPort = 0x388;
+static int AL_RightPort = 0x388;
+static int AL_Stereo = FALSE;
+static int AL_SendStereo = FALSE;
+static int AL_OPL3 = FALSE;
+static int AL_MaxMidiChannel = 16;
+
+
+/**********************************************************************
+
+ Memory locked functions:
+
+**********************************************************************/
+
+
+#define AL_LockStart AL_SendOutputToPort
+
+
+/*---------------------------------------------------------------------
+ Function: AL_SendOutputToPort
+
+ Sends data to the Adlib using a specified port.
+---------------------------------------------------------------------*/
+
+void AL_SendOutputToPort
+ (
+ int port,
+ int reg,
+ int data
+ )
+
+ {
+ int delay;
+
+ outp( port, reg );
+
+ for( delay = 6; delay > 0 ; delay-- )
+// for( delay = 2; delay > 0 ; delay-- )
+ {
+ inp( port );
+ }
+
+ outp( port + 1, data );
+
+// for( delay = 35; delay > 0 ; delay-- )
+ for( delay = 27; delay > 0 ; delay-- )
+// for( delay = 2; delay > 0 ; delay-- )
+ {
+ inp( port );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_SendOutput
+
+ Sends data to the Adlib.
+---------------------------------------------------------------------*/
+
+void AL_SendOutput
+ (
+ int voice,
+ int reg,
+ int data
+ )
+
+ {
+ int port;
+
+ if ( AL_SendStereo )
+ {
+ AL_SendOutputToPort( AL_LeftPort, reg, data );
+ AL_SendOutputToPort( AL_RightPort, reg, data );
+ }
+ else
+ {
+ port = ( voice == 0 ) ? AL_RightPort : AL_LeftPort;
+ AL_SendOutputToPort( port, reg, data );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_SetVoiceTimbre
+
+ Programs the specified voice's timbre.
+---------------------------------------------------------------------*/
+
+static void AL_SetVoiceTimbre
+ (
+ int voice
+ )
+
+ {
+ int off;
+ int slot;
+ int port;
+ int voc;
+ int patch;
+ int channel;
+ TIMBRE *timbre;
+
+ channel = Voice[ voice ].channel;
+
+ if ( channel == 9 )
+ {
+ patch = Voice[ voice ].key + 128;
+ }
+ else
+ {
+ patch = Channel[ channel ].Timbre;
+ }
+
+ if ( Voice[ voice ].timbre == patch )
+ {
+ return;
+ }
+
+ Voice[ voice ].timbre = patch;
+ timbre = &ADLIB_TimbreBank[ patch ];
+
+ port = Voice[ voice ].port;
+ voc = ( voice >= NUM_VOICES ) ? voice - NUM_VOICES : voice;
+ slot = slotVoice[ voc ][ 0 ];
+ off = offsetSlot[ slot ];
+
+ VoiceLevel[ slot ][ port ] = 63 - ( timbre->Level[ 0 ] & 0x3f );
+ VoiceKsl[ slot ][ port ] = timbre->Level[ 0 ] & 0xc0;
+
+ AL_SendOutput( port, 0xA0 + voc, 0 );
+ AL_SendOutput( port, 0xB0 + voc, 0 );
+
+ // Let voice clear the release
+ AL_SendOutput( port, 0x80 + off, 0xff );
+
+ AL_SendOutput( port, 0x60 + off, timbre->Env1[ 0 ] );
+ AL_SendOutput( port, 0x80 + off, timbre->Env2[ 0 ] );
+ AL_SendOutput( port, 0x20 + off, timbre->SAVEK[ 0 ] );
+ AL_SendOutput( port, 0xE0 + off, timbre->Wave[ 0 ] );
+
+ AL_SendOutput( port, 0x40 + off, timbre->Level[ 0 ] );
+ slot = slotVoice[ voc ][ 1 ];
+
+ if ( AL_SendStereo )
+ {
+ AL_SendOutputToPort( AL_LeftPort, 0xC0 + voice,
+ ( timbre->Feedback & 0x0f ) | 0x20 );
+ AL_SendOutputToPort( AL_RightPort, 0xC0 + voice,
+ ( timbre->Feedback & 0x0f ) | 0x10 );
+ }
+ else
+ {
+ if ( AL_OPL3 )
+ {
+ AL_SendOutput( port, 0xC0 + voc, ( timbre->Feedback & 0x0f ) |
+ 0x30 );
+ }
+ else
+ {
+ AL_SendOutputToPort( ADLIB_PORT, 0xC0 + voice, timbre->Feedback );
+ }
+ }
+
+ off = offsetSlot[ slot ];
+
+ VoiceLevel[ slot ][ port ] = 63 - ( timbre->Level[ 1 ] & 0x3f );
+ VoiceKsl[ slot ][ port ] = timbre->Level[ 1 ] & 0xc0;
+ AL_SendOutput( port, 0x40 + off, 63 );
+
+ // Let voice clear the release
+ AL_SendOutput( port, 0x80 + off, 0xff );
+
+ AL_SendOutput( port, 0x60 + off, timbre->Env1[ 1 ] );
+ AL_SendOutput( port, 0x80 + off, timbre->Env2[ 1 ] );
+ AL_SendOutput( port, 0x20 + off, timbre->SAVEK[ 1 ] );
+ AL_SendOutput( port, 0xE0 + off, timbre->Wave[ 1 ] );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_SetVoiceVolume
+
+ Sets the volume of the specified voice.
+---------------------------------------------------------------------*/
+
+static void AL_SetVoiceVolume
+ (
+ int voice
+ )
+
+ {
+ int channel;
+ int velocity;
+ int slot;
+ int port;
+ int voc;
+ unsigned long t1;
+ unsigned long t2;
+ unsigned long volume;
+ TIMBRE *timbre;
+
+ channel = Voice[ voice ].channel;
+
+ timbre = &ADLIB_TimbreBank[ Voice[ voice ].timbre ];
+
+ velocity = Voice[ voice ].velocity + timbre->Velocity;
+ velocity = min( velocity, MAX_VELOCITY );
+
+ voc = ( voice >= NUM_VOICES ) ? voice - NUM_VOICES : voice;
+ slot = slotVoice[ voc ][ 1 ];
+ port = Voice[ voice ].port;
+
+ // amplitude
+ t1 = ( unsigned )VoiceLevel[ slot ][ port ];
+ t1 *= ( velocity + 0x80 );
+ t1 = ( Channel[ channel ].Volume * t1 ) >> 15;
+
+ if ( !AL_SendStereo )
+ {
+ volume = t1 ^ 63;
+ volume |= ( unsigned )VoiceKsl[ slot ][ port ];
+
+ AL_SendOutput( port, 0x40 + offsetSlot[ slot ], volume );
+
+ // Check if this timbre is Additive
+ if ( timbre->Feedback & 0x01 )
+ {
+ slot = slotVoice[ voc ][ 0 ];
+
+ // amplitude
+ t2 = ( unsigned )VoiceLevel[ slot ][ port ];
+ t2 *= ( velocity + 0x80 );
+ t2 = ( Channel[ channel ].Volume * t1 ) >> 15;
+
+ volume = t2 ^ 63;
+ volume |= ( unsigned )VoiceKsl[ slot ][ port ];
+
+ AL_SendOutput( port, 0x40 + offsetSlot[ slot ], volume );
+ }
+ }
+ else
+ {
+ // Set left channel volume
+ volume = t1;
+ if ( Channel[ channel ].Pan < 64 )
+ {
+ volume *= Channel[ channel ].Pan;
+ volume >>= 6;
+ }
+
+ volume ^= 63;
+ volume |= ( unsigned )VoiceKsl[ slot ][ port ];
+
+ AL_SendOutputToPort( AL_LeftPort, 0x40 + offsetSlot[ slot ], volume );
+
+ // Set right channel volume
+ volume = t1;
+ if ( Channel[ channel ].Pan > 64 )
+ {
+ volume *= 127 - Channel[ channel ].Pan;
+ volume >>= 6;
+ }
+
+ volume ^= 63;
+ volume |= ( unsigned )VoiceKsl[ slot ][ port ];
+
+ AL_SendOutputToPort( AL_RightPort, 0x40 + offsetSlot[ slot ], volume );
+
+ // Check if this timbre is Additive
+ if ( timbre->Feedback & 0x01 )
+ {
+ // amplitude
+ t2 = ( unsigned )VoiceLevel[ slot ][ port ];
+ t2 *= ( velocity + 0x80 );
+ t2 = ( Channel[ channel ].Volume * t1 ) >> 15;
+
+ slot = slotVoice[ voc ][ 0 ];
+
+ // Set left channel volume
+ volume = t2;
+ if ( Channel[ channel ].Pan < 64 )
+ {
+ volume *= Channel[ channel ].Pan;
+ volume >>= 6;
+ }
+
+ volume ^= 63;
+ volume |= ( unsigned )VoiceKsl[ slot ][ port ];
+
+ AL_SendOutputToPort( AL_LeftPort, 0x40 + offsetSlot[ slot ], volume );
+
+ // Set right channel volume
+ volume = t2;
+ if ( Channel[ channel ].Pan > 64 )
+ {
+ volume *= 127 - Channel[ channel ].Pan;
+ volume >>= 6;
+ }
+
+ volume ^= 63;
+ volume |= ( unsigned )VoiceKsl[ slot ][ port ];
+
+ AL_SendOutputToPort( AL_RightPort, 0x40 + offsetSlot[ slot ], volume );
+ }
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_AllocVoice
+
+ Retrieves a free voice from the voice pool.
+---------------------------------------------------------------------*/
+
+static int AL_AllocVoice
+ (
+ void
+ )
+
+ {
+ int voice;
+
+ if ( Voice_Pool.start )
+ {
+ voice = Voice_Pool.start->num;
+ LL_Remove( VOICE, &Voice_Pool, &Voice[ voice ] );
+ return( voice );
+ }
+
+ return( AL_VoiceNotFound );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_GetVoice
+
+ Determines which voice is associated with a specified note and
+ MIDI channel.
+---------------------------------------------------------------------*/
+
+static int AL_GetVoice
+ (
+ int channel,
+ int key
+ )
+
+ {
+ VOICE *voice;
+
+ voice = Channel[ channel ].Voices.start;
+
+ while( voice != NULL )
+ {
+ if ( voice->key == key )
+ {
+ return( voice->num );
+ }
+ voice = voice->next;
+ }
+
+ return( AL_VoiceNotFound );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_SetVoicePitch
+
+ Programs the pitch of the specified voice.
+---------------------------------------------------------------------*/
+
+static void AL_SetVoicePitch
+ (
+ int voice
+ )
+
+ {
+ int note;
+ int channel;
+ int patch;
+ int detune;
+ int ScaleNote;
+ int Octave;
+ int pitch;
+ int port;
+ int voc;
+
+ port = Voice[ voice ].port;
+ voc = ( voice >= NUM_VOICES ) ? voice - NUM_VOICES : voice;
+ channel = Voice[ voice ].channel;
+
+ if ( channel == 9 )
+ {
+ patch = Voice[ voice ].key + 128;
+ note = ADLIB_TimbreBank[ patch ].Transpose;
+ }
+ else
+ {
+ patch = Channel[ channel ].Timbre;
+ note = Voice[ voice ].key + ADLIB_TimbreBank[ patch ].Transpose;
+ }
+
+ note += Channel[ channel ].KeyOffset - 12;
+ if ( note > MAX_NOTE )
+ {
+ note = MAX_NOTE;
+ }
+ if ( note < 0 )
+ {
+ note = 0;
+ }
+
+ detune = Channel[ channel ].KeyDetune;
+
+ ScaleNote = NoteMod12[ note ];
+ Octave = NoteDiv12[ note ];
+
+ pitch = OctavePitch[ Octave ] | NotePitch[ detune ][ ScaleNote ];
+
+ Voice[ voice ].pitchleft = pitch;
+
+ pitch |= Voice[ voice ].status;
+
+ if ( !AL_SendStereo )
+ {
+ AL_SendOutput( port, 0xA0 + voc, pitch );
+ AL_SendOutput( port, 0xB0 + voc, pitch >> 8 );
+ }
+ else
+ {
+ AL_SendOutputToPort( AL_LeftPort, 0xA0 + voice, pitch );
+ AL_SendOutputToPort( AL_LeftPort, 0xB0 + voice, pitch >> 8 );
+
+ if ( channel != 9 )
+ {
+ detune += STEREO_DETUNE;
+ }
+
+ if ( detune > FINETUNE_MAX )
+ {
+ detune -= FINETUNE_RANGE;
+ if ( note < MAX_NOTE )
+ {
+ note++;
+ ScaleNote = NoteMod12[ note ];
+ Octave = NoteDiv12[ note ];
+ }
+ }
+
+ pitch = OctavePitch[ Octave ] | NotePitch[ detune ][ ScaleNote ];
+
+ Voice[ voice ].pitchright = pitch;
+
+ pitch |= Voice[ voice ].status;
+
+ AL_SendOutputToPort( AL_RightPort, 0xA0 + voice, pitch );
+ AL_SendOutputToPort( AL_RightPort, 0xB0 + voice, pitch >> 8 );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_SetChannelVolume
+
+ Sets the volume of the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+static void AL_SetChannelVolume
+ (
+ int channel,
+ int volume
+ )
+
+ {
+ VOICE *voice;
+
+ volume = max( 0, volume );
+ volume = min( volume, AL_MaxVolume );
+ Channel[ channel ].Volume = volume;
+
+ voice = Channel[ channel ].Voices.start;
+ while( voice != NULL )
+ {
+ AL_SetVoiceVolume( voice->num );
+ voice = voice->next;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_SetChannelPan
+
+ Sets the pan position of the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+static void AL_SetChannelPan
+ (
+ int channel,
+ int pan
+ )
+
+ {
+ // Don't pan drum sounds
+ if ( channel != 9 )
+ {
+ Channel[ channel ].Pan = pan;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_SetChannelDetune
+
+ Sets the stereo voice detune of the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+static void AL_SetChannelDetune
+ (
+ int channel,
+ int detune
+ )
+
+ {
+ Channel[ channel ].Detune = detune;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_ResetVoices
+
+ Sets all voice info to the default state.
+---------------------------------------------------------------------*/
+
+static void AL_ResetVoices
+ (
+ void
+ )
+
+ {
+ int index;
+ int numvoices;
+
+ Voice_Pool.start = NULL;
+ Voice_Pool.end = NULL;
+
+ numvoices = NUM_VOICES;
+ if ( ( AL_OPL3 ) && ( !AL_Stereo ) )
+ {
+ numvoices = NUM_VOICES * 2;
+ }
+ for( index = 0; index < numvoices; index++ )
+ {
+ if ( VoiceReserved[ index ] == FALSE )
+ {
+ Voice[ index ].num = index;
+ Voice[ index ].key = 0;
+ Voice[ index ].velocity = 0;
+ Voice[ index ].channel = -1;
+ Voice[ index ].timbre = -1;
+ Voice[ index ].port = ( index < NUM_VOICES ) ? 0 : 1;
+ Voice[ index ].status = NOTE_OFF;
+ LL_AddToTail( VOICE, &Voice_Pool, &Voice[ index ] );
+ }
+ }
+
+ for( index = 0; index < NUM_CHANNELS; index++ )
+ {
+ Channel[ index ].Voices.start = NULL;
+ Channel[ index ].Voices.end = NULL;
+ Channel[ index ].Timbre = 0;
+ Channel[ index ].Pitchbend = 0;
+ Channel[ index ].KeyOffset = 0;
+ Channel[ index ].KeyDetune = 0;
+ Channel[ index ].Volume = AL_DefaultChannelVolume;
+ Channel[ index ].Pan = 64;
+ Channel[ index ].RPN = 0;
+ Channel[ index ].PitchBendRange = AL_DefaultPitchBendRange;
+ Channel[ index ].PitchBendSemiTones = AL_DefaultPitchBendRange / 100;
+ Channel[ index ].PitchBendHundreds = AL_DefaultPitchBendRange % 100;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_CalcPitchInfo
+
+ Calculates the pitch table.
+---------------------------------------------------------------------*/
+
+static void AL_CalcPitchInfo
+ (
+ void
+ )
+
+ {
+ int note;
+// int finetune;
+// double detune;
+
+ for( note = 0; note <= MAX_NOTE; note++ )
+ {
+ NoteMod12[ note ] = note % 12;
+ NoteDiv12[ note ] = note / 12;
+ }
+
+// for( finetune = 1; finetune <= FINETUNE_MAX; finetune++ )
+// {
+// detune = pow( 2, ( double )finetune / ( 12.0 * FINETUNE_RANGE ) );
+// for( note = 0; note < 12; note++ )
+// {
+// NotePitch[ finetune ][ note ] = ( ( double )NotePitch[ 0 ][ note ] * detune );
+// }
+// }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_FlushCard
+
+ Sets all voices to a known (quiet) state.
+---------------------------------------------------------------------*/
+
+void AL_FlushCard
+ (
+ int port
+ )
+
+ {
+ int i;
+ unsigned slot1;
+ unsigned slot2;
+
+ for( i = 0 ; i < NUM_VOICES; i++ )
+ {
+ if ( VoiceReserved[ i ] == FALSE )
+ {
+ slot1 = offsetSlot[ slotVoice[ i ][ 0 ] ];
+ slot2 = offsetSlot[ slotVoice[ i ][ 1 ] ];
+
+ AL_SendOutputToPort( port, 0xA0 + i, 0 );
+ AL_SendOutputToPort( port, 0xB0 + i, 0 );
+
+ AL_SendOutputToPort( port, 0xE0 + slot1, 0 );
+ AL_SendOutputToPort( port, 0xE0 + slot2, 0 );
+
+ // Set the envelope to be fast and quiet
+ AL_SendOutputToPort( port, 0x60 + slot1, 0xff );
+ AL_SendOutputToPort( port, 0x60 + slot2, 0xff );
+ AL_SendOutputToPort( port, 0x80 + slot1, 0xff );
+ AL_SendOutputToPort( port, 0x80 + slot2, 0xff );
+
+ // Maximum attenuation
+ AL_SendOutputToPort( port, 0x40 + slot1, 0xff );
+ AL_SendOutputToPort( port, 0x40 + slot2, 0xff );
+ }
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_StereoOn
+
+ Sets the card send info in stereo.
+---------------------------------------------------------------------*/
+
+void AL_StereoOn
+ (
+ void
+ )
+
+ {
+ if ( ( AL_Stereo ) && ( !AL_SendStereo ) )
+ {
+ AL_SendStereo = TRUE;
+ if ( AL_OPL3 )
+ {
+ // Set card to OPL3 operation
+ AL_SendOutputToPort( AL_RightPort, 0x5, 1 );
+ }
+ }
+ else if ( AL_OPL3 )
+ {
+ // Set card to OPL3 operation
+ AL_SendOutputToPort( AL_RightPort, 0x5, 1 );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_StereoOff
+
+ Sets the card send info in mono.
+---------------------------------------------------------------------*/
+
+void AL_StereoOff
+ (
+ void
+ )
+
+ {
+ if ( ( AL_Stereo ) && ( AL_SendStereo ) )
+ {
+ AL_SendStereo = FALSE;
+ if ( AL_OPL3 )
+ {
+ // Set card back to OPL2 operation
+ AL_SendOutputToPort( AL_RightPort, 0x5, 0 );
+ }
+ }
+ else if ( AL_OPL3 )
+ {
+ // Set card back to OPL2 operation
+ AL_SendOutputToPort( AL_RightPort, 0x5, 0 );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_Reset
+
+ Sets the card to a known (quiet) state.
+---------------------------------------------------------------------*/
+
+void AL_Reset
+ (
+ void
+ )
+
+ {
+ AL_SendOutputToPort( ADLIB_PORT, 1, 0x20 );
+ AL_SendOutputToPort( ADLIB_PORT, 0x08, 0 );
+
+ // Set the values: AM Depth, VIB depth & Rhythm
+ AL_SendOutputToPort( ADLIB_PORT, 0xBD, 0 );
+
+ AL_StereoOn();
+
+ if ( ( AL_SendStereo ) || ( AL_OPL3 ) )
+ {
+ AL_FlushCard( AL_LeftPort );
+ AL_FlushCard( AL_RightPort );
+ }
+ else
+ {
+ AL_FlushCard( ADLIB_PORT );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_ReserveVoice
+
+ Marks a voice as being not available for use. This allows the
+ driver to use the rest of the card while another driver uses the
+ reserved voice.
+---------------------------------------------------------------------*/
+
+int AL_ReserveVoice
+ (
+ int voice
+ )
+
+ {
+ unsigned flags;
+
+ if ( ( voice < 0 ) || ( voice >= NUM_VOICES ) )
+ {
+ return( AL_Error );
+ }
+
+ if ( VoiceReserved[ voice ] )
+ {
+ return( AL_Warning );
+ }
+
+ flags = DisableInterrupts();
+
+ if ( Voice[ voice ].status == NOTE_ON )
+ {
+ AL_NoteOff( Voice[ voice ].channel, Voice[ voice ].key, 0 );
+ }
+
+ VoiceReserved[ voice ] = TRUE;
+ LL_Remove( VOICE, &Voice_Pool, &Voice[ voice ] );
+
+ RestoreInterrupts( flags );
+ return( AL_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_ReleaseVoice
+
+ Marks a previously reserved voice as being free to use.
+---------------------------------------------------------------------*/
+
+int AL_ReleaseVoice
+ (
+ int voice
+ )
+
+ {
+ unsigned flags;
+
+ if ( ( voice < 0 ) || ( voice >= NUM_VOICES ) )
+ {
+ return( AL_Error );
+ }
+
+ if ( !VoiceReserved[ voice ] )
+ {
+ return( AL_Warning );
+ }
+
+ flags = DisableInterrupts();
+
+ VoiceReserved[ voice ] = FALSE;
+ LL_AddToTail( VOICE, &Voice_Pool, &Voice[ voice ] );
+
+ RestoreInterrupts( flags );
+ return( AL_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_NoteOff
+
+ Turns off a note on the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+void AL_NoteOff
+ (
+ int channel,
+ int key,
+ int velocity
+ )
+
+ {
+ int voice;
+ int port;
+ int voc;
+
+ // We only play channels 1 through 10
+ if ( channel > AL_MaxMidiChannel )
+ {
+ return;
+ }
+
+ voice = AL_GetVoice( channel, key );
+
+ if ( voice == AL_VoiceNotFound )
+ {
+ return;
+ }
+
+ Voice[ voice ].status = NOTE_OFF;
+
+ port = Voice[ voice ].port;
+ voc = ( voice >= NUM_VOICES ) ? voice - NUM_VOICES : voice;
+
+ if ( AL_SendStereo )
+ {
+ AL_SendOutputToPort( AL_LeftPort, 0xB0 + voice,
+ hibyte( Voice[ voice ].pitchleft ) );
+ AL_SendOutputToPort( AL_RightPort, 0xB0 + voice,
+ hibyte( Voice[ voice ].pitchright ) );
+ }
+ else
+ {
+ AL_SendOutput( port, 0xB0 + voc, hibyte( Voice[ voice ].pitchleft ) );
+ }
+
+ LL_Remove( VOICE, &Channel[ channel ].Voices, &Voice[ voice ] );
+ LL_AddToTail( VOICE, &Voice_Pool, &Voice[ voice ] );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_NoteOn
+
+ Plays a note on the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+void AL_NoteOn
+ (
+ int channel,
+ int key,
+ int velocity
+ )
+
+ {
+ int voice;
+
+ // We only play channels 1 through 10
+ if ( channel > AL_MaxMidiChannel )
+ {
+ return;
+ }
+
+ if ( velocity == 0 )
+ {
+ AL_NoteOff( channel, key, velocity );
+ return;
+ }
+
+ voice = AL_AllocVoice();
+
+ if ( voice == AL_VoiceNotFound )
+ {
+ if ( Channel[ 9 ].Voices.start )
+ {
+ AL_NoteOff( 9, Channel[ 9 ].Voices.start->key, 0 );
+ voice = AL_AllocVoice();
+ }
+ if ( voice == AL_VoiceNotFound )
+ {
+ return;
+ }
+ }
+
+ Voice[ voice ].key = key;
+ Voice[ voice ].channel = channel;
+ Voice[ voice ].velocity = velocity;
+ Voice[ voice ].status = NOTE_ON;
+
+ LL_AddToTail( VOICE, &Channel[ channel ].Voices, &Voice[ voice ] );
+
+ AL_SetVoiceTimbre( voice );
+ AL_SetVoiceVolume( voice );
+ AL_SetVoicePitch( voice );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_AllNotesOff
+
+ Turns off all currently playing voices.
+---------------------------------------------------------------------*/
+
+void AL_AllNotesOff
+ (
+ int channel
+ )
+
+ {
+ while( Channel[ channel ].Voices.start != NULL )
+ {
+ AL_NoteOff( channel, Channel[ channel ].Voices.start->key, 0 );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_ControlChange
+
+ Sets the value of a controller on the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+void AL_ControlChange
+ (
+ int channel,
+ int type,
+ int data
+ )
+
+ {
+ // We only play channels 1 through 10
+ if ( channel > AL_MaxMidiChannel )
+ {
+ return;
+ }
+
+ switch( type )
+ {
+ case MIDI_VOLUME :
+ AL_SetChannelVolume( channel, data );
+ break;
+
+ case MIDI_PAN :
+ AL_SetChannelPan( channel, data );
+ break;
+
+ case MIDI_DETUNE :
+ AL_SetChannelDetune( channel, data );
+ break;
+
+ case MIDI_ALL_NOTES_OFF :
+ AL_AllNotesOff( channel );
+ break;
+
+ case MIDI_RESET_ALL_CONTROLLERS :
+ AL_ResetVoices();
+ AL_SetChannelVolume( channel, AL_DefaultChannelVolume );
+ AL_SetChannelPan( channel, 64 );
+ AL_SetChannelDetune( channel, 0 );
+ break;
+
+ case MIDI_RPN_MSB :
+ Channel[ channel ].RPN &= 0x00FF;
+ Channel[ channel ].RPN |= ( data & 0xFF ) << 8;
+ break;
+
+ case MIDI_RPN_LSB :
+ Channel[ channel ].RPN &= 0xFF00;
+ Channel[ channel ].RPN |= data & 0xFF;
+ break;
+
+ case MIDI_DATAENTRY_MSB :
+ if ( Channel[ channel ].RPN == MIDI_PITCHBEND_RPN )
+ {
+ Channel[ channel ].PitchBendSemiTones = data;
+ Channel[ channel ].PitchBendRange =
+ Channel[ channel ].PitchBendSemiTones * 100 +
+ Channel[ channel ].PitchBendHundreds;
+ }
+ break;
+
+ case MIDI_DATAENTRY_LSB :
+ if ( Channel[ channel ].RPN == MIDI_PITCHBEND_RPN )
+ {
+ Channel[ channel ].PitchBendHundreds = data;
+ Channel[ channel ].PitchBendRange =
+ Channel[ channel ].PitchBendSemiTones * 100 +
+ Channel[ channel ].PitchBendHundreds;
+ }
+ break;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_ProgramChange
+
+ Selects the instrument to use on the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+void AL_ProgramChange
+ (
+ int channel,
+ int patch
+ )
+
+ {
+ // We only play channels 1 through 10
+ if ( channel > AL_MaxMidiChannel )
+ {
+ return;
+ }
+
+ Channel[ channel ].Timbre = patch;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_SetPitchBend
+
+ Sets the pitch bend amount on the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+void AL_SetPitchBend
+ (
+ int channel,
+ int lsb,
+ int msb
+ )
+
+ {
+ int pitchbend;
+ unsigned long TotalBend;
+ VOICE *voice;
+
+ // We only play channels 1 through 10
+ if ( channel > AL_MaxMidiChannel )
+ {
+ return;
+ }
+
+ pitchbend = lsb + ( msb << 8 );
+ Channel[ channel ].Pitchbend = pitchbend;
+
+ TotalBend = pitchbend * Channel[ channel ].PitchBendRange;
+ TotalBend /= ( PITCHBEND_CENTER / FINETUNE_RANGE );
+
+ Channel[ channel ].KeyOffset = ( int )( TotalBend / FINETUNE_RANGE );
+ Channel[ channel ].KeyOffset -= Channel[ channel ].PitchBendSemiTones;
+
+ Channel[ channel ].KeyDetune = ( unsigned )( TotalBend % FINETUNE_RANGE );
+
+ voice = Channel[ channel ].Voices.start;
+ while( voice != NULL )
+ {
+ AL_SetVoicePitch( voice->num );
+ voice = voice->next;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_DetectFM
+
+ Determines if an Adlib compatible card is installed in the machine.
+---------------------------------------------------------------------*/
+
+int AL_DetectFM
+ (
+ void
+ )
+
+ {
+ int status1;
+ int status2;
+ int i;
+
+ if ( USER_CheckParameter( NO_ADLIB_DETECTION ) )
+ {
+ return( FALSE );
+ }
+
+ AL_SendOutputToPort( ADLIB_PORT, 4, 0x60 ); // Reset T1 & T2
+ AL_SendOutputToPort( ADLIB_PORT, 4, 0x80 ); // Reset IRQ
+
+ status1 = inp( ADLIB_PORT );
+
+ AL_SendOutputToPort( ADLIB_PORT, 2, 0xff ); // Set timer 1
+ AL_SendOutputToPort( ADLIB_PORT, 4, 0x21 ); // Start timer 1
+
+ for( i = 100; i > 0; i-- )
+ {
+ inp( ADLIB_PORT );
+ }
+
+ status2 = inp( ADLIB_PORT );
+
+ AL_SendOutputToPort( ADLIB_PORT, 4, 0x60 );
+ AL_SendOutputToPort( ADLIB_PORT, 4, 0x80 );
+
+ return( ( ( status1 & 0xe0 ) == 0x00 ) && ( ( status2 & 0xe0 ) == 0xc0 ) );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_LockEnd
+
+ Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void AL_LockEnd
+ (
+ void
+ )
+
+ {
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_Shutdown
+
+ Ends use of the sound card and resets it to a quiet state.
+---------------------------------------------------------------------*/
+
+void AL_Shutdown
+ (
+ void
+ )
+
+ {
+ AL_StereoOff();
+
+ AL_OPL3 = FALSE;
+ AL_ResetVoices();
+ AL_Reset();
+
+ DPMI_UnlockMemoryRegion( AL_LockStart, AL_LockEnd );
+ DPMI_Unlock( slotVoice );
+ DPMI_Unlock( VoiceLevel );
+ DPMI_Unlock( VoiceKsl );
+ DPMI_Unlock( offsetSlot );
+ DPMI_Unlock( NotePitch );
+ DPMI_Unlock( OctavePitch );
+ DPMI_Unlock( NoteMod12 );
+ DPMI_Unlock( NoteDiv12 );
+ DPMI_Unlock( VoiceReserved );
+ DPMI_Unlock( Voice );
+ DPMI_Unlock( Voice_Pool );
+ DPMI_Unlock( Channel );
+ DPMI_Unlock( AL_LeftPort );
+ DPMI_Unlock( AL_RightPort );
+ DPMI_Unlock( AL_Stereo );
+ DPMI_Unlock( AL_SendStereo );
+ DPMI_Unlock( AL_OPL3 );
+ DPMI_Unlock( AL_MaxMidiChannel );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_SetMaxMidiChannel
+
+ Sets the maximum MIDI channel that FM cards respond to.
+---------------------------------------------------------------------*/
+
+void AL_SetMaxMidiChannel
+ (
+ int channel
+ )
+
+ {
+ AL_MaxMidiChannel = channel - 1;
+ }
+
+/*---------------------------------------------------------------------
+ Function: AL_Init
+
+ Begins use of the sound card.
+---------------------------------------------------------------------*/
+
+int AL_Init
+ (
+ int soundcard
+ )
+
+ {
+ BLASTER_CONFIG Blaster;
+ int status;
+
+ status = DPMI_LockMemoryRegion( AL_LockStart, AL_LockEnd );
+ status |= DPMI_Lock( slotVoice );
+ status |= DPMI_Lock( VoiceLevel );
+ status |= DPMI_Lock( VoiceKsl );
+ status |= DPMI_Lock( offsetSlot );
+ status |= DPMI_Lock( NotePitch );
+ status |= DPMI_Lock( OctavePitch );
+ status |= DPMI_Lock( NoteMod12 );
+ status |= DPMI_Lock( NoteDiv12 );
+ status |= DPMI_Lock( VoiceReserved );
+ status |= DPMI_Lock( Voice );
+ status |= DPMI_Lock( Voice_Pool );
+ status |= DPMI_Lock( Channel );
+ status |= DPMI_Lock( AL_LeftPort );
+ status |= DPMI_Lock( AL_RightPort );
+ status |= DPMI_Lock( AL_Stereo );
+ status |= DPMI_Lock( AL_SendStereo );
+ status |= DPMI_Lock( AL_OPL3 );
+ status |= DPMI_Lock( AL_MaxMidiChannel );
+
+ if ( status != DPMI_Ok )
+ {
+ return( AL_Error );
+ }
+
+ AL_Stereo = FALSE;
+ AL_OPL3 = FALSE;
+ AL_LeftPort = 0x388;
+ AL_RightPort = 0x388;
+
+ switch( soundcard )
+ {
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ AL_OPL3 = TRUE;
+ AL_LeftPort = 0x388;
+ AL_RightPort = 0x38A;
+ break;
+
+ case SoundBlaster :
+ status = BLASTER_GetCardSettings( &Blaster );
+ if ( status != BLASTER_Ok )
+ {
+ status = BLASTER_GetEnv( &Blaster );
+ if ( status != BLASTER_Ok )
+ {
+ break;
+ }
+ }
+
+ switch( Blaster.Type )
+ {
+ case SBPro2 :
+ case SB16 :
+ AL_OPL3 = TRUE;
+ AL_LeftPort = Blaster.Address;
+ AL_RightPort = Blaster.Address + 2;
+ break;
+ }
+ break;
+ }
+// Temporarally commented out for ROTT.
+// Stereo FM seems to take too long on some computers and
+// causes the mouse driver to miss interrupts.
+
+/*
+ switch( soundcard )
+ {
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ AL_OPL3 = TRUE;
+ AL_Stereo = TRUE;
+ AL_LeftPort = 0x388;
+ AL_RightPort = 0x38A;
+ break;
+
+ case SoundBlaster :
+ status = BLASTER_GetCardSettings( &Blaster );
+ if ( status != BLASTER_Ok )
+ {
+ status = BLASTER_GetEnv( &Blaster );
+ if ( status != BLASTER_Ok )
+ {
+ break;
+ }
+ }
+
+ switch( Blaster.Type )
+ {
+ case SBPro2 :
+ case SB16 :
+ AL_OPL3 = TRUE;
+ AL_Stereo = TRUE;
+ AL_LeftPort = Blaster.Address;
+ AL_RightPort = Blaster.Address + 2;
+ break;
+
+ case SBPro :
+ AL_Stereo = TRUE;
+ AL_LeftPort = Blaster.Address;
+ AL_RightPort = Blaster.Address + 2;
+ break;
+ }
+ break;
+ }
+*/
+
+ AL_CalcPitchInfo();
+ AL_Reset();
+ AL_ResetVoices();
+
+ return( AL_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AL_RegisterTimbreBank
+
+ Copies user supplied timbres over the default timbre bank.
+---------------------------------------------------------------------*/
+
+void AL_RegisterTimbreBank
+ (
+ unsigned char *timbres
+ )
+
+ {
+ int i;
+
+ for( i = 0; i < 256; i++ )
+ {
+ ADLIB_TimbreBank[ i ].SAVEK[ 0 ] = *( timbres++ );
+ ADLIB_TimbreBank[ i ].SAVEK[ 1 ] = *( timbres++ );
+ ADLIB_TimbreBank[ i ].Level[ 0 ] = *( timbres++ );
+ ADLIB_TimbreBank[ i ].Level[ 1 ] = *( timbres++ );
+ ADLIB_TimbreBank[ i ].Env1[ 0 ] = *( timbres++ );
+ ADLIB_TimbreBank[ i ].Env1[ 1 ] = *( timbres++ );
+ ADLIB_TimbreBank[ i ].Env2[ 0 ] = *( timbres++ );
+ ADLIB_TimbreBank[ i ].Env2[ 1 ] = *( timbres++ );
+ ADLIB_TimbreBank[ i ].Wave[ 0 ] = *( timbres++ );
+ ADLIB_TimbreBank[ i ].Wave[ 1 ] = *( timbres++ );
+ ADLIB_TimbreBank[ i ].Feedback = *( timbres++ );
+ ADLIB_TimbreBank[ i ].Transpose = *( signed char * )( timbres++ );
+ ADLIB_TimbreBank[ i ].Velocity = *( signed char * )( timbres++ );
+ }
+ }
--- /dev/null
+++ b/rott/audiolib/al_midi.h
@@ -1,0 +1,58 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef __AL_MIDI_H
+#define __AL_MIDI_H
+
+enum AL_Errors
+ {
+ AL_Warning = -2,
+ AL_Error = -1,
+ AL_Ok = 0,
+ };
+
+#define AL_MaxVolume 127
+#define AL_DefaultChannelVolume 90
+//#define AL_DefaultPitchBendRange 2
+#define AL_DefaultPitchBendRange 200
+
+#define ADLIB_PORT 0x388
+
+void AL_SendOutputToPort( int port, int reg, int data );
+void AL_SendOutput( int voice, int reg, int data );
+void AL_StereoOn( void );
+void AL_StereoOff( void );
+int AL_ReserveVoice( int voice );
+int AL_ReleaseVoice( int voice );
+void AL_Shutdown( void );
+int AL_Init( int soundcard );
+void AL_SetMaxMidiChannel( int channel );
+void AL_Reset( void );
+void AL_NoteOff( int channel, int key, int velocity );
+void AL_NoteOn( int channel, int key, int vel );
+//Turned off to test if it works with Watcom 10a
+// #pragma aux AL_NoteOn frame;
+void AL_AllNotesOff( int channel );
+void AL_ControlChange( int channel, int type, int data );
+void AL_ProgramChange( int channel, int patch );
+void AL_SetPitchBend( int channel, int lsb, int msb );
+int AL_DetectFM( void );
+void AL_RegisterTimbreBank( unsigned char *timbres );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/assert.h
@@ -1,0 +1,45 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef __ASSERT_H
+
+ #define __ASSERT_H
+
+ #ifdef NDEBUG
+
+ #define ASSERT(f)
+
+ #else
+
+ #pragma aux _Assert aborts; /* _Assert will not return */
+ extern void _Assert( char *strFile, unsigned uLine ); /*prototype */
+
+ #define ASSERT(f) \
+ if (f) \
+ ; \
+ else \
+ _Assert( __FILE__, __LINE__ )
+
+ #endif
+
+#else
+
+ #error Multiple definition of ASSERT()
+
+#endif
binary files /dev/null b/rott/audiolib/audiolib.a differ
--- /dev/null
+++ b/rott/audiolib/awe32.c
@@ -1,0 +1,540 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: AWE32.C
+
+ author: James R. Dose
+ date: August 23, 1994
+
+ Cover functions for calling the AWE32 low-level library.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#include <conio.h>
+#include <string.h>
+#include "dpmi.h"
+#include "blaster.h"
+#include "ctaweapi.h"
+#include "awe32.h"
+
+#define _inp inp
+#define _outp outp
+
+/* DSP defines */
+#define MPU_ACK_OK 0xfe
+#define MPU_RESET_CMD 0xff
+#define MPU_ENTER_UART 0x3f
+
+static WORD wSBCBaseAddx; /* Sound Blaster base address */
+static WORD wEMUBaseAddx; /* EMU8000 subsystem base address */
+static WORD wMpuBaseAddx; /* MPU401 base address */
+
+static unsigned short NoteFlags[ 128 ];
+
+/* macros */
+#define SBCPort( x ) ( ( x ) + wSBCBaseAddx )
+#define MPUPort( x ) ( ( x ) + wMpuBaseAddx )
+
+static SOUND_PACKET spSound =
+ {
+ 0
+ };
+
+static LONG lBankSizes[ MAXBANKS ] =
+ {
+ 0
+ };
+
+unsigned SetES( void );
+#pragma aux SetES = \
+ "xor eax, eax" \
+ "mov ax, es" \
+ "mov bx, ds" \
+ "mov es, bx" \
+ modify [ eax ebx ];
+
+void RestoreES( unsigned num );
+#pragma aux RestoreES = \
+ "mov es, ax" \
+ parm [ eax ];
+
+int AWE32_ErrorCode = AWE32_Ok;
+
+#define AWE32_SetErrorCode( status ) \
+ AWE32_ErrorCode = ( status );
+
+
+/*---------------------------------------------------------------------
+ Function: AWE32_ErrorString
+
+ Returns a pointer to the error message associated with an error
+ number. A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *AWE32_ErrorString
+ (
+ int ErrorNumber
+ )
+
+ {
+ char *ErrorString;
+
+ switch( ErrorNumber )
+ {
+ case AWE32_Warning :
+ case AWE32_Error :
+ ErrorString = AWE32_ErrorString( AWE32_ErrorCode );
+ break;
+
+ case AWE32_Ok :
+ ErrorString = "AWE32 ok.";
+ break;
+
+ case AWE32_SoundBlasterError :
+ ErrorString = BLASTER_ErrorString( BLASTER_Error );
+ break;
+
+ case AWE32_NotDetected :
+ ErrorString = "Could not detect AWE32.";
+ break;
+
+ case AWE32_UnableToInitialize :
+ ErrorString = "Unable to initialize AWE32.";
+
+ case AWE32_MPU401Error :
+ ErrorString = "MPU-401 initialization failed in AWE32.";
+ break;
+
+ case AWE32_DPMI_Error :
+ ErrorString = "DPMI Error in AWE32.";
+ break;
+
+ default :
+ ErrorString = "Unknown AWE32 error code.";
+ break;
+ }
+
+ return( ErrorString );
+ }
+
+
+/**********************************************************************
+
+ Memory locked functions:
+
+**********************************************************************/
+
+
+#define AWE32_LockStart AWE32_NoteOff
+
+
+void AWE32_NoteOff
+ (
+ int channel,
+ int key,
+ int velocity
+ )
+
+ {
+ unsigned temp;
+
+ temp = SetES();
+ awe32NoteOff( channel, key, velocity );
+ RestoreES( temp );
+ NoteFlags[ key ] ^= ( 1 << channel );
+ }
+
+void AWE32_NoteOn
+ (
+ int channel,
+ int key,
+ int velocity
+ )
+
+ {
+ unsigned temp;
+
+ temp = SetES();
+ awe32NoteOn( channel, key, velocity );
+ RestoreES( temp );
+ NoteFlags[ key ] |= ( 1 << channel );
+ }
+
+void AWE32_PolyAftertouch
+ (
+ int channel,
+ int key,
+ int pressure
+ )
+
+ {
+ unsigned temp;
+
+ temp = SetES();
+ awe32PolyKeyPressure( channel, key, pressure );
+ RestoreES( temp );
+ }
+
+void AWE32_ChannelAftertouch
+ (
+ int channel,
+ int pressure
+ )
+
+ {
+ unsigned temp;
+
+ temp = SetES();
+ awe32ChannelPressure( channel, pressure );
+ RestoreES( temp );
+ }
+
+void AWE32_ControlChange
+ (
+ int channel,
+ int number,
+ int value
+ )
+
+ {
+ unsigned temp;
+ int i;
+ unsigned channelmask;
+
+ temp = SetES();
+
+ if ( number == 0x7b )
+ {
+ channelmask = 1 << channel;
+ for( i = 0; i < 128; i++ )
+ {
+ if ( NoteFlags[ i ] & channelmask )
+ {
+ awe32NoteOff( channel, i, 0 );
+ NoteFlags[ i ] ^= channelmask;
+ }
+ }
+ }
+ else
+ {
+ awe32Controller( channel, number, value );
+ }
+ RestoreES( temp );
+ }
+
+void AWE32_ProgramChange
+ (
+ int channel,
+ int program
+ )
+
+ {
+ unsigned temp;
+
+ temp = SetES();
+ awe32ProgramChange( channel, program );
+ RestoreES( temp );
+ }
+
+void AWE32_PitchBend
+ (
+ int channel,
+ int lsb,
+ int msb
+ )
+
+ {
+ unsigned temp;
+
+ temp = SetES();
+ awe32PitchBend( channel, lsb, msb );
+ RestoreES( temp );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: AWE32_LockEnd
+
+ Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void AWE32_LockEnd
+ (
+ void
+ )
+
+ {
+ }
+
+
+/*
+static int InitMPU
+ (
+ void
+ )
+
+ {
+ volatile DWORD dwCount;
+
+ for (dwCount=0; dwCount<0x2000; dwCount++) ;
+ dwCount = 0x2000;
+ while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
+ _outp(MPUPort(1), MPU_RESET_CMD);
+
+ for (dwCount=0; dwCount<0x2000; dwCount++) ;
+ dwCount = 0x2000;
+ while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount;
+ _inp(MPUPort(0));
+
+ for (dwCount=0; dwCount<0x2000; dwCount++) ;
+ dwCount = 0x2000;
+ while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
+ _outp(MPUPort(1), MPU_RESET_CMD);
+
+ for (dwCount=0; dwCount<0x2000; dwCount++) ;
+ dwCount = 0x2000;
+ while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount;
+ _inp(MPUPort(0));
+
+ for (dwCount=0; dwCount<0x2000; dwCount++) ;
+ dwCount = 0x2000;
+ while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
+ _outp(MPUPort(1), MPU_ENTER_UART);
+
+ for (dwCount=0; dwCount<0x2000; dwCount++) ;
+ dwCount = 0x2000;
+ while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount;
+ if (!dwCount) return TRUE;
+ if (_inp(MPUPort(0)) != MPU_ACK_OK) return TRUE;
+
+ // mask MPU-401 interrupt
+ _outp(SBCPort(0x4), 0x83);
+ _outp(SBCPort(0x5), _inp(SBCPort(0x5)) & ~0x04);
+
+ return FALSE;
+ }
+*/
+
+/*������������������������������������������������������������������������*/
+/*� ShutdownMPU �*/
+/*� Cleans up Sound Blaster to normal state. �*/
+/*������������������������������������������������������������������������;*/
+
+static void ShutdownMPU
+ (
+ void
+ )
+
+ {
+ volatile DWORD dwCount;
+
+ for (dwCount=0; dwCount<0x2000; dwCount++) ;
+ dwCount = 0x2000;
+ while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
+ _outp(MPUPort(1), MPU_RESET_CMD);
+ for (dwCount=0; dwCount<0x2000; dwCount++) ;
+ _inp(MPUPort(0));
+
+ for (dwCount=0; dwCount<0x2000; dwCount++) ;
+ dwCount = 0x2000;
+ while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount;
+ _outp(MPUPort(1), MPU_RESET_CMD);
+ for (dwCount=0; dwCount<0x2000; dwCount++) ;
+ _inp(MPUPort(0));
+ }
+
+
+/*������������������������������������������������������������������������*/
+/*� LoadSBK �*/
+/*������������������������������������������������������������������������;*/
+
+static void LoadSBK
+ (
+ void
+ )
+
+ {
+ /* use embeded preset objects */
+ spSound.bank_no = 0; /* load as Bank 0 */
+ spSound.total_banks = 1; /* use 1 bank first */
+ lBankSizes[ 0 ] = 0; /* ram is not needed */
+
+ spSound.banksizes = lBankSizes;
+ awe32DefineBankSizes( &spSound );
+ awe32SoundPad.SPad1 = awe32SPad1Obj;
+ awe32SoundPad.SPad2 = awe32SPad2Obj;
+ awe32SoundPad.SPad3 = awe32SPad3Obj;
+ awe32SoundPad.SPad4 = awe32SPad4Obj;
+ awe32SoundPad.SPad5 = awe32SPad5Obj;
+ awe32SoundPad.SPad6 = awe32SPad6Obj;
+ awe32SoundPad.SPad7 = awe32SPad7Obj;
+ }
+
+
+int AWE32_Init
+ (
+ void
+ )
+
+ {
+ int status;
+ BLASTER_CONFIG Blaster;
+
+ wSBCBaseAddx = 0x220;
+ wEMUBaseAddx = 0x620;
+ wMpuBaseAddx = 0x330;
+
+ status = BLASTER_GetCardSettings( &Blaster );
+ if ( status != BLASTER_Ok )
+ {
+ status = BLASTER_GetEnv( &Blaster );
+ if ( status != BLASTER_Ok )
+ {
+ AWE32_SetErrorCode( AWE32_SoundBlasterError );
+ return( AWE32_Error );
+ }
+ }
+
+ wSBCBaseAddx = Blaster.Address;
+ if ( wSBCBaseAddx == UNDEFINED )
+ {
+ wSBCBaseAddx = 0x220;
+ }
+
+ wMpuBaseAddx = Blaster.Midi;
+ if ( wMpuBaseAddx == UNDEFINED )
+ {
+ wMpuBaseAddx = 0x330;
+ }
+
+ wEMUBaseAddx = Blaster.Emu;
+ if ( wEMUBaseAddx <= 0 )
+ {
+ wEMUBaseAddx = wSBCBaseAddx + 0x400;
+ }
+
+ status = awe32Detect( wEMUBaseAddx );
+ if ( status )
+ {
+ AWE32_SetErrorCode( AWE32_NotDetected );
+ return( AWE32_Error );
+ }
+
+ status = awe32InitHardware();
+ if ( status )
+ {
+ AWE32_SetErrorCode( AWE32_UnableToInitialize );
+ return( AWE32_Error );
+ }
+
+
+ status = awe32InitMIDI();
+ if ( status )
+ {
+ AWE32_Shutdown();
+ AWE32_SetErrorCode( AWE32_MPU401Error )
+ return( AWE32_Error );
+ }
+
+/*
+ status = InitMPU();
+ if ( status )
+ {
+ ShutdownMPU();
+ status = InitMPU();
+ if ( status )
+ {
+ ShutdownMPU();
+ status = InitMPU();
+ if ( status )
+ {
+ AWE32_Shutdown();
+ AWE32_SetErrorCode( AWE32_MPU401Error )
+ return( AWE32_Error );
+ }
+ }
+ }
+*/
+ status = DPMI_LockMemoryRegion( AWE32_LockStart, AWE32_LockEnd );
+ status |= DPMI_Lock( wSBCBaseAddx );
+ status |= DPMI_Lock( wEMUBaseAddx );
+ status |= DPMI_Lock( wMpuBaseAddx );
+ status |= DPMI_Lock( spSound );
+ status |= DPMI_Lock( lBankSizes );
+ status |= DPMI_LockMemory( NoteFlags, sizeof( NoteFlags ) );
+
+ // Lock awe32 library
+ status = DPMI_LockMemoryRegion( __midieng_code, __midieng_ecode );
+ status = DPMI_LockMemoryRegion( __midieng_code(), __midieng_ecode() );
+ status = DPMI_LockMemoryRegion( __nrpn_code, __nrpn_ecode );
+ status = DPMI_LockMemoryRegion( __nrpn_code(), __nrpn_ecode() );
+ status = DPMI_LockMemoryRegion( &__midivar_data, &__midivar_edata );
+ status = DPMI_LockMemoryRegion( &__nrpnvar_data, &__nrpnvar_edata );
+ status = DPMI_LockMemoryRegion( &__embed_data, &__embed_edata );
+
+ if ( status != DPMI_Ok )
+ {
+ ShutdownMPU();
+ awe32Terminate();
+ AWE32_SetErrorCode( AWE32_DPMI_Error );
+ return( AWE32_Error );
+ }
+
+ // Set the number of voices to use to 32
+ awe32NumG = 32;
+
+ awe32TotalPatchRam(&spSound);
+
+ LoadSBK();
+ awe32InitMIDI();
+ awe32InitNRPN();
+
+ memset( NoteFlags, 0, sizeof( NoteFlags ) );
+
+ return( AWE32_Ok );
+ }
+
+void AWE32_Shutdown
+ (
+ void
+ )
+
+ {
+ ShutdownMPU();
+ awe32Terminate();
+
+ DPMI_UnlockMemoryRegion( AWE32_LockStart, AWE32_LockEnd );
+ DPMI_Unlock( wSBCBaseAddx );
+ DPMI_Unlock( wEMUBaseAddx );
+ DPMI_Unlock( wMpuBaseAddx );
+ DPMI_Unlock( spSound );
+ DPMI_Unlock( lBankSizes );
+ DPMI_UnlockMemory( NoteFlags, sizeof( NoteFlags ) );
+
+ // Unlock awe32 library
+ DPMI_UnlockMemoryRegion( __midieng_code, __midieng_ecode );
+ DPMI_UnlockMemoryRegion( __midieng_code(), __midieng_ecode() );
+ DPMI_UnlockMemoryRegion( __nrpn_code, __nrpn_ecode );
+ DPMI_UnlockMemoryRegion( __nrpn_code(), __nrpn_ecode() );
+ DPMI_UnlockMemoryRegion( &__midivar_data, &__midivar_edata );
+ DPMI_UnlockMemoryRegion( &__nrpnvar_data, &__nrpnvar_edata );
+ DPMI_UnlockMemoryRegion( &__embed_data, &__embed_edata );
+ }
--- /dev/null
+++ b/rott/audiolib/awe32.h
@@ -1,0 +1,58 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: AWE32.H
+
+ author: James R. Dose
+ date: August 23, 1994
+
+ Public header for AWE32.C Cover functions for calling the
+ AWE32 low-level library.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __AWE32_H
+#define __AWE32_H
+
+enum AWE32_ERRORS
+ {
+ AWE32_Warning = -2,
+ AWE32_Error = -1,
+ AWE32_Ok = 0,
+ AWE32_SoundBlasterError,
+ AWE32_NotDetected,
+ AWE32_UnableToInitialize,
+ AWE32_MPU401Error,
+ AWE32_DPMI_Error
+ };
+
+char *AWE32_ErrorString( int ErrorNumber );
+int AWE32_Init( void );
+void AWE32_Shutdown( void );
+void AWE32_NoteOff( int channel, int key, int velocity );
+void AWE32_NoteOn( int channel, int key, int velocity );
+void AWE32_PolyAftertouch( int channel, int key, int pressure );
+void AWE32_ChannelAftertouch( int channel, int pressure );
+void AWE32_ControlChange( int channel, int number, int value );
+void AWE32_ProgramChange( int channel, int program );
+void AWE32_PitchBend( int channel, int lsb, int msb );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/blaster.c
@@ -1,0 +1,2330 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: BLASTER.C
+
+ author: James R. Dose
+ date: February 4, 1994
+
+ Low level routines to support Sound Blaster, Sound Blaster Pro,
+ Sound Blaster 16, and compatible sound cards.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#include <dos.h>
+#include <conio.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "dpmi.h"
+#include "dma.h"
+#include "irq.h"
+#include "blaster.h"
+#include "_blaster.h"
+
+#define USESTACK
+
+const int BLASTER_Interrupts[ BLASTER_MaxIrq + 1 ] =
+ {
+ INVALID, INVALID, 0xa, 0xb,
+ INVALID, 0xd, INVALID, 0xf,
+ INVALID, INVALID, 0x72, 0x73,
+ 0x74, INVALID, INVALID, 0x77
+ };
+
+const int BLASTER_SampleSize[ BLASTER_MaxMixMode + 1 ] =
+ {
+ MONO_8BIT_SAMPLE_SIZE, STEREO_8BIT_SAMPLE_SIZE,
+ MONO_16BIT_SAMPLE_SIZE, STEREO_16BIT_SAMPLE_SIZE
+ };
+
+const CARD_CAPABILITY BLASTER_CardConfig[ BLASTER_MaxCardType + 1 ] =
+ {
+ { FALSE, INVALID, INVALID, INVALID, INVALID }, // Unsupported
+ { TRUE, NO, MONO_8BIT, 4000, 23000 }, // SB 1.0
+ { TRUE, YES, STEREO_8BIT, 4000, 44100 }, // SBPro
+ { TRUE, NO, MONO_8BIT, 4000, 23000 }, // SB 2.xx
+ { TRUE, YES, STEREO_8BIT, 4000, 44100 }, // SBPro 2
+ { FALSE, INVALID, INVALID, INVALID, INVALID }, // Unsupported
+ { TRUE, YES, STEREO_16BIT, 5000, 44100 }, // SB16
+ };
+
+CARD_CAPABILITY BLASTER_Card;
+
+static void ( __interrupt __far *BLASTER_OldInt )( void );
+
+BLASTER_CONFIG BLASTER_Config =
+ {
+ UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED
+ };
+
+static int BLASTER_Installed = FALSE;
+
+int BLASTER_Version;
+
+static char *BLASTER_DMABuffer;
+static char *BLASTER_DMABufferEnd;
+static char *BLASTER_CurrentDMABuffer;
+static int BLASTER_TotalDMABufferSize;
+
+static int BLASTER_TransferLength = 0;
+static int BLASTER_MixMode = BLASTER_DefaultMixMode;
+static int BLASTER_SamplePacketSize = MONO_16BIT_SAMPLE_SIZE;
+static unsigned BLASTER_SampleRate = BLASTER_DefaultSampleRate;
+
+static unsigned BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
+
+volatile int BLASTER_SoundPlaying;
+volatile int BLASTER_SoundRecording;
+
+void ( *BLASTER_CallBack )( void );
+
+static int BLASTER_IntController1Mask;
+static int BLASTER_IntController2Mask;
+
+static int BLASTER_MixerAddress = UNDEFINED;
+static int BLASTER_MixerType = 0;
+static int BLASTER_OriginalMidiVolumeLeft = 255;
+static int BLASTER_OriginalMidiVolumeRight = 255;
+static int BLASTER_OriginalVoiceVolumeLeft = 255;
+static int BLASTER_OriginalVoiceVolumeRight = 255;
+
+static int BLASTER_WaveBlasterState = 0x0F;
+
+// adequate stack size
+#define kStackSize 2048
+
+static unsigned short StackSelector = NULL;
+static unsigned long StackPointer;
+
+static unsigned short oldStackSelector;
+static unsigned long oldStackPointer;
+
+// This is defined because we can't create local variables in a
+// function that switches stacks.
+static int GlobalStatus;
+
+// These declarations are necessary to use the inline assembly pragmas.
+
+extern void GetStack(unsigned short *selptr,unsigned long *stackptr);
+extern void SetStack(unsigned short selector,unsigned long stackptr);
+
+// This function will get the current stack selector and pointer and save
+// them off.
+#pragma aux GetStack = \
+ "mov [edi],esp" \
+ "mov ax,ss" \
+ "mov [esi],ax" \
+ parm [esi] [edi] \
+ modify [eax esi edi];
+
+// This function will set the stack selector and pointer to the specified
+// values.
+#pragma aux SetStack = \
+ "mov ss,ax" \
+ "mov esp,edx" \
+ parm [ax] [edx] \
+ modify [eax edx];
+
+int BLASTER_DMAChannel;
+
+int BLASTER_ErrorCode = BLASTER_Ok;
+
+#define BLASTER_SetErrorCode( status ) \
+ BLASTER_ErrorCode = ( status );
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_ErrorString
+
+ Returns a pointer to the error message associated with an error
+ number. A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *BLASTER_ErrorString
+ (
+ int ErrorNumber
+ )
+
+ {
+ char *ErrorString;
+
+ switch( ErrorNumber )
+ {
+ case BLASTER_Warning :
+ case BLASTER_Error :
+ ErrorString = BLASTER_ErrorString( BLASTER_ErrorCode );
+ break;
+
+ case BLASTER_Ok :
+ ErrorString = "Sound Blaster ok.";
+ break;
+
+ case BLASTER_EnvNotFound :
+ ErrorString = "BLASTER environment variable not set.";
+ break;
+
+ case BLASTER_AddrNotSet :
+ ErrorString = "Sound Blaster address not set.";
+ break;
+
+ case BLASTER_DMANotSet :
+ ErrorString = "Sound Blaster 8-bit DMA channel not set.";
+ break;
+
+ case BLASTER_DMA16NotSet :
+ ErrorString = "Sound Blaster 16-bit DMA channel not set.";
+ break;
+
+ case BLASTER_InvalidParameter :
+ ErrorString = "Invalid parameter in BLASTER environment variable.";
+ break;
+
+ case BLASTER_CardNotReady :
+ ErrorString = "Sound Blaster not responding on selected port.";
+ break;
+
+ case BLASTER_NoSoundPlaying :
+ ErrorString = "No sound playing on Sound Blaster.";
+ break;
+
+ case BLASTER_InvalidIrq :
+ ErrorString = "Invalid Sound Blaster Irq.";
+ break;
+
+ case BLASTER_UnableToSetIrq :
+ ErrorString = "Unable to set Sound Blaster IRQ. Try selecting an IRQ of 7 or below.";
+ break;
+
+ case BLASTER_DmaError :
+ ErrorString = DMA_ErrorString( DMA_Error );
+ break;
+
+ case BLASTER_NoMixer :
+ ErrorString = "Mixer not available on selected Sound Blaster card.";
+ break;
+
+ case BLASTER_DPMI_Error :
+ ErrorString = "DPMI Error in Blaster.";
+ break;
+
+ case BLASTER_OutOfMemory :
+ ErrorString = "Out of conventional memory in Blaster.";
+ break;
+
+ default :
+ ErrorString = "Unknown Sound Blaster error code.";
+ break;
+ }
+
+ return( ErrorString );
+ }
+
+
+/**********************************************************************
+
+ Memory locked functions:
+
+**********************************************************************/
+
+
+#define BLASTER_LockStart BLASTER_EnableInterrupt
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_EnableInterrupt
+
+ Enables the triggering of the sound card interrupt.
+---------------------------------------------------------------------*/
+
+void BLASTER_EnableInterrupt
+ (
+ void
+ )
+
+ {
+ int Irq;
+ int mask;
+
+ // Unmask system interrupt
+ Irq = BLASTER_Config.Interrupt;
+ if ( Irq < 8 )
+ {
+ mask = inp( 0x21 ) & ~( 1 << Irq );
+ outp( 0x21, mask );
+ }
+ else
+ {
+ mask = inp( 0xA1 ) & ~( 1 << ( Irq - 8 ) );
+ outp( 0xA1, mask );
+
+ mask = inp( 0x21 ) & ~( 1 << 2 );
+ outp( 0x21, mask );
+ }
+
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_DisableInterrupt
+
+ Disables the triggering of the sound card interrupt.
+---------------------------------------------------------------------*/
+
+void BLASTER_DisableInterrupt
+ (
+ void
+ )
+
+ {
+ int Irq;
+ int mask;
+
+ // Restore interrupt mask
+ Irq = BLASTER_Config.Interrupt;
+ if ( Irq < 8 )
+ {
+ mask = inp( 0x21 ) & ~( 1 << Irq );
+ mask |= BLASTER_IntController1Mask & ( 1 << Irq );
+ outp( 0x21, mask );
+ }
+ else
+ {
+ mask = inp( 0x21 ) & ~( 1 << 2 );
+ mask |= BLASTER_IntController1Mask & ( 1 << 2 );
+ outp( 0x21, mask );
+
+ mask = inp( 0xA1 ) & ~( 1 << ( Irq - 8 ) );
+ mask |= BLASTER_IntController2Mask & ( 1 << ( Irq - 8 ) );
+ outp( 0xA1, mask );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_ServiceInterrupt
+
+ Handles interrupt generated by sound card at the end of a voice
+ transfer. Calls the user supplied callback function.
+---------------------------------------------------------------------*/
+
+void __interrupt __far BLASTER_ServiceInterrupt
+ (
+ void
+ )
+
+ {
+ #ifdef USESTACK
+ // save stack
+ GetStack( &oldStackSelector, &oldStackPointer );
+
+ // set our stack
+ SetStack( StackSelector, StackPointer );
+ #endif
+
+ // Acknowledge interrupt
+ // Check if this is this an SB16 or newer
+ if ( BLASTER_Version >= DSP_Version4xx )
+ {
+ outp( BLASTER_Config.Address + BLASTER_MixerAddressPort,
+ MIXER_DSP4xxISR_Ack );
+
+ GlobalStatus = inp( BLASTER_Config.Address + BLASTER_MixerDataPort );
+
+ // Check if a 16-bit DMA interrupt occurred
+ if ( GlobalStatus & MIXER_16BITDMA_INT )
+ {
+ // Acknowledge 16-bit transfer interrupt
+ inp( BLASTER_Config.Address + BLASTER_16BitDMAAck );
+ }
+ else if ( GlobalStatus & MIXER_8BITDMA_INT )
+ {
+ inp( BLASTER_Config.Address + BLASTER_DataAvailablePort );
+ }
+ else
+ {
+ #ifdef USESTACK
+ // restore stack
+ SetStack( oldStackSelector, oldStackPointer );
+ #endif
+
+ // Wasn't our interrupt. Call the old one.
+ _chain_intr( BLASTER_OldInt );
+ }
+ }
+ else
+ {
+ // Older card - can't detect if an interrupt occurred.
+ inp( BLASTER_Config.Address + BLASTER_DataAvailablePort );
+ }
+
+ // Keep track of current buffer
+ BLASTER_CurrentDMABuffer += BLASTER_TransferLength;
+
+ if ( BLASTER_CurrentDMABuffer >= BLASTER_DMABufferEnd )
+ {
+ BLASTER_CurrentDMABuffer = BLASTER_DMABuffer;
+ }
+
+ // Continue playback on cards without autoinit mode
+ if ( BLASTER_Version < DSP_Version2xx )
+ {
+ if ( BLASTER_SoundPlaying )
+ {
+ BLASTER_DSP1xx_BeginPlayback( BLASTER_TransferLength );
+ }
+
+ if ( BLASTER_SoundRecording )
+ {
+ BLASTER_DSP1xx_BeginRecord( BLASTER_TransferLength );
+ }
+ }
+
+ // Call the caller's callback function
+ if ( BLASTER_CallBack != NULL )
+ {
+ BLASTER_CallBack();
+ }
+
+ #ifdef USESTACK
+ // restore stack
+ SetStack( oldStackSelector, oldStackPointer );
+ #endif
+
+ // send EOI to Interrupt Controller
+ if ( BLASTER_Config.Interrupt > 7 )
+ {
+ outp( 0xA0, 0x20 );
+ }
+
+ outp( 0x20, 0x20 );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_WriteDSP
+
+ Writes a byte of data to the sound card's DSP.
+---------------------------------------------------------------------*/
+
+int BLASTER_WriteDSP
+ (
+ unsigned data
+ )
+
+ {
+ int port;
+ unsigned count;
+ int status;
+
+ port = BLASTER_Config.Address + BLASTER_WritePort;
+
+ status = BLASTER_Error;
+
+ count = 0xFFFF;
+
+ do
+ {
+ if ( ( inp( port ) & 0x80 ) == 0 )
+ {
+ outp( port, data );
+ status = BLASTER_Ok;
+ break;
+ }
+
+ count--;
+ }
+ while( count > 0 );
+
+ if ( status != BLASTER_Ok )
+ {
+ BLASTER_SetErrorCode( BLASTER_CardNotReady );
+ }
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_ReadDSP
+
+ Reads a byte of data from the sound card's DSP.
+---------------------------------------------------------------------*/
+
+int BLASTER_ReadDSP
+ (
+ void
+ )
+
+ {
+ int port;
+ unsigned count;
+ int status;
+
+ port = BLASTER_Config.Address + BLASTER_DataAvailablePort;
+
+ status = BLASTER_Error;
+
+ count = 0xFFFF;
+
+ do
+ {
+ if ( inp( port ) & 0x80 )
+ {
+ status = inp( BLASTER_Config.Address + BLASTER_ReadPort );
+ break;
+ }
+
+ count--;
+ }
+ while( count > 0 );
+
+ if ( status == BLASTER_Error )
+ {
+ BLASTER_SetErrorCode( BLASTER_CardNotReady );
+ }
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_ResetDSP
+
+ Sends a reset command to the sound card's Digital Signal Processor
+ (DSP), causing it to perform an initialization.
+---------------------------------------------------------------------*/
+
+int BLASTER_ResetDSP
+ (
+ void
+ )
+
+ {
+ volatile int count;
+ int port;
+ int status;
+
+ port = BLASTER_Config.Address + BLASTER_ResetPort;
+
+ status = BLASTER_CardNotReady;
+
+ outp( port, 1 );
+
+/* What the hell am I doing here?
+ count = 100;
+
+ do
+ {
+ if ( inp( port ) == 255 )
+ {
+ break;
+ }
+
+ count--;
+ }
+ while( count > 0 );
+*/
+
+ count = 0x100;
+ do
+ {
+ count--;
+ }
+ while( count > 0 );
+
+ outp( port, 0 );
+
+ count = 100;
+
+ do
+ {
+ if ( BLASTER_ReadDSP() == BLASTER_Ready )
+ {
+ status = BLASTER_Ok;
+ break;
+ }
+
+ count--;
+ }
+ while( count > 0 );
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_GetDSPVersion
+
+ Returns the version number of the sound card's DSP.
+---------------------------------------------------------------------*/
+
+int BLASTER_GetDSPVersion
+ (
+ void
+ )
+
+ {
+ int MajorVersion;
+ int MinorVersion;
+ int version;
+
+ BLASTER_WriteDSP( DSP_GetVersion );
+
+ MajorVersion = BLASTER_ReadDSP();
+ MinorVersion = BLASTER_ReadDSP();
+
+ if ( ( MajorVersion == BLASTER_Error ) ||
+ ( MinorVersion == BLASTER_Error ) )
+ {
+ BLASTER_SetErrorCode( BLASTER_CardNotReady );
+ return( BLASTER_Error );
+ }
+
+ version = ( MajorVersion << 8 ) + MinorVersion;
+
+ if ( version >= DSP_Version4xx )
+ {
+ BLASTER_Card.IsSupported = TRUE;
+ BLASTER_Card.HasMixer = YES;
+ BLASTER_Card.MaxMixMode = STEREO_16BIT;
+ BLASTER_Card.MinSamplingRate = 5000;
+ BLASTER_Card.MaxSamplingRate = 44100;
+ BLASTER_MixerType = SB16;
+ }
+ else if ( version >= DSP_Version3xx )
+ {
+ BLASTER_Card.IsSupported = TRUE;
+ BLASTER_Card.HasMixer = YES;
+ BLASTER_Card.MaxMixMode = STEREO_8BIT;
+ BLASTER_Card.MinSamplingRate = 4000;
+ BLASTER_Card.MaxSamplingRate = 44100;
+ BLASTER_MixerType = SBPro;
+ }
+ else if ( version >= DSP_Version2xx )
+ {
+ BLASTER_Card.IsSupported = TRUE;
+ BLASTER_Card.HasMixer = NO;
+ BLASTER_Card.MaxMixMode = MONO_8BIT;
+ BLASTER_Card.MinSamplingRate = 4000;
+ BLASTER_Card.MaxSamplingRate = 23000;
+ BLASTER_MixerType = 0;
+ }
+ else
+ {
+ // DSP_Version1xx
+ BLASTER_Card.IsSupported = TRUE;
+ BLASTER_Card.HasMixer = NO;
+ BLASTER_Card.MaxMixMode = MONO_8BIT;
+ BLASTER_Card.MinSamplingRate = 4000;
+ BLASTER_Card.MaxSamplingRate = 23000;
+ BLASTER_MixerType = 0;
+ }
+
+ return( version );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_SpeakerOn
+
+ Enables output from the DAC.
+---------------------------------------------------------------------*/
+
+void BLASTER_SpeakerOn
+ (
+ void
+ )
+
+ {
+ BLASTER_WriteDSP( DSP_SpeakerOn );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_SpeakerOff
+
+ Disables output from the DAC.
+---------------------------------------------------------------------*/
+
+void BLASTER_SpeakerOff
+ (
+ void
+ )
+
+ {
+ BLASTER_WriteDSP( DSP_SpeakerOff );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_SetPlaybackRate
+
+ Sets the rate at which the digitized sound will be played in
+ hertz.
+---------------------------------------------------------------------*/
+
+void BLASTER_SetPlaybackRate
+ (
+ unsigned rate
+ )
+
+ {
+ int LoByte;
+ int HiByte;
+
+ if ( BLASTER_Version < DSP_Version4xx )
+ {
+ int timeconstant;
+ long ActualRate;
+
+ // Send sampling rate as time constant for older Sound
+ // Blaster compatible cards.
+
+ ActualRate = rate * BLASTER_SamplePacketSize;
+ if ( ActualRate < BLASTER_Card.MinSamplingRate )
+ {
+ rate = BLASTER_Card.MinSamplingRate / BLASTER_SamplePacketSize;
+ }
+
+ if ( ActualRate > BLASTER_Card.MaxSamplingRate )
+ {
+ rate = BLASTER_Card.MaxSamplingRate / BLASTER_SamplePacketSize;
+ }
+
+ timeconstant = ( int )CalcTimeConstant( rate, BLASTER_SamplePacketSize );
+
+ // Keep track of what the actual rate is
+ BLASTER_SampleRate = ( unsigned )CalcSamplingRate( timeconstant );
+ BLASTER_SampleRate /= BLASTER_SamplePacketSize;
+
+ BLASTER_WriteDSP( DSP_SetTimeConstant );
+ BLASTER_WriteDSP( timeconstant );
+ }
+ else
+ {
+ // Send literal sampling rate for cards with DSP version
+ // 4.xx (Sound Blaster 16)
+
+ BLASTER_SampleRate = rate;
+
+ if ( BLASTER_SampleRate < BLASTER_Card.MinSamplingRate )
+ {
+ BLASTER_SampleRate = BLASTER_Card.MinSamplingRate;
+ }
+
+ if ( BLASTER_SampleRate > BLASTER_Card.MaxSamplingRate )
+ {
+ BLASTER_SampleRate = BLASTER_Card.MaxSamplingRate;
+ }
+
+ HiByte = hibyte( BLASTER_SampleRate );
+ LoByte = lobyte( BLASTER_SampleRate );
+
+ // Set playback rate
+ BLASTER_WriteDSP( DSP_Set_DA_Rate );
+ BLASTER_WriteDSP( HiByte );
+ BLASTER_WriteDSP( LoByte );
+
+ // Set recording rate
+ BLASTER_WriteDSP( DSP_Set_AD_Rate );
+ BLASTER_WriteDSP( HiByte );
+ BLASTER_WriteDSP( LoByte );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_GetPlaybackRate
+
+ Returns the rate at which the digitized sound will be played in
+ hertz.
+---------------------------------------------------------------------*/
+
+unsigned BLASTER_GetPlaybackRate
+ (
+ void
+ )
+
+ {
+ return( BLASTER_SampleRate );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_SetMixMode
+
+ Sets the sound card to play samples in mono or stereo.
+---------------------------------------------------------------------*/
+
+int BLASTER_SetMixMode
+ (
+ int mode
+ )
+
+ {
+ int port;
+ int data;
+ int CardType;
+
+ CardType = BLASTER_Config.Type;
+
+ mode &= BLASTER_MaxMixMode;
+
+ if ( !( BLASTER_Card.MaxMixMode & STEREO ) )
+ {
+ mode &= ~STEREO;
+ }
+
+ if ( !( BLASTER_Card.MaxMixMode & SIXTEEN_BIT ) )
+ {
+ mode &= ~SIXTEEN_BIT;
+ }
+
+ BLASTER_MixMode = mode;
+ BLASTER_SamplePacketSize = BLASTER_SampleSize[ mode ];
+
+ // For the Sound Blaster Pro, we have to set the mixer chip
+ // to play mono or stereo samples.
+
+ if ( ( CardType == SBPro ) || ( CardType == SBPro2 ) )
+ {
+ port = BLASTER_Config.Address + BLASTER_MixerAddressPort;
+ outp( port, MIXER_SBProOutputSetting );
+
+ port = BLASTER_Config.Address + BLASTER_MixerDataPort;
+
+ // Get current mode
+ data = inp( port );
+
+ // set stereo mode bit
+ if ( mode & STEREO )
+ {
+ data |= MIXER_SBProStereoFlag;
+ }
+ else
+ {
+ data &= ~MIXER_SBProStereoFlag;
+ }
+
+ // set the mode
+ outp( port, data );
+
+ BLASTER_SetPlaybackRate( BLASTER_SampleRate );
+ }
+
+ return( mode );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_StopPlayback
+
+ Ends the DMA transfer of digitized sound to the sound card.
+---------------------------------------------------------------------*/
+
+void BLASTER_StopPlayback
+ (
+ void
+ )
+
+ {
+ int DmaChannel;
+
+ // Don't allow anymore interrupts
+ BLASTER_DisableInterrupt();
+
+ if ( BLASTER_HaltTransferCommand == DSP_Reset )
+ {
+ BLASTER_ResetDSP();
+ }
+ else
+ {
+ BLASTER_WriteDSP( BLASTER_HaltTransferCommand );
+ }
+
+ // Disable the DMA channel
+ if ( BLASTER_MixMode & SIXTEEN_BIT )
+ {
+ DmaChannel = BLASTER_Config.Dma16;
+ }
+ else
+ {
+ DmaChannel = BLASTER_Config.Dma8;
+ }
+ DMA_EndTransfer( DmaChannel );
+
+ // Turn off speaker
+ BLASTER_SpeakerOff();
+
+ BLASTER_SoundPlaying = FALSE;
+ BLASTER_SoundRecording = FALSE;
+
+ BLASTER_DMABuffer = NULL;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_SetupDMABuffer
+
+ Programs the DMAC for sound transfer.
+---------------------------------------------------------------------*/
+
+int BLASTER_SetupDMABuffer
+ (
+ char *BufferPtr,
+ int BufferSize,
+ int mode
+ )
+
+ {
+ int DmaChannel;
+ int DmaStatus;
+ int errorcode;
+
+ if ( BLASTER_MixMode & SIXTEEN_BIT )
+ {
+ DmaChannel = BLASTER_Config.Dma16;
+ errorcode = BLASTER_DMA16NotSet;
+ }
+ else
+ {
+ DmaChannel = BLASTER_Config.Dma8;
+ errorcode = BLASTER_DMANotSet;
+ }
+
+ if ( DmaChannel == UNDEFINED )
+ {
+ BLASTER_SetErrorCode( errorcode );
+ return( BLASTER_Error );
+ }
+
+ DmaStatus = DMA_SetupTransfer( DmaChannel, BufferPtr, BufferSize, mode );
+ if ( DmaStatus == DMA_Error )
+ {
+ BLASTER_SetErrorCode( BLASTER_DmaError );
+ return( BLASTER_Error );
+ }
+
+ BLASTER_DMAChannel = DmaChannel;
+
+ BLASTER_DMABuffer = BufferPtr;
+ BLASTER_CurrentDMABuffer = BufferPtr;
+ BLASTER_TotalDMABufferSize = BufferSize;
+ BLASTER_DMABufferEnd = BufferPtr + BufferSize;
+
+ return( BLASTER_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_GetCurrentPos
+
+ Returns the offset within the current sound being played.
+---------------------------------------------------------------------*/
+
+int BLASTER_GetCurrentPos
+ (
+ void
+ )
+
+ {
+ char *CurrentAddr;
+ int DmaChannel;
+ int offset;
+
+ if ( !BLASTER_SoundPlaying )
+ {
+ BLASTER_SetErrorCode( BLASTER_NoSoundPlaying );
+ return( BLASTER_Error );
+ }
+
+ if ( BLASTER_MixMode & SIXTEEN_BIT )
+ {
+ DmaChannel = BLASTER_Config.Dma16;
+ }
+ else
+ {
+ DmaChannel = BLASTER_Config.Dma8;
+ }
+
+ if ( DmaChannel == UNDEFINED )
+ {
+ BLASTER_SetErrorCode( BLASTER_DMANotSet );
+ return( BLASTER_Error );
+ }
+
+ CurrentAddr = DMA_GetCurrentPos( DmaChannel );
+
+ offset = ( int )( ( ( unsigned long )CurrentAddr ) -
+ ( ( unsigned long )BLASTER_CurrentDMABuffer ) );
+
+ if ( BLASTER_MixMode & SIXTEEN_BIT )
+ {
+ offset >>= 1;
+ }
+
+ if ( BLASTER_MixMode & STEREO )
+ {
+ offset >>= 1;
+ }
+
+ return( offset );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_DSP1xx_BeginPlayback
+
+ Starts playback of digitized sound on cards compatible with DSP
+ version 1.xx.
+---------------------------------------------------------------------*/
+
+int BLASTER_DSP1xx_BeginPlayback
+ (
+ int length
+ )
+
+ {
+ int SampleLength;
+ int LoByte;
+ int HiByte;
+
+ SampleLength = length - 1;
+ HiByte = hibyte( SampleLength );
+ LoByte = lobyte( SampleLength );
+
+ // Program DSP to play sound
+ BLASTER_WriteDSP( DSP_Old8BitDAC );
+ BLASTER_WriteDSP( LoByte );
+ BLASTER_WriteDSP( HiByte );
+
+ BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
+
+ BLASTER_SoundPlaying = TRUE;
+
+ return( BLASTER_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_DSP2xx_BeginPlayback
+
+ Starts playback of digitized sound on cards compatible with DSP
+ version 2.xx.
+---------------------------------------------------------------------*/
+
+int BLASTER_DSP2xx_BeginPlayback
+ (
+ int length
+ )
+
+ {
+ int SampleLength;
+ int LoByte;
+ int HiByte;
+
+ SampleLength = length - 1;
+ HiByte = hibyte( SampleLength );
+ LoByte = lobyte( SampleLength );
+
+ BLASTER_WriteDSP( DSP_SetBlockLength );
+ BLASTER_WriteDSP( LoByte );
+ BLASTER_WriteDSP( HiByte );
+
+ if ( ( BLASTER_Version >= DSP_Version201 ) && ( DSP_MaxNormalRate <
+ ( BLASTER_SampleRate * BLASTER_SamplePacketSize ) ) )
+ {
+ BLASTER_WriteDSP( DSP_8BitHighSpeedAutoInitMode );
+ BLASTER_HaltTransferCommand = DSP_Reset;
+ }
+ else
+ {
+ BLASTER_WriteDSP( DSP_8BitAutoInitMode );
+ BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
+ }
+
+ BLASTER_SoundPlaying = TRUE;
+
+ return( BLASTER_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_DSP4xx_BeginPlayback
+
+ Starts playback of digitized sound on cards compatible with DSP
+ version 4.xx, such as the Sound Blaster 16.
+---------------------------------------------------------------------*/
+
+int BLASTER_DSP4xx_BeginPlayback
+ (
+ int length
+ )
+
+ {
+ int TransferCommand;
+ int TransferMode;
+ int SampleLength;
+ int LoByte;
+ int HiByte;
+
+ if ( BLASTER_MixMode & SIXTEEN_BIT )
+ {
+ TransferCommand = DSP_16BitDAC;
+ SampleLength = ( length / 2 ) - 1;
+ BLASTER_HaltTransferCommand = DSP_Halt16bitTransfer;
+ if ( BLASTER_MixMode & STEREO )
+ {
+ TransferMode = DSP_SignedStereoData;
+ }
+ else
+ {
+ TransferMode = DSP_SignedMonoData;
+ }
+ }
+ else
+ {
+ TransferCommand = DSP_8BitDAC;
+ SampleLength = length - 1;
+ BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
+ if ( BLASTER_MixMode & STEREO )
+ {
+ TransferMode = DSP_UnsignedStereoData;
+ }
+ else
+ {
+ TransferMode = DSP_UnsignedMonoData;
+ }
+ }
+
+ HiByte = hibyte( SampleLength );
+ LoByte = lobyte( SampleLength );
+
+ // Program DSP to play sound
+ BLASTER_WriteDSP( TransferCommand );
+ BLASTER_WriteDSP( TransferMode );
+ BLASTER_WriteDSP( LoByte );
+ BLASTER_WriteDSP( HiByte );
+
+ BLASTER_SoundPlaying = TRUE;
+
+ return( BLASTER_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_BeginBufferedPlayback
+
+ Begins multibuffered playback of digitized sound on the sound card.
+---------------------------------------------------------------------*/
+
+int BLASTER_BeginBufferedPlayback
+ (
+ char *BufferStart,
+ int BufferSize,
+ int NumDivisions,
+ unsigned SampleRate,
+ int MixMode,
+ void ( *CallBackFunc )( void )
+ )
+
+ {
+ int DmaStatus;
+ int TransferLength;
+
+//JIM
+// if ( BLASTER_SoundPlaying || BLASTER_SoundRecording )
+ {
+ BLASTER_StopPlayback();
+ }
+
+ BLASTER_SetMixMode( MixMode );
+
+ DmaStatus = BLASTER_SetupDMABuffer( BufferStart, BufferSize, DMA_AutoInitRead );
+ if ( DmaStatus == BLASTER_Error )
+ {
+ return( BLASTER_Error );
+ }
+
+ BLASTER_SetPlaybackRate( SampleRate );
+
+ BLASTER_SetCallBack( CallBackFunc );
+
+ BLASTER_EnableInterrupt();
+
+ // Turn on speaker
+ BLASTER_SpeakerOn();
+
+ TransferLength = BufferSize / NumDivisions;
+ BLASTER_TransferLength = TransferLength;
+
+ // Program the sound card to start the transfer.
+ if ( BLASTER_Version < DSP_Version2xx )
+ {
+ BLASTER_DSP1xx_BeginPlayback( TransferLength );
+ }
+ else if ( BLASTER_Version < DSP_Version4xx )
+ {
+ BLASTER_DSP2xx_BeginPlayback( TransferLength );
+ }
+ else
+ {
+ BLASTER_DSP4xx_BeginPlayback( TransferLength );
+ }
+
+ return( BLASTER_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_DSP4xx_BeginRecord
+
+ Starts recording of digitized sound on cards compatible with DSP
+ version 4.xx, such as the Sound Blaster 16.
+---------------------------------------------------------------------*/
+
+int BLASTER_DSP4xx_BeginRecord
+ (
+ int length
+ )
+
+ {
+ int TransferCommand;
+ int TransferMode;
+ int SampleLength;
+ int LoByte;
+ int HiByte;
+
+ TransferCommand = DSP_8BitADC;
+ SampleLength = length - 1;
+ BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
+
+ TransferMode = DSP_UnsignedMonoData;
+
+ HiByte = hibyte( SampleLength );
+ LoByte = lobyte( SampleLength );
+
+ // Program DSP to play sound
+ BLASTER_WriteDSP( TransferCommand );
+ BLASTER_WriteDSP( TransferMode );
+ BLASTER_WriteDSP( LoByte );
+ BLASTER_WriteDSP( HiByte );
+
+ BLASTER_SoundRecording = TRUE;
+
+ return( BLASTER_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_DSP2xx_BeginRecord
+
+ Starts recording of digitized sound on cards compatible with DSP
+ version 2.xx.
+---------------------------------------------------------------------*/
+
+int BLASTER_DSP2xx_BeginRecord
+ (
+ int length
+ )
+
+ {
+ int SampleLength;
+ int LoByte;
+ int HiByte;
+
+ SampleLength = length - 1;
+ HiByte = hibyte( SampleLength );
+ LoByte = lobyte( SampleLength );
+
+ BLASTER_WriteDSP( DSP_SetBlockLength );
+ BLASTER_WriteDSP( LoByte );
+ BLASTER_WriteDSP( HiByte );
+
+ if ( ( BLASTER_Version >= DSP_Version201 ) && ( DSP_MaxNormalRate <
+ ( BLASTER_SampleRate * BLASTER_SamplePacketSize ) ) )
+ {
+ BLASTER_WriteDSP( DSP_8BitHighSpeedAutoInitRecord );
+ BLASTER_HaltTransferCommand = DSP_Reset;
+ }
+ else
+ {
+ BLASTER_WriteDSP( DSP_8BitAutoInitRecord );
+ BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
+ }
+
+ BLASTER_SoundRecording = TRUE;
+
+ return( BLASTER_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_DSP1xx_BeginRecord
+
+ Starts recording of digitized sound on cards compatible with DSP
+ version 1.xx.
+---------------------------------------------------------------------*/
+
+int BLASTER_DSP1xx_BeginRecord
+ (
+ int length
+ )
+
+ {
+ int SampleLength;
+ int LoByte;
+ int HiByte;
+
+ SampleLength = length - 1;
+ HiByte = hibyte( SampleLength );
+ LoByte = lobyte( SampleLength );
+
+ // Program DSP to play sound
+ BLASTER_WriteDSP( DSP_Old8BitADC );
+ BLASTER_WriteDSP( LoByte );
+ BLASTER_WriteDSP( HiByte );
+
+ BLASTER_HaltTransferCommand = DSP_Halt8bitTransfer;
+
+ BLASTER_SoundRecording = TRUE;
+
+ return( BLASTER_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_BeginBufferedRecord
+
+ Begins multibuffered recording of digitized sound on the sound card.
+---------------------------------------------------------------------*/
+
+int BLASTER_BeginBufferedRecord
+ (
+ char *BufferStart,
+ int BufferSize,
+ int NumDivisions,
+ unsigned SampleRate,
+ int MixMode,
+ void ( *CallBackFunc )( void )
+ )
+
+ {
+ int DmaStatus;
+ int TransferLength;
+
+//JIM
+// if ( BLASTER_SoundPlaying || BLASTER_SoundRecording )
+ {
+ BLASTER_StopPlayback();
+ }
+
+ BLASTER_SetMixMode( MixMode );
+
+ DmaStatus = BLASTER_SetupDMABuffer( BufferStart, BufferSize, DMA_AutoInitWrite );
+ if ( DmaStatus == BLASTER_Error )
+ {
+ return( BLASTER_Error );
+ }
+
+ BLASTER_SetPlaybackRate( SampleRate );
+
+ BLASTER_SetCallBack( CallBackFunc );
+
+ BLASTER_EnableInterrupt();
+
+ // Turn off speaker
+ BLASTER_SpeakerOff();
+
+ TransferLength = BufferSize / NumDivisions;
+ BLASTER_TransferLength = TransferLength;
+
+ // Program the sound card to start the transfer.
+ if ( BLASTER_Version < DSP_Version2xx )
+ {
+ BLASTER_DSP1xx_BeginRecord( TransferLength );
+ }
+ else if ( BLASTER_Version < DSP_Version4xx )
+ {
+ BLASTER_DSP2xx_BeginRecord( TransferLength );
+ }
+ else
+ {
+ BLASTER_DSP4xx_BeginRecord( TransferLength );
+ }
+
+ return( BLASTER_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_WriteMixer
+
+ Writes a byte of data to the Sound Blaster's mixer chip.
+---------------------------------------------------------------------*/
+
+void BLASTER_WriteMixer
+ (
+ int reg,
+ int data
+ )
+
+ {
+ outp( BLASTER_MixerAddress + BLASTER_MixerAddressPort, reg );
+ outp( BLASTER_MixerAddress + BLASTER_MixerDataPort, data );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_ReadMixer
+
+ Reads a byte of data from the Sound Blaster's mixer chip.
+---------------------------------------------------------------------*/
+
+int BLASTER_ReadMixer
+ (
+ int reg
+ )
+
+ {
+ int data;
+
+ outp( BLASTER_MixerAddress + BLASTER_MixerAddressPort, reg );
+ data = inp( BLASTER_MixerAddress + BLASTER_MixerDataPort );
+ return( data );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_GetVoiceVolume
+
+ Reads the average volume of the digitized sound channel from the
+ Sound Blaster's mixer chip.
+---------------------------------------------------------------------*/
+
+int BLASTER_GetVoiceVolume
+ (
+ void
+ )
+
+ {
+ int volume;
+ int left;
+ int right;
+
+ switch( BLASTER_MixerType )
+ {
+ case SBPro :
+ case SBPro2 :
+ left = BLASTER_ReadMixer( MIXER_SBProVoice );
+ right = ( left & 0x0f ) << 4;
+ left &= 0xf0;
+ volume = ( left + right ) / 2;
+ break;
+
+ case SB16 :
+ left = BLASTER_ReadMixer( MIXER_SB16VoiceLeft );
+ right = BLASTER_ReadMixer( MIXER_SB16VoiceRight );
+ volume = ( left + right ) / 2;
+ break;
+
+ default :
+ BLASTER_SetErrorCode( BLASTER_NoMixer );
+ volume = BLASTER_Error;
+ }
+
+ return( volume );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_SetVoiceVolume
+
+ Sets the volume of the digitized sound channel on the Sound
+ Blaster's mixer chip.
+---------------------------------------------------------------------*/
+
+int BLASTER_SetVoiceVolume
+ (
+ int volume
+ )
+
+ {
+ int data;
+ int status;
+
+ volume = min( 255, volume );
+ volume = max( 0, volume );
+
+ status = BLASTER_Ok;
+ switch( BLASTER_MixerType )
+ {
+ case SBPro :
+ case SBPro2 :
+ data = ( volume & 0xf0 ) + ( volume >> 4 );
+ BLASTER_WriteMixer( MIXER_SBProVoice, data );
+ break;
+
+ case SB16 :
+ BLASTER_WriteMixer( MIXER_SB16VoiceLeft, volume & 0xf8 );
+ BLASTER_WriteMixer( MIXER_SB16VoiceRight, volume & 0xf8 );
+ break;
+
+ default :
+ BLASTER_SetErrorCode( BLASTER_NoMixer );
+ status = BLASTER_Error;
+ }
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_GetMidiVolume
+
+ Reads the average volume of the Midi sound channel from the
+ Sound Blaster's mixer chip.
+---------------------------------------------------------------------*/
+
+int BLASTER_GetMidiVolume
+ (
+ void
+ )
+
+ {
+ int volume;
+ int left;
+ int right;
+
+ switch( BLASTER_MixerType )
+ {
+ case SBPro :
+ case SBPro2 :
+ left = BLASTER_ReadMixer( MIXER_SBProMidi );
+ right = ( left & 0x0f ) << 4;
+ left &= 0xf0;
+ volume = ( left + right ) / 2;
+ break;
+
+ case SB16 :
+ left = BLASTER_ReadMixer( MIXER_SB16MidiLeft );
+ right = BLASTER_ReadMixer( MIXER_SB16MidiRight );
+ volume = ( left + right ) / 2;
+ break;
+
+ default :
+ BLASTER_SetErrorCode( BLASTER_NoMixer );
+ volume = BLASTER_Error;
+ }
+
+ return( volume );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_SetMidiVolume
+
+ Sets the volume of the Midi sound channel on the Sound
+ Blaster's mixer chip.
+---------------------------------------------------------------------*/
+
+int BLASTER_SetMidiVolume
+ (
+ int volume
+ )
+
+ {
+ int data;
+ int status;
+
+ volume = min( 255, volume );
+ volume = max( 0, volume );
+
+ status = BLASTER_Ok;
+ switch( BLASTER_MixerType )
+ {
+ case SBPro :
+ case SBPro2 :
+ data = ( volume & 0xf0 ) + ( volume >> 4 );
+ BLASTER_WriteMixer( MIXER_SBProMidi, data );
+ break;
+
+ case SB16 :
+ BLASTER_WriteMixer( MIXER_SB16MidiLeft, volume & 0xf8 );
+ BLASTER_WriteMixer( MIXER_SB16MidiRight, volume & 0xf8 );
+ break;
+
+ default :
+ BLASTER_SetErrorCode( BLASTER_NoMixer );
+ status = BLASTER_Error;
+ }
+
+ return( status );
+ }
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_CardHasMixer
+
+ Checks if the selected Sound Blaster card has a mixer.
+---------------------------------------------------------------------*/
+
+int BLASTER_CardHasMixer
+ (
+ void
+ )
+
+ {
+ return( BLASTER_Card.HasMixer );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_SaveVoiceVolume
+
+ Saves the user's voice mixer settings.
+---------------------------------------------------------------------*/
+
+void BLASTER_SaveVoiceVolume
+ (
+ void
+ )
+
+ {
+ switch( BLASTER_MixerType )
+ {
+ case SBPro :
+ case SBPro2 :
+ BLASTER_OriginalVoiceVolumeLeft =
+ BLASTER_ReadMixer( MIXER_SBProVoice );
+ break;
+
+ case SB16 :
+ BLASTER_OriginalVoiceVolumeLeft =
+ BLASTER_ReadMixer( MIXER_SB16VoiceLeft );
+ BLASTER_OriginalVoiceVolumeRight =
+ BLASTER_ReadMixer( MIXER_SB16VoiceRight );
+ break;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_RestoreVoiceVolume
+
+ Restores the user's voice mixer settings.
+---------------------------------------------------------------------*/
+
+void BLASTER_RestoreVoiceVolume
+ (
+ void
+ )
+
+ {
+ switch( BLASTER_MixerType )
+ {
+ case SBPro :
+ case SBPro2 :
+ BLASTER_WriteMixer( MIXER_SBProVoice,
+ BLASTER_OriginalVoiceVolumeLeft );
+ break;
+
+ case SB16 :
+ BLASTER_WriteMixer( MIXER_SB16VoiceLeft,
+ BLASTER_OriginalVoiceVolumeLeft );
+ BLASTER_WriteMixer( MIXER_SB16VoiceRight,
+ BLASTER_OriginalVoiceVolumeRight );
+ break;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_SaveMidiVolume
+
+ Saves the user's FM mixer settings.
+---------------------------------------------------------------------*/
+
+void BLASTER_SaveMidiVolume
+ (
+ void
+ )
+
+ {
+ switch( BLASTER_MixerType )
+ {
+ case SBPro :
+ case SBPro2 :
+ BLASTER_OriginalMidiVolumeLeft =
+ BLASTER_ReadMixer( MIXER_SBProMidi );
+ break;
+
+ case SB16 :
+ BLASTER_OriginalMidiVolumeLeft =
+ BLASTER_ReadMixer( MIXER_SB16MidiLeft );
+ BLASTER_OriginalMidiVolumeRight =
+ BLASTER_ReadMixer( MIXER_SB16MidiRight );
+ break;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_RestoreMidiVolume
+
+ Restores the user's FM mixer settings.
+---------------------------------------------------------------------*/
+
+void BLASTER_RestoreMidiVolume
+ (
+ void
+ )
+
+ {
+ switch( BLASTER_MixerType )
+ {
+ case SBPro :
+ case SBPro2 :
+ BLASTER_WriteMixer( MIXER_SBProMidi,
+ BLASTER_OriginalMidiVolumeLeft );
+ break;
+
+ case SB16 :
+ BLASTER_WriteMixer( MIXER_SB16MidiLeft,
+ BLASTER_OriginalMidiVolumeLeft );
+ BLASTER_WriteMixer( MIXER_SB16MidiRight,
+ BLASTER_OriginalMidiVolumeRight );
+ break;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_GetEnv
+
+ Retrieves the BLASTER environment settings and returns them to
+ the caller.
+---------------------------------------------------------------------*/
+
+int BLASTER_GetEnv
+ (
+ BLASTER_CONFIG *Config
+ )
+
+ {
+ char *Blaster;
+ char parameter;
+
+ Config->Address = UNDEFINED;
+ Config->Type = UNDEFINED;
+ Config->Interrupt = UNDEFINED;
+ Config->Dma8 = UNDEFINED;
+ Config->Dma16 = UNDEFINED;
+ Config->Midi = UNDEFINED;
+ Config->Emu = UNDEFINED;
+
+ Blaster = getenv( "BLASTER" );
+ if ( Blaster == NULL )
+ {
+ BLASTER_SetErrorCode( BLASTER_EnvNotFound );
+ return( BLASTER_Error );
+ }
+
+ while( *Blaster != 0 )
+ {
+ if ( *Blaster == ' ' )
+ {
+ Blaster++;
+ continue;
+ }
+
+ parameter = toupper( *Blaster );
+ Blaster++;
+
+ if ( !isxdigit( *Blaster ) )
+ {
+ BLASTER_SetErrorCode( BLASTER_InvalidParameter );
+ return( BLASTER_Error );
+ }
+
+ switch( parameter )
+ {
+ case BlasterEnv_Address :
+ sscanf( Blaster, "%x", &Config->Address );
+ break;
+ case BlasterEnv_Interrupt :
+ sscanf( Blaster, "%d", &Config->Interrupt );
+ break;
+ case BlasterEnv_8bitDma :
+ sscanf( Blaster, "%d", &Config->Dma8 );
+ break;
+ case BlasterEnv_Type :
+ sscanf( Blaster, "%d", &Config->Type );
+ break;
+ case BlasterEnv_16bitDma :
+ sscanf( Blaster, "%d", &Config->Dma16 );
+ break;
+ case BlasterEnv_Midi :
+ sscanf( Blaster, "%x", &Config->Midi );
+ break;
+ case BlasterEnv_EmuAddress :
+ sscanf( Blaster, "%x", &Config->Emu );
+ break;
+ default :
+ // Skip the offending data
+ // sscanf( Blaster, "%*s" );
+ break;
+ }
+
+ while( isxdigit( *Blaster ) )
+ {
+ Blaster++;
+ }
+ }
+
+ return( BLASTER_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_SetCardSettings
+
+ Sets up the sound card's parameters.
+---------------------------------------------------------------------*/
+
+int BLASTER_SetCardSettings
+ (
+ BLASTER_CONFIG Config
+ )
+
+ {
+ if ( BLASTER_Installed )
+ {
+ BLASTER_Shutdown();
+ }
+
+ BLASTER_Config.Address = Config.Address;
+ BLASTER_Config.Type = Config.Type;
+ BLASTER_Config.Interrupt = Config.Interrupt;
+ BLASTER_Config.Dma8 = Config.Dma8;
+ BLASTER_Config.Dma16 = Config.Dma16;
+ BLASTER_Config.Midi = Config.Midi;
+ BLASTER_Config.Emu = Config.Emu;
+ BLASTER_MixerAddress = Config.Address;
+ BLASTER_MixerType = Config.Type;
+
+ if ( BLASTER_Config.Emu == UNDEFINED )
+ {
+ BLASTER_Config.Emu = BLASTER_Config.Address + 0x400;
+ }
+
+ return( BLASTER_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_GetCardSettings
+
+ Sets up the sound card's parameters.
+---------------------------------------------------------------------*/
+
+int BLASTER_GetCardSettings
+ (
+ BLASTER_CONFIG *Config
+ )
+
+ {
+ if ( BLASTER_Config.Address == UNDEFINED )
+ {
+ return( BLASTER_Warning );
+ }
+ else
+ {
+ Config->Address = BLASTER_Config.Address;
+ Config->Type = BLASTER_Config.Type;
+ Config->Interrupt = BLASTER_Config.Interrupt;
+ Config->Dma8 = BLASTER_Config.Dma8;
+ Config->Dma16 = BLASTER_Config.Dma16;
+ Config->Midi = BLASTER_Config.Midi;
+ Config->Emu = BLASTER_Config.Emu;
+ }
+
+ return( BLASTER_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_GetCardInfo
+
+ Returns the maximum number of bits that can represent a sample
+ (8 or 16) and the number of channels (1 for mono, 2 for stereo).
+---------------------------------------------------------------------*/
+
+int BLASTER_GetCardInfo
+ (
+ int *MaxSampleBits,
+ int *MaxChannels
+ )
+
+ {
+ if ( BLASTER_Card.MaxMixMode & STEREO )
+ {
+ *MaxChannels = 2;
+ }
+ else
+ {
+ *MaxChannels = 1;
+ }
+
+ if ( BLASTER_Card.MaxMixMode & SIXTEEN_BIT )
+ {
+ *MaxSampleBits = 16;
+ }
+ else
+ {
+ *MaxSampleBits = 8;
+ }
+
+ return( BLASTER_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_SetCallBack
+
+ Specifies the user function to call at the end of a sound transfer.
+---------------------------------------------------------------------*/
+
+void BLASTER_SetCallBack
+ (
+ void ( *func )( void )
+ )
+
+ {
+ BLASTER_CallBack = func;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_LockEnd
+
+ Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void BLASTER_LockEnd
+ (
+ void
+ )
+
+ {
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_UnlockMemory
+
+ Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+void BLASTER_UnlockMemory
+ (
+ void
+ )
+
+ {
+ DPMI_UnlockMemoryRegion( BLASTER_LockStart, BLASTER_LockEnd );
+ DPMI_UnlockMemory( ( void * )&BLASTER_Interrupts[ 0 ],
+ sizeof( BLASTER_Interrupts ) );
+ DPMI_UnlockMemory( ( void * )&BLASTER_SampleSize[ 0 ],
+ sizeof( BLASTER_SampleSize ) );
+ DPMI_Unlock( BLASTER_Card );
+ DPMI_Unlock( BLASTER_OldInt );
+ DPMI_Unlock( BLASTER_Config );
+ DPMI_Unlock( BLASTER_Installed );
+ DPMI_Unlock( BLASTER_Version );
+ DPMI_Unlock( BLASTER_DMABuffer );
+ DPMI_Unlock( BLASTER_DMABufferEnd );
+ DPMI_Unlock( BLASTER_CurrentDMABuffer );
+ DPMI_Unlock( BLASTER_TotalDMABufferSize );
+ DPMI_Unlock( BLASTER_TransferLength );
+ DPMI_Unlock( BLASTER_MixMode );
+ DPMI_Unlock( BLASTER_SamplePacketSize );
+ DPMI_Unlock( BLASTER_SampleRate );
+ DPMI_Unlock( BLASTER_HaltTransferCommand );
+ DPMI_Unlock( ( int )BLASTER_SoundPlaying );
+ DPMI_Unlock( ( int )BLASTER_SoundRecording );
+ DPMI_Unlock( BLASTER_CallBack );
+ DPMI_Unlock( BLASTER_IntController1Mask );
+ DPMI_Unlock( BLASTER_IntController2Mask );
+ DPMI_Unlock( BLASTER_MixerAddress );
+ DPMI_Unlock( BLASTER_MixerType );
+ DPMI_Unlock( BLASTER_OriginalMidiVolumeLeft );
+ DPMI_Unlock( BLASTER_OriginalMidiVolumeRight );
+ DPMI_Unlock( BLASTER_OriginalVoiceVolumeLeft );
+ DPMI_Unlock( BLASTER_OriginalVoiceVolumeRight );
+ DPMI_Unlock( GlobalStatus );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_LockMemory
+
+ Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+int BLASTER_LockMemory
+ (
+ void
+ )
+
+ {
+ int status;
+
+ status = DPMI_LockMemoryRegion( BLASTER_LockStart, BLASTER_LockEnd );
+ status |= DPMI_LockMemory( ( void * )&BLASTER_Interrupts[ 0 ],
+ sizeof( BLASTER_Interrupts ) );
+ status |= DPMI_LockMemory( ( void * )&BLASTER_SampleSize[ 0 ],
+ sizeof( BLASTER_SampleSize ) );
+ status |= DPMI_Lock( BLASTER_Card );
+ status |= DPMI_Lock( BLASTER_OldInt );
+ status |= DPMI_Lock( BLASTER_Config );
+ status |= DPMI_Lock( BLASTER_Installed );
+ status |= DPMI_Lock( BLASTER_Version );
+ status |= DPMI_Lock( BLASTER_DMABuffer );
+ status |= DPMI_Lock( BLASTER_DMABufferEnd );
+ status |= DPMI_Lock( BLASTER_CurrentDMABuffer );
+ status |= DPMI_Lock( BLASTER_TotalDMABufferSize );
+ status |= DPMI_Lock( BLASTER_TransferLength );
+ status |= DPMI_Lock( BLASTER_MixMode );
+ status |= DPMI_Lock( BLASTER_SamplePacketSize );
+ status |= DPMI_Lock( BLASTER_SampleRate );
+ status |= DPMI_Lock( BLASTER_HaltTransferCommand );
+ status |= DPMI_Lock( ( ( int )BLASTER_SoundPlaying ) );
+ status |= DPMI_Lock( ( ( int )BLASTER_SoundRecording ) );
+ status |= DPMI_Lock( BLASTER_CallBack );
+ status |= DPMI_Lock( BLASTER_IntController1Mask );
+ status |= DPMI_Lock( BLASTER_IntController2Mask );
+ status |= DPMI_Lock( BLASTER_MixerAddress );
+ status |= DPMI_Lock( BLASTER_MixerType );
+ status |= DPMI_Lock( BLASTER_OriginalMidiVolumeLeft );
+ status |= DPMI_Lock( BLASTER_OriginalMidiVolumeRight );
+ status |= DPMI_Lock( BLASTER_OriginalVoiceVolumeLeft );
+ status |= DPMI_Lock( BLASTER_OriginalVoiceVolumeRight );
+ status |= DPMI_Lock( GlobalStatus );
+
+ if ( status != DPMI_Ok )
+ {
+ BLASTER_UnlockMemory();
+ BLASTER_SetErrorCode( BLASTER_DPMI_Error );
+ return( BLASTER_Error );
+ }
+
+ return( BLASTER_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: allocateTimerStack
+
+ Allocate a block of memory from conventional (low) memory and return
+ the selector (which can go directly into a segment register) of the
+ memory block or 0 if an error occured.
+---------------------------------------------------------------------*/
+
+static unsigned short allocateTimerStack
+ (
+ unsigned short size
+ )
+
+ {
+ union REGS regs;
+
+ // clear all registers
+ memset( ®s, 0, sizeof( regs ) );
+
+ // DPMI allocate conventional memory
+ regs.w.ax = 0x100;
+
+ // size in paragraphs
+ regs.w.bx = ( size + 15 ) / 16;
+
+ int386( 0x31, ®s, ®s );
+ if (!regs.w.cflag)
+ {
+ // DPMI call returns selector in dx
+ // (ax contains real mode segment
+ // which is ignored here)
+
+ return( regs.w.dx );
+ }
+
+ // Couldn't allocate memory.
+ return( NULL );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: deallocateTimerStack
+
+ Deallocate a block of conventional (low) memory given a selector to
+ it. Assumes the block was allocated with DPMI function 0x100.
+---------------------------------------------------------------------*/
+
+static void deallocateTimerStack
+ (
+ unsigned short selector
+ )
+
+ {
+ union REGS regs;
+
+ if ( selector != NULL )
+ {
+ // clear all registers
+ memset( ®s, 0, sizeof( regs ) );
+
+ regs.w.ax = 0x101;
+ regs.w.dx = selector;
+ int386( 0x31, ®s, ®s );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_SetupWaveBlaster
+
+ Allows the WaveBlaster to play music while the Sound Blaster 16
+ plays digital sound.
+---------------------------------------------------------------------*/
+
+void BLASTER_SetupWaveBlaster
+ (
+ void
+ )
+
+ {
+
+ if ( BLASTER_MixerType == SB16 )
+ {
+ // Disable MPU401 interrupts. If they are not disabled,
+ // the SB16 will not produce sound or music.
+ BLASTER_WaveBlasterState = BLASTER_ReadMixer( MIXER_DSP4xxISR_Enable );
+ BLASTER_WriteMixer( MIXER_DSP4xxISR_Enable, MIXER_DisableMPU401Interrupts );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_ShutdownWaveBlaster
+
+ Restores WaveBlaster mixer to original state.
+---------------------------------------------------------------------*/
+
+void BLASTER_ShutdownWaveBlaster
+ (
+ void
+ )
+
+ {
+ if ( BLASTER_MixerType == SB16 )
+ {
+ // Restore the state of MPU401 interrupts. If they are not disabled,
+ // the SB16 will not produce sound or music.
+ BLASTER_WriteMixer( MIXER_DSP4xxISR_Enable, BLASTER_WaveBlasterState );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_Init
+
+ Initializes the sound card and prepares the module to play
+ digitized sounds.
+---------------------------------------------------------------------*/
+
+int BLASTER_Init
+ (
+ void
+ )
+
+ {
+ int Irq;
+ int Interrupt;
+ int status;
+
+ if ( BLASTER_Installed )
+ {
+ BLASTER_Shutdown();
+ }
+
+ if ( BLASTER_Config.Address == UNDEFINED )
+ {
+ BLASTER_SetErrorCode( BLASTER_AddrNotSet );
+ return( BLASTER_Error );
+ }
+
+ // Save the interrupt masks
+ BLASTER_IntController1Mask = inp( 0x21 );
+ BLASTER_IntController2Mask = inp( 0xA1 );
+
+ status = BLASTER_ResetDSP();
+ if ( status == BLASTER_Ok )
+ {
+ BLASTER_SaveVoiceVolume();
+
+ BLASTER_SoundPlaying = FALSE;
+
+ BLASTER_SetCallBack( NULL );
+
+ BLASTER_DMABuffer = NULL;
+
+ BLASTER_Version = BLASTER_GetDSPVersion();
+
+ BLASTER_SetPlaybackRate( BLASTER_DefaultSampleRate );
+ BLASTER_SetMixMode( BLASTER_DefaultMixMode );
+
+ if ( BLASTER_Config.Dma16 != UNDEFINED )
+ {
+ status = DMA_VerifyChannel( BLASTER_Config.Dma16 );
+ if ( status == DMA_Error )
+ {
+ BLASTER_SetErrorCode( BLASTER_DmaError );
+ return( BLASTER_Error );
+ }
+ }
+
+ if ( BLASTER_Config.Dma8 != UNDEFINED )
+ {
+ status = DMA_VerifyChannel( BLASTER_Config.Dma8 );
+ if ( status == DMA_Error )
+ {
+ BLASTER_SetErrorCode( BLASTER_DmaError );
+ return( BLASTER_Error );
+ }
+ }
+
+ // Install our interrupt handler
+ Irq = BLASTER_Config.Interrupt;
+ if ( !VALID_IRQ( Irq ) )
+ {
+ BLASTER_SetErrorCode( BLASTER_InvalidIrq );
+ return( BLASTER_Error );
+ }
+
+ Interrupt = BLASTER_Interrupts[ Irq ];
+ if ( Interrupt == INVALID )
+ {
+ BLASTER_SetErrorCode( BLASTER_InvalidIrq );
+ return( BLASTER_Error );
+ }
+
+ status = BLASTER_LockMemory();
+ if ( status != BLASTER_Ok )
+ {
+ BLASTER_UnlockMemory();
+ return( status );
+ }
+
+ StackSelector = allocateTimerStack( kStackSize );
+ if ( StackSelector == NULL )
+ {
+ BLASTER_UnlockMemory();
+ BLASTER_SetErrorCode( BLASTER_OutOfMemory );
+ return( BLASTER_Error );
+ }
+
+ // Leave a little room at top of stack just for the hell of it...
+ StackPointer = kStackSize - sizeof( long );
+
+ BLASTER_OldInt = _dos_getvect( Interrupt );
+ if ( Irq < 8 )
+ {
+ _dos_setvect( Interrupt, BLASTER_ServiceInterrupt );
+ }
+ else
+ {
+ status = IRQ_SetVector( Interrupt, BLASTER_ServiceInterrupt );
+ if ( status != IRQ_Ok )
+ {
+ BLASTER_UnlockMemory();
+ deallocateTimerStack( StackSelector );
+ StackSelector = NULL;
+ BLASTER_SetErrorCode( BLASTER_UnableToSetIrq );
+ return( BLASTER_Error );
+ }
+ }
+
+ BLASTER_Installed = TRUE;
+ status = BLASTER_Ok;
+ }
+
+ BLASTER_SetErrorCode( status );
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: BLASTER_Shutdown
+
+ Ends transfer of sound data to the sound card and restores the
+ system resources used by the card.
+---------------------------------------------------------------------*/
+
+void BLASTER_Shutdown
+ (
+ void
+ )
+
+ {
+ int Irq;
+ int Interrupt;
+
+ // Halt the DMA transfer
+ BLASTER_StopPlayback();
+
+ BLASTER_RestoreVoiceVolume();
+
+ // Reset the DSP
+ BLASTER_ResetDSP();
+
+ // Restore the original interrupt
+ Irq = BLASTER_Config.Interrupt;
+ Interrupt = BLASTER_Interrupts[ Irq ];
+ if ( Irq >= 8 )
+ {
+ IRQ_RestoreVector( Interrupt );
+ }
+ _dos_setvect( Interrupt, BLASTER_OldInt );
+
+ BLASTER_SoundPlaying = FALSE;
+
+ BLASTER_DMABuffer = NULL;
+
+ BLASTER_SetCallBack( NULL );
+
+ BLASTER_UnlockMemory();
+
+ deallocateTimerStack( StackSelector );
+ StackSelector = NULL;
+
+ BLASTER_Installed = FALSE;
+ }
--- /dev/null
+++ b/rott/audiolib/blaster.h
@@ -1,0 +1,148 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: BLASTER.H
+
+ author: James R. Dose
+ date: February 4, 1994
+
+ Public header for BLASTER.C
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __BLASTER_H
+#define __BLASTER_H
+
+typedef struct
+ {
+ unsigned Address;
+ unsigned Type;
+ unsigned Interrupt;
+ unsigned Dma8;
+ unsigned Dma16;
+ unsigned Midi;
+ unsigned Emu;
+ } BLASTER_CONFIG;
+
+extern BLASTER_CONFIG BLASTER_Config;
+extern int BLASTER_DMAChannel;
+
+#define UNDEFINED -1
+
+enum BLASTER_ERRORS
+ {
+ BLASTER_Warning = -2,
+ BLASTER_Error = -1,
+ BLASTER_Ok = 0,
+ BLASTER_EnvNotFound,
+ BLASTER_AddrNotSet,
+ BLASTER_DMANotSet,
+ BLASTER_DMA16NotSet,
+ BLASTER_InvalidParameter,
+ BLASTER_CardNotReady,
+ BLASTER_NoSoundPlaying,
+ BLASTER_InvalidIrq,
+ BLASTER_UnableToSetIrq,
+ BLASTER_DmaError,
+ BLASTER_NoMixer,
+ BLASTER_DPMI_Error,
+ BLASTER_OutOfMemory
+ };
+
+enum BLASTER_Types
+ {
+ SB = 1,
+ SBPro = 2,
+ SB20 = 3,
+ SBPro2 = 4,
+ SB16 = 6
+ };
+
+#define BLASTER_MinCardType SB
+#define BLASTER_MaxCardType SB16
+
+#define STEREO 1
+#define SIXTEEN_BIT 2
+
+#define MONO_8BIT 0
+#define STEREO_8BIT ( STEREO )
+#define MONO_16BIT ( SIXTEEN_BIT )
+#define STEREO_16BIT ( STEREO | SIXTEEN_BIT )
+
+#define BLASTER_MaxMixMode STEREO_16BIT
+
+#define MONO_8BIT_SAMPLE_SIZE 1
+#define MONO_16BIT_SAMPLE_SIZE 2
+#define STEREO_8BIT_SAMPLE_SIZE ( 2 * MONO_8BIT_SAMPLE_SIZE )
+#define STEREO_16BIT_SAMPLE_SIZE ( 2 * MONO_16BIT_SAMPLE_SIZE )
+
+#define BLASTER_DefaultSampleRate 11000
+#define BLASTER_DefaultMixMode MONO_8BIT
+#define BLASTER_MaxIrq 15
+
+char *BLASTER_ErrorString( int ErrorNumber );
+void BLASTER_EnableInterrupt( void );
+void BLASTER_DisableInterrupt( void );
+int BLASTER_WriteDSP( unsigned data );
+int BLASTER_ReadDSP( void );
+int BLASTER_ResetDSP( void );
+int BLASTER_GetDSPVersion( void );
+void BLASTER_SpeakerOn( void );
+void BLASTER_SpeakerOff( void );
+void BLASTER_SetPlaybackRate( unsigned rate );
+unsigned BLASTER_GetPlaybackRate( void );
+int BLASTER_SetMixMode( int mode );
+void BLASTER_StopPlayback( void );
+int BLASTER_SetupDMABuffer( char *BufferPtr, int BufferSize, int mode );
+int BLASTER_GetCurrentPos( void );
+int BLASTER_DSP1xx_BeginPlayback( int length );
+int BLASTER_DSP2xx_BeginPlayback( int length );
+int BLASTER_DSP4xx_BeginPlayback( int length );
+int BLASTER_BeginBufferedRecord( char *BufferStart, int BufferSize,
+ int NumDivisions, unsigned SampleRate, int MixMode,
+ void ( *CallBackFunc )( void ) );
+int BLASTER_BeginBufferedPlayback( char *BufferStart,
+ int BufferSize, int NumDivisions, unsigned SampleRate,
+ int MixMode, void ( *CallBackFunc )( void ) );
+void BLASTER_WriteMixer( int reg, int data );
+int BLASTER_ReadMixer( int reg );
+int BLASTER_GetVoiceVolume( void );
+int BLASTER_SetVoiceVolume( int volume );
+int BLASTER_GetMidiVolume( void );
+int BLASTER_SetMidiVolume( int volume );
+int BLASTER_CardHasMixer( void );
+void BLASTER_SaveVoiceVolume( void );
+void BLASTER_RestoreVoiceVolume( void );
+void BLASTER_SaveMidiVolume( void );
+void BLASTER_RestoreMidiVolume( void );
+int BLASTER_GetEnv( BLASTER_CONFIG *Config );
+int BLASTER_SetCardSettings( BLASTER_CONFIG Config );
+int BLASTER_GetCardSettings( BLASTER_CONFIG *Config );
+int BLASTER_GetCardInfo( int *MaxSampleBits, int *MaxChannels );
+void BLASTER_SetCallBack( void ( *func )( void ) );
+void BLASTER_SetupWaveBlaster( void );
+void BLASTER_ShutdownWaveBlaster( void );
+int BLASTER_Init( void );
+void BLASTER_Shutdown( void );
+void BLASTER_UnlockMemory( void );
+int BLASTER_LockMemory( void );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/ctaweapi.h
@@ -1,0 +1,352 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/****************************************************************************\
+* *
+* CTAWEAPI.H SB AWE32 DOS API header *
+* *
+* (C) Copyright Creative Technology Ltd. 1992-94. All rights reserved *
+* worldwide. *
+* *
+* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY *
+* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE *
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR *
+* PURPOSE. *
+* *
+* You have a royalty-free right to use, modify, reproduce and *
+* distribute the Sample Files (and/or any modified version) in *
+* any way you find useful, provided that you agree to *
+* the Creative's Software Licensing Aggreement and you also agree that *
+* Creative has no warranty obligations or liability for any Sample Files. *
+* *
+\****************************************************************************/
+
+/****************************************************************************\
+* File name : CTAWEAPI.H *
+* *
+* Programmer : Creative SB AWE32 Team *
+* Creative Technology Ltd, 1994. All rights reserved. *
+* *
+* Version : 2.0b *
+* *
+\****************************************************************************/
+
+#ifndef _CTAWEAPI
+#define _CTAWEAPI
+
+
+#define MAXBANKS 64 /* maximum number of banks */
+#define MAXNRPN 32 /* maximum number of NRPN */
+
+
+#if defined(__FLAT__) || defined(__HIGHC__) || defined(DOS386)
+#define PACKETSIZE 8192 /* packet size for 32bit libraries */
+#else
+#define PACKETSIZE 512 /* packet size for real mode libraries */
+#endif
+
+
+#if defined(__FLAT__)
+ #define NEAR
+ #define FAR
+#endif
+
+
+#if defined(__SC__)
+ #pragma pack(1)
+ #if defined(DOS386)
+ #define NEAR
+ #define FAR
+ #endif
+#endif
+
+
+#if defined(__WATCOMC__)
+ #pragma pack(1)
+#endif
+
+
+#if defined(__HIGHC__)
+ #define NEAR
+ #define FAR
+ #define PASCAL _DCC((_DEFAULT_CALLING_CONVENTION|_CALLEE_POPS_STACK) & \
+ ~ (_REVERSE_PARMS|_OVERLOADED))
+ #pragma Push_align_members(1)
+ #pragma Global_aliasing_convention("_%r")
+#endif
+
+
+typedef int BOOL;
+#define FALSE 0
+#define TRUE 1
+
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+
+typedef short int SHORT;
+typedef unsigned int UINT;
+typedef signed long LONG;
+
+#ifndef FAR
+#define FAR __far
+#endif
+
+#ifndef HUGE
+#define HUGE __huge
+#endif
+
+#ifndef PASCAL
+#define PASCAL __pascal
+#endif
+
+typedef void FAR* LPVOID;
+typedef BYTE FAR* LPBYTE;
+typedef WORD FAR* LPWORD;
+typedef DWORD FAR* LPDWORD;
+
+#define LOBYTE(w) ((BYTE)(w))
+#define HIBYTE(w) ((BYTE)(((UINT)(w) >> 8) & 0xFF))
+
+#define LOWORD(l) ((WORD)(DWORD)(l))
+#define HIWORD(l) ((WORD)((((DWORD)(l)) >> 16) & 0xFFFF))
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Start of modules */
+extern int* __midieng_code(void);
+extern int* __hardware_code(void);
+extern int* __sbkload_code(void);
+extern int* __nrpn_code(void);
+extern int __midivar_data;
+extern int __nrpnvar_data;
+extern int __embed_data;
+
+
+typedef char SCRATCH[702];
+typedef char SOUNDFONT[124];
+typedef char GCHANNEL[20];
+typedef char MIDICHANNEL[32];
+typedef char NRPNCHANNEL[96];
+
+typedef struct {
+ SHORT bank_no; /* Slot number being used */
+ SHORT total_banks; /* Total number of banks */
+ LONG FAR* banksizes; /* Pointer to a list of bank sizes */
+ LONG file_size; /* exact size of the sound font file */
+ char FAR* data; /* Address of buffer of size >= PACKETSIZE */
+ char FAR* presets; /* Allocated memory for preset data */
+
+ LONG total_patch_ram; /* Total patch ram available */
+ SHORT no_sample_packets;/* Number of packets of sound sample to stream */
+ LONG sample_seek; /* Start file location of sound sample */
+ LONG preset_seek; /* Address of preset_seek location */
+ LONG preset_read_size; /* Number of bytes from preset_seek to allocate and read */
+ LONG preset_size; /* Preset actual size */
+} SOUND_PACKET;
+
+typedef struct {
+ SHORT tag; /* Must be 0x100 or 0x101 */
+ SHORT preset_size; /* Preset table of this size is required */
+ SHORT no_wave_packets; /* Number of packets of Wave sample to stream. */
+ LONG reserved;
+
+ SHORT bank_no; /* bank number */
+ char FAR* data; /* Address of packet of size PACKETSIZE */
+ char FAR* presets; /* Allocated memory for preset data */
+ LONG sample_size; /* Sample size, i.e. number of samples */
+ LONG samples_per_sec; /* Samples per second */
+ SHORT bits_per_sample; /* Bits per sample, 8 or 16 */
+ SHORT no_channels; /* Number of channels, 1=mono, 2=stereo */
+ SHORT looping; /* Looping? 0=no, 1=yes */
+ LONG startloop; /* if looping, then these are the addresses */
+ LONG endloop;
+ SHORT release; /* release time, 0=24ms, 8191=23.78s */
+} WAVE_PACKET;
+
+typedef struct {
+ LPBYTE SPad1;
+ LPBYTE SPad2;
+ LPBYTE SPad3;
+ LPBYTE SPad4;
+ LPBYTE SPad5;
+ LPBYTE SPad6;
+ LPBYTE SPad7;
+} SOUNDPAD;
+
+/* AWE32 variables */
+extern WORD awe32NumG;
+extern WORD awe32BaseAddx;
+extern DWORD awe32DramSize;
+
+/* MIDI variables */
+extern SCRATCH awe32Scratch;
+extern SOUNDFONT awe32SFont[4];
+extern GCHANNEL awe32GChannel[32];
+extern MIDICHANNEL awe32MIDIChannel[16];
+extern SOUNDPAD awe32SoundPad;
+
+/* NRPN variables */
+extern NRPNCHANNEL awe32NRPNChannel[16];
+
+/* SoundFont objects */
+extern BYTE awe32SPad1Obj[];
+extern BYTE awe32SPad2Obj[];
+extern BYTE awe32SPad3Obj[];
+extern BYTE awe32SPad4Obj[];
+extern BYTE awe32SPad5Obj[];
+extern BYTE awe32SPad6Obj[];
+extern BYTE awe32SPad7Obj[];
+
+/* AWE register functions */
+extern void PASCAL awe32RegW(WORD, WORD);
+extern WORD PASCAL awe32RegRW(WORD);
+extern void PASCAL awe32RegDW(WORD, DWORD);
+extern DWORD PASCAL awe32RegRDW(WORD);
+
+/* MIDI support functions */
+extern WORD PASCAL awe32InitMIDI(void);
+extern WORD PASCAL awe32NoteOn(WORD, WORD, WORD);
+extern WORD PASCAL awe32NoteOff(WORD, WORD, WORD);
+extern WORD PASCAL awe32ProgramChange(WORD, WORD);
+extern WORD PASCAL awe32Controller(WORD, WORD, WORD);
+extern WORD PASCAL awe32PolyKeyPressure(WORD, WORD, WORD);
+extern WORD PASCAL awe32ChannelPressure(WORD, WORD);
+extern WORD PASCAL awe32PitchBend(WORD, WORD, WORD);
+extern WORD PASCAL awe32Sysex(WORD, LPBYTE, WORD);
+extern WORD PASCAL __awe32NoteOff(WORD, WORD, WORD, WORD);
+extern WORD PASCAL __awe32IsPlaying(WORD, WORD, WORD, WORD);
+
+/* NRPN support functions */
+extern WORD PASCAL awe32InitNRPN(void);
+
+/* Hardware support functions */
+extern WORD PASCAL awe32Detect(WORD);
+extern WORD PASCAL awe32InitHardware(void);
+extern WORD PASCAL awe32Terminate(void);
+
+/* SoundFont support functions */
+extern WORD PASCAL awe32TotalPatchRam(SOUND_PACKET FAR*);
+extern WORD PASCAL awe32DefineBankSizes(SOUND_PACKET FAR*);
+extern WORD PASCAL awe32SFontLoadRequest(SOUND_PACKET FAR*);
+extern WORD PASCAL awe32StreamSample(SOUND_PACKET FAR*);
+extern WORD PASCAL awe32SetPresets(SOUND_PACKET FAR*);
+extern WORD PASCAL awe32ReleaseBank(SOUND_PACKET FAR*);
+extern WORD PASCAL awe32ReleaseAllBanks(SOUND_PACKET FAR*);
+extern WORD PASCAL awe32WPLoadRequest(WAVE_PACKET FAR*);
+extern WORD PASCAL awe32WPLoadWave(WAVE_PACKET FAR*);
+extern WORD PASCAL awe32WPStreamWave(WAVE_PACKET FAR*);
+extern WORD PASCAL awe32WPBuildSFont(WAVE_PACKET FAR*);
+
+/* End of modules */
+extern int* __midieng_ecode(void);
+extern int* __hardware_ecode(void);
+extern int* __sbkload_ecode(void);
+extern int* __nrpn_ecode(void);
+extern int __midivar_edata;
+extern int __nrpnvar_edata;
+extern int __embed_edata;
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#if defined(__SC__)
+ #pragma pack()
+#endif
+
+
+#if defined(__HIGHC__)
+ #pragma Pop_align_members
+ #pragma Global_aliasing_convention()
+ #pragma Alias(awe32RegW,"AWE32REGW")
+ #pragma Alias(awe32RegRW,"AWE32REGRW")
+ #pragma Alias(awe32RegDW,"AWE32REGDW")
+ #pragma Alias(awe32RegRDW,"AWE32REGRDW")
+ #pragma Alias(awe32InitMIDI,"AWE32INITMIDI")
+ #pragma Alias(awe32NoteOn,"AWE32NOTEON")
+ #pragma Alias(awe32NoteOff,"AWE32NOTEOFF")
+ #pragma Alias(awe32ProgramChange,"AWE32PROGRAMCHANGE")
+ #pragma Alias(awe32Controller,"AWE32CONTROLLER")
+ #pragma Alias(awe32PolyKeyPressure,"AWE32POLYKEYPRESSURE")
+ #pragma Alias(awe32ChannelPressure,"AWE32CHANNELPRESSURE")
+ #pragma Alias(awe32PitchBend,"AWE32PITCHBEND")
+ #pragma Alias(awe32Sysex,"AWE32SYSEX")
+ #pragma Alias(__awe32NoteOff,"__AWE32NOTEOFF")
+ #pragma Alias(__awe32IsPlaying,"__AWE32ISPLAYING")
+ #pragma Alias(awe32InitNRPN,"AWE32INITNRPN")
+ #pragma Alias(awe32Detect,"AWE32DETECT")
+ #pragma Alias(awe32InitHardware,"AWE32INITHARDWARE")
+ #pragma Alias(awe32Terminate,"AWE32TERMINATE")
+ #pragma Alias(awe32TotalPatchRam,"AWE32TOTALPATCHRAM")
+ #pragma Alias(awe32DefineBankSizes,"AWE32DEFINEBANKSIZES")
+ #pragma Alias(awe32SFontLoadRequest,"AWE32SFONTLOADREQUEST")
+ #pragma Alias(awe32StreamSample,"AWE32STREAMSAMPLE")
+ #pragma Alias(awe32SetPresets,"AWE32SETPRESETS")
+ #pragma Alias(awe32ReleaseBank,"AWE32RELEASEBANK")
+ #pragma Alias(awe32ReleaseAllBanks,"AWE32RELEASEALLBANKS")
+ #pragma Alias(awe32WPLoadRequest,"AWE32WPLOADREQUEST")
+ #pragma Alias(awe32WPLoadWave,"AWE32WPLOADWAVE")
+ #pragma Alias(awe32WPStreamWave,"AWE32WPSTREAMWAVE")
+ #pragma Alias(awe32WPBuildSFont,"AWE32WPBUILDSFONT")
+#endif
+
+
+#if defined(__WATCOMC__)
+ #pragma pack()
+ #pragma aux awe32NumG "_*"
+ #pragma aux awe32BaseAddx "_*"
+ #pragma aux awe32DramSize "_*"
+ #pragma aux awe32Scratch "_*"
+ #pragma aux awe32SFont "_*"
+ #pragma aux awe32GChannel "_*"
+ #pragma aux awe32MIDIChannel "_*"
+ #pragma aux awe32SoundPad "_*"
+ #pragma aux awe32NRPNChannel "_*"
+ #pragma aux awe32SPad1Obj "_*"
+ #pragma aux awe32SPad2Obj "_*"
+ #pragma aux awe32SPad3Obj "_*"
+ #pragma aux awe32SPad4Obj "_*"
+ #pragma aux awe32SPad5Obj "_*"
+ #pragma aux awe32SPad6Obj "_*"
+ #pragma aux awe32SPad7Obj "_*"
+ #pragma aux __midieng_code "_*"
+ #pragma aux __midieng_ecode "_*"
+ #pragma aux __hardware_code "_*"
+ #pragma aux __hardware_ecode "_*"
+ #pragma aux __sbkload_code "_*"
+ #pragma aux __sbkload_ecode "_*"
+ #pragma aux __nrpn_code "_*"
+ #pragma aux __nrpn_ecode "_*"
+ #pragma aux __midivar_data "_*"
+ #pragma aux __midivar_edata "_*"
+ #pragma aux __nrpnvar_data "_*"
+ #pragma aux __nrpnvar_edata "_*"
+ #pragma aux __embed_data "_*"
+ #pragma aux __embed_edata "_*"
+#endif
+
+
+#endif /* _CTAWEAPI */
--- /dev/null
+++ b/rott/audiolib/debugio.c
@@ -1,0 +1,251 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include "debugio.h"
+
+static unsigned short disp_offset = 160 * 24;
+static void myutoa( unsigned num, char *string, int radix );
+static void myitoa( int num, char *string, int radix );
+
+void DB_SetXY
+ (
+ int x,
+ int y
+ )
+
+ {
+ disp_offset = ( x * 2 ) + ( y * 160 );
+ }
+
+void DB_PutChar
+ (
+ char ch
+ )
+
+ {
+ int j;
+ char *disp_start = (char *)( 0xb0000 );
+
+ if ( disp_offset >= 160 * 24 )
+ {
+ for ( j = 160; j < 160 * 24; j += 2 )
+ {
+ *( disp_start + j - 160 ) = *( disp_start + j );
+ }
+
+ disp_offset = 160 * 23;
+
+ for ( j = disp_offset; j < ( 160 * 24 ); j += 2 )
+ {
+ *( disp_start + j ) = ' ';
+ }
+ }
+
+ if ( ch >= 32 )
+ {
+ *( disp_start + disp_offset ) = ch;
+ disp_offset = disp_offset + 2;
+ }
+
+ if ( ch == '\r' )
+ {
+ disp_offset = disp_offset / 160;
+ disp_offset = disp_offset * 160;
+ }
+
+ if ( ch == '\n' )
+ {
+ disp_offset = disp_offset + 160;
+ if ( disp_offset < 160 * 24 )
+ {
+ for ( j = disp_offset; j < ( ( ( disp_offset / 160 ) + 1 ) *
+ 160 ); j += 2 )
+ {
+ *( disp_start + j ) = ' ';
+ }
+ }
+ }
+ }
+
+int DB_PrintString
+ (
+ char *string
+ )
+
+ {
+ int count;
+ char *ptr;
+
+ ptr = string;
+ count = 0;
+
+ while ( *ptr )
+ {
+ DB_PutChar( *ptr );
+ count++;
+ ptr++;
+ }
+
+ return( count );
+ }
+
+static void myutoa
+ (
+ unsigned num,
+ char *string,
+ int radix
+ )
+
+ {
+ int val;
+ int length;
+ int pos;
+ char temp[ 100 ];
+
+ length = 0;
+ do
+ {
+ val = num % radix;
+ if ( val < 10 )
+ {
+ temp[ length ] = '0' + val;
+ }
+ else
+ {
+ temp[ length ] = 'A' + val - 10;
+ }
+ num /= radix;
+ length++;
+ }
+ while( num > 0 );
+
+ pos = 0;
+ while( length > 0 )
+ {
+ length--;
+ string[ length ] = temp[ pos ];
+ pos++;
+ }
+ string[ pos ] = 0;
+ }
+
+static void myitoa
+ (
+ int num,
+ char *string,
+ int radix
+ )
+
+ {
+ if ( num < 0 )
+ {
+ *string++ = '-';
+ num = -num;
+ }
+
+ myutoa( num, string, radix );
+ }
+
+int DB_PrintNum
+ (
+ int number
+ )
+
+ {
+ char string[ 100 ];
+ int count;
+
+ myitoa( number, &string[ 0 ], 10 );
+ count = DB_PrintString( &string[ 0 ] );
+
+ return( count );
+ }
+
+int DB_PrintUnsigned
+ (
+ unsigned long number,
+ int radix
+ )
+
+ {
+ char string[ 100 ];
+ int count;
+
+ myutoa( number, &string[ 0 ], radix );
+ count = DB_PrintString( &string[ 0 ] );
+
+ return( count );
+ }
+
+int DB_printf
+ (
+ char *fmt,
+ ...
+ )
+
+ {
+ va_list argptr;
+ int count;
+ char *ptr;
+
+ va_start( argptr, fmt );
+ ptr = fmt;
+ count = 0;
+
+ while( *ptr != 0 )
+ {
+ if ( *ptr == '%' )
+ {
+ ptr++;
+ switch( *ptr )
+ {
+ case 0 :
+ return( EOF );
+ break;
+ case 'd' :
+ count += DB_PrintNum( va_arg( argptr, int ) );
+ break;
+ case 's' :
+ count += DB_PrintString( va_arg( argptr, char * ) );
+ break;
+ case 'u' :
+ count += DB_PrintUnsigned( va_arg( argptr, int ), 10 );
+ break;
+ case 'x' :
+ case 'X' :
+ count += DB_PrintUnsigned( va_arg( argptr, int ), 16 );
+ break;
+ }
+ ptr++;
+ }
+ else
+ {
+ DB_PutChar( *ptr );
+ count++;
+ ptr++;
+ }
+ }
+
+ va_end( argptr );
+
+ return( count );
+ }
--- /dev/null
+++ b/rott/audiolib/debugio.h
@@ -1,0 +1,30 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef __DEBUGIO_H
+#define __DEBUGIO_H
+
+void DB_SetXY( int x, int y );
+void DB_PutChar( char ch );
+int DB_PrintString( char *string );
+int DB_PrintNum( int number );
+int DB_PrintUnsigned( unsigned long number, int radix );
+int DB_printf( char *fmt, ... );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/dma.c
@@ -1,0 +1,379 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: DMA.C
+
+ author: James R. Dose
+ date: February 4, 1994
+
+ Low level routines to for programming the DMA controller for 8 bit
+ and 16 bit transfers.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#include <dos.h>
+#include <conio.h>
+#include <stdlib.h>
+#include "dma.h"
+
+#define DMA_MaxChannel 7
+
+#define VALID ( 1 == 1 )
+#define INVALID ( !VALID )
+
+#define BYTE 0
+#define WORD 1
+
+typedef struct
+ {
+ int Valid;
+ int Width;
+ int Mask;
+ int Mode;
+ int Clear;
+ int Page;
+ int Address;
+ int Length;
+ } DMA_PORT;
+
+static const DMA_PORT DMA_PortInfo[ DMA_MaxChannel + 1 ] =
+ {
+ { VALID, BYTE, 0xA, 0xB, 0xC, 0x87, 0x0, 0x1 },
+ { VALID, BYTE, 0xA, 0xB, 0xC, 0x83, 0x2, 0x3 },
+ { INVALID, BYTE, 0xA, 0xB, 0xC, 0x81, 0x4, 0x5 },
+ { VALID, BYTE, 0xA, 0xB, 0xC, 0x82, 0x6, 0x7 },
+ { INVALID, WORD, 0xD4, 0xD6, 0xD8, 0x8F, 0xC0, 0xC2 },
+ { VALID, WORD, 0xD4, 0xD6, 0xD8, 0x8B, 0xC4, 0xC6 },
+ { VALID, WORD, 0xD4, 0xD6, 0xD8, 0x89, 0xC8, 0xCA },
+ { VALID, WORD, 0xD4, 0xD6, 0xD8, 0x8A, 0xCC, 0xCE },
+ };
+
+int DMA_ErrorCode = DMA_Ok;
+
+#define DMA_SetErrorCode( status ) \
+ DMA_ErrorCode = ( status );
+
+
+/*---------------------------------------------------------------------
+ Function: DMA_ErrorString
+
+ Returns a pointer to the error message associated with an error
+ number. A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *DMA_ErrorString
+ (
+ int ErrorNumber
+ )
+
+ {
+ char *ErrorString;
+
+ switch( ErrorNumber )
+ {
+ case DMA_Error :
+ ErrorString = DMA_ErrorString( DMA_ErrorCode );
+ break;
+
+ case DMA_Ok :
+ ErrorString = "DMA channel ok.";
+ break;
+
+ case DMA_ChannelOutOfRange :
+ ErrorString = "DMA channel out of valid range.";
+ break;
+
+ case DMA_InvalidChannel :
+ ErrorString = "Unsupported DMA channel.";
+ break;
+
+ default :
+ ErrorString = "Unknown DMA error code.";
+ break;
+ }
+
+ return( ErrorString );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: DMA_VerifyChannel
+
+ Verifies whether a DMA channel is available to transfer data.
+---------------------------------------------------------------------*/
+
+int DMA_VerifyChannel
+ (
+ int channel
+ )
+
+ {
+ int status;
+ int Error;
+
+ status = DMA_Ok;
+ Error = DMA_Ok;
+
+ if ( ( channel < 0 ) || ( DMA_MaxChannel < channel ) )
+ {
+ Error = DMA_ChannelOutOfRange;
+ status = DMA_Error;
+ }
+ else if ( DMA_PortInfo[ channel ].Valid == INVALID )
+ {
+ Error = DMA_InvalidChannel;
+ status = DMA_Error;
+ }
+
+ DMA_SetErrorCode( Error );
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: DMA_SetupTransfer
+
+ Programs the specified DMA channel to transfer data.
+---------------------------------------------------------------------*/
+
+int DMA_SetupTransfer
+ (
+ int channel,
+ char *address,
+ int length,
+ int mode
+ )
+
+ {
+ DMA_PORT *Port;
+ int addr;
+ int ChannelSelect;
+ int Page;
+ int HiByte;
+ int LoByte;
+ int TransferLength;
+ int status;
+
+ status = DMA_VerifyChannel( channel );
+
+ if ( status == DMA_Ok )
+ {
+ Port = &DMA_PortInfo[ channel ];
+ ChannelSelect = channel & 0x3;
+
+ addr = ( int )address;
+
+ if ( Port->Width == WORD )
+ {
+ Page = ( addr >> 16 ) & 255;
+ HiByte = ( addr >> 9 ) & 255;
+ LoByte = ( addr >> 1 ) & 255;
+
+ // Convert the length in bytes to the length in words
+ TransferLength = ( length + 1 ) >> 1;
+
+ // The length is always one less the number of bytes or words
+ // that we're going to send
+ TransferLength--;
+ }
+ else
+ {
+ Page = ( addr >> 16 ) & 255;
+ HiByte = ( addr >> 8 ) & 255;
+ LoByte = addr & 255;
+
+ // The length is always one less the number of bytes or words
+ // that we're going to send
+ TransferLength = length - 1;
+ }
+
+ // Mask off DMA channel
+ outp( Port->Mask, 4 | ChannelSelect );
+
+ // Clear flip-flop to lower byte with any data
+ outp( Port->Clear, 0 );
+
+ // Set DMA mode
+ switch( mode )
+ {
+ case DMA_SingleShotRead :
+ outp( Port->Mode, 0x48 | ChannelSelect );
+ break;
+
+ case DMA_SingleShotWrite :
+ outp( Port->Mode, 0x44 | ChannelSelect );
+ break;
+
+ case DMA_AutoInitRead :
+ outp( Port->Mode, 0x58 | ChannelSelect );
+ break;
+
+ case DMA_AutoInitWrite :
+ outp( Port->Mode, 0x54 | ChannelSelect );
+ break;
+ }
+
+ // Send address
+ outp( Port->Address, LoByte );
+ outp( Port->Address, HiByte );
+
+ // Send page
+ outp( Port->Page, Page );
+
+ // Send length
+ outp( Port->Length, TransferLength );
+ outp( Port->Length, TransferLength >> 8 );
+
+ // enable DMA channel
+ outp( Port->Mask, ChannelSelect );
+ }
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: DMA_EndTransfer
+
+ Ends use of the specified DMA channel.
+---------------------------------------------------------------------*/
+
+int DMA_EndTransfer
+ (
+ int channel
+ )
+
+ {
+ DMA_PORT *Port;
+ int ChannelSelect;
+ int status;
+
+ status = DMA_VerifyChannel( channel );
+ if ( status == DMA_Ok )
+ {
+ Port = &DMA_PortInfo[ channel ];
+ ChannelSelect = channel & 0x3;
+
+ // Mask off DMA channel
+ outp( Port->Mask, 4 | ChannelSelect );
+
+ // Clear flip-flop to lower byte with any data
+ outp( Port->Clear, 0 );
+ }
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: DMA_GetCurrentPos
+
+ Returns the position of the specified DMA transfer.
+---------------------------------------------------------------------*/
+
+char *DMA_GetCurrentPos
+ (
+ int channel
+ )
+
+ {
+ DMA_PORT *Port;
+ unsigned long addr;
+ int status;
+
+ addr = NULL;
+ status = DMA_VerifyChannel( channel );
+
+ if ( status == DMA_Ok )
+ {
+ Port = &DMA_PortInfo[ channel ];
+
+ if ( Port->Width == WORD )
+ {
+ // Get address
+ addr = inp( Port->Address ) << 1;
+ addr |= inp( Port->Address ) << 9;
+
+ // Get page
+ addr |= inp( Port->Page ) << 16;
+ }
+ else
+ {
+ // Get address
+ addr = inp( Port->Address );
+ addr |= inp( Port->Address ) << 8;
+
+ // Get page
+ addr |= inp( Port->Page ) << 16;
+ }
+ }
+
+ return( ( char * )addr );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: DMA_GetTransferCount
+
+ Returns how many bytes are left in the DMA's transfer.
+---------------------------------------------------------------------*/
+
+int DMA_GetTransferCount
+ (
+ int channel
+ )
+
+ {
+ DMA_PORT *Port;
+ int count;
+ int status;
+
+ status = DMA_Ok;
+
+ count = 0;
+
+ if ( ( channel < 0 ) || ( DMA_MaxChannel < channel ) )
+ {
+ status = DMA_ChannelOutOfRange;
+ }
+ else if ( DMA_PortInfo[ channel ].Valid == INVALID )
+ {
+ status = DMA_InvalidChannel;
+ }
+
+ if ( status == DMA_Ok )
+ {
+ Port = &DMA_PortInfo[ channel ];
+
+ outp( Port->Clear, 0 );
+ count = inp( Port->Length );
+ count += inp( Port->Length ) << 8;
+
+ if ( Port->Width == WORD )
+ {
+ count <<= 1;
+ }
+ }
+
+ DMA_SetErrorCode( status );
+
+ return( count );
+ }
--- /dev/null
+++ b/rott/audiolib/dma.h
@@ -1,0 +1,83 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ file: DMA.H
+
+ author: James R. Dose
+ date: February 4, 1994
+
+ Public header file for DMA.C
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __DMA_H
+#define __DMA_H
+
+enum DMA_ERRORS
+ {
+ DMA_Error = -1,
+ DMA_Ok = 0,
+ DMA_ChannelOutOfRange,
+ DMA_InvalidChannel
+ };
+
+enum DMA_Modes
+ {
+ DMA_SingleShotRead,
+ DMA_SingleShotWrite,
+ DMA_AutoInitRead,
+ DMA_AutoInitWrite
+ };
+
+char *DMA_ErrorString
+ (
+ int ErrorNumber
+ );
+
+int DMA_VerifyChannel
+ (
+ int channel
+ );
+
+int DMA_SetupTransfer
+ (
+ int channel,
+ char *address,
+ int length,
+ int mode
+ );
+
+int DMA_EndTransfer
+ (
+ int channel
+ );
+
+char *DMA_GetCurrentPos
+ (
+ int channel
+ );
+
+int DMA_GetTransferCount
+ (
+ int channel
+ );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/dpmi.c
@@ -1,0 +1,250 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: DPMI.C
+
+ author: James R. Dose
+ date: April 8, 1994
+
+ Functions for performing DPMI calls.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#include <dos.h>
+#include <string.h>
+#include "dpmi.h"
+
+#define TRUE ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+static union REGS Regs;
+static struct SREGS SegRegs;
+
+
+/*---------------------------------------------------------------------
+ Function: DPMI_GetRealModeVector
+
+ Returns the vector of a real mode interrupt.
+---------------------------------------------------------------------*/
+
+unsigned long DPMI_GetRealModeVector
+ (
+ int num
+ )
+
+ {
+ unsigned long vector;
+
+ Regs.x.eax = 0x0200;
+ Regs.h.bl = num;
+ int386( 0x31, &Regs, &Regs );
+
+ vector = Regs.w.cx & 0xffff;
+ vector <<= 16;
+ vector |= Regs.w.dx & 0xffff;
+
+ return( vector );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: DPMI_SetRealModeVector
+
+ Sets the vector of a real mode interrupt.
+---------------------------------------------------------------------*/
+
+void DPMI_SetRealModeVector
+ (
+ int num,
+ unsigned long vector
+ )
+
+ {
+ Regs.x.eax = 0x0201;
+ Regs.h.bl = num;
+ Regs.w.dx = vector & 0xffff;
+ Regs.w.cx = ( vector >> 16 ) & 0xffff;
+
+ int386( 0x31, &Regs, &Regs );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: DPMI_CallRealModeFunction
+
+ Performs a call to a real mode function.
+---------------------------------------------------------------------*/
+
+int DPMI_CallRealModeFunction
+ (
+ dpmi_regs *callregs
+ )
+
+ {
+ // Setup our registers to call DPMI
+ Regs.w.ax = 0x0301;
+ Regs.h.bl = 0;
+ Regs.h.bh = 0;
+ Regs.w.cx = 0;
+
+ SegRegs.es = FP_SEG( callregs );
+ Regs.x.edi = FP_OFF( callregs );
+
+ // Call Real-mode procedure with Far Return Frame
+ int386x( 0x31, &Regs, &Regs, &SegRegs );
+
+ if ( Regs.x.cflag )
+ {
+ return( DPMI_Error );
+ }
+
+ return( DPMI_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: DPMI_LockMemory
+
+ Locks a region of memory to keep the virtual memory manager from
+ paging the region out.
+---------------------------------------------------------------------*/
+
+int DPMI_LockMemory
+ (
+ void *address,
+ unsigned length
+ )
+
+ {
+ unsigned linear;
+
+ // Thanks to DOS/4GW's zero-based flat memory model, converting
+ // a pointer of any type to a linear address is trivial.
+
+ linear = (unsigned) address;
+
+ // DPMI Lock Linear Region
+ Regs.w.ax = 0x600;
+
+ // Linear address in BX:CX
+ Regs.w.bx = (linear >> 16);
+ Regs.w.cx = (linear & 0xFFFF);
+
+ // Length in SI:DI
+ Regs.w.si = (length >> 16);
+ Regs.w.di = (length & 0xFFFF);
+
+ int386 (0x31, &Regs, &Regs);
+
+ // Return 0 if can't lock
+ if ( Regs.w.cflag )
+ {
+ return( DPMI_Error );
+ }
+
+ return ( DPMI_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: DPMI_LockMemoryRegion
+
+ Locks a region of memory to keep the virtual memory manager from
+ paging the region out.
+---------------------------------------------------------------------*/
+
+int DPMI_LockMemoryRegion
+ (
+ void *start,
+ void *end
+ )
+
+ {
+ int status;
+
+ status = DPMI_LockMemory( start, ( char * )end - ( char * )start );
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: DPMI_UnlockMemory
+
+ Unlocks a region of memory that was previously locked.
+---------------------------------------------------------------------*/
+
+int DPMI_UnlockMemory
+ (
+ void *address,
+ unsigned length
+ )
+
+ {
+ unsigned linear;
+
+ // Thanks to DOS/4GW's zero-based flat memory model, converting
+ // a pointer of any type to a linear address is trivial.
+
+ linear = (unsigned) address;
+
+ // DPMI Unlock Linear Region
+ Regs.w.ax = 0x601;
+
+ // Linear address in BX:CX
+ Regs.w.bx = (linear >> 16);
+ Regs.w.cx = (linear & 0xFFFF);
+
+ // Length in SI:DI
+ Regs.w.si = (length >> 16);
+ Regs.w.di = (length & 0xFFFF);
+
+ int386 (0x31, &Regs, &Regs);
+
+ // Return 0 if can't unlock
+ if ( Regs.w.cflag )
+ {
+ return( DPMI_Error );
+ }
+
+ return ( DPMI_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: DPMI_UnlockMemoryRegion
+
+ Unlocks a region of memory that was previously locked.
+---------------------------------------------------------------------*/
+
+int DPMI_UnlockMemoryRegion
+ (
+ void *start,
+ void *end
+ )
+
+ {
+ int status;
+
+ status = DPMI_UnlockMemory( start, ( char * )end - ( char * )start );
+
+ return( status );
+ }
--- /dev/null
+++ b/rott/audiolib/dpmi.h
@@ -1,0 +1,102 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: DPMI.H
+
+ author: James R. Dose
+ date: March 31, 1994
+
+ Inline functions for performing DPMI calls.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __DPMI_H
+#define __DPMI_H
+
+enum DPMI_Errors
+ {
+ DPMI_Warning = -2,
+ DPMI_Error = -1,
+ DPMI_Ok = 0
+ };
+
+typedef struct
+ {
+ unsigned long EDI;
+ unsigned long ESI;
+ unsigned long EBP;
+ unsigned long Reserved;
+ unsigned long EBX;
+ unsigned long EDX;
+ unsigned long ECX;
+ unsigned long EAX;
+ unsigned short Flags;
+ unsigned short ES;
+ unsigned short DS;
+ unsigned short FS;
+ unsigned short GS;
+ unsigned short IP;
+ unsigned short CS;
+ unsigned short SP;
+ unsigned short SS;
+ } dpmi_regs;
+
+unsigned long DPMI_GetRealModeVector( int num );
+void DPMI_SetRealModeVector( int num, unsigned long vector );
+int DPMI_CallRealModeFunction( dpmi_regs *callregs );
+int DPMI_GetDOSMemory( void **ptr, long *descriptor, unsigned length );
+int DPMI_FreeDOSMemory( long descriptor );
+int DPMI_LockMemory( void *address, unsigned length );
+int DPMI_LockMemoryRegion( void *start, void *end );
+int DPMI_UnlockMemory( void *address, unsigned length );
+int DPMI_UnlockMemoryRegion( void *start, void *end );
+
+#define DPMI_Lock( variable ) \
+ ( DPMI_LockMemory( (void *) &( variable ), sizeof( variable ) ) )
+
+#define DPMI_Unlock( variable ) \
+ ( DPMI_UnlockMemory( (void *) &( variable ), sizeof( variable ) ) )
+
+#ifdef PLAT_DOS
+#pragma aux DPMI_GetDOSMemory = \
+ "mov eax, 0100h", \
+ "add ebx, 15", \
+ "shr ebx, 4", \
+ "int 31h", \
+ "jc DPMI_Exit", \
+ "movzx eax, ax", \
+ "shl eax, 4", \
+ "mov [ esi ], eax", \
+ "mov [ edi ], edx", \
+ "sub eax, eax", \
+ "DPMI_Exit:", \
+ parm [ esi ] [ edi ] [ ebx ] modify exact [ eax ebx edx ];
+
+#pragma aux DPMI_FreeDOSMemory = \
+ "mov eax, 0101h", \
+ "int 31h", \
+ "jc DPMI_Exit", \
+ "sub eax, eax", \
+ "DPMI_Exit:", \
+ parm [ edx ] modify exact [ eax ];
+#endif
+
+#endif
--- /dev/null
+++ b/rott/audiolib/dsl.c
@@ -1,0 +1,235 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "dsl.h"
+#include "util.h"
+
+#include "SDL.h"
+#include "SDL_mixer.h"
+
+extern volatile int MV_MixPage;
+
+static int DSL_ErrorCode = DSL_Ok;
+
+static int mixer_initialized;
+
+static void ( *_CallBackFunc )( void );
+static volatile char *_BufferStart;
+static int _BufferSize;
+static int _NumDivisions;
+static int _SampleRate;
+static int _remainder;
+
+static Mix_Chunk *blank;
+static unsigned char *blank_buf;
+
+/*
+possible todo ideas: cache sdl/sdl mixer error messages.
+*/
+
+char *DSL_ErrorString( int ErrorNumber )
+{
+ char *ErrorString;
+
+ switch (ErrorNumber) {
+ case DSL_Warning:
+ case DSL_Error:
+ ErrorString = DSL_ErrorString(DSL_ErrorCode);
+ break;
+
+ case DSL_Ok:
+ ErrorString = "SDL Driver ok.";
+ break;
+
+ case DSL_SDLInitFailure:
+ ErrorString = "SDL Audio initialization failed.";
+ break;
+
+ case DSL_MixerActive:
+ ErrorString = "SDL Mixer already initialized.";
+ break;
+
+ case DSL_MixerInitFailure:
+ ErrorString = "SDL Mixer initialization failed.";
+ break;
+
+ default:
+ ErrorString = "Unknown SDL Driver error.";
+ break;
+ }
+
+ return ErrorString;
+}
+
+static void DSL_SetErrorCode(int ErrorCode)
+{
+ DSL_ErrorCode = ErrorCode;
+}
+
+int DSL_Init( void )
+{
+ DSL_SetErrorCode(DSL_Ok);
+
+ if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
+ DSL_SetErrorCode(DSL_SDLInitFailure);
+
+ return DSL_Error;
+ }
+
+ return DSL_Ok;
+}
+
+void DSL_Shutdown( void )
+{
+ DSL_StopPlayback();
+}
+
+static void mixer_callback(int chan, void *stream, int len, void *udata)
+{
+ Uint8 *stptr;
+ Uint8 *fxptr;
+ int copysize;
+
+ /* len should equal _BufferSize, else this is screwed up */
+
+ stptr = (Uint8 *)stream;
+
+ if (_remainder > 0) {
+ copysize = min(len, _remainder);
+
+ fxptr = (Uint8 *)(&_BufferStart[MV_MixPage *
+ _BufferSize]);
+
+ memcpy(stptr, fxptr+(_BufferSize-_remainder), copysize);
+
+ len -= copysize;
+ _remainder -= copysize;
+
+ stptr += copysize;
+ }
+
+ while (len > 0) {
+ /* new buffer */
+
+ _CallBackFunc();
+
+ fxptr = (Uint8 *)(&_BufferStart[MV_MixPage *
+ _BufferSize]);
+
+ copysize = min(len, _BufferSize);
+
+ memcpy(stptr, fxptr, copysize);
+
+ len -= copysize;
+
+ stptr += copysize;
+ }
+
+ _remainder = len;
+}
+
+int DSL_BeginBufferedPlayback( char *BufferStart,
+ int BufferSize, int NumDivisions, unsigned SampleRate,
+ int MixMode, void ( *CallBackFunc )( void ) )
+{
+ Uint16 format;
+ Uint8 *tmp;
+ int channels;
+ int chunksize;
+
+ if (mixer_initialized) {
+ DSL_SetErrorCode(DSL_MixerActive);
+
+ return DSL_Error;
+ }
+
+ _CallBackFunc = CallBackFunc;
+ _BufferStart = BufferStart;
+ _BufferSize = (BufferSize / NumDivisions);
+ _NumDivisions = NumDivisions;
+ _SampleRate = SampleRate;
+
+ _remainder = 0;
+
+ format = (MixMode & SIXTEEN_BIT) ? AUDIO_S16SYS : AUDIO_U8;
+ channels = (MixMode & STEREO) ? 2 : 1;
+
+/*
+ 23ms is typically ideal (11025,22050,44100)
+ 46ms isn't bad
+*/
+
+ chunksize = 512;
+
+ if (SampleRate >= 16000) chunksize *= 2;
+ if (SampleRate >= 32000) chunksize *= 2;
+
+/*
+// SDL mixer does this already
+ if (MixMode & SIXTEEN_BIT) chunksize *= 2;
+ if (MixMode & STEREO) chunksize *= 2;
+*/
+
+ if (Mix_OpenAudio(SampleRate, format, channels, chunksize) < 0) {
+ DSL_SetErrorCode(DSL_MixerInitFailure);
+
+ return DSL_Error;
+ }
+
+/*
+ Mix_SetPostMix(mixer_callback, NULL);
+*/
+ /* have to use a channel because postmix will overwrite the music... */
+ Mix_RegisterEffect(0, mixer_callback, NULL, NULL);
+
+ /* create a dummy sample just to allocate that channel */
+ blank_buf = (Uint8 *)malloc(4096);
+ memset(blank_buf, 0, 4096);
+
+ blank = Mix_QuickLoad_RAW(blank_buf, 4096);
+
+ Mix_PlayChannel(0, blank, -1);
+
+ mixer_initialized = 1;
+
+ return DSL_Ok;
+}
+
+void DSL_StopPlayback( void )
+{
+ if (mixer_initialized) {
+ Mix_HaltChannel(0);
+ }
+
+ if (blank != NULL) {
+ Mix_FreeChunk(blank);
+ }
+
+ blank = NULL;
+
+ if (blank_buf != NULL) {
+ free(blank_buf);
+ }
+
+ blank_buf = NULL;
+
+ if (mixer_initialized) {
+ Mix_CloseAudio();
+ }
+
+ mixer_initialized = 0;
+}
+
+unsigned DSL_GetPlaybackRate( void )
+{
+ return _SampleRate;
+}
+
+unsigned long DisableInterrupts( void )
+{
+ return 0;
+}
+
+void RestoreInterrupts( unsigned long flags )
+{
+}
--- /dev/null
+++ b/rott/audiolib/dsl.h
@@ -1,0 +1,28 @@
+#ifndef AUDIOLIB__DSL_H
+#define AUDIOLIB__DSL_H
+
+#define MONO_8BIT 0
+#define STEREO 1
+#define SIXTEEN_BIT 2
+#define STEREO_16BIT ( STEREO | SIXTEEN_BIT )
+
+enum DSL_ERRORS
+ {
+ DSL_Warning = -2,
+ DSL_Error = -1,
+ DSL_Ok = 0,
+ DSL_SDLInitFailure,
+ DSL_MixerActive,
+ DSL_MixerInitFailure
+ };
+
+char *DSL_ErrorString( int ErrorNumber );
+int DSL_Init( void );
+void DSL_StopPlayback( void );
+unsigned DSL_GetPlaybackRate( void );
+int DSL_BeginBufferedPlayback( char *BufferStart,
+ int BufferSize, int NumDivisions, unsigned SampleRate,
+ int MixMode, void ( *CallBackFunc )( void ) );
+void DSL_Shutdown( void );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/fx_man.c
@@ -1,0 +1,1376 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: FX_MAN.C
+
+ author: James R. Dose
+ date: March 17, 1994
+
+ Device independant sound effect routines.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "sndcards.h"
+#include "multivoc.h"
+
+#ifdef PLAT_DOS
+#include "blaster.h"
+#include "pas16.h"
+#include "sndscape.h"
+#include "guswave.h"
+#include "sndsrc.h"
+#else
+#include "dsl.h"
+#endif
+
+#include "ll_man.h"
+#include "user.h"
+#include "fx_man.h"
+
+#define TRUE ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+static unsigned FX_MixRate;
+
+int FX_SoundDevice = -1;
+int FX_ErrorCode = FX_Ok;
+int FX_Installed = FALSE;
+
+#define FX_SetErrorCode( status ) \
+ FX_ErrorCode = ( status );
+
+/*---------------------------------------------------------------------
+ Function: FX_ErrorString
+
+ Returns a pointer to the error message associated with an error
+ number. A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *FX_ErrorString
+ (
+ int ErrorNumber
+ )
+
+ {
+ char *ErrorString;
+
+ switch( ErrorNumber )
+ {
+ case FX_Warning :
+ case FX_Error :
+ ErrorString = FX_ErrorString( FX_ErrorCode );
+ break;
+
+ case FX_Ok :
+ ErrorString = "Fx ok.";
+ break;
+
+ case FX_ASSVersion :
+ ErrorString = "Apogee Sound System Version " ASS_VERSION_STRING " "
+ "Programmed by Jim Dose\n"
+ "(c) Copyright 1995 James R. Dose. All Rights Reserved.\n";
+ break;
+
+#ifdef PLAT_DOS
+ case FX_BlasterError :
+ ErrorString = BLASTER_ErrorString( BLASTER_Error );
+ break;
+#endif
+
+ case FX_SoundCardError :
+#ifdef PLAT_DOS
+ switch( FX_SoundDevice )
+ {
+ case SoundBlaster :
+ case Awe32 :
+ ErrorString = BLASTER_ErrorString( BLASTER_Error );
+ break;
+
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ ErrorString = PAS_ErrorString( PAS_Error );
+ break;
+
+ case SoundScape :
+ ErrorString = SOUNDSCAPE_ErrorString( SOUNDSCAPE_Error );
+ break;
+
+ case UltraSound :
+ ErrorString = GUSWAVE_ErrorString( GUSWAVE_Error );
+ break;
+
+ case SoundSource :
+ case TandySoundSource :
+ ErrorString = SS_ErrorString( SS_Error );
+ break;
+ }
+#else
+ ErrorString = DSL_ErrorString( DSL_Error );
+#endif
+ break;
+
+ case FX_InvalidCard :
+ ErrorString = "Invalid Sound Fx device.";
+ break;
+
+ case FX_MultiVocError :
+ ErrorString = MV_ErrorString( MV_Error );
+ break;
+
+ case FX_DPMI_Error :
+ ErrorString = "DPMI Error in FX_MAN.";
+ break;
+
+ default :
+ ErrorString = "Unknown Fx error code.";
+ break;
+ }
+
+ return( ErrorString );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_SetupCard
+
+ Sets the configuration of a sound device.
+---------------------------------------------------------------------*/
+
+int FX_SetupCard
+ (
+ int SoundCard,
+ fx_device *device
+ )
+
+ {
+ int status;
+ int DeviceStatus;
+
+ if ( USER_CheckParameter( "ASSVER" ) )
+ {
+ FX_SetErrorCode( FX_ASSVersion );
+ return( FX_Error );
+ }
+
+ FX_SoundDevice = SoundCard;
+
+ status = FX_Ok;
+ FX_SetErrorCode( FX_Ok );
+
+#ifdef PLAT_DOS
+ switch( SoundCard )
+ {
+ case SoundBlaster :
+ case Awe32 :
+ DeviceStatus = BLASTER_Init();
+ if ( DeviceStatus != BLASTER_Ok )
+ {
+ FX_SetErrorCode( FX_SoundCardError );
+ status = FX_Error;
+ break;
+ }
+
+ device->MaxVoices = 32;
+ BLASTER_GetCardInfo( &device->MaxSampleBits, &device->MaxChannels );
+ break;
+
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ DeviceStatus = PAS_Init();
+ if ( DeviceStatus != PAS_Ok )
+ {
+ FX_SetErrorCode( FX_SoundCardError );
+ status = FX_Error;
+ break;
+ }
+
+ device->MaxVoices = 32;
+ PAS_GetCardInfo( &device->MaxSampleBits, &device->MaxChannels );
+ break;
+
+ case GenMidi :
+ case SoundCanvas :
+ case WaveBlaster :
+ device->MaxVoices = 0;
+ device->MaxSampleBits = 0;
+ device->MaxChannels = 0;
+ break;
+
+ case SoundScape :
+ device->MaxVoices = 32;
+ DeviceStatus = SOUNDSCAPE_GetCardInfo( &device->MaxSampleBits,
+ &device->MaxChannels );
+ if ( DeviceStatus != SOUNDSCAPE_Ok )
+ {
+ FX_SetErrorCode( FX_SoundCardError );
+ status = FX_Error;
+ }
+ break;
+
+ case UltraSound :
+ if ( GUSWAVE_Init( 8 ) != GUSWAVE_Ok )
+ {
+ FX_SetErrorCode( FX_SoundCardError );
+ status = FX_Error;
+ break;
+ }
+
+ device->MaxVoices = 8;
+ device->MaxSampleBits = 0;
+ device->MaxChannels = 0;
+ break;
+
+ case SoundSource :
+ case TandySoundSource :
+ DeviceStatus = SS_Init( SoundCard );
+ if ( DeviceStatus != SS_Ok )
+ {
+ FX_SetErrorCode( FX_SoundCardError );
+ status = FX_Error;
+ break;
+ }
+ SS_Shutdown();
+ device->MaxVoices = 32;
+ device->MaxSampleBits = 8;
+ device->MaxChannels = 1;
+ break;
+ default :
+ FX_SetErrorCode( FX_InvalidCard );
+ status = FX_Error;
+ }
+#else
+ DeviceStatus = DSL_Init();
+ if ( DeviceStatus != DSL_Ok )
+ {
+ FX_SetErrorCode( FX_SoundCardError );
+ status = FX_Error;
+ }
+ else
+ {
+ device->MaxVoices = 32;
+ device->MaxSampleBits = 0;
+ device->MaxChannels = 0;
+ }
+#endif
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_GetBlasterSettings
+
+ Returns the current BLASTER environment variable settings.
+---------------------------------------------------------------------*/
+
+int FX_GetBlasterSettings
+ (
+ fx_blaster_config *blaster
+ )
+
+ {
+#ifdef PLAT_DOS
+ int status;
+ BLASTER_CONFIG Blaster;
+
+ FX_SetErrorCode( FX_Ok );
+
+ status = BLASTER_GetEnv( &Blaster );
+ if ( status != BLASTER_Ok )
+ {
+ FX_SetErrorCode( FX_BlasterError );
+ return( FX_Error );
+ }
+
+ blaster->Type = Blaster.Type;
+ blaster->Address = Blaster.Address;
+ blaster->Interrupt = Blaster.Interrupt;
+ blaster->Dma8 = Blaster.Dma8;
+ blaster->Dma16 = Blaster.Dma16;
+ blaster->Midi = Blaster.Midi;
+ blaster->Emu = Blaster.Emu;
+#endif
+
+ return( FX_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_SetupSoundBlaster
+
+ Handles manual setup of the Sound Blaster information.
+---------------------------------------------------------------------*/
+
+int FX_SetupSoundBlaster
+ (
+ fx_blaster_config blaster,
+ int *MaxVoices,
+ int *MaxSampleBits,
+ int *MaxChannels
+ )
+
+ {
+#ifdef PLAT_DOS
+ int DeviceStatus;
+ BLASTER_CONFIG Blaster;
+
+ FX_SetErrorCode( FX_Ok );
+
+ FX_SoundDevice = SoundBlaster;
+
+ Blaster.Type = blaster.Type;
+ Blaster.Address = blaster.Address;
+ Blaster.Interrupt = blaster.Interrupt;
+ Blaster.Dma8 = blaster.Dma8;
+ Blaster.Dma16 = blaster.Dma16;
+ Blaster.Midi = blaster.Midi;
+ Blaster.Emu = blaster.Emu;
+
+ BLASTER_SetCardSettings( Blaster );
+
+ DeviceStatus = BLASTER_Init();
+ if ( DeviceStatus != BLASTER_Ok )
+ {
+ FX_SetErrorCode( FX_SoundCardError );
+ return( FX_Error );
+ }
+
+ *MaxVoices = 8;
+ BLASTER_GetCardInfo( MaxSampleBits, MaxChannels );
+#endif
+
+ return( FX_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_Init
+
+ Selects which sound device to use.
+---------------------------------------------------------------------*/
+
+int FX_Init
+ (
+ int SoundCard,
+ int numvoices,
+ int numchannels,
+ int samplebits,
+ unsigned mixrate
+ )
+
+ {
+ int status;
+ int devicestatus;
+
+ if ( FX_Installed )
+ {
+ FX_Shutdown();
+ }
+
+ if ( USER_CheckParameter( "ASSVER" ) )
+ {
+ FX_SetErrorCode( FX_ASSVersion );
+ return( FX_Error );
+ }
+
+ status = LL_LockMemory();
+ if ( status != LL_Ok )
+ {
+ FX_SetErrorCode( FX_DPMI_Error );
+ return( FX_Error );
+ }
+
+ FX_MixRate = mixrate;
+
+ status = FX_Ok;
+ FX_SoundDevice = SoundCard;
+ switch( SoundCard )
+ {
+ case SoundBlaster :
+ case Awe32 :
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ case SoundScape :
+ case SoundSource :
+ case TandySoundSource :
+ case UltraSound :
+ devicestatus = MV_Init( SoundCard, FX_MixRate, numvoices,
+ numchannels, samplebits );
+ if ( devicestatus != MV_Ok )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ status = FX_Error;
+ }
+ break;
+
+ default :
+ FX_SetErrorCode( FX_InvalidCard );
+ status = FX_Error;
+ }
+
+ if ( status != FX_Ok )
+ {
+ LL_UnlockMemory();
+ }
+ else
+ {
+ FX_Installed = TRUE;
+ }
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_Shutdown
+
+ Terminates use of sound device.
+---------------------------------------------------------------------*/
+
+int FX_Shutdown
+ (
+ void
+ )
+
+ {
+ int status;
+
+ if ( !FX_Installed )
+ {
+ return( FX_Ok );
+ }
+
+ status = FX_Ok;
+ switch( FX_SoundDevice )
+ {
+ case SoundBlaster :
+ case Awe32 :
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ case SoundScape :
+ case SoundSource :
+ case TandySoundSource :
+ case UltraSound :
+ status = MV_Shutdown();
+ if ( status != MV_Ok )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ status = FX_Error;
+ }
+ break;
+
+ default :
+ FX_SetErrorCode( FX_InvalidCard );
+ status = FX_Error;
+ }
+
+ FX_Installed = FALSE;
+ LL_UnlockMemory();
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_SetCallback
+
+ Sets the function to call when a voice is done.
+---------------------------------------------------------------------*/
+
+int FX_SetCallBack
+ (
+ void ( *function )( unsigned long )
+ )
+
+ {
+ int status;
+
+ status = FX_Ok;
+
+ switch( FX_SoundDevice )
+ {
+ case SoundBlaster :
+ case Awe32 :
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ case SoundScape :
+ case SoundSource :
+ case TandySoundSource :
+ case UltraSound :
+ MV_SetCallBack( function );
+ break;
+
+ default :
+ FX_SetErrorCode( FX_InvalidCard );
+ status = FX_Error;
+ }
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_SetVolume
+
+ Sets the volume of the current sound device.
+---------------------------------------------------------------------*/
+
+void FX_SetVolume
+ (
+ int volume
+ )
+
+ {
+ int status;
+
+#ifdef PLAT_DOS
+ switch( FX_SoundDevice )
+ {
+ case SoundBlaster :
+ case Awe32 :
+ if ( BLASTER_CardHasMixer() )
+ {
+ BLASTER_SetVoiceVolume( volume );
+ }
+ else
+ {
+ MV_SetVolume( volume );
+ }
+ break;
+
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ status = PAS_SetPCMVolume( volume );
+ if ( status != PAS_Ok )
+ {
+ MV_SetVolume( volume );
+ }
+ break;
+
+ case GenMidi :
+ case SoundCanvas :
+ case WaveBlaster :
+ break;
+
+ case SoundScape :
+ MV_SetVolume( volume );
+ break;
+
+ case UltraSound :
+ GUSWAVE_SetVolume( volume );
+ break;
+
+ case SoundSource :
+ case TandySoundSource :
+ MV_SetVolume( volume );
+ break;
+ }
+#else
+ MV_SetVolume( volume );
+#endif
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_GetVolume
+
+ Returns the volume of the current sound device.
+---------------------------------------------------------------------*/
+
+int FX_GetVolume
+ (
+ void
+ )
+
+ {
+ int volume;
+
+#ifdef PLAT_DOS
+ switch( FX_SoundDevice )
+ {
+ case SoundBlaster :
+ case Awe32 :
+ if ( BLASTER_CardHasMixer() )
+ {
+ volume = BLASTER_GetVoiceVolume();
+ }
+ else
+ {
+ volume = MV_GetVolume();
+ }
+ break;
+
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ volume = PAS_GetPCMVolume();
+ if ( volume == PAS_Error )
+ {
+ volume = MV_GetVolume();
+ }
+ break;
+
+ case GenMidi :
+ case SoundCanvas :
+ case WaveBlaster :
+ volume = 255;
+ break;
+
+ case SoundScape :
+ volume = MV_GetVolume();
+ break;
+
+ case UltraSound :
+ volume = GUSWAVE_GetVolume();
+ break;
+
+ case SoundSource :
+ case TandySoundSource :
+ volume = MV_GetVolume();
+ break;
+
+ default :
+ volume = 0;
+ }
+#else
+ volume = MV_GetVolume();
+#endif
+
+ return( volume );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_SetReverseStereo
+
+ Set the orientation of the left and right channels.
+---------------------------------------------------------------------*/
+
+void FX_SetReverseStereo
+ (
+ int setting
+ )
+
+ {
+ MV_SetReverseStereo( setting );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_GetReverseStereo
+
+ Returns the orientation of the left and right channels.
+---------------------------------------------------------------------*/
+
+int FX_GetReverseStereo
+ (
+ void
+ )
+
+ {
+ return MV_GetReverseStereo();
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_SetReverb
+
+ Sets the reverb level.
+---------------------------------------------------------------------*/
+
+void FX_SetReverb
+ (
+ int reverb
+ )
+
+ {
+ MV_SetReverb( reverb );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_SetFastReverb
+
+ Sets the reverb level.
+---------------------------------------------------------------------*/
+
+void FX_SetFastReverb
+ (
+ int reverb
+ )
+
+ {
+ MV_SetFastReverb( reverb );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_GetMaxReverbDelay
+
+ Returns the maximum delay time for reverb.
+---------------------------------------------------------------------*/
+
+int FX_GetMaxReverbDelay
+ (
+ void
+ )
+
+ {
+ return MV_GetMaxReverbDelay();
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_GetReverbDelay
+
+ Returns the current delay time for reverb.
+---------------------------------------------------------------------*/
+
+int FX_GetReverbDelay
+ (
+ void
+ )
+
+ {
+ return MV_GetReverbDelay();
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_SetReverbDelay
+
+ Sets the delay level of reverb to add to mix.
+---------------------------------------------------------------------*/
+
+void FX_SetReverbDelay
+ (
+ int delay
+ )
+
+ {
+ MV_SetReverbDelay( delay );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_VoiceAvailable
+
+ Checks if a voice can be play at the specified priority.
+---------------------------------------------------------------------*/
+
+int FX_VoiceAvailable
+ (
+ int priority
+ )
+
+ {
+ return MV_VoiceAvailable( priority );
+ }
+
+/*---------------------------------------------------------------------
+ Function: FX_EndLooping
+
+ Stops the voice associated with the specified handle from looping
+ without stoping the sound.
+---------------------------------------------------------------------*/
+
+int FX_EndLooping
+ (
+ int handle
+ )
+
+ {
+ int status;
+
+ status = MV_EndLooping( handle );
+ if ( status == MV_Error )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ status = FX_Warning;
+ }
+
+ return( status );
+ }
+
+/*---------------------------------------------------------------------
+ Function: FX_SetPan
+
+ Sets the stereo and mono volume level of the voice associated
+ with the specified handle.
+---------------------------------------------------------------------*/
+
+int FX_SetPan
+ (
+ int handle,
+ int vol,
+ int left,
+ int right
+ )
+
+ {
+ int status;
+
+ status = MV_SetPan( handle, vol, left, right );
+ if ( status == MV_Error )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ status = FX_Warning;
+ }
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_SetPitch
+
+ Sets the pitch of the voice associated with the specified handle.
+---------------------------------------------------------------------*/
+
+int FX_SetPitch
+ (
+ int handle,
+ int pitchoffset
+ )
+
+ {
+ int status;
+
+ status = MV_SetPitch( handle, pitchoffset );
+ if ( status == MV_Error )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ status = FX_Warning;
+ }
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_SetFrequency
+
+ Sets the frequency of the voice associated with the specified handle.
+---------------------------------------------------------------------*/
+
+int FX_SetFrequency
+ (
+ int handle,
+ int frequency
+ )
+
+ {
+ int status;
+
+ status = MV_SetFrequency( handle, frequency );
+ if ( status == MV_Error )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ status = FX_Warning;
+ }
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_PlayVOC
+
+ Begin playback of sound data with the given volume and priority.
+---------------------------------------------------------------------*/
+
+int FX_PlayVOC
+ (
+ char *ptr,
+ int pitchoffset,
+ int vol,
+ int left,
+ int right,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ int handle;
+
+ handle = MV_PlayVOC( ptr, pitchoffset, vol, left, right,
+ priority, callbackval );
+ if ( handle < MV_Ok )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ handle = FX_Warning;
+ }
+
+ return( handle );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_PlayLoopedVOC
+
+ Begin playback of sound data with the given volume and priority.
+---------------------------------------------------------------------*/
+
+int FX_PlayLoopedVOC
+ (
+ char *ptr,
+ long loopstart,
+ long loopend,
+ int pitchoffset,
+ int vol,
+ int left,
+ int right,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ int handle;
+
+ handle = MV_PlayLoopedVOC( ptr, loopstart, loopend, pitchoffset,
+ vol, left, right, priority, callbackval );
+ if ( handle < MV_Ok )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ handle = FX_Warning;
+ }
+
+ return( handle );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_PlayWAV
+
+ Begin playback of sound data with the given volume and priority.
+---------------------------------------------------------------------*/
+
+int FX_PlayWAV
+ (
+ char *ptr,
+ int pitchoffset,
+ int vol,
+ int left,
+ int right,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ int handle;
+
+ handle = MV_PlayWAV( ptr, pitchoffset, vol, left, right,
+ priority, callbackval );
+ if ( handle < MV_Ok )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ handle = FX_Warning;
+ }
+
+ return( handle );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_PlayWAV
+
+ Begin playback of sound data with the given volume and priority.
+---------------------------------------------------------------------*/
+
+int FX_PlayLoopedWAV
+ (
+ char *ptr,
+ long loopstart,
+ long loopend,
+ int pitchoffset,
+ int vol,
+ int left,
+ int right,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ int handle;
+
+ handle = MV_PlayLoopedWAV( ptr, loopstart, loopend,
+ pitchoffset, vol, left, right, priority, callbackval );
+ if ( handle < MV_Ok )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ handle = FX_Warning;
+ }
+
+ return( handle );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_PlayVOC3D
+
+ Begin playback of sound data at specified angle and distance
+ from listener.
+---------------------------------------------------------------------*/
+
+int FX_PlayVOC3D
+ (
+ char *ptr,
+ int pitchoffset,
+ int angle,
+ int distance,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ int handle;
+
+ handle = MV_PlayVOC3D( ptr, pitchoffset, angle, distance,
+ priority, callbackval );
+ if ( handle < MV_Ok )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ handle = FX_Warning;
+ }
+
+ return( handle );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_PlayWAV3D
+
+ Begin playback of sound data at specified angle and distance
+ from listener.
+---------------------------------------------------------------------*/
+
+int FX_PlayWAV3D
+ (
+ char *ptr,
+ int pitchoffset,
+ int angle,
+ int distance,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ int handle;
+
+ handle = MV_PlayWAV3D( ptr, pitchoffset, angle, distance,
+ priority, callbackval );
+ if ( handle < MV_Ok )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ handle = FX_Warning;
+ }
+
+ return( handle );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_PlayRaw
+
+ Begin playback of raw sound data with the given volume and priority.
+---------------------------------------------------------------------*/
+
+int FX_PlayRaw
+ (
+ char *ptr,
+ unsigned long length,
+ unsigned rate,
+ int pitchoffset,
+ int vol,
+ int left,
+ int right,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ int handle;
+
+ handle = MV_PlayRaw( ptr, length, rate, pitchoffset,
+ vol, left, right, priority, callbackval );
+ if ( handle < MV_Ok )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ handle = FX_Warning;
+ }
+
+ return( handle );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_PlayLoopedRaw
+
+ Begin playback of raw sound data with the given volume and priority.
+---------------------------------------------------------------------*/
+
+int FX_PlayLoopedRaw
+ (
+ char *ptr,
+ unsigned long length,
+ char *loopstart,
+ char *loopend,
+ unsigned rate,
+ int pitchoffset,
+ int vol,
+ int left,
+ int right,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ int handle;
+
+ handle = MV_PlayLoopedRaw( ptr, length, loopstart, loopend,
+ rate, pitchoffset, vol, left, right, priority, callbackval );
+ if ( handle < MV_Ok )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ handle = FX_Warning;
+ }
+
+ return( handle );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_Pan3D
+
+ Set the angle and distance from the listener of the voice associated
+ with the specified handle.
+---------------------------------------------------------------------*/
+
+int FX_Pan3D
+ (
+ int handle,
+ int angle,
+ int distance
+ )
+
+ {
+ int status;
+
+ status = MV_Pan3D( handle, angle, distance );
+ if ( status != MV_Ok )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ status = FX_Warning;
+ }
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_SoundActive
+
+ Tests if the specified sound is currently playing.
+---------------------------------------------------------------------*/
+
+int FX_SoundActive
+ (
+ int handle
+ )
+
+ {
+ return( MV_VoicePlaying( handle ) );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_SoundsPlaying
+
+ Reports the number of voices playing.
+---------------------------------------------------------------------*/
+
+int FX_SoundsPlaying
+ (
+ void
+ )
+
+ {
+ return( MV_VoicesPlaying() );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_StopSound
+
+ Halts playback of a specific voice
+---------------------------------------------------------------------*/
+
+int FX_StopSound
+ (
+ int handle
+ )
+
+ {
+ int status;
+
+ status = MV_Kill( handle );
+ if ( status != MV_Ok )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ return( FX_Warning );
+ }
+
+ return( FX_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_StopAllSounds
+
+ Halts playback of all sounds.
+---------------------------------------------------------------------*/
+
+int FX_StopAllSounds
+ (
+ void
+ )
+
+ {
+ int status;
+
+ status = MV_KillAllVoices();
+ if ( status != MV_Ok )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ return( FX_Warning );
+ }
+
+ return( FX_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_StartDemandFeedPlayback
+
+ Plays a digitized sound from a user controlled buffering system.
+---------------------------------------------------------------------*/
+
+int FX_StartDemandFeedPlayback
+ (
+ void ( *function )( char **ptr, unsigned long *length ),
+ int rate,
+ int pitchoffset,
+ int vol,
+ int left,
+ int right,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ int handle;
+
+ handle = MV_StartDemandFeedPlayback( function, rate,
+ pitchoffset, vol, left, right, priority, callbackval );
+ if ( handle < MV_Ok )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ handle = FX_Warning;
+ }
+
+ return( handle );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_StartRecording
+
+ Starts the sound recording engine.
+---------------------------------------------------------------------*/
+
+int FX_StartRecording
+ (
+ int MixRate,
+ void ( *function )( char *ptr, int length )
+ )
+
+ {
+ int status;
+
+#ifdef PLAT_DOS
+ switch( FX_SoundDevice )
+ {
+ case SoundBlaster :
+ case Awe32 :
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ status = MV_StartRecording( MixRate, function );
+ if ( status != MV_Ok )
+ {
+ FX_SetErrorCode( FX_MultiVocError );
+ status = FX_Warning;
+ }
+ else
+ {
+ status = FX_Ok;
+ }
+ break;
+
+ default :
+ FX_SetErrorCode( FX_InvalidCard );
+ status = FX_Warning;
+ break;
+ }
+#else
+ FX_SetErrorCode( FX_InvalidCard );
+ status = FX_Warning;
+#endif
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: FX_StopRecord
+
+ Stops the sound record engine.
+---------------------------------------------------------------------*/
+
+void FX_StopRecord
+ (
+ void
+ )
+
+ {
+#ifdef PLAT_DOS
+ // Stop sound playback
+ switch( FX_SoundDevice )
+ {
+ case SoundBlaster :
+ case Awe32 :
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ MV_StopRecord();
+ break;
+ }
+#endif
+ }
--- /dev/null
+++ b/rott/audiolib/fx_man.h
@@ -1,0 +1,135 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: FX_MAN.H
+
+ author: James R. Dose
+ date: March 17, 1994
+
+ Public header for FX_MAN.C
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __FX_MAN_H
+#define __FX_MAN_H
+
+#include "sndcards.h"
+
+typedef struct
+ {
+ int MaxVoices;
+ int MaxSampleBits;
+ int MaxChannels;
+ } fx_device;
+
+#define MonoFx 1
+#define StereoFx 2
+
+typedef struct
+ {
+ unsigned long Address;
+ unsigned long Type;
+ unsigned long Interrupt;
+ unsigned long Dma8;
+ unsigned long Dma16;
+ unsigned long Midi;
+ unsigned long Emu;
+ } fx_blaster_config;
+
+enum FX_ERRORS
+ {
+ FX_Warning = -2,
+ FX_Error = -1,
+ FX_Ok = 0,
+ FX_ASSVersion,
+ FX_BlasterError,
+ FX_SoundCardError,
+ FX_InvalidCard,
+ FX_MultiVocError,
+ FX_DPMI_Error
+ };
+
+enum fx_BLASTER_Types
+ {
+ fx_SB = 1,
+ fx_SBPro = 2,
+ fx_SB20 = 3,
+ fx_SBPro2 = 4,
+ fx_SB16 = 6
+ };
+
+
+char *FX_ErrorString( int ErrorNumber );
+int FX_SetupCard( int SoundCard, fx_device *device );
+int FX_GetBlasterSettings( fx_blaster_config *blaster );
+int FX_SetupSoundBlaster( fx_blaster_config blaster, int *MaxVoices, int *MaxSampleBits, int *MaxChannels );
+int FX_Init( int SoundCard, int numvoices, int numchannels, int samplebits, unsigned mixrate );
+int FX_Shutdown( void );
+int FX_SetCallBack( void ( *function )( unsigned long ) );
+void FX_SetVolume( int volume );
+int FX_GetVolume( void );
+
+void FX_SetReverseStereo( int setting );
+int FX_GetReverseStereo( void );
+void FX_SetReverb( int reverb );
+void FX_SetFastReverb( int reverb );
+int FX_GetMaxReverbDelay( void );
+int FX_GetReverbDelay( void );
+void FX_SetReverbDelay( int delay );
+
+int FX_VoiceAvailable( int priority );
+int FX_EndLooping( int handle );
+int FX_SetPan( int handle, int vol, int left, int right );
+int FX_SetPitch( int handle, int pitchoffset );
+int FX_SetFrequency( int handle, int frequency );
+
+int FX_PlayVOC( char *ptr, int pitchoffset, int vol, int left, int right,
+ int priority, unsigned long callbackval );
+int FX_PlayLoopedVOC( char *ptr, long loopstart, long loopend,
+ int pitchoffset, int vol, int left, int right, int priority,
+ unsigned long callbackval );
+int FX_PlayWAV( char *ptr, int pitchoffset, int vol, int left, int right,
+ int priority, unsigned long callbackval );
+int FX_PlayLoopedWAV( char *ptr, long loopstart, long loopend,
+ int pitchoffset, int vol, int left, int right, int priority,
+ unsigned long callbackval );
+int FX_PlayVOC3D( char *ptr, int pitchoffset, int angle, int distance,
+ int priority, unsigned long callbackval );
+int FX_PlayWAV3D( char *ptr, int pitchoffset, int angle, int distance,
+ int priority, unsigned long callbackval );
+int FX_PlayRaw( char *ptr, unsigned long length, unsigned rate,
+ int pitchoffset, int vol, int left, int right, int priority,
+ unsigned long callbackval );
+int FX_PlayLoopedRaw( char *ptr, unsigned long length, char *loopstart,
+ char *loopend, unsigned rate, int pitchoffset, int vol, int left,
+ int right, int priority, unsigned long callbackval );
+int FX_Pan3D( int handle, int angle, int distance );
+int FX_SoundActive( int handle );
+int FX_SoundsPlaying( void );
+int FX_StopSound( int handle );
+int FX_StopAllSounds( void );
+int FX_StartDemandFeedPlayback( void ( *function )( char **ptr, unsigned long *length ),
+ int rate, int pitchoffset, int vol, int left, int right,
+ int priority, unsigned long callbackval );
+int FX_StartRecording( int MixRate, void ( *function )( char *ptr, int length ) );
+void FX_StopRecord( void );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/gmtimbre.c
@@ -1,0 +1,290 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+typedef struct
+ {
+ unsigned char SAVEK[ 2 ];
+ unsigned char Level[ 2 ];
+ unsigned char Env1[ 2 ];
+ unsigned char Env2[ 2 ];
+ unsigned char Wave[ 2 ];
+ unsigned char Feedback;
+ signed char Transpose;
+ signed char Velocity;
+ } TIMBRE;
+
+TIMBRE ADLIB_TimbreBank[ 256 ] =
+ {
+ { { 33, 33 }, { 143, 6 }, { 242, 242 }, { 69, 118 }, { 0, 0 }, 8, 0 },
+ { { 49, 33 }, { 75, 0 }, { 242, 242 }, { 84, 86 }, { 0, 0 }, 8, 0 },
+ { { 49, 33 }, { 73, 0 }, { 242, 242 }, { 85, 118 }, { 0, 0 }, 8, 0 },
+ { { 177, 97 }, { 14, 0 }, { 242, 243 }, { 59, 11 }, { 0, 0 }, 6, 0 },
+ { { 1, 33 }, { 87, 0 }, { 241, 241 }, { 56, 40 }, { 0, 0 }, 0, 0 },
+ { { 1, 33 }, { 147, 0 }, { 241, 241 }, { 56, 40 }, { 0, 0 }, 0, 0 },
+ { { 33, 54 }, { 128, 14 }, { 162, 241 }, { 1, 213 }, { 0, 0 }, 8, 0 },
+ { { 1, 1 }, { 146, 0 }, { 194, 194 }, { 168, 88 }, { 0, 0 }, 10, 0 },
+ { { 12, 129 }, { 92, 0 }, { 246, 243 }, { 84, 181 }, { 0, 0 }, 0, 0 },
+ { { 7, 17 }, { 151, 128 }, { 246, 245 }, { 50, 17 }, { 0, 0 }, 2, 0 },
+ { { 23, 1 }, { 33, 0 }, { 86, 246 }, { 4, 4 }, { 0, 0 }, 2, 0 },
+ { { 24, 129 }, { 98, 0 }, { 243, 242 }, { 230, 246 }, { 0, 0 }, 0, 0 },
+ { { 24, 33 }, { 35, 0 }, { 247, 229 }, { 85, 216 }, { 0, 0 }, 0, 0 },
+ { { 21, 1 }, { 145, 0 }, { 246, 246 }, { 166, 230 }, { 0, 0 }, 4, 0 },
+ { { 69, 129 }, { 89, 128 }, { 211, 163 }, { 130, 227 }, { 0, 0 }, 12, 0 },
+ { { 3, 129 }, { 73, 128 }, { 116, 179 }, { 85, 5 }, { 1, 0 }, 4, 0 },
+ { { 113, 49 }, { 146, 0 }, { 246, 241 }, { 20, 7 }, { 0, 0 }, 2, 0 },
+ { { 114, 48 }, { 20, 0 }, { 199, 199 }, { 88, 8 }, { 0, 0 }, 2, 0 },
+ { { 112, 177 }, { 68, 0 }, { 170, 138 }, { 24, 8 }, { 0, 0 }, 4, 0 },
+ { { 35, 177 }, { 147, 0 }, { 151, 85 }, { 35, 20 }, { 1, 0 }, 4, 0 },
+ { { 97, 177 }, { 19, 128 }, { 151, 85 }, { 4, 4 }, { 1, 0 }, 0, 0 },
+ { { 36, 177 }, { 72, 0 }, { 152, 70 }, { 42, 26 }, { 1, 0 }, 12, 0 },
+ { { 97, 33 }, { 19, 0 }, { 145, 97 }, { 6, 7 }, { 1, 0 }, 10, 0 },
+ { { 33, 161 }, { 19, 137 }, { 113, 97 }, { 6, 7 }, { 0, 0 }, 6, 0 },
+ { { 2, 65 }, { 156, 128 }, { 243, 243 }, { 148, 200 }, { 1, 0 }, 12, 0 },
+ { { 3, 17 }, { 84, 0 }, { 243, 241 }, { 154, 231 }, { 1, 0 }, 12, 0 },
+ { { 35, 33 }, { 95, 0 }, { 241, 242 }, { 58, 248 }, { 0, 0 }, 0, 0 },
+ { { 3, 33 }, { 135, 128 }, { 246, 243 }, { 34, 243 }, { 1, 0 }, 6, 0 },
+ { { 3, 33 }, { 71, 0 }, { 249, 246 }, { 84, 58 }, { 0, 0 }, 0, 0 },
+ { { 35, 33 }, { 72, 0 }, { 149, 132 }, { 25, 25 }, { 1, 0 }, 8, 0 },
+ { { 35, 33 }, { 74, 0 }, { 149, 148 }, { 25, 25 }, { 1, 0 }, 8, 0 },
+ { { 9, 132 }, { 161, 128 }, { 32, 209 }, { 79, 248 }, { 0, 0 }, 8, 0 },
+ { { 33, 162 }, { 30, 0 }, { 148, 195 }, { 6, 166 }, { 0, 0 }, 2, 0 },
+ { { 49, 49 }, { 18, 0 }, { 241, 241 }, { 40, 24 }, { 0, 0 }, 10, 0 },
+ { { 49, 49 }, { 141, 0 }, { 241, 241 }, { 232, 120 }, { 0, 0 }, 10, 0 },
+ { { 49, 50 }, { 91, 0 }, { 81, 113 }, { 40, 72 }, { 0, 0 }, 12, 0 },
+ { { 1, 33 }, { 139, 64 }, { 161, 242 }, { 154, 223 }, { 0, 0 }, 8, 0 },
+ { { 1, 33 }, { 137, 64 }, { 161, 242 }, { 154, 223 }, { 0, 0 }, 8, 0 },
+ { { 49, 49 }, { 139, 0 }, { 244, 241 }, { 232, 120 }, { 0, 0 }, 10, 0 },
+ { { 49, 49 }, { 18, 0 }, { 241, 241 }, { 40, 24 }, { 0, 0 }, 10, 0 },
+ { { 49, 33 }, { 21, 0 }, { 221, 86 }, { 19, 38 }, { 1, 0 }, 8, 0 },
+ { { 49, 33 }, { 22, 0 }, { 221, 102 }, { 19, 6 }, { 1, 0 }, 8, 0 },
+ { { 113, 49 }, { 73, 0 }, { 209, 97 }, { 28, 12 }, { 1, 0 }, 8, 0 },
+ { { 33, 35 }, { 77, 128 }, { 113, 114 }, { 18, 6 }, { 1, 0 }, 2, 0 },
+ { { 241, 225 }, { 64, 0 }, { 241, 111 }, { 33, 22 }, { 1, 0 }, 2, 0 },
+ { { 2, 1 }, { 26, 128 }, { 245, 133 }, { 117, 53 }, { 1, 0 }, 0, 0 },
+ { { 2, 1 }, { 29, 128 }, { 245, 243 }, { 117, 244 }, { 1, 0 }, 0, 0 },
+ { { 16, 17 }, { 65, 0 }, { 245, 242 }, { 5, 195 }, { 1, 0 }, 2, 0 },
+ { { 33, 162 }, { 155, 1 }, { 177, 114 }, { 37, 8 }, { 1, 0 }, 14, 0 },
+ { { 161, 33 }, { 152, 0 }, { 127, 63 }, { 3, 7 }, { 1, 1 }, 0, 0 },
+ { { 161, 97 }, { 147, 0 }, { 193, 79 }, { 18, 5 }, { 0, 0 }, 10, 0 },
+ { { 33, 97 }, { 24, 0 }, { 193, 79 }, { 34, 5 }, { 0, 0 }, 12, 0 },
+ { { 49, 114 }, { 91, 131 }, { 244, 138 }, { 21, 5 }, { 0, 0 }, 0, 0 },
+ { { 161, 97 }, { 144, 0 }, { 116, 113 }, { 57, 103 }, { 0, 0 }, 0, 0 },
+ { { 113, 114 }, { 87, 0 }, { 84, 122 }, { 5, 5 }, { 0, 0 }, 12, 0 },
+ { { 144, 65 }, { 0, 0 }, { 84, 165 }, { 99, 69 }, { 0, 0 }, 8, 0 },
+ { { 33, 33 }, { 146, 1 }, { 133, 143 }, { 23, 9 }, { 0, 0 }, 12, 0 },
+ { { 33, 33 }, { 148, 5 }, { 117, 143 }, { 23, 9 }, { 0, 0 }, 12, 0 },
+ { { 33, 97 }, { 148, 0 }, { 118, 130 }, { 21, 55 }, { 0, 0 }, 12, 0 },
+ { { 49, 33 }, { 67, 0 }, { 158, 98 }, { 23, 44 }, { 1, 1 }, 2, 0 },
+ { { 33, 33 }, { 155, 0 }, { 97, 127 }, { 106, 10 }, { 0, 0 }, 2, 0 },
+ { { 97, 34 }, { 138, 6 }, { 117, 116 }, { 31, 15 }, { 0, 0 }, 8, 0 },
+ { { 161, 33 }, { 134, 13 }, { 114, 113 }, { 85, 24 }, { 1, 0 }, 0, 0 },
+ { { 33, 33 }, { 77, 0 }, { 84, 166 }, { 60, 28 }, { 0, 0 }, 8, 0 },
+ { { 49, 97 }, { 143, 0 }, { 147, 114 }, { 2, 11 }, { 1, 0 }, 8, 0 },
+ { { 49, 97 }, { 142, 0 }, { 147, 114 }, { 3, 9 }, { 1, 0 }, 8, 0 },
+ { { 49, 97 }, { 145, 0 }, { 147, 130 }, { 3, 9 }, { 1, 0 }, 10, 0 },
+ { { 49, 97 }, { 142, 0 }, { 147, 114 }, { 15, 15 }, { 1, 0 }, 10, 0 },
+ { { 33, 33 }, { 75, 0 }, { 170, 143 }, { 22, 10 }, { 1, 0 }, 8, 0 },
+ { { 49, 33 }, { 144, 0 }, { 126, 139 }, { 23, 12 }, { 1, 1 }, 6, 0 },
+ { { 49, 50 }, { 129, 0 }, { 117, 97 }, { 25, 25 }, { 1, 0 }, 0, 0 },
+ { { 50, 33 }, { 144, 0 }, { 155, 114 }, { 33, 23 }, { 0, 0 }, 4, 0 },
+ { { 225, 225 }, { 31, 0 }, { 133, 101 }, { 95, 26 }, { 0, 0 }, 0, 0 },
+ { { 225, 225 }, { 70, 0 }, { 136, 101 }, { 95, 26 }, { 0, 0 }, 0, 0 },
+ { { 161, 33 }, { 156, 0 }, { 117, 117 }, { 31, 10 }, { 0, 0 }, 2, 0 },
+ { { 49, 33 }, { 139, 0 }, { 132, 101 }, { 88, 26 }, { 0, 0 }, 0, 0 },
+ { { 225, 161 }, { 76, 0 }, { 102, 101 }, { 86, 38 }, { 0, 0 }, 0, 0 },
+ { { 98, 161 }, { 203, 0 }, { 118, 85 }, { 70, 54 }, { 0, 0 }, 0, 0 },
+ { { 98, 161 }, { 153, 0 }, { 87, 86 }, { 7, 7 }, { 0, 0 }, 11, 0 },
+ { { 98, 161 }, { 147, 0 }, { 119, 118 }, { 7, 7 }, { 0, 0 }, 11, 0 },
+ { { 34, 33 }, { 89, 0 }, { 255, 255 }, { 3, 15 }, { 2, 0 }, 0, 0 },
+ { { 33, 33 }, { 14, 0 }, { 255, 255 }, { 15, 15 }, { 1, 1 }, 0, 0 },
+ { { 34, 33 }, { 70, 128 }, { 134, 100 }, { 85, 24 }, { 0, 0 }, 0, 0 },
+ { { 33, 161 }, { 69, 0 }, { 102, 150 }, { 18, 10 }, { 0, 0 }, 0, 0 },
+ { { 33, 34 }, { 139, 0 }, { 146, 145 }, { 42, 42 }, { 1, 0 }, 0, 0 },
+ { { 162, 97 }, { 158, 64 }, { 223, 111 }, { 5, 7 }, { 0, 0 }, 2, 0 },
+ { { 32, 96 }, { 26, 0 }, { 239, 143 }, { 1, 6 }, { 0, 2 }, 0, 0 },
+ { { 33, 33 }, { 143, 128 }, { 241, 244 }, { 41, 9 }, { 0, 0 }, 10, 0 },
+ { { 119, 161 }, { 165, 0 }, { 83, 160 }, { 148, 5 }, { 0, 0 }, 2, 0 },
+ { { 97, 177 }, { 31, 128 }, { 168, 37 }, { 17, 3 }, { 0, 0 }, 10, 0 },
+ { { 97, 97 }, { 23, 0 }, { 145, 85 }, { 52, 22 }, { 0, 0 }, 12, 0 },
+ { { 113, 114 }, { 93, 0 }, { 84, 106 }, { 1, 3 }, { 0, 0 }, 0, 0 },
+ { { 33, 162 }, { 151, 0 }, { 33, 66 }, { 67, 53 }, { 0, 0 }, 8, 0 },
+ { { 161, 33 }, { 28, 0 }, { 161, 49 }, { 119, 71 }, { 1, 1 }, 0, 0 },
+ { { 33, 97 }, { 137, 3 }, { 17, 66 }, { 51, 37 }, { 0, 0 }, 10, 0 },
+ { { 161, 33 }, { 21, 0 }, { 17, 207 }, { 71, 7 }, { 1, 0 }, 0, 0 },
+ { { 58, 81 }, { 206, 0 }, { 248, 134 }, { 246, 2 }, { 0, 0 }, 2, 0 },
+ { { 33, 33 }, { 21, 0 }, { 33, 65 }, { 35, 19 }, { 1, 0 }, 0, 0 },
+ { { 6, 1 }, { 91, 0 }, { 116, 165 }, { 149, 114 }, { 0, 0 }, 0, 0 },
+ { { 34, 97 }, { 146, 131 }, { 177, 242 }, { 129, 38 }, { 0, 0 }, 12, 0 },
+ { { 65, 66 }, { 77, 0 }, { 241, 242 }, { 81, 245 }, { 1, 0 }, 0, 0 },
+ { { 97, 163 }, { 148, 128 }, { 17, 17 }, { 81, 19 }, { 1, 0 }, 6, 0 },
+ { { 97, 161 }, { 140, 128 }, { 17, 29 }, { 49, 3 }, { 0, 0 }, 6, 0 },
+ { { 164, 97 }, { 76, 0 }, { 243, 129 }, { 115, 35 }, { 1, 0 }, 4, 0 },
+ { { 2, 7 }, { 133, 3 }, { 210, 242 }, { 83, 246 }, { 0, 1 }, 0, 0 },
+ { { 17, 19 }, { 12, 128 }, { 163, 162 }, { 17, 229 }, { 1, 0 }, 0, 0 },
+ { { 17, 17 }, { 6, 0 }, { 246, 242 }, { 65, 230 }, { 1, 2 }, 4, 0 },
+ { { 147, 145 }, { 145, 0 }, { 212, 235 }, { 50, 17 }, { 0, 1 }, 8, 0 },
+ { { 4, 1 }, { 79, 0 }, { 250, 194 }, { 86, 5 }, { 0, 0 }, 12, 0 },
+ { { 33, 34 }, { 73, 0 }, { 124, 111 }, { 32, 12 }, { 0, 1 }, 6, 0 },
+ { { 49, 33 }, { 133, 0 }, { 221, 86 }, { 51, 22 }, { 1, 0 }, 10, 0 },
+ { { 32, 33 }, { 4, 129 }, { 218, 143 }, { 5, 11 }, { 2, 0 }, 6, 0 },
+ { { 5, 3 }, { 106, 128 }, { 241, 195 }, { 229, 229 }, { 0, 0 }, 6, 0 },
+ { { 7, 2 }, { 21, 0 }, { 236, 248 }, { 38, 22 }, { 0, 0 }, 10, 0 },
+ { { 5, 1 }, { 157, 0 }, { 103, 223 }, { 53, 5 }, { 0, 0 }, 8, 0 },
+ { { 24, 18 }, { 150, 0 }, { 250, 248 }, { 40, 229 }, { 0, 0 }, 10, 0 },
+ { { 16, 0 }, { 134, 3 }, { 168, 250 }, { 7, 3 }, { 0, 0 }, 6, 0 },
+ { { 17, 16 }, { 65, 3 }, { 248, 243 }, { 71, 3 }, { 2, 0 }, 4, 0 },
+ { { 1, 16 }, { 142, 0 }, { 241, 243 }, { 6, 2 }, { 2, 0 }, 14, 0 },
+ { { 14, 192 }, { 0, 0 }, { 31, 31 }, { 0, 255 }, { 0, 3 }, 14, 0 },
+ { { 6, 3 }, { 128, 136 }, { 248, 86 }, { 36, 132 }, { 0, 2 }, 14, 0 },
+ { { 14, 208 }, { 0, 5 }, { 248, 52 }, { 0, 4 }, { 0, 3 }, 14, 0 },
+ { { 14, 192 }, { 0, 0 }, { 246, 31 }, { 0, 2 }, { 0, 3 }, 14, 0 },
+ { { 213, 218 }, { 149, 64 }, { 55, 86 }, { 163, 55 }, { 0, 0 }, 0, 0 },
+ { { 53, 20 }, { 92, 8 }, { 178, 244 }, { 97, 21 }, { 2, 0 }, 10, 0 },
+ { { 14, 208 }, { 0, 0 }, { 246, 79 }, { 0, 245 }, { 0, 3 }, 14, 0 },
+ { { 38, 228 }, { 0, 0 }, { 255, 18 }, { 1, 22 }, { 0, 1 }, 14, 0 },
+ { { 0, 0 }, { 0, 0 }, { 243, 246 }, { 240, 201 }, { 0, 2 }, 14, 0 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 0, 0 }, { 0, 0 }, { 252, 250 }, { 5, 23 }, { 2, 0 }, 14, 52 },
+ { { 0, 1 }, { 2, 0 }, { 255, 255 }, { 7, 8 }, { 0, 0 }, 0, 48 },
+ { { 0, 0 }, { 0, 0 }, { 252, 250 }, { 5, 23 }, { 2, 0 }, 14, 58 },
+ { { 0, 0 }, { 0, 0 }, { 246, 246 }, { 12, 6 }, { 0, 0 }, 4, 60 },
+ { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 47 },
+ { { 0, 0 }, { 3, 0 }, { 248, 246 }, { 42, 69 }, { 0, 1 }, 4, 43 },
+ { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 49 },
+ { { 0, 0 }, { 3, 0 }, { 248, 246 }, { 42, 69 }, { 0, 1 }, 4, 43 },
+ { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 51 },
+ { { 0, 0 }, { 3, 0 }, { 248, 246 }, { 42, 69 }, { 0, 1 }, 4, 43 },
+ { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 54 },
+ { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 57 },
+ { { 0, 0 }, { 3, 0 }, { 248, 246 }, { 42, 69 }, { 0, 1 }, 4, 72 },
+ { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 60 },
+ { { 14, 208 }, { 0, 10 }, { 245, 159 }, { 48, 2 }, { 0, 0 }, 14, 76 },
+ { { 14, 7 }, { 10, 93 }, { 228, 245 }, { 228, 229 }, { 3, 1 }, 6, 84 },
+ { { 2, 5 }, { 3, 10 }, { 180, 151 }, { 4, 247 }, { 0, 0 }, 14, 36 },
+ { { 78, 158 }, { 0, 0 }, { 246, 159 }, { 0, 2 }, { 0, 3 }, 14, 76 },
+ { { 17, 16 }, { 69, 8 }, { 248, 243 }, { 55, 5 }, { 2, 0 }, 8, 84 },
+ { { 14, 208 }, { 0, 0 }, { 246, 159 }, { 0, 2 }, { 0, 3 }, 14, 83 },
+ { { 128, 16 }, { 0, 13 }, { 255, 255 }, { 3, 20 }, { 3, 0 }, 12, 84 },
+ { { 14, 7 }, { 8, 81 }, { 248, 244 }, { 66, 228 }, { 0, 3 }, 14, 24 },
+ { { 14, 208 }, { 0, 10 }, { 245, 159 }, { 48, 2 }, { 0, 0 }, 14, 77 },
+ { { 1, 2 }, { 0, 0 }, { 250, 200 }, { 191, 151 }, { 0, 0 }, 7, 60 },
+ { { 1, 1 }, { 81, 0 }, { 250, 250 }, { 135, 183 }, { 0, 0 }, 6, 65 },
+ { { 1, 2 }, { 84, 0 }, { 250, 248 }, { 141, 184 }, { 0, 0 }, 6, 59 },
+ { { 1, 2 }, { 89, 0 }, { 250, 248 }, { 136, 182 }, { 0, 0 }, 6, 51 },
+ { { 1, 0 }, { 0, 0 }, { 249, 250 }, { 10, 6 }, { 3, 0 }, 14, 45 },
+ { { 0, 0 }, { 128, 0 }, { 249, 246 }, { 137, 108 }, { 3, 0 }, 14, 71 },
+ { { 3, 12 }, { 128, 8 }, { 248, 246 }, { 136, 182 }, { 3, 0 }, 15, 60 },
+ { { 3, 12 }, { 133, 0 }, { 248, 246 }, { 136, 182 }, { 3, 0 }, 15, 58 },
+ { { 14, 0 }, { 64, 8 }, { 118, 119 }, { 79, 24 }, { 0, 2 }, 14, 53 },
+ { { 14, 3 }, { 64, 0 }, { 200, 155 }, { 73, 105 }, { 0, 2 }, 14, 64 },
+ { { 215, 199 }, { 220, 0 }, { 173, 141 }, { 5, 5 }, { 3, 0 }, 14, 71 },
+ { { 215, 199 }, { 220, 0 }, { 168, 136 }, { 4, 4 }, { 3, 0 }, 14, 61 },
+ { { 128, 17 }, { 0, 0 }, { 246, 103 }, { 6, 23 }, { 3, 3 }, 14, 61 },
+ { { 128, 17 }, { 0, 9 }, { 245, 70 }, { 5, 22 }, { 2, 3 }, 14, 48 },
+ { { 6, 21 }, { 63, 0 }, { 0, 247 }, { 244, 245 }, { 0, 0 }, 1, 48 },
+ { { 6, 18 }, { 63, 0 }, { 0, 247 }, { 244, 245 }, { 3, 0 }, 0, 69 },
+ { { 6, 18 }, { 63, 0 }, { 0, 247 }, { 244, 245 }, { 0, 0 }, 1, 68 },
+ { { 1, 2 }, { 88, 0 }, { 103, 117 }, { 231, 7 }, { 0, 0 }, 0, 63 },
+ { { 65, 66 }, { 69, 8 }, { 248, 117 }, { 72, 5 }, { 0, 0 }, 0, 74 },
+ { { 10, 30 }, { 64, 78 }, { 224, 255 }, { 240, 5 }, { 3, 0 }, 8, 60 },
+ { { 10, 30 }, { 124, 82 }, { 224, 255 }, { 240, 2 }, { 3, 0 }, 8, 80 },
+ { { 14, 0 }, { 64, 8 }, { 122, 123 }, { 74, 27 }, { 0, 2 }, 14, 64 },
+ { { 14, 7 }, { 10, 64 }, { 228, 85 }, { 228, 57 }, { 3, 1 }, 6, 69 },
+ { { 5, 4 }, { 5, 64 }, { 249, 214 }, { 50, 165 }, { 3, 0 }, 14, 73 },
+ { { 2, 21 }, { 63, 0 }, { 0, 247 }, { 243, 245 }, { 3, 0 }, 8, 75 },
+ { { 1, 2 }, { 79, 0 }, { 250, 248 }, { 141, 181 }, { 0, 0 }, 7, 68 },
+ { { 0, 0 }, { 0, 0 }, { 246, 246 }, { 12, 6 }, { 0, 0 }, 4, 48 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 53 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 35 }
+ };
--- /dev/null
+++ b/rott/audiolib/gus.c
@@ -1,0 +1,283 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ file: GUS.C
+
+ author: James R. Dose
+ date: September 7, 1994
+
+ Gravis Ultrasound initialization routines.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#include <conio.h>
+#include <dos.h>
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include "usrhooks.h"
+#include "interrup.h"
+#include "newgf1.h"
+#include "gusmidi.h"
+#include "guswave.h"
+#include "_guswave.h"
+
+#define TRUE ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+// size of DMA buffer for patch loading
+#define DMABUFFSIZE 2048U
+
+struct gf1_dma_buff GUS_HoldBuffer;
+static int HoldBufferAllocated = FALSE;
+
+static int GUS_Installed = 0;
+
+extern VoiceNode GUSWAVE_Voices[ VOICES ];
+extern int GUSWAVE_Installed;
+
+unsigned long GUS_TotalMemory;
+int GUS_MemConfig;
+
+int GUS_AuxError = 0;
+
+int GUS_ErrorCode = GUS_Ok;
+
+#define GUS_SetErrorCode( status ) \
+ GUS_ErrorCode = ( status );
+
+
+/*---------------------------------------------------------------------
+ Function: GUS_ErrorString
+
+ Returns a pointer to the error message associated with an error
+ number. A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *GUS_ErrorString
+ (
+ int ErrorNumber
+ )
+
+ {
+ char *ErrorString;
+
+ switch( ErrorNumber )
+ {
+ case GUS_Warning :
+ case GUS_Error :
+ ErrorString = GUS_ErrorString( GUS_ErrorCode );
+ break;
+
+ case GUS_Ok :
+ ErrorString = "Ultrasound music ok.";
+ break;
+
+ case GUS_OutOfMemory :
+ ErrorString = "Out of memory in GusMidi.";
+ break;
+
+ case GUS_OutOfDosMemory :
+ ErrorString = "Out of conventional (640K) memory in GusMidi.";
+ break;
+
+ case GUS_GF1Error :
+ ErrorString = gf1_error_str( GUS_AuxError );
+ break;
+
+ case GUS_InvalidIrq :
+ ErrorString = "Ultrasound IRQ must be 7 or less.";
+ break;
+
+ case GUS_ULTRADIRNotSet :
+ ErrorString = "ULTRADIR environment variable not set.";
+ break;
+
+ case GUS_MissingConfig :
+// ErrorString = "Can't find GUSMIDI.INI file.";
+ ErrorString = "Can't find ULTRAMID.INI file.";
+ break;
+
+ case GUS_FileError :
+ ErrorString = strerror( GUS_AuxError );
+ break;
+
+ default :
+ ErrorString = "Unknown Ultrasound error code.";
+ break;
+ }
+
+ return( ErrorString );
+ }
+
+
+
+/*---------------------------------------------------------------------
+ Function: D32DosMemAlloc
+
+ Allocate a block of Conventional memory.
+---------------------------------------------------------------------*/
+
+void *D32DosMemAlloc
+ (
+ unsigned size
+ )
+
+ {
+ union REGS r;
+
+ // DPMI allocate DOS memory
+ r.x.eax = 0x0100;
+
+ // Number of paragraphs requested
+ r.x.ebx = ( size + 15 ) >> 4;
+ int386( 0x31, &r, &r );
+ if ( r.x.cflag )
+ {
+ // Failed
+ return( NULL );
+ }
+
+ return( ( void * )( ( r.x.eax & 0xFFFF ) << 4 ) );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUS_Init
+
+ Initializes the Gravis Ultrasound for sound and music playback.
+---------------------------------------------------------------------*/
+
+int GUS_Init
+ (
+ void
+ )
+
+ {
+ struct load_os os;
+ int ret;
+
+ if ( GUS_Installed > 0 )
+ {
+ GUS_Installed++;
+ return( GUS_Ok );
+ }
+
+ GUS_SetErrorCode( GUS_Ok );
+
+ GUS_Installed = 0;
+
+ GetUltraCfg( &os );
+
+ if ( os.forced_gf1_irq > 7 )
+ {
+ GUS_SetErrorCode( GUS_InvalidIrq );
+ return( GUS_Error );
+ }
+
+ if ( !HoldBufferAllocated )
+ {
+ GUS_HoldBuffer.vptr = D32DosMemAlloc( DMABUFFSIZE );
+ if ( GUS_HoldBuffer.vptr == NULL )
+ {
+ GUS_SetErrorCode( GUS_OutOfDosMemory );
+ return( GUS_Error );
+ }
+ GUS_HoldBuffer.paddr = ( unsigned long )GUS_HoldBuffer.vptr;
+
+ HoldBufferAllocated = TRUE;
+ }
+
+ os.voices = 24;
+ ret = gf1_load_os( &os );
+ if ( ret )
+ {
+ GUS_AuxError = ret;
+ GUS_SetErrorCode( GUS_GF1Error );
+ return( GUS_Error );
+ }
+
+ GUS_TotalMemory = gf1_mem_avail();
+ GUS_MemConfig = ( GUS_TotalMemory - 1 ) >> 18;
+
+ GUS_Installed = 1;
+ return( GUS_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUS_Shutdown
+
+ Ends use of the Gravis Ultrasound. Must be called the same number
+ of times as GUS_Init.
+---------------------------------------------------------------------*/
+
+void GUS_Shutdown
+ (
+ void
+ )
+
+ {
+ if ( GUS_Installed > 0 )
+ {
+ GUS_Installed--;
+ if ( GUS_Installed == 0 )
+ {
+ gf1_unload_os();
+ }
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_Shutdown
+
+ Terminates use of the Gravis Ultrasound for digitized sound playback.
+---------------------------------------------------------------------*/
+
+void GUSWAVE_Shutdown
+ (
+ void
+ )
+
+ {
+ int i;
+
+ if ( GUSWAVE_Installed )
+ {
+ GUSWAVE_KillAllVoices();
+
+ // free memory
+ for ( i = 0; i < VOICES; i++ )
+ {
+ if ( GUSWAVE_Voices[ i ].mem != NULL )
+ {
+ gf1_free( GUSWAVE_Voices[ i ].mem );
+ GUSWAVE_Voices[ i ].mem = NULL;
+ }
+ }
+
+ GUS_Shutdown();
+ GUSWAVE_Installed = FALSE;
+ }
+ }
--- /dev/null
+++ b/rott/audiolib/gusmidi.c
@@ -1,0 +1,561 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ file: GUSMIDI.C
+
+ author: James R. Dose
+ date: March 23, 1994
+
+ General MIDI playback functions for the Gravis Ultrasound
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+// Module MUST be compiled with structure allignment set to a maximum
+// of 1 byte ( zp1 ).
+
+#include <conio.h>
+#include <dos.h>
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include "usrhooks.h"
+#include "interrup.h"
+#include "newgf1.h"
+#include "gusmidi.h"
+
+#define TRUE ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+// size of DMA buffer for patch loading
+#define DMABUFFSIZE 2048U
+
+#define MAX_MEM_CONFIG 3
+
+// size of patch array (128 perc, 128 melodic)
+#define NUM_PATCHES 256
+
+// size of largest patch name
+#define BIGGEST_NAME 9
+
+#define UNUSED_PATCH -1
+
+static struct patch Patch[ NUM_PATCHES ];
+static unsigned char *PatchWaves[ NUM_PATCHES ];
+
+static int PatchMap[ NUM_PATCHES ][ MAX_MEM_CONFIG + 1 ];
+static char ProgramName[ NUM_PATCHES ][ BIGGEST_NAME ];
+static char PatchLoaded[ NUM_PATCHES ];
+
+static char ConfigFileName[] = "ULTRAMID.INI";
+static char ConfigDirectory[ 80 ] = { '\0' };
+
+// The name of the configuration directory
+static char InstrumentDirectory[ 80 ];
+
+extern struct gf1_dma_buff GUS_HoldBuffer;
+
+extern unsigned long GUS_TotalMemory;
+extern int GUS_MemConfig;
+
+static int GUSMIDI_Volume = 255;
+
+extern int GUS_AuxError;
+extern int GUS_ErrorCode;
+
+int GUSMIDI_Installed = FALSE;
+
+#define GUS_SetErrorCode( status ) \
+ GUS_ErrorCode = ( status );
+
+
+/*---------------------------------------------------------------------
+ Function: GUS_GetPatchMap
+
+ Reads the patch map from disk.
+---------------------------------------------------------------------*/
+
+int GUS_GetPatchMap
+ (
+ char *name
+ )
+
+ {
+ char text[ 80 ];
+ char *ud;
+ int index;
+ int ignore;
+ FILE *fp;
+
+ for( index = 0; index < NUM_PATCHES; index++ )
+ {
+ PatchMap[ index ][ 0 ] = UNUSED_PATCH;
+ PatchMap[ index ][ 1 ] = UNUSED_PATCH;
+ PatchMap[ index ][ 2 ] = UNUSED_PATCH;
+ PatchMap[ index ][ 3 ] = UNUSED_PATCH;
+ ProgramName[ index ][ 0 ] = 0;
+ }
+
+ ud = getenv( "ULTRADIR" );
+ if ( ud == NULL )
+ {
+ GUS_SetErrorCode( GUS_ULTRADIRNotSet );
+ return( GUS_Error );
+ }
+
+ strcpy( InstrumentDirectory, ud );
+ strcat( InstrumentDirectory, "\\midi\\" );
+ strcpy( ConfigDirectory, ud );
+ strcat( ConfigDirectory, "\\midi\\" );
+ strcpy( text, name );
+
+ fp = fopen( text, "r" );
+ if ( fp == NULL )
+ {
+ strcpy( text, InstrumentDirectory );
+ strcat( text, name );
+
+ fp = fopen( text, "r" );
+ if ( fp == NULL )
+ {
+ GUS_SetErrorCode( GUS_MissingConfig );
+ return( GUS_Error );
+ }
+ }
+
+ while( 1 )
+ {
+ if ( fgets( text, 80, fp ) == NULL )
+ {
+ break;
+ }
+
+ if ( text[ 0 ] == '#' )
+ {
+ continue;
+ }
+
+ if ( sscanf( text, "%d", &index ) != 1 )
+ {
+ continue;
+ }
+
+ sscanf( text, "%d, %d, %d, %d, %d, %s\n", &ignore,
+ &PatchMap[ index ][ 0 ],
+ &PatchMap[ index ][ 1 ],
+ &PatchMap[ index ][ 2 ],
+ &PatchMap[ index ][ 3 ],
+ ProgramName[ index ] );
+ }
+
+ fclose( fp );
+
+ return( GUS_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSMIDI_UnloadPatch
+
+ Unloads a patch from the GUS's memory.
+---------------------------------------------------------------------*/
+
+int GUSMIDI_UnloadPatch
+ (
+ int prognum
+ )
+
+ {
+ int prog;
+ unsigned flags;
+
+ prog = PatchMap[ prognum ][ GUS_MemConfig ];
+
+ if ( PatchLoaded[ prog ] )
+ {
+ flags = DisableInterrupts();
+
+ gf1_unload_patch( &Patch[ prog ] );
+ if ( PatchWaves[ prog ] != NULL )
+ {
+ USRHOOKS_FreeMem( PatchWaves[ prog ] );
+ PatchWaves[ prog ] = NULL;
+ }
+
+ // just in case sequence is still playing
+ Patch[ prog ].nlayers = 0;
+ PatchLoaded[ prog ] = FALSE;
+
+ RestoreInterrupts( flags );
+ }
+
+ return( GUS_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSMIDI_LoadPatch
+
+ Loads a patch into the GUS's memory.
+---------------------------------------------------------------------*/
+
+int GUSMIDI_LoadPatch
+ (
+ int prognum
+ )
+
+ {
+ int prog;
+ char text[ 80 ];
+ int ret;
+ unsigned char *wave_buff;
+ struct patchinfo patchi;
+ int status;
+
+ prog = PatchMap[ prognum ][ GUS_MemConfig ];
+
+ if ( ( PatchLoaded[ prog ] ) || ( prog == UNUSED_PATCH ) )
+ {
+ return( GUS_Ok );
+ }
+
+ if ( !ProgramName[ prog ][ 0 ] )
+ {
+ return( GUS_Ok );
+ }
+
+ strcpy( text, InstrumentDirectory );
+ strcat( text, ProgramName[ prog ] );
+ strcat( text, ".pat" );
+
+ ret = gf1_get_patch_info( text, &patchi );
+ if ( ret != OK )
+ {
+ GUS_AuxError = ret;
+ GUS_SetErrorCode( GUS_GF1Error );
+ return( GUS_Error );
+ }
+
+ status = USRHOOKS_GetMem( &wave_buff, patchi.header.wave_forms *
+ sizeof( struct wave_struct ) );
+ if ( status != USRHOOKS_Ok )
+ {
+ GUS_SetErrorCode( GUS_OutOfMemory );
+ return( GUS_Error );
+ }
+
+ ret = gf1_load_patch( text, &patchi, &Patch[ prog ], &GUS_HoldBuffer,
+ DMABUFFSIZE, ( unsigned char * )wave_buff, PATCH_LOAD_8_BIT );
+
+ if ( ret != OK )
+ {
+ USRHOOKS_FreeMem( wave_buff );
+ GUS_AuxError = ret;
+ GUS_SetErrorCode( GUS_GF1Error );
+ return( GUS_Error );
+ }
+
+ PatchWaves[ prog ] = wave_buff;
+ PatchLoaded[ prog ] = TRUE;
+
+ return( GUS_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSMIDI_ProgramChange
+
+ Selects the instrument to use on the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+void GUSMIDI_ProgramChange
+ (
+ int channel,
+ int prognum
+ )
+
+ {
+ int prog;
+
+ prog = PatchMap[ prognum ][ GUS_MemConfig ];
+
+ if ( PatchLoaded[ prog ] )
+ {
+ gf1_midi_change_program( &Patch[ prog ], channel );
+ }
+ else
+ {
+ gf1_midi_change_program( NULL, channel );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSMIDI_NoteOn
+
+ Plays a note on the specified channel.
+---------------------------------------------------------------------*/
+
+void GUSMIDI_NoteOn
+ (
+ int chan,
+ int note,
+ int velocity
+ )
+
+ {
+ int prog;
+
+ if ( chan == 9 )
+ {
+ prog = PatchMap[ note + 128 ][ GUS_MemConfig ];
+
+ if ( PatchLoaded[ prog ] )
+ {
+ gf1_midi_note_on( &Patch[ note + 128 ], 1,
+ note, velocity, 9 );
+ }
+ }
+ else
+ {
+ gf1_midi_note_on( 0L, 1, note, velocity, chan );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSMIDI_NoteOff
+
+ Turns off a note on the specified channel.
+---------------------------------------------------------------------*/
+#pragma warn -par
+void GUSMIDI_NoteOff
+ (
+ int chan,
+ int note,
+ int velocity
+ )
+
+ {
+ gf1_midi_note_off( note, chan );
+ }
+#pragma warn .par
+
+
+/*---------------------------------------------------------------------
+ Function: GUSMIDI_ControlChange
+
+ Sets the value of a controller on the specified channel.
+---------------------------------------------------------------------*/
+
+void GUSMIDI_ControlChange
+ (
+ int channel,
+ int number,
+ int value
+ )
+
+ {
+ gf1_midi_parameter( channel, number, value );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSMIDI_PitchBend
+
+ Sets the pitch bend on the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+void GUSMIDI_PitchBend
+ (
+ int channel,
+ int lsb,
+ int msb
+ )
+
+ {
+ gf1_midi_pitch_bend( channel, lsb, msb );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSMIDI_ReleasePatches
+
+ Removes all the instruments from the GUS's memory.
+---------------------------------------------------------------------*/
+
+void GUSMIDI_ReleasePatches
+ (
+ void
+ )
+
+ {
+ int i;
+
+ for( i = 0; i < 256; i++ )
+ {
+ GUSMIDI_UnloadPatch( i );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSMIDI_SetVolume
+
+ Sets the total music volume.
+---------------------------------------------------------------------*/
+
+void GUSMIDI_SetVolume
+ (
+ int volume
+ )
+
+ {
+ // Set the minimum to 2 because 0 has a tremolo problem
+ volume = max( 2, volume );
+ volume = min( volume, 255 );
+
+ GUSMIDI_Volume = volume;
+
+ // range = 0 to 127
+ gf1_midi_synth_volume( 0, volume >> 1 );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSMIDI_GetVolume
+
+ Returns the total music volume.
+---------------------------------------------------------------------*/
+
+int GUSMIDI_GetVolume
+ (
+ void
+ )
+
+ {
+ return( GUSMIDI_Volume );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSMIDI_Init
+
+ Initializes the Gravis Ultrasound for music playback.
+---------------------------------------------------------------------*/
+
+int GUSMIDI_Init
+ (
+ void
+ )
+
+ {
+ int ret;
+ int i;
+ int startmem;
+// unsigned long mem;
+ extern int GUSWAVE_Installed;
+
+ if ( GUSMIDI_Installed )
+ {
+ GUSMIDI_Shutdown();
+ }
+
+ ret = GUS_Init();
+ if ( ret != GUS_Ok )
+ {
+ return( ret );
+ }
+
+ if ( GUS_MemConfig < 0 )
+ {
+ GUS_MemConfig = 0;
+ }
+
+ if ( GUS_MemConfig > MAX_MEM_CONFIG )
+ {
+ GUS_MemConfig = MAX_MEM_CONFIG;
+ }
+
+ for( i = 0; i < NUM_PATCHES; i++ )
+ {
+ ProgramName[ i ][ 0 ] = '\0';
+ PatchWaves[ i ] = NULL;
+ PatchLoaded[ i ] = FALSE;
+ }
+
+ GUSMIDI_SetVolume( 255 );
+
+ GUSMIDI_Installed = TRUE;
+
+ ret = GUS_GetPatchMap( ConfigFileName );
+ if ( ret != GUS_Ok )
+ {
+ GUSMIDI_Shutdown();
+ return( ret );
+ }
+
+// if ( !GUSWAVE_Installed )
+// {
+// mem = gf1_malloc( 8192 );
+// }
+
+ startmem = gf1_mem_avail();
+ for( i = 0; i < NUM_PATCHES; i++ )
+ {
+ ret = GUSMIDI_LoadPatch( i );
+ if ( ret != GUS_Ok )
+ {
+ }
+// if ( ret != GUS_Ok )
+// {
+// return( ret );
+// }
+ }
+
+// if ( !GUSWAVE_Installed )
+// {
+// gf1_free( mem );
+// }
+
+ GUSMIDI_Installed = TRUE;
+
+ return( GUS_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSMIDI_Shutdown
+
+ Ends use of the Gravis Ultrasound for music playback.
+---------------------------------------------------------------------*/
+
+void GUSMIDI_Shutdown
+ (
+ void
+ )
+
+ {
+ GUSMIDI_ReleasePatches();
+ GUS_Shutdown();
+ GUSMIDI_Installed = FALSE;
+ }
--- /dev/null
+++ b/rott/audiolib/gusmidi.h
@@ -1,0 +1,59 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef __GUSMIDI_H
+#define __GUSMIDI_H
+
+extern struct gf1_dma_buff GUS_HoldBuffer;
+
+enum GUS_Errors
+ {
+ GUS_Warning = -2,
+ GUS_Error = -1,
+ GUS_Ok = 0,
+ GUS_OutOfMemory,
+ GUS_OutOfDosMemory,
+ GUS_OutOfDRAM,
+ GUS_GF1Error,
+ GUS_InvalidIrq,
+ GUS_ULTRADIRNotSet,
+ GUS_MissingConfig,
+ GUS_FileError
+ };
+
+char *GUS_ErrorString( int ErrorNumber );
+int GUS_GetPatchMap( char *name );
+int GUSMIDI_UnloadPatch( int prog );
+int GUSMIDI_LoadPatch( int prog );
+void GUSMIDI_ProgramChange( int channel, int prog );
+void GUSMIDI_NoteOn( int chan, int note, int velocity );
+void GUSMIDI_NoteOff( int chan, int note, int velocity );
+void GUSMIDI_ControlChange( int channel, int number, int value );
+void GUSMIDI_PitchBend( int channel, int lsb, int msb );
+void GUSMIDI_ReleasePatches( void );
+void GUSMIDI_SetVolume( int volume );
+int GUSMIDI_GetVolume( void );
+int GUS_Init( void );
+void GUS_Shutdown( void );
+#pragma aux GUS_Shutdown frame;
+int GUSMIDI_Init( void );
+void GUSMIDI_Shutdown( void );
+void *D32DosMemAlloc( unsigned size );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/guswave.c
@@ -1,0 +1,1773 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ file: GUSWAVE.C
+
+ author: James R. Dose
+ date: March 23, 1994
+
+ Digitized sound playback routines for the Gravis Ultrasound.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#include <stdlib.h>
+#include <conio.h>
+#include <dos.h>
+#include <stdio.h>
+#include <io.h>
+#include <string.h>
+#include "debugio.h"
+#include "interrup.h"
+#include "ll_man.h"
+#include "pitch.h"
+#include "user.h"
+#include "multivoc.h"
+#include "_guswave.h"
+#include "newgf1.h"
+#include "gusmidi.h"
+#include "guswave.h"
+
+#define ATR_INDEX 0x3c0
+#define STATUS_REGISTER_1 0x3da
+
+#define SetBorderColor(color) \
+ { \
+ inp (STATUS_REGISTER_1); \
+ outp (ATR_INDEX,0x31); \
+ outp (ATR_INDEX,color); \
+ }
+
+static const int GUSWAVE_PanTable[ 32 ] =
+ {
+ 8, 9, 10, 11, 11, 12, 13, 14,
+ 15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 4, 3, 2, 1,
+ 0, 1, 2, 3, 4, 5, 6, 7
+ };
+
+static voicelist VoiceList;
+static voicelist VoicePool;
+
+static voicestatus VoiceStatus[ MAX_VOICES ];
+//static
+VoiceNode GUSWAVE_Voices[ VOICES ];
+
+static int GUSWAVE_VoiceHandle = GUSWAVE_MinVoiceHandle;
+static int GUSWAVE_MaxVoices = VOICES;
+//static
+int GUSWAVE_Installed = FALSE;
+
+static void ( *GUSWAVE_CallBackFunc )( unsigned long ) = NULL;
+
+// current volume for dig audio - from 0 to 4095
+static int GUSWAVE_Volume = MAX_VOLUME;
+
+static int GUSWAVE_SwapLeftRight = FALSE;
+
+static int GUS_Debug = FALSE;
+
+extern int GUSMIDI_Installed;
+
+int GUSWAVE_ErrorCode = GUSWAVE_Ok;
+
+#define GUSWAVE_SetErrorCode( status ) \
+ GUSWAVE_ErrorCode = ( status );
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_ErrorString
+
+ Returns a pointer to the error message associated with an error
+ number. A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *GUSWAVE_ErrorString
+ (
+ int ErrorNumber
+ )
+
+ {
+ char *ErrorString;
+
+ switch( ErrorNumber )
+ {
+ case GUSWAVE_Warning :
+ case GUSWAVE_Error :
+ ErrorString = GUSWAVE_ErrorString( GUSWAVE_ErrorCode );
+ break;
+
+ case GUSWAVE_Ok :
+ ErrorString = "GUSWAVE ok.";
+ break;
+
+ case GUSWAVE_GUSError :
+ ErrorString = GUS_ErrorString( GUS_Error );
+ break;
+
+ case GUSWAVE_NotInstalled :
+ ErrorString = "GUSWAVE not installed.";
+ break;
+
+ case GUSWAVE_NoVoices :
+ ErrorString = "No free voices available to GUSWAVE.";
+ break;
+
+ case GUSWAVE_UltraNoMem :
+ ErrorString = "Not enough Ultrasound memory available for GUSWAVE.";
+ break;
+
+ case GUSWAVE_UltraNoMemMIDI :
+ ErrorString = "Not enough Ultrasound memory available for GUSWAVE. "
+ "Try initializing Sound FX before Music.";
+ break;
+
+ case GUSWAVE_VoiceNotFound :
+ ErrorString = "No voice with matching handle found.";
+ break;
+
+ case GUSWAVE_InvalidVOCFile :
+ ErrorString = "Invalid VOC file passed in to GUSWAVE.";
+ break;
+
+ case GUSWAVE_InvalidWAVFile :
+ ErrorString = "Invalid WAV file passed in to GUSWAVE.";
+ break;
+
+ default :
+ ErrorString = "Unknown GUSWAVE error code.";
+ break;
+ }
+
+ return( ErrorString );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_CallBack
+
+ GF1 callback service routine.
+---------------------------------------------------------------------*/
+
+char GUS_Silence8[ 1024 ] = //256 ] =
+ {
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80
+
+
+ };
+
+//unsigned short GUS_Silence16[ 128 ] =
+unsigned short GUS_Silence16[ 512 ] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+static int LOADDS GUSWAVE_CallBack
+ (
+ int reason,
+ int voice,
+ unsigned char **buf,
+ unsigned long *size
+ )
+
+ {
+ VoiceNode *Voice;
+ playbackstatus status;
+
+ // this function is called from an interrupt
+ // remember not to make any DOS or BIOS calls from here
+ // also don't call any C library functions unless you are sure that
+ // they are reentrant
+ // restore our DS register
+
+ if ( VoiceStatus[ voice ].playing == FALSE )
+ {
+ return( DIG_DONE );
+ }
+
+ if ( reason == DIG_MORE_DATA )
+ {
+// SetBorderColor(16);
+ Voice = VoiceStatus[ voice ].Voice;
+
+ if ( ( Voice != NULL ) && ( Voice->Playing ) )
+/*
+ {
+ *buf = ( unsigned char * )GUS_Silence16;
+ *size = 1024;
+
+ SetBorderColor(0);
+ return( DIG_MORE_DATA );
+ }
+ */
+ {
+ status = Voice->GetSound( Voice );
+ if ( status != SoundDone )
+ {
+ if ( ( Voice->sound == NULL ) || ( status == NoMoreData ) )
+ {
+ if ( Voice->bits == 8 )
+ {
+ *buf = GUS_Silence8;
+ }
+ else
+ {
+ *buf = ( unsigned char * )GUS_Silence16;
+ }
+ *size = 256;
+ }
+ else
+ {
+ *buf = Voice->sound;
+ *size = Voice->length;
+ }
+ return( DIG_MORE_DATA );
+ }
+ }
+// SetBorderColor(16);
+ return( DIG_DONE );
+ }
+
+ if ( reason == DIG_DONE )
+ {
+ Voice = VoiceStatus[ voice ].Voice;
+ VoiceStatus[ voice ].playing = FALSE;
+
+ if ( Voice != NULL )
+ {
+ Voice->Active = FALSE;
+ Voice->Playing = FALSE;
+
+// I'm commenting this out because a -1 could cause a crash if it
+// is sent to the GF1 code. This shouldn't be necessary since
+// Active should be false when GF1voice is -1, but this is just
+// a precaution. Adjust the pan on the wrong voice is a lot
+// more pleasant than a crash!
+// Voice->GF1voice = -1;
+
+ LL_Remove( VoiceNode, &VoiceList, Voice );
+ LL_AddToTail( VoiceNode, &VoicePool, Voice );
+ }
+
+ if ( GUSWAVE_CallBackFunc )
+ {
+ GUSWAVE_CallBackFunc( Voice->callbackval );
+ }
+ }
+
+ return( DIG_DONE );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_DebugCallBack
+
+ GF1 callback service routine with debugging info.
+---------------------------------------------------------------------*/
+
+static int LOADDS GUSWAVE_DebugCallBack
+ (
+ int reason,
+ int voice,
+ unsigned char **buf,
+ unsigned long *size
+ )
+
+ {
+ VoiceNode *Voice;
+
+ // this function is called from an interrupt
+ // remember not to make any DOS or BIOS calls from here
+ // also don't call any C library functions unless you are sure that
+ // they are reentrant
+ // restore our DS register
+
+ if ( VoiceStatus[ voice ].playing == FALSE )
+ {
+// DB_printf( "GUS Voice %d not playing.\n", voice );
+ DB_printf( "GUS Voice " );
+ DB_PrintNum( voice );
+ DB_printf( " not playing.\n" );
+ return( DIG_DONE );
+ }
+
+ if ( reason == DIG_MORE_DATA )
+ {
+ Voice = VoiceStatus[ voice ].Voice;
+
+// DB_printf( "Voice %d : More data -- ", Voice );
+ DB_printf( "Voice " );
+ DB_PrintNum( voice );
+ DB_printf( " : More data -- " );
+ if ( Voice != NULL )
+ {
+ if ( Voice->Playing )
+ {
+ GUSWAVE_GetNextVOCBlock( Voice );
+ if ( Voice->Playing )
+ {
+// DB_printf( "More data -- size = %u blocklength = %u\n",
+// Voice->length, Voice->BlockLength );
+ DB_printf( "More data -- size = " );
+ DB_PrintNum( Voice->length );
+ DB_printf( " blocklength = " );
+ DB_PrintNum( Voice->BlockLength );
+ DB_printf( "\n" );
+ *buf = Voice->sound;
+ *size = Voice->length;
+ return( DIG_MORE_DATA );
+ }
+ else
+ {
+ DB_printf( "Voice done.\n" );
+ }
+ }
+ else
+ {
+ DB_printf( "Voice not active.\n" );
+ }
+ }
+ else
+ {
+ DB_printf( " NULL Voice\n" );
+ }
+
+ return( DIG_DONE );
+ }
+
+ if ( reason == DIG_DONE )
+ {
+ VoiceStatus[ voice ].playing = FALSE;
+ Voice = VoiceStatus[ voice ].Voice;
+// DB_printf( "Voice %d : Done -- ", Voice );
+ DB_printf( "Voice " );
+ DB_PrintNum( voice );
+ DB_printf( " : Done -- " );
+
+ if ( Voice != NULL )
+ {
+ DB_printf( "Ok\n" );
+
+ Voice->Active = FALSE;
+ Voice->Playing = FALSE;
+
+// I'm commenting this out because a -1 could cause a crash if it
+// is sent to the GF1 code. This shouldn't be necessary since
+// Active should be false when GF1voice is -1, but this is just
+// a precaution. Adjust the pan on the wrong voice is a lot
+// more pleasant than a crash!
+// Voice->GF1voice = -1;
+
+ LL_Remove( VoiceNode, &VoiceList, Voice );
+ LL_AddToTail( VoiceNode, &VoicePool, Voice );
+ }
+ else
+ {
+ DB_printf( "Null voice\n" );
+ }
+
+ if ( GUSWAVE_CallBackFunc )
+ {
+ GUSWAVE_CallBackFunc( Voice->callbackval );
+ }
+ }
+
+ return( DIG_DONE );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_GetVoice
+
+ Locates the voice with the specified handle.
+---------------------------------------------------------------------*/
+
+static VoiceNode *GUSWAVE_GetVoice
+ (
+ int handle
+ )
+
+ {
+ VoiceNode *voice;
+ unsigned flags;
+
+ flags = DisableInterrupts();
+
+ voice = VoiceList.start;
+
+ while( voice != NULL )
+ {
+ if ( handle == voice->handle )
+ {
+ break;
+ }
+
+ voice = voice->next;
+ }
+
+ RestoreInterrupts( flags );
+
+ if ( voice == NULL )
+ {
+ GUSWAVE_SetErrorCode( GUSWAVE_VoiceNotFound );
+ }
+
+ return( voice );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_VoicePlaying
+
+ Checks if the voice associated with the specified handle is
+ playing.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_VoicePlaying
+ (
+ int handle
+ )
+
+ {
+ VoiceNode *voice;
+
+ voice = GUSWAVE_GetVoice( handle );
+ if ( voice != NULL )
+ {
+ return( voice->Active );
+ }
+
+ return( FALSE );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_VoicesPlaying
+
+ Determines the number of currently active voices.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_VoicesPlaying
+ (
+ void
+ )
+
+ {
+ int index;
+ int NumVoices = 0;
+ unsigned flags;
+
+ flags = DisableInterrupts();
+
+ for( index = 0; index < GUSWAVE_MaxVoices; index++ )
+ {
+ if ( GUSWAVE_Voices[ index ].Active )
+ {
+ NumVoices++;
+ }
+ }
+
+ RestoreInterrupts( flags );
+
+ if ( GUS_Debug )
+ {
+ DB_printf( "Number of voices = %d.\n", NumVoices );
+ }
+
+ return( NumVoices );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_Kill
+
+ Stops output of the voice associated with the specified handle.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_Kill
+ (
+ int handle
+ )
+
+ {
+ VoiceNode *voice;
+ unsigned flags;
+
+ flags = DisableInterrupts();
+
+ voice = GUSWAVE_GetVoice( handle );
+
+ if ( voice == NULL )
+ {
+ RestoreInterrupts( flags );
+ GUSWAVE_SetErrorCode( GUSWAVE_VoiceNotFound );
+
+ if ( GUS_Debug )
+ {
+ DB_printf( "Could not find voice to kill.\n" );
+ }
+
+ return( GUSWAVE_Warning );
+ }
+
+ RestoreInterrupts( flags );
+
+ if ( !GUS_Debug )
+ {
+ if ( voice->Active )
+ {
+ gf1_stop_digital( voice->GF1voice );
+ }
+ }
+ else
+ {
+ DB_printf( "Kill - GUS Voice %d ", voice->GF1voice );
+ if ( voice->Active )
+ {
+ DB_printf( "active\n" );
+ gf1_stop_digital( voice->GF1voice );
+ }
+ else
+ {
+ DB_printf( "inactive\n" );
+ }
+ }
+
+// RestoreInterrupts( flags );
+
+ return( GUSWAVE_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_KillAllVoices
+
+ Stops output of all currently active voices.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_KillAllVoices
+ (
+ void
+ )
+
+ {
+ int i;
+ unsigned flags;
+
+ if ( !GUSWAVE_Installed )
+ {
+ return( GUSWAVE_Ok );
+ }
+
+ if ( GUS_Debug )
+ {
+ DB_printf( "Kill All Voices\n" );
+ }
+
+ flags = DisableInterrupts();
+
+ // Remove all the voices from the list
+ for( i = 0; i < GUSWAVE_MaxVoices; i++ )
+ {
+ if ( GUSWAVE_Voices[ i ].Active )
+ {
+// GUSWAVE_Kill( GUSWAVE_Voices[ i ].handle );
+
+ gf1_stop_digital( GUSWAVE_Voices[ i ].GF1voice );
+ }
+ }
+
+ for( i = 0; i < MAX_VOICES; i++ )
+ {
+ VoiceStatus[ i ].playing = FALSE;
+ VoiceStatus[ i ].Voice = NULL;
+ }
+
+ VoicePool.start = NULL;
+ VoicePool.end = NULL;
+ VoiceList.start = NULL;
+ VoiceList.end = NULL;
+
+ for( i = 0; i < GUSWAVE_MaxVoices; i++ )
+ {
+ GUSWAVE_Voices[ i ].Active = FALSE;
+ if ( GUSWAVE_Voices[ i ].mem != NULL )
+ {
+ LL_AddToTail( VoiceNode, &VoicePool, &GUSWAVE_Voices[ i ] );
+ }
+ }
+
+ RestoreInterrupts( flags );
+
+ return( GUSWAVE_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_SetPitch
+
+ Sets the pitch for the voice associated with the specified handle.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_SetPitch
+ (
+ int handle,
+ int pitchoffset
+ )
+
+ {
+ VoiceNode *voice;
+ unsigned flags;
+
+ flags = DisableInterrupts();
+
+ voice = GUSWAVE_GetVoice( handle );
+
+ if ( voice == NULL )
+ {
+ RestoreInterrupts( flags );
+
+ GUSWAVE_SetErrorCode( GUSWAVE_VoiceNotFound );
+ return( GUSWAVE_Warning );
+ }
+
+ if ( voice->Active )
+ {
+ voice->PitchScale = PITCH_GetScale( pitchoffset );
+ voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) >> 16;
+ gf1_dig_set_freq( voice->GF1voice, voice->RateScale );
+ }
+
+ RestoreInterrupts( flags );
+
+ return( GUSWAVE_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_SetPan3D
+
+ Sets the pan position of the voice with the specified handle.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_SetPan3D
+ (
+ int handle,
+ int angle,
+ int distance
+ )
+
+ {
+ VoiceNode *voice;
+ int pan;
+ unsigned flags;
+
+ flags = DisableInterrupts();
+
+ voice = GUSWAVE_GetVoice( handle );
+
+ if ( voice == NULL )
+ {
+ RestoreInterrupts( flags );
+
+ GUSWAVE_SetErrorCode( GUSWAVE_VoiceNotFound );
+ return( GUSWAVE_Warning );
+ }
+
+ if ( voice->Active )
+ {
+ angle &= 31;
+
+ pan = GUSWAVE_PanTable[ angle ];
+ if ( GUSWAVE_SwapLeftRight )
+ {
+ pan = 15 - pan;
+ }
+
+ distance = max( 0, distance );
+ distance = min( 255, distance );
+
+ voice->Volume = 255 - distance;
+ voice->Pan = pan;
+
+ gf1_dig_set_pan( voice->GF1voice, pan );
+ gf1_dig_set_vol( voice->GF1voice, GUSWAVE_Volume - distance * 4 );
+ }
+
+ RestoreInterrupts( flags );
+
+ return( GUSWAVE_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_SetVolume
+
+ Sets the total volume of the digitized sounds.
+---------------------------------------------------------------------*/
+
+void GUSWAVE_SetVolume
+ (
+ int volume
+ )
+
+ {
+ int i;
+
+ volume = max( 0, volume );
+ volume = min( 255, volume );
+ GUSWAVE_Volume = MAX_VOLUME - ( 255 - volume ) * 4;
+
+ for( i = 0; i < GUSWAVE_MaxVoices; i++ )
+ {
+ if ( GUSWAVE_Voices[ i ].Active )
+ {
+ gf1_dig_set_vol( GUSWAVE_Voices[ i ].GF1voice,
+ GUSWAVE_Volume - ( 255 - GUSWAVE_Voices[ i ].Volume ) * 4 );
+ }
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_GetVolume
+
+ Returns the total volume of the digitized sounds.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_GetVolume
+ (
+ void
+ )
+
+ {
+ return( 255 - ( ( MAX_VOLUME - GUSWAVE_Volume ) / 4 ) );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_AllocVoice
+
+ Retrieve an inactive or lower priority voice for output.
+---------------------------------------------------------------------*/
+
+static VoiceNode *GUSWAVE_AllocVoice
+ (
+ int priority
+ )
+
+ {
+ VoiceNode *voice;
+ VoiceNode *node;
+ unsigned flags;
+
+ // If we don't have any free voices, check if we have a higher
+ // priority than one that is playing.
+ if ( GUSWAVE_VoicesPlaying() >= GUSWAVE_MaxVoices )
+ {
+ flags = DisableInterrupts();
+
+ node = VoiceList.start;
+ voice = node;
+ while( node != NULL )
+ {
+ if ( node->priority < voice->priority )
+ {
+ voice = node;
+ }
+
+ node = node->next;
+ }
+
+ RestoreInterrupts( flags );
+
+ if ( priority >= voice->priority )
+ {
+ GUSWAVE_Kill( voice->handle );
+ }
+ }
+
+ // Check if any voices are in the voice pool
+ flags = DisableInterrupts();
+
+ voice = VoicePool.start;
+ if ( voice != NULL )
+ {
+ LL_Remove( VoiceNode, &VoicePool, voice );
+ }
+
+ RestoreInterrupts( flags );
+
+ if ( voice != NULL )
+ {
+ do
+ {
+ GUSWAVE_VoiceHandle++;
+ if ( GUSWAVE_VoiceHandle < GUSWAVE_MinVoiceHandle )
+ {
+ GUSWAVE_VoiceHandle = GUSWAVE_MinVoiceHandle;
+ }
+ }
+ while( GUSWAVE_VoicePlaying( GUSWAVE_VoiceHandle ) );
+
+ voice->handle = GUSWAVE_VoiceHandle;
+ }
+
+ return( voice );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_VoiceAvailable
+
+ Checks if a voice can be play at the specified priority.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_VoiceAvailable
+ (
+ int priority
+ )
+
+ {
+ VoiceNode *voice;
+ VoiceNode *node;
+ unsigned flags;
+
+ if ( GUSWAVE_VoicesPlaying() < GUSWAVE_MaxVoices )
+ {
+ return( TRUE );
+ }
+
+ flags = DisableInterrupts();
+
+ node = VoiceList.start;
+ voice = node;
+ while( node != NULL )
+ {
+ if ( node->priority < voice->priority )
+ {
+ voice = node;
+ }
+
+ node = node->next;
+ }
+
+ RestoreInterrupts( flags );
+
+ if ( priority >= voice->priority )
+ {
+ return( TRUE );
+ }
+
+ return( FALSE );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_GetNextVOCBlock
+
+ Interperate the information of a VOC format sound file.
+---------------------------------------------------------------------*/
+
+playbackstatus GUSWAVE_GetNextVOCBlock
+ (
+ VoiceNode *voice
+ )
+
+ {
+ unsigned char *ptr;
+ int blocktype;
+ int lastblocktype;
+ unsigned long blocklength;
+ unsigned long samplespeed;
+ unsigned int tc;
+ int packtype;
+ int voicemode;
+ int done;
+ unsigned BitsPerSample;
+ unsigned Channels;
+ unsigned Format;
+
+ if ( voice->BlockLength > 0 )
+ {
+ voice->sound += MAX_BLOCK_LENGTH;
+ voice->length = min( voice->BlockLength, MAX_BLOCK_LENGTH );
+ voice->BlockLength -= voice->length;
+ return( KeepPlaying );
+ }
+
+ ptr = ( unsigned char * )voice->NextBlock;
+
+ voice->Playing = TRUE;
+
+ voicemode = 0;
+ lastblocktype = 0;
+ packtype = 0;
+
+ done = FALSE;
+ while( !done )
+ {
+ // Stop playing if we get a NULL pointer
+ if ( ptr == NULL )
+ {
+ voice->Playing = FALSE;
+ done = TRUE;
+ break;
+ }
+
+ blocktype = ( int )*ptr;
+ blocklength = ( *( unsigned long * )( ptr + 1 ) ) & 0x00ffffff;
+ ptr += 4;
+
+ switch( blocktype )
+ {
+ case 0 :
+ // End of data
+ voice->Playing = FALSE;
+ done = TRUE;
+ break;
+
+ case 1 :
+ // Sound data block
+ voice->bits = 8;
+ if ( lastblocktype != 8 )
+ {
+ tc = ( unsigned int )*ptr << 8;
+ packtype = *( ptr + 1 );
+ }
+
+ ptr += 2;
+ blocklength -= 2;
+
+ samplespeed = 256000000L / ( 65536 - tc );
+
+ // Skip packed or stereo data
+ if ( ( packtype != 0 ) || ( voicemode != 0 ) )
+ {
+ ptr += blocklength;
+ }
+ else
+ {
+ done = TRUE;
+ }
+ voicemode = 0;
+ break;
+
+ case 2 :
+ // Sound continuation block
+ samplespeed = voice->SamplingRate;
+ done = TRUE;
+ break;
+
+ case 3 :
+ // Silence
+ // Not implimented.
+ ptr += blocklength;
+ break;
+
+ case 4 :
+ // Marker
+ // Not implimented.
+ ptr += blocklength;
+ break;
+
+ case 5 :
+ // ASCII string
+ // Not implimented.
+ ptr += blocklength;
+ break;
+
+ case 6 :
+ // Repeat begin
+ voice->LoopCount = *( unsigned short * )ptr;
+ ptr += blocklength;
+ voice->LoopStart = ptr;
+ break;
+
+ case 7 :
+ // Repeat end
+ ptr += blocklength;
+ if ( lastblocktype == 6 )
+ {
+ voice->LoopCount = 0;
+ }
+ else
+ {
+ if ( ( voice->LoopCount > 0 ) && ( voice->LoopStart != NULL ) )
+ {
+ ptr = voice->LoopStart;
+ if ( voice->LoopCount < 0xffff )
+ {
+ voice->LoopCount--;
+ if ( voice->LoopCount == 0 )
+ {
+ voice->LoopStart = NULL;
+ }
+ }
+ }
+ }
+ break;
+
+ case 8 :
+ // Extended block
+ voice->bits = 8;
+ tc = *( unsigned short * )ptr;
+ packtype = *( ptr + 2 );
+ voicemode = *( ptr + 3 );
+ ptr += blocklength;
+ break;
+
+ case 9 :
+ // New sound data block
+ samplespeed = *( unsigned long * )ptr;
+ BitsPerSample = ( unsigned )*( ptr + 4 );
+ Channels = ( unsigned )*( ptr + 5 );
+ Format = ( unsigned )*( unsigned short * )( ptr + 6 );
+
+ if ( ( BitsPerSample == 8 ) && ( Channels == 1 ) &&
+ ( Format == VOC_8BIT ) )
+ {
+ ptr += 12;
+ blocklength -= 12;
+ voice->bits = 8;
+ done = TRUE;
+ }
+ else if ( ( BitsPerSample == 16 ) && ( Channels == 1 ) &&
+ ( Format == VOC_16BIT ) )
+ {
+ ptr += 12;
+ blocklength -= 12;
+ voice->bits = 16;
+ done = TRUE;
+ }
+ else
+ {
+ ptr += blocklength;
+ }
+ break;
+
+ default :
+ // Unknown data. Probably not a VOC file.
+ voice->Playing = FALSE;
+ done = TRUE;
+ break;
+ }
+
+ lastblocktype = blocktype;
+ }
+
+ if ( voice->Playing )
+ {
+ voice->NextBlock = ptr + blocklength;
+ voice->sound = ptr;
+
+ voice->SamplingRate = samplespeed;
+ voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) >> 16;
+
+ voice->length = min( blocklength, MAX_BLOCK_LENGTH );
+ voice->BlockLength = blocklength - voice->length;
+
+ return( KeepPlaying );
+ }
+
+ return( SoundDone );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_GetNextWAVBlock
+
+ Controls playback of demand fed data.
+---------------------------------------------------------------------*/
+
+playbackstatus GUSWAVE_GetNextWAVBlock
+ (
+ VoiceNode *voice
+ )
+
+ {
+ if ( voice->BlockLength <= 0 )
+ {
+ if ( voice->LoopStart == NULL )
+ {
+ voice->Playing = FALSE;
+ return( SoundDone );
+ }
+
+ voice->BlockLength = voice->LoopSize;
+ voice->NextBlock = voice->LoopStart;
+ voice->length = 0;
+ }
+
+ voice->sound = voice->NextBlock;
+ voice->length = min( voice->BlockLength, 0x8000 );
+ voice->NextBlock += voice->length;
+ voice->BlockLength -= voice->length;
+
+ return( KeepPlaying );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_GetNextDemandFeedBlock
+
+ Controls playback of demand fed data.
+---------------------------------------------------------------------*/
+
+playbackstatus GUSWAVE_GetNextDemandFeedBlock
+ (
+ VoiceNode *voice
+ )
+
+ {
+ if ( voice->BlockLength > 0 )
+ {
+ voice->sound += voice->length;
+ voice->length = min( voice->BlockLength, 0x8000 );
+ voice->BlockLength -= voice->length;
+
+ return( KeepPlaying );
+ }
+
+ if ( voice->DemandFeed == NULL )
+ {
+ return( SoundDone );
+ }
+
+ ( voice->DemandFeed )( &voice->sound, &voice->BlockLength );
+// voice->sound = GUS_Silence16;
+// voice->BlockLength = 256;
+
+ voice->length = min( voice->BlockLength, 0x8000 );
+ voice->BlockLength -= voice->length;
+
+ if ( ( voice->length > 0 ) && ( voice->sound != NULL ) )
+ {
+ return( KeepPlaying );
+ }
+ return( NoMoreData );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_Play
+
+ Begins playback of digitized sound.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_Play
+ (
+ VoiceNode *voice,
+ int angle,
+ int volume,
+ int channels
+ )
+
+ {
+ int VoiceNumber;
+ int type;
+ int pan;
+ unsigned flags;
+ int ( *servicefunction )( int reason, int voice, unsigned char **buf, unsigned long *size );
+
+ type = 0;
+ if ( channels != 1 )
+ {
+ type |= TYPE_STEREO;
+ }
+
+ if ( voice->bits == 8 )
+ {
+ type |= TYPE_8BIT;
+ type |= TYPE_INVERT_MSB;
+ }
+
+ voice->GF1voice = -1;
+
+ angle &= 31;
+ pan = GUSWAVE_PanTable[ angle ];
+ if ( GUSWAVE_SwapLeftRight )
+ {
+ pan = 15 - pan;
+ }
+
+ voice->Pan = pan;
+
+ volume = max( 0, volume );
+ volume = min( 255, volume );
+ voice->Volume = volume;
+
+ if ( !GUS_Debug )
+ {
+ servicefunction = GUSWAVE_CallBack;
+ }
+ else
+ {
+ servicefunction = GUSWAVE_DebugCallBack;
+ }
+
+ VoiceNumber = gf1_play_digital( 0, voice->sound, voice->length,
+ voice->mem, GUSWAVE_Volume - ( 255 - volume ) * 4, pan,
+ voice->RateScale, type, &GUS_HoldBuffer, servicefunction );
+
+ if ( VoiceNumber == NO_MORE_VOICES )
+ {
+ if ( GUS_Debug )
+ {
+ DB_printf( "Out of voices.\n" );
+ }
+
+ flags = DisableInterrupts();
+ LL_AddToTail( VoiceNode, &VoicePool, voice );
+ RestoreInterrupts( flags );
+
+ GUSWAVE_SetErrorCode( GUSWAVE_NoVoices );
+ return( GUSWAVE_Warning );
+ }
+
+ flags = DisableInterrupts();
+ voice->GF1voice = VoiceNumber;
+ voice->Active = TRUE;
+ LL_AddToTail( VoiceNode, &VoiceList, voice );
+ VoiceStatus[ VoiceNumber ].playing = TRUE;
+ VoiceStatus[ VoiceNumber ].Voice = voice;
+
+ if ( GUS_Debug )
+ {
+ DB_printf( "GUS voice %d playing\n", VoiceNumber );
+ }
+
+ RestoreInterrupts( flags );
+
+ return( voice->handle );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_PlayVOC
+
+ Begins playback of digitized sound.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_PlayVOC
+ (
+ char *sample,
+ int pitchoffset,
+ int angle,
+ int volume,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ int handle;
+ int status;
+ playbackstatus soundstatus;
+ VoiceNode *voice;
+ unsigned flags;
+
+ // Make sure it's a valid VOC file.
+ status = strncmp( sample, "Creative Voice File", 19 );
+ if ( status != 0 )
+ {
+ // Tell multivoc that we had a bad VOC file
+ MV_ErrorCode = MV_InvalidVOCFile;
+
+ GUSWAVE_SetErrorCode( GUSWAVE_InvalidVOCFile );
+ return( GUSWAVE_Error );
+ }
+
+ // Request a voice from the voice pool
+ voice = GUSWAVE_AllocVoice( priority );
+ if ( voice == NULL )
+ {
+ if ( GUS_Debug )
+ {
+ DB_printf( "No more voices. Skipping sound.\n" );
+ }
+ GUSWAVE_SetErrorCode( GUSWAVE_NoVoices );
+ return( GUSWAVE_Warning );
+ }
+
+ voice->NextBlock = sample + *( unsigned short int * )( sample + 0x14 );
+ voice->LoopStart = NULL;
+ voice->LoopCount = 0;
+ voice->BlockLength = 0;
+ voice->PitchScale = PITCH_GetScale( pitchoffset );
+ voice->wavetype = VOC;
+ voice->bits = 8;
+ voice->GetSound = GUSWAVE_GetNextVOCBlock;
+ voice->length = 0;
+ voice->next = NULL;
+ voice->prev = NULL;
+ voice->priority = priority;
+ voice->callbackval = callbackval;
+
+ soundstatus = GUSWAVE_GetNextVOCBlock( voice );
+ if ( soundstatus == SoundDone )
+ {
+ flags = DisableInterrupts();
+ LL_AddToTail( VoiceNode, &VoicePool, voice );
+ RestoreInterrupts( flags );
+
+ if ( GUS_Debug )
+ {
+ DB_printf( "Voice ended before playback.\n" );
+ }
+
+ // Tell multivoc that we had a bad VOC file
+ MV_ErrorCode = MV_InvalidVOCFile;
+
+ GUSWAVE_SetErrorCode( GUSWAVE_InvalidVOCFile );
+ return( GUSWAVE_Error );
+ }
+
+ handle = GUSWAVE_Play( voice, angle, volume, 1 );
+ return( handle );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_PlayWAV
+
+ Begins playback of digitized sound.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_PlayWAV
+ (
+ char *sample,
+ int pitchoffset,
+ int angle,
+ int volume,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ VoiceNode *voice;
+ int handle;
+ int channels;
+ int bits;
+ int length;
+ riff_header *riff;
+ format_header *format;
+ data_header *data;
+
+ riff = ( riff_header * )sample;
+
+ if ( ( strncmp( riff->RIFF, "RIFF", 4 ) != 0 ) ||
+ ( strncmp( riff->WAVE, "WAVE", 4 ) != 0 ) ||
+ ( strncmp( riff->fmt, "fmt ", 4) != 0 ) )
+ {
+ GUSWAVE_SetErrorCode( GUSWAVE_InvalidWAVFile );
+ return( GUSWAVE_Error );
+ }
+
+ format = ( format_header * )( riff + 1 );
+ data = ( data_header * )( ( ( char * )format ) + riff->format_size );
+
+ if ( format->wFormatTag != 1 )
+ {
+ GUSWAVE_SetErrorCode( GUSWAVE_InvalidWAVFile );
+ return( GUSWAVE_Error );
+ }
+
+ channels = format->nChannels;
+ if ( ( channels != 1 ) && ( channels != 2 ) )
+ {
+ GUSWAVE_SetErrorCode( GUSWAVE_InvalidWAVFile );
+ return( GUSWAVE_Error );
+ }
+
+ bits = format->nBitsPerSample;
+ if ( ( bits != 8 ) && ( bits != 16 ) )
+ {
+ GUSWAVE_SetErrorCode( GUSWAVE_InvalidWAVFile );
+ return( GUSWAVE_Error );
+ }
+
+ if ( strncmp( data->DATA, "data", 4 ) != 0 )
+ {
+ GUSWAVE_SetErrorCode( GUSWAVE_InvalidWAVFile );
+ return( GUSWAVE_Error );
+ }
+
+ // Request a voice from the voice pool
+ voice = GUSWAVE_AllocVoice( priority );
+ if ( voice == NULL )
+ {
+ if ( GUS_Debug )
+ {
+ DB_printf( "No more voices. Skipping sound.\n" );
+ }
+ GUSWAVE_SetErrorCode( GUSWAVE_NoVoices );
+ return( GUSWAVE_Warning );
+ }
+
+ voice->wavetype = WAV;
+ voice->bits = bits;
+ voice->GetSound = GUSWAVE_GetNextWAVBlock;
+
+ length = data->size;
+
+ voice->Playing = TRUE;
+ voice->DemandFeed = NULL;
+ voice->LoopStart = NULL;
+ voice->LoopCount = 0;
+ voice->length = min( length, 0x8000 );
+ voice->BlockLength = length - voice->length;// min( loopend + 1, data->size );
+ voice->sound = ( char * )( data + 1 );
+ voice->NextBlock = voice->sound + voice->length;
+ voice->next = NULL;
+ voice->prev = NULL;
+ voice->priority = priority;
+ voice->callbackval = callbackval;
+ voice->LoopStart = NULL;// voice->NextBlock + loopstart;
+ voice->LoopEnd = NULL;//voice->NextBlock + min( loopend, data->size - 1 );
+ voice->LoopSize = 0;//( voice->LoopEnd - voice->LoopStart ) + 1;
+ voice->PitchScale = PITCH_GetScale( pitchoffset );
+ voice->SamplingRate = format->nSamplesPerSec;
+ voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) >> 16;
+
+ handle = GUSWAVE_Play( voice, angle, volume, channels );
+
+ return( handle );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_StartDemandFeedPlayback
+
+ Begins playback of digitized sound.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_StartDemandFeedPlayback
+ (
+ void ( *function )( char **ptr, unsigned long *length ),
+ int channels,
+ int bits,
+ int rate,
+ int pitchoffset,
+ int angle,
+ int volume,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ VoiceNode *voice;
+ int handle;
+
+ // Request a voice from the voice pool
+ voice = GUSWAVE_AllocVoice( priority );
+ if ( voice == NULL )
+ {
+ if ( GUS_Debug )
+ {
+ DB_printf( "No more voices. Skipping sound.\n" );
+ }
+ GUSWAVE_SetErrorCode( GUSWAVE_NoVoices );
+ return( GUSWAVE_Warning );
+ }
+
+ voice->wavetype = DemandFeed;
+ voice->bits = bits;
+ voice->GetSound = GUSWAVE_GetNextDemandFeedBlock;
+ voice->Playing = TRUE;
+ voice->DemandFeed = function;
+ voice->LoopStart = NULL;
+ voice->LoopCount = 0;
+ voice->BlockLength = 0;
+ voice->length = 256;
+ voice->sound = ( bits == 8 ) ? GUS_Silence8 : ( char * )GUS_Silence16;
+ voice->NextBlock = NULL;
+ voice->next = NULL;
+ voice->prev = NULL;
+ voice->priority = priority;
+ voice->callbackval = callbackval;
+ voice->PitchScale = PITCH_GetScale( pitchoffset );
+ voice->SamplingRate = rate;
+ voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) >> 16;
+
+ handle = GUSWAVE_Play( voice, angle, volume, channels );
+
+ return( handle );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_SetReverseStereo
+
+ Set the orientation of the left and right channels.
+---------------------------------------------------------------------*/
+
+void GUSWAVE_SetReverseStereo
+ (
+ int setting
+ )
+
+ {
+ GUSWAVE_SwapLeftRight = setting;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_GetReverseStereo
+
+ Returns the orientation of the left and right channels.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_GetReverseStereo
+ (
+ void
+ )
+
+ {
+ return( GUSWAVE_SwapLeftRight );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_InitVoices
+
+ Begins playback of digitized sound.
+---------------------------------------------------------------------*/
+
+static int GUSWAVE_InitVoices
+ (
+ void
+ )
+
+ {
+ int i;
+
+ for( i = 0; i < MAX_VOICES; i++ )
+ {
+ VoiceStatus[ i ].playing = FALSE;
+ VoiceStatus[ i ].Voice = NULL;
+ }
+
+ VoicePool.start = NULL;
+ VoicePool.end = NULL;
+ VoiceList.start = NULL;
+ VoiceList.end = NULL;
+
+ for( i = 0; i < VOICES; i++ )
+ {
+ GUSWAVE_Voices[ i ].num = -1;
+ GUSWAVE_Voices[ i ].Active = FALSE;
+ GUSWAVE_Voices[ i ].GF1voice = -1;
+ GUSWAVE_Voices[ i ].mem = NULL;
+ }
+
+ for( i = 0; i < VOICES; i++ )
+ {
+ GUSWAVE_Voices[ i ].num = i;
+ GUSWAVE_Voices[ i ].Active = FALSE;
+ GUSWAVE_Voices[ i ].GF1voice = 0;
+
+ GUSWAVE_Voices[ i ].mem = gf1_malloc( GF1BSIZE );
+ if ( GUSWAVE_Voices[ i ].mem == NULL )
+ {
+ GUSWAVE_MaxVoices = i;
+ if ( i < 1 )
+ {
+ if ( GUSMIDI_Installed )
+ {
+ GUSWAVE_SetErrorCode( GUSWAVE_UltraNoMemMIDI );
+ }
+ else
+ {
+ GUSWAVE_SetErrorCode( GUSWAVE_UltraNoMem );
+ }
+ return( GUSWAVE_Error );
+ }
+
+ break;
+ }
+
+ LL_AddToTail( VoiceNode, &VoicePool, &GUSWAVE_Voices[ i ] );
+ }
+
+ return( GUSWAVE_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_SetCallBack
+
+ Set the function to call when a voice stops.
+---------------------------------------------------------------------*/
+
+void GUSWAVE_SetCallBack
+ (
+ void ( *function )( unsigned long )
+ )
+
+ {
+ GUSWAVE_CallBackFunc = function;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: GUSWAVE_Init
+
+ Initializes the Gravis Ultrasound for digitized sound playback.
+---------------------------------------------------------------------*/
+
+int GUSWAVE_Init
+ (
+ int numvoices
+ )
+
+ {
+ int status;
+
+ if ( GUSWAVE_Installed )
+ {
+ GUSWAVE_Shutdown();
+ }
+
+ GUSWAVE_SetErrorCode( GUSWAVE_Ok );
+
+ status = GUS_Init();
+ if ( status != GUS_Ok )
+ {
+ GUSWAVE_SetErrorCode( GUSWAVE_GUSError );
+ return( GUSWAVE_Error );
+ }
+
+ GUS_Debug = USER_CheckParameter( "DEBUGGUS" );
+
+ GUSWAVE_MaxVoices = min( numvoices, VOICES );
+ GUSWAVE_MaxVoices = max( GUSWAVE_MaxVoices, 0 );
+
+ status = GUSWAVE_InitVoices();
+ if ( status != GUSWAVE_Ok )
+ {
+ GUS_Shutdown();
+ return( status );
+ }
+
+ GUSWAVE_SetReverseStereo( FALSE );
+
+ GUSWAVE_CallBackFunc = NULL;
+ GUSWAVE_Installed = TRUE;
+
+ return( GUSWAVE_Ok );
+ }
--- /dev/null
+++ b/rott/audiolib/guswave.h
@@ -1,0 +1,75 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: GUSWAVE.H
+
+ author: James R. Dose
+ date: March 23, 1994
+
+ Public header for for GUSWAVE.C
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __GUSWAVE_H
+#define __GUSWAVE_H
+
+#define GUSWAVE_MinVoiceHandle 1
+
+enum GUSWAVE_Errors
+ {
+ GUSWAVE_Warning = -2,
+ GUSWAVE_Error = -1,
+ GUSWAVE_Ok = 0,
+ GUSWAVE_GUSError,
+ GUSWAVE_NotInstalled,
+ GUSWAVE_NoVoices,
+ GUSWAVE_UltraNoMem,
+ GUSWAVE_UltraNoMemMIDI,
+ GUSWAVE_VoiceNotFound,
+ GUSWAVE_InvalidVOCFile,
+ GUSWAVE_InvalidWAVFile
+ };
+
+char *GUSWAVE_ErrorString( int ErrorNumber );
+int GUSWAVE_VoicePlaying( int handle );
+int GUSWAVE_VoicesPlaying( void );
+int GUSWAVE_Kill( int handle );
+int GUSWAVE_KillAllVoices( void );
+int GUSWAVE_SetPitch( int handle, int pitchoffset );
+int GUSWAVE_SetPan3D( int handle, int angle, int distance );
+void GUSWAVE_SetVolume( int volume );
+int GUSWAVE_GetVolume( void );
+int GUSWAVE_VoiceAvailable( int priority );
+int GUSWAVE_PlayVOC( char *sample, int pitchoffset, int angle, int volume,
+ int priority, unsigned long callbackval );
+int GUSWAVE_PlayWAV( char *sample, int pitchoffset, int angle, int volume,
+ int priority, unsigned long callbackval );
+int GUSWAVE_StartDemandFeedPlayback( void ( *function )( char **ptr, unsigned long *length ),
+ int channels, int bits, int rate, int pitchoffset, int angle,
+ int volume, int priority, unsigned long callbackval );
+void GUSWAVE_SetCallBack( void ( *function )( unsigned long ) );
+void GUSWAVE_SetReverseStereo( int setting );
+int GUSWAVE_GetReverseStereo( void );
+int GUSWAVE_Init( int numvoices );
+void GUSWAVE_Shutdown( void );
+#pragma aux GUSWAVE_Shutdown frame;
+
+#endif
--- /dev/null
+++ b/rott/audiolib/interrup.h
@@ -1,0 +1,50 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: INTERRUP.H
+
+ author: James R. Dose
+ date: March 31, 1994
+
+ Inline functions for disabling and restoring the interrupt flag.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __INTERRUPT_H
+#define __INTERRUPT_H
+
+unsigned long DisableInterrupts( void );
+void RestoreInterrupts( unsigned long flags );
+
+#ifdef PLAT_DOS
+#pragma aux DisableInterrupts = \
+ "pushfd", \
+ "pop eax", \
+ "cli" \
+ modify [ eax ];
+
+#pragma aux RestoreInterrupts = \
+ "push eax", \
+ "popfd" \
+ parm [ eax ];
+#endif
+
+#endif
--- /dev/null
+++ b/rott/audiolib/irq.c
@@ -1,0 +1,325 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: IRQ.C
+
+ author: James R. Dose
+ date: August 26, 1994
+
+ Low level routines to set and restore IRQ's through DPMI.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#include <dos.h>
+#include <stdlib.h>
+#include "irq.h"
+
+#define D32RealSeg(P) ( ( ( ( unsigned long )( P ) ) >> 4 ) & 0xFFFF )
+#define D32RealOff(P) ( ( ( unsigned long )( P ) ) & 0xF )
+
+typedef struct
+ {
+ unsigned long drdi;
+ unsigned long drsi;
+ unsigned long drbp;
+ unsigned long drxx;
+ unsigned long drbx;
+ unsigned long drdx;
+ unsigned long drcx;
+ unsigned long drax;
+
+ unsigned short drflags;
+ unsigned short dres;
+ unsigned short drds;
+ unsigned short drfs;
+ unsigned short drgs;
+ unsigned short drip;
+ unsigned short drcs;
+ unsigned short drsp;
+ unsigned short drss;
+ } DPMI_REGS;
+
+static DPMI_REGS rmregs = { 0 };
+static void ( __interrupt __far *IRQ_Callback )( void ) = NULL;
+
+static char *IRQ_RealModeCode = NULL;
+
+static unsigned short IRQ_CallBackSegment;
+static unsigned short IRQ_CallBackOffset;
+static unsigned short IRQ_RealModeSegment;
+static unsigned short IRQ_RealModeOffset;
+static unsigned long IRQ_ProtectedModeOffset;
+static unsigned short IRQ_ProtectedModeSelector;
+
+static union REGS Regs;
+static struct SREGS SegRegs;
+
+static void *D32DosMemAlloc
+ (
+ unsigned long size
+ )
+
+ {
+ // DPMI allocate DOS memory
+ Regs.x.eax = 0x0100;
+
+ // Number of paragraphs requested
+ Regs.x.ebx = ( size + 15 ) >> 4;
+
+ int386( 0x31, &Regs, &Regs );
+
+ if ( Regs.x.cflag != 0 )
+ {
+ // Failed
+ return ( ( unsigned long )0 );
+ }
+
+ return( ( void * )( ( Regs.x.eax & 0xFFFF ) << 4 ) );
+ }
+
+// Intermediary function: DPMI calls this, making it
+// easier to write in C
+// handle 16-bit incoming stack
+
+void fixebp
+ (
+ void
+ );
+
+#pragma aux fixebp = \
+ "mov bx, ss" \
+ "lar ebx, ebx" \
+ "bt ebx, 22" \
+ "jc bigstk" \
+ "movzx esp, sp" \
+ "mov ebp, esp" \
+ "bigstk:" \
+modify exact [ ebx ];
+
+#pragma aux rmcallback parm [];
+
+void rmcallback
+ (
+ unsigned short _far *stkp
+ )
+
+ {
+ // "Pop" the real mode return frame so we
+ // can resume where we left off
+ rmregs.drip = *stkp++;
+ rmregs.drcs = *stkp++;
+
+ rmregs.drsp = FP_OFF(stkp);
+
+ // Call protected-mode handler
+ IRQ_Callback();
+ }
+
+static void _interrupt _cdecl callback_x
+ (
+ // regs pushed in this order by prologue
+
+ int rgs,
+ int rfs,
+ int res,
+ int rds,
+ int rdi,
+ int rsi,
+ int rbp,
+ int rsp,
+ int rbx,
+ int rdx,
+ int rcx,
+ int rax
+ )
+
+ {
+// unsigned short _far *stkp;
+// return;
+
+ fixebp();
+ rmcallback (MK_FP(rds, rsi));
+ }
+
+/*
+static void _interrupt _cdecl callback_x
+ (
+ // regs pushed in this order by prologue
+
+ int rgs,
+ int rfs,
+ int res,
+ int rds,
+ int rdi,
+ int rsi,
+ int rbp,
+ int rsp,
+ int rbx,
+ int rdx,
+ int rcx,
+ int rax
+ )
+
+ {
+ unsigned short _far *stkp;
+
+ fixebp();
+ stkp = MK_FP(rds, rsi);
+
+ // "Pop" the real mode return frame so we
+ // can resume where we left off
+ rmregs.drip = *stkp++;
+ rmregs.drcs = *stkp++;
+
+ rmregs.drsp = FP_OFF(stkp);
+
+ // Call protected-mode handler
+ IRQ_Callback();
+ }
+*/
+
+
+int IRQ_SetVector
+ (
+ int vector,
+ void ( __interrupt __far *function )( void )
+ )
+
+ {
+ void far *fp;
+
+ IRQ_Callback = function;
+
+ // Save the starting real-mode and protected-mode handler addresses
+
+ // DPMI get protected mode vector */
+ Regs.w.ax = 0x0204;
+ Regs.w.bx = vector;
+ int386( 0x31, &Regs, &Regs );
+ IRQ_ProtectedModeSelector = Regs.w.cx;
+ IRQ_ProtectedModeOffset = Regs.x.edx;
+
+ // DPMI get real mode vector
+ Regs.w.ax = 0x0200;
+ Regs.w.bx = vector;
+ int386( 0x31, &Regs, &Regs );
+ IRQ_RealModeSegment = Regs.w.cx;
+ IRQ_RealModeOffset = Regs.w.dx;
+
+ // Set up callback
+ // DPMI allocate real mode callback
+ Regs.w.ax = 0x0303;
+ fp = ( void far * )callback_x;
+ SegRegs.ds = FP_SEG( fp );
+ Regs.x.esi = FP_OFF( fp );
+ fp = ( void _far * )&rmregs;
+ SegRegs.es = FP_SEG( fp );
+ Regs.x.edi = FP_OFF( fp );
+ int386x( 0x31, &Regs, &Regs, &SegRegs );
+
+ IRQ_CallBackSegment = Regs.w.cx;
+ IRQ_CallBackOffset = Regs.w.dx;
+
+ if ( Regs.x.cflag != 0 )
+ {
+ return( IRQ_Error );
+ }
+
+ if ( IRQ_RealModeCode == NULL )
+ {
+ // Allocate 6 bytes of low memory for real mode interrupt handler
+ IRQ_RealModeCode = D32DosMemAlloc( 6 );
+ if ( IRQ_RealModeCode == NULL )
+ {
+ // Free callback
+ Regs.w.ax = 0x304;
+ Regs.w.cx = IRQ_CallBackSegment;
+ Regs.w.dx = IRQ_CallBackOffset;
+ int386x( 0x31, &Regs, &Regs, &SegRegs );
+
+ return( IRQ_Error );
+ }
+ }
+
+ // Poke code (to call callback) into real mode handler
+
+ // CALL FAR PTR (callback)
+ IRQ_RealModeCode[ 0 ] = '\x9A';
+ *( ( unsigned short * )&IRQ_RealModeCode[ 1 ] ) = IRQ_CallBackOffset;
+ *( ( unsigned short * )&IRQ_RealModeCode[ 3 ] ) = IRQ_CallBackSegment;
+
+ // IRET
+ IRQ_RealModeCode[ 5 ] = '\xCF';
+
+ // Install protected mode handler
+ // DPMI set protected mode vector
+ Regs.w.ax = 0x0205;
+ Regs.w.bx = vector;
+ fp = function;
+
+ Regs.w.cx = FP_SEG( fp );
+ Regs.x.edx = FP_OFF( fp );
+ int386( 0x31, &Regs, &Regs );
+
+ // Install callback address as real mode handler
+ // DPMI set real mode vector
+ Regs.w.ax = 0x0201;
+ Regs.w.bx = vector;
+ Regs.w.cx = D32RealSeg( IRQ_RealModeCode );
+ Regs.w.dx = D32RealOff( IRQ_RealModeCode );
+ int386( 0x31, &Regs, &Regs );
+
+ return( IRQ_Ok );
+ }
+
+int IRQ_RestoreVector
+ (
+ int vector
+ )
+
+ {
+ // Restore original interrupt handlers
+ // DPMI set real mode vector
+ Regs.w.ax = 0x0201;
+ Regs.w.bx = vector;
+ Regs.w.cx = IRQ_RealModeSegment;
+ Regs.w.dx = IRQ_RealModeOffset;
+ int386( 0x31, &Regs, &Regs );
+
+ Regs.w.ax = 0x0205;
+ Regs.w.bx = vector;
+ Regs.w.cx = IRQ_ProtectedModeSelector;
+ Regs.x.edx = IRQ_ProtectedModeOffset;
+ int386( 0x31, &Regs, &Regs );
+
+ // Free callback
+ Regs.w.ax = 0x304;
+ Regs.w.cx = IRQ_CallBackSegment;
+ Regs.w.dx = IRQ_CallBackOffset;
+ int386x( 0x31, &Regs, &Regs, &SegRegs );
+
+ if ( Regs.x.cflag )
+ {
+ return( IRQ_Error );
+ }
+
+ return( IRQ_Ok );
+ }
--- /dev/null
+++ b/rott/audiolib/irq.h
@@ -1,0 +1,54 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: IRQ.H
+
+ author: James R. Dose
+ date: August 8, 1994
+
+ Public header for IRQ.C
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __IRQ_H
+#define __IRQ_H
+
+enum IRQ_ERRORS
+ {
+ IRQ_Warning = -2,
+ IRQ_Error = -1,
+ IRQ_Ok = 0,
+ };
+
+#define VALID_IRQ( irq ) ( ( ( irq ) >= 0 ) && ( ( irq ) <= 15 ) )
+
+int IRQ_SetVector
+ (
+ int vector,
+ void ( __interrupt *function )( void )
+ );
+int IRQ_RestoreVector
+ (
+ int vector
+ );
+
+
+#endif
--- /dev/null
+++ b/rott/audiolib/leetimbr.c
@@ -1,0 +1,290 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+typedef struct
+ {
+ unsigned char SAVEK[ 2 ];
+ unsigned char Level[ 2 ];
+ unsigned char Env1[ 2 ];
+ unsigned char Env2[ 2 ];
+ unsigned char Wave[ 2 ];
+ unsigned char Feedback;
+ signed char Transpose;
+ signed char Velocity;
+ } TIMBRE;
+
+TIMBRE ADLIB_TimbreBank[ 256 ] =
+ {
+ { { 33, 49 }, { 79, 0 }, { 242, 210 }, { 82, 115 }, { 0, 0 }, 6, 0 },
+ { { 19, 17 }, { 198, 10 }, { 242, 241 }, { 245, 245 }, { 1, 0 }, 0, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 3, 18 }, { 48, 16 }, { 246, 242 }, { 25, 244 }, { 0, 0 }, 15, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 24, 129 }, { 98, 0 }, { 243, 242 }, { 230, 246 }, { 0, 0 }, 0, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 23, 2 }, { 79, 16 }, { 242, 242 }, { 96, 114 }, { 0, 0 }, 8, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 178, 176 }, { 192, 134 }, { 159, 148 }, { 6, 15 }, { 1, 1 }, 9, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 178, 176 }, { 192, 128 }, { 159, 148 }, { 6, 15 }, { 1, 1 }, 9, 0 },
+ { { 130, 128 }, { 192, 134 }, { 145, 145 }, { 246, 246 }, { 1, 1 }, 9, 0 },
+ { { 36, 49 }, { 79, 27 }, { 242, 82 }, { 11, 11 }, { 0, 0 }, 14, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 35, 33 }, { 72, 0 }, { 149, 132 }, { 25, 25 }, { 1, 0 }, 8, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 19, 49 }, { 150, 128 }, { 254, 242 }, { 33, 148 }, { 0, 0 }, 10, 0 },
+ { { 1, 17 }, { 77, 0 }, { 242, 245 }, { 83, 116 }, { 1, 1 }, 8, 0 },
+ { { 33, 40 }, { 1, 9 }, { 148, 148 }, { 25, 9 }, { 0, 0 }, 6, 0 },
+ { { 33, 40 }, { 1, 19 }, { 148, 148 }, { 25, 9 }, { 0, 0 }, 6, 0 },
+ { { 36, 194 }, { 138, 3 }, { 250, 145 }, { 111, 248 }, { 0, 0 }, 8, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 33 }, { 26, 0 }, { 241, 246 }, { 207, 72 }, { 0, 0 }, 10, 0 },
+ { { 1, 34 }, { 29, 0 }, { 183, 196 }, { 34, 55 }, { 0, 0 }, 14, 0 },
+ { { 49, 34 }, { 30, 0 }, { 242, 241 }, { 239, 104 }, { 0, 0 }, 14, 0 },
+ { { 49, 34 }, { 30, 0 }, { 242, 245 }, { 239, 120 }, { 0, 0 }, 14, 0 },
+ { { 49, 34 }, { 30, 0 }, { 242, 245 }, { 239, 120 }, { 0, 0 }, 14, 0 },
+ { { 17, 49 }, { 5, 9 }, { 249, 241 }, { 37, 52 }, { 0, 0 }, 10, 0 },
+ { { 17, 49 }, { 5, 0 }, { 249, 241 }, { 37, 52 }, { 0, 0 }, 10, 0 },
+ { { 49, 114 }, { 138, 0 }, { 213, 97 }, { 25, 27 }, { 0, 0 }, 12, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 17, 17 }, { 150, 128 }, { 165, 245 }, { 85, 179 }, { 2, 1 }, 12, 0 },
+ { { 1, 17 }, { 156, 128 }, { 128, 240 }, { 5, 6 }, { 0, 0 }, 0, 0 },
+ { { 17, 17 }, { 150, 128 }, { 165, 245 }, { 85, 179 }, { 2, 1 }, 12, 0 },
+ { { 2, 1 }, { 153, 128 }, { 245, 246 }, { 85, 83 }, { 0, 0 }, 0, 0 },
+ { { 192, 0 }, { 13, 0 }, { 165, 212 }, { 67, 35 }, { 2, 1 }, 0, 0 },
+ { { 33, 32 }, { 88, 0 }, { 194, 97 }, { 227, 22 }, { 1, 3 }, 0, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 34 }, { 22, 0 }, { 176, 179 }, { 129, 44 }, { 0, 1 }, 12, 0 },
+ { { 49, 114 }, { 91, 131 }, { 244, 138 }, { 21, 5 }, { 0, 0 }, 0, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 33 }, { 29, 0 }, { 113, 129 }, { 174, 158 }, { 0, 0 }, 14, 0 },
+ { { 49, 97 }, { 28, 128 }, { 65, 146 }, { 11, 59 }, { 0, 0 }, 14, 0 },
+ { { 49, 241 }, { 28, 0 }, { 65, 146 }, { 11, 27 }, { 0, 0 }, 10, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 33 }, { 155, 0 }, { 97, 127 }, { 106, 10 }, { 0, 0 }, 2, 0 },
+ { { 225, 226 }, { 21, 3 }, { 113, 129 }, { 174, 158 }, { 0, 0 }, 14, 0 },
+ { { 33, 33 }, { 29, 0 }, { 113, 129 }, { 174, 158 }, { 0, 0 }, 14, 0 },
+ { { 33, 33 }, { 77, 0 }, { 84, 166 }, { 60, 28 }, { 0, 0 }, 8, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 50 }, { 79, 0 }, { 113, 82 }, { 83, 76 }, { 0, 0 }, 10, 0 },
+ { { 33, 50 }, { 79, 0 }, { 113, 82 }, { 83, 76 }, { 0, 0 }, 10, 0 },
+ { { 32, 49 }, { 78, 0 }, { 113, 82 }, { 104, 94 }, { 0, 0 }, 10, 0 },
+ { { 33, 33 }, { 75, 0 }, { 170, 143 }, { 22, 10 }, { 1, 0 }, 8, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 50, 97 }, { 154, 130 }, { 81, 162 }, { 27, 59 }, { 0, 0 }, 12, 0 },
+ { { 50, 33 }, { 192, 0 }, { 155, 114 }, { 33, 7 }, { 0, 0 }, 4, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 162 }, { 131, 141 }, { 116, 101 }, { 23, 23 }, { 0, 0 }, 7, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 225, 98 }, { 236, 0 }, { 110, 101 }, { 143, 42 }, { 0, 0 }, 14, 0 },
+ { { 50, 33 }, { 144, 0 }, { 155, 114 }, { 33, 23 }, { 0, 0 }, 4, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 245, 242 }, { 154, 128 }, { 12, 96 }, { 199, 165 }, { 0, 0 }, 13, 0 },
+ { { 98, 161 }, { 147, 0 }, { 119, 118 }, { 7, 7 }, { 0, 0 }, 11, 0 },
+ { { 34, 33 }, { 89, 8 }, { 255, 255 }, { 3, 15 }, { 2, 0 }, 0, 0 },
+ { { 33, 33 }, { 29, 0 }, { 113, 129 }, { 14, 14 }, { 0, 0 }, 14, 0 },
+ { { 34, 33 }, { 70, 128 }, { 134, 100 }, { 85, 24 }, { 0, 0 }, 0, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 113, 114 }, { 93, 0 }, { 84, 106 }, { 1, 3 }, { 0, 0 }, 0, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 0, 17 }, { 13, 128 }, { 241, 80 }, { 255, 255 }, { 0, 0 }, 6, 0 },
+ { { 33, 97 }, { 137, 3 }, { 17, 66 }, { 51, 37 }, { 0, 0 }, 10, 0 },
+ { { 0, 49 }, { 16, 128 }, { 17, 176 }, { 239, 15 }, { 0, 0 }, 10, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 164, 97 }, { 76, 16 }, { 243, 129 }, { 115, 35 }, { 1, 0 }, 4, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 1, 1 }, { 0, 0 }, { 255, 255 }, { 7, 7 }, { 0, 0 }, 7, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 1, 221 }, { 0, 0 }, { 246, 31 }, { 0, 6 }, { 2, 3 }, 12, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 36 },
+ { { 16, 17 }, { 68, 0 }, { 248, 243 }, { 119, 6 }, { 2, 0 }, 8, 36 },
+ { { 3, 15 }, { 0, 0 }, { 251, 245 }, { 43, 11 }, { 2, 0 }, 15, 36 },
+ { { 33, 0 }, { 128, 0 }, { 255, 249 }, { 7, 7 }, { 0, 1 }, 14, 36 },
+ { { 240, 229 }, { 192, 0 }, { 255, 251 }, { 255, 240 }, { 3, 0 }, 14, 48 },
+ { { 33, 0 }, { 128, 0 }, { 255, 248 }, { 10, 25 }, { 0, 1 }, 14, 36 },
+ { { 1, 0 }, { 0, 0 }, { 250, 242 }, { 124, 4 }, { 0, 0 }, 0, 48 },
+ { { 12, 18 }, { 0, 0 }, { 246, 251 }, { 8, 71 }, { 0, 2 }, 10, 69 },
+ { { 1, 0 }, { 0, 0 }, { 250, 242 }, { 124, 4 }, { 0, 0 }, 0, 52 },
+ { { 14, 0 }, { 64, 8 }, { 118, 119 }, { 79, 24 }, { 0, 2 }, 14, 48 },
+ { { 1, 0 }, { 0, 0 }, { 250, 242 }, { 124, 4 }, { 0, 0 }, 0, 55 },
+ { { 2, 5 }, { 3, 10 }, { 180, 151 }, { 4, 247 }, { 0, 0 }, 14, 57 },
+ { { 1, 0 }, { 0, 0 }, { 250, 242 }, { 124, 4 }, { 0, 0 }, 0, 58 },
+ { { 1, 0 }, { 0, 0 }, { 250, 242 }, { 124, 4 }, { 0, 0 }, 0, 60 },
+ { { 1, 221 }, { 12, 0 }, { 246, 159 }, { 0, 2 }, { 0, 3 }, 12, 62 },
+ { { 1, 0 }, { 0, 0 }, { 250, 242 }, { 124, 4 }, { 0, 0 }, 0, 63 },
+ { { 12, 18 }, { 0, 0 }, { 246, 203 }, { 2, 67 }, { 0, 2 }, 10, 70 },
+ { { 12, 18 }, { 0, 0 }, { 246, 203 }, { 2, 19 }, { 0, 2 }, 10, 70 },
+ { { 14, 7 }, { 6, 68 }, { 248, 244 }, { 66, 228 }, { 3, 3 }, 14, 53 },
+ { { 14, 0 }, { 64, 8 }, { 150, 183 }, { 79, 24 }, { 0, 2 }, 14, 48 },
+ { { 1, 221 }, { 0, 0 }, { 246, 159 }, { 0, 2 }, { 2, 3 }, 12, 84 },
+ { { 2, 9 }, { 27, 0 }, { 245, 246 }, { 118, 214 }, { 2, 0 }, 4, 43 },
+ { { 0, 223 }, { 9, 0 }, { 246, 147 }, { 0, 67 }, { 0, 2 }, 14, 56 },
+ { { 128, 144 }, { 13, 0 }, { 248, 159 }, { 0, 4 }, { 2, 3 }, 14, 24 },
+ { { 12, 18 }, { 0, 0 }, { 246, 203 }, { 2, 67 }, { 0, 2 }, 10, 65 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 1, 2 }, { 84, 0 }, { 250, 248 }, { 141, 184 }, { 0, 0 }, 6, 48 },
+ { { 1, 2 }, { 84, 0 }, { 250, 248 }, { 141, 184 }, { 0, 0 }, 6, 51 },
+ { { 1, 2 }, { 84, 0 }, { 250, 248 }, { 141, 184 }, { 0, 0 }, 6, 54 },
+ { { 2, 4 }, { 0, 0 }, { 250, 200 }, { 191, 151 }, { 0, 0 }, 11, 42 },
+ { { 2, 4 }, { 0, 0 }, { 250, 200 }, { 191, 151 }, { 0, 0 }, 11, 39 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 14, 0 }, { 64, 8 }, { 118, 119 }, { 79, 24 }, { 0, 2 }, 14, 64 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 128, 17 }, { 0, 0 }, { 255, 111 }, { 6, 22 }, { 3, 0 }, 14, 52 },
+ { { 128, 17 }, { 0, 0 }, { 255, 79 }, { 6, 22 }, { 3, 0 }, 14, 52 },
+ { { 6, 21 }, { 63, 0 }, { 0, 247 }, { 244, 245 }, { 0, 0 }, 1, 60 },
+ { { 6, 21 }, { 63, 0 }, { 0, 247 }, { 244, 245 }, { 0, 0 }, 1, 66 },
+ { { 6, 21 }, { 63, 0 }, { 0, 247 }, { 244, 245 }, { 0, 0 }, 1, 59 },
+ { { 65, 66 }, { 69, 0 }, { 252, 105 }, { 69, 5 }, { 0, 0 }, 0, 91 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 23, 2 }, { 79, 16 }, { 242, 242 }, { 96, 114 }, { 0, 0 }, 8, 109 },
+ { { 14, 0 }, { 64, 8 }, { 118, 119 }, { 79, 24 }, { 0, 2 }, 14, 64 },
+ { { 133, 132 }, { 5, 64 }, { 249, 214 }, { 50, 165 }, { 3, 0 }, 14, 79 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 },
+ { { 33, 17 }, { 17, 0 }, { 163, 196 }, { 67, 34 }, { 2, 0 }, 13, 0 }
+ };
--- /dev/null
+++ b/rott/audiolib/linklist.h
@@ -1,0 +1,118 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef __linklist_h
+#define __linklist_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define NewNode(type) ((type*)SafeMalloc(sizeof(type)))
+
+
+#define LL_CreateNewLinkedList(rootnode,type,next,prev) \
+ { \
+ (rootnode) = NewNode(type); \
+ (rootnode)->prev = (rootnode); \
+ (rootnode)->next = (rootnode); \
+ }
+
+
+
+#define LL_AddNode(rootnode, newnode, next, prev) \
+ { \
+ (newnode)->next = (rootnode); \
+ (newnode)->prev = (rootnode)->prev; \
+ (rootnode)->prev->next = (newnode); \
+ (rootnode)->prev = (newnode); \
+ }
+
+#define LL_TransferList(oldroot,newroot,next,prev) \
+ { \
+ if ((oldroot)->prev != (oldroot)) \
+ { \
+ (oldroot)->prev->next = (newroot); \
+ (oldroot)->next->prev = (newroot)->prev; \
+ (newroot)->prev->next = (oldroot)->next; \
+ (newroot)->prev = (oldroot)->prev; \
+ (oldroot)->next = (oldroot); \
+ (oldroot)->prev = (oldroot); \
+ } \
+ }
+
+#define LL_ReverseList(root,type,next,prev) \
+ { \
+ type *newend,*trav,*tprev; \
+ \
+ newend = (root)->next; \
+ for(trav = (root)->prev; trav != newend; trav = tprev) \
+ { \
+ tprev = trav->prev; \
+ LL_MoveNode(trav,newend,next,prev); \
+ } \
+ }
+
+
+#define LL_RemoveNode(node,next,prev) \
+ { \
+ (node)->prev->next = (node)->next; \
+ (node)->next->prev = (node)->prev; \
+ (node)->next = (node); \
+ (node)->prev = (node); \
+ }
+
+
+#define LL_SortedInsertion(rootnode,insertnode,next,prev,type,sortparm) \
+ { \
+ type *hoya; \
+ \
+ hoya = (rootnode)->next; \
+ while((hoya != (rootnode)) && ((insertnode)->sortparm > hoya->sortparm)) \
+ { \
+ hoya = hoya->next; \
+ } \
+ LL_AddNode(hoya,(insertnode),next,prev); \
+ }
+
+#define LL_MoveNode(node,newroot,next,prev) \
+ { \
+ LL_RemoveNode((node),next,prev); \
+ LL_AddNode((newroot),(node),next,prev); \
+ }
+
+#define LL_ListEmpty(list,next,prev) \
+ ( \
+ ((list)->next == (list)) && \
+ ((list)->prev == (list)) \
+ )
+
+#define LL_Free(list) SafeFree(list)
+#define LL_Reset(list,next,prev) (list)->next = (list)->prev = (list)
+#define LL_New LL_CreateNewLinkedList
+#define LL_Remove LL_RemoveNode
+#define LL_Add LL_AddNode
+#define LL_Empty LL_ListEmpty
+#define LL_Move LL_MoveNode
+
+
+#ifdef __cplusplus
+};
+#endif
+#endif
--- /dev/null
+++ b/rott/audiolib/ll_man.c
@@ -1,0 +1,173 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: LL_MAN.C
+
+ author: James R. Dose
+ date: January 1, 1994
+
+ Linked list management routines.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#define LOCKMEMORY
+
+#include <stddef.h>
+#include "ll_man.h"
+
+#ifdef LOCKMEMORY
+#include "dpmi.h"
+#endif
+
+#define OFFSET( structure, offset ) \
+ ( *( ( char ** )&( structure )[ offset ] ) )
+
+
+/**********************************************************************
+
+ Memory locked functions:
+
+**********************************************************************/
+
+
+#define LL_LockStart LL_AddNode
+
+
+void LL_AddNode
+ (
+ char *item,
+ char **head,
+ char **tail,
+ int next,
+ int prev
+ )
+
+ {
+ OFFSET( item, prev ) = NULL;
+ OFFSET( item, next ) = *head;
+
+ if ( *head )
+ {
+ OFFSET( *head, prev ) = item;
+ }
+ else
+ {
+ *tail = item;
+ }
+
+ *head = item;
+ }
+
+void LL_RemoveNode
+ (
+ char *item,
+ char **head,
+ char **tail,
+ int next,
+ int prev
+ )
+
+ {
+ if ( OFFSET( item, prev ) == NULL )
+ {
+ *head = OFFSET( item, next );
+ }
+ else
+ {
+ OFFSET( OFFSET( item, prev ), next ) = OFFSET( item, next );
+ }
+
+ if ( OFFSET( item, next ) == NULL )
+ {
+ *tail = OFFSET( item, prev );
+ }
+ else
+ {
+ OFFSET( OFFSET( item, next ), prev ) = OFFSET( item, prev );
+ }
+
+ OFFSET( item, next ) = NULL;
+ OFFSET( item, prev ) = NULL;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: LL_LockEnd
+
+ Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void LL_LockEnd
+ (
+ void
+ )
+
+ {
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: LL_UnlockMemory
+
+ Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+void LL_UnlockMemory
+ (
+ void
+ )
+
+ {
+#ifdef LOCKMEMORY
+
+ DPMI_UnlockMemoryRegion( LL_LockStart, LL_LockEnd );
+
+#endif
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: LL_LockMemory
+
+ Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+int LL_LockMemory
+ (
+ void
+ )
+
+ {
+
+#ifdef LOCKMEMORY
+
+ int status;
+
+ status = DPMI_LockMemoryRegion( LL_LockStart, LL_LockEnd );
+ if ( status != DPMI_Ok )
+ {
+ return( LL_Error );
+ }
+
+#endif
+
+ return( LL_Ok );
+ }
--- /dev/null
+++ b/rott/audiolib/ll_man.h
@@ -1,0 +1,76 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: LL_MAN.H
+
+ author: James R. Dose
+ date: February 4, 1994
+
+ Public header for LL_MAN.C. Linked list management routines.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __LL_MAN_H
+#define __LL_MAN_H
+
+enum LL_Errors
+ {
+ LL_Warning = -2,
+ LL_Error = -1,
+ LL_Ok = 0
+ };
+
+typedef struct list
+ {
+ void *start;
+ void *end;
+ } list;
+
+void LL_AddNode( char *node, char **head, char **tail, int next, int prev );
+void LL_RemoveNode( char *node, char **head, char **tail, int next, int prev );
+void LL_UnlockMemory( void );
+int LL_LockMemory( void );
+
+#define LL_AddToHead( type, listhead, node ) \
+ LL_AddNode( ( char * )( node ), \
+ ( char ** )&( ( listhead )->start ), \
+ ( char ** )&( ( listhead )->end ), \
+ ( int )&( ( type * ) 0 )->next, \
+ ( int )&( ( type * ) 0 )->prev )
+
+#define LL_AddToTail( type, listhead, node ) \
+ LL_AddNode( ( char * )( node ), \
+ ( char ** )&( ( listhead )->end ), \
+ ( char ** )&( ( listhead )->start ), \
+ ( int )&( ( type * ) 0 )->prev, \
+ ( int )&( ( type * ) 0 )->next )
+
+#define LL_Remove( type, listhead, node ) \
+ LL_RemoveNode( ( char * )( node ), \
+ ( char ** )&( ( listhead )->start ), \
+ ( char ** )&( ( listhead )->end ), \
+ ( int )&( ( type * ) 0 )->next, \
+ ( int )&( ( type * ) 0 )->prev )
+
+#define LL_NextNode( node ) ( ( node )->next )
+#define LL_PreviousNode( node ) ( ( node )->prev )
+
+#endif
--- /dev/null
+++ b/rott/audiolib/midi.c
@@ -1,0 +1,2265 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: MIDI.C
+
+ author: James R. Dose
+ date: May 25, 1994
+
+ Midi song file playback routines.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#include <stdlib.h>
+#include <time.h>
+#include <dos.h>
+#include <string.h>
+#include "sndcards.h"
+#include "interrup.h"
+#include "dpmi.h"
+#include "standard.h"
+#include "task_man.h"
+#include "ll_man.h"
+#include "usrhooks.h"
+#include "music.h"
+#include "_midi.h"
+#include "midi.h"
+#include "debugio.h"
+
+extern int MUSIC_SoundDevice;
+
+static const int _MIDI_CommandLengths[ NUM_MIDI_CHANNELS ] =
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 2, 0
+ };
+
+static int cdecl ( *_MIDI_RerouteFunctions[ NUM_MIDI_CHANNELS ] )
+ (
+ int event,
+ int c1,
+ int c2
+ ) = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+
+static track *_MIDI_TrackPtr = NULL;
+static int _MIDI_TrackMemSize;
+static int _MIDI_NumTracks;
+
+static int _MIDI_SongActive = FALSE;
+static int _MIDI_SongLoaded = FALSE;
+static int _MIDI_Loop = FALSE;
+
+static task *_MIDI_PlayRoutine = NULL;
+
+static int _MIDI_Division;
+static int _MIDI_Tick = 0;
+static int _MIDI_Beat = 1;
+static int _MIDI_Measure = 1;
+static unsigned _MIDI_Time;
+static int _MIDI_BeatsPerMeasure;
+static int _MIDI_TicksPerBeat;
+static int _MIDI_TimeBase;
+static long _MIDI_FPSecondsPerTick;
+static unsigned _MIDI_TotalTime;
+static int _MIDI_TotalTicks;
+static int _MIDI_TotalBeats;
+static int _MIDI_TotalMeasures;
+
+static unsigned long _MIDI_PositionInTicks;
+
+static int _MIDI_Context;
+
+static int _MIDI_ActiveTracks;
+static int _MIDI_TotalVolume = MIDI_MaxVolume;
+
+static int _MIDI_ChannelVolume[ NUM_MIDI_CHANNELS ];
+static int _MIDI_UserChannelVolume[ NUM_MIDI_CHANNELS ] =
+ {
+ 256, 256, 256, 256, 256, 256, 256, 256,
+ 256, 256, 256, 256, 256, 256, 256, 256
+ };
+
+static midifuncs *_MIDI_Funcs = NULL;
+
+static int Reset = FALSE;
+
+int MIDI_Tempo = 120;
+
+char MIDI_PatchMap[ 128 ];
+
+
+/**********************************************************************
+
+ Memory locked functions:
+
+**********************************************************************/
+
+
+#define MIDI_LockStart _MIDI_ReadNumber
+
+
+/*---------------------------------------------------------------------
+ Function: _MIDI_ReadNumber
+
+ Reads a variable length number from a MIDI track.
+---------------------------------------------------------------------*/
+
+static long _MIDI_ReadNumber
+ (
+ void *from,
+ size_t size
+ )
+
+ {
+ unsigned char *FromPtr;
+ long value;
+
+ if ( size > 4 )
+ {
+ size = 4;
+ }
+
+ FromPtr = ( unsigned char * )from;
+
+ value = 0;
+ while( size-- )
+ {
+ value <<= 8;
+ value += *FromPtr++;
+ }
+
+ return( value );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: _MIDI_ReadDelta
+
+ Reads a variable length encoded delta delay time from the MIDI data.
+---------------------------------------------------------------------*/
+
+static long _MIDI_ReadDelta
+ (
+ track *ptr
+ )
+
+ {
+ long value;
+ unsigned char c;
+
+ GET_NEXT_EVENT( ptr, value );
+
+ if ( value & 0x80 )
+ {
+ value &= 0x7f;
+ do
+ {
+ GET_NEXT_EVENT( ptr, c );
+ value = ( value << 7 ) + ( c & 0x7f );
+ }
+ while ( c & 0x80 );
+ }
+
+ return( value );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: _MIDI_ResetTracks
+
+ Sets the track pointers to the beginning of the song.
+---------------------------------------------------------------------*/
+
+static void _MIDI_ResetTracks
+ (
+ void
+ )
+
+ {
+ int i;
+ track *ptr;
+
+ _MIDI_Tick = 0;
+ _MIDI_Beat = 1;
+ _MIDI_Measure = 1;
+ _MIDI_Time = 0;
+ _MIDI_BeatsPerMeasure = 4;
+ _MIDI_TicksPerBeat = _MIDI_Division;
+ _MIDI_TimeBase = 4;
+
+ _MIDI_PositionInTicks = 0;
+ _MIDI_ActiveTracks = 0;
+ _MIDI_Context = 0;
+
+ ptr = _MIDI_TrackPtr;
+ for( i = 0; i < _MIDI_NumTracks; i++ )
+ {
+ ptr->pos = ptr->start;
+ ptr->delay = _MIDI_ReadDelta( ptr );
+ ptr->active = ptr->EMIDI_IncludeTrack;
+ ptr->RunningStatus = 0;
+ ptr->currentcontext = 0;
+ ptr->context[ 0 ].loopstart = ptr->start;
+ ptr->context[ 0 ].loopcount = 0;
+
+ if ( ptr->active )
+ {
+ _MIDI_ActiveTracks++;
+ }
+
+ ptr++;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: _MIDI_AdvanceTick
+
+ Increment tick counters.
+---------------------------------------------------------------------*/
+
+static void _MIDI_AdvanceTick
+ (
+ void
+ )
+
+ {
+ _MIDI_PositionInTicks++;
+ _MIDI_Time += _MIDI_FPSecondsPerTick;
+
+ _MIDI_Tick++;
+ while( _MIDI_Tick > _MIDI_TicksPerBeat )
+ {
+ _MIDI_Tick -= _MIDI_TicksPerBeat;
+ _MIDI_Beat++;
+ }
+ while( _MIDI_Beat > _MIDI_BeatsPerMeasure )
+ {
+ _MIDI_Beat -= _MIDI_BeatsPerMeasure;
+ _MIDI_Measure++;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: _MIDI_SysEx
+
+ Interpret SysEx Event.
+---------------------------------------------------------------------*/
+
+static void _MIDI_SysEx
+ (
+ track *Track
+ )
+
+ {
+ int length;
+
+ length = _MIDI_ReadDelta( Track );
+ Track->pos += length;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: _MIDI_MetaEvent
+
+ Interpret Meta Event.
+---------------------------------------------------------------------*/
+
+static void _MIDI_MetaEvent
+ (
+ track *Track
+ )
+
+ {
+ int command;
+ int length;
+ int denominator;
+ long tempo;
+
+ GET_NEXT_EVENT( Track, command );
+ GET_NEXT_EVENT( Track, length );
+
+ switch( command )
+ {
+ case MIDI_END_OF_TRACK :
+ Track->active = FALSE;
+
+ _MIDI_ActiveTracks--;
+ break;
+
+ case MIDI_TEMPO_CHANGE :
+ tempo = 60000000L / _MIDI_ReadNumber( Track->pos, 3 );
+ MIDI_SetTempo( tempo );
+ break;
+
+ case MIDI_TIME_SIGNATURE :
+ if ( ( _MIDI_Tick > 0 ) || ( _MIDI_Beat > 1 ) )
+ {
+ _MIDI_Measure++;
+ }
+
+ _MIDI_Tick = 0;
+ _MIDI_Beat = 1;
+
+ _MIDI_BeatsPerMeasure = (int)*Track->pos;
+ denominator = (int)*( Track->pos + 1 );
+ _MIDI_TimeBase = 1;
+ while( denominator > 0 )
+ {
+ _MIDI_TimeBase += _MIDI_TimeBase;
+ denominator--;
+ }
+ _MIDI_TicksPerBeat = ( _MIDI_Division * 4 ) / _MIDI_TimeBase;
+ break;
+ }
+
+ Track->pos += length;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: _MIDI_InterpretControllerInfo
+
+ Interprets the MIDI controller info.
+---------------------------------------------------------------------*/
+
+static int _MIDI_InterpretControllerInfo
+ (
+ track *Track,
+ int TimeSet,
+ int channel,
+ int c1,
+ int c2
+ )
+
+ {
+ track *trackptr;
+ int tracknum;
+ int loopcount;
+
+ switch( c1 )
+ {
+ case MIDI_MONO_MODE_ON :
+ Track->pos++;
+ break;
+
+ case MIDI_VOLUME :
+ if ( !Track->EMIDI_VolumeChange )
+ {
+ _MIDI_SetChannelVolume( channel, c2 );
+ }
+ break;
+
+ case EMIDI_INCLUDE_TRACK :
+ case EMIDI_EXCLUDE_TRACK :
+ break;
+
+ case EMIDI_PROGRAM_CHANGE :
+ if ( Track->EMIDI_ProgramChange )
+ {
+ _MIDI_Funcs->ProgramChange( channel, MIDI_PatchMap[ c2 & 0x7f ] );
+ }
+ break;
+
+ case EMIDI_VOLUME_CHANGE :
+ if ( Track->EMIDI_VolumeChange )
+ {
+ _MIDI_SetChannelVolume( channel, c2 );
+ }
+ break;
+
+ case EMIDI_CONTEXT_START :
+ break;
+
+ case EMIDI_CONTEXT_END :
+ if ( ( Track->currentcontext == _MIDI_Context ) ||
+ ( _MIDI_Context < 0 ) ||
+ ( Track->context[ _MIDI_Context ].pos == NULL ) )
+ {
+ break;
+ }
+
+ Track->currentcontext = _MIDI_Context;
+ Track->context[ 0 ].loopstart = Track->context[ _MIDI_Context ].loopstart;
+ Track->context[ 0 ].loopcount = Track->context[ _MIDI_Context ].loopcount;
+ Track->pos = Track->context[ _MIDI_Context ].pos;
+ Track->RunningStatus = Track->context[ _MIDI_Context ].RunningStatus;
+
+ if ( TimeSet )
+ {
+ break;
+ }
+
+ _MIDI_Time = Track->context[ _MIDI_Context ].time;
+ _MIDI_FPSecondsPerTick = Track->context[ _MIDI_Context ].FPSecondsPerTick;
+ _MIDI_Tick = Track->context[ _MIDI_Context ].tick;
+ _MIDI_Beat = Track->context[ _MIDI_Context ].beat;
+ _MIDI_Measure = Track->context[ _MIDI_Context ].measure;
+ _MIDI_BeatsPerMeasure = Track->context[ _MIDI_Context ].BeatsPerMeasure;
+ _MIDI_TicksPerBeat = Track->context[ _MIDI_Context ].TicksPerBeat;
+ _MIDI_TimeBase = Track->context[ _MIDI_Context ].TimeBase;
+ TimeSet = TRUE;
+ break;
+
+ case EMIDI_LOOP_START :
+ case EMIDI_SONG_LOOP_START :
+ if ( c2 == 0 )
+ {
+ loopcount = EMIDI_INFINITE;
+ }
+ else
+ {
+ loopcount = c2;
+ }
+
+ if ( c1 == EMIDI_SONG_LOOP_START )
+ {
+ trackptr = _MIDI_TrackPtr;
+ tracknum = _MIDI_NumTracks;
+ }
+ else
+ {
+ trackptr = Track;
+ tracknum = 1;
+ }
+
+ while( tracknum > 0 )
+ {
+ trackptr->context[ 0 ].loopcount = loopcount;
+ trackptr->context[ 0 ].pos = trackptr->pos;
+ trackptr->context[ 0 ].loopstart = trackptr->pos;
+ trackptr->context[ 0 ].RunningStatus = trackptr->RunningStatus;
+ trackptr->context[ 0 ].active = trackptr->active;
+ trackptr->context[ 0 ].delay = trackptr->delay;
+ trackptr->context[ 0 ].time = _MIDI_Time;
+ trackptr->context[ 0 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick;
+ trackptr->context[ 0 ].tick = _MIDI_Tick;
+ trackptr->context[ 0 ].beat = _MIDI_Beat;
+ trackptr->context[ 0 ].measure = _MIDI_Measure;
+ trackptr->context[ 0 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure;
+ trackptr->context[ 0 ].TicksPerBeat = _MIDI_TicksPerBeat;
+ trackptr->context[ 0 ].TimeBase = _MIDI_TimeBase;
+ trackptr++;
+ tracknum--;
+ }
+ break;
+
+ case EMIDI_LOOP_END :
+ case EMIDI_SONG_LOOP_END :
+ if ( ( c2 != EMIDI_END_LOOP_VALUE ) ||
+ ( Track->context[ 0 ].loopstart == NULL ) ||
+ ( Track->context[ 0 ].loopcount == 0 ) )
+ {
+ break;
+ }
+
+ if ( c1 == EMIDI_SONG_LOOP_END )
+ {
+ trackptr = _MIDI_TrackPtr;
+ tracknum = _MIDI_NumTracks;
+ _MIDI_ActiveTracks = 0;
+ }
+ else
+ {
+ trackptr = Track;
+ tracknum = 1;
+ _MIDI_ActiveTracks--;
+ }
+
+ while( tracknum > 0 )
+ {
+ if ( trackptr->context[ 0 ].loopcount != EMIDI_INFINITE )
+ {
+ trackptr->context[ 0 ].loopcount--;
+ }
+
+ trackptr->pos = trackptr->context[ 0 ].loopstart;
+ trackptr->RunningStatus = trackptr->context[ 0 ].RunningStatus;
+ trackptr->delay = trackptr->context[ 0 ].delay;
+ trackptr->active = trackptr->context[ 0 ].active;
+ if ( trackptr->active )
+ {
+ _MIDI_ActiveTracks++;
+ }
+
+ if ( !TimeSet )
+ {
+ _MIDI_Time = trackptr->context[ 0 ].time;
+ _MIDI_FPSecondsPerTick = trackptr->context[ 0 ].FPSecondsPerTick;
+ _MIDI_Tick = trackptr->context[ 0 ].tick;
+ _MIDI_Beat = trackptr->context[ 0 ].beat;
+ _MIDI_Measure = trackptr->context[ 0 ].measure;
+ _MIDI_BeatsPerMeasure = trackptr->context[ 0 ].BeatsPerMeasure;
+ _MIDI_TicksPerBeat = trackptr->context[ 0 ].TicksPerBeat;
+ _MIDI_TimeBase = trackptr->context[ 0 ].TimeBase;
+ TimeSet = TRUE;
+ }
+
+ trackptr++;
+ tracknum--;
+ }
+ break;
+
+ default :
+ if ( _MIDI_Funcs->ControlChange )
+ {
+ _MIDI_Funcs->ControlChange( channel, c1, c2 );
+ }
+ }
+
+ return TimeSet;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: _MIDI_ServiceRoutine
+
+ Task that interperates the MIDI data.
+---------------------------------------------------------------------*/
+// NOTE: We have to use a stack frame here because of a strange bug
+// that occurs with Watcom. This means that we cannot access Task!
+//Turned off to test if it works with Watcom 10a
+//#pragma aux _MIDI_ServiceRoutine frame;
+/*
+static void test
+ (
+ task *Task
+ )
+ {
+ _MIDI_ServiceRoutine( Task );
+ _MIDI_ServiceRoutine( Task );
+ _MIDI_ServiceRoutine( Task );
+ _MIDI_ServiceRoutine( Task );
+ }
+*/
+static void _MIDI_ServiceRoutine
+ (
+ task *Task
+ )
+
+ {
+ int event;
+ int channel;
+ int command;
+ track *Track;
+ int tracknum;
+ int status;
+ int c1;
+ int c2;
+ int TimeSet = FALSE;
+
+ if ( !_MIDI_SongActive )
+ {
+ return;
+ }
+
+ Track = _MIDI_TrackPtr;
+ tracknum = 0;
+ while( tracknum < _MIDI_NumTracks )
+ {
+ while ( ( Track->active ) && ( Track->delay == 0 ) )
+ {
+ GET_NEXT_EVENT( Track, event );
+
+ if ( GET_MIDI_COMMAND( event ) == MIDI_SPECIAL )
+ {
+ switch( event )
+ {
+ case MIDI_SYSEX :
+ case MIDI_SYSEX_CONTINUE :
+ _MIDI_SysEx( Track );
+ break;
+
+ case MIDI_META_EVENT :
+ _MIDI_MetaEvent( Track );
+ break;
+ }
+
+ if ( Track->active )
+ {
+ Track->delay = _MIDI_ReadDelta( Track );
+ }
+
+ continue;
+ }
+
+ if ( event & MIDI_RUNNING_STATUS )
+ {
+ Track->RunningStatus = event;
+ }
+ else
+ {
+ event = Track->RunningStatus;
+ Track->pos--;
+ }
+
+ channel = GET_MIDI_CHANNEL( event );
+ command = GET_MIDI_COMMAND( event );
+
+ if ( _MIDI_CommandLengths[ command ] > 0 )
+ {
+ GET_NEXT_EVENT( Track, c1 );
+ if ( _MIDI_CommandLengths[ command ] > 1 )
+ {
+ GET_NEXT_EVENT( Track, c2 );
+ }
+ }
+
+ if ( _MIDI_RerouteFunctions[ channel ] != NULL )
+ {
+ status = _MIDI_RerouteFunctions[ channel ]( event, c1, c2 );
+
+ if ( status == MIDI_DONT_PLAY )
+ {
+ Track->delay = _MIDI_ReadDelta( Track );
+ continue;
+ }
+ }
+
+ switch ( command )
+ {
+ case MIDI_NOTE_OFF :
+ if ( _MIDI_Funcs->NoteOff )
+ {
+ _MIDI_Funcs->NoteOff( channel, c1, c2 );
+ }
+ break;
+
+ case MIDI_NOTE_ON :
+ if ( _MIDI_Funcs->NoteOn )
+ {
+ _MIDI_Funcs->NoteOn( channel, c1, c2 );
+ }
+ break;
+
+ case MIDI_POLY_AFTER_TCH :
+ if ( _MIDI_Funcs->PolyAftertouch )
+ {
+ _MIDI_Funcs->PolyAftertouch( channel, c1, c2 );
+ }
+ break;
+
+ case MIDI_CONTROL_CHANGE :
+ TimeSet = _MIDI_InterpretControllerInfo( Track, TimeSet,
+ channel, c1, c2 );
+ break;
+
+ case MIDI_PROGRAM_CHANGE :
+ if ( ( _MIDI_Funcs->ProgramChange ) &&
+ ( !Track->EMIDI_ProgramChange ) )
+ {
+ _MIDI_Funcs->ProgramChange( channel, MIDI_PatchMap[ c1 & 0x7f ] );
+ }
+ break;
+
+ case MIDI_AFTER_TOUCH :
+ if ( _MIDI_Funcs->ChannelAftertouch )
+ {
+ _MIDI_Funcs->ChannelAftertouch( channel, c1 );
+ }
+ break;
+
+ case MIDI_PITCH_BEND :
+ if ( _MIDI_Funcs->PitchBend )
+ {
+ _MIDI_Funcs->PitchBend( channel, c1, c2 );
+ }
+ break;
+
+ default :
+ break;
+ }
+
+ Track->delay = _MIDI_ReadDelta( Track );
+ }
+
+ Track->delay--;
+ Track++;
+ tracknum++;
+
+ if ( _MIDI_ActiveTracks == 0 )
+ {
+ _MIDI_ResetTracks();
+ if ( _MIDI_Loop )
+ {
+ tracknum = 0;
+ Track = _MIDI_TrackPtr;
+ }
+ else
+ {
+ _MIDI_SongActive = FALSE;
+ break;
+ }
+ }
+ }
+
+ _MIDI_AdvanceTick();
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: _MIDI_SendControlChange
+
+ Sends a control change to the proper device
+---------------------------------------------------------------------*/
+
+static int _MIDI_SendControlChange
+ (
+ int channel,
+ int c1,
+ int c2
+ )
+
+ {
+ int status;
+
+ if ( _MIDI_RerouteFunctions[ channel ] != NULL )
+ {
+ status = _MIDI_RerouteFunctions[ channel ]( 0xB0 + channel,
+ c1, c2 );
+ if ( status == MIDI_DONT_PLAY )
+ {
+ return( MIDI_Ok );
+ }
+ }
+
+ if ( _MIDI_Funcs == NULL )
+ {
+ return( MIDI_Error );
+ }
+
+ if ( _MIDI_Funcs->ControlChange == NULL )
+ {
+ return( MIDI_Error );
+ }
+
+ _MIDI_Funcs->ControlChange( channel, c1, c2 );
+
+ return( MIDI_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_RerouteMidiChannel
+
+ Sets callback function to reroute MIDI commands from specified
+ function.
+---------------------------------------------------------------------*/
+
+void MIDI_RerouteMidiChannel
+ (
+ int channel,
+ int cdecl ( *function )( int event, int c1, int c2 )
+ )
+
+ {
+ if ( ( channel >= 1 ) && ( channel <= 16 ) )
+ {
+ _MIDI_RerouteFunctions[ channel - 1 ] = function;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_AllNotesOff
+
+ Sends all notes off commands on all midi channels.
+---------------------------------------------------------------------*/
+
+int MIDI_AllNotesOff
+ (
+ void
+ )
+
+ {
+ int channel;
+
+ for( channel = 0; channel < NUM_MIDI_CHANNELS; channel++ )
+ {
+ _MIDI_SendControlChange( channel, 0x40, 0 );
+ _MIDI_SendControlChange( channel, MIDI_ALL_NOTES_OFF, 0 );
+ _MIDI_SendControlChange( channel, 0x78, 0 );
+ }
+
+ return( MIDI_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: _MIDI_SetChannelVolume
+
+ Sets the volume of the specified midi channel.
+---------------------------------------------------------------------*/
+
+static void _MIDI_SetChannelVolume
+ (
+ int channel,
+ int volume
+ )
+
+ {
+ int status;
+ int remotevolume;
+
+ _MIDI_ChannelVolume[ channel ] = volume;
+
+ if ( _MIDI_RerouteFunctions[ channel ] != NULL )
+ {
+ remotevolume = volume * _MIDI_TotalVolume;
+ remotevolume *= _MIDI_UserChannelVolume[ channel ];
+ remotevolume /= MIDI_MaxVolume;
+ remotevolume >>= 8;
+
+ status = _MIDI_RerouteFunctions[ channel ]( 0xB0 + channel,
+ MIDI_VOLUME, remotevolume );
+ if ( status == MIDI_DONT_PLAY )
+ {
+ return;
+ }
+ }
+
+ if ( _MIDI_Funcs == NULL )
+ {
+ return;
+ }
+
+ if ( _MIDI_Funcs->ControlChange == NULL )
+ {
+ return;
+ }
+
+ // For user volume
+ volume *= _MIDI_UserChannelVolume[ channel ];
+
+ if ( _MIDI_Funcs->SetVolume == NULL )
+ {
+ volume *= _MIDI_TotalVolume;
+ volume /= MIDI_MaxVolume;
+ }
+
+ // For user volume
+ volume >>= 8;
+
+ _MIDI_Funcs->ControlChange( channel, MIDI_VOLUME, volume );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_SetUserChannelVolume
+
+ Sets the volume of the specified midi channel.
+---------------------------------------------------------------------*/
+
+void MIDI_SetUserChannelVolume
+ (
+ int channel,
+ int volume
+ )
+
+ {
+ // Convert channel from 1-16 to 0-15
+ channel--;
+
+ volume = max( 0, volume );
+ volume = min( volume, 256 );
+
+ if ( ( channel >= 0 ) && ( channel < NUM_MIDI_CHANNELS ) )
+ {
+ _MIDI_UserChannelVolume[ channel ] = volume;
+ _MIDI_SetChannelVolume( channel, _MIDI_ChannelVolume[ channel ] );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_ResetUserChannelVolume
+
+ Sets the volume of the specified midi channel.
+---------------------------------------------------------------------*/
+
+void MIDI_ResetUserChannelVolume
+ (
+ void
+ )
+
+ {
+ int channel;
+
+ for( channel = 0; channel < NUM_MIDI_CHANNELS; channel++ )
+ {
+ _MIDI_UserChannelVolume[ channel ] = 256;
+ }
+
+ _MIDI_SendChannelVolumes();
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: _MIDI_SendChannelVolumes
+
+ Sets the volume on all the midi channels.
+---------------------------------------------------------------------*/
+
+static void _MIDI_SendChannelVolumes
+ (
+ void
+ )
+
+ {
+ int channel;
+
+ for( channel = 0; channel < NUM_MIDI_CHANNELS; channel++ )
+ {
+ _MIDI_SetChannelVolume( channel, _MIDI_ChannelVolume[ channel ] );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_Reset
+
+ Resets the MIDI device to General Midi defaults.
+---------------------------------------------------------------------*/
+
+int MIDI_Reset
+ (
+ void
+ )
+
+ {
+ int channel;
+ long time;
+ unsigned flags;
+
+ MIDI_AllNotesOff();
+
+ flags = DisableInterrupts();
+ _enable();
+ time = clock() + CLOCKS_PER_SEC/24;
+ while(clock() < time)
+ ;
+
+ RestoreInterrupts( flags );
+
+ for( channel = 0; channel < NUM_MIDI_CHANNELS; channel++ )
+ {
+ _MIDI_SendControlChange( channel, MIDI_RESET_ALL_CONTROLLERS, 0 );
+ _MIDI_SendControlChange( channel, MIDI_RPN_MSB, MIDI_PITCHBEND_MSB );
+ _MIDI_SendControlChange( channel, MIDI_RPN_LSB, MIDI_PITCHBEND_LSB );
+ _MIDI_SendControlChange( channel, MIDI_DATAENTRY_MSB, 2 ); /* Pitch Bend Sensitivity MSB */
+ _MIDI_SendControlChange( channel, MIDI_DATAENTRY_LSB, 0 ); /* Pitch Bend Sensitivity LSB */
+ _MIDI_ChannelVolume[ channel ] = GENMIDI_DefaultVolume;
+ }
+
+ _MIDI_SendChannelVolumes();
+
+ Reset = TRUE;
+
+ return( MIDI_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_SetVolume
+
+ Sets the total volume of the music.
+---------------------------------------------------------------------*/
+
+int MIDI_SetVolume
+ (
+ int volume
+ )
+
+ {
+ int i;
+
+ if ( _MIDI_Funcs == NULL )
+ {
+ return( MIDI_NullMidiModule );
+ }
+
+ volume = min( MIDI_MaxVolume, volume );
+ volume = max( 0, volume );
+
+ _MIDI_TotalVolume = volume;
+
+ if ( _MIDI_Funcs->SetVolume )
+ {
+ _MIDI_Funcs->SetVolume( volume );
+
+ for( i = 0; i < NUM_MIDI_CHANNELS; i++ )
+ {
+ if ( _MIDI_RerouteFunctions[ i ] != NULL )
+ {
+ _MIDI_SetChannelVolume( i, _MIDI_ChannelVolume[ i ] );
+ }
+ }
+ }
+ else
+ {
+ _MIDI_SendChannelVolumes();
+ }
+
+ return( MIDI_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_GetVolume
+
+ Returns the total volume of the music.
+---------------------------------------------------------------------*/
+
+int MIDI_GetVolume
+ (
+ void
+ )
+
+ {
+ int volume;
+
+ if ( _MIDI_Funcs == NULL )
+ {
+ return( MIDI_NullMidiModule );
+ }
+
+ if ( _MIDI_Funcs->GetVolume )
+ {
+ volume = _MIDI_Funcs->GetVolume();
+ }
+ else
+ {
+ volume = _MIDI_TotalVolume;
+ }
+
+ return( volume );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_SetContext
+
+ Sets the song context.
+---------------------------------------------------------------------*/
+
+void MIDI_SetContext
+ (
+ int context
+ )
+
+ {
+ if ( ( context > 0 ) && ( context < EMIDI_NUM_CONTEXTS ) )
+ {
+ _MIDI_Context = context;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_GetContext
+
+ Returns the current song context.
+---------------------------------------------------------------------*/
+
+int MIDI_GetContext
+ (
+ void
+ )
+
+ {
+ return _MIDI_Context;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_SetLoopFlag
+
+ Sets whether the song should loop when finished or not.
+---------------------------------------------------------------------*/
+
+void MIDI_SetLoopFlag
+ (
+ int loopflag
+ )
+
+ {
+ _MIDI_Loop = loopflag;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_ContinueSong
+
+ Continues playback of a paused song.
+---------------------------------------------------------------------*/
+
+void MIDI_ContinueSong
+ (
+ void
+ )
+
+ {
+ if ( _MIDI_SongLoaded )
+ {
+ _MIDI_SongActive = TRUE;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_PauseSong
+
+ Pauses playback of the current song.
+---------------------------------------------------------------------*/
+
+void MIDI_PauseSong
+ (
+ void
+ )
+
+ {
+ if ( _MIDI_SongLoaded )
+ {
+ _MIDI_SongActive = FALSE;
+ MIDI_AllNotesOff();
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_SongPlaying
+
+ Returns whether a song is playing or not.
+---------------------------------------------------------------------*/
+
+int MIDI_SongPlaying
+ (
+ void
+ )
+
+ {
+ return( _MIDI_SongActive );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_SetMidiFuncs
+
+ Selects the routines that send the MIDI data to the music device.
+---------------------------------------------------------------------*/
+
+void MIDI_SetMidiFuncs
+ (
+ midifuncs *funcs
+ )
+
+ {
+ _MIDI_Funcs = funcs;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_StopSong
+
+ Stops playback of the currently playing song.
+---------------------------------------------------------------------*/
+
+void MIDI_StopSong
+ (
+ void
+ )
+
+ {
+ if ( _MIDI_SongLoaded )
+ {
+ TS_Terminate( _MIDI_PlayRoutine );
+
+ _MIDI_PlayRoutine = NULL;
+ _MIDI_SongActive = FALSE;
+ _MIDI_SongLoaded = FALSE;
+
+ MIDI_Reset();
+ _MIDI_ResetTracks();
+
+ if ( _MIDI_Funcs->ReleasePatches )
+ {
+ _MIDI_Funcs->ReleasePatches();
+ }
+
+ DPMI_UnlockMemory( _MIDI_TrackPtr, _MIDI_TrackMemSize );
+ USRHOOKS_FreeMem( _MIDI_TrackPtr );
+
+ _MIDI_TrackPtr = NULL;
+ _MIDI_NumTracks = 0;
+ _MIDI_TrackMemSize = 0;
+
+ _MIDI_TotalTime = 0;
+ _MIDI_TotalTicks = 0;
+ _MIDI_TotalBeats = 0;
+ _MIDI_TotalMeasures = 0;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_PlaySong
+
+ Begins playback of a MIDI song.
+---------------------------------------------------------------------*/
+
+int MIDI_PlaySong
+ (
+ unsigned char *song,
+ int loopflag
+ )
+
+ {
+ int numtracks;
+ int format;
+ long headersize;
+ long tracklength;
+ track *CurrentTrack;
+ unsigned char *ptr;
+ int status;
+
+ if ( _MIDI_SongLoaded )
+ {
+ MIDI_StopSong();
+ }
+
+ _MIDI_Loop = loopflag;
+
+ if ( _MIDI_Funcs == NULL )
+ {
+ return( MIDI_NullMidiModule );
+ }
+
+ if ( *( unsigned long * )song != MIDI_HEADER_SIGNATURE )
+ {
+ return( MIDI_InvalidMidiFile );
+ }
+
+ song += 4;
+
+ headersize = _MIDI_ReadNumber( song, 4 );
+ song += 4;
+ format = _MIDI_ReadNumber( song, 2 );
+ _MIDI_NumTracks = _MIDI_ReadNumber( song + 2, 2 );
+ _MIDI_Division = _MIDI_ReadNumber( song + 4, 2 );
+ if ( _MIDI_Division < 0 )
+ {
+ // If a SMPTE time division is given, just set to 96 so no errors occur
+ _MIDI_Division = 96;
+ }
+
+ if ( format > MAX_FORMAT )
+ {
+ return( MIDI_UnknownMidiFormat );
+ }
+
+ ptr = song + headersize;
+
+ if ( _MIDI_NumTracks == 0 )
+ {
+ return( MIDI_NoTracks );
+ }
+
+ _MIDI_TrackMemSize = _MIDI_NumTracks * sizeof( track );
+ status = USRHOOKS_GetMem( &_MIDI_TrackPtr, _MIDI_TrackMemSize );
+ if ( status != USRHOOKS_Ok )
+ {
+ return( MIDI_NoMemory );
+ }
+
+ status = DPMI_LockMemory( _MIDI_TrackPtr, _MIDI_TrackMemSize );
+ if ( status != DPMI_Ok )
+ {
+ USRHOOKS_FreeMem( _MIDI_TrackPtr );
+
+ _MIDI_TrackPtr = NULL;
+ _MIDI_TrackMemSize = 0;
+ _MIDI_NumTracks = 0;
+// MIDI_SetErrorCode( MIDI_DPMI_Error );
+ return( MIDI_Error );
+ }
+
+ CurrentTrack = _MIDI_TrackPtr;
+ numtracks = _MIDI_NumTracks;
+ while( numtracks-- )
+ {
+ if ( *( unsigned long * )ptr != MIDI_TRACK_SIGNATURE )
+ {
+ DPMI_UnlockMemory( _MIDI_TrackPtr, _MIDI_TrackMemSize );
+
+ USRHOOKS_FreeMem( _MIDI_TrackPtr );
+
+ _MIDI_TrackPtr = NULL;
+ _MIDI_TrackMemSize = 0;
+
+ return( MIDI_InvalidTrack );
+ }
+
+ tracklength = _MIDI_ReadNumber( ptr + 4, 4 );
+ ptr += 8;
+ CurrentTrack->start = ptr;
+ ptr += tracklength;
+ CurrentTrack++;
+ }
+
+ if ( _MIDI_Funcs->GetVolume != NULL )
+ {
+ _MIDI_TotalVolume = _MIDI_Funcs->GetVolume();
+ }
+
+ _MIDI_InitEMIDI();
+
+ if ( _MIDI_Funcs->LoadPatch )
+ {
+ MIDI_LoadTimbres();
+ }
+
+ _MIDI_ResetTracks();
+
+ if ( !Reset )
+ {
+ MIDI_Reset();
+ }
+
+ Reset = FALSE;
+
+ _MIDI_PlayRoutine = TS_ScheduleTask( _MIDI_ServiceRoutine, 100, 1, NULL );
+// _MIDI_PlayRoutine = TS_ScheduleTask( test, 100, 1, NULL );
+ MIDI_SetTempo( 120 );
+ TS_Dispatch();
+
+ _MIDI_SongLoaded = TRUE;
+ _MIDI_SongActive = TRUE;
+
+ return( MIDI_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_SetTempo
+
+ Sets the song tempo.
+---------------------------------------------------------------------*/
+
+void MIDI_SetTempo
+ (
+ int tempo
+ )
+
+ {
+ long tickspersecond;
+
+ MIDI_Tempo = tempo;
+ tickspersecond = ( tempo * _MIDI_Division ) / 60;
+ if ( _MIDI_PlayRoutine != NULL )
+ {
+ TS_SetTaskRate( _MIDI_PlayRoutine, tickspersecond );
+// TS_SetTaskRate( _MIDI_PlayRoutine, tickspersecond / 4 );
+ }
+ _MIDI_FPSecondsPerTick = ( 1 << TIME_PRECISION ) / tickspersecond;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_GetTempo
+
+ Returns the song tempo.
+---------------------------------------------------------------------*/
+
+int MIDI_GetTempo
+ (
+ void
+ )
+
+ {
+ return( MIDI_Tempo );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: _MIDI_ProcessNextTick
+
+ Sets the position of the song pointer.
+---------------------------------------------------------------------*/
+
+static int _MIDI_ProcessNextTick
+ (
+ void
+ )
+
+ {
+ int event;
+ int channel;
+ int command;
+ track *Track;
+ int tracknum;
+ int status;
+ int c1;
+ int c2;
+ int TimeSet = FALSE;
+
+ Track = _MIDI_TrackPtr;
+ tracknum = 0;
+ while( ( tracknum < _MIDI_NumTracks ) && ( Track != NULL ) )
+ {
+ while ( ( Track->active ) && ( Track->delay == 0 ) )
+ {
+ GET_NEXT_EVENT( Track, event );
+
+ if ( GET_MIDI_COMMAND( event ) == MIDI_SPECIAL )
+ {
+ switch( event )
+ {
+ case MIDI_SYSEX :
+ case MIDI_SYSEX_CONTINUE :
+ _MIDI_SysEx( Track );
+ break;
+
+ case MIDI_META_EVENT :
+ _MIDI_MetaEvent( Track );
+ break;
+ }
+
+ if ( Track->active )
+ {
+ Track->delay = _MIDI_ReadDelta( Track );
+ }
+
+ continue;
+ }
+
+ if ( event & MIDI_RUNNING_STATUS )
+ {
+ Track->RunningStatus = event;
+ }
+ else
+ {
+ event = Track->RunningStatus;
+ Track->pos--;
+ }
+
+ channel = GET_MIDI_CHANNEL( event );
+ command = GET_MIDI_COMMAND( event );
+
+ if ( _MIDI_CommandLengths[ command ] > 0 )
+ {
+ GET_NEXT_EVENT( Track, c1 );
+ if ( _MIDI_CommandLengths[ command ] > 1 )
+ {
+ GET_NEXT_EVENT( Track, c2 );
+ }
+ }
+
+ if ( _MIDI_RerouteFunctions[ channel ] != NULL )
+ {
+ status = _MIDI_RerouteFunctions[ channel ]( event, c1, c2 );
+
+ if ( status == MIDI_DONT_PLAY )
+ {
+ Track->delay = _MIDI_ReadDelta( Track );
+ continue;
+ }
+ }
+
+ switch ( command )
+ {
+ case MIDI_NOTE_OFF :
+ break;
+
+ case MIDI_NOTE_ON :
+ break;
+
+ case MIDI_POLY_AFTER_TCH :
+ if ( _MIDI_Funcs->PolyAftertouch )
+ {
+ _MIDI_Funcs->PolyAftertouch( channel, c1, c2 );
+ }
+ break;
+
+ case MIDI_CONTROL_CHANGE :
+ TimeSet = _MIDI_InterpretControllerInfo( Track, TimeSet,
+ channel, c1, c2 );
+ break;
+
+ case MIDI_PROGRAM_CHANGE :
+ if ( ( _MIDI_Funcs->ProgramChange ) &&
+ ( !Track->EMIDI_ProgramChange ) )
+ {
+ _MIDI_Funcs->ProgramChange( channel, c1 );
+ }
+ break;
+
+ case MIDI_AFTER_TOUCH :
+ if ( _MIDI_Funcs->ChannelAftertouch )
+ {
+ _MIDI_Funcs->ChannelAftertouch( channel, c1 );
+ }
+ break;
+
+ case MIDI_PITCH_BEND :
+ if ( _MIDI_Funcs->PitchBend )
+ {
+ _MIDI_Funcs->PitchBend( channel, c1, c2 );
+ }
+ break;
+
+ default :
+ break;
+ }
+
+ Track->delay = _MIDI_ReadDelta( Track );
+ }
+
+ Track->delay--;
+ Track++;
+ tracknum++;
+
+ if ( _MIDI_ActiveTracks == 0 )
+ {
+ break;
+ }
+ }
+
+ _MIDI_AdvanceTick();
+
+ return( TimeSet );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_SetSongTick
+
+ Sets the position of the song pointer.
+---------------------------------------------------------------------*/
+
+void MIDI_SetSongTick
+ (
+ unsigned long PositionInTicks
+ )
+
+ {
+ if ( !_MIDI_SongLoaded )
+ {
+ return;
+ }
+
+ MIDI_PauseSong();
+
+ if ( PositionInTicks < _MIDI_PositionInTicks )
+ {
+ _MIDI_ResetTracks();
+ MIDI_Reset();
+ }
+
+ while( _MIDI_PositionInTicks < PositionInTicks )
+ {
+ if ( _MIDI_ProcessNextTick() )
+ {
+ break;
+ }
+ if ( _MIDI_ActiveTracks == 0 )
+ {
+ _MIDI_ResetTracks();
+ if ( !_MIDI_Loop )
+ {
+ return;
+ }
+ break;
+ }
+ }
+
+ MIDI_SetVolume( _MIDI_TotalVolume );
+ MIDI_ContinueSong();
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_SetSongTime
+
+ Sets the position of the song pointer.
+---------------------------------------------------------------------*/
+
+void MIDI_SetSongTime
+ (
+ unsigned long milliseconds
+ )
+
+ {
+ unsigned long mil;
+ unsigned long sec;
+ unsigned long newtime;
+
+ if ( !_MIDI_SongLoaded )
+ {
+ return;
+ }
+
+ MIDI_PauseSong();
+
+ mil = ( ( milliseconds % 1000 ) << TIME_PRECISION ) / 1000;
+ sec = ( milliseconds / 1000 ) << TIME_PRECISION;
+ newtime = sec + mil;
+
+ if ( newtime < _MIDI_Time )
+ {
+ _MIDI_ResetTracks();
+ MIDI_Reset();
+ }
+
+ while( _MIDI_Time < newtime )
+ {
+ if ( _MIDI_ProcessNextTick() )
+ {
+ break;
+ }
+ if ( _MIDI_ActiveTracks == 0 )
+ {
+ _MIDI_ResetTracks();
+ if ( !_MIDI_Loop )
+ {
+ return;
+ }
+ break;
+ }
+ }
+
+ MIDI_SetVolume( _MIDI_TotalVolume );
+ MIDI_ContinueSong();
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_SetSongPosition
+
+ Sets the position of the song pointer.
+---------------------------------------------------------------------*/
+
+void MIDI_SetSongPosition
+ (
+ int measure,
+ int beat,
+ int tick
+ )
+
+ {
+ unsigned long pos;
+
+ if ( !_MIDI_SongLoaded )
+ {
+ return;
+ }
+
+ MIDI_PauseSong();
+
+ pos = RELATIVE_BEAT( measure, beat, tick );
+
+ if ( pos < RELATIVE_BEAT( _MIDI_Measure, _MIDI_Beat, _MIDI_Tick ) )
+ {
+ _MIDI_ResetTracks();
+ MIDI_Reset();
+ }
+
+ while( RELATIVE_BEAT( _MIDI_Measure, _MIDI_Beat, _MIDI_Tick ) < pos )
+ {
+ if ( _MIDI_ProcessNextTick() )
+ {
+ break;
+ }
+ if ( _MIDI_ActiveTracks == 0 )
+ {
+ _MIDI_ResetTracks();
+ if ( !_MIDI_Loop )
+ {
+ return;
+ }
+ break;
+ }
+ }
+
+ MIDI_SetVolume( _MIDI_TotalVolume );
+ MIDI_ContinueSong();
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_GetSongPosition
+
+ Returns the position of the song pointer in Measures, beats, ticks.
+---------------------------------------------------------------------*/
+
+void MIDI_GetSongPosition
+ (
+ songposition *pos
+ )
+
+ {
+ unsigned long mil;
+ unsigned long sec;
+
+ mil = ( _MIDI_Time & ( ( 1 << TIME_PRECISION ) - 1 ) ) * 1000;
+ sec = _MIDI_Time >> TIME_PRECISION;
+ pos->milliseconds = ( mil >> TIME_PRECISION ) + ( sec * 1000 );
+ pos->tickposition = _MIDI_PositionInTicks;
+ pos->measure = _MIDI_Measure;
+ pos->beat = _MIDI_Beat;
+ pos->tick = _MIDI_Tick;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_GetSongLength
+
+ Returns the length of the song.
+---------------------------------------------------------------------*/
+
+void MIDI_GetSongLength
+ (
+ songposition *pos
+ )
+
+ {
+ unsigned long mil;
+ unsigned long sec;
+
+ mil = ( _MIDI_TotalTime & ( ( 1 << TIME_PRECISION ) - 1 ) ) * 1000;
+ sec = _MIDI_TotalTime >> TIME_PRECISION;
+
+ pos->milliseconds = ( mil >> TIME_PRECISION ) + ( sec * 1000 );
+ pos->measure = _MIDI_TotalMeasures;
+ pos->beat = _MIDI_TotalBeats;
+ pos->tick = _MIDI_TotalTicks;
+ pos->tickposition = 0;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_InitEMIDI
+
+ Sets up the EMIDI
+---------------------------------------------------------------------*/
+
+static void _MIDI_InitEMIDI
+ (
+ void
+ )
+
+ {
+ int event;
+ int command;
+ int channel;
+ int length;
+ int IncludeFound;
+ track *Track;
+ int tracknum;
+ int type;
+ int c1;
+ int c2;
+
+ type = EMIDI_GeneralMIDI;
+ switch( MUSIC_SoundDevice )
+ {
+ case SoundBlaster :
+ type = EMIDI_SoundBlaster;
+ break;
+
+ case ProAudioSpectrum :
+ type = EMIDI_ProAudio;
+ break;
+
+ case SoundMan16 :
+ type = EMIDI_SoundMan16;
+ break;
+
+ case Adlib :
+ type = EMIDI_Adlib;
+ break;
+
+ case GenMidi :
+ type = EMIDI_GeneralMIDI;
+ break;
+
+ case SoundCanvas :
+ type = EMIDI_SoundCanvas;
+ break;
+
+ case Awe32 :
+ type = EMIDI_AWE32;
+ break;
+
+ case WaveBlaster :
+ type = EMIDI_WaveBlaster;
+ break;
+
+ case SoundScape :
+ type = EMIDI_Soundscape;
+ break;
+
+ case UltraSound :
+ type = EMIDI_Ultrasound;
+ break;
+ }
+
+ _MIDI_ResetTracks();
+
+ _MIDI_TotalTime = 0;
+ _MIDI_TotalTicks = 0;
+ _MIDI_TotalBeats = 0;
+ _MIDI_TotalMeasures = 0;
+
+ Track = _MIDI_TrackPtr;
+ tracknum = 0;
+ while( ( tracknum < _MIDI_NumTracks ) && ( Track != NULL ) )
+ {
+ _MIDI_Tick = 0;
+ _MIDI_Beat = 1;
+ _MIDI_Measure = 1;
+ _MIDI_Time = 0;
+ _MIDI_BeatsPerMeasure = 4;
+ _MIDI_TicksPerBeat = _MIDI_Division;
+ _MIDI_TimeBase = 4;
+
+ _MIDI_PositionInTicks = 0;
+ _MIDI_ActiveTracks = 0;
+ _MIDI_Context = -1;
+
+ Track->RunningStatus = 0;
+ Track->active = TRUE;
+
+ Track->EMIDI_ProgramChange = FALSE;
+ Track->EMIDI_VolumeChange = FALSE;
+ Track->EMIDI_IncludeTrack = TRUE;
+
+ memset( Track->context, 0, sizeof( Track->context ) );
+
+ while( Track->delay > 0 )
+ {
+ _MIDI_AdvanceTick();
+ Track->delay--;
+ }
+
+ IncludeFound = FALSE;
+ while ( Track->active )
+ {
+ GET_NEXT_EVENT( Track, event );
+
+ if ( GET_MIDI_COMMAND( event ) == MIDI_SPECIAL )
+ {
+ switch( event )
+ {
+ case MIDI_SYSEX :
+ case MIDI_SYSEX_CONTINUE :
+ _MIDI_SysEx( Track );
+ break;
+
+ case MIDI_META_EVENT :
+ _MIDI_MetaEvent( Track );
+ break;
+ }
+
+ if ( Track->active )
+ {
+ Track->delay = _MIDI_ReadDelta( Track );
+ while( Track->delay > 0 )
+ {
+ _MIDI_AdvanceTick();
+ Track->delay--;
+ }
+ }
+
+ continue;
+ }
+
+ if ( event & MIDI_RUNNING_STATUS )
+ {
+ Track->RunningStatus = event;
+ }
+ else
+ {
+ event = Track->RunningStatus;
+ Track->pos--;
+ }
+
+ channel = GET_MIDI_CHANNEL( event );
+ command = GET_MIDI_COMMAND( event );
+ length = _MIDI_CommandLengths[ command ];
+
+ if ( command == MIDI_CONTROL_CHANGE )
+ {
+ if ( *Track->pos == MIDI_MONO_MODE_ON )
+ {
+ length++;
+ }
+ GET_NEXT_EVENT( Track, c1 );
+ GET_NEXT_EVENT( Track, c2 );
+ length -= 2;
+
+ switch( c1 )
+ {
+ case EMIDI_LOOP_START :
+ case EMIDI_SONG_LOOP_START :
+ if ( c2 == 0 )
+ {
+ Track->context[ 0 ].loopcount = EMIDI_INFINITE;
+ }
+ else
+ {
+ Track->context[ 0 ].loopcount = c2;
+ }
+
+ Track->context[ 0 ].pos = Track->pos;
+ Track->context[ 0 ].loopstart = Track->pos;
+ Track->context[ 0 ].RunningStatus = Track->RunningStatus;
+ Track->context[ 0 ].time = _MIDI_Time;
+ Track->context[ 0 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick;
+ Track->context[ 0 ].tick = _MIDI_Tick;
+ Track->context[ 0 ].beat = _MIDI_Beat;
+ Track->context[ 0 ].measure = _MIDI_Measure;
+ Track->context[ 0 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure;
+ Track->context[ 0 ].TicksPerBeat = _MIDI_TicksPerBeat;
+ Track->context[ 0 ].TimeBase = _MIDI_TimeBase;
+ break;
+
+ case EMIDI_LOOP_END :
+ case EMIDI_SONG_LOOP_END :
+ if ( c2 == EMIDI_END_LOOP_VALUE )
+ {
+ Track->context[ 0 ].loopstart = NULL;
+ Track->context[ 0 ].loopcount = 0;
+ }
+ break;
+
+ case EMIDI_INCLUDE_TRACK :
+ if ( EMIDI_AffectsCurrentCard( c2, type ) )
+ {
+ //printf( "Include track %d on card %d\n", tracknum, c2 );
+ IncludeFound = TRUE;
+ Track->EMIDI_IncludeTrack = TRUE;
+ }
+ else if ( !IncludeFound )
+ {
+ //printf( "Track excluded %d on card %d\n", tracknum, c2 );
+ IncludeFound = TRUE;
+ Track->EMIDI_IncludeTrack = FALSE;
+ }
+ break;
+
+ case EMIDI_EXCLUDE_TRACK :
+ if ( EMIDI_AffectsCurrentCard( c2, type ) )
+ {
+ //printf( "Exclude track %d on card %d\n", tracknum, c2 );
+ Track->EMIDI_IncludeTrack = FALSE;
+ }
+ break;
+
+ case EMIDI_PROGRAM_CHANGE :
+ if ( !Track->EMIDI_ProgramChange )
+ //printf( "Program change on track %d\n", tracknum );
+ Track->EMIDI_ProgramChange = TRUE;
+ break;
+
+ case EMIDI_VOLUME_CHANGE :
+ if ( !Track->EMIDI_VolumeChange )
+ //printf( "Volume change on track %d\n", tracknum );
+ Track->EMIDI_VolumeChange = TRUE;
+ break;
+
+ case EMIDI_CONTEXT_START :
+ if ( ( c2 > 0 ) && ( c2 < EMIDI_NUM_CONTEXTS ) )
+ {
+ Track->context[ c2 ].pos = Track->pos;
+ Track->context[ c2 ].loopstart = Track->context[ 0 ].loopstart;
+ Track->context[ c2 ].loopcount = Track->context[ 0 ].loopcount;
+ Track->context[ c2 ].RunningStatus = Track->RunningStatus;
+ Track->context[ c2 ].time = _MIDI_Time;
+ Track->context[ c2 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick;
+ Track->context[ c2 ].tick = _MIDI_Tick;
+ Track->context[ c2 ].beat = _MIDI_Beat;
+ Track->context[ c2 ].measure = _MIDI_Measure;
+ Track->context[ c2 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure;
+ Track->context[ c2 ].TicksPerBeat = _MIDI_TicksPerBeat;
+ Track->context[ c2 ].TimeBase = _MIDI_TimeBase;
+ }
+ break;
+
+ case EMIDI_CONTEXT_END :
+ break;
+ }
+ }
+
+ Track->pos += length;
+ Track->delay = _MIDI_ReadDelta( Track );
+
+ while( Track->delay > 0 )
+ {
+ _MIDI_AdvanceTick();
+ Track->delay--;
+ }
+ }
+
+ _MIDI_TotalTime = max( _MIDI_TotalTime, _MIDI_Time );
+ if ( RELATIVE_BEAT( _MIDI_Measure, _MIDI_Beat, _MIDI_Tick ) >
+ RELATIVE_BEAT( _MIDI_TotalMeasures, _MIDI_TotalBeats,
+ _MIDI_TotalTicks ) )
+ {
+ _MIDI_TotalTicks = _MIDI_Tick;
+ _MIDI_TotalBeats = _MIDI_Beat;
+ _MIDI_TotalMeasures = _MIDI_Measure;
+ }
+
+ Track++;
+ tracknum++;
+ }
+
+ _MIDI_ResetTracks();
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_LoadTimbres
+
+ Preloads the timbres on cards that use patch-caching.
+---------------------------------------------------------------------*/
+
+void MIDI_LoadTimbres
+ (
+ void
+ )
+
+ {
+ int event;
+ int command;
+ int channel;
+ int length;
+ int Finished;
+ track *Track;
+ int tracknum;
+
+ Track = _MIDI_TrackPtr;
+ tracknum = 0;
+ while( ( tracknum < _MIDI_NumTracks ) && ( Track != NULL ) )
+ {
+ Finished = FALSE;
+ while ( !Finished )
+ {
+ GET_NEXT_EVENT( Track, event );
+
+ if ( GET_MIDI_COMMAND( event ) == MIDI_SPECIAL )
+ {
+ switch( event )
+ {
+ case MIDI_SYSEX :
+ case MIDI_SYSEX_CONTINUE :
+ length = _MIDI_ReadDelta( Track );
+ Track->pos += length;
+ break;
+
+ case MIDI_META_EVENT :
+ GET_NEXT_EVENT( Track, command );
+ GET_NEXT_EVENT( Track, length );
+
+ if ( command == MIDI_END_OF_TRACK )
+ {
+ Finished = TRUE;
+ }
+
+ Track->pos += length;
+ break;
+ }
+
+ if ( !Finished )
+ {
+ _MIDI_ReadDelta( Track );
+ }
+
+ continue;
+ }
+
+ if ( event & MIDI_RUNNING_STATUS )
+ {
+ Track->RunningStatus = event;
+ }
+ else
+ {
+ event = Track->RunningStatus;
+ Track->pos--;
+ }
+
+ channel = GET_MIDI_CHANNEL( event );
+ command = GET_MIDI_COMMAND( event );
+ length = _MIDI_CommandLengths[ command ];
+
+ if ( command == MIDI_CONTROL_CHANGE )
+ {
+ if ( *Track->pos == MIDI_MONO_MODE_ON )
+ {
+ length++;
+ }
+
+ if ( *Track->pos == EMIDI_PROGRAM_CHANGE )
+ {
+ _MIDI_Funcs->LoadPatch( *( Track->pos + 1 ) );
+ }
+ }
+
+ if ( channel == MIDI_RHYTHM_CHANNEL )
+ {
+ if ( command == MIDI_NOTE_ON )
+ {
+ _MIDI_Funcs->LoadPatch( 128 + *Track->pos );
+ }
+ }
+ else
+ {
+ if ( command == MIDI_PROGRAM_CHANGE )
+ {
+ _MIDI_Funcs->LoadPatch( *Track->pos );
+ }
+ }
+ Track->pos += length;
+ _MIDI_ReadDelta( Track );
+ }
+ Track++;
+ tracknum++;
+ }
+
+ _MIDI_ResetTracks();
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_LockEnd
+
+ Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void MIDI_LockEnd
+ (
+ void
+ )
+
+ {
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_UnlockMemory
+
+ Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+void MIDI_UnlockMemory
+ (
+ void
+ )
+
+ {
+ DPMI_UnlockMemoryRegion( MIDI_LockStart, MIDI_LockEnd );
+ DPMI_UnlockMemory( ( void * )&_MIDI_CommandLengths[ 0 ],
+ sizeof( _MIDI_CommandLengths ) );
+ DPMI_Unlock( _MIDI_TrackPtr );
+ DPMI_Unlock( _MIDI_NumTracks );
+ DPMI_Unlock( _MIDI_SongActive );
+ DPMI_Unlock( _MIDI_SongLoaded );
+ DPMI_Unlock( _MIDI_Loop );
+ DPMI_Unlock( _MIDI_PlayRoutine );
+ DPMI_Unlock( _MIDI_Division );
+ DPMI_Unlock( _MIDI_ActiveTracks );
+ DPMI_Unlock( _MIDI_TotalVolume );
+ DPMI_Unlock( _MIDI_ChannelVolume );
+ DPMI_Unlock( _MIDI_Funcs );
+ DPMI_Unlock( _MIDI_PositionInTicks );
+ DPMI_Unlock( _MIDI_Division );
+ DPMI_Unlock( _MIDI_Tick );
+ DPMI_Unlock( _MIDI_Beat );
+ DPMI_Unlock( _MIDI_Measure );
+ DPMI_Unlock( _MIDI_Time );
+ DPMI_Unlock( _MIDI_BeatsPerMeasure );
+ DPMI_Unlock( _MIDI_TicksPerBeat );
+ DPMI_Unlock( _MIDI_TimeBase );
+ DPMI_Unlock( _MIDI_FPSecondsPerTick );
+ DPMI_Unlock( _MIDI_Context );
+ DPMI_Unlock( _MIDI_TotalTime );
+ DPMI_Unlock( _MIDI_TotalTicks );
+ DPMI_Unlock( _MIDI_TotalBeats );
+ DPMI_Unlock( _MIDI_TotalMeasures );
+ DPMI_Unlock( MIDI_Tempo );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MIDI_LockMemory
+
+ Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+int MIDI_LockMemory
+ (
+ void
+ )
+
+ {
+ int status;
+
+ status = DPMI_LockMemoryRegion( MIDI_LockStart, MIDI_LockEnd );
+ status |= DPMI_LockMemory( ( void * )&_MIDI_CommandLengths[ 0 ],
+ sizeof( _MIDI_CommandLengths ) );
+ status |= DPMI_Lock( _MIDI_TrackPtr );
+ status |= DPMI_Lock( _MIDI_NumTracks );
+ status |= DPMI_Lock( _MIDI_SongActive );
+ status |= DPMI_Lock( _MIDI_SongLoaded );
+ status |= DPMI_Lock( _MIDI_Loop );
+ status |= DPMI_Lock( _MIDI_PlayRoutine );
+ status |= DPMI_Lock( _MIDI_Division );
+ status |= DPMI_Lock( _MIDI_ActiveTracks );
+ status |= DPMI_Lock( _MIDI_TotalVolume );
+ status |= DPMI_Lock( _MIDI_ChannelVolume );
+ status |= DPMI_Lock( _MIDI_Funcs );
+ status |= DPMI_Lock( _MIDI_PositionInTicks );
+ status |= DPMI_Lock( _MIDI_Division );
+ status |= DPMI_Lock( _MIDI_Tick );
+ status |= DPMI_Lock( _MIDI_Beat );
+ status |= DPMI_Lock( _MIDI_Measure );
+ status |= DPMI_Lock( _MIDI_Time );
+ status |= DPMI_Lock( _MIDI_BeatsPerMeasure );
+ status |= DPMI_Lock( _MIDI_TicksPerBeat );
+ status |= DPMI_Lock( _MIDI_TimeBase );
+ status |= DPMI_Lock( _MIDI_FPSecondsPerTick );
+ status |= DPMI_Lock( _MIDI_Context );
+ status |= DPMI_Lock( _MIDI_TotalTime );
+ status |= DPMI_Lock( _MIDI_TotalTicks );
+ status |= DPMI_Lock( _MIDI_TotalBeats );
+ status |= DPMI_Lock( _MIDI_TotalMeasures );
+ status |= DPMI_Lock( MIDI_Tempo );
+
+ if ( status != DPMI_Ok )
+ {
+ MIDI_UnlockMemory();
+// MIDI_SetErrorCode( MIDI_DPMI_Error );
+ return( MIDI_Error );
+ }
+
+ return( MIDI_Ok );
+ }
--- /dev/null
+++ b/rott/audiolib/midi.h
@@ -1,0 +1,98 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: MIDI.H
+
+ author: James R. Dose
+ date: May 25, 1994
+
+ Public header for MIDI.C. Midi song file playback routines.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __MIDI_H
+#define __MIDI_H
+
+enum MIDI_Errors
+ {
+ MIDI_Warning = -2,
+ MIDI_Error = -1,
+ MIDI_Ok = 0,
+ MIDI_NullMidiModule,
+ MIDI_InvalidMidiFile,
+ MIDI_UnknownMidiFormat,
+ MIDI_NoTracks,
+ MIDI_InvalidTrack,
+ MIDI_NoMemory,
+ MIDI_DPMI_Error
+ };
+
+
+#define MIDI_PASS_THROUGH 1
+#define MIDI_DONT_PLAY 0
+
+#define MIDI_MaxVolume 255
+
+extern char MIDI_PatchMap[ 128 ];
+
+typedef struct
+ {
+ void ( *NoteOff )( int channel, int key, int velocity );
+ void ( *NoteOn )( int channel, int key, int velocity );
+ void ( *PolyAftertouch )( int channel, int key, int pressure );
+ void ( *ControlChange )( int channel, int number, int value );
+ void ( *ProgramChange )( int channel, int program );
+ void ( *ChannelAftertouch )( int channel, int pressure );
+ void ( *PitchBend )( int channel, int lsb, int msb );
+ void ( *ReleasePatches )( void );
+ void ( *LoadPatch )( int number );
+ void ( *SetVolume )( int volume );
+ int ( *GetVolume )( void );
+ } midifuncs;
+
+void MIDI_RerouteMidiChannel( int channel, int cdecl ( *function )( int event, int c1, int c2 ) );
+int MIDI_AllNotesOff( void );
+void MIDI_SetUserChannelVolume( int channel, int volume );
+void MIDI_ResetUserChannelVolume( void );
+int MIDI_Reset( void );
+int MIDI_SetVolume( int volume );
+int MIDI_GetVolume( void );
+void MIDI_SetMidiFuncs( midifuncs *funcs );
+void MIDI_SetContext( int context );
+int MIDI_GetContext( void );
+void MIDI_SetLoopFlag( int loopflag );
+void MIDI_ContinueSong( void );
+void MIDI_PauseSong( void );
+int MIDI_SongPlaying( void );
+void MIDI_StopSong( void );
+int MIDI_PlaySong( unsigned char *song, int loopflag );
+void MIDI_SetTempo( int tempo );
+int MIDI_GetTempo( void );
+void MIDI_SetSongTick( unsigned long PositionInTicks );
+void MIDI_SetSongTime( unsigned long milliseconds );
+void MIDI_SetSongPosition( int measure, int beat, int tick );
+void MIDI_GetSongPosition( songposition *pos );
+void MIDI_GetSongLength( songposition *pos );
+void MIDI_LoadTimbres( void );
+void MIDI_UnlockMemory( void );
+int MIDI_LockMemory( void );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/mpu401.c
@@ -1,0 +1,451 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: MPU401.C
+
+ author: James R. Dose
+ date: January 1, 1994
+
+ Low level routines to support sending of MIDI data to MPU401
+ compatible MIDI interfaces.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#include <conio.h>
+#include <dos.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "dpmi.h"
+#include "user.h"
+#include "mpu401.h"
+
+#define MIDI_NOTE_OFF 0x80
+#define MIDI_NOTE_ON 0x90
+#define MIDI_POLY_AFTER_TCH 0xA0
+#define MIDI_CONTROL_CHANGE 0xB0
+#define MIDI_PROGRAM_CHANGE 0xC0
+#define MIDI_AFTER_TOUCH 0xD0
+#define MIDI_PITCH_BEND 0xE0
+#define MIDI_META_EVENT 0xFF
+#define MIDI_END_OF_TRACK 0x2F
+#define MIDI_TEMPO_CHANGE 0x51
+#define MIDI_MONO_MODE_ON 0x7E
+#define MIDI_ALL_NOTES_OFF 0x7B
+
+int MPU_BaseAddr = MPU_DefaultAddress;
+
+//unsigned MPU_Delay = 500;
+//unsigned MPU_Delay = 5000;
+unsigned MPU_Delay = 0x5000;
+
+
+/**********************************************************************
+
+ Memory locked functions:
+
+**********************************************************************/
+
+
+#define MPU_LockStart MPU_SendMidi
+
+
+/*---------------------------------------------------------------------
+ Function: MPU_SendMidi
+
+ Sends a byte of MIDI data to the music device.
+---------------------------------------------------------------------*/
+
+void MPU_SendMidi
+ (
+ int data
+ )
+
+ {
+ int port = MPU_BaseAddr + 1;
+ unsigned count;
+
+ count = MPU_Delay;
+ while( count > 0 )
+ {
+ // check if status port says we're ready for write
+ if ( !( inp( port ) & MPU_ReadyToWrite ) )
+ {
+ break;
+ }
+
+ count--;
+ }
+
+ port--;
+
+ // Send the midi data
+ outp( port, data );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MPU_NoteOff
+
+ Sends a full MIDI note off event out to the music device.
+---------------------------------------------------------------------*/
+
+void MPU_NoteOff
+ (
+ int channel,
+ int key,
+ int velocity
+ )
+
+ {
+ MPU_SendMidi( MIDI_NOTE_OFF | channel );
+ MPU_SendMidi( key );
+ MPU_SendMidi( velocity );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MPU_NoteOn
+
+ Sends a full MIDI note on event out to the music device.
+---------------------------------------------------------------------*/
+
+void MPU_NoteOn
+ (
+ int channel,
+ int key,
+ int velocity
+ )
+
+ {
+ MPU_SendMidi( MIDI_NOTE_ON | channel );
+ MPU_SendMidi( key );
+ MPU_SendMidi( velocity );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MPU_PolyAftertouch
+
+ Sends a full MIDI polyphonic aftertouch event out to the music device.
+---------------------------------------------------------------------*/
+
+void MPU_PolyAftertouch
+ (
+ int channel,
+ int key,
+ int pressure
+ )
+
+ {
+ MPU_SendMidi( MIDI_POLY_AFTER_TCH | channel );
+ MPU_SendMidi( key );
+ MPU_SendMidi( pressure );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MPU_ControlChange
+
+ Sends a full MIDI control change event out to the music device.
+---------------------------------------------------------------------*/
+
+void MPU_ControlChange
+ (
+ int channel,
+ int number,
+ int value
+ )
+
+ {
+ MPU_SendMidi( MIDI_CONTROL_CHANGE | channel );
+ MPU_SendMidi( number );
+ MPU_SendMidi( value );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MPU_ProgramChange
+
+ Sends a full MIDI program change event out to the music device.
+---------------------------------------------------------------------*/
+
+void MPU_ProgramChange
+ (
+ int channel,
+ int program
+ )
+
+ {
+ MPU_SendMidi( MIDI_PROGRAM_CHANGE | channel );
+ MPU_SendMidi( program );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MPU_ChannelAftertouch
+
+ Sends a full MIDI channel aftertouch event out to the music device.
+---------------------------------------------------------------------*/
+
+void MPU_ChannelAftertouch
+ (
+ int channel,
+ int pressure
+ )
+
+ {
+ MPU_SendMidi( MIDI_AFTER_TOUCH | channel );
+ MPU_SendMidi( pressure );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MPU_PitchBend
+
+ Sends a full MIDI pitch bend event out to the music device.
+---------------------------------------------------------------------*/
+
+void MPU_PitchBend
+ (
+ int channel,
+ int lsb,
+ int msb
+ )
+
+ {
+ MPU_SendMidi( MIDI_PITCH_BEND | channel );
+ MPU_SendMidi( lsb );
+ MPU_SendMidi( msb );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MPU_SendCommand
+
+ Sends a command to the MPU401 card.
+---------------------------------------------------------------------*/
+
+void MPU_SendCommand
+ (
+ int data
+ )
+
+ {
+ int port = MPU_BaseAddr + 1;
+ unsigned count;
+
+ count = 0xffff;
+ while( count > 0 )
+ {
+ // check if status port says we're ready for write
+ if ( !( inp( port ) & MPU_ReadyToWrite ) )
+ {
+ break;
+ }
+ count--;
+ }
+
+ outp( port, data );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MPU_Reset
+
+ Resets the MPU401 card.
+---------------------------------------------------------------------*/
+
+int MPU_Reset
+ (
+ void
+ )
+
+ {
+ int port = MPU_BaseAddr + 1;
+ unsigned count;
+
+ // Output "Reset" command via Command port
+ MPU_SendCommand( MPU_CmdReset );
+
+ // Wait for status port to be ready for read
+ count = 0xffff;
+ while( count > 0 )
+ {
+ if ( !( inp( port ) & MPU_ReadyToRead ) )
+ {
+ port--;
+
+ // Check for a successful reset
+ if ( inp( port ) == MPU_CmdAcknowledge )
+ {
+ return( MPU_Ok );
+ }
+
+ port++;
+ }
+ count--;
+ }
+
+ // Failed to reset : MPU-401 not detected
+ return( MPU_NotFound );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MPU_EnterUART
+
+ Sets the MPU401 card to operate in UART mode.
+---------------------------------------------------------------------*/
+
+int MPU_EnterUART
+ (
+ void
+ )
+
+ {
+ int port = MPU_BaseAddr + 1;
+ unsigned count;
+
+ // Output "Enter UART" command via Command port
+ MPU_SendCommand( MPU_CmdEnterUART );
+
+ // Wait for status port to be ready for read
+ count = 0xffff;
+ while( count > 0 )
+ {
+ if ( !( inp( port ) & MPU_ReadyToRead ) )
+ {
+ port--;
+
+ // Check for a successful reset
+ if ( inp( port ) == MPU_CmdAcknowledge )
+ {
+ return( MPU_Ok );
+ }
+
+ port++;
+ }
+ count--;
+ }
+
+ // Failed to reset : MPU-401 not detected
+ return( MPU_UARTFailed );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MPU_Init
+
+ Detects and initializes the MPU401 card.
+---------------------------------------------------------------------*/
+
+int MPU_Init
+ (
+ int addr
+ )
+
+ {
+ int status;
+ int count;
+ char *ptr;
+
+ ptr = USER_GetText( "MPUDELAY" );
+ if ( ptr != NULL )
+ {
+ MPU_Delay = ( unsigned )atol( ptr );
+ }
+
+ MPU_BaseAddr = addr;
+
+ count = 4;
+ while( count > 0 )
+ {
+ status = MPU_Reset();
+ if ( status == MPU_Ok )
+ {
+ return( MPU_EnterUART() );
+ }
+ count--;
+ }
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MPU_LockEnd
+
+ Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void MPU_LockEnd
+ (
+ void
+ )
+
+ {
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MPU_UnlockMemory
+
+ Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+void MPU_UnlockMemory
+ (
+ void
+ )
+
+ {
+ DPMI_UnlockMemoryRegion( MPU_LockStart, MPU_LockEnd );
+ DPMI_Unlock( MPU_BaseAddr );
+ DPMI_Unlock( MPU_Delay );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MPU_LockMemory
+
+ Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+int MPU_LockMemory
+ (
+ void
+ )
+
+ {
+ int status;
+
+ status = DPMI_LockMemoryRegion( MPU_LockStart, MPU_LockEnd );
+ status |= DPMI_Lock( MPU_BaseAddr );
+ status |= DPMI_Lock( MPU_Delay );
+
+ if ( status != DPMI_Ok )
+ {
+ MPU_UnlockMemory();
+ return( MPU_Error );
+ }
+
+ return( MPU_Ok );
+ }
--- /dev/null
+++ b/rott/audiolib/mpu401.h
@@ -1,0 +1,61 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef __MPU401_H
+#define __MPU401_H
+
+#define MPU_DefaultAddress 0x330
+
+enum MPU_ERRORS
+ {
+ MPU_Warning = -2,
+ MPU_Error = -1,
+ MPU_Ok = 0,
+ MPU_DPMI_Error
+ };
+
+#define MPU_NotFound -1
+#define MPU_UARTFailed -2
+
+#define MPU_ReadyToWrite 0x40
+#define MPU_ReadyToRead 0x80
+#define MPU_CmdEnterUART 0x3f
+#define MPU_CmdReset 0xff
+#define MPU_CmdAcknowledge 0xfe
+
+extern int MPU_BaseAddr;
+extern unsigned MPU_Delay;
+
+void MPU_SendCommand( int data );
+void MPU_SendMidi( int data );
+int MPU_Reset( void );
+int MPU_EnterUART( void );
+int MPU_Init( int addr );
+void MPU_ResetMidi( void );
+void MPU_NoteOff( int channel, int key, int velocity );
+void MPU_NoteOn( int channel, int key, int velocity );
+void MPU_PolyAftertouch( int channel, int key, int pressure );
+void MPU_ControlChange( int channel, int number, int value );
+void MPU_ProgramChange( int channel, int program );
+void MPU_ChannelAftertouch( int channel, int pressure );
+void MPU_PitchBend( int channel, int lsb, int msb );
+void MPU_UnlockMemory( void );
+int MPU_LockMemory( void );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/multivoc.c
@@ -1,0 +1,3555 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: MULTIVOC.C
+
+ author: James R. Dose
+ date: December 20, 1993
+
+ Routines to provide multichannel digitized sound playback for
+ Sound Blaster compatible sound cards.
+
+ (c) Copyright 1993 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifdef PLAT_DOS
+#include <dos.h>
+#include <conio.h>
+#endif
+
+#include "util.h"
+#include "dpmi.h"
+#include "usrhooks.h"
+#include "interrup.h"
+#include "dma.h"
+#include "linklist.h"
+#include "sndcards.h"
+
+#ifdef PLAT_DOS
+#include "blaster.h"
+#include "sndscape.h"
+#include "sndsrc.h"
+#include "pas16.h"
+#include "guswave.h"
+#else
+#include "dsl.h"
+#endif
+
+#include "pitch.h"
+#include "multivoc.h"
+#include "_multivc.h"
+#include "debugio.h"
+
+#define RoundFixed( fixedval, bits ) \
+ ( \
+ ( \
+ (fixedval) + ( 1 << ( (bits) - 1 ) )\
+ ) >> (bits) \
+ )
+
+#define IS_QUIET( ptr ) ( ( void * )( ptr ) == ( void * )&MV_VolumeTable[ 0 ] )
+
+static int MV_ReverbLevel;
+static int MV_ReverbDelay;
+static VOLUME16 *MV_ReverbTable = NULL;
+
+//static signed short MV_VolumeTable[ MV_MaxVolume + 1 ][ 256 ];
+static signed short MV_VolumeTable[ 63 + 1 ][ 256 ];
+
+//static Pan MV_PanTable[ MV_NumPanPositions ][ MV_MaxVolume + 1 ];
+static Pan MV_PanTable[ MV_NumPanPositions ][ 63 + 1 ];
+
+static int MV_Installed = FALSE;
+static int MV_SoundCard = SoundBlaster;
+static int MV_TotalVolume = MV_MaxTotalVolume;
+static int MV_MaxVoices = 1;
+static int MV_Recording;
+
+static int MV_BufferSize = MixBufferSize;
+static int MV_BufferLength;
+
+static int MV_NumberOfBuffers = NumberOfBuffers;
+
+static int MV_MixMode = MONO_8BIT;
+static int MV_Channels = 1;
+static int MV_Bits = 8;
+
+static int MV_Silence = SILENCE_8BIT;
+static int MV_SwapLeftRight = FALSE;
+
+static int MV_RequestedMixRate;
+static int MV_MixRate;
+
+static int MV_DMAChannel = -1;
+static int MV_BuffShift;
+
+static int MV_TotalMemory;
+
+static long MV_BufferDescriptor;
+static int MV_BufferEmpty[ NumberOfBuffers ];
+char *MV_MixBuffer[ NumberOfBuffers + 1 ];
+
+static VoiceNode *MV_Voices = NULL;
+
+static volatile VoiceNode VoiceList;
+static volatile VoiceNode VoicePool;
+
+/*static*/ int MV_MixPage = 0;
+static int MV_VoiceHandle = MV_MinVoiceHandle;
+
+static void ( *MV_CallBackFunc )( unsigned long ) = NULL;
+static void ( *MV_RecordFunc )( char *ptr, int length ) = NULL;
+static void ( *MV_MixFunction )( VoiceNode *voice, int buffer );
+
+static int MV_MaxVolume = 63;
+
+char *MV_HarshClipTable;
+char *MV_MixDestination;
+short *MV_LeftVolume;
+short *MV_RightVolume;
+int MV_SampleSize = 1;
+int MV_RightChannelOffset;
+
+unsigned long MV_MixPosition;
+
+int MV_ErrorCode = MV_Ok;
+
+#define MV_SetErrorCode( status ) \
+ MV_ErrorCode = ( status );
+
+
+/*---------------------------------------------------------------------
+ Function: MV_ErrorString
+
+ Returns a pointer to the error message associated with an error
+ number. A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *MV_ErrorString
+ (
+ int ErrorNumber
+ )
+
+ {
+ char *ErrorString;
+
+ switch( ErrorNumber )
+ {
+ case MV_Warning :
+ case MV_Error :
+ ErrorString = MV_ErrorString( MV_ErrorCode );
+ break;
+
+ case MV_Ok :
+ ErrorString = "Multivoc ok.";
+ break;
+
+ case MV_UnsupportedCard :
+ ErrorString = "Selected sound card is not supported by Multivoc.";
+ break;
+
+ case MV_NotInstalled :
+ ErrorString = "Multivoc not installed.";
+ break;
+
+ case MV_NoVoices :
+ ErrorString = "No free voices available to Multivoc.";
+ break;
+
+ case MV_NoMem :
+ ErrorString = "Out of memory in Multivoc.";
+ break;
+
+ case MV_VoiceNotFound :
+ ErrorString = "No voice with matching handle found.";
+ break;
+
+#ifdef PLAT_DOS
+ case MV_BlasterError :
+ ErrorString = BLASTER_ErrorString( BLASTER_Error );
+ break;
+
+ case MV_PasError :
+ ErrorString = PAS_ErrorString( PAS_Error );
+ break;
+
+ case MV_SoundScapeError :
+ ErrorString = SOUNDSCAPE_ErrorString( SOUNDSCAPE_Error );
+ break;
+
+ #ifndef SOUNDSOURCE_OFF
+ case MV_SoundSourceError :
+ ErrorString = SS_ErrorString( SS_Error );
+ break;
+ #endif
+#endif
+
+ case MV_DPMI_Error :
+ ErrorString = "DPMI Error in Multivoc.";
+ break;
+
+ case MV_InvalidVOCFile :
+ ErrorString = "Invalid VOC file passed in to Multivoc.";
+ break;
+
+ case MV_InvalidWAVFile :
+ ErrorString = "Invalid WAV file passed in to Multivoc.";
+ break;
+
+ case MV_InvalidMixMode :
+ ErrorString = "Invalid mix mode request in Multivoc.";
+ break;
+
+ case MV_SoundSourceFailure :
+ ErrorString = "Sound Source playback failed.";
+ break;
+
+ case MV_IrqFailure :
+ ErrorString = "Playback failed, possibly due to an invalid or conflicting IRQ.";
+ break;
+
+ case MV_DMAFailure :
+ ErrorString = "Playback failed, possibly due to an invalid or conflicting DMA channel.";
+ break;
+
+ case MV_DMA16Failure :
+ ErrorString = "Playback failed, possibly due to an invalid or conflicting DMA channel. \n"
+ "Make sure the 16-bit DMA channel is correct.";
+ break;
+
+ case MV_NullRecordFunction :
+ ErrorString = "Null record function passed to MV_StartRecording.";
+ break;
+
+ default :
+ ErrorString = "Unknown Multivoc error code.";
+ break;
+ }
+
+ return( ErrorString );
+ }
+
+
+/**********************************************************************
+
+ Memory locked functions:
+
+**********************************************************************/
+
+
+#define MV_LockStart MV_Mix
+
+
+/*---------------------------------------------------------------------
+ Function: MV_Mix
+
+ Mixes the sound into the buffer.
+---------------------------------------------------------------------*/
+
+static void MV_Mix
+ (
+ VoiceNode *voice,
+ int buffer
+ )
+
+ {
+ char *start;
+ int length;
+ long voclength;
+ unsigned long position;
+ unsigned long rate;
+ unsigned long FixedPointBufferSize;
+
+ if ( ( voice->length == 0 ) &&
+ ( voice->GetSound != NULL ) &&
+ ( voice->GetSound( voice ) != KeepPlaying ) )
+ {
+ return;
+ }
+
+ length = MixBufferSize;
+ FixedPointBufferSize = voice->FixedPointBufferSize;
+
+ MV_MixDestination = MV_MixBuffer[ buffer ];
+ MV_LeftVolume = voice->LeftVolume;
+ MV_RightVolume = voice->RightVolume;
+
+ if ( ( MV_Channels == 2 ) && ( IS_QUIET( MV_LeftVolume ) ) )
+ {
+ MV_LeftVolume = MV_RightVolume;
+ MV_MixDestination += MV_RightChannelOffset;
+ }
+
+ // Add this voice to the mix
+ while( length > 0 )
+ {
+ start = voice->sound;
+ rate = voice->RateScale;
+ position = voice->position;
+
+ // Check if the last sample in this buffer would be
+ // beyond the length of the sample block
+ if ( ( position + FixedPointBufferSize ) >= voice->length )
+ {
+ if ( position < voice->length )
+ {
+ voclength = ( voice->length - position + rate - 1 ) / rate;
+ }
+ else
+ {
+ voice->GetSound( voice );
+ return;
+ }
+ }
+ else
+ {
+ voclength = length;
+ }
+
+ voice->mix( position, rate, start, voclength );
+
+ if ( voclength & 1 )
+ {
+ MV_MixPosition += rate;
+ voclength -= 1;
+ }
+ voice->position = MV_MixPosition;
+
+ length -= voclength;
+
+ if ( voice->position >= voice->length )
+ {
+ // Get the next block of sound
+ if ( voice->GetSound( voice ) != KeepPlaying )
+ {
+ return;
+ }
+
+ if ( length > 0 )
+ {
+ // Get the position of the last sample in the buffer
+ FixedPointBufferSize = voice->RateScale * ( length - 1 );
+ }
+ }
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_PlayVoice
+
+ Adds a voice to the play list.
+---------------------------------------------------------------------*/
+
+void MV_PlayVoice
+ (
+ VoiceNode *voice
+ )
+
+ {
+ unsigned flags;
+
+ flags = DisableInterrupts();
+ LL_SortedInsertion( &VoiceList, voice, prev, next, VoiceNode, priority );
+
+ RestoreInterrupts( flags );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_StopVoice
+
+ Removes the voice from the play list and adds it to the free list.
+---------------------------------------------------------------------*/
+
+void MV_StopVoice
+ (
+ VoiceNode *voice
+ )
+
+ {
+ unsigned flags;
+
+ flags = DisableInterrupts();
+
+ // move the voice from the play list to the free list
+ LL_Remove( voice, next, prev );
+ LL_Add( (VoiceNode *)&VoicePool, voice, next, prev );
+
+ RestoreInterrupts( flags );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_ServiceVoc
+
+ Starts playback of the waiting buffer and mixes the next one.
+---------------------------------------------------------------------*/
+
+// static int backcolor = 1;
+
+void MV_ServiceVoc
+ (
+ void
+ )
+
+ {
+ VoiceNode *voice;
+ VoiceNode *next;
+ char *buffer;
+
+#ifdef PLAT_DOS
+ if ( MV_DMAChannel >= 0 )
+ {
+ // Get the currently playing buffer
+ buffer = ( char * )DMA_GetCurrentPos( MV_DMAChannel );
+ MV_MixPage = ( unsigned )( buffer - MV_MixBuffer[ 0 ] );
+ MV_MixPage >>= MV_BuffShift;
+ }
+#endif
+
+ // Toggle which buffer we'll mix next
+ MV_MixPage++;
+ if ( MV_MixPage >= MV_NumberOfBuffers )
+ {
+ MV_MixPage -= MV_NumberOfBuffers;
+ }
+
+ if ( MV_ReverbLevel == 0 )
+ {
+ // Initialize buffer
+ //Commented out so that the buffer is always cleared.
+ //This is so the guys at Echo Speech can mix into the
+ //buffer even when no sounds are playing.
+ //if ( !MV_BufferEmpty[ MV_MixPage ] )
+ {
+ ClearBuffer_DW( MV_MixBuffer[ MV_MixPage ], MV_Silence, MV_BufferSize >> 2 );
+ if ( ( MV_SoundCard == UltraSound ) && ( MV_Channels == 2 ) )
+ {
+ ClearBuffer_DW( MV_MixBuffer[ MV_MixPage ] + MV_RightChannelOffset,
+ MV_Silence, MV_BufferSize >> 2 );
+ }
+ MV_BufferEmpty[ MV_MixPage ] = TRUE;
+ }
+ }
+ else
+ {
+ char *end;
+ char *source;
+ char *dest;
+ int count;
+ int length;
+
+ end = MV_MixBuffer[ 0 ] + MV_BufferLength;;
+ dest = MV_MixBuffer[ MV_MixPage ];
+ source = MV_MixBuffer[ MV_MixPage ] - MV_ReverbDelay;
+ if ( source < MV_MixBuffer[ 0 ] )
+ {
+ source += MV_BufferLength;
+ }
+
+ length = MV_BufferSize;
+ while( length > 0 )
+ {
+ count = length;
+ if ( source + count > end )
+ {
+ count = end - source;
+ }
+
+ if ( MV_Bits == 16 )
+ {
+ if ( MV_ReverbTable != NULL )
+ {
+ MV_16BitReverb( source, dest, (const VOLUME16 *)MV_ReverbTable, count / 2 );
+ if ( ( MV_SoundCard == UltraSound ) && ( MV_Channels == 2 ) )
+ {
+ MV_16BitReverb( source + MV_RightChannelOffset,
+ dest + MV_RightChannelOffset, (const VOLUME16 *)MV_ReverbTable, count / 2 );
+ }
+ }
+ else
+ {
+ MV_16BitReverbFast( source, dest, count / 2, MV_ReverbLevel );
+ if ( ( MV_SoundCard == UltraSound ) && ( MV_Channels == 2 ) )
+ {
+ MV_16BitReverbFast( source + MV_RightChannelOffset,
+ dest + MV_RightChannelOffset, count / 2, MV_ReverbLevel );
+ }
+ }
+ }
+ else
+ {
+ if ( MV_ReverbTable != NULL )
+ {
+ MV_8BitReverb( source, dest, (const VOLUME16 *)MV_ReverbTable, count );
+ if ( ( MV_SoundCard == UltraSound ) && ( MV_Channels == 2 ) )
+ {
+ MV_8BitReverb( source + MV_RightChannelOffset,
+ dest + MV_RightChannelOffset, (const VOLUME16 *)MV_ReverbTable, count );
+ }
+ }
+ else
+ {
+ MV_8BitReverbFast( source, dest, count, MV_ReverbLevel );
+ if ( ( MV_SoundCard == UltraSound ) && ( MV_Channels == 2 ) )
+ {
+ MV_8BitReverbFast( source + MV_RightChannelOffset,
+ dest + MV_RightChannelOffset, count, MV_ReverbLevel );
+ }
+ }
+ }
+
+ // if we go through the loop again, it means that we've wrapped around the buffer
+ source = MV_MixBuffer[ 0 ];
+ dest += count;
+ length -= count;
+ }
+ }
+
+ // Play any waiting voices
+ for( voice = VoiceList.next; voice != &VoiceList; voice = next )
+ {
+// if ( ( voice < &MV_Voices[ 0 ] ) || ( voice > &MV_Voices[ 8 ] ) )
+// {
+// SetBorderColor(backcolor++);
+// break;
+// }
+
+ MV_BufferEmpty[ MV_MixPage ] = FALSE;
+
+ MV_MixFunction( voice, MV_MixPage );
+
+ next = voice->next;
+
+ // Is this voice done?
+ if ( !voice->Playing )
+ {
+ MV_StopVoice( voice );
+
+ if ( MV_CallBackFunc )
+ {
+ MV_CallBackFunc( voice->callbackval );
+ }
+ }
+ }
+ }
+
+
+int leftpage = -1;
+int rightpage = -1;
+
+void MV_ServiceGus( char **ptr, unsigned long *length )
+ {
+ if ( leftpage == MV_MixPage )
+ {
+ MV_ServiceVoc();
+ }
+
+ leftpage = MV_MixPage;
+
+ *ptr = MV_MixBuffer[ MV_MixPage ];
+ *length = MV_BufferSize;
+ }
+
+void MV_ServiceRightGus( char **ptr, unsigned long *length )
+ {
+ if ( rightpage == MV_MixPage )
+ {
+ MV_ServiceVoc();
+ }
+
+ rightpage = MV_MixPage;
+
+ *ptr = MV_MixBuffer[ MV_MixPage ] + MV_RightChannelOffset;
+ *length = MV_BufferSize;
+ }
+
+/*---------------------------------------------------------------------
+ Function: MV_GetNextVOCBlock
+
+ Interperate the information of a VOC format sound file.
+---------------------------------------------------------------------*/
+static __inline unsigned int get_le32(void *p0)
+{
+ //unsigned char *p = p0;
+ //return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
+ unsigned int val = *((unsigned int *) p0);
+ return(BUILDSWAP_INTEL32(val));
+}
+
+static __inline unsigned int get_le16(void *p0)
+{
+ //unsigned char *p = p0;
+ //return p[0] | (p[1]<<8);
+ unsigned short val = *((unsigned short *) p0);
+ return( (unsigned int) (BUILDSWAP_INTEL16(val)) );
+}
+
+playbackstatus MV_GetNextVOCBlock
+ (
+ VoiceNode *voice
+ )
+
+ {
+ unsigned char *ptr;
+ int blocktype=0;
+ int lastblocktype=0;
+ unsigned long blocklength=0l;
+ unsigned long samplespeed=0l;
+ unsigned int tc=0;
+ int packtype=0;
+ int voicemode=0;
+ int done=0;
+ unsigned BitsPerSample;
+ unsigned Channels;
+ unsigned Format;
+
+ if ( voice->BlockLength > 0 )
+ {
+ voice->position -= voice->length;
+ voice->sound += voice->length >> 16;
+ if ( voice->bits == 16 )
+ {
+ voice->sound += voice->length >> 16;
+ }
+ voice->length = min( voice->BlockLength, 0x8000 );
+ voice->BlockLength -= voice->length;
+ voice->length <<= 16;
+ return( KeepPlaying );
+ }
+
+ if ( ( voice->length > 0 ) && ( voice->LoopEnd != NULL ) &&
+ ( voice->LoopStart != NULL ) )
+ {
+ voice->BlockLength = voice->LoopSize;
+ voice->sound = voice->LoopStart;
+ voice->position = 0;
+ voice->length = min( voice->BlockLength, 0x8000 );
+ voice->BlockLength -= voice->length;
+ voice->length <<= 16;
+ return( KeepPlaying );
+ }
+
+ ptr = ( unsigned char * )voice->NextBlock;
+
+ voice->Playing = TRUE;
+
+ voicemode = 0;
+ lastblocktype = 0;
+ packtype = 0;
+
+ done = FALSE;
+ while( !done )
+ {
+ // Stop playing if we get a NULL pointer
+ if ( ptr == NULL )
+ {
+ voice->Playing = FALSE;
+ done = TRUE;
+ break;
+ }
+
+ {
+ unsigned tmp = get_le32(ptr);
+ blocktype = tmp&255;
+ blocklength = tmp>>8;
+ }
+ ptr += 4;
+
+ switch( blocktype )
+ {
+ case 0 :
+ // End of data
+ if ( ( voice->LoopStart == NULL ) ||
+ ( (unsigned char *)voice->LoopStart >= ( ptr - 4 ) ) )
+ {
+ voice->Playing = FALSE;
+ done = TRUE;
+ }
+ else
+ {
+ voice->BlockLength = ( ptr - 4 ) - (unsigned char *)voice->LoopStart;
+ voice->sound = voice->LoopStart;
+ voice->position = 0;
+ voice->length = min( voice->BlockLength, 0x8000 );
+ voice->BlockLength -= voice->length;
+ voice->length <<= 16;
+ return( KeepPlaying );
+ }
+ break;
+
+ case 1 :
+ // Sound data block
+ voice->bits = 8;
+ if ( lastblocktype != 8 )
+ {
+ tc = ( unsigned int )*ptr << 8;
+ packtype = *( ptr + 1 );
+ }
+
+ ptr += 2;
+ blocklength -= 2;
+
+ samplespeed = 256000000L / ( 65536 - tc );
+
+ // Skip packed or stereo data
+ if ( ( packtype != 0 ) || ( voicemode != 0 ) )
+ {
+ ptr += blocklength;
+ }
+ else
+ {
+ done = TRUE;
+ }
+ voicemode = 0;
+ break;
+
+ case 2 :
+ // Sound continuation block
+ samplespeed = voice->SamplingRate;
+ done = TRUE;
+ break;
+
+ case 3 :
+ // Silence
+ // Not implimented.
+ ptr += blocklength;
+ break;
+
+ case 4 :
+ // Marker
+ // Not implimented.
+ ptr += blocklength;
+ break;
+
+ case 5 :
+ // ASCII string
+ // Not implimented.
+ ptr += blocklength;
+ break;
+
+ case 6 :
+ // Repeat begin
+ if ( voice->LoopEnd == NULL )
+ {
+ voice->LoopCount = get_le16(ptr);
+ voice->LoopStart = ptr + blocklength;
+ }
+ ptr += blocklength;
+ break;
+
+ case 7 :
+ // Repeat end
+ ptr += blocklength;
+ if ( lastblocktype == 6 )
+ {
+ voice->LoopCount = 0;
+ }
+ else
+ {
+ if ( ( voice->LoopCount > 0 ) && ( voice->LoopStart != NULL ) )
+ {
+ ptr = voice->LoopStart;
+ if ( voice->LoopCount < 0xffff )
+ {
+ voice->LoopCount--;
+ if ( voice->LoopCount == 0 )
+ {
+ voice->LoopStart = NULL;
+ }
+ }
+ }
+ }
+ break;
+
+ case 8 :
+ // Extended block
+ voice->bits = 8;
+ tc = get_le16(ptr);
+ packtype = *( ptr + 2 );
+ voicemode = *( ptr + 3 );
+ ptr += blocklength;
+ break;
+
+ case 9 :
+ // New sound data block
+ samplespeed = get_le32(ptr);
+ BitsPerSample = ptr[4];
+ Channels = ptr[5];
+ Format = get_le16(ptr+6);
+
+ if ( ( BitsPerSample == 8 ) && ( Channels == 1 ) &&
+ ( Format == VOC_8BIT ) )
+ {
+ ptr += 12;
+ blocklength -= 12;
+ voice->bits = 8;
+ done = TRUE;
+ }
+ else if ( ( BitsPerSample == 16 ) && ( Channels == 1 ) &&
+ ( Format == VOC_16BIT ) )
+ {
+ ptr += 12;
+ blocklength -= 12;
+ voice->bits = 16;
+ done = TRUE;
+ }
+ else
+ {
+ ptr += blocklength;
+ }
+ break;
+
+ default :
+ // Unknown data. Probably not a VOC file.
+ voice->Playing = FALSE;
+ done = TRUE;
+ break;
+ }
+
+ lastblocktype = blocktype;
+ }
+
+ if ( voice->Playing )
+ {
+ voice->NextBlock = ptr + blocklength;
+ voice->sound = ptr;
+
+ voice->SamplingRate = samplespeed;
+ voice->RateScale = ( voice->SamplingRate * voice->PitchScale ) / MV_MixRate;
+
+ // Multiply by MixBufferSize - 1
+ voice->FixedPointBufferSize = ( voice->RateScale * MixBufferSize ) -
+ voice->RateScale;
+
+ if ( voice->LoopEnd != NULL )
+ {
+ if ( blocklength > ( unsigned long )voice->LoopEnd )
+ {
+ blocklength = ( unsigned long )voice->LoopEnd;
+ }
+ else
+ {
+ voice->LoopEnd = ( char * )blocklength;
+ }
+
+ voice->LoopStart = voice->sound + ( unsigned long )voice->LoopStart;
+ voice->LoopEnd = voice->sound + ( unsigned long )voice->LoopEnd;
+ voice->LoopSize = voice->LoopEnd - voice->LoopStart;
+ }
+
+ if ( voice->bits == 16 )
+ {
+ blocklength /= 2;
+ }
+
+ voice->position = 0;
+ voice->length = min( blocklength, 0x8000 );
+ voice->BlockLength = blocklength - voice->length;
+ voice->length <<= 16;
+
+ MV_SetVoiceMixMode( voice );
+
+ return( KeepPlaying );
+ }
+
+ return( NoMoreData );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_GetNextDemandFeedBlock
+
+ Controls playback of demand fed data.
+---------------------------------------------------------------------*/
+
+playbackstatus MV_GetNextDemandFeedBlock
+ (
+ VoiceNode *voice
+ )
+
+ {
+ if ( voice->BlockLength > 0 )
+ {
+ voice->position -= voice->length;
+ voice->sound += voice->length >> 16;
+ voice->length = min( voice->BlockLength, 0x8000 );
+ voice->BlockLength -= voice->length;
+ voice->length <<= 16;
+
+ return( KeepPlaying );
+ }
+
+ if ( voice->DemandFeed == NULL )
+ {
+ return( NoMoreData );
+ }
+
+ voice->position = 0;
+ ( voice->DemandFeed )( &voice->sound, &voice->BlockLength );
+ voice->length = min( voice->BlockLength, 0x8000 );
+ voice->BlockLength -= voice->length;
+ voice->length <<= 16;
+
+ if ( ( voice->length > 0 ) && ( voice->sound != NULL ) )
+ {
+ return( KeepPlaying );
+ }
+ return( NoMoreData );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_GetNextRawBlock
+
+ Controls playback of demand fed data.
+---------------------------------------------------------------------*/
+
+playbackstatus MV_GetNextRawBlock
+ (
+ VoiceNode *voice
+ )
+
+ {
+ if ( voice->BlockLength <= 0 )
+ {
+ if ( voice->LoopStart == NULL )
+ {
+ voice->Playing = FALSE;
+ return( NoMoreData );
+ }
+
+ voice->BlockLength = voice->LoopSize;
+ voice->NextBlock = voice->LoopStart;
+ voice->length = 0;
+ voice->position = 0;
+ }
+
+ voice->sound = voice->NextBlock;
+ voice->position -= voice->length;
+ voice->length = min( voice->BlockLength, 0x8000 );
+ voice->NextBlock += voice->length;
+ if ( voice->bits == 16 )
+ {
+ voice->NextBlock += voice->length;
+ }
+ voice->BlockLength -= voice->length;
+ voice->length <<= 16;
+
+ return( KeepPlaying );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_GetNextWAVBlock
+
+ Controls playback of demand fed data.
+---------------------------------------------------------------------*/
+
+playbackstatus MV_GetNextWAVBlock
+ (
+ VoiceNode *voice
+ )
+
+ {
+ if ( voice->BlockLength <= 0 )
+ {
+ if ( voice->LoopStart == NULL )
+ {
+ voice->Playing = FALSE;
+ return( NoMoreData );
+ }
+
+ voice->BlockLength = voice->LoopSize;
+ voice->NextBlock = voice->LoopStart;
+ voice->length = 0;
+ voice->position = 0;
+ }
+
+ voice->sound = voice->NextBlock;
+ voice->position -= voice->length;
+ voice->length = min( voice->BlockLength, 0x8000 );
+ voice->NextBlock += voice->length;
+ if ( voice->bits == 16 )
+ {
+ voice->NextBlock += voice->length;
+ }
+ voice->BlockLength -= voice->length;
+ voice->length <<= 16;
+
+ return( KeepPlaying );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_ServiceRecord
+
+ Starts recording of the waiting buffer.
+---------------------------------------------------------------------*/
+
+static void MV_ServiceRecord
+ (
+ void
+ )
+
+ {
+ if ( MV_RecordFunc )
+ {
+ MV_RecordFunc( MV_MixBuffer[ 0 ] + MV_MixPage * MixBufferSize,
+ MixBufferSize );
+ }
+
+ // Toggle which buffer we'll mix next
+ MV_MixPage++;
+ if ( MV_MixPage >= NumberOfBuffers )
+ {
+ MV_MixPage = 0;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_GetVoice
+
+ Locates the voice with the specified handle.
+---------------------------------------------------------------------*/
+
+VoiceNode *MV_GetVoice
+ (
+ int handle
+ )
+
+ {
+ VoiceNode *voice;
+ unsigned flags;
+
+ flags = DisableInterrupts();
+
+ for( voice = VoiceList.next; voice != &VoiceList; voice = voice->next )
+ {
+ if ( handle == voice->handle )
+ {
+ break;
+ }
+ }
+
+ RestoreInterrupts( flags );
+
+ if ( voice == &VoiceList )
+ {
+ MV_SetErrorCode( MV_VoiceNotFound );
+
+ // SBF - should this return null?
+ return NULL;
+ }
+
+ return( voice );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_VoicePlaying
+
+ Checks if the voice associated with the specified handle is
+ playing.
+---------------------------------------------------------------------*/
+
+int MV_VoicePlaying
+ (
+ int handle
+ )
+
+ {
+ VoiceNode *voice;
+
+ if ( !MV_Installed )
+ {
+ MV_SetErrorCode( MV_NotInstalled );
+ return( FALSE );
+ }
+
+ voice = MV_GetVoice( handle );
+
+ if ( voice == NULL )
+ {
+ return( FALSE );
+ }
+
+ return( TRUE );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_KillAllVoices
+
+ Stops output of all currently active voices.
+---------------------------------------------------------------------*/
+
+int MV_KillAllVoices
+ (
+ void
+ )
+
+ {
+ if ( !MV_Installed )
+ {
+ MV_SetErrorCode( MV_NotInstalled );
+ return( MV_Error );
+ }
+
+ // Remove all the voices from the list
+ while( VoiceList.next != &VoiceList )
+ {
+ MV_Kill( VoiceList.next->handle );
+ }
+
+ return( MV_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_Kill
+
+ Stops output of the voice associated with the specified handle.
+---------------------------------------------------------------------*/
+
+int MV_Kill
+ (
+ int handle
+ )
+
+ {
+ VoiceNode *voice;
+ unsigned flags;
+ unsigned long callbackval;
+
+ if ( !MV_Installed )
+ {
+ MV_SetErrorCode( MV_NotInstalled );
+ return( MV_Error );
+ }
+
+ flags = DisableInterrupts();
+
+ voice = MV_GetVoice( handle );
+ if ( voice == NULL )
+ {
+ RestoreInterrupts( flags );
+ MV_SetErrorCode( MV_VoiceNotFound );
+ return( MV_Error );
+ }
+
+ callbackval = voice->callbackval;
+
+ MV_StopVoice( voice );
+
+ RestoreInterrupts( flags );
+
+ if ( MV_CallBackFunc )
+ {
+ MV_CallBackFunc( callbackval );
+ }
+
+ return( MV_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_VoicesPlaying
+
+ Determines the number of currently active voices.
+---------------------------------------------------------------------*/
+
+int MV_VoicesPlaying
+ (
+ void
+ )
+
+ {
+ VoiceNode *voice;
+ int NumVoices = 0;
+ unsigned flags;
+
+ if ( !MV_Installed )
+ {
+ MV_SetErrorCode( MV_NotInstalled );
+ return( 0 );
+ }
+
+ flags = DisableInterrupts();
+
+ for( voice = VoiceList.next; voice != &VoiceList; voice = voice->next )
+ {
+ NumVoices++;
+ }
+
+ RestoreInterrupts( flags );
+
+ return( NumVoices );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_AllocVoice
+
+ Retrieve an inactive or lower priority voice for output.
+---------------------------------------------------------------------*/
+
+VoiceNode *MV_AllocVoice
+ (
+ int priority
+ )
+
+ {
+ VoiceNode *voice;
+ VoiceNode *node;
+ unsigned flags;
+
+//return( NULL );
+ if ( MV_Recording )
+ {
+ return( NULL );
+ }
+
+ flags = DisableInterrupts();
+
+ // Check if we have any free voices
+ if ( LL_Empty( &VoicePool, next, prev ) )
+ {
+ // check if we have a higher priority than a voice that is playing.
+ voice = VoiceList.next;
+ for( node = voice->next; node != &VoiceList; node = node->next )
+ {
+ if ( node->priority < voice->priority )
+ {
+ voice = node;
+ }
+ }
+
+ if ( priority >= voice->priority )
+ {
+ MV_Kill( voice->handle );
+ }
+ }
+
+ // Check if any voices are in the voice pool
+ if ( LL_Empty( &VoicePool, next, prev ) )
+ {
+ // No free voices
+ RestoreInterrupts( flags );
+ return( NULL );
+ }
+
+ voice = VoicePool.next;
+ LL_Remove( voice, next, prev );
+ RestoreInterrupts( flags );
+
+ // Find a free voice handle
+ do
+ {
+ MV_VoiceHandle++;
+ if ( MV_VoiceHandle < MV_MinVoiceHandle )
+ {
+ MV_VoiceHandle = MV_MinVoiceHandle;
+ }
+ }
+ while( MV_VoicePlaying( MV_VoiceHandle ) );
+
+ voice->handle = MV_VoiceHandle;
+
+ return( voice );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_VoiceAvailable
+
+ Checks if a voice can be play at the specified priority.
+---------------------------------------------------------------------*/
+
+int MV_VoiceAvailable
+ (
+ int priority
+ )
+
+ {
+ VoiceNode *voice;
+ VoiceNode *node;
+ unsigned flags;
+
+ // Check if we have any free voices
+ if ( !LL_Empty( &VoicePool, next, prev ) )
+ {
+ return( TRUE );
+ }
+
+ flags = DisableInterrupts();
+
+ // check if we have a higher priority than a voice that is playing.
+ voice = VoiceList.next;
+ for( node = VoiceList.next; node != &VoiceList; node = node->next )
+ {
+ if ( node->priority < voice->priority )
+ {
+ voice = node;
+ }
+ }
+
+ RestoreInterrupts( flags );
+
+ if ( ( voice != &VoiceList ) && ( priority >= voice->priority ) )
+ {
+ return( TRUE );
+ }
+
+ return( FALSE );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_SetVoicePitch
+
+ Sets the pitch for the specified voice.
+---------------------------------------------------------------------*/
+
+void MV_SetVoicePitch
+ (
+ VoiceNode *voice,
+ unsigned long rate,
+ int pitchoffset
+ )
+
+ {
+ voice->SamplingRate = rate;
+ voice->PitchScale = PITCH_GetScale( pitchoffset );
+ voice->RateScale = ( rate * voice->PitchScale ) / MV_MixRate;
+
+ // Multiply by MixBufferSize - 1
+ voice->FixedPointBufferSize = ( voice->RateScale * MixBufferSize ) -
+ voice->RateScale;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_SetPitch
+
+ Sets the pitch for the voice associated with the specified handle.
+---------------------------------------------------------------------*/
+
+int MV_SetPitch
+ (
+ int handle,
+ int pitchoffset
+ )
+
+ {
+ VoiceNode *voice;
+
+ if ( !MV_Installed )
+ {
+ MV_SetErrorCode( MV_NotInstalled );
+ return( MV_Error );
+ }
+
+ voice = MV_GetVoice( handle );
+ if ( voice == NULL )
+ {
+ MV_SetErrorCode( MV_VoiceNotFound );
+ return( MV_Error );
+ }
+
+ MV_SetVoicePitch( voice, voice->SamplingRate, pitchoffset );
+
+ return( MV_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_SetFrequency
+
+ Sets the frequency for the voice associated with the specified handle.
+---------------------------------------------------------------------*/
+
+int MV_SetFrequency
+ (
+ int handle,
+ int frequency
+ )
+
+ {
+ VoiceNode *voice;
+
+ if ( !MV_Installed )
+ {
+ MV_SetErrorCode( MV_NotInstalled );
+ return( MV_Error );
+ }
+
+ voice = MV_GetVoice( handle );
+ if ( voice == NULL )
+ {
+ MV_SetErrorCode( MV_VoiceNotFound );
+ return( MV_Error );
+ }
+
+ MV_SetVoicePitch( voice, frequency, 0 );
+
+ return( MV_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_GetVolumeTable
+
+ Returns a pointer to the volume table associated with the specified
+ volume.
+---------------------------------------------------------------------*/
+
+static short *MV_GetVolumeTable
+ (
+ int vol
+ )
+
+ {
+ int volume;
+ short *table;
+
+ volume = MIX_VOLUME( vol );
+
+ table = (short *)&MV_VolumeTable[ volume ];
+
+ return( table );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_SetVoiceMixMode
+
+ Selects which method should be used to mix the voice.
+---------------------------------------------------------------------*/
+
+static void MV_SetVoiceMixMode
+ (
+ VoiceNode *voice
+ )
+
+ {
+ unsigned flags;
+ int test;
+
+ flags = DisableInterrupts();
+
+ test = T_DEFAULT;
+ if ( MV_Bits == 8 )
+ {
+ test |= T_8BITS;
+ }
+
+ if ( voice->bits == 16 )
+ {
+ test |= T_16BITSOURCE;
+ }
+
+ if ( MV_Channels == 1 )
+ {
+ test |= T_MONO;
+ }
+ else
+ {
+ if ( IS_QUIET( voice->RightVolume ) )
+ {
+ test |= T_RIGHTQUIET;
+ }
+ else if ( IS_QUIET( voice->LeftVolume ) )
+ {
+ test |= T_LEFTQUIET;
+ }
+ }
+
+ // Default case
+ voice->mix = MV_Mix8BitMono;
+
+ switch( test )
+ {
+ case T_8BITS | T_MONO | T_16BITSOURCE :
+ voice->mix = MV_Mix8BitMono16;
+ break;
+
+ case T_8BITS | T_MONO :
+ voice->mix = MV_Mix8BitMono;
+ break;
+
+ case T_8BITS | T_16BITSOURCE | T_LEFTQUIET :
+ MV_LeftVolume = MV_RightVolume;
+ voice->mix = MV_Mix8BitMono16;
+ break;
+
+ case T_8BITS | T_LEFTQUIET :
+ MV_LeftVolume = MV_RightVolume;
+ voice->mix = MV_Mix8BitMono;
+ break;
+
+ case T_8BITS | T_16BITSOURCE | T_RIGHTQUIET :
+ voice->mix = MV_Mix8BitMono16;
+ break;
+
+ case T_8BITS | T_RIGHTQUIET :
+ voice->mix = MV_Mix8BitMono;
+ break;
+
+ case T_8BITS | T_16BITSOURCE :
+ voice->mix = MV_Mix8BitStereo16;
+ break;
+
+ case T_8BITS :
+ voice->mix = MV_Mix8BitStereo;
+ break;
+
+ case T_MONO | T_16BITSOURCE :
+ voice->mix = MV_Mix16BitMono16;
+ break;
+
+ case T_MONO :
+ voice->mix = MV_Mix16BitMono;
+ break;
+
+ case T_16BITSOURCE | T_LEFTQUIET :
+ MV_LeftVolume = MV_RightVolume;
+ voice->mix = MV_Mix16BitMono16;
+ break;
+
+ case T_LEFTQUIET :
+ MV_LeftVolume = MV_RightVolume;
+ voice->mix = MV_Mix16BitMono;
+ break;
+
+ case T_16BITSOURCE | T_RIGHTQUIET :
+ voice->mix = MV_Mix16BitMono16;
+ break;
+
+ case T_RIGHTQUIET :
+ voice->mix = MV_Mix16BitMono;
+ break;
+
+ case T_16BITSOURCE :
+ voice->mix = MV_Mix16BitStereo16;
+ break;
+
+ case T_SIXTEENBIT_STEREO :
+ voice->mix = MV_Mix16BitStereo;
+ break;
+
+ default :
+ voice->mix = MV_Mix8BitMono;
+ }
+
+ RestoreInterrupts( flags );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_SetVoiceVolume
+
+ Sets the stereo and mono volume level of the voice associated
+ with the specified handle.
+---------------------------------------------------------------------*/
+
+void MV_SetVoiceVolume
+ (
+ VoiceNode *voice,
+ int vol,
+ int left,
+ int right
+ )
+
+ {
+ if ( MV_Channels == 1 )
+ {
+ left = vol;
+ right = vol;
+ }
+
+ if ( MV_SwapLeftRight )
+ {
+ // SBPro uses reversed panning
+ voice->LeftVolume = MV_GetVolumeTable( right );
+ voice->RightVolume = MV_GetVolumeTable( left );
+ }
+ else
+ {
+ voice->LeftVolume = MV_GetVolumeTable( left );
+ voice->RightVolume = MV_GetVolumeTable( right );
+ }
+
+ MV_SetVoiceMixMode( voice );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_EndLooping
+
+ Stops the voice associated with the specified handle from looping
+ without stoping the sound.
+---------------------------------------------------------------------*/
+
+int MV_EndLooping
+ (
+ int handle
+ )
+
+ {
+ VoiceNode *voice;
+ unsigned flags;
+
+ if ( !MV_Installed )
+ {
+ MV_SetErrorCode( MV_NotInstalled );
+ return( MV_Error );
+ }
+
+ flags = DisableInterrupts();
+
+ voice = MV_GetVoice( handle );
+ if ( voice == NULL )
+ {
+ RestoreInterrupts( flags );
+ MV_SetErrorCode( MV_VoiceNotFound );
+ return( MV_Warning );
+ }
+
+ voice->LoopCount = 0;
+ voice->LoopStart = NULL;
+ voice->LoopEnd = NULL;
+
+ RestoreInterrupts( flags );
+
+ return( MV_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_SetPan
+
+ Sets the stereo and mono volume level of the voice associated
+ with the specified handle.
+---------------------------------------------------------------------*/
+
+int MV_SetPan
+ (
+ int handle,
+ int vol,
+ int left,
+ int right
+ )
+
+ {
+ VoiceNode *voice;
+
+ if ( !MV_Installed )
+ {
+ MV_SetErrorCode( MV_NotInstalled );
+ return( MV_Error );
+ }
+
+ voice = MV_GetVoice( handle );
+ if ( voice == NULL )
+ {
+ MV_SetErrorCode( MV_VoiceNotFound );
+ return( MV_Warning );
+ }
+
+ MV_SetVoiceVolume( voice, vol, left, right );
+
+ return( MV_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_Pan3D
+
+ Set the angle and distance from the listener of the voice associated
+ with the specified handle.
+---------------------------------------------------------------------*/
+
+int MV_Pan3D
+ (
+ int handle,
+ int angle,
+ int distance
+ )
+
+ {
+ int left;
+ int right;
+ int mid;
+ int volume;
+ int status;
+
+ if ( distance < 0 )
+ {
+ distance = -distance;
+ angle += MV_NumPanPositions / 2;
+ }
+
+ volume = MIX_VOLUME( distance );
+
+ // Ensure angle is within 0 - 31
+ angle &= MV_MaxPanPosition;
+
+ left = MV_PanTable[ angle ][ volume ].left;
+ right = MV_PanTable[ angle ][ volume ].right;
+ mid = max( 0, 255 - distance );
+
+ status = MV_SetPan( handle, mid, left, right );
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_SetReverb
+
+ Sets the level of reverb to add to mix.
+---------------------------------------------------------------------*/
+
+void MV_SetReverb
+ (
+ int reverb
+ )
+
+ {
+ MV_ReverbLevel = MIX_VOLUME( reverb );
+ MV_ReverbTable = &MV_VolumeTable[ MV_ReverbLevel ];
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_SetFastReverb
+
+ Sets the level of reverb to add to mix.
+---------------------------------------------------------------------*/
+
+void MV_SetFastReverb
+ (
+ int reverb
+ )
+
+ {
+ MV_ReverbLevel = max( 0, min( 16, reverb ) );
+ MV_ReverbTable = NULL;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_GetMaxReverbDelay
+
+ Returns the maximum delay time for reverb.
+---------------------------------------------------------------------*/
+
+int MV_GetMaxReverbDelay
+ (
+ void
+ )
+
+ {
+ int maxdelay;
+
+ maxdelay = MixBufferSize * MV_NumberOfBuffers;
+
+ return maxdelay;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_GetReverbDelay
+
+ Returns the current delay time for reverb.
+---------------------------------------------------------------------*/
+
+int MV_GetReverbDelay
+ (
+ void
+ )
+
+ {
+ return MV_ReverbDelay / MV_SampleSize;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_SetReverbDelay
+
+ Sets the delay level of reverb to add to mix.
+---------------------------------------------------------------------*/
+
+void MV_SetReverbDelay
+ (
+ int delay
+ )
+
+ {
+ int maxdelay;
+
+ maxdelay = MV_GetMaxReverbDelay();
+ MV_ReverbDelay = max( MixBufferSize, min( delay, maxdelay ) );
+ MV_ReverbDelay *= MV_SampleSize;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_SetMixMode
+
+ Prepares Multivoc to play stereo of mono digitized sounds.
+---------------------------------------------------------------------*/
+
+int MV_SetMixMode
+ (
+ int numchannels,
+ int samplebits
+ )
+
+ {
+ int mode;
+
+ if ( !MV_Installed )
+ {
+ MV_SetErrorCode( MV_NotInstalled );
+ return( MV_Error );
+ }
+
+ mode = 0;
+ if ( numchannels == 2 )
+ {
+ mode |= STEREO;
+ }
+ if ( samplebits == 16 )
+ {
+ mode |= SIXTEEN_BIT;
+ }
+
+#ifdef PLAT_DOS
+ switch( MV_SoundCard )
+ {
+ case UltraSound :
+ MV_MixMode = mode;
+ break;
+
+ case SoundBlaster :
+ case Awe32 :
+ MV_MixMode = BLASTER_SetMixMode( mode );
+ break;
+
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ MV_MixMode = PAS_SetMixMode( mode );
+ break;
+
+ case SoundScape :
+ MV_MixMode = SOUNDSCAPE_SetMixMode( mode );
+ break;
+
+ #ifndef SOUNDSOURCE_OFF
+ case SoundSource :
+ case TandySoundSource :
+ MV_MixMode = SS_SetMixMode( mode );
+ break;
+ #endif
+ }
+#else
+ MV_MixMode = mode;
+#endif
+
+ MV_Channels = 1;
+ if ( MV_MixMode & STEREO )
+ {
+ MV_Channels = 2;
+ }
+
+ MV_Bits = 8;
+ if ( MV_MixMode & SIXTEEN_BIT )
+ {
+ MV_Bits = 16;
+ }
+
+ MV_BuffShift = 7 + MV_Channels;
+ MV_SampleSize = sizeof( MONO8 ) * MV_Channels;
+
+ if ( MV_Bits == 8 )
+ {
+ MV_Silence = SILENCE_8BIT;
+ }
+ else
+ {
+ MV_Silence = SILENCE_16BIT;
+ MV_BuffShift += 1;
+ MV_SampleSize *= 2;
+ }
+
+ MV_BufferSize = MixBufferSize * MV_SampleSize;
+ MV_NumberOfBuffers = TotalBufferSize / MV_BufferSize;
+ MV_BufferLength = TotalBufferSize;
+
+ MV_RightChannelOffset = MV_SampleSize / 2;
+ if ( ( MV_SoundCard == UltraSound ) && ( MV_Channels == 2 ) )
+ {
+ MV_SampleSize /= 2;
+ MV_BufferSize /= 2;
+ MV_RightChannelOffset = MV_BufferSize * MV_NumberOfBuffers;
+ MV_BufferLength /= 2;
+ }
+
+ return( MV_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_StartPlayback
+
+ Starts the sound playback engine.
+---------------------------------------------------------------------*/
+
+int MV_StartPlayback
+ (
+ void
+ )
+
+ {
+ int status;
+ int buffer;
+
+ // Initialize the buffers
+ ClearBuffer_DW( MV_MixBuffer[ 0 ], MV_Silence, TotalBufferSize >> 2 );
+ for( buffer = 0; buffer < MV_NumberOfBuffers; buffer++ )
+ {
+ MV_BufferEmpty[ buffer ] = TRUE;
+ }
+
+ // Set the mix buffer variables
+ MV_MixPage = 1;
+
+ MV_MixFunction = MV_Mix;
+
+//JIM
+// MV_MixRate = MV_RequestedMixRate;
+// return( MV_Ok );
+
+ // Start playback
+#ifdef PLAT_DOS
+ switch( MV_SoundCard )
+ {
+ case SoundBlaster :
+ case Awe32 :
+ status = BLASTER_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
+ TotalBufferSize, MV_NumberOfBuffers,
+ MV_RequestedMixRate, MV_MixMode, MV_ServiceVoc );
+
+ if ( status != BLASTER_Ok )
+ {
+ MV_SetErrorCode( MV_BlasterError );
+ return( MV_Error );
+ }
+
+ MV_MixRate = BLASTER_GetPlaybackRate();
+ MV_DMAChannel = BLASTER_DMAChannel;
+ break;
+
+ case UltraSound :
+
+ status = GUSWAVE_StartDemandFeedPlayback( MV_ServiceGus, 1,
+ MV_Bits, MV_RequestedMixRate, 0, ( MV_Channels == 1 ) ?
+ 0 : 24, 255, 0xffff, 0 );
+ if ( status < GUSWAVE_Ok )
+ {
+ MV_SetErrorCode( MV_BlasterError );
+ return( MV_Error );
+ }
+
+ if ( MV_Channels == 2 )
+ {
+ status = GUSWAVE_StartDemandFeedPlayback( MV_ServiceRightGus, 1,
+ MV_Bits, MV_RequestedMixRate, 0, 8, 255, 0xffff, 0 );
+ if ( status < GUSWAVE_Ok )
+ {
+ GUSWAVE_KillAllVoices();
+ MV_SetErrorCode( MV_BlasterError );
+ return( MV_Error );
+ }
+ }
+
+ MV_MixRate = MV_RequestedMixRate;
+ MV_DMAChannel = -1;
+ break;
+
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ status = PAS_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
+ TotalBufferSize, MV_NumberOfBuffers,
+ MV_RequestedMixRate, MV_MixMode, MV_ServiceVoc );
+
+ if ( status != PAS_Ok )
+ {
+ MV_SetErrorCode( MV_PasError );
+ return( MV_Error );
+ }
+
+ MV_MixRate = PAS_GetPlaybackRate();
+ MV_DMAChannel = PAS_DMAChannel;
+ break;
+
+ case SoundScape :
+ status = SOUNDSCAPE_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
+ TotalBufferSize, MV_NumberOfBuffers, MV_RequestedMixRate,
+ MV_MixMode, MV_ServiceVoc );
+
+ if ( status != SOUNDSCAPE_Ok )
+ {
+ MV_SetErrorCode( MV_SoundScapeError );
+ return( MV_Error );
+ }
+
+ MV_MixRate = SOUNDSCAPE_GetPlaybackRate();
+ MV_DMAChannel = SOUNDSCAPE_DMAChannel;
+ break;
+
+ #ifndef SOUNDSOURCE_OFF
+ case SoundSource :
+ case TandySoundSource :
+ SS_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
+ TotalBufferSize, MV_NumberOfBuffers,
+ MV_ServiceVoc );
+ MV_MixRate = SS_SampleRate;
+ MV_DMAChannel = -1;
+ break;
+ #endif
+ }
+#else
+ status = DSL_BeginBufferedPlayback( MV_MixBuffer[ 0 ],
+ TotalBufferSize, MV_NumberOfBuffers,
+ MV_RequestedMixRate, MV_MixMode, MV_ServiceVoc );
+
+ if ( status != DSL_Ok )
+ {
+ MV_SetErrorCode( MV_BlasterError );
+ return( MV_Error );
+ }
+
+ MV_MixRate = DSL_GetPlaybackRate();
+#endif
+
+ return( MV_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_StopPlayback
+
+ Stops the sound playback engine.
+---------------------------------------------------------------------*/
+
+void MV_StopPlayback
+ (
+ void
+ )
+
+ {
+ VoiceNode *voice;
+ VoiceNode *next;
+ unsigned flags;
+
+#ifdef PLAT_DOS
+ // Stop sound playback
+ switch( MV_SoundCard )
+ {
+ case SoundBlaster :
+ case Awe32 :
+ BLASTER_StopPlayback();
+ break;
+
+ case UltraSound :
+ GUSWAVE_KillAllVoices();
+ break;
+
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ PAS_StopPlayback();
+ break;
+
+ case SoundScape :
+ SOUNDSCAPE_StopPlayback();
+ break;
+
+ #ifndef SOUNDSOURCE_OFF
+ case SoundSource :
+ case TandySoundSource :
+ SS_StopPlayback();
+ break;
+ #endif
+ }
+#else
+ DSL_StopPlayback();
+#endif
+
+ // Make sure all callbacks are done.
+ flags = DisableInterrupts();
+
+ for( voice = VoiceList.next; voice != &VoiceList; voice = next )
+ {
+ next = voice->next;
+
+ MV_StopVoice( voice );
+
+ if ( MV_CallBackFunc )
+ {
+ MV_CallBackFunc( voice->callbackval );
+ }
+ }
+
+ RestoreInterrupts( flags );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_StartRecording
+
+ Starts the sound recording engine.
+---------------------------------------------------------------------*/
+
+int MV_StartRecording
+ (
+ int MixRate,
+ void ( *function )( char *ptr, int length )
+ )
+
+ {
+#ifdef PLAT_DOS
+ int status;
+
+ switch( MV_SoundCard )
+ {
+ case SoundBlaster :
+ case Awe32 :
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ break;
+
+ default :
+ MV_SetErrorCode( MV_UnsupportedCard );
+ return( MV_Error );
+ break;
+ }
+
+ if ( function == NULL )
+ {
+ MV_SetErrorCode( MV_NullRecordFunction );
+ return( MV_Error );
+ }
+
+ MV_StopPlayback();
+
+ // Initialize the buffers
+ ClearBuffer_DW( MV_MixBuffer[ 0 ], SILENCE_8BIT, TotalBufferSize >> 2 );
+
+ // Set the mix buffer variables
+ MV_MixPage = 0;
+
+ MV_RecordFunc = function;
+
+ // Start playback
+ switch( MV_SoundCard )
+ {
+ case SoundBlaster :
+ case Awe32 :
+ status = BLASTER_BeginBufferedRecord( MV_MixBuffer[ 0 ],
+ TotalBufferSize, NumberOfBuffers, MixRate, MONO_8BIT,
+ MV_ServiceRecord );
+
+ if ( status != BLASTER_Ok )
+ {
+ MV_SetErrorCode( MV_BlasterError );
+ return( MV_Error );
+ }
+ break;
+
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ status = PAS_BeginBufferedRecord( MV_MixBuffer[ 0 ],
+ TotalBufferSize, NumberOfBuffers, MixRate, MONO_8BIT,
+ MV_ServiceRecord );
+
+ if ( status != PAS_Ok )
+ {
+ MV_SetErrorCode( MV_PasError );
+ return( MV_Error );
+ }
+ break;
+ }
+
+ MV_Recording = TRUE;
+ return( MV_Ok );
+#else
+ MV_SetErrorCode( MV_UnsupportedCard );
+ return( MV_Error );
+#endif
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_StopRecord
+
+ Stops the sound record engine.
+---------------------------------------------------------------------*/
+
+void MV_StopRecord
+ (
+ void
+ )
+
+ {
+#ifdef PLAT_DOS
+ // Stop sound playback
+ switch( MV_SoundCard )
+ {
+ case SoundBlaster :
+ case Awe32 :
+ BLASTER_StopPlayback();
+ break;
+
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ PAS_StopPlayback();
+ break;
+ }
+
+ MV_Recording = FALSE;
+ MV_StartPlayback();
+#endif
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_StartDemandFeedPlayback
+
+ Plays a digitized sound from a user controlled buffering system.
+---------------------------------------------------------------------*/
+
+int MV_StartDemandFeedPlayback
+ (
+ void ( *function )( char **ptr, unsigned long *length ),
+ int rate,
+ int pitchoffset,
+ int vol,
+ int left,
+ int right,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ VoiceNode *voice;
+
+ if ( !MV_Installed )
+ {
+ MV_SetErrorCode( MV_NotInstalled );
+ return( MV_Error );
+ }
+
+ // Request a voice from the voice pool
+ voice = MV_AllocVoice( priority );
+ if ( voice == NULL )
+ {
+ MV_SetErrorCode( MV_NoVoices );
+ return( MV_Error );
+ }
+
+ voice->wavetype = DemandFeed;
+ voice->bits = 8;
+ voice->GetSound = MV_GetNextDemandFeedBlock;
+ voice->NextBlock = NULL;
+ voice->DemandFeed = function;
+ voice->LoopStart = NULL;
+ voice->LoopCount = 0;
+ voice->BlockLength = 0;
+ voice->position = 0;
+ voice->sound = NULL;
+ voice->length = 0;
+ voice->BlockLength = 0;
+ voice->Playing = TRUE;
+ voice->next = NULL;
+ voice->prev = NULL;
+ voice->priority = priority;
+ voice->callbackval = callbackval;
+
+ MV_SetVoicePitch( voice, rate, pitchoffset );
+ MV_SetVoiceVolume( voice, vol, left, right );
+ MV_PlayVoice( voice );
+
+ return( voice->handle );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_PlayRaw
+
+ Begin playback of sound data with the given sound levels and
+ priority.
+---------------------------------------------------------------------*/
+
+int MV_PlayRaw
+ (
+ char *ptr,
+ unsigned long length,
+ unsigned rate,
+ int pitchoffset,
+ int vol,
+ int left,
+ int right,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ int status;
+
+ status = MV_PlayLoopedRaw( ptr, length, NULL, NULL, rate, pitchoffset,
+ vol, left, right, priority, callbackval );
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_PlayLoopedRaw
+
+ Begin playback of sound data with the given sound levels and
+ priority.
+---------------------------------------------------------------------*/
+
+int MV_PlayLoopedRaw
+ (
+ char *ptr,
+ unsigned long length,
+ char *loopstart,
+ char *loopend,
+ unsigned rate,
+ int pitchoffset,
+ int vol,
+ int left,
+ int right,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ VoiceNode *voice;
+
+ if ( !MV_Installed )
+ {
+ MV_SetErrorCode( MV_NotInstalled );
+ return( MV_Error );
+ }
+
+ // Request a voice from the voice pool
+ voice = MV_AllocVoice( priority );
+ if ( voice == NULL )
+ {
+ MV_SetErrorCode( MV_NoVoices );
+ return( MV_Error );
+ }
+
+ voice->wavetype = Raw;
+ voice->bits = 8;
+ voice->GetSound = MV_GetNextRawBlock;
+ voice->Playing = TRUE;
+ voice->NextBlock = ptr;
+ voice->position = 0;
+ voice->BlockLength = length;
+ voice->length = 0;
+ voice->next = NULL;
+ voice->prev = NULL;
+ voice->priority = priority;
+ voice->callbackval = callbackval;
+ voice->LoopStart = loopstart;
+ voice->LoopEnd = loopend;
+ voice->LoopSize = ( voice->LoopEnd - voice->LoopStart ) + 1;
+
+ MV_SetVoicePitch( voice, rate, pitchoffset );
+ MV_SetVoiceVolume( voice, vol, left, right );
+ MV_PlayVoice( voice );
+
+ return( voice->handle );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_PlayWAV
+
+ Begin playback of sound data with the given sound levels and
+ priority.
+---------------------------------------------------------------------*/
+
+int MV_PlayWAV
+ (
+ char *ptr,
+ int pitchoffset,
+ int vol,
+ int left,
+ int right,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ int status;
+
+ status = MV_PlayLoopedWAV( ptr, -1, -1, pitchoffset, vol, left, right,
+ priority, callbackval );
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_PlayWAV3D
+
+ Begin playback of sound data at specified angle and distance
+ from listener.
+---------------------------------------------------------------------*/
+
+int MV_PlayWAV3D
+ (
+ char *ptr,
+ int pitchoffset,
+ int angle,
+ int distance,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ int left;
+ int right;
+ int mid;
+ int volume;
+ int status;
+
+ if ( !MV_Installed )
+ {
+ MV_SetErrorCode( MV_NotInstalled );
+ return( MV_Error );
+ }
+
+ if ( distance < 0 )
+ {
+ distance = -distance;
+ angle += MV_NumPanPositions / 2;
+ }
+
+ volume = MIX_VOLUME( distance );
+
+ // Ensure angle is within 0 - 31
+ angle &= MV_MaxPanPosition;
+
+ left = MV_PanTable[ angle ][ volume ].left;
+ right = MV_PanTable[ angle ][ volume ].right;
+ mid = max( 0, 255 - distance );
+
+ status = MV_PlayWAV( ptr, pitchoffset, mid, left, right, priority,
+ callbackval );
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_PlayLoopedWAV
+
+ Begin playback of sound data with the given sound levels and
+ priority.
+---------------------------------------------------------------------*/
+
+int MV_PlayLoopedWAV
+ (
+ char *ptr,
+ long loopstart,
+ long loopend,
+ int pitchoffset,
+ int vol,
+ int left,
+ int right,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ riff_header *riff;
+ format_header *format;
+ data_header *data;
+ VoiceNode *voice;
+ int length;
+ int absloopend;
+ int absloopstart;
+
+ if ( !MV_Installed )
+ {
+ MV_SetErrorCode( MV_NotInstalled );
+ return( MV_Error );
+ }
+
+ riff = ( riff_header * )ptr;
+
+ if ( ( strncmp( riff->RIFF, "RIFF", 4 ) != 0 ) ||
+ ( strncmp( riff->WAVE, "WAVE", 4 ) != 0 ) ||
+ ( strncmp( riff->fmt, "fmt ", 4) != 0 ) )
+ {
+ MV_SetErrorCode( MV_InvalidWAVFile );
+ return( MV_Error );
+ }
+
+ format = ( format_header * )( riff + 1 );
+ data = ( data_header * )( ( ( char * )format ) + riff->format_size );
+
+ // Check if it's PCM data.
+ if ( format->wFormatTag != 1 )
+ {
+ MV_SetErrorCode( MV_InvalidWAVFile );
+ return( MV_Error );
+ }
+
+ if ( format->nChannels != 1 )
+ {
+ MV_SetErrorCode( MV_InvalidWAVFile );
+ return( MV_Error );
+ }
+
+ if ( ( format->nBitsPerSample != 8 ) &&
+ ( format->nBitsPerSample != 16 ) )
+ {
+ MV_SetErrorCode( MV_InvalidWAVFile );
+ return( MV_Error );
+ }
+
+ if ( strncmp( data->DATA, "data", 4 ) != 0 )
+ {
+ MV_SetErrorCode( MV_InvalidWAVFile );
+ return( MV_Error );
+ }
+
+ // Request a voice from the voice pool
+ voice = MV_AllocVoice( priority );
+ if ( voice == NULL )
+ {
+ MV_SetErrorCode( MV_NoVoices );
+ return( MV_Error );
+ }
+
+ voice->wavetype = WAV;
+ voice->bits = format->nBitsPerSample;
+ voice->GetSound = MV_GetNextWAVBlock;
+
+ length = data->size;
+ absloopstart = loopstart;
+ absloopend = loopend;
+ if ( voice->bits == 16 )
+ {
+ loopstart *= 2;
+ data->size &= ~1;
+ loopend *= 2;
+ length /= 2;
+ }
+
+ loopend = min( loopend, (long)data->size );
+ absloopend = min( absloopend, length );
+
+ voice->Playing = TRUE;
+ voice->DemandFeed = NULL;
+ voice->LoopStart = NULL;
+ voice->LoopCount = 0;
+ voice->position = 0;
+ voice->length = 0;
+ voice->BlockLength = absloopend;
+ voice->NextBlock = ( char * )( data + 1 );
+ voice->next = NULL;
+ voice->prev = NULL;
+ voice->priority = priority;
+ voice->callbackval = callbackval;
+ voice->LoopStart = voice->NextBlock + loopstart;
+ voice->LoopEnd = voice->NextBlock + loopend;
+ voice->LoopSize = absloopend - absloopstart;
+
+ if ( ( loopstart >= (long)data->size ) || ( loopstart < 0 ) )
+ {
+ voice->LoopStart = NULL;
+ voice->LoopEnd = NULL;
+ voice->BlockLength = length;
+ }
+
+ MV_SetVoicePitch( voice, format->nSamplesPerSec, pitchoffset );
+ MV_SetVoiceVolume( voice, vol, left, right );
+ MV_PlayVoice( voice );
+
+ return( voice->handle );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_PlayVOC3D
+
+ Begin playback of sound data at specified angle and distance
+ from listener.
+---------------------------------------------------------------------*/
+
+int MV_PlayVOC3D
+ (
+ char *ptr,
+ int pitchoffset,
+ int angle,
+ int distance,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ int left;
+ int right;
+ int mid;
+ int volume;
+ int status;
+
+ if ( !MV_Installed )
+ {
+ MV_SetErrorCode( MV_NotInstalled );
+ return( MV_Error );
+ }
+
+ if ( distance < 0 )
+ {
+ distance = -distance;
+ angle += MV_NumPanPositions / 2;
+ }
+
+ volume = MIX_VOLUME( distance );
+
+ // Ensure angle is within 0 - 31
+ angle &= MV_MaxPanPosition;
+
+ left = MV_PanTable[ angle ][ volume ].left;
+ right = MV_PanTable[ angle ][ volume ].right;
+ mid = max( 0, 255 - distance );
+
+ status = MV_PlayVOC( ptr, pitchoffset, mid, left, right, priority,
+ callbackval );
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_PlayVOC
+
+ Begin playback of sound data with the given sound levels and
+ priority.
+---------------------------------------------------------------------*/
+
+int MV_PlayVOC
+ (
+ char *ptr,
+ int pitchoffset,
+ int vol,
+ int left,
+ int right,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ int status;
+
+ status = MV_PlayLoopedVOC( ptr, -1, -1, pitchoffset, vol, left, right,
+ priority, callbackval );
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_PlayLoopedVOC
+
+ Begin playback of sound data with the given sound levels and
+ priority.
+---------------------------------------------------------------------*/
+
+int MV_PlayLoopedVOC
+ (
+ char *ptr,
+ long loopstart,
+ long loopend,
+ int pitchoffset,
+ int vol,
+ int left,
+ int right,
+ int priority,
+ unsigned long callbackval
+ )
+
+ {
+ VoiceNode *voice;
+ int status;
+ unsigned short nextpos;
+
+ if ( !MV_Installed )
+ {
+ MV_SetErrorCode( MV_NotInstalled );
+ return( MV_Error );
+ }
+
+ // Make sure it's a valid VOC file.
+ status = strncmp( ptr, "Creative Voice File", 19 );
+ if ( status != 0 )
+ {
+ MV_SetErrorCode( MV_InvalidVOCFile );
+ return( MV_Error );
+ }
+
+ // Request a voice from the voice pool
+ voice = MV_AllocVoice( priority );
+ if ( voice == NULL )
+ {
+ MV_SetErrorCode( MV_NoVoices );
+ return( MV_Error );
+ }
+
+ voice->wavetype = VOC;
+ voice->bits = 8;
+ voice->GetSound = MV_GetNextVOCBlock;
+
+ nextpos = *( unsigned short * )( ptr + 0x14 );
+ voice->NextBlock = ptr + BUILDSWAP_INTEL16(nextpos);
+
+ voice->DemandFeed = NULL;
+ voice->LoopStart = NULL;
+ voice->LoopCount = 0;
+ voice->BlockLength = 0;
+ voice->PitchScale = PITCH_GetScale( pitchoffset );
+ voice->length = 0;
+ voice->next = NULL;
+ voice->prev = NULL;
+ voice->priority = priority;
+ voice->callbackval = callbackval;
+ voice->LoopStart = ( char * )loopstart;
+ voice->LoopEnd = ( char * )loopend;
+ voice->LoopSize = loopend - loopstart + 1;
+
+ if ( loopstart < 0 )
+ {
+ voice->LoopStart = NULL;
+ voice->LoopEnd = NULL;
+ }
+
+ MV_SetVoiceVolume( voice, vol, left, right );
+ MV_PlayVoice( voice );
+
+ return( voice->handle );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_LockEnd
+
+ Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void MV_LockEnd
+ (
+ void
+ )
+
+ {
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_CreateVolumeTable
+
+ Create the table used to convert sound data to a specific volume
+ level.
+---------------------------------------------------------------------*/
+
+void MV_CreateVolumeTable
+ (
+ int index,
+ int volume,
+ int MaxVolume
+ )
+
+ {
+ int val;
+ int level;
+ int i;
+
+ level = ( volume * MaxVolume ) / MV_MaxTotalVolume;
+ if ( MV_Bits == 16 )
+ {
+ for( i = 0; i < 65536; i += 256 )
+ {
+ val = i - 0x8000;
+ val *= level;
+ val /= MV_MaxVolume;
+ MV_VolumeTable[ index ][ i / 256 ] = val;
+ }
+ }
+ else
+ {
+ for( i = 0; i < 256; i++ )
+ {
+ val = i - 0x80;
+ val *= level;
+ val /= MV_MaxVolume;
+ MV_VolumeTable[ volume ][ i ] = val;
+ }
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_CalcVolume
+
+ Create the table used to convert sound data to a specific volume
+ level.
+---------------------------------------------------------------------*/
+
+void MV_CalcVolume
+ (
+ int MaxVolume
+ )
+
+ {
+ int volume;
+
+ for( volume = 0; volume < 128; volume++ )
+ {
+ MV_HarshClipTable[ volume ] = 0;
+ MV_HarshClipTable[ volume + 384 ] = 255;
+ }
+ for( volume = 0; volume < 256; volume++ )
+ {
+ MV_HarshClipTable[ volume + 128 ] = volume;
+ }
+
+ // For each volume level, create a translation table with the
+ // appropriate volume calculated.
+ for( volume = 0; volume <= MV_MaxVolume; volume++ )
+ {
+ MV_CreateVolumeTable( volume, volume, MaxVolume );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_CalcPanTable
+
+ Create the table used to determine the stereo volume level of
+ a sound located at a specific angle and distance from the listener.
+---------------------------------------------------------------------*/
+
+void MV_CalcPanTable
+ (
+ void
+ )
+
+ {
+ int level;
+ int angle;
+ int distance;
+ int HalfAngle;
+ int ramp;
+
+ HalfAngle = ( MV_NumPanPositions / 2 );
+
+ for( distance = 0; distance <= MV_MaxVolume; distance++ )
+ {
+ level = ( 255 * ( MV_MaxVolume - distance ) ) / MV_MaxVolume;
+ for( angle = 0; angle <= HalfAngle / 2; angle++ )
+ {
+ ramp = level - ( ( level * angle ) /
+ ( MV_NumPanPositions / 4 ) );
+
+ MV_PanTable[ angle ][ distance ].left = ramp;
+ MV_PanTable[ HalfAngle - angle ][ distance ].left = ramp;
+ MV_PanTable[ HalfAngle + angle ][ distance ].left = level;
+ MV_PanTable[ MV_MaxPanPosition - angle ][ distance ].left = level;
+
+ MV_PanTable[ angle ][ distance ].right = level;
+ MV_PanTable[ HalfAngle - angle ][ distance ].right = level;
+ MV_PanTable[ HalfAngle + angle ][ distance ].right = ramp;
+ MV_PanTable[ MV_MaxPanPosition - angle ][ distance ].right = ramp;
+ }
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_SetVolume
+
+ Sets the volume of digitized sound playback.
+---------------------------------------------------------------------*/
+
+void MV_SetVolume
+ (
+ int volume
+ )
+
+ {
+ volume = max( 0, volume );
+ volume = min( volume, MV_MaxTotalVolume );
+
+ MV_TotalVolume = volume;
+
+ // Calculate volume table
+ MV_CalcVolume( volume );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_GetVolume
+
+ Returns the volume of digitized sound playback.
+---------------------------------------------------------------------*/
+
+int MV_GetVolume
+ (
+ void
+ )
+
+ {
+ return( MV_TotalVolume );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_SetCallBack
+
+ Set the function to call when a voice stops.
+---------------------------------------------------------------------*/
+
+void MV_SetCallBack
+ (
+ void ( *function )( unsigned long )
+ )
+
+ {
+ MV_CallBackFunc = function;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_SetReverseStereo
+
+ Set the orientation of the left and right channels.
+---------------------------------------------------------------------*/
+
+void MV_SetReverseStereo
+ (
+ int setting
+ )
+
+ {
+ MV_SwapLeftRight = setting;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_GetReverseStereo
+
+ Returns the orientation of the left and right channels.
+---------------------------------------------------------------------*/
+
+int MV_GetReverseStereo
+ (
+ void
+ )
+
+ {
+ return( MV_SwapLeftRight );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_TestPlayback
+
+ Checks if playback has started.
+---------------------------------------------------------------------*/
+
+int MV_TestPlayback
+ (
+ void
+ )
+
+ {
+#ifdef PLAT_DOS
+ unsigned flags;
+ long time;
+ int start;
+ int status;
+ int pos;
+
+ if ( MV_SoundCard == UltraSound )
+ {
+ return( MV_Ok );
+ }
+
+ flags = DisableInterrupts();
+ _enable();
+
+ status = MV_Error;
+ start = MV_MixPage;
+ time = clock() + CLOCKS_PER_SEC * 2;
+
+ while( clock() < time )
+ {
+ if ( MV_MixPage != start )
+ {
+ status = MV_Ok;
+ }
+ }
+
+ RestoreInterrupts( flags );
+
+ if ( status != MV_Ok )
+ {
+ // Just in case an error doesn't get reported
+ MV_SetErrorCode( MV_DMAFailure );
+
+ switch( MV_SoundCard )
+ {
+ case SoundBlaster :
+ case Awe32 :
+ pos = BLASTER_GetCurrentPos();
+ break;
+
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ pos = PAS_GetCurrentPos();
+ break;
+
+ case SoundScape :
+ pos = SOUNDSCAPE_GetCurrentPos();
+ break;
+
+ #ifndef SOUNDSOURCE_OFF
+ case SoundSource :
+ case TandySoundSource :
+ MV_SetErrorCode( MV_SoundSourceFailure );
+ pos = -1;
+ break;
+ #endif
+
+ default :
+ MV_SetErrorCode( MV_UnsupportedCard );
+ pos = -2;
+ break;
+ }
+
+ if ( pos > 0 )
+ {
+ MV_SetErrorCode( MV_IrqFailure );
+ }
+ else if ( pos == 0 )
+ {
+ if ( MV_Bits == 16 )
+ {
+ MV_SetErrorCode( MV_DMA16Failure );
+ }
+ else
+ {
+ MV_SetErrorCode( MV_DMAFailure );
+ }
+ }
+ }
+
+ return( status );
+#else
+ return MV_Ok;
+#endif
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_Init
+
+ Perform the initialization of variables and memory used by
+ Multivoc.
+---------------------------------------------------------------------*/
+
+int MV_Init
+ (
+ int soundcard,
+ int MixRate,
+ int Voices,
+ int numchannels,
+ int samplebits
+ )
+
+ {
+ char *ptr;
+ int status;
+ int buffer;
+ int index;
+
+ if ( MV_Installed )
+ {
+ MV_Shutdown();
+ }
+
+ MV_SetErrorCode( MV_Ok );
+
+ status = MV_LockMemory();
+ if ( status != MV_Ok )
+ {
+ return( status );
+ }
+
+ MV_TotalMemory = Voices * sizeof( VoiceNode ) + sizeof( HARSH_CLIP_TABLE_8 );
+ status = USRHOOKS_GetMem( ( void ** )&ptr, MV_TotalMemory );
+ if ( status != USRHOOKS_Ok )
+ {
+ MV_UnlockMemory();
+ MV_SetErrorCode( MV_NoMem );
+ return( MV_Error );
+ }
+
+ status = DPMI_LockMemory( ptr, MV_TotalMemory );
+ if ( status != DPMI_Ok )
+ {
+ USRHOOKS_FreeMem( ptr );
+ MV_UnlockMemory();
+ MV_SetErrorCode( MV_DPMI_Error );
+ return( MV_Error );
+ }
+
+ MV_Voices = ( VoiceNode * )ptr;
+ MV_HarshClipTable = ptr + ( MV_TotalMemory - sizeof( HARSH_CLIP_TABLE_8 ) );
+
+ // Set number of voices before calculating volume table
+ MV_MaxVoices = Voices;
+
+ LL_Reset( (VoiceNode *)&VoiceList, next, prev );
+ LL_Reset( (VoiceNode *)&VoicePool, next, prev );
+
+ for( index = 0; index < Voices; index++ )
+ {
+ LL_Add( (VoiceNode *)&VoicePool, &MV_Voices[ index ], next, prev );
+ }
+
+ // Allocate mix buffer within 1st megabyte
+ status = DPMI_GetDOSMemory( ( void ** )&ptr, &MV_BufferDescriptor,
+ 2 * TotalBufferSize );
+
+ if ( status )
+ {
+ DPMI_UnlockMemory( MV_Voices, MV_TotalMemory );
+ USRHOOKS_FreeMem( MV_Voices );
+ MV_Voices = NULL;
+ MV_TotalMemory = 0;
+ MV_UnlockMemory();
+
+ MV_SetErrorCode( MV_NoMem );
+ return( MV_Error );
+ }
+
+ MV_SetReverseStereo( FALSE );
+
+ // Initialize the sound card
+#ifdef PLAT_DOS
+ switch( soundcard )
+ {
+ case UltraSound :
+ status = GUSWAVE_Init( 2 );
+ if ( status != GUSWAVE_Ok )
+ {
+ //JIM
+ MV_SetErrorCode( MV_BlasterError );
+ }
+ break;
+
+ case SoundBlaster :
+ case Awe32 :
+ status = BLASTER_Init();
+ if ( status != BLASTER_Ok )
+ {
+ MV_SetErrorCode( MV_BlasterError );
+ }
+
+ if ( ( BLASTER_Config.Type == SBPro ) ||
+ ( BLASTER_Config.Type == SBPro2 ) )
+ {
+ MV_SetReverseStereo( TRUE );
+ }
+ break;
+
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ status = PAS_Init();
+ if ( status != PAS_Ok )
+ {
+ MV_SetErrorCode( MV_PasError );
+ }
+ break;
+
+ case SoundScape :
+ status = SOUNDSCAPE_Init();
+ if ( status != SOUNDSCAPE_Ok )
+ {
+ MV_SetErrorCode( MV_SoundScapeError );
+ }
+ break;
+
+ #ifndef SOUNDSOURCE_OFF
+ case SoundSource :
+ case TandySoundSource :
+ status = SS_Init( soundcard );
+ if ( status != SS_Ok )
+ {
+ MV_SetErrorCode( MV_SoundSourceError );
+ }
+ break;
+ #endif
+
+ default :
+ MV_SetErrorCode( MV_UnsupportedCard );
+ break;
+ }
+#else
+ status = DSL_Init();
+ if ( status != DSL_Ok )
+ {
+ MV_SetErrorCode( MV_BlasterError );
+ }
+#endif
+
+ if ( MV_ErrorCode != MV_Ok )
+ {
+ status = MV_ErrorCode;
+
+ DPMI_UnlockMemory( MV_Voices, MV_TotalMemory );
+ USRHOOKS_FreeMem( MV_Voices );
+ MV_Voices = NULL;
+ MV_TotalMemory = 0;
+
+ DPMI_FreeDOSMemory( MV_BufferDescriptor );
+ MV_UnlockMemory();
+
+ MV_SetErrorCode( status );
+ return( MV_Error );
+ }
+
+ MV_SoundCard = soundcard;
+ MV_Installed = TRUE;
+ MV_CallBackFunc = NULL;
+ MV_RecordFunc = NULL;
+ MV_Recording = FALSE;
+ MV_ReverbLevel = 0;
+ MV_ReverbTable = NULL;
+
+ // Set the sampling rate
+ MV_RequestedMixRate = MixRate;
+
+ // Set Mixer to play stereo digitized sound
+ MV_SetMixMode( numchannels, samplebits );
+ MV_ReverbDelay = MV_BufferSize * 3;
+
+#ifdef PLAT_DOS
+ // Make sure we don't cross a physical page
+ if ( ( ( unsigned long )ptr & 0xffff ) + TotalBufferSize > 0x10000 )
+ {
+ ptr = ( char * )( ( ( unsigned long )ptr & 0xff0000 ) + 0x10000 );
+ }
+#endif
+
+ MV_MixBuffer[ MV_NumberOfBuffers ] = ptr;
+ for( buffer = 0; buffer < MV_NumberOfBuffers; buffer++ )
+ {
+ MV_MixBuffer[ buffer ] = ptr;
+ ptr += MV_BufferSize;
+ }
+
+ // Calculate pan table
+ MV_CalcPanTable();
+
+ MV_SetVolume( MV_MaxTotalVolume );
+
+ // Start the playback engine
+ status = MV_StartPlayback();
+ if ( status != MV_Ok )
+ {
+ // Preserve error code while we shutdown.
+ status = MV_ErrorCode;
+ MV_Shutdown();
+ MV_SetErrorCode( status );
+ return( MV_Error );
+ }
+
+ if ( MV_TestPlayback() != MV_Ok )
+ {
+ status = MV_ErrorCode;
+ MV_Shutdown();
+ MV_SetErrorCode( status );
+ return( MV_Error );
+ }
+
+ return( MV_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_Shutdown
+
+ Restore any resources allocated by Multivoc back to the system.
+---------------------------------------------------------------------*/
+
+int MV_Shutdown
+ (
+ void
+ )
+
+ {
+ int buffer;
+ unsigned flags;
+
+ if ( !MV_Installed )
+ {
+ return( MV_Ok );
+ }
+
+ flags = DisableInterrupts();
+
+ MV_KillAllVoices();
+
+ MV_Installed = FALSE;
+
+ // Stop the sound recording engine
+ if ( MV_Recording )
+ {
+ MV_StopRecord();
+ }
+
+ // Stop the sound playback engine
+ MV_StopPlayback();
+
+ // Shutdown the sound card
+#ifdef PLAT_DOS
+ switch( MV_SoundCard )
+ {
+ case UltraSound :
+ GUSWAVE_Shutdown();
+ break;
+
+ case SoundBlaster :
+ case Awe32 :
+ BLASTER_Shutdown();
+ break;
+
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ PAS_Shutdown();
+ break;
+
+ case SoundScape :
+ SOUNDSCAPE_Shutdown();
+ break;
+
+ #ifndef SOUNDSOURCE_OFF
+ case SoundSource :
+ case TandySoundSource :
+ SS_Shutdown();
+ break;
+ #endif
+ }
+#else
+ DSL_Shutdown();
+#endif
+
+ RestoreInterrupts( flags );
+
+ // Free any voices we allocated
+ DPMI_UnlockMemory( MV_Voices, MV_TotalMemory );
+ USRHOOKS_FreeMem( MV_Voices );
+ MV_Voices = NULL;
+ MV_TotalMemory = 0;
+
+ LL_Reset( (VoiceNode *)&VoiceList, next, prev );
+ LL_Reset( (VoiceNode *)&VoicePool, next, prev );
+
+ MV_MaxVoices = 1;
+
+ // Release the descriptor from our mix buffer
+ DPMI_FreeDOSMemory( MV_BufferDescriptor );
+ for( buffer = 0; buffer < NumberOfBuffers; buffer++ )
+ {
+ MV_MixBuffer[ buffer ] = NULL;
+ }
+
+ return( MV_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_UnlockMemory
+
+ Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+void MV_UnlockMemory
+ (
+ void
+ )
+
+ {
+ PITCH_UnlockMemory();
+
+ DPMI_UnlockMemoryRegion( MV_LockStart, MV_LockEnd );
+ DPMI_Unlock( MV_VolumeTable );
+ DPMI_Unlock( MV_PanTable );
+ DPMI_Unlock( MV_Installed );
+ DPMI_Unlock( MV_SoundCard );
+ DPMI_Unlock( MV_TotalVolume );
+ DPMI_Unlock( MV_MaxVoices );
+ DPMI_Unlock( MV_BufferSize );
+ DPMI_Unlock( MV_BufferLength );
+ DPMI_Unlock( MV_SampleSize );
+ DPMI_Unlock( MV_NumberOfBuffers );
+ DPMI_Unlock( MV_MixMode );
+ DPMI_Unlock( MV_Channels );
+ DPMI_Unlock( MV_Bits );
+ DPMI_Unlock( MV_Silence );
+ DPMI_Unlock( MV_SwapLeftRight );
+ DPMI_Unlock( MV_RequestedMixRate );
+ DPMI_Unlock( MV_MixRate );
+ DPMI_Unlock( MV_BufferDescriptor );
+ DPMI_Unlock( MV_MixBuffer );
+ DPMI_Unlock( MV_BufferEmpty );
+ DPMI_Unlock( MV_Voices );
+ DPMI_Unlock( VoiceList );
+ DPMI_Unlock( VoicePool );
+ DPMI_Unlock( MV_MixPage );
+ DPMI_Unlock( MV_VoiceHandle );
+ DPMI_Unlock( MV_CallBackFunc );
+ DPMI_Unlock( MV_RecordFunc );
+ DPMI_Unlock( MV_Recording );
+ DPMI_Unlock( MV_MixFunction );
+ DPMI_Unlock( MV_HarshClipTable );
+ DPMI_Unlock( MV_MixDestination );
+ DPMI_Unlock( MV_LeftVolume );
+ DPMI_Unlock( MV_RightVolume );
+ DPMI_Unlock( MV_MixPosition );
+ DPMI_Unlock( MV_ErrorCode );
+ DPMI_Unlock( MV_DMAChannel );
+ DPMI_Unlock( MV_BuffShift );
+ DPMI_Unlock( MV_ReverbLevel );
+ DPMI_Unlock( MV_ReverbDelay );
+ DPMI_Unlock( MV_ReverbTable );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MV_LockMemory
+
+ Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+int MV_LockMemory
+ (
+ void
+ )
+
+ {
+ int status;
+ int pitchstatus;
+
+ status = DPMI_LockMemoryRegion( MV_LockStart, MV_LockEnd );
+ status |= DPMI_Lock( MV_VolumeTable );
+ status |= DPMI_Lock( MV_PanTable );
+ status |= DPMI_Lock( MV_Installed );
+ status |= DPMI_Lock( MV_SoundCard );
+ status |= DPMI_Lock( MV_TotalVolume );
+ status |= DPMI_Lock( MV_MaxVoices );
+ status |= DPMI_Lock( MV_BufferSize );
+ status |= DPMI_Lock( MV_BufferLength );
+ status |= DPMI_Lock( MV_SampleSize );
+ status |= DPMI_Lock( MV_NumberOfBuffers );
+ status |= DPMI_Lock( MV_MixMode );
+ status |= DPMI_Lock( MV_Channels );
+ status |= DPMI_Lock( MV_Bits );
+ status |= DPMI_Lock( MV_Silence );
+ status |= DPMI_Lock( MV_SwapLeftRight );
+ status |= DPMI_Lock( MV_RequestedMixRate );
+ status |= DPMI_Lock( MV_MixRate );
+ status |= DPMI_Lock( MV_BufferDescriptor );
+ status |= DPMI_Lock( MV_MixBuffer );
+ status |= DPMI_Lock( MV_BufferEmpty );
+ status |= DPMI_Lock( MV_Voices );
+ status |= DPMI_Lock( VoiceList );
+ status |= DPMI_Lock( VoicePool );
+ status |= DPMI_Lock( MV_MixPage );
+ status |= DPMI_Lock( MV_VoiceHandle );
+ status |= DPMI_Lock( MV_CallBackFunc );
+ status |= DPMI_Lock( MV_RecordFunc );
+ status |= DPMI_Lock( MV_Recording );
+ status |= DPMI_Lock( MV_MixFunction );
+ status |= DPMI_Lock( MV_HarshClipTable );
+ status |= DPMI_Lock( MV_MixDestination );
+ status |= DPMI_Lock( MV_LeftVolume );
+ status |= DPMI_Lock( MV_RightVolume );
+ status |= DPMI_Lock( MV_MixPosition );
+ status |= DPMI_Lock( MV_ErrorCode );
+ status |= DPMI_Lock( MV_DMAChannel );
+ status |= DPMI_Lock( MV_BuffShift );
+ status |= DPMI_Lock( MV_ReverbLevel );
+ status |= DPMI_Lock( MV_ReverbDelay );
+ status |= DPMI_Lock( MV_ReverbTable );
+
+ pitchstatus = PITCH_LockMemory();
+ if ( ( pitchstatus != PITCH_Ok ) || ( status != DPMI_Ok ) )
+ {
+ MV_UnlockMemory();
+ MV_SetErrorCode( MV_DPMI_Error );
+ return( MV_Error );
+ }
+
+ return( MV_Ok );
+ }
+
+#ifndef PLAT_DOS
+void ClearBuffer_DW( void *ptr, unsigned data, int length )
+{
+ unsigned *d = (unsigned *)ptr;
+
+ while (length--) {
+ *d = data;
+
+ d++;
+ }
+}
+#endif
--- /dev/null
+++ b/rott/audiolib/multivoc.h
@@ -1,0 +1,123 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ file: MULTIVOC.H
+
+ author: James R. Dose
+ date: December 20, 1993
+
+ Public header for MULTIVOC.C
+
+ (c) Copyright 1993 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __MULTIVOC_H
+#define __MULTIVOC_H
+
+// platform.h is in buildengine, but I need the byteswapping macros... --ryan.
+#include "platform.h"
+
+#define MV_MinVoiceHandle 1
+
+extern int MV_ErrorCode;
+
+enum MV_Errors
+ {
+ MV_Warning = -2,
+ MV_Error = -1,
+ MV_Ok = 0,
+ MV_UnsupportedCard,
+ MV_NotInstalled,
+ MV_NoVoices,
+ MV_NoMem,
+ MV_VoiceNotFound,
+ MV_BlasterError,
+ MV_PasError,
+ MV_SoundScapeError,
+ MV_SoundSourceError,
+ MV_DPMI_Error,
+ MV_InvalidVOCFile,
+ MV_InvalidWAVFile,
+ MV_InvalidMixMode,
+ MV_SoundSourceFailure,
+ MV_IrqFailure,
+ MV_DMAFailure,
+ MV_DMA16Failure,
+ MV_NullRecordFunction
+ };
+
+char *MV_ErrorString( int ErrorNumber );
+int MV_VoicePlaying( int handle );
+int MV_KillAllVoices( void );
+int MV_Kill( int handle );
+int MV_VoicesPlaying( void );
+int MV_VoiceAvailable( int priority );
+int MV_SetPitch( int handle, int pitchoffset );
+int MV_SetFrequency( int handle, int frequency );
+int MV_EndLooping( int handle );
+int MV_SetPan( int handle, int vol, int left, int right );
+int MV_Pan3D( int handle, int angle, int distance );
+void MV_SetReverb( int reverb );
+void MV_SetFastReverb( int reverb );
+int MV_GetMaxReverbDelay( void );
+int MV_GetReverbDelay( void );
+void MV_SetReverbDelay( int delay );
+int MV_SetMixMode( int numchannels, int samplebits );
+int MV_StartPlayback( void );
+void MV_StopPlayback( void );
+int MV_StartRecording( int MixRate, void ( *function )( char *ptr, int length ) );
+void MV_StopRecord( void );
+int MV_StartDemandFeedPlayback( void ( *function )( char **ptr, unsigned long *length ),
+ int rate, int pitchoffset, int vol, int left, int right,
+ int priority, unsigned long callbackval );
+int MV_PlayRaw( char *ptr, unsigned long length,
+ unsigned rate, int pitchoffset, int vol, int left,
+ int right, int priority, unsigned long callbackval );
+int MV_PlayLoopedRaw( char *ptr, unsigned long length,
+ char *loopstart, char *loopend, unsigned rate, int pitchoffset,
+ int vol, int left, int right, int priority,
+ unsigned long callbackval );
+int MV_PlayWAV( char *ptr, int pitchoffset, int vol, int left,
+ int right, int priority, unsigned long callbackval );
+int MV_PlayWAV3D( char *ptr, int pitchoffset, int angle, int distance,
+ int priority, unsigned long callbackval );
+int MV_PlayLoopedWAV( char *ptr, long loopstart, long loopend,
+ int pitchoffset, int vol, int left, int right, int priority,
+ unsigned long callbackval );
+int MV_PlayVOC3D( char *ptr, int pitchoffset, int angle, int distance,
+ int priority, unsigned long callbackval );
+int MV_PlayVOC( char *ptr, int pitchoffset, int vol, int left, int right,
+ int priority, unsigned long callbackval );
+int MV_PlayLoopedVOC( char *ptr, long loopstart, long loopend,
+ int pitchoffset, int vol, int left, int right, int priority,
+ unsigned long callbackval );
+void MV_CreateVolumeTable( int index, int volume, int MaxVolume );
+void MV_SetVolume( int volume );
+int MV_GetVolume( void );
+void MV_SetCallBack( void ( *function )( unsigned long ) );
+void MV_SetReverseStereo( int setting );
+int MV_GetReverseStereo( void );
+int MV_Init( int soundcard, int MixRate, int Voices, int numchannels,
+ int samplebits );
+int MV_Shutdown( void );
+void MV_UnlockMemory( void );
+int MV_LockMemory( void );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/music.c
@@ -1,0 +1,1035 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: MUSIC.C
+
+ author: James R. Dose
+ date: March 25, 1994
+
+ Device independant music playback routines.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "task_man.h"
+#include "sndcards.h"
+#include "music.h"
+#include "midi.h"
+#include "al_midi.h"
+#include "pas16.h"
+#include "blaster.h"
+#include "gusmidi.h"
+#include "mpu401.h"
+#include "awe32.h"
+#include "sndscape.h"
+#include "ll_man.h"
+#include "user.h"
+
+#define TRUE ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+void TextMode( void );
+#pragma aux TextMode = \
+ "mov ax, 0003h", \
+ "int 10h" \
+ modify [ ax ];
+
+int MUSIC_SoundDevice = -1;
+int MUSIC_ErrorCode = MUSIC_Ok;
+
+static midifuncs MUSIC_MidiFunctions;
+
+static int MUSIC_FadeLength;
+static int MUSIC_FadeRate;
+static unsigned MUSIC_CurrentFadeVolume;
+static unsigned MUSIC_LastFadeVolume;
+static int MUSIC_EndingFadeVolume;
+static task *MUSIC_FadeTask = NULL;
+
+int MUSIC_InitAWE32( midifuncs *Funcs );
+int MUSIC_InitFM( int card, midifuncs *Funcs );
+int MUSIC_InitMidi( int card, midifuncs *Funcs, int Address );
+int MUSIC_InitGUS( midifuncs *Funcs );
+
+#define MUSIC_SetErrorCode( status ) \
+ MUSIC_ErrorCode = ( status );
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_ErrorString
+
+ Returns a pointer to the error message associated with an error
+ number. A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *MUSIC_ErrorString
+ (
+ int ErrorNumber
+ )
+
+ {
+ char *ErrorString;
+
+ switch( ErrorNumber )
+ {
+ case MUSIC_Warning :
+ case MUSIC_Error :
+ ErrorString = MUSIC_ErrorString( MUSIC_ErrorCode );
+ break;
+
+ case MUSIC_Ok :
+ ErrorString = "Music ok.";
+ break;
+
+ case MUSIC_ASSVersion :
+ ErrorString = "Apogee Sound System Version " ASS_VERSION_STRING " "
+ "Programmed by Jim Dose\n"
+ "(c) Copyright 1996 James R. Dose. All Rights Reserved.\n";
+ break;
+
+ case MUSIC_SoundCardError :
+ switch( MUSIC_SoundDevice )
+ {
+ case SoundBlaster :
+ case WaveBlaster :
+ ErrorString = BLASTER_ErrorString( BLASTER_Error );
+ break;
+
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ ErrorString = PAS_ErrorString( PAS_Error );
+ break;
+
+ case Adlib :
+ ErrorString = "Adlib error.";
+ break;
+
+ case GenMidi :
+ case SoundCanvas :
+ ErrorString = "Could not detect MPU-401.";
+ break;
+
+ case SoundScape :
+ ErrorString = SOUNDSCAPE_ErrorString( SOUNDSCAPE_Error );
+ break;
+
+ case Awe32 :
+ ErrorString = AWE32_ErrorString( AWE32_Error );
+ break;
+
+ case UltraSound :
+ ErrorString = GUS_ErrorString( GUS_Error );
+ break;
+
+ default :
+ ErrorString = MUSIC_ErrorString( MUSIC_InvalidCard );
+ break;
+ }
+ break;
+
+ case MUSIC_MPU401Error :
+ ErrorString = "Could not detect MPU-401.";
+ break;
+
+ case MUSIC_InvalidCard :
+ ErrorString = "Invalid Music device.";
+ break;
+
+ case MUSIC_MidiError :
+ ErrorString = "Error playing MIDI file.";
+ break;
+
+ case MUSIC_TaskManError :
+ ErrorString = "TaskMan error.";
+ break;
+
+ case MUSIC_FMNotDetected :
+ ErrorString = "Could not detect FM chip.";
+ break;
+
+ case MUSIC_DPMI_Error :
+ ErrorString = "DPMI Error in MUSIC.";
+ break;
+
+ default :
+ ErrorString = "Unknown Music error code.";
+ break;
+ }
+
+ return( ErrorString );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_Init
+
+ Selects which sound device to use.
+---------------------------------------------------------------------*/
+
+int MUSIC_Init
+ (
+ int SoundCard,
+ int Address
+ )
+
+ {
+ int i;
+ int status;
+
+ if ( USER_CheckParameter( "ASSVER" ) )
+ {
+ MUSIC_SetErrorCode( MUSIC_ASSVersion );
+ return( MUSIC_Error );
+ }
+
+ status = LL_LockMemory();
+ if ( status != LL_Ok )
+ {
+ MUSIC_SetErrorCode( MUSIC_DPMI_Error );
+ return( MUSIC_Error );
+ }
+
+ for( i = 0; i < 128; i++ )
+ {
+ MIDI_PatchMap[ i ] = i;
+ }
+
+ status = MUSIC_Ok;
+ MUSIC_SoundDevice = SoundCard;
+
+ switch( SoundCard )
+ {
+ case SoundBlaster :
+ case Adlib :
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ status = MUSIC_InitFM( SoundCard, &MUSIC_MidiFunctions );
+ break;
+
+ case GenMidi :
+ case SoundCanvas :
+ case WaveBlaster :
+ case SoundScape :
+ status = MUSIC_InitMidi( SoundCard, &MUSIC_MidiFunctions, Address );
+ break;
+
+ case Awe32 :
+ status = MUSIC_InitAWE32( &MUSIC_MidiFunctions );
+ break;
+
+ case UltraSound :
+ status = MUSIC_InitGUS( &MUSIC_MidiFunctions );
+ break;
+
+ case SoundSource :
+ case PC :
+ default :
+ MUSIC_SetErrorCode( MUSIC_InvalidCard );
+ status = MUSIC_Error;
+ }
+
+ if ( status != MUSIC_Ok )
+ {
+ LL_UnlockMemory();
+ }
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_Shutdown
+
+ Terminates use of sound device.
+---------------------------------------------------------------------*/
+
+int MUSIC_Shutdown
+ (
+ void
+ )
+
+ {
+ int status;
+
+ status = MUSIC_Ok;
+
+ MIDI_StopSong();
+
+ if ( MUSIC_FadeTask != NULL )
+ {
+ MUSIC_StopFade();
+ }
+
+ switch ( MUSIC_SoundDevice )
+ {
+ case Adlib :
+ AL_Shutdown();
+ break;
+
+ case SoundBlaster :
+ AL_Shutdown();
+ BLASTER_RestoreMidiVolume();
+ break;
+
+ case GenMidi :
+ case SoundCanvas :
+ case SoundScape :
+ MPU_Reset();
+ break;
+
+ case WaveBlaster :
+ BLASTER_ShutdownWaveBlaster();
+ MPU_Reset();
+ BLASTER_RestoreMidiVolume();
+ break;
+
+ case Awe32 :
+ AWE32_Shutdown();
+ BLASTER_RestoreMidiVolume();
+ break;
+
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ AL_Shutdown();
+ PAS_RestoreMusicVolume();
+ break;
+
+ case UltraSound :
+ GUSMIDI_Shutdown();
+ break;
+ }
+
+ LL_UnlockMemory();
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_SetMaxFMMidiChannel
+
+ Sets the maximum MIDI channel that FM cards respond to.
+---------------------------------------------------------------------*/
+
+void MUSIC_SetMaxFMMidiChannel
+ (
+ int channel
+ )
+
+ {
+ AL_SetMaxMidiChannel( channel );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_SetVolume
+
+ Sets the volume of music playback.
+---------------------------------------------------------------------*/
+
+void MUSIC_SetVolume
+ (
+ int volume
+ )
+
+ {
+ volume = max( 0, volume );
+ volume = min( volume, 255 );
+
+ if ( MUSIC_SoundDevice != -1 )
+ {
+ MIDI_SetVolume( volume );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_SetMidiChannelVolume
+
+ Sets the volume of music playback on the specified MIDI channel.
+---------------------------------------------------------------------*/
+
+void MUSIC_SetMidiChannelVolume
+ (
+ int channel,
+ int volume
+ )
+
+ {
+ MIDI_SetUserChannelVolume( channel, volume );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_ResetMidiChannelVolumes
+
+ Sets the volume of music playback on all MIDI channels to full volume.
+---------------------------------------------------------------------*/
+
+void MUSIC_ResetMidiChannelVolumes
+ (
+ void
+ )
+
+ {
+ MIDI_ResetUserChannelVolume();
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_GetVolume
+
+ Returns the volume of music playback.
+---------------------------------------------------------------------*/
+
+int MUSIC_GetVolume
+ (
+ void
+ )
+
+ {
+ if ( MUSIC_SoundDevice == -1 )
+ {
+ return( 0 );
+ }
+ return( MIDI_GetVolume() );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_SetLoopFlag
+
+ Set whether the music will loop or end when it reaches the end of
+ the song.
+---------------------------------------------------------------------*/
+
+void MUSIC_SetLoopFlag
+ (
+ int loopflag
+ )
+
+ {
+ MIDI_SetLoopFlag( loopflag );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_SongPlaying
+
+ Returns whether there is a song playing.
+---------------------------------------------------------------------*/
+
+int MUSIC_SongPlaying
+ (
+ void
+ )
+
+ {
+ return( MIDI_SongPlaying() );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_Continue
+
+ Continues playback of a paused song.
+---------------------------------------------------------------------*/
+
+void MUSIC_Continue
+ (
+ void
+ )
+
+ {
+ MIDI_ContinueSong();
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_Pause
+
+ Pauses playback of a song.
+---------------------------------------------------------------------*/
+
+void MUSIC_Pause
+ (
+ void
+ )
+
+ {
+ MIDI_PauseSong();
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_StopSong
+
+ Stops playback of current song.
+---------------------------------------------------------------------*/
+
+int MUSIC_StopSong
+ (
+ void
+ )
+
+ {
+ MUSIC_StopFade();
+ MIDI_StopSong();
+ MUSIC_SetErrorCode( MUSIC_Ok );
+ return( MUSIC_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_PlaySong
+
+ Begins playback of MIDI song.
+---------------------------------------------------------------------*/
+
+int MUSIC_PlaySong
+ (
+ unsigned char *song,
+ int loopflag
+ )
+
+ {
+ int status;
+
+ switch( MUSIC_SoundDevice )
+ {
+ case SoundBlaster :
+ case Adlib :
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ case GenMidi :
+ case SoundCanvas :
+ case WaveBlaster :
+ case SoundScape :
+ case Awe32 :
+ case UltraSound :
+ MIDI_StopSong();
+ status = MIDI_PlaySong( song, loopflag );
+ if ( status != MIDI_Ok )
+ {
+ MUSIC_SetErrorCode( MUSIC_MidiError );
+ return( MUSIC_Warning );
+ }
+ break;
+
+ case SoundSource :
+ case PC :
+ default :
+ MUSIC_SetErrorCode( MUSIC_InvalidCard );
+ return( MUSIC_Warning );
+ break;
+ }
+
+ return( MUSIC_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_SetContext
+
+ Sets the song context.
+---------------------------------------------------------------------*/
+
+void MUSIC_SetContext
+ (
+ int context
+ )
+
+ {
+ MIDI_SetContext( context );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_GetContext
+
+ Returns the current song context.
+---------------------------------------------------------------------*/
+
+int MUSIC_GetContext
+ (
+ void
+ )
+
+ {
+ return MIDI_GetContext();
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_SetSongTick
+
+ Sets the position of the song pointer.
+---------------------------------------------------------------------*/
+
+void MUSIC_SetSongTick
+ (
+ unsigned long PositionInTicks
+ )
+
+ {
+ MIDI_SetSongTick( PositionInTicks );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_SetSongTime
+
+ Sets the position of the song pointer.
+---------------------------------------------------------------------*/
+
+void MUSIC_SetSongTime
+ (
+ unsigned long milliseconds
+ )
+
+ {
+ MIDI_SetSongTime( milliseconds );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_SetSongPosition
+
+ Sets the position of the song pointer.
+---------------------------------------------------------------------*/
+
+void MUSIC_SetSongPosition
+ (
+ int measure,
+ int beat,
+ int tick
+ )
+
+ {
+ MIDI_SetSongPosition( measure, beat, tick );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_GetSongPosition
+
+ Returns the position of the song pointer.
+---------------------------------------------------------------------*/
+
+void MUSIC_GetSongPosition
+ (
+ songposition *pos
+ )
+
+ {
+ MIDI_GetSongPosition( pos );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_GetSongLength
+
+ Returns the length of the song.
+---------------------------------------------------------------------*/
+
+void MUSIC_GetSongLength
+ (
+ songposition *pos
+ )
+
+ {
+ MIDI_GetSongLength( pos );
+ }
+
+
+int MUSIC_InitAWE32
+ (
+ midifuncs *Funcs
+ )
+
+ {
+ int status;
+
+ status = AWE32_Init();
+ if ( status != AWE32_Ok )
+ {
+ MUSIC_SetErrorCode( MUSIC_SoundCardError );
+ return( MUSIC_Error );
+ }
+
+ Funcs->NoteOff = AWE32_NoteOff;
+ Funcs->NoteOn = AWE32_NoteOn;
+ Funcs->PolyAftertouch = AWE32_PolyAftertouch;
+ Funcs->ControlChange = AWE32_ControlChange;
+ Funcs->ProgramChange = AWE32_ProgramChange;
+ Funcs->ChannelAftertouch = AWE32_ChannelAftertouch;
+ Funcs->PitchBend = AWE32_PitchBend;
+ Funcs->ReleasePatches = NULL;
+ Funcs->LoadPatch = NULL;
+ Funcs->SetVolume = NULL;
+ Funcs->GetVolume = NULL;
+
+ if ( BLASTER_CardHasMixer() )
+ {
+ BLASTER_SaveMidiVolume();
+ Funcs->SetVolume = BLASTER_SetMidiVolume;
+ Funcs->GetVolume = BLASTER_GetMidiVolume;
+ }
+
+ status = MUSIC_Ok;
+ MIDI_SetMidiFuncs( Funcs );
+
+ return( status );
+ }
+
+
+int MUSIC_InitFM
+ (
+ int card,
+ midifuncs *Funcs
+ )
+
+ {
+ int status;
+ int passtatus;
+
+ status = MIDI_Ok;
+
+ if ( !AL_DetectFM() )
+ {
+ MUSIC_SetErrorCode( MUSIC_FMNotDetected );
+ return( MUSIC_Error );
+ }
+
+ // Init the fm routines
+ AL_Init( card );
+
+ Funcs->NoteOff = AL_NoteOff;
+ Funcs->NoteOn = AL_NoteOn;
+ Funcs->PolyAftertouch = NULL;
+ Funcs->ControlChange = AL_ControlChange;
+ Funcs->ProgramChange = AL_ProgramChange;
+ Funcs->ChannelAftertouch = NULL;
+ Funcs->PitchBend = AL_SetPitchBend;
+ Funcs->ReleasePatches = NULL;
+ Funcs->LoadPatch = NULL;
+ Funcs->SetVolume = NULL;
+ Funcs->GetVolume = NULL;
+
+ switch( card )
+ {
+ case SoundBlaster :
+ if ( BLASTER_CardHasMixer() )
+ {
+ BLASTER_SaveMidiVolume();
+ Funcs->SetVolume = BLASTER_SetMidiVolume;
+ Funcs->GetVolume = BLASTER_GetMidiVolume;
+ }
+ else
+ {
+ Funcs->SetVolume = NULL;
+ Funcs->GetVolume = NULL;
+ }
+ break;
+
+ case Adlib :
+ Funcs->SetVolume = NULL;
+ Funcs->GetVolume = NULL;
+ break;
+
+ case ProAudioSpectrum :
+ case SoundMan16 :
+ Funcs->SetVolume = NULL;
+ Funcs->GetVolume = NULL;
+
+ passtatus = PAS_SaveMusicVolume();
+ if ( passtatus == PAS_Ok )
+ {
+ Funcs->SetVolume = PAS_SetFMVolume;
+ Funcs->GetVolume = PAS_GetFMVolume;
+ }
+ break;
+ }
+
+ MIDI_SetMidiFuncs( Funcs );
+
+ return( status );
+ }
+
+int MUSIC_InitMidi
+ (
+ int card,
+ midifuncs *Funcs,
+ int Address
+ )
+
+ {
+ int status;
+
+ status = MUSIC_Ok;
+
+ if ( ( card == WaveBlaster ) || ( card == SoundCanvas ) ||
+ ( card == GenMidi ) )
+ {
+ // Setup WaveBlaster Daughterboard clone
+ // (ie. SoundCanvas DB, TurtleBeach Rio)
+ BLASTER_SetupWaveBlaster();
+ }
+
+ if ( card == SoundScape )
+ {
+ Address = SOUNDSCAPE_GetMIDIPort();
+ if ( Address < SOUNDSCAPE_Ok )
+ {
+ MUSIC_SetErrorCode( MUSIC_SoundCardError );
+ return( MUSIC_Error );
+ }
+ }
+
+ if ( MPU_Init( Address ) != MPU_Ok )
+ {
+ MUSIC_SetErrorCode( MUSIC_MPU401Error );
+ return( MUSIC_Error );
+ }
+
+ Funcs->NoteOff = MPU_NoteOff;
+ Funcs->NoteOn = MPU_NoteOn;
+ Funcs->PolyAftertouch = MPU_PolyAftertouch;
+ Funcs->ControlChange = MPU_ControlChange;
+ Funcs->ProgramChange = MPU_ProgramChange;
+ Funcs->ChannelAftertouch = MPU_ChannelAftertouch;
+ Funcs->PitchBend = MPU_PitchBend;
+ Funcs->ReleasePatches = NULL;
+ Funcs->LoadPatch = NULL;
+ Funcs->SetVolume = NULL;
+ Funcs->GetVolume = NULL;
+
+ if ( card == WaveBlaster )
+ {
+ if ( BLASTER_CardHasMixer() )
+ {
+ BLASTER_SaveMidiVolume();
+ Funcs->SetVolume = BLASTER_SetMidiVolume;
+ Funcs->GetVolume = BLASTER_GetMidiVolume;
+ }
+ }
+
+ MIDI_SetMidiFuncs( Funcs );
+
+ return( status );
+ }
+
+int MUSIC_InitGUS
+ (
+ midifuncs *Funcs
+ )
+
+ {
+ int status;
+
+ status = MUSIC_Ok;
+
+ if ( GUSMIDI_Init() != GUS_Ok )
+ {
+ MUSIC_SetErrorCode( MUSIC_SoundCardError );
+ return( MUSIC_Error );
+ }
+
+ Funcs->NoteOff = GUSMIDI_NoteOff;
+ Funcs->NoteOn = GUSMIDI_NoteOn;
+ Funcs->PolyAftertouch = NULL;
+ Funcs->ControlChange = GUSMIDI_ControlChange;
+ Funcs->ProgramChange = GUSMIDI_ProgramChange;
+ Funcs->ChannelAftertouch = NULL;
+ Funcs->PitchBend = GUSMIDI_PitchBend;
+ Funcs->ReleasePatches = NULL;//GUSMIDI_ReleasePatches;
+ Funcs->LoadPatch = NULL;//GUSMIDI_LoadPatch;
+ Funcs->SetVolume = GUSMIDI_SetVolume;
+ Funcs->GetVolume = GUSMIDI_GetVolume;
+
+ MIDI_SetMidiFuncs( Funcs );
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_FadeRoutine
+
+ Fades music volume from current level to another over a specified
+ period of time.
+---------------------------------------------------------------------*/
+
+static void MUSIC_FadeRoutine
+ (
+ task *Task
+ )
+
+ {
+ int volume;
+
+ MUSIC_CurrentFadeVolume += MUSIC_FadeRate;
+ if ( MUSIC_FadeLength == 0 )
+ {
+ MIDI_SetVolume( MUSIC_EndingFadeVolume );
+ TS_Terminate( Task );
+ MUSIC_FadeTask = NULL;
+ }
+ else
+ {
+ MUSIC_FadeLength--;
+// if ( ( MUSIC_SoundDevice == GenMidi ) &&
+// ( ( MUSIC_FadeLength % 12 ) != 0 ) )
+// {
+// return;
+// }
+
+ volume = MUSIC_CurrentFadeVolume >> 7;
+ if ( MUSIC_LastFadeVolume != volume )
+ {
+ MUSIC_LastFadeVolume = volume;
+ MIDI_SetVolume( volume );
+ }
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_FadeVolume
+
+ Fades music volume from current level to another over a specified
+ period of time.
+---------------------------------------------------------------------*/
+
+int MUSIC_FadeVolume
+ (
+ int tovolume,
+ int milliseconds
+ )
+
+ {
+ int fromvolume;
+
+ if ( ( MUSIC_SoundDevice == ProAudioSpectrum ) ||
+ ( MUSIC_SoundDevice == SoundMan16 ) ||
+ ( MUSIC_SoundDevice == GenMidi ) ||
+ ( MUSIC_SoundDevice == SoundScape ) ||
+ ( MUSIC_SoundDevice == SoundCanvas ) )
+ {
+ MIDI_SetVolume( tovolume );
+ return( MUSIC_Ok );
+ }
+
+ if ( MUSIC_FadeTask != NULL )
+ {
+ MUSIC_StopFade();
+ }
+
+ tovolume = max( 0, tovolume );
+ tovolume = min( 255, tovolume );
+ fromvolume = MUSIC_GetVolume();
+
+ MUSIC_FadeLength = milliseconds / 25;
+ MUSIC_FadeRate = ( ( tovolume - fromvolume ) << 7 ) / MUSIC_FadeLength;
+ MUSIC_LastFadeVolume = fromvolume;
+ MUSIC_CurrentFadeVolume = fromvolume << 7;
+ MUSIC_EndingFadeVolume = tovolume;
+
+ MUSIC_FadeTask = TS_ScheduleTask( MUSIC_FadeRoutine, 40, 1, NULL );
+ if ( MUSIC_FadeTask == NULL )
+ {
+ MUSIC_SetErrorCode( MUSIC_TaskManError );
+ return( MUSIC_Warning );
+ }
+
+ TS_Dispatch();
+ return( MUSIC_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_FadeActive
+
+ Returns whether the fade routine is active.
+---------------------------------------------------------------------*/
+
+int MUSIC_FadeActive
+ (
+ void
+ )
+
+ {
+ return( MUSIC_FadeTask != NULL );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_StopFade
+
+ Stops fading the music.
+---------------------------------------------------------------------*/
+
+void MUSIC_StopFade
+ (
+ void
+ )
+
+ {
+ if ( MUSIC_FadeTask != NULL )
+ {
+ TS_Terminate( MUSIC_FadeTask );
+ MUSIC_FadeTask = NULL;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_RerouteMidiChannel
+
+ Sets callback function to reroute MIDI commands from specified
+ function.
+---------------------------------------------------------------------*/
+
+void MUSIC_RerouteMidiChannel
+ (
+ int channel,
+ int cdecl ( *function )( int event, int c1, int c2 )
+ )
+
+ {
+ MIDI_RerouteMidiChannel( channel, function );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: MUSIC_RegisterTimbreBank
+
+ Halts playback of all sounds.
+---------------------------------------------------------------------*/
+
+void MUSIC_RegisterTimbreBank
+ (
+ unsigned char *timbres
+ )
+
+ {
+ AL_RegisterTimbreBank( timbres );
+ }
--- /dev/null
+++ b/rott/audiolib/music.h
@@ -1,0 +1,96 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: MUSIC.H
+
+ author: James R. Dose
+ date: March 25, 1994
+
+ Public header for MUSIC.C
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __MUSIC_H
+#define __MUSIC_H
+
+#include "sndcards.h"
+
+#ifndef PLAT_DOS
+#define cdecl
+#endif
+
+extern int MUSIC_ErrorCode;
+
+enum MUSIC_ERRORS
+ {
+ MUSIC_Warning = -2,
+ MUSIC_Error = -1,
+ MUSIC_Ok = 0,
+ MUSIC_ASSVersion,
+ MUSIC_SoundCardError,
+ MUSIC_MPU401Error,
+ MUSIC_InvalidCard,
+ MUSIC_MidiError,
+ MUSIC_TaskManError,
+ MUSIC_FMNotDetected,
+ MUSIC_DPMI_Error
+ };
+
+typedef struct
+ {
+ unsigned long tickposition;
+ unsigned long milliseconds;
+ unsigned int measure;
+ unsigned int beat;
+ unsigned int tick;
+ } songposition;
+
+#define MUSIC_LoopSong ( 1 == 1 )
+#define MUSIC_PlayOnce ( !MUSIC_LoopSong )
+
+char *MUSIC_ErrorString( int ErrorNumber );
+int MUSIC_Init( int SoundCard, int Address );
+int MUSIC_Shutdown( void );
+void MUSIC_SetMaxFMMidiChannel( int channel );
+void MUSIC_SetVolume( int volume );
+void MUSIC_SetMidiChannelVolume( int channel, int volume );
+void MUSIC_ResetMidiChannelVolumes( void );
+int MUSIC_GetVolume( void );
+void MUSIC_SetLoopFlag( int loopflag );
+int MUSIC_SongPlaying( void );
+void MUSIC_Continue( void );
+void MUSIC_Pause( void );
+int MUSIC_StopSong( void );
+int MUSIC_PlaySong( unsigned char *song, int loopflag );
+void MUSIC_SetContext( int context );
+int MUSIC_GetContext( void );
+void MUSIC_SetSongTick( unsigned long PositionInTicks );
+void MUSIC_SetSongTime( unsigned long milliseconds );
+void MUSIC_SetSongPosition( int measure, int beat, int tick );
+void MUSIC_GetSongPosition( songposition *pos );
+void MUSIC_GetSongLength( songposition *pos );
+int MUSIC_FadeVolume( int tovolume, int milliseconds );
+int MUSIC_FadeActive( void );
+void MUSIC_StopFade( void );
+void MUSIC_RerouteMidiChannel( int channel, int cdecl ( *function )( int event, int c1, int c2 ) );
+void MUSIC_RegisterTimbreBank( unsigned char *timbres );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/mv_mix.asm
@@ -1,0 +1,505 @@
+ IDEAL
+
+ p386
+ MODEL flat
+
+ dataseg
+ CODESEG
+
+ MASM
+ ALIGN 4
+
+EXTRN _MV_HarshClipTable:DWORD
+EXTRN _MV_MixDestination:DWORD
+EXTRN _MV_MixPosition:DWORD
+EXTRN _MV_LeftVolume:DWORD
+EXTRN _MV_RightVolume:DWORD
+EXTRN _MV_SampleSize:DWORD
+EXTRN _MV_RightChannelOffset:DWORD
+
+;================
+;
+; MV_Mix8BitMono
+;
+;================
+
+; eax - position
+; edx - rate
+; ebx - start
+; ecx - number of samples to mix
+
+PROC MV_Mix8BitMono_
+PUBLIC MV_Mix8BitMono_
+; Two at once
+ pushad
+
+ mov ebp, eax
+
+ mov esi, ebx ; Source pointer
+
+ ; Sample size
+ mov ebx, _MV_SampleSize
+ mov eax,OFFSET apatch7+2 ; convice tasm to modify code...
+ mov [eax],bl
+ mov eax,OFFSET apatch8+2 ; convice tasm to modify code...
+ mov [eax],bl
+ mov eax,OFFSET apatch9+3 ; convice tasm to modify code...
+ mov [eax],bl
+
+ ; Volume table ptr
+ mov ebx, _MV_LeftVolume ; Since we're mono, use left volume
+ mov eax,OFFSET apatch1+4 ; convice tasm to modify code...
+ mov [eax],ebx
+ mov eax,OFFSET apatch2+4 ; convice tasm to modify code...
+ mov [eax],ebx
+
+ ; Harsh Clip table ptr
+ mov ebx, _MV_HarshClipTable
+ add ebx, 128
+ mov eax,OFFSET apatch3+2 ; convice tasm to modify code...
+ mov [eax],ebx
+ mov eax,OFFSET apatch4+2 ; convice tasm to modify code...
+ mov [eax],ebx
+
+ ; Rate scale ptr
+ mov eax,OFFSET apatch5+2 ; convice tasm to modify code...
+ mov [eax],edx
+ mov eax,OFFSET apatch6+2 ; convice tasm to modify code...
+ mov [eax],edx
+
+ mov edi, _MV_MixDestination ; Get the position to write to
+
+ ; Number of samples to mix
+ shr ecx, 1 ; double sample count
+ cmp ecx, 0
+ je short exit8m
+
+; eax - scratch
+; ebx - scratch
+; edx - scratch
+; ecx - count
+; edi - destination
+; esi - source
+; ebp - frac pointer
+; apatch1 - volume table
+; apatch2 - volume table
+; apatch3 - harsh clip table
+; apatch4 - harsh clip table
+; apatch5 - sample rate
+; apatch6 - sample rate
+
+ mov eax,ebp ; begin calculating first sample
+ add ebp,edx ; advance frac pointer
+ shr eax,16 ; finish calculation for first sample
+
+ mov ebx,ebp ; begin calculating second sample
+ add ebp,edx ; advance frac pointer
+ shr ebx,16 ; finish calculation for second sample
+
+ movzx eax, byte ptr [esi+eax] ; get first sample
+ movzx ebx, byte ptr [esi+ebx] ; get second sample
+
+ ALIGN 4
+mix8Mloop:
+ movzx edx, byte ptr [edi] ; get current sample from destination
+apatch1:
+ movsx eax, byte ptr [2*eax+12345678h] ; volume translate first sample
+apatch2:
+ movsx ebx, byte ptr [2*ebx+12345678h] ; volume translate second sample
+ add eax, edx ; mix first sample
+apatch9:
+ movzx edx, byte ptr [edi + 1] ; get current sample from destination
+apatch3:
+ mov eax, [eax + 12345678h] ; harsh clip new sample
+ add ebx, edx ; mix second sample
+ mov [edi], al ; write new sample to destination
+ mov edx, ebp ; begin calculating third sample
+apatch4:
+ mov ebx, [ebx + 12345678h] ; harsh clip new sample
+apatch5:
+ add ebp,12345678h ; advance frac pointer
+ shr edx, 16 ; finish calculation for third sample
+ mov eax, ebp ; begin calculating fourth sample
+apatch7:
+ add edi, 1 ; move destination to second sample
+ shr eax, 16 ; finish calculation for fourth sample
+ mov [edi], bl ; write new sample to destination
+apatch6:
+ add ebp,12345678h ; advance frac pointer
+ movzx ebx, byte ptr [esi+eax] ; get fourth sample
+ movzx eax, byte ptr [esi+edx] ; get third sample
+apatch8:
+ add edi, 2 ; move destination to third sample
+ dec ecx ; decrement count
+ jnz mix8Mloop ; loop
+
+ mov _MV_MixDestination, edi ; Store the current write position
+ mov _MV_MixPosition, ebp ; return position
+exit8m:
+ popad
+ ret
+ENDP MV_Mix8BitMono_
+
+;================
+;
+; MV_Mix8BitStereo
+;
+;================
+
+; eax - position
+; edx - rate
+; ebx - start
+; ecx - number of samples to mix
+
+PROC MV_Mix8BitStereo_
+PUBLIC MV_Mix8BitStereo_
+
+ pushad
+ mov ebp, eax
+
+ mov esi, ebx ; Source pointer
+
+ ; Sample size
+ mov ebx, _MV_SampleSize
+ mov eax,OFFSET bpatch8+2 ; convice tasm to modify code...
+ mov [eax],bl
+
+ ; Right channel offset
+ mov ebx, _MV_RightChannelOffset
+ mov eax,OFFSET bpatch6+3 ; convice tasm to modify code...
+ mov [eax],ebx
+ mov eax,OFFSET bpatch7+2 ; convice tasm to modify code...
+ mov [eax],ebx
+
+ ; Volume table ptr
+ mov ebx, _MV_LeftVolume
+ mov eax,OFFSET bpatch1+4 ; convice tasm to modify code...
+ mov [eax],ebx
+
+ mov ebx, _MV_RightVolume
+ mov eax,OFFSET bpatch2+4 ; convice tasm to modify code...
+ mov [eax],ebx
+
+ ; Rate scale ptr
+ mov eax,OFFSET bpatch3+2 ; convice tasm to modify code...
+ mov [eax],edx
+
+ ; Harsh Clip table ptr
+ mov ebx, _MV_HarshClipTable
+ add ebx,128
+ mov eax,OFFSET bpatch4+2 ; convice tasm to modify code...
+ mov [eax],ebx
+ mov eax,OFFSET bpatch5+2 ; convice tasm to modify code...
+ mov [eax],ebx
+
+ mov edi, _MV_MixDestination ; Get the position to write to
+
+ ; Number of samples to mix
+ cmp ecx, 0
+ je short exit8S
+
+; eax - scratch
+; ebx - scratch
+; edx - scratch
+; ecx - count
+; edi - destination
+; esi - source
+; ebp - frac pointer
+; bpatch1 - left volume table
+; bpatch2 - right volume table
+; bpatch3 - sample rate
+; bpatch4 - harsh clip table
+; bpatch5 - harsh clip table
+
+ mov eax,ebp ; begin calculating first sample
+ shr eax,16 ; finish calculation for first sample
+
+ movzx ebx, byte ptr [esi+eax] ; get first sample
+
+ ALIGN 4
+mix8Sloop:
+bpatch1:
+ movsx eax, byte ptr [2*ebx+12345678h] ; volume translate left sample
+ movzx edx, byte ptr [edi] ; get current sample from destination
+bpatch2:
+ movsx ebx, byte ptr [2*ebx+12345678h] ; volume translate right sample
+ add eax, edx ; mix left sample
+bpatch3:
+ add ebp,12345678h ; advance frac pointer
+bpatch6:
+ movzx edx, byte ptr [edi+12345678h] ; get current sample from destination
+bpatch4:
+ mov eax, [eax + 12345678h] ; harsh clip left sample
+ add ebx, edx ; mix right sample
+ mov [edi], al ; write left sample to destination
+bpatch5:
+ mov ebx, [ebx + 12345678h] ; harsh clip right sample
+ mov edx, ebp ; begin calculating second sample
+bpatch7:
+ mov [edi+12345678h], bl ; write right sample to destination
+ shr edx, 16 ; finish calculation for second sample
+bpatch8:
+ add edi, 2 ; move destination to second sample
+ movzx ebx, byte ptr [esi+edx] ; get second sample
+ dec ecx ; decrement count
+ jnz mix8Sloop ; loop
+
+ mov _MV_MixDestination, edi ; Store the current write position
+ mov _MV_MixPosition, ebp ; return position
+
+EXIT8S:
+ popad
+ ret
+ENDP MV_Mix8BitStereo_
+
+;================
+;
+; MV_Mix16BitMono
+;
+;================
+
+; eax - position
+; edx - rate
+; ebx - start
+; ecx - number of samples to mix
+
+PROC MV_Mix16BitMono_
+PUBLIC MV_Mix16BitMono_
+; Two at once
+ pushad
+
+ mov ebp, eax
+
+ mov esi, ebx ; Source pointer
+
+ ; Sample size
+ mov ebx, _MV_SampleSize
+ mov eax,OFFSET cpatch5+3 ; convice tasm to modify code...
+ mov [eax],bl
+ mov eax,OFFSET cpatch6+3 ; convice tasm to modify code...
+ mov [eax],bl
+ mov eax,OFFSET cpatch7+2 ; convice tasm to modify code...
+ add bl,bl
+ mov [eax],bl
+
+ ; Volume table ptr
+ mov ebx, _MV_LeftVolume
+ mov eax,OFFSET cpatch1+4 ; convice tasm to modify code...
+ mov [eax],ebx
+ mov eax,OFFSET cpatch2+4 ; convice tasm to modify code...
+ mov [eax],ebx
+
+ ; Rate scale ptr
+ mov eax,OFFSET cpatch3+2 ; convice tasm to modify code...
+ mov [eax],edx
+ mov eax,OFFSET cpatch4+2 ; convice tasm to modify code...
+ mov [eax],edx
+
+ mov edi, _MV_MixDestination ; Get the position to write to
+
+ ; Number of samples to mix
+ shr ecx, 1 ; double sample count
+ cmp ecx, 0
+ je exit16M
+
+; eax - scratch
+; ebx - scratch
+; edx - scratch
+; ecx - count
+; edi - destination
+; esi - source
+; ebp - frac pointer
+; cpatch1 - volume table
+; cpatch2 - volume table
+; cpatch3 - sample rate
+; cpatch4 - sample rate
+
+ mov eax,ebp ; begin calculating first sample
+ add ebp,edx ; advance frac pointer
+ shr eax,16 ; finish calculation for first sample
+
+ mov ebx,ebp ; begin calculating second sample
+ add ebp,edx ; advance frac pointer
+ shr ebx,16 ; finish calculation for second sample
+
+ movzx eax, byte ptr [esi+eax] ; get first sample
+ movzx ebx, byte ptr [esi+ebx] ; get second sample
+
+ ALIGN 4
+mix16Mloop:
+ movsx edx, word ptr [edi] ; get current sample from destination
+cpatch1:
+ movsx eax, word ptr [2*eax+12345678h] ; volume translate first sample
+cpatch2:
+ movsx ebx, word ptr [2*ebx+12345678h] ; volume translate second sample
+ add eax, edx ; mix first sample
+cpatch5:
+ movsx edx, word ptr [edi + 2] ; get current sample from destination
+
+ cmp eax, -32768 ; Harsh clip sample
+ jge short m16skip1
+ mov eax, -32768
+ jmp short m16skip2
+m16skip1:
+ cmp eax, 32767
+ jle short m16skip2
+ mov eax, 32767
+m16skip2:
+ add ebx, edx ; mix second sample
+ mov [edi], ax ; write new sample to destination
+ mov edx, ebp ; begin calculating third sample
+
+ cmp ebx, -32768 ; Harsh clip sample
+ jge short m16skip3
+ mov ebx, -32768
+ jmp short m16skip4
+m16skip3:
+ cmp ebx, 32767
+ jle short m16skip4
+ mov ebx, 32767
+m16skip4:
+cpatch3:
+ add ebp,12345678h ; advance frac pointer
+ shr edx, 16 ; finish calculation for third sample
+ mov eax, ebp ; begin calculating fourth sample
+cpatch6:
+ mov [edi + 2], bx ; write new sample to destination
+ shr eax, 16 ; finish calculation for fourth sample
+
+cpatch4:
+ add ebp,12345678h ; advance frac pointer
+ movzx ebx, byte ptr [esi+eax] ; get fourth sample
+cpatch7:
+ add edi, 4 ; move destination to third sample
+ movzx eax, byte ptr [esi+edx] ; get third sample
+ dec ecx ; decrement count
+ jnz mix16Mloop ; loop
+
+ mov _MV_MixDestination, edi ; Store the current write position
+ mov _MV_MixPosition, ebp ; return position
+EXIT16M:
+ popad
+ ret
+ENDP MV_Mix16BitMono_
+
+;================
+;
+; MV_Mix16BitStereo
+;
+;================
+
+; eax - position
+; edx - rate
+; ebx - start
+; ecx - number of samples to mix
+
+PROC MV_Mix16BitStereo_
+PUBLIC MV_Mix16BitStereo_
+
+ pushad
+ mov ebp, eax
+
+ mov esi, ebx ; Source pointer
+
+ ; Sample size
+ mov ebx, _MV_SampleSize
+ mov eax,OFFSET dpatch6+2 ; convice tasm to modify code...
+ mov [eax],bl
+
+ ; Right channel offset
+ mov ebx, _MV_RightChannelOffset
+ mov eax,OFFSET dpatch4+3 ; convice tasm to modify code...
+ mov [eax],ebx
+ mov eax,OFFSET dpatch5+3 ; convice tasm to modify code...
+ mov [eax],ebx
+
+ ; Volume table ptr
+ mov ebx, _MV_LeftVolume
+ mov eax,OFFSET dpatch1+4 ; convice tasm to modify code...
+ mov [eax],ebx
+
+ mov ebx, _MV_RightVolume
+ mov eax,OFFSET dpatch2+4 ; convice tasm to modify code...
+ mov [eax],ebx
+
+ ; Rate scale ptr
+ mov eax,OFFSET dpatch3+2 ; convice tasm to modify code...
+ mov [eax],edx
+
+ mov edi, _MV_MixDestination ; Get the position to write to
+
+ ; Number of samples to mix
+ cmp ecx, 0
+ je exit16S
+
+; eax - scratch
+; ebx - scratch
+; edx - scratch
+; ecx - count
+; edi - destination
+; esi - source
+; ebp - frac pointer
+; dpatch1 - left volume table
+; dpatch2 - right volume table
+; dpatch3 - sample rate
+
+ mov eax,ebp ; begin calculating first sample
+ shr eax,16 ; finish calculation for first sample
+
+ movzx ebx, byte ptr [esi+eax] ; get first sample
+
+ ALIGN 4
+mix16Sloop:
+dpatch1:
+ movsx eax, word ptr [2*ebx+12345678h] ; volume translate left sample
+ movsx edx, word ptr [edi] ; get current sample from destination
+dpatch2:
+ movsx ebx, word ptr [2*ebx+12345678h] ; volume translate right sample
+ add eax, edx ; mix left sample
+dpatch3:
+ add ebp,12345678h ; advance frac pointer
+dpatch4:
+ movsx edx, word ptr [edi+12345678h] ; get current sample from destination
+
+ cmp eax, -32768 ; Harsh clip sample
+ jge short s16skip1
+ mov eax, -32768
+ jmp short s16skip2
+s16skip1:
+ cmp eax, 32767
+ jle short s16skip2
+ mov eax, 32767
+s16skip2:
+ add ebx, edx ; mix right sample
+ mov [edi], ax ; write left sample to destination
+
+ cmp ebx, -32768 ; Harsh clip sample
+ jge short s16skip3
+ mov ebx, -32768
+ jmp short s16skip4
+s16skip3:
+ cmp ebx, 32767
+ jle short s16skip4
+ mov ebx, 32767
+s16skip4:
+
+ mov edx, ebp ; begin calculating second sample
+dpatch5:
+ mov [edi+12345678h], bx ; write right sample to destination
+ shr edx, 16 ; finish calculation for second sample
+dpatch6:
+ add edi, 4 ; move destination to second sample
+ movzx ebx, byte ptr [esi+edx] ; get second sample
+ dec ecx ; decrement count
+ jnz mix16Sloop ; loop
+
+ mov _MV_MixDestination, edi ; Store the current write position
+ mov _MV_MixPosition, ebp ; return position
+exit16S:
+ popad
+ ret
+ENDP MV_Mix16BitStereo_
+
+ ENDS
+
+ END
--- /dev/null
+++ b/rott/audiolib/mv_mix.c
@@ -1,0 +1,293 @@
+#include "multivoc.h"
+
+extern char *MV_MixDestination;
+extern unsigned long MV_MixPosition;
+
+extern char *MV_LeftVolume;
+extern char *MV_RightVolume;
+
+extern unsigned char *MV_HarshClipTable;
+
+extern int MV_RightChannelOffset;
+extern int MV_SampleSize;
+
+void MV_Mix8BitMono( unsigned long position, unsigned long rate,
+ const char *start, unsigned long length )
+{
+ const unsigned char *src;
+ unsigned char *dest;
+ unsigned int i;
+
+ src = (const unsigned char *)start;
+ dest = (unsigned char *)MV_MixDestination;
+
+ for (i = 0; i < length; i++) {
+ int s = src[position >> 16];
+ int d = *dest;
+
+ s = MV_LeftVolume[s * 2];
+
+ s += d;
+
+ s = MV_HarshClipTable[s + 0x80];
+
+ *dest = (s & 0xff);
+
+ position += rate;
+ dest += MV_SampleSize;
+ }
+
+ MV_MixPosition = position;
+ MV_MixDestination = (char *)dest;
+}
+
+void MV_Mix8BitStereo( unsigned long position,
+ unsigned long rate, const char *start, unsigned long length )
+{
+ const unsigned char *src;
+ unsigned char *dest;
+ unsigned int i;
+
+ src = (const unsigned char *)start;
+ dest = (unsigned char *)MV_MixDestination;
+
+ for (i = 0; i < length; i++) {
+ int s = src[(position >> 16)];
+ int dl = dest[0];
+ int dr = dest[MV_RightChannelOffset];
+
+ dl += MV_LeftVolume[s * 2];
+ dr += MV_RightVolume[s * 2];
+
+ dl = MV_HarshClipTable[dl + 0x80];
+ dr = MV_HarshClipTable[dr + 0x80];
+
+ dest[0] = (dl & 0xff);
+ dest[MV_RightChannelOffset] = (dr & 0xff);
+
+ position += rate;
+ dest += MV_SampleSize;
+ }
+
+ MV_MixPosition = position;
+ MV_MixDestination = (char *)dest;
+}
+
+void MV_Mix16BitMono( unsigned long position,
+ unsigned long rate, const char *start, unsigned long length )
+{
+ const short *MV_LeftVolumeS;
+ const unsigned char *src;
+ short *dest;
+ unsigned int i;
+
+ src = (const unsigned char *)start;
+ dest = (short *)MV_MixDestination;
+
+ MV_LeftVolumeS = (const short *)MV_LeftVolume;
+
+ for (i = 0; i < length; i++) {
+ int s = src[position >> 16];
+ int d = dest[0];
+
+ s = MV_LeftVolumeS[s];
+
+ s += d;
+
+ if (s < -32768) s = -32768;
+ if (s > 32767) s = 32767;
+
+ *dest = (short) s;
+
+ position += rate;
+ dest += MV_SampleSize/2;
+ }
+
+ MV_MixPosition = position;
+ MV_MixDestination = (char *)dest;
+}
+
+void MV_Mix16BitStereo( unsigned long position,
+ unsigned long rate, const char *start, unsigned long length )
+{
+ const short *MV_LeftVolumeS;
+ const short *MV_RightVolumeS;
+ const unsigned char *src;
+ short *dest;
+ unsigned int i;
+
+ src = (unsigned char *)start;
+ dest = (short *)MV_MixDestination;
+
+ MV_LeftVolumeS = (const short *)MV_LeftVolume;
+ MV_RightVolumeS = (const short *)MV_RightVolume;
+
+ for (i = 0; i < length; i++) {
+ int s = src[position >> 16];
+ int dl = dest[0];
+ int dr = dest[MV_RightChannelOffset/2];
+
+ dl += MV_LeftVolumeS[s];
+ dr += MV_RightVolumeS[s];
+
+ if (dl < -32768) dl = -32768;
+ if (dl > 32767) dl = 32767;
+ if (dr < -32768) dr = -32768;
+ if (dr > 32767) dr = 32767;
+
+ dest[0] = (short) dl;
+ dest[MV_RightChannelOffset/2] = (short) dr;
+
+ position += rate;
+ dest += MV_SampleSize/2;
+ }
+
+ MV_MixPosition = position;
+ MV_MixDestination = (char *)dest;
+}
+
+void MV_Mix8BitMono16( unsigned long position, unsigned long rate,
+ const char *start, unsigned long length )
+{
+ const char *src;
+ unsigned char *dest;
+ unsigned int i;
+
+ src = (const char *)start + 1;
+ dest = (unsigned char *)MV_MixDestination;
+
+ for (i = 0; i < length; i++) {
+ int s = (int)src[(position >> 16) * 2] + 0x80;
+ int d = *dest;
+
+ s = MV_LeftVolume[s * 2];
+
+ s += d;
+
+ s = MV_HarshClipTable[s + 0x80];
+
+ *dest = (s & 0xff);
+
+ position += rate;
+ dest += MV_SampleSize;
+ }
+
+ MV_MixPosition = position;
+ MV_MixDestination = (char *)dest;
+}
+
+void MV_Mix8BitStereo16( unsigned long position,
+ unsigned long rate, const char *start, unsigned long length )
+{
+ const char *src;
+ unsigned char *dest;
+ unsigned int i;
+
+ src = (const char *)start + 1;
+ dest = (unsigned char *)MV_MixDestination;
+
+ for (i = 0; i < length; i++) {
+ int s = src[(position >> 16) * 2] + 0x80;
+ int dl = dest[0];
+ int dr = dest[MV_RightChannelOffset];
+
+ dl += MV_LeftVolume[s * 2];
+ dr += MV_RightVolume[s * 2];
+
+ dl = MV_HarshClipTable[dl + 0x80];
+ dr = MV_HarshClipTable[dr + 0x80];
+
+ dest[0] = (dl & 0xff);
+ dest[MV_RightChannelOffset] = (dr & 0xff);
+
+ position += rate;
+ dest += MV_SampleSize;
+ }
+
+ MV_MixPosition = position;
+ MV_MixDestination = (char *)dest;
+}
+
+void MV_Mix16BitMono16( unsigned long position,
+ unsigned long rate, const char *start, unsigned long length )
+{
+ const short *MV_LeftVolumeS;
+ const unsigned char *src;
+ short *dest;
+ unsigned int i;
+
+ src = (const unsigned char *)start;
+ dest = (short *)MV_MixDestination;
+
+ MV_LeftVolumeS = (const short *)MV_LeftVolume;
+
+ for (i = 0; i < length; i++) {
+ int sl = src[(position >> 16) * 2 + 0];
+ int sh = src[(position >> 16) * 2 + 1] ^ 0x80;
+
+ int d = *dest;
+
+ sl = MV_LeftVolume[sl * 2 + 1];
+ sh = MV_LeftVolumeS[sh];
+
+ d = sl + sh + 0x80 + d;
+
+ if (d < -32768) d = -32768;
+ if (d > 32767) d = 32767;
+
+ *dest = (short) d;
+
+ position += rate;
+ dest += MV_SampleSize/2;
+ }
+
+ MV_MixPosition = position;
+ MV_MixDestination = (char *)dest;
+}
+
+void MV_Mix16BitStereo16( unsigned long position,
+ unsigned long rate, const char *start, unsigned long length )
+{
+ const short *MV_LeftVolumeS;
+ const short *MV_RightVolumeS;
+ const unsigned char *src;
+ short *dest;
+ unsigned int i;
+
+ src = (const unsigned char *)start;
+ dest = (short *)MV_MixDestination;
+
+ MV_LeftVolumeS = (const short *)MV_LeftVolume;
+ MV_RightVolumeS = (const short *)MV_RightVolume;
+
+ for (i = 0; i < length; i++) {
+ int sl = src[(position >> 16) * 2 + 0];
+ int sh = src[(position >> 16) * 2 + 1] ^ 0x80;
+
+ int dl = dest[0];
+ int dr = dest[MV_RightChannelOffset/2];
+
+ int sll = MV_LeftVolume[sl * 2 + 1];
+ int slh = MV_LeftVolumeS[sh];
+
+ int srl = MV_RightVolume[sl * 2 + 1];
+ int srh = MV_RightVolumeS[sh];
+
+ dl = sll + slh + 0x80 + dl;
+ dr = srl + srh + 0x80 + dr;
+
+ if (dl < -32768) dl = -32768;
+ if (dl > 32767) dl = 32767;
+ if (dr < -32768) dr = -32768;
+ if (dr > 32767) dr = 32767;
+
+ dest[0] = (short) dl;
+ dest[MV_RightChannelOffset/2] = (short) dr;
+
+ position += rate;
+ dest += MV_SampleSize/2;
+ }
+
+ MV_MixPosition = position;
+ MV_MixDestination = (char *)dest;
+}
--- /dev/null
+++ b/rott/audiolib/mv_mix16.asm
@@ -1,0 +1,524 @@
+ IDEAL
+
+ p386
+ MODEL flat
+
+ dataseg
+ CODESEG
+
+ MASM
+ ALIGN 4
+
+EXTRN _MV_HarshClipTable:DWORD
+EXTRN _MV_MixDestination:DWORD
+EXTRN _MV_MixPosition:DWORD
+EXTRN _MV_LeftVolume:DWORD
+EXTRN _MV_RightVolume:DWORD
+EXTRN _MV_SampleSize:DWORD
+EXTRN _MV_RightChannelOffset:DWORD
+
+;================
+;
+; MV_Mix8BitMono16
+;
+;================
+
+; eax - position
+; edx - rate
+; ebx - start
+; ecx - number of samples to mix
+
+PROC MV_Mix8BitMono16_
+PUBLIC MV_Mix8BitMono16_
+; Two at once
+ pushad
+ mov ebp, eax
+
+ mov esi, ebx ; Source pointer
+ inc esi
+
+ ; Sample size
+ mov ebx, _MV_SampleSize
+ mov eax,OFFSET apatch7+2 ; convice tasm to modify code...
+ mov [eax],bl
+ mov eax,OFFSET apatch8+2 ; convice tasm to modify code...
+ mov [eax],bl
+ mov eax,OFFSET apatch9+3 ; convice tasm to modify code...
+ mov [eax],bl
+
+ ; Volume table ptr
+ mov ebx, _MV_LeftVolume ; Since we're mono, use left volume
+ mov eax,OFFSET apatch1+4 ; convice tasm to modify code...
+ mov [eax],ebx
+ mov eax,OFFSET apatch2+4 ; convice tasm to modify code...
+ mov [eax],ebx
+
+ ; Harsh Clip table ptr
+ mov ebx, _MV_HarshClipTable
+ add ebx, 128
+ mov eax,OFFSET apatch3+2 ; convice tasm to modify code...
+ mov [eax],ebx
+ mov eax,OFFSET apatch4+2 ; convice tasm to modify code...
+ mov [eax],ebx
+
+ ; Rate scale ptr
+ mov eax,OFFSET apatch5+2 ; convice tasm to modify code...
+ mov [eax],edx
+ mov eax,OFFSET apatch6+2 ; convice tasm to modify code...
+ mov [eax],edx
+
+ mov edi, _MV_MixDestination ; Get the position to write to
+
+ ; Number of samples to mix
+ shr ecx, 1 ; double sample count
+ cmp ecx, 0
+ je exit8m
+
+; eax - scratch
+; ebx - scratch
+; edx - scratch
+; ecx - count
+; edi - destination
+; esi - source
+; ebp - frac pointer
+; apatch1 - volume table
+; apatch2 - volume table
+; apatch3 - harsh clip table
+; apatch4 - harsh clip table
+; apatch5 - sample rate
+; apatch6 - sample rate
+
+ mov eax,ebp ; begin calculating first sample
+ add ebp,edx ; advance frac pointer
+ shr eax,16 ; finish calculation for first sample
+
+ mov ebx,ebp ; begin calculating second sample
+ add ebp,edx ; advance frac pointer
+ shr ebx,16 ; finish calculation for second sample
+
+ movsx eax, byte ptr [esi+2*eax] ; get first sample
+ movsx ebx, byte ptr [esi+2*ebx] ; get second sample
+ add eax, 80h
+ add ebx, 80h
+
+ ALIGN 4
+mix8Mloop:
+ movzx edx, byte ptr [edi] ; get current sample from destination
+apatch1:
+ movsx eax, byte ptr [2*eax+12345678h] ; volume translate first sample
+apatch2:
+ movsx ebx, byte ptr [2*ebx+12345678h] ; volume translate second sample
+ add eax, edx ; mix first sample
+apatch9:
+ movzx edx, byte ptr [edi + 1] ; get current sample from destination
+apatch3:
+ mov eax, [eax + 12345678h] ; harsh clip new sample
+ add ebx, edx ; mix second sample
+ mov [edi], al ; write new sample to destination
+ mov edx, ebp ; begin calculating third sample
+apatch4:
+ mov ebx, [ebx + 12345678h] ; harsh clip new sample
+apatch5:
+ add ebp,12345678h ; advance frac pointer
+ shr edx, 16 ; finish calculation for third sample
+ mov eax, ebp ; begin calculating fourth sample
+apatch7:
+ add edi, 2 ; move destination to second sample
+ shr eax, 16 ; finish calculation for fourth sample
+ mov [edi], bl ; write new sample to destination
+apatch6:
+ add ebp,12345678h ; advance frac pointer
+ movsx ebx, byte ptr [esi+2*eax] ; get fourth sample
+ movsx eax, byte ptr [esi+2*edx] ; get third sample
+ add ebx, 80h
+ add eax, 80h
+apatch8:
+ add edi, 2 ; move destination to third sample
+ dec ecx ; decrement count
+ jnz mix8Mloop ; loop
+
+ mov _MV_MixDestination, edi ; Store the current write position
+ mov _MV_MixPosition, ebp ; return position
+exit8m:
+ popad
+ ret
+ENDP MV_Mix8BitMono16_
+
+;================
+;
+; MV_Mix8BitStereo16
+;
+;================
+
+; eax - position
+; edx - rate
+; ebx - start
+; ecx - number of samples to mix
+
+PROC MV_Mix8BitStereo16_
+PUBLIC MV_Mix8BitStereo16_
+
+ pushad
+ mov ebp, eax
+
+ mov esi, ebx ; Source pointer
+ inc esi
+
+ ; Sample size
+ mov ebx, _MV_SampleSize
+ mov eax,OFFSET bpatch8+2 ; convice tasm to modify code...
+ mov [eax],bl
+ ; mov eax,OFFSET bpatch9+2 ; convice tasm to modify code...
+ ; mov [eax],bl
+
+ ; Right channel offset
+ mov ebx, _MV_RightChannelOffset
+ mov eax,OFFSET bpatch6+3 ; convice tasm to modify code...
+ mov [eax],ebx
+ mov eax,OFFSET bpatch7+2 ; convice tasm to modify code...
+ mov [eax],ebx
+
+ ; Volume table ptr
+ mov ebx, _MV_LeftVolume
+ mov eax,OFFSET bpatch1+4 ; convice tasm to modify code...
+ mov [eax],ebx
+
+ mov ebx, _MV_RightVolume
+ mov eax,OFFSET bpatch2+4 ; convice tasm to modify code...
+ mov [eax],ebx
+
+ ; Rate scale ptr
+ mov eax,OFFSET bpatch3+2 ; convice tasm to modify code...
+ mov [eax],edx
+
+ ; Harsh Clip table ptr
+ mov ebx, _MV_HarshClipTable
+ add ebx,128
+ mov eax,OFFSET bpatch4+2 ; convice tasm to modify code...
+ mov [eax],ebx
+ mov eax,OFFSET bpatch5+2 ; convice tasm to modify code...
+ mov [eax],ebx
+
+ mov edi, _MV_MixDestination ; Get the position to write to
+
+ ; Number of samples to mix
+ cmp ecx, 0
+ je short exit8S
+
+; eax - scratch
+; ebx - scratch
+; edx - scratch
+; ecx - count
+; edi - destination
+; esi - source
+; ebp - frac pointer
+; bpatch1 - left volume table
+; bpatch2 - right volume table
+; bpatch3 - sample rate
+; bpatch4 - harsh clip table
+; bpatch5 - harsh clip table
+
+ mov eax,ebp ; begin calculating first sample
+ shr eax,16 ; finish calculation for first sample
+
+ movsx ebx, byte ptr [esi+2*eax] ; get first sample
+ add ebx, 80h
+
+ ALIGN 4
+mix8Sloop:
+bpatch1:
+ movsx eax, byte ptr [2*ebx+12345678h] ; volume translate left sample
+ movzx edx, byte ptr [edi] ; get current sample from destination
+bpatch2:
+ movsx ebx, byte ptr [2*ebx+12345678h] ; volume translate right sample
+ add eax, edx ; mix left sample
+bpatch3:
+ add ebp,12345678h ; advance frac pointer
+bpatch6:
+ movzx edx, byte ptr [edi+12345678h] ; get current sample from destination
+bpatch4:
+ mov eax, [eax + 12345678h] ; harsh clip left sample
+ add ebx, edx ; mix right sample
+ mov [edi], al ; write left sample to destination
+bpatch5:
+ mov ebx, [ebx + 12345678h] ; harsh clip right sample
+ mov edx, ebp ; begin calculating second sample
+bpatch7:
+ mov [edi+12345678h], bl ; write right sample to destination
+ shr edx, 16 ; finish calculation for second sample
+bpatch8:
+ add edi, 1 ; move destination to second sample
+ movsx ebx, byte ptr [esi+2*edx] ; get second sample
+ add ebx, 80h
+ dec ecx ; decrement count
+ jnz mix8Sloop ; loop
+
+ mov _MV_MixDestination, edi ; Store the current write position
+ mov _MV_MixPosition, ebp ; return position
+
+EXIT8S:
+ popad
+ ret
+ENDP MV_Mix8BitStereo16_
+
+;================
+;
+; MV_Mix16BitMono16
+;
+;================
+
+; eax - position
+; edx - rate
+; ebx - start
+; ecx - number of samples to mix
+
+PROC MV_Mix16BitMono16_
+PUBLIC MV_Mix16BitMono16_
+
+ pushad
+ mov ebp, eax
+
+ mov esi, ebx ; Source pointer
+
+ ; Sample size
+ mov ebx, _MV_SampleSize
+ mov eax,OFFSET cpatch4+2 ; convice tasm to modify code...
+ mov [eax],bl
+ mov eax,OFFSET cpatch5+3 ; convice tasm to modify code...
+ mov [eax],bl
+
+ ; Volume table ptr
+ mov ebx, _MV_LeftVolume
+ mov eax,OFFSET cpatch2+4 ; convice tasm to modify code...
+ mov [eax],ebx
+ mov eax,OFFSET cpatch1+4 ; convice tasm to modify code...
+ inc ebx
+ mov [eax],ebx
+
+ ; Rate scale ptr
+ mov eax,OFFSET cpatch3+2 ; convice tasm to modify code...
+ mov [eax],edx
+
+ mov edi, _MV_MixDestination ; Get the position to write to
+
+ ; Number of samples to mix
+ cmp ecx, 0
+ je exit16M
+
+; eax - scratch
+; ebx - scratch
+; edx - scratch
+; ecx - count
+; edi - destination
+; esi - source
+; ebp - frac pointer
+; cpatch1 - volume table
+; cpatch2 - volume table
+; cpatch3 - sample rate
+; cpatch4 - sample rate
+
+ mov ebx,ebp ; begin calculating first sample
+ add ebp,edx ; advance frac pointer
+ shr ebx,16 ; finish calculation for first sample
+ movzx eax, word ptr [esi+2*ebx] ; get low byte of sample
+ xor eax, 8000h
+ movzx ebx, ah
+ sub ah, ah
+
+ movsx edx, word ptr [edi] ; get current sample from destination
+
+ ALIGN 4
+mix16Mloop:
+cpatch1:
+ movsx eax, byte ptr [2*eax+12345678h] ; volume translate low byte of sample
+cpatch2:
+ movsx ebx, word ptr [2*ebx+12345678h] ; volume translate high byte of sample
+ lea eax, [ eax + ebx + 80h ] ; mix high byte of sample
+ add eax, edx ; mix low byte of sample
+cpatch5:
+ movsx edx, word ptr [edi + 2] ; get current sample from destination
+
+ cmp eax, -32768 ; Harsh clip sample
+ jge short m16skip1
+ mov eax, -32768
+ jmp short m16skip2
+m16skip1:
+ cmp eax, 32767
+ jle short m16skip2
+ mov eax, 32767
+m16skip2:
+ mov ebx, ebp ; begin calculating second sample
+ mov [edi], ax ; write new sample to destination
+
+ shr ebx, 16 ; finish calculation for second sample
+cpatch3:
+ add ebp, 12345678h ; advance frac pointer
+
+ movzx eax, word ptr [esi+2*ebx] ; get second sample
+cpatch4:
+ add edi, 2 ; move destination to second sample
+ xor eax, 8000h
+ movzx ebx, ah
+ sub ah, ah
+
+ dec ecx ; decrement count
+ jnz mix16Mloop ; loop
+
+ mov _MV_MixDestination, edi ; Store the current write position
+ mov _MV_MixPosition, ebp ; return position
+EXIT16M:
+ popad
+ ret
+ENDP MV_Mix16BitMono16_
+
+;================
+;
+; MV_Mix16BitStereo16
+;
+;================
+
+; eax - position
+; edx - rate
+; ebx - start
+; ecx - number of samples to mix
+
+PROC MV_Mix16BitStereo16_
+PUBLIC MV_Mix16BitStereo16_
+
+ pushad
+ mov ebp, eax
+
+ mov esi, ebx ; Source pointer
+
+ ; Sample size
+ mov ebx, _MV_SampleSize
+ mov eax,OFFSET dpatch9+2 ; convice tasm to modify code...
+ mov [eax],bl
+
+ ; Right channel offset
+ mov ebx, _MV_RightChannelOffset
+ mov eax,OFFSET dpatch7+3 ; convice tasm to modify code...
+ mov [eax],ebx
+ mov eax,OFFSET dpatch8+3 ; convice tasm to modify code...
+ mov [eax],ebx
+
+ ; Volume table ptr
+ mov ebx, _MV_LeftVolume
+ mov eax,OFFSET dpatch1+4 ; convice tasm to modify code...
+ mov [eax],ebx
+ mov eax,OFFSET dpatch2+4 ; convice tasm to modify code...
+ inc ebx
+ mov [eax],ebx
+
+ mov ebx, _MV_RightVolume
+ mov eax,OFFSET dpatch3+4 ; convice tasm to modify code...
+ mov [eax],ebx
+ mov eax,OFFSET dpatch4+4 ; convice tasm to modify code...
+ inc ebx
+ mov [eax],ebx
+
+ ; Rate scale ptr
+ mov eax,OFFSET dpatch5+2 ; convice tasm to modify code...
+ mov [eax],edx
+
+ ; Source ptr
+ mov eax,OFFSET dpatch6+4 ; convice tasm to modify code...
+ mov [eax],esi
+
+ mov edi, _MV_MixDestination ; Get the position to write to
+
+ ; Number of samples to mix
+ cmp ecx, 0
+ je exit16S
+
+; eax - scratch
+; ebx - scratch
+; edx - scratch
+; esi - scratch
+; ecx - count
+; edi - destination
+; ebp - frac pointer
+; dpatch1 - left volume table
+; dpatch2 - right volume table
+; dpatch3 - sample rate
+
+ mov ebx,ebp ; begin calculating first sample
+ shr ebx,16 ; finish calculation for first sample
+
+ movzx edx, word ptr [esi+2*ebx] ; get first sample
+ xor edx, 8000h ; Change from signed to unsigned
+ movzx esi, dh ; put high byte in esi
+ sub dh, dh ; lo byte in edx
+
+ ALIGN 4
+mix16Sloop:
+ ; Left channel
+dpatch1:
+ movsx eax, word ptr [2*esi+12345678h] ; volume translate high byte of sample
+dpatch2:
+ movsx ebx, byte ptr [2*edx+12345678h] ; volume translate low byte of sample
+ lea eax, [ eax + ebx + 80h ] ; mix high byte of sample
+
+ ; Right channel
+dpatch3:
+ movsx esi, word ptr [2*esi+12345678h] ; volume translate high byte of sample
+dpatch4:
+ movsx ebx, byte ptr [2*edx+12345678h] ; volume translate low byte of sample
+ lea ebx, [ esi + ebx + 80h ] ; mix high byte of sample
+
+dpatch7:
+ movsx edx, word ptr [edi+12345678h] ; get current sample from destination
+dpatch5:
+ add ebp,12345678h ; advance frac pointer
+
+ add eax, edx ; mix left sample
+
+ cmp eax, -32768 ; Harsh clip sample
+ jge short s16skip1
+ mov eax, -32768
+ jmp short s16skip2
+s16skip1:
+ cmp eax, 32767
+ jle short s16skip2
+ mov eax, 32767
+s16skip2:
+ movsx edx, word ptr [edi+2] ; get current sample from destination
+ mov [edi], ax ; write left sample to destination
+ add ebx, edx ; mix right sample
+
+ cmp ebx, -32768 ; Harsh clip sample
+ jge short s16skip3
+ mov ebx, -32768
+ jmp short s16skip4
+s16skip3:
+ cmp ebx, 32767
+ jle short s16skip4
+ mov ebx, 32767
+s16skip4:
+
+ mov edx, ebp ; begin calculating second sample
+dpatch8:
+ mov [edi+12345678h], bx ; write right sample to destination
+ shr edx, 16 ; finish calculation for second sample
+dpatch9:
+ add edi, 4 ; move destination to second sample
+
+dpatch6:
+ movzx edx, word ptr [2*edx+12345678h] ; get second sample
+ xor edx, 8000h ; Change from signed to unsigned
+ movzx esi, dh ; put high byte in esi
+ sub dh, dh ; lo byte in edx
+
+ dec ecx ; decrement count
+ jnz mix16Sloop ; loop
+
+ mov _MV_MixDestination, edi ; Store the current write position
+ mov _MV_MixPosition, ebp ; return position
+exit16S:
+ popad
+ ret
+ENDP MV_Mix16BitStereo16_
+
+ ENDS
+
+ END
--- /dev/null
+++ b/rott/audiolib/mvreverb.asm
@@ -1,0 +1,181 @@
+ IDEAL
+
+ p386
+ MODEL flat
+
+ dataseg
+ CODESEG
+
+ MASM
+ ALIGN 4
+
+;================
+;
+; MV_16BitReverb
+;
+;================
+
+; eax - source position
+; edx - destination position
+; ebx - Volume table
+; ecx - number of samples
+
+PROC MV_16BitReverb_
+PUBLIC MV_16BitReverb_
+
+ mov esi, eax
+ lea edi, [edx - 2]
+
+ ALIGN 4
+rev16loop:
+ movzx eax, word ptr [esi] ; get sample
+ add edi, 2
+
+ movzx edx, ah
+ sub ah, ah
+
+ movsx eax, byte ptr [2*eax+ebx+1] ; volume translate low byte of sample
+ xor edx, 80h
+
+ movsx edx, word ptr [2*edx+ebx] ; volume translate high byte of sample
+ add esi, 2
+
+ lea eax, [ eax + edx + 80h ] ; mix high byte of sample
+ dec ecx ; decrement count
+
+ mov [edi], ax ; write new sample to destination
+ jnz rev16loop ; loop
+
+ ret
+ENDP MV_16BitReverb_
+
+;================
+;
+; MV_8BitReverb
+;
+;================
+
+; eax - source position
+; edx - destination position
+; ebx - Volume table
+; ecx - number of samples
+
+PROC MV_8BitReverb_
+PUBLIC MV_8BitReverb_
+
+ mov esi, eax
+ lea edi, [edx - 1]
+
+ xor eax, eax
+
+ ALIGN 4
+rev8loop:
+; movzx eax, byte ptr [esi] ; get sample
+ mov al, byte ptr [esi] ; get sample
+ inc edi
+
+; movsx eax, byte ptr [2*eax+ebx] ; volume translate sample
+ mov al, byte ptr [2*eax+ebx] ; volume translate sample
+ inc esi
+
+; add eax, 80h
+ add al, 80h
+ dec ecx ; decrement count
+
+ mov [edi], al ; write new sample to destination
+ jnz rev8loop ; loop
+
+ ret
+ENDP MV_8BitReverb_
+
+;================
+;
+; MV_16BitReverbFast
+;
+;================
+
+; eax - source position
+; edx - destination position
+; ebx - number of samples
+; ecx - shift
+
+PROC MV_16BitReverbFast_
+PUBLIC MV_16BitReverbFast_
+
+ mov esi, eax
+ mov eax,OFFSET rpatch16+3
+
+ mov [eax],cl
+ lea edi, [edx - 2]
+
+ ALIGN 4
+frev16loop:
+ mov ax, word ptr [esi] ; get sample
+ add edi, 2
+
+rpatch16:
+ sar ax, 5 ;;;;Add 1 before shift
+ add esi, 2
+
+ mov [edi], ax ; write new sample to destination
+ dec ebx ; decrement count
+
+ jnz frev16loop ; loop
+
+ ret
+ENDP MV_16BITREVERBFAST_
+
+;================
+;
+; MV_8BitReverbFast
+;
+;================
+
+; eax - source position
+; edx - destination position
+; ebx - number of samples
+; ecx - shift
+
+PROC MV_8BitReverbFast_
+PUBLIC MV_8BitReverbFast_
+ mov esi, eax
+ mov eax,OFFSET rpatch8+2
+
+ mov edi, edx
+ mov edx, 80h
+
+ mov [eax],cl
+ mov eax, 80h
+
+ shr eax, cl
+
+ dec edi
+ sub edx, eax
+
+ ALIGN 4
+frev8loop:
+ mov al, byte ptr [esi] ; get sample
+ inc esi
+
+ mov ecx, eax
+ inc edi
+
+rpatch8:
+ shr eax, 3
+ xor ecx, 80h ; flip the sign bit
+
+ shr ecx, 7 ; shift the sign down to 1
+ add eax, edx
+
+ add eax, ecx ; add sign bit to round to 0
+ dec ebx ; decrement count
+
+ mov [edi], al ; write new sample to destination
+ jnz frev8loop ; loop
+
+ ret
+ENDP MV_8BITREVERBFAST_
+
+ ENDS
+
+ END
--- /dev/null
+++ b/rott/audiolib/mvreverb.c
@@ -1,0 +1,58 @@
+#include "multivoc.h"
+#include "_multivc.h"
+
+void MV_16BitReverb( const char *src, char *dest, const VOLUME16 *volume, int count )
+{
+ int i;
+
+ short *pdest = (short *)dest;
+
+ for (i = 0; i < count; i++) {
+ int sl = src[i*2+0];
+ int sh = src[i*2+1] ^ 0x80;
+
+ sl = (*volume)[sl] >> 8;
+ sh = (*volume)[sh];
+
+ pdest[i] = (short)(sl + sh + 0x80);
+ }
+}
+
+void MV_8BitReverb( const signed char *src, signed char *dest, const VOLUME16 *volume, int count )
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ unsigned char s = (unsigned char) src[i];
+
+ s = (*volume)[s] & 0xff;
+
+ dest[i] = (char)(s + 0x80);
+ }
+}
+
+void MV_16BitReverbFast( const char *src, char *dest, int count, int shift )
+{
+ int i;
+
+ short *pdest = (short *)dest;
+ const short *psrc = (const short *)src;
+
+ for (i = 0; i < count; i++) {
+ pdest[i] = psrc[i] >> shift;
+ }
+}
+
+void MV_8BitReverbFast( const signed char *src, signed char *dest, int count, int shift )
+{
+ int i;
+
+ unsigned char sh = 0x80 - (0x80 >> shift);
+
+ for (i = 0; i < count; i++) {
+ unsigned char a = ((unsigned char) src[i]) >> shift;
+ unsigned char c = (((unsigned char) src[i]) ^ 0x80) >> 7;
+
+ dest[i] = (signed char) (a + sh + c);
+ }
+}
--- /dev/null
+++ b/rott/audiolib/myprint.c
@@ -1,0 +1,310 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include "myprint.h"
+
+static unsigned short disp_offset = 160 * 24;
+
+void DrawText
+ (
+ int x,
+ int y,
+ int ch,
+ int foreground,
+ int background
+ )
+
+ {
+ char *vid;
+
+ vid = ( char * )( 0xb0000 );
+ vid += y * 160;
+ vid += x * 2;
+
+ if ( ch != NONE )
+ {
+ *vid = ch;
+ }
+ vid++;
+ *vid = ( ( background & 0x0f ) << 4 ) | ( foreground & 0x0f );
+ }
+
+void TextBox
+ (
+ int x1,
+ int y1,
+ int x2,
+ int y2,
+ int ch,
+ int foreground,
+ int background
+ )
+
+ {
+ int x;
+ int y;
+
+ for( x = x1; x <= x2; x++ )
+ {
+ for( y = y1; y <= y2; y++ )
+ {
+ DrawText( x, y, ch, foreground, background );
+ }
+ }
+ }
+
+void TextFrame
+ (
+ int x1,
+ int y1,
+ int x2,
+ int y2,
+ int type,
+ int foreground,
+ int background
+ )
+
+ {
+ int x;
+ int y;
+
+ if ( type == 0 )
+ {
+ for( x = x1 + 1; x < x2; x++ )
+ {
+ DrawText( x, y1, type, foreground, background );
+ DrawText( x, y2, type, foreground, background );
+ }
+ for( y = y1 + 1; y < y2; y++ )
+ {
+ DrawText( x1, y, type, foreground, background );
+ DrawText( x2, y, type, foreground, background );
+ }
+ }
+ if ( type == SINGLE_FRAME )
+ {
+ DrawText( x1, y1, '�', foreground, background );
+ DrawText( x2, y1, '�', foreground, background );
+ DrawText( x1, y2, '�', foreground, background );
+ DrawText( x2, y2, '�', foreground, background );
+ for( x = x1 + 1; x < x2; x++ )
+ {
+ DrawText( x, y1, '�', foreground, background );
+ DrawText( x, y2, '�', foreground, background );
+ }
+ for( y = y1 + 1; y < y2; y++ )
+ {
+ DrawText( x1, y, '�', foreground, background );
+ DrawText( x2, y, '�', foreground, background );
+ }
+ }
+ if ( type == DOUBLE_FRAME )
+ {
+ DrawText( x1, y1, '�', foreground, background );
+ DrawText( x2, y1, '�', foreground, background );
+ DrawText( x1, y2, '�', foreground, background );
+ DrawText( x2, y2, '�', foreground, background );
+ for( x = x1 + 1; x < x2; x++ )
+ {
+ DrawText( x, y1, '�', foreground, background );
+ DrawText( x, y2, '�', foreground, background );
+ }
+ for( y = y1 + 1; y < y2; y++ )
+ {
+ DrawText( x1, y, '�', foreground, background );
+ DrawText( x2, y, '�', foreground, background );
+ }
+ }
+ }
+
+void mysetxy
+ (
+ int x,
+ int y
+ )
+
+ {
+ disp_offset = ( x * 2 ) + ( y * 160 );
+ }
+
+void myputch
+ (
+ char ch
+ )
+
+ {
+ int j;
+ char *disp_start = (char *)( 0xb0000 );
+
+ if ( disp_offset >= 160 * 24 )
+ {
+ for ( j = 160; j < 160 * 24; j += 2 )
+ {
+ *( disp_start + j - 160 ) = *( disp_start + j );
+ }
+
+ disp_offset = 160 * 23;
+
+ for ( j = disp_offset; j < ( 160 * 24 ); j += 2 )
+ {
+ *( disp_start + j ) = ' ';
+ }
+ }
+
+ if ( ch >= 32 )
+ {
+ *( disp_start + disp_offset ) = ch;
+ disp_offset = disp_offset + 2;
+ }
+
+ if ( ch == '\r' )
+ {
+ disp_offset = disp_offset / 160;
+ disp_offset = disp_offset * 160;
+ }
+
+ if ( ch == '\n' )
+ {
+ disp_offset = disp_offset + 160;
+ if ( disp_offset < 160 * 24 )
+ {
+ for ( j = disp_offset; j < ( ( ( disp_offset / 160 ) + 1 ) *
+ 160 ); j += 2 )
+ {
+ *( disp_start + j ) = ' ';
+ }
+ }
+ }
+ }
+
+int printstring
+ (
+ char *string
+ )
+
+ {
+ int count;
+ char *ptr;
+
+ ptr = string;
+ count = 0;
+
+ while ( *ptr )
+ {
+ myputch( *ptr );
+ count++;
+ ptr++;
+ }
+
+ return( count );
+ }
+
+
+int printnum
+ (
+ int number
+ )
+
+ {
+ char string[ 100 ];
+ int count;
+
+ itoa( number, string, 10 );
+ count = printstring( string );
+
+ return( count );
+ }
+
+int printunsigned
+ (
+ unsigned long number,
+ int radix
+ )
+
+ {
+ char string[ 100 ];
+ int count;
+
+ ultoa( number, string, radix );
+ count = printstring( string );
+
+ return( count );
+ }
+
+int myprintf
+ (
+ char *fmt,
+ ...
+ )
+
+ {
+ va_list argptr;
+ int count;
+ char *ptr;
+
+ return( 0 );
+
+ // DEBUG
+ mysetxy( 0, 0 );
+
+ va_start( argptr, fmt );
+ ptr = fmt;
+ count = 0;
+
+ while( *ptr != 0 )
+ {
+ if ( *ptr == '%' )
+ {
+ ptr++;
+ switch( *ptr )
+ {
+ case 0 :
+ return( EOF );
+ break;
+ case 'd' :
+ count += printnum( va_arg( argptr, int ) );
+ break;
+ case 's' :
+ count += printstring( va_arg( argptr, char * ) );
+ break;
+ case 'u' :
+ count += printunsigned( va_arg( argptr, int ), 10 );
+ break;
+ case 'x' :
+ case 'X' :
+ count += printunsigned( va_arg( argptr, int ), 16 );
+ break;
+ }
+ ptr++;
+ }
+ else
+ {
+ myputch( *ptr );
+ count++;
+ ptr++;
+ }
+ }
+
+ va_end( argptr );
+
+ return( count );
+ }
--- /dev/null
+++ b/rott/audiolib/myprint.h
@@ -1,0 +1,43 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef __MYPRINT_H
+#define __MYPRINT_H
+
+enum COLORS
+ {
+ BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LIGHTGRAY, DARKGRAY,
+ LIGHTBLUE, LIGHTGREEN, LIGHTCYAN, LIGHTRED, LIGHTMAGENTA, YELLOW, WHITE
+ };
+
+#define NONE -1
+#define SINGLE_FRAME -1
+#define DOUBLE_FRAME -2
+
+void DrawText( int x, int y, int ch, int foreground, int background );
+void TextBox( int x1, int y1, int x2, int y2, int ch, int foreground, int background );
+void TextFrame( int x1, int y1, int x2, int y2, int type, int foreground, int background );
+void mysetxy( int x, int y );
+void myputch( char ch );
+int printstring( char *string );
+int printnum( int number );
+int printunsigned( unsigned long number, int radix );
+int myprintf( char *fmt, ... );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/newgf1.h
@@ -1,0 +1,431 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/***************************************************************************
+* NAME: GF1.H
+** COPYRIGHT:
+** "Copyright (c) 1991,1992, by FORTE
+**
+** "This software is furnished under a license and may be used,
+** copied, or disclosed only in accordance with the terms of such
+** license and with the inclusion of the above copyright notice.
+** This software or any other copies thereof may not be provided or
+** otherwise made available to any other person. No title to and
+** ownership of the software is hereby transfered."
+****************************************************************************
+* CREATION DATE: 07/01/92
+*--------------------------------------------------------------------------*
+* VERSION DATE NAME DESCRIPTION
+*> 1.0 07/01/92 Original
+***************************************************************************/
+
+#ifndef _GF1_H /* allow header to be processed only once */
+#define _GF1_H
+
+/* error codes */
+#define OK 0
+#define NO_MORE_VOICES -1
+#define BASE_NOT_FOUND 1
+#define BAD_IRQ 2
+#define BAD_DMA 3
+#define OS_LOADED 4
+#define NOT_LOADED 5
+#define NO_MEMORY 6
+#define DMA_BUSY 7
+#define NO_MORE_HANDLERS 8
+#define DMA_HUNG 9
+#define CARD_NOT_FOUND 10
+#define CARD_BEING_USED 11
+#define NO_MORE_INTERRUPTS 12
+#define BAD_TIMER 13
+#define BAD_PATCH 14
+#define OLD_PATCH 15
+#define DOS_ERROR 16
+#define FILE_NOT_FOUND 17
+
+/* bits */
+#define BIT0 0x01
+#define BIT1 0x02
+#define BIT2 0x04
+#define BIT3 0x08
+#define BIT4 0x10
+#define BIT5 0x20
+#define BIT6 0x40
+#define BIT7 0x80
+
+/* bounds for volume enveloping functions */
+#define MIN_OFFSET 5U
+#define MAX_OFFSET 251U
+
+/* bounds for voice allocation */
+#define MIN_VOICES 14
+#define MAX_VOICES 32
+
+/* DMA control bits */
+#define DMA_ENABLE BIT0
+#define DMA_READ BIT1
+#define DMA_WIDTH_16 BIT2 /* width of DMA channel */
+#define DMA_RATE_DIV_1 BIT3
+#define DMA_RATE_DIV_2 BIT4
+#define DMA_IRQ_ENABLE BIT5
+#define DMA_IRQ_PRESENT BIT6
+#define DMA_DATA_16 BIT6 /* width of data */
+#define DMA_INVERT_MSB BIT7
+
+/* SAMPLE control bits */
+#define DMA_STEREO 2
+
+/* DMA flags */
+#define GF1_RECORD 0 /* use dma control or sample control */
+#define GF1_DMA 1
+
+/* MIDI control register */
+#define MIDI_RESET (BIT0|BIT1)
+#define MIDI_TD_INT BIT5
+#define MIDI_RD_INT BIT7
+
+/* MIDI_STATUS_REGISTER */
+#define MIDI_RD BIT0
+#define MIDI_TD BIT1
+#define MIDI_ERR_FRAMING BIT4
+#define MIDI_ERR_OVERRUN BIT5
+
+/* digital playback flags */
+#define TYPE_8BIT BIT0 /* 1 use 8 bit data */
+ /* 0 use 16 bit data */
+#define TYPE_PRELOAD BIT1 /* preload data */
+#define TYPE_INVERT_MSB BIT2 /* invert most significant bit during dma */
+#define TYPE_STEREO BIT3 /* 1 for stereo data */
+
+/* sound effects and digital music types */
+#define SND_LOOP_MASK (BIT0|BIT1)
+#define SND_LOOP_NONE 0
+#define SND_LOOP 1
+#define SND_LOOP_BIDIR 2
+#define SND_8BIT (BIT2)
+#define SND_BACKWARD (BIT3)
+
+#define SOUND_PLAYING 2
+#define SOUND_ACTIVE 1
+
+/* patch macros */
+#define HEADER_SIZE 12
+#define ID_SIZE 10
+#define DESC_SIZE 60
+#define RESERVED_SIZE 40
+#define PATCH_HEADER_RESERVED_SIZE 36
+#define LAYER_RESERVED_SIZE 40
+#define PATCH_DATA_RESERVED_SIZE 36
+#define GF1_HEADER_TEXT "GF1PATCH110"
+#define INST_NAME_SIZE 16
+#define ENVELOPES 6
+#define MAX_LAYERS 4
+
+/* patch modes */
+#define PATCH_16 BIT0
+#define PATCH_UNSIGNED BIT1
+#define PATCH_LOOPEN BIT2
+#define PATCH_BIDIR BIT3
+#define PATCH_BACKWARD BIT4
+#define PATCH_SUSTAIN BIT5
+#define PATCH_NO_SRELEASE BIT6
+#define PATCH_FAST_REL BIT7
+
+/* flags for patch loading */
+#define PATCH_LOAD_8_BIT BIT0
+
+/* digital playback callback reasons & return values */
+#define DIG_DONE 0
+#define DIG_MORE_DATA 1
+#define DIG_BUFFER_DONE 2
+#define DIG_PAUSE 3
+
+/* log table used for vibrato and pitch bend. log table made public for
+** developers use */
+#define LOG_TAB_SIZE 12
+extern long gf1_log_table[LOG_TAB_SIZE];
+
+#if defined(__BORLANDC__)
+#undef RFAR
+#define RFAR far
+#elif defined(_MSC_VER) && (_MSC_VER <= 600)
+#define RFAR far
+#elif defined(_MSC_VER) && (_MSC_VER > 600)
+#define RFAR __far
+#else
+#undef RFAR
+#define RFAR
+#endif
+
+/* structure definitions */
+struct load_os
+{
+ unsigned short voices;
+ unsigned short forced_base_port;
+ unsigned char forced_gf1_irq;
+ unsigned char forced_midi_irq;
+ unsigned char forced_channel_in;
+ unsigned char forced_channel_out;
+};
+
+struct patchheader
+{
+ char header[ HEADER_SIZE ];
+ char gravis_id[ ID_SIZE ]; /* Id = "ID#000002" */
+ char description[ DESC_SIZE ];
+ unsigned char instruments;
+ char voices;
+ char channels;
+ unsigned short wave_forms;
+ unsigned short master_volume;
+ unsigned long data_size;
+ char reserved[ PATCH_HEADER_RESERVED_SIZE ];
+};
+
+struct instrumentdata
+{
+ unsigned short instrument;
+ char instrument_name[ INST_NAME_SIZE ];
+ long instrument_size;
+ char layers;
+ char reserved[ RESERVED_SIZE ];
+};
+
+struct layerdata
+{
+ char layer_duplicate;
+ char layer;
+ long layer_size;
+ char samples;
+ char reserved[ LAYER_RESERVED_SIZE ];
+};
+
+struct patchdata
+{
+ char wave_name[7];
+ unsigned char fractions;
+ long wave_size;
+ long start_loop;
+ long end_loop;
+ unsigned short sample_rate;
+ long low_frequency;
+ long high_frequency;
+ long root_frequency;
+ short tune;
+ unsigned char balance;
+ unsigned char envelope_rate[ ENVELOPES ];
+ unsigned char envelope_offset[ ENVELOPES ];
+ unsigned char tremolo_sweep;
+ unsigned char tremolo_rate;
+ unsigned char tremolo_depth;
+ unsigned char vibrato_sweep;
+ unsigned char vibrato_rate;
+ unsigned char vibrato_depth;
+ char modes;
+ short scale_frequency;
+ unsigned short scale_factor; /* from 0 to 2048 or 0 to 2 */
+ char reserved[ PATCH_DATA_RESERVED_SIZE ];
+};
+
+struct wave_struct
+{
+ unsigned long start_loop;
+ unsigned long end_loop;
+ long low_frequency;
+ long high_frequency;
+ long root_frequency;
+ unsigned long mem;
+ unsigned short scale_frequency;
+ unsigned short sample_rate;
+ unsigned short scale_factor;
+ unsigned short start_acc_low;
+ unsigned short start_acc_high;
+ unsigned short start_low;
+ unsigned short start_high;
+ unsigned short end_low;
+ unsigned short end_high;
+ unsigned short end_acc_low;
+ unsigned short end_acc_high;
+ unsigned short sample_ratio;
+ unsigned long wave_size;
+ unsigned char fractions;
+ unsigned char balance;
+ unsigned char envelope_rate[ ENVELOPES ];
+ unsigned char envelope_offset[ ENVELOPES ];
+ unsigned char tremolo_sweep;
+ unsigned char tremolo_rate;
+ unsigned char tremolo_depth;
+ unsigned char vibrato_sweep;
+ unsigned char vibrato_rate;
+ unsigned char vibrato_depth;
+ unsigned char modes;
+};
+
+struct patchinfo {
+ struct patchheader header;
+ struct instrumentdata idata;
+};
+
+struct patch {
+ short nlayers;
+ struct wave_struct RFAR *layer_waves[MAX_LAYERS];
+ short layer_nwaves[MAX_LAYERS];
+ unsigned short detune;
+};
+
+struct gf1_dma_buff {
+ unsigned char RFAR *vptr;
+ unsigned long paddr;
+};
+
+struct gf1_sound {
+ unsigned long mem_pos;
+ unsigned long start_loop;
+ unsigned long end_loop;
+ unsigned char type;
+};
+
+/* GLOBAL VARIABLES (flags) */
+extern char gf1_linear_volumes;
+extern char gf1_dig_use_extra_voice;
+
+/* FUNCTION PROTOTYPES */
+/* Initializeation routines */
+int gf1_init_ports(int);
+int gf1_load_os(struct load_os RFAR *os);
+int gf1_unload_os(void);
+void gf1_set_appname(char RFAR *);
+void reset_ultra(int);
+int gf1_asm_init(void);
+unsigned char gf1_peek(unsigned long address);
+void gf1_poke(unsigned long address, unsigned char data);
+void gf1_poke_block(unsigned char RFAR *data, unsigned long address, unsigned long len, unsigned char dma_control);
+char gf1_good_dram(unsigned long address);
+int GetUltraCfg(struct load_os RFAR *os);
+unsigned long gf1_malloc(unsigned long);
+void gf1_free(unsigned long);
+unsigned long gf1_mem_avail(void);
+unsigned long gf1_mem_largest_avail(void);
+void gf1_delay(void);
+int gf1_allocate_voice(int priority, void (RFAR *steal_notify)(int));
+void gf1_free_voice(unsigned int i);
+void gf1_adjust_priority(int voice, int priority);
+int gf1_dram_xfer(struct gf1_dma_buff RFAR *dptr, unsigned long size, unsigned long dram_address, unsigned char dma_control, unsigned short flags);
+void gf1_stop_dma(void);
+long convert_to_16bit(long address);
+int gf1_wait_dma(void);
+int gf1_dma_ready(void);
+unsigned long gf1_amount_xferred(void);
+int gf1_detect_card(unsigned short port);
+char *gf1_error_str(int);
+int gf1_play_digital(unsigned short priority, unsigned char RFAR *buffer,
+ unsigned long size, unsigned long gf1_addr, unsigned short volume,
+ unsigned short pan, unsigned short frequency, unsigned char type,
+ struct gf1_dma_buff RFAR *dptr,
+ int (RFAR *callback)(int, int, unsigned char RFAR * RFAR *, unsigned long RFAR *));
+void gf1_restart_digital(int voice);
+void gf1_start_digital(int voice);
+void gf1_pause_digital(int voice);
+void RFAR gf1_stop_digital(int voice);
+void gf1_dig_set_dma_rate(unsigned short rate);
+unsigned long gf1_digital_position(int voice);
+int gf1_myatoi(void);
+int gf1_update_waveform(struct wave_struct RFAR *wave_info);
+int gf1_get_patch_info(char RFAR *patch_file, struct patchinfo RFAR *patch);
+int gf1_load_patch(char RFAR *patch_file, struct patchinfo RFAR *patchinfo,
+ struct patch RFAR *patch,
+ struct gf1_dma_buff RFAR *dptr, unsigned short size,
+ unsigned char RFAR *wavemem, int flags);
+void gf1_unload_patch(struct patch RFAR *patch);
+void gf1_detune_patch(struct patch RFAR *patch, unsigned short detune);
+unsigned short gf1_calc_fc(unsigned int sample_ratio,long root,long frequency);
+void gf1_midi_stop_voice(int voice);
+void gf1_midi_wait_voice(int voice);
+unsigned short gf1_midi_status_note(int voice);
+unsigned short gf1_midi_status_voice(int voice);
+void RFAR gf1_midi_stop_note(int note_voice);
+void gf1_midi_note_on(struct patch RFAR *patch, int priority, int note, int velocity, int channel);
+void gf1_midi_note_off(int note, int channel);
+void gf1_midi_silence_patch_notes(struct patch RFAR *patch);
+void gf1_midi_patch_removed(struct patch RFAR *patch);
+int gf1_enable_timer1(int (RFAR *callback)(void), int resolution);
+int gf1_enable_timer2(int (RFAR *callback)(void), int resolution);
+void gf1_disable_timer1(void);
+void gf1_disable_timer2(void);
+void gf1_channel_pitch_bend(int channel, unsigned int bend);
+void gf1_midi_synth_volume(unsigned short synth, int master_volume);
+void gf1_midi_change_program(struct patch RFAR *patch, int channel);
+void gf1_midi_set_vibrato(int channel, int value);
+void gf1_midi_change_volume(int channel, unsigned int volume);
+void gf1_midi_set_balance(int balance, int channel);
+void gf1_midi_channel_sustain(int channel, int sustain);
+void gf1_midi_all_notes_off(int channel);
+void gf1_midi_pitch_bend(int channel, int lsb, int msb);
+void gf1_midi_parameter(int channel, int control, int value);
+int gf1_midi_get_channel_notes(int channel, int notes[]);
+int gf1_midi_get_channel_volume(int channel);
+int gf1_midi_get_master_volume(void);
+int gf1_midi_get_volume(int voice);
+unsigned short gf1_read(int handle, void RFAR *io_buffer, unsigned short size);
+unsigned short gf1_close_file(int handle);
+unsigned int gf1_seek(int handle, unsigned long offset, int method);
+int gf1_open(char RFAR *name);
+#ifdef __FLAT__
+int gf1_atoi(char RFAR **str, int base);
+#else
+int gf1_atoi(void);
+#endif
+void gf1_leave(void);
+short gf1_enter(void);
+void gf1_enter1(void);
+int gf1_play_next_buffer(int voice, unsigned char RFAR *buff, unsigned long size);
+void gf1_dig_set_vol(unsigned short voice, unsigned short vol);
+void gf1_dig_set_pan(unsigned short voice, unsigned short pan);
+int gf1_set_external_semaphore(void RFAR *addr);
+int gf1_clear_external_semaphore(void RFAR *addr);
+void gf1_midi_reset(int c);
+int gf1_add_midi_recv_handler(int (RFAR *handler)());
+int gf1_add_dma_handler(int (*handler)());
+int gf1_add_voice_handler(int (*handler)(int));
+int gf1_add_volume_handler(int (*handler)(int));
+int gf1_add_timer_handler(int timer, int (RFAR *handler)(void));
+void gf1_set_record_rate(unsigned long rate);
+void gf1_create_patch(struct patch RFAR *patch);
+int gf1_add_layer(struct patch RFAR *patch, int layer, char RFAR *wavemem);
+void gf1_get_waveform_info(struct patch RFAR *patch, int layer, int waven,
+ struct wave_struct RFAR *wave);
+void gf1_set_waveform_info(struct patch RFAR *patch, int layer, int waven,
+ struct wave_struct RFAR *wave);
+void gf1_enable_line_in(void);
+void gf1_disable_line_in(void);
+void gf1_enable_mic_in(void);
+void gf1_disable_mic_in(void);
+void gf1_enable_output(void);
+void gf1_disable_output(void);
+void gf1_sound_volume(unsigned short voice, int volume,
+ unsigned long period /* us*10 */);
+void gf1_sound_pan(unsigned short voice, unsigned short pan);
+void gf1_sound_frequency(unsigned short voice, unsigned long freq);
+void RFAR gf1_sound_stop(int voice);
+void gf1_sound_mode(int voice, struct gf1_sound RFAR *sound,
+ unsigned char type);
+int gf1_sound_start(unsigned short priority, struct gf1_sound RFAR *sound,
+ short volume, unsigned long period, short pan, unsigned long freq);
+int gf1_sound_playing(int voice);
+#endif
--- /dev/null
+++ b/rott/audiolib/nodpmi.c
@@ -1,0 +1,179 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: DPMI.C
+
+ author: James R. Dose
+ date: April 8, 1994
+
+ Functions for performing DPMI calls.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include "dpmi.h"
+
+#define TRUE ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+/*---------------------------------------------------------------------
+ Function: DPMI_GetRealModeVector
+
+ Returns the vector of a real mode interrupt.
+---------------------------------------------------------------------*/
+
+unsigned long DPMI_GetRealModeVector
+ (
+ int num
+ )
+
+ {
+ return 0;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: DPMI_SetRealModeVector
+
+ Sets the vector of a real mode interrupt.
+---------------------------------------------------------------------*/
+
+void DPMI_SetRealModeVector
+ (
+ int num,
+ unsigned long vector
+ )
+
+ {
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: DPMI_CallRealModeFunction
+
+ Performs a call to a real mode function.
+---------------------------------------------------------------------*/
+
+int DPMI_CallRealModeFunction
+ (
+ dpmi_regs *callregs
+ )
+
+ {
+ return( DPMI_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: DPMI_LockMemory
+
+ Locks a region of memory to keep the virtual memory manager from
+ paging the region out.
+---------------------------------------------------------------------*/
+
+int DPMI_LockMemory
+ (
+ void *address,
+ unsigned length
+ )
+
+ {
+ return ( DPMI_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: DPMI_LockMemoryRegion
+
+ Locks a region of memory to keep the virtual memory manager from
+ paging the region out.
+---------------------------------------------------------------------*/
+
+int DPMI_LockMemoryRegion
+ (
+ void *start,
+ void *end
+ )
+
+ {
+ int status;
+
+ status = DPMI_LockMemory( start, ( char * )end - ( char * )start );
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: DPMI_UnlockMemory
+
+ Unlocks a region of memory that was previously locked.
+---------------------------------------------------------------------*/
+
+int DPMI_UnlockMemory
+ (
+ void *address,
+ unsigned length
+ )
+
+ {
+ return ( DPMI_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: DPMI_UnlockMemoryRegion
+
+ Unlocks a region of memory that was previously locked.
+---------------------------------------------------------------------*/
+
+int DPMI_UnlockMemoryRegion
+ (
+ void *start,
+ void *end
+ )
+
+ {
+ int status;
+
+ status = DPMI_UnlockMemory( start, ( char * )end - ( char * )start );
+
+ return( status );
+ }
+
+int DPMI_GetDOSMemory( void **ptr, long *descriptor, unsigned length )
+{
+ /* Lovely... */
+
+ *ptr = (void *)malloc(length);
+
+ *descriptor = (long) *ptr;
+
+ return (descriptor == 0) ? DPMI_Error : DPMI_Ok;
+}
+
+int DPMI_FreeDOSMemory( long descriptor )
+{
+ free((void *)descriptor);
+
+ return (descriptor == 0) ? DPMI_Error : DPMI_Ok;
+}
--- /dev/null
+++ b/rott/audiolib/nomusic.c
@@ -1,0 +1,115 @@
+#include "music.h"
+
+char *MUSIC_ErrorString(int ErrorNumber)
+{
+ return "";
+}
+
+int MUSIC_Init(int SoundCard, int Address)
+{
+ return 0;
+}
+
+int MUSIC_Shutdown(void)
+{
+ return 0;
+}
+
+void MUSIC_SetMaxFMMidiChannel(int channel)
+{
+}
+
+void MUSIC_SetVolume(int volume)
+{
+}
+
+void MUSIC_SetMidiChannelVolume(int channel, int volume)
+{
+}
+
+void MUSIC_ResetMidiChannelVolumes(void)
+{
+}
+
+int MUSIC_GetVolume(void)
+{
+ return 0;
+}
+
+void MUSIC_SetLoopFlag(int loopflag)
+{
+}
+
+int MUSIC_SongPlaying(void)
+{
+ return 0;
+}
+
+void MUSIC_Continue(void)
+{
+}
+
+void MUSIC_Pause(void)
+{
+}
+
+int MUSIC_StopSong(void)
+{
+ return 0;
+}
+
+int MUSIC_PlaySong(unsigned char *song, int loopflag)
+{
+ return 0;
+}
+
+void MUSIC_SetContext(int context)
+{
+}
+
+int MUSIC_GetContext(void)
+{
+ return 0;
+}
+
+void MUSIC_SetSongTick(unsigned long PositionInTicks)
+{
+}
+
+void MUSIC_SetSongTime(unsigned long milliseconds)
+{
+}
+
+void MUSIC_SetSongPosition(int measure, int beat, int tick)
+{
+}
+
+void MUSIC_GetSongPosition(songposition *pos)
+{
+}
+
+void MUSIC_GetSongLength(songposition *pos)
+{
+}
+
+int MUSIC_FadeVolume(int tovolume, int milliseconds)
+{
+ return 0;
+}
+
+int MUSIC_FadeActive(void)
+{
+ return 0;
+}
+
+void MUSIC_StopFade(void)
+{
+}
+
+void MUSIC_RerouteMidiChannel(int channel, int cdecl function( int event, int c1, int c2 ))
+{
+}
+
+void MUSIC_RegisterTimbreBank(unsigned char *timbres)
+{
+}
--- /dev/null
+++ b/rott/audiolib/pas16.c
@@ -1,0 +1,1924 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: PAS16.C
+
+ author: James R. Dose
+ date: March 27, 1994
+
+ Low level routines to support Pro AudioSpectrum and compatible
+ sound cards.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#include <dos.h>
+#include <conio.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "dpmi.h"
+#include "dma.h"
+#include "interrup.h"
+#include "irq.h"
+#include "pas16.h"
+#include "_pas16.h"
+
+#define USESTACK
+
+static const int PAS_Interrupts[ PAS_MaxIrq + 1 ] =
+ {
+ INVALID, INVALID, 0xa, 0xb,
+ INVALID, 0xd, INVALID, 0xf,
+ INVALID, INVALID, 0x72, 0x73,
+ 0x74, INVALID, INVALID, 0x77
+ };
+
+static void ( interrupt far *PAS_OldInt )( void );
+
+static int PAS_IntController1Mask;
+static int PAS_IntController2Mask;
+
+static int PAS_Installed = FALSE;
+static int PAS_TranslateCode = DEFAULT_BASE;
+
+static int PAS_OriginalPCMLeftVolume = 75;
+static int PAS_OriginalPCMRightVolume = 75;
+
+static int PAS_OriginalFMLeftVolume = 75;
+static int PAS_OriginalFMRightVolume = 75;
+
+unsigned int PAS_DMAChannel;
+static int PAS_Irq;
+
+static MVState *PAS_State = NULL;
+static MVFunc *PAS_Func = NULL;
+
+static MVState PAS_OriginalState;
+static int PAS_SampleSizeConfig;
+
+static char *PAS_DMABuffer;
+static char *PAS_DMABufferEnd;
+static char *PAS_CurrentDMABuffer;
+static int PAS_TotalDMABufferSize;
+
+static int PAS_TransferLength = 0;
+static int PAS_MixMode = PAS_DefaultMixMode;
+static unsigned PAS_SampleRate = PAS_DefaultSampleRate;
+static int PAS_TimeInterval = 0;
+
+volatile int PAS_SoundPlaying;
+
+void ( *PAS_CallBack )( void );
+
+// adequate stack size
+#define kStackSize 2048
+
+static unsigned short StackSelector = NULL;
+static unsigned long StackPointer;
+
+static unsigned short oldStackSelector;
+static unsigned long oldStackPointer;
+
+// This is defined because we can't create local variables in a
+// function that switches stacks.
+static int irqstatus;
+
+// These declarations are necessary to use the inline assembly pragmas.
+
+extern void GetStack(unsigned short *selptr,unsigned long *stackptr);
+extern void SetStack(unsigned short selector,unsigned long stackptr);
+
+// This function will get the current stack selector and pointer and save
+// them off.
+#pragma aux GetStack = \
+ "mov [edi],esp" \
+ "mov ax,ss" \
+ "mov [esi],ax" \
+ parm [esi] [edi] \
+ modify [eax esi edi];
+
+// This function will set the stack selector and pointer to the specified
+// values.
+#pragma aux SetStack = \
+ "mov ss,ax" \
+ "mov esp,edx" \
+ parm [ax] [edx] \
+ modify [eax edx];
+
+int PAS_ErrorCode = PAS_Ok;
+
+#define PAS_SetErrorCode( status ) \
+ PAS_ErrorCode = ( status );
+
+/*---------------------------------------------------------------------
+ Function: PAS_ErrorString
+
+ Returns a pointer to the error message associated with an error
+ number. A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *PAS_ErrorString
+ (
+ int ErrorNumber
+ )
+
+ {
+ char *ErrorString;
+
+ switch( ErrorNumber )
+ {
+ case PAS_Warning :
+ case PAS_Error :
+ ErrorString = PAS_ErrorString( PAS_ErrorCode );
+ break;
+
+ case PAS_Ok :
+ ErrorString = "Pro AudioSpectrum ok.";
+ break;
+
+ case PAS_DriverNotFound :
+ ErrorString = "MVSOUND.SYS not loaded.";
+ break;
+
+ case PAS_DmaError :
+ ErrorString = DMA_ErrorString( DMA_Error );
+ break;
+
+ case PAS_InvalidIrq :
+ ErrorString = "Invalid Pro AudioSpectrum Irq.";
+ break;
+
+ case PAS_UnableToSetIrq :
+ ErrorString = "Unable to set Pro AudioSpectrum IRQ. Try selecting an IRQ of 7 or below.";
+ break;
+
+ case PAS_Dos4gwIrqError :
+ ErrorString = "Unsupported Pro AudioSpectrum Irq.";
+ break;
+
+ case PAS_NoSoundPlaying :
+ ErrorString = "No sound playing on Pro AudioSpectrum.";
+ break;
+
+ case PAS_CardNotFound :
+ ErrorString = "Could not find Pro AudioSpectrum.";
+ break;
+
+ case PAS_DPMI_Error :
+ ErrorString = "DPMI Error in PAS16.";
+ break;
+
+ case PAS_OutOfMemory :
+ ErrorString = "Out of conventional memory in PAS16.";
+ break;
+
+ default :
+ ErrorString = "Unknown Pro AudioSpectrum error code.";
+ break;
+ }
+
+ return( ErrorString );
+ }
+
+
+/**********************************************************************
+
+ Memory locked functions:
+
+**********************************************************************/
+
+
+#define PAS_LockStart PAS_CheckForDriver
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_CheckForDriver
+
+ Checks to see if MVSOUND.SYS is installed.
+---------------------------------------------------------------------*/
+
+int PAS_CheckForDriver
+ (
+ void
+ )
+
+ {
+ union REGS regs;
+ unsigned result;
+
+ regs.w.ax = MV_CheckForDriver;
+ regs.w.bx = 0x3f3f;
+
+ #ifdef __386__
+ int386( MV_SoundInt, ®s, ®s );
+ #else
+ int86( MV_SoundInt, ®s, ®s );
+ #endif
+
+ if ( regs.w.ax != MV_CheckForDriver )
+ {
+ PAS_SetErrorCode( PAS_DriverNotFound );
+ return( PAS_Error );
+ }
+
+ result = regs.w.bx ^ regs.w.cx ^ regs.w.dx;
+ if ( result != MV_Signature )
+ {
+ PAS_SetErrorCode( PAS_DriverNotFound );
+ return( PAS_Error );
+ }
+
+ return( PAS_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_GetStateTable
+
+ Returns a pointer to the state table containing hardware state
+ information. The state table is necessary because the Pro Audio-
+ Spectrum contains only write-only registers.
+---------------------------------------------------------------------*/
+
+MVState *PAS_GetStateTable
+ (
+ void
+ )
+
+ {
+ union REGS regs;
+ MVState *ptr;
+
+ regs.w.ax = MV_GetPointerToStateTable;
+
+ #ifdef __386__
+ int386( MV_SoundInt, ®s, ®s );
+ #else
+ int86( MV_SoundInt, ®s, ®s );
+ #endif
+
+ if ( regs.w.ax != MV_Signature )
+ {
+ PAS_SetErrorCode( PAS_DriverNotFound );
+ return( NULL );
+ }
+
+ #if defined(__WATCOMC__) && defined(__FLAT__)
+ ptr = ( MVState * )( ( ( ( unsigned )regs.w.dx ) << 4 ) +
+ ( ( unsigned )regs.w.bx ) );
+ #else
+ ptr = MK_FP( regs.w.dx, regs.w.bx );
+ #endif
+
+ return( ptr );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_GetFunctionTable
+
+ Returns a pointer to the function table containing addresses of
+ driver functions.
+---------------------------------------------------------------------*/
+
+MVFunc *PAS_GetFunctionTable
+ (
+ void
+ )
+
+ {
+ union REGS regs;
+ MVFunc *ptr;
+
+ regs.w.ax = MV_GetPointerToFunctionTable;
+
+ #ifdef __386__
+ int386( MV_SoundInt, ®s, ®s );
+ #else
+ int86( MV_SoundInt, ®s, ®s );
+ #endif
+
+ if ( regs.w.ax != MV_Signature )
+ {
+ PAS_SetErrorCode( PAS_DriverNotFound );
+ return( NULL );
+ }
+
+ #if defined(__WATCOMC__) && defined(__FLAT__)
+ ptr = ( MVFunc * )( ( ( ( unsigned )regs.w.dx ) << 4 ) +
+ ( ( unsigned )regs.w.bx ) );
+ #else
+ ptr = MK_FP( regs.w.dx, regs.w.bx );
+ #endif
+
+ return( ptr );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_GetCardSettings
+
+ Returns the DMA and the IRQ channels of the sound card.
+---------------------------------------------------------------------*/
+
+int PAS_GetCardSettings
+ (
+ void
+ )
+
+ {
+ union REGS regs;
+ int status;
+
+ regs.w.ax = MV_GetDmaIrqInt;
+
+ #ifdef __386__
+ int386( MV_SoundInt, ®s, ®s );
+ #else
+ int86( MV_SoundInt, ®s, ®s );
+ #endif
+
+ if ( regs.w.ax != MV_Signature )
+ {
+ PAS_SetErrorCode( PAS_DriverNotFound );
+ return( PAS_Error );
+ }
+
+ PAS_DMAChannel = regs.w.bx;
+ PAS_Irq = regs.w.cx;
+
+ if ( PAS_Irq > PAS_MaxIrq )
+ {
+ PAS_SetErrorCode( PAS_Dos4gwIrqError );
+ return( PAS_Error );
+ }
+
+ if ( !VALID_IRQ( PAS_Irq ) )
+ {
+ PAS_SetErrorCode( PAS_InvalidIrq );
+ return( PAS_Error );
+ }
+
+ if ( PAS_Interrupts[ PAS_Irq ] == INVALID )
+ {
+ PAS_SetErrorCode( PAS_InvalidIrq );
+ return( PAS_Error );
+ }
+
+ status = DMA_VerifyChannel( PAS_DMAChannel );
+ if ( status == DMA_Error )
+ {
+ PAS_SetErrorCode( PAS_DmaError );
+ return( PAS_Error );
+ }
+
+ return( PAS_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_EnableInterrupt
+
+ Enables the triggering of the sound card interrupt.
+---------------------------------------------------------------------*/
+
+void PAS_EnableInterrupt
+ (
+ void
+ )
+
+ {
+ int mask;
+ int data;
+ unsigned flags;
+
+ flags = DisableInterrupts();
+
+ if ( PAS_Irq < 8 )
+ {
+ mask = inp( 0x21 ) & ~( 1 << PAS_Irq );
+ outp( 0x21, mask );
+ }
+ else
+ {
+ mask = inp( 0xA1 ) & ~( 1 << ( PAS_Irq - 8 ) );
+ outp( 0xA1, mask );
+
+ mask = inp( 0x21 ) & ~( 1 << 2 );
+ outp( 0x21, mask );
+ }
+
+ // Flush any pending interrupts
+ PAS_Write( InterruptStatus, PAS_Read( InterruptStatus ) & 0x40 );
+
+ // Enable the interrupt on the PAS
+ data = PAS_State->intrctlr;
+ data |= SampleBufferInterruptFlag;
+ PAS_Write( InterruptControl, data );
+ PAS_State->intrctlr = data;
+
+ RestoreInterrupts( flags );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_DisableInterrupt
+
+ Disables the triggering of the sound card interrupt.
+---------------------------------------------------------------------*/
+
+void PAS_DisableInterrupt
+ (
+ void
+ )
+
+ {
+ int mask;
+ int data;
+ unsigned flags;
+
+ flags = DisableInterrupts();
+
+ // Disable the interrupt on the PAS
+ data = PAS_State->intrctlr;
+ data &= ~( SampleRateInterruptFlag | SampleBufferInterruptFlag );
+ PAS_Write( InterruptControl, data );
+ PAS_State->intrctlr = data;
+
+ // Restore interrupt mask
+ if ( PAS_Irq < 8 )
+ {
+ mask = inp( 0x21 ) & ~( 1 << PAS_Irq );
+ mask |= PAS_IntController1Mask & ( 1 << PAS_Irq );
+ outp( 0x21, mask );
+ }
+ else
+ {
+ mask = inp( 0x21 ) & ~( 1 << 2 );
+ mask |= PAS_IntController1Mask & ( 1 << 2 );
+ outp( 0x21, mask );
+
+ mask = inp( 0xA1 ) & ~( 1 << ( PAS_Irq - 8 ) );
+ mask |= PAS_IntController2Mask & ( 1 << ( PAS_Irq - 8 ) );
+ outp( 0xA1, mask );
+ }
+
+ RestoreInterrupts( flags );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_ServiceInterrupt
+
+ Handles interrupt generated by sound card at the end of a voice
+ transfer. Calls the user supplied callback function.
+---------------------------------------------------------------------*/
+
+void interrupt far PAS_ServiceInterrupt
+ (
+ void
+ )
+
+ {
+ #ifdef USESTACK
+ // save stack
+ GetStack( &oldStackSelector, &oldStackPointer );
+
+ // set our stack
+ SetStack( StackSelector, StackPointer );
+ #endif
+
+ irqstatus = PAS_Read( InterruptStatus );
+ if ( ( irqstatus & SampleBufferInterruptFlag ) == 0 )
+ {
+ #ifdef USESTACK
+ // restore stack
+ SetStack( oldStackSelector, oldStackPointer );
+ #endif
+
+ _chain_intr( PAS_OldInt );
+ }
+
+ // Clear the interrupt
+ irqstatus &= ~SampleBufferInterruptFlag;
+ PAS_Write( InterruptStatus, irqstatus );
+
+ // send EOI to Interrupt Controller
+ if ( PAS_Irq > 7 )
+ {
+ outp( 0xA0, 0x20 );
+ }
+ outp( 0x20, 0x20 );
+
+
+ // Keep track of current buffer
+ PAS_CurrentDMABuffer += PAS_TransferLength;
+ if ( PAS_CurrentDMABuffer >= PAS_DMABufferEnd )
+ {
+ PAS_CurrentDMABuffer = PAS_DMABuffer;
+ }
+
+ // Call the caller's callback function
+ if ( PAS_CallBack != NULL )
+ {
+ PAS_CallBack();
+ }
+
+ #ifdef USESTACK
+ // restore stack
+ SetStack( oldStackSelector, oldStackPointer );
+ #endif
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_Write
+
+ Writes a byte of data to the sound card.
+---------------------------------------------------------------------*/
+
+void PAS_Write
+ (
+ int Register,
+ int Data
+ )
+
+ {
+ int port;
+
+ port = Register ^ PAS_TranslateCode;
+ outp( port, Data );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_Read
+
+ Reads a byte of data from the sound card.
+---------------------------------------------------------------------*/
+
+int PAS_Read
+ (
+ int Register
+ )
+
+ {
+ int port;
+ int data;
+
+ port = Register ^ PAS_TranslateCode;
+ data = inp( port );
+ return( data );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_SetSampleRateTimer
+
+ Programs the Sample Rate Timer.
+---------------------------------------------------------------------*/
+
+void PAS_SetSampleRateTimer
+ (
+ void
+ )
+
+ {
+ int LoByte;
+ int HiByte;
+ int data;
+ unsigned flags;
+
+ flags = DisableInterrupts();
+
+ // Disable the Sample Rate Timer
+ data = PAS_State->audiofilt;
+ data &= ~SampleRateTimerGateFlag;
+ PAS_Write( AudioFilterControl, data );
+ PAS_State->audiofilt = data;
+
+ // Select the Sample Rate Timer
+ data = SelectSampleRateTimer;
+ PAS_Write( LocalTimerControl, data );
+ PAS_State->tmrctlr = data;
+
+ LoByte = lobyte( PAS_TimeInterval );
+ HiByte = hibyte( PAS_TimeInterval );
+
+ // Program the Sample Rate Timer
+ PAS_Write( SampleRateTimer, LoByte );
+ PAS_Write( SampleRateTimer, HiByte );
+ PAS_State->samplerate = PAS_TimeInterval;
+
+ RestoreInterrupts( flags );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_SetSampleBufferCount
+
+ Programs the Sample Buffer Count.
+---------------------------------------------------------------------*/
+
+void PAS_SetSampleBufferCount
+ (
+ void
+ )
+
+ {
+ int LoByte;
+ int HiByte;
+ int count;
+ int data;
+ unsigned flags;
+
+ flags = DisableInterrupts();
+
+ // Disable the Sample Buffer Count
+ data = PAS_State->audiofilt;
+ data &= ~SampleBufferCountGateFlag;
+ PAS_Write( AudioFilterControl, data );
+ PAS_State->audiofilt = data;
+
+ // Select the Sample Buffer Count
+ data = SelectSampleBufferCount;
+ PAS_Write( LocalTimerControl, data );
+ PAS_State->tmrctlr = data;
+
+ count = PAS_TransferLength;
+
+ // Check if we're using a 16-bit DMA channel
+ if ( PAS_DMAChannel > 3 )
+ {
+ count >>= 1;
+ }
+
+ LoByte = lobyte( count );
+ HiByte = hibyte( count );
+
+ // Program the Sample Buffer Count
+ PAS_Write( SampleBufferCount, LoByte );
+ PAS_Write( SampleBufferCount, HiByte );
+ PAS_State->samplecnt = count;
+
+ RestoreInterrupts( flags );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_SetPlaybackRate
+
+ Sets the rate at which the digitized sound will be played in
+ hertz.
+---------------------------------------------------------------------*/
+
+void PAS_SetPlaybackRate
+ (
+ unsigned rate
+ )
+
+ {
+ if ( rate < PAS_MinSamplingRate )
+ {
+ rate = PAS_MinSamplingRate;
+ }
+
+ if ( rate > PAS_MaxSamplingRate )
+ {
+ rate = PAS_MaxSamplingRate;
+ }
+
+ PAS_TimeInterval = ( unsigned )CalcTimeInterval( rate );
+ if ( PAS_MixMode & STEREO )
+ {
+ PAS_TimeInterval /= 2;
+ }
+
+ // Keep track of what the actual rate is
+ PAS_SampleRate = CalcSamplingRate( PAS_TimeInterval );
+ if ( PAS_MixMode & STEREO )
+ {
+ PAS_SampleRate /= 2;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_GetPlaybackRate
+
+ Returns the rate at which the digitized sound will be played in
+ hertz.
+---------------------------------------------------------------------*/
+
+unsigned PAS_GetPlaybackRate
+ (
+ void
+ )
+
+ {
+ return( PAS_SampleRate );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_SetMixMode
+
+ Sets the sound card to play samples in mono or stereo.
+---------------------------------------------------------------------*/
+
+int PAS_SetMixMode
+ (
+ int mode
+ )
+
+ {
+ mode &= PAS_MaxMixMode;
+
+ // Check board revision. Revision # 0 can't play 16-bit data.
+ if ( ( PAS_State->intrctlr & 0xe0 ) == 0 )
+ {
+ // Force the mode to 8-bit data.
+ mode &= ~SIXTEEN_BIT;
+ }
+
+ PAS_MixMode = mode;
+
+ PAS_SetPlaybackRate( PAS_SampleRate );
+
+ return( mode );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_StopPlayback
+
+ Ends the DMA transfer of digitized sound to the sound card.
+---------------------------------------------------------------------*/
+
+void PAS_StopPlayback
+ (
+ void
+ )
+
+ {
+ int data;
+
+ // Don't allow anymore interrupts
+ PAS_DisableInterrupt();
+
+ // Stop the transfer of digital data
+ data = PAS_State->crosschannel;
+ data &= PAS_PCMStopMask;
+ PAS_Write( CrossChannelControl, data );
+ PAS_State->crosschannel = data;
+
+ // Turn off 16-bit unsigned data
+ data = PAS_Read( SampleSizeConfiguration );
+ data &= PAS_SampleSizeMask;
+ PAS_Write( SampleSizeConfiguration, data );
+
+ // Disable the DMA channel
+ DMA_EndTransfer( PAS_DMAChannel );
+
+ PAS_SoundPlaying = FALSE;
+
+ PAS_DMABuffer = NULL;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_SetupDMABuffer
+
+ Programs the DMAC for sound transfer.
+---------------------------------------------------------------------*/
+
+int PAS_SetupDMABuffer
+ (
+ char *BufferPtr,
+ int BufferSize,
+ int mode
+ )
+
+ {
+ int DmaStatus;
+ int data;
+
+ // Enable PAS Dma
+ data = PAS_State->crosschannel;
+ data |= PAS_DMAEnable;
+ PAS_Write( CrossChannelControl, data );
+ PAS_State->crosschannel = data;
+
+ DmaStatus = DMA_SetupTransfer( PAS_DMAChannel, BufferPtr, BufferSize, mode );
+ if ( DmaStatus == DMA_Error )
+ {
+ PAS_SetErrorCode( PAS_DmaError );
+ return( PAS_Error );
+ }
+
+ PAS_DMABuffer = BufferPtr;
+ PAS_CurrentDMABuffer = BufferPtr;
+ PAS_TotalDMABufferSize = BufferSize;
+ PAS_DMABufferEnd = BufferPtr + BufferSize;
+
+ return( PAS_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_GetCurrentPos
+
+ Returns the offset within the current sound being played.
+---------------------------------------------------------------------*/
+
+int PAS_GetCurrentPos
+ (
+ void
+ )
+
+ {
+ char *CurrentAddr;
+ int offset;
+
+ if ( !PAS_SoundPlaying )
+ {
+ PAS_SetErrorCode( PAS_NoSoundPlaying );
+ return( PAS_Error );
+ }
+
+ CurrentAddr = DMA_GetCurrentPos( PAS_DMAChannel );
+ if ( CurrentAddr == NULL )
+ {
+ PAS_SetErrorCode( PAS_DmaError );
+ return( PAS_Error );
+ }
+
+ offset = ( int )( ( ( unsigned long )CurrentAddr ) -
+ ( ( unsigned long )PAS_CurrentDMABuffer ) );
+
+ if ( PAS_MixMode & SIXTEEN_BIT )
+ {
+ offset >>= 1;
+ }
+
+ if ( PAS_MixMode & STEREO )
+ {
+ offset >>= 1;
+ }
+
+ return( offset );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_GetFilterSetting
+
+ Returns the bit settings for the appropriate filter level.
+---------------------------------------------------------------------*/
+
+int PAS_GetFilterSetting
+ (
+ int rate
+ )
+
+ {
+ /* CD Quality 17897hz */
+ if ( ( unsigned long )rate > ( unsigned long )17897L * 2 )
+ {
+ /* 00001b 20hz to 17.8khz */
+ return( 0x01 );
+ }
+
+ /* Cassette Quality 15090hz */
+ if ( ( unsigned long )rate > ( unsigned long )15909L * 2 )
+ {
+ /* 00010b 20hz to 15.9khz */
+ return( 0x02 );
+ }
+
+ /* FM Radio Quality 11931hz */
+ if ( ( unsigned long )rate > ( unsigned long )11931L * 2 )
+ {
+ /* 01001b 20hz to 11.9khz */
+ return( 0x09 );
+ }
+
+ /* AM Radio Quality 8948hz */
+ if ( ( unsigned long )rate > ( unsigned long )8948L * 2 )
+ {
+ /* 10001b 20hz to 8.9khz */
+ return( 0x11 );
+ }
+
+ /* Telphone Quality 5965hz */
+ if ( ( unsigned long )rate > ( unsigned long )5965L * 2 )
+ {
+ /* 00100b 20hz to 5.9khz */
+ return( 0x19 );
+ }
+
+ /* Male voice quality 2982hz */
+ /* 111001b 20hz to 2.9khz */
+ return( 0x04 );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_BeginTransfer
+
+ Starts playback of digitized sound on the sound card.
+---------------------------------------------------------------------*/
+
+void PAS_BeginTransfer
+ (
+ int mode
+ )
+
+ {
+ int data;
+
+ PAS_SetSampleRateTimer();
+
+ PAS_SetSampleBufferCount();
+
+ PAS_EnableInterrupt();
+
+ // Get sample size configuration
+ data = PAS_Read( SampleSizeConfiguration );
+
+ // Check board revision. Revision # 0 can't play 16-bit data.
+ if ( PAS_State->intrctlr & 0xe0 )
+ {
+ data &= PAS_SampleSizeMask;
+
+ // set sample size bit
+ if ( PAS_MixMode & SIXTEEN_BIT )
+ {
+ data |= PAS_16BitSampleFlag;
+ }
+ }
+
+ // set oversampling rate
+ data &= PAS_OverSamplingMask;
+ data |= PAS_4xOverSampling;
+
+ // Set sample size configuration
+ PAS_Write( SampleSizeConfiguration, data );
+
+ // Get Cross channel setting
+ data = PAS_State->crosschannel;
+ data &= PAS_ChannelConnectMask;
+ if ( mode == RECORD )
+ {
+ data |= PAS_PCMStartADC;
+ }
+ else
+ {
+ data |= PAS_PCMStartDAC;
+ }
+
+ // set stereo mode bit
+ if ( !( PAS_MixMode & STEREO ) )
+ {
+ data |= PAS_StereoFlag;
+ }
+
+ PAS_Write( CrossChannelControl, data );
+ PAS_State->crosschannel = data;
+
+ // Get the filter appropriate filter setting
+ data = PAS_GetFilterSetting( PAS_SampleRate );
+
+ // Enable the Sample Rate Timer and Sample Buffer Count
+ data |= SampleRateTimerGateFlag | SampleBufferCountGateFlag;
+
+ if ( mode != RECORD )
+ {
+ // Enable audio (not Audio Mute)
+ data |= PAS_AudioMuteFlag;
+ }
+
+ PAS_Write( AudioFilterControl, data );
+ PAS_State->audiofilt = data;
+
+ PAS_SoundPlaying = TRUE;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_BeginBufferedPlayback
+
+ Begins multibuffered playback of digitized sound on the sound card.
+---------------------------------------------------------------------*/
+
+int PAS_BeginBufferedPlayback
+ (
+ char *BufferStart,
+ int BufferSize,
+ int NumDivisions,
+ unsigned SampleRate,
+ int MixMode,
+ void ( *CallBackFunc )( void )
+ )
+
+ {
+ int DmaStatus;
+
+ PAS_StopPlayback();
+
+ PAS_SetMixMode( MixMode );
+ PAS_SetPlaybackRate( SampleRate );
+
+ PAS_TransferLength = BufferSize / NumDivisions;
+ PAS_SetCallBack( CallBackFunc );
+
+ DmaStatus = PAS_SetupDMABuffer( BufferStart, BufferSize, DMA_AutoInitRead );
+ if ( DmaStatus == PAS_Error )
+ {
+ return( PAS_Error );
+ }
+
+ PAS_BeginTransfer( PLAYBACK );
+
+ return( PAS_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_BeginBufferedRecord
+
+ Begins multibuffered recording of digitized sound on the sound card.
+---------------------------------------------------------------------*/
+
+int PAS_BeginBufferedRecord
+ (
+ char *BufferStart,
+ int BufferSize,
+ int NumDivisions,
+ unsigned SampleRate,
+ int MixMode,
+ void ( *CallBackFunc )( void )
+ )
+
+ {
+ int DmaStatus;
+
+ PAS_StopPlayback();
+
+ PAS_SetMixMode( MixMode );
+ PAS_SetPlaybackRate( SampleRate );
+
+ PAS_TransferLength = BufferSize / NumDivisions;
+ PAS_SetCallBack( CallBackFunc );
+
+ DmaStatus = PAS_SetupDMABuffer( BufferStart, BufferSize, DMA_AutoInitWrite );
+ if ( DmaStatus == PAS_Error )
+ {
+ return( PAS_Error );
+ }
+
+ PAS_BeginTransfer( RECORD );
+
+ return( PAS_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_CallInt
+
+ Calls interrupt 2fh.
+---------------------------------------------------------------------*/
+
+int PAS_CallInt( int ebx, int ecx, int edx );
+#pragma aux PAS_CallInt = \
+ "int 2fh", \
+ parm [ ebx ] [ ecx ] [ edx ] modify exact [ eax ebx ecx edx esi edi ] value [ ebx ];
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_CallMVFunction
+
+ Performs a call to a real mode function.
+---------------------------------------------------------------------*/
+
+int PAS_CallMVFunction
+ (
+ unsigned long function,
+ int ebx,
+ int ecx,
+ int edx
+ )
+
+ {
+ dpmi_regs callregs;
+ int status;
+
+ callregs.EBX = ebx;
+ callregs.ECX = ecx;
+ callregs.EDX = edx;
+
+ callregs.SS = 0;
+ callregs.SP = 0;
+
+ callregs.DS = 0;
+ callregs.ES = 0;
+ callregs.FS = 0;
+ callregs.GS = 0;
+
+ callregs.IP = function;
+ callregs.CS = function >> 16;
+
+ status = DPMI_CallRealModeFunction( &callregs );
+ if ( status != DPMI_Ok )
+ {
+ return( PAS_Error );
+ }
+
+ return( callregs.EBX & 0xff );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_SetPCMVolume
+
+ Sets the volume of digitized sound playback.
+---------------------------------------------------------------------*/
+
+int PAS_SetPCMVolume
+ (
+ int volume
+ )
+
+ {
+ int status;
+
+ volume = max( 0, volume );
+ volume = min( volume, 255 );
+
+ volume *= 100;
+ volume /= 255;
+
+ status = PAS_CallMVFunction( PAS_Func->SetMixer, volume,
+ OUTPUTMIXER, L_PCM );
+ if ( status == PAS_Error )
+ {
+ return( status );
+ }
+
+ status = PAS_CallMVFunction( PAS_Func->SetMixer, volume,
+ OUTPUTMIXER, R_PCM );
+ if ( status == PAS_Error )
+ {
+ return( status );
+ }
+
+ return( PAS_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_GetPCMVolume
+
+ Returns the current volume of digitized sound playback.
+---------------------------------------------------------------------*/
+
+int PAS_GetPCMVolume
+ (
+ void
+ )
+
+ {
+ int leftvolume;
+ int rightvolume;
+ int totalvolume;
+
+ if ( PAS_Func == NULL )
+ {
+ return( PAS_Error );
+ }
+
+ leftvolume = PAS_CallMVFunction( PAS_Func->GetMixer, 0,
+ OUTPUTMIXER, L_PCM );
+ rightvolume = PAS_CallMVFunction( PAS_Func->GetMixer, 0,
+ OUTPUTMIXER, R_PCM );
+
+ if ( ( leftvolume == PAS_Error ) || ( rightvolume == PAS_Error ) )
+ {
+ return( PAS_Error );
+ }
+
+ leftvolume &= 0xff;
+ rightvolume &= 0xff;
+
+ totalvolume = ( rightvolume + leftvolume ) / 2;
+ totalvolume *= 255;
+ totalvolume /= 100;
+ return( totalvolume );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_SetFMVolume
+
+ Sets the volume of FM sound playback.
+---------------------------------------------------------------------*/
+
+void PAS_SetFMVolume
+ (
+ int volume
+ )
+
+ {
+ volume = max( 0, volume );
+ volume = min( volume, 255 );
+
+ volume *= 100;
+ volume /= 255;
+ if ( PAS_Func )
+ {
+ PAS_CallMVFunction( PAS_Func->SetMixer, volume, OUTPUTMIXER, L_FM );
+ PAS_CallMVFunction( PAS_Func->SetMixer, volume, OUTPUTMIXER, R_FM );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_GetFMVolume
+
+ Returns the current volume of FM sound playback.
+---------------------------------------------------------------------*/
+
+int PAS_GetFMVolume
+ (
+ void
+ )
+
+ {
+ int leftvolume;
+ int rightvolume;
+ int totalvolume;
+
+ if ( PAS_Func == NULL )
+ {
+ return( 255 );
+ }
+
+ leftvolume = PAS_CallMVFunction( PAS_Func->GetMixer, 0,
+ OUTPUTMIXER, L_FM ) & 0xff;
+ rightvolume = PAS_CallMVFunction( PAS_Func->GetMixer, 0,
+ OUTPUTMIXER, R_FM ) & 0xff;
+
+ totalvolume = ( rightvolume + leftvolume ) / 2;
+ totalvolume *= 255;
+ totalvolume /= 100;
+ totalvolume = min( 255, totalvolume );
+
+ return( totalvolume );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_GetCardInfo
+
+ Returns the maximum number of bits that can represent a sample
+ (8 or 16) and the number of channels (1 for mono, 2 for stereo).
+---------------------------------------------------------------------*/
+
+int PAS_GetCardInfo
+ (
+ int *MaxSampleBits,
+ int *MaxChannels
+ )
+
+ {
+ int status;
+
+ if ( PAS_State == NULL )
+ {
+ status = PAS_CheckForDriver();
+ if ( status != PAS_Ok )
+ {
+ return( status );
+ }
+
+ PAS_State = PAS_GetStateTable();
+ if ( PAS_State == NULL )
+ {
+ return( PAS_Error );
+ }
+ }
+
+ *MaxChannels = 2;
+
+ // Check board revision. Revision # 0 can't play 16-bit data.
+ if ( ( PAS_State->intrctlr & 0xe0 ) == 0 )
+ {
+ *MaxSampleBits = 8;
+ }
+ else
+ {
+ *MaxSampleBits = 16;
+ }
+
+ return( PAS_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_SetCallBack
+
+ Specifies the user function to call at the end of a sound transfer.
+---------------------------------------------------------------------*/
+
+void PAS_SetCallBack
+ (
+ void ( *func )( void )
+ )
+
+ {
+ PAS_CallBack = func;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_FindCard
+
+ Auto-detects the port the Pro AudioSpectrum is set for.
+---------------------------------------------------------------------*/
+
+int PAS_FindCard
+ (
+ void
+ )
+
+ {
+ int status;
+
+ status = PAS_TestAddress( DEFAULT_BASE );
+ if ( status == 0 )
+ {
+ PAS_TranslateCode = DEFAULT_BASE;
+ return( PAS_Ok );
+ }
+
+ status = PAS_TestAddress( ALT_BASE_1 );
+ if ( status == 0 )
+ {
+ PAS_TranslateCode = ALT_BASE_1;
+ return( PAS_Ok );
+ }
+
+ status = PAS_TestAddress( ALT_BASE_2 );
+ if ( status == 0 )
+ {
+ PAS_TranslateCode = ALT_BASE_2;
+ return( PAS_Ok );
+ }
+
+ status = PAS_TestAddress( ALT_BASE_3 );
+ if ( status == 0 )
+ {
+ PAS_TranslateCode = ALT_BASE_3;
+ return( PAS_Ok );
+ }
+
+ PAS_SetErrorCode( PAS_CardNotFound );
+ return( PAS_Error );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_SaveMusicVolume
+
+ Saves the user's FM mixer settings.
+---------------------------------------------------------------------*/
+
+int PAS_SaveMusicVolume
+ (
+ void
+ )
+
+ {
+ int status;
+ int data;
+
+ if ( !PAS_Installed )
+ {
+ status = PAS_CheckForDriver();
+ if ( status != PAS_Ok )
+ {
+ return( status );
+ }
+
+ PAS_State = PAS_GetStateTable();
+ if ( PAS_State == NULL )
+ {
+ return( PAS_Error );
+ }
+
+ PAS_Func = PAS_GetFunctionTable();
+ if ( PAS_Func == NULL )
+ {
+ return( PAS_Error );
+ }
+
+ status = PAS_GetCardSettings();
+ if ( status != PAS_Ok )
+ {
+ return( status );
+ }
+
+ status = PAS_FindCard();
+ if ( status != PAS_Ok )
+ {
+ return( status );
+ }
+
+ // Enable PAS Sound
+ data = PAS_State->audiofilt;
+ data |= PAS_AudioMuteFlag;
+
+ PAS_Write( AudioFilterControl, data );
+ PAS_State->audiofilt = data;
+ }
+
+ status = PAS_CallMVFunction( PAS_Func->GetMixer, 0, OUTPUTMIXER, L_FM );
+ if ( status != PAS_Error )
+ {
+ PAS_OriginalFMLeftVolume = PAS_CallMVFunction( PAS_Func->GetMixer,
+ 0, OUTPUTMIXER, L_FM ) & 0xff;
+
+ PAS_OriginalFMRightVolume = PAS_CallMVFunction( PAS_Func->GetMixer,
+ 0, OUTPUTMIXER, R_FM ) & 0xff;
+
+ return( PAS_Ok );
+ }
+
+ return( PAS_Warning );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_RestoreMusicVolume
+
+ Restores the user's FM mixer settings.
+---------------------------------------------------------------------*/
+
+void PAS_RestoreMusicVolume
+ (
+ void
+ )
+
+ {
+ if ( PAS_Func )
+ {
+ PAS_CallMVFunction( PAS_Func->SetMixer, PAS_OriginalFMLeftVolume,
+ OUTPUTMIXER, L_FM );
+ PAS_CallMVFunction( PAS_Func->SetMixer, PAS_OriginalFMRightVolume,
+ OUTPUTMIXER, R_FM );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_SaveState
+
+ Saves the original state of the PAS prior to use.
+---------------------------------------------------------------------*/
+
+void PAS_SaveState
+ (
+ void
+ )
+
+ {
+ PAS_OriginalState.intrctlr = PAS_State->intrctlr;
+ PAS_OriginalState.audiofilt = PAS_State->audiofilt;
+ PAS_OriginalState.tmrctlr = PAS_State->tmrctlr;
+ PAS_OriginalState.samplerate = PAS_State->samplerate;
+ PAS_OriginalState.samplecnt = PAS_State->samplecnt;
+ PAS_OriginalState.crosschannel = PAS_State->crosschannel;
+ PAS_SampleSizeConfig = PAS_Read( SampleSizeConfiguration );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_RestoreState
+
+ Restores the original state of the PAS after use.
+---------------------------------------------------------------------*/
+
+void PAS_RestoreState
+ (
+ void
+ )
+
+ {
+ int LoByte;
+ int HiByte;
+
+ // Select the Sample Rate Timer
+ PAS_Write( LocalTimerControl, SelectSampleRateTimer );
+ PAS_State->tmrctlr = SelectSampleRateTimer;
+
+ PAS_Write( SampleRateTimer, PAS_OriginalState.samplerate );
+ PAS_State->samplerate = PAS_OriginalState.samplerate;
+
+ // Select the Sample Buffer Count
+ PAS_Write( LocalTimerControl, SelectSampleBufferCount );
+ PAS_State->tmrctlr = SelectSampleBufferCount;
+
+ LoByte = lobyte( PAS_OriginalState.samplecnt );
+ HiByte = hibyte( PAS_OriginalState.samplecnt );
+ PAS_Write( SampleRateTimer, LoByte );
+ PAS_Write( SampleRateTimer, HiByte );
+ PAS_State->samplecnt = PAS_OriginalState.samplecnt;
+
+ PAS_Write( CrossChannelControl, PAS_OriginalState.crosschannel );
+ PAS_State->crosschannel = PAS_OriginalState.crosschannel;
+
+ PAS_Write( SampleSizeConfiguration, PAS_SampleSizeConfig );
+
+ PAS_Write( InterruptControl, PAS_OriginalState.intrctlr );
+ PAS_State->intrctlr = PAS_OriginalState.intrctlr;
+
+ PAS_Write( AudioFilterControl, PAS_OriginalState.audiofilt );
+ PAS_State->audiofilt = PAS_OriginalState.audiofilt;
+
+ PAS_Write( LocalTimerControl, PAS_OriginalState.tmrctlr );
+ PAS_State->tmrctlr = PAS_OriginalState.tmrctlr;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_LockEnd
+
+ Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void PAS_LockEnd
+ (
+ void
+ )
+
+ {
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: allocateTimerStack
+
+ Allocate a block of memory from conventional (low) memory and return
+ the selector (which can go directly into a segment register) of the
+ memory block or 0 if an error occured.
+---------------------------------------------------------------------*/
+
+static unsigned short allocateTimerStack
+ (
+ unsigned short size
+ )
+
+ {
+ union REGS regs;
+
+ // clear all registers
+ memset( ®s, 0, sizeof( regs ) );
+
+ // DPMI allocate conventional memory
+ regs.w.ax = 0x100;
+
+ // size in paragraphs
+ regs.w.bx = ( size + 15 ) / 16;
+
+ int386( 0x31, ®s, ®s );
+ if (!regs.w.cflag)
+ {
+ // DPMI call returns selector in dx
+ // (ax contains real mode segment
+ // which is ignored here)
+
+ return( regs.w.dx );
+ }
+
+ // Couldn't allocate memory.
+ return( NULL );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: deallocateTimerStack
+
+ Deallocate a block of conventional (low) memory given a selector to
+ it. Assumes the block was allocated with DPMI function 0x100.
+---------------------------------------------------------------------*/
+
+static void deallocateTimerStack
+ (
+ unsigned short selector
+ )
+
+ {
+ union REGS regs;
+
+ if ( selector != NULL )
+ {
+ // clear all registers
+ memset( ®s, 0, sizeof( regs ) );
+
+ regs.w.ax = 0x101;
+ regs.w.dx = selector;
+ int386( 0x31, ®s, ®s );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_Init
+
+ Initializes the sound card and prepares the module to play
+ digitized sounds.
+---------------------------------------------------------------------*/
+
+int PAS_Init
+ (
+ void
+ )
+
+ {
+ int Interrupt;
+ int status;
+ int data;
+
+ if ( PAS_Installed )
+ {
+ return( PAS_Ok );
+ }
+
+ PAS_IntController1Mask = inp( 0x21 );
+ PAS_IntController2Mask = inp( 0xA1 );
+
+ status = PAS_CheckForDriver();
+ if ( status != PAS_Ok )
+ {
+ return( status );
+ }
+
+ PAS_State = PAS_GetStateTable();
+ if ( PAS_State == NULL )
+ {
+ return( PAS_Error );
+ }
+
+ PAS_Func = PAS_GetFunctionTable();
+ if ( PAS_Func == NULL )
+ {
+ return( PAS_Error );
+ }
+
+ status = PAS_GetCardSettings();
+ if ( status != PAS_Ok )
+ {
+ return( status );
+ }
+
+ status = PAS_FindCard();
+ if ( status != PAS_Ok )
+ {
+ return( status );
+ }
+
+ PAS_SaveState();
+
+ PAS_OriginalPCMLeftVolume = PAS_CallMVFunction( PAS_Func->GetMixer, 0,
+ OUTPUTMIXER, L_PCM ) & 0xff;
+ PAS_OriginalPCMRightVolume = PAS_CallMVFunction( PAS_Func->GetMixer, 0,
+ OUTPUTMIXER, R_PCM ) & 0xff;
+
+ PAS_SoundPlaying = FALSE;
+
+ PAS_SetCallBack( NULL );
+
+ PAS_DMABuffer = NULL;
+
+ status = PAS_LockMemory();
+ if ( status != PAS_Ok )
+ {
+ PAS_UnlockMemory();
+ return( status );
+ }
+
+ StackSelector = allocateTimerStack( kStackSize );
+ if ( StackSelector == NULL )
+ {
+ PAS_UnlockMemory();
+ PAS_SetErrorCode( PAS_OutOfMemory );
+ return( PAS_Error );
+ }
+
+ // Leave a little room at top of stack just for the hell of it...
+ StackPointer = kStackSize - sizeof( long );
+
+ // Install our interrupt handler
+ Interrupt = PAS_Interrupts[ PAS_Irq ];
+ PAS_OldInt = _dos_getvect( Interrupt );
+ if ( PAS_Irq < 8 )
+ {
+ _dos_setvect( Interrupt, PAS_ServiceInterrupt );
+ }
+ else
+ {
+ status = IRQ_SetVector( Interrupt, PAS_ServiceInterrupt );
+ if ( status != IRQ_Ok )
+ {
+ PAS_UnlockMemory();
+ deallocateTimerStack( StackSelector );
+ StackSelector = NULL;
+ PAS_SetErrorCode( PAS_UnableToSetIrq );
+ return( PAS_Error );
+ }
+ }
+
+ // Enable PAS Sound
+ data = PAS_State->audiofilt;
+ data |= PAS_AudioMuteFlag;
+
+ PAS_Write( AudioFilterControl, data );
+ PAS_State->audiofilt = data;
+
+ PAS_SetPlaybackRate( PAS_DefaultSampleRate );
+ PAS_SetMixMode( PAS_DefaultMixMode );
+
+ PAS_Installed = TRUE;
+
+ PAS_SetErrorCode( PAS_Ok );
+ return( PAS_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_Shutdown
+
+ Ends transfer of sound data to the sound card and restores the
+ system resources used by the card.
+---------------------------------------------------------------------*/
+
+void PAS_Shutdown
+ (
+ void
+ )
+
+ {
+ int Interrupt;
+
+ if ( PAS_Installed )
+ {
+ // Halt the DMA transfer
+ PAS_StopPlayback();
+
+ // Restore the original interrupt
+ Interrupt = PAS_Interrupts[ PAS_Irq ];
+ if ( PAS_Irq >= 8 )
+ {
+ IRQ_RestoreVector( Interrupt );
+ }
+ _dos_setvect( Interrupt, PAS_OldInt );
+
+ PAS_SoundPlaying = FALSE;
+
+ PAS_DMABuffer = NULL;
+
+ PAS_SetCallBack( NULL );
+
+ PAS_CallMVFunction( PAS_Func->SetMixer, PAS_OriginalPCMLeftVolume,
+ OUTPUTMIXER, L_PCM );
+ PAS_CallMVFunction( PAS_Func->SetMixer, PAS_OriginalPCMRightVolume,
+ OUTPUTMIXER, R_PCM );
+
+// DEBUG
+// PAS_RestoreState();
+
+ PAS_UnlockMemory();
+
+ deallocateTimerStack( StackSelector );
+ StackSelector = NULL;
+
+ PAS_Installed = FALSE;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_UnlockMemory
+
+ Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+void PAS_UnlockMemory
+ (
+ void
+ )
+
+ {
+ DPMI_UnlockMemoryRegion( PAS_LockStart, PAS_LockEnd );
+ DPMI_Unlock( PAS_Interrupts );
+ DPMI_Unlock( PAS_OldInt );
+ DPMI_Unlock( PAS_IntController1Mask );
+ DPMI_Unlock( PAS_IntController2Mask );
+ DPMI_Unlock( PAS_Installed );
+ DPMI_Unlock( PAS_TranslateCode );
+ DPMI_Unlock( PAS_OriginalPCMLeftVolume );
+ DPMI_Unlock( PAS_OriginalPCMRightVolume );
+ DPMI_Unlock( PAS_OriginalFMLeftVolume );
+ DPMI_Unlock( PAS_OriginalFMRightVolume );
+ DPMI_Unlock( PAS_DMAChannel );
+ DPMI_Unlock( PAS_Irq );
+ DPMI_Unlock( PAS_State );
+ DPMI_Unlock( PAS_Func );
+ DPMI_Unlock( PAS_OriginalState );
+ DPMI_Unlock( PAS_SampleSizeConfig );
+ DPMI_Unlock( PAS_DMABuffer );
+ DPMI_Unlock( PAS_DMABufferEnd );
+ DPMI_Unlock( PAS_CurrentDMABuffer );
+ DPMI_Unlock( PAS_TotalDMABufferSize );
+ DPMI_Unlock( PAS_TransferLength );
+ DPMI_Unlock( PAS_MixMode );
+ DPMI_Unlock( PAS_SampleRate );
+ DPMI_Unlock( PAS_TimeInterval );
+ DPMI_Unlock( PAS_SoundPlaying );
+ DPMI_Unlock( PAS_CallBack );
+ DPMI_Unlock( PAS_ErrorCode );
+ DPMI_Unlock( irqstatus );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PAS_LockMemory
+
+ Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+int PAS_LockMemory
+ (
+ void
+ )
+
+ {
+ int status;
+
+ status = DPMI_LockMemoryRegion( PAS_LockStart, PAS_LockEnd );
+ status |= DPMI_Lock( PAS_Interrupts );
+ status |= DPMI_Lock( PAS_OldInt );
+ status |= DPMI_Lock( PAS_IntController1Mask );
+ status |= DPMI_Lock( PAS_IntController2Mask );
+ status |= DPMI_Lock( PAS_Installed );
+ status |= DPMI_Lock( PAS_TranslateCode );
+ status |= DPMI_Lock( PAS_OriginalPCMLeftVolume );
+ status |= DPMI_Lock( PAS_OriginalPCMRightVolume );
+ status |= DPMI_Lock( PAS_OriginalFMLeftVolume );
+ status |= DPMI_Lock( PAS_OriginalFMRightVolume );
+ status |= DPMI_Lock( PAS_DMAChannel );
+ status |= DPMI_Lock( PAS_Irq );
+ status |= DPMI_Lock( PAS_State );
+ status |= DPMI_Lock( PAS_Func );
+ status |= DPMI_Lock( PAS_OriginalState );
+ status |= DPMI_Lock( PAS_SampleSizeConfig );
+ status |= DPMI_Lock( PAS_DMABuffer );
+ status |= DPMI_Lock( PAS_DMABufferEnd );
+ status |= DPMI_Lock( PAS_CurrentDMABuffer );
+ status |= DPMI_Lock( PAS_TotalDMABufferSize );
+ status |= DPMI_Lock( PAS_TransferLength );
+ status |= DPMI_Lock( PAS_MixMode );
+ status |= DPMI_Lock( PAS_SampleRate );
+ status |= DPMI_Lock( PAS_TimeInterval );
+ status |= DPMI_Lock( PAS_SoundPlaying );
+ status |= DPMI_Lock( PAS_CallBack );
+ status |= DPMI_Lock( PAS_ErrorCode );
+ status |= DPMI_Lock( irqstatus );
+
+ if ( status != DPMI_Ok )
+ {
+ PAS_UnlockMemory();
+ PAS_SetErrorCode( PAS_DPMI_Error );
+ return( PAS_Error );
+ }
+
+ return( PAS_Ok );
+ }
--- /dev/null
+++ b/rott/audiolib/pas16.h
@@ -1,0 +1,81 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: PAS16.H
+
+ author: James R. Dose
+ date: March 27, 1994
+
+ Public header for for PAS16.C
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __PAS16_H
+#define __PAS16_H
+
+enum PAS_ERRORS
+ {
+ PAS_Warning = -2,
+ PAS_Error = -1,
+ PAS_Ok = 0,
+ PAS_DriverNotFound,
+ PAS_DmaError,
+ PAS_InvalidIrq,
+ PAS_UnableToSetIrq,
+ PAS_Dos4gwIrqError,
+ PAS_NoSoundPlaying,
+ PAS_CardNotFound,
+ PAS_DPMI_Error,
+ PAS_OutOfMemory
+ };
+
+#define PAS_MaxMixMode STEREO_16BIT
+#define PAS_DefaultSampleRate 11000
+#define PAS_DefaultMixMode MONO_8BIT
+#define PAS_MaxIrq 15
+
+#define PAS_MinSamplingRate 4000
+#define PAS_MaxSamplingRate 44000
+
+extern unsigned int PAS_DMAChannel;
+
+char *PAS_ErrorString( int ErrorNumber );
+void PAS_SetPlaybackRate( unsigned rate );
+unsigned PAS_GetPlaybackRate( void );
+int PAS_SetMixMode( int mode );
+void PAS_StopPlayback( void );
+int PAS_GetCurrentPos( void );
+int PAS_BeginBufferedPlayback( char *BufferStart, int BufferSize, int NumDivisions, unsigned SampleRate, int MixMode, void ( *CallBackFunc )( void ) );
+int PAS_BeginBufferedRecord( char *BufferStart, int BufferSize, int NumDivisions, unsigned SampleRate, int MixMode, void ( *CallBackFunc )( void ) );
+int PAS_SetPCMVolume( int volume );
+int PAS_GetPCMVolume( void );
+void PAS_SetFMVolume( int volume );
+int PAS_GetFMVolume( void );
+int PAS_GetCardInfo( int *MaxSampleBits, int *MaxChannels );
+void PAS_SetCallBack( void ( *func )( void ) );
+int PAS_SaveMusicVolume( void );
+void PAS_RestoreMusicVolume( void );
+int PAS_Init( void );
+void PAS_Shutdown( void );
+void PAS_UnlockMemory( void );
+int PAS_LockMemory( void );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/pitch.c
@@ -1,0 +1,258 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: PITCH.C
+
+ author: James R. Dose
+ date: June 14, 1993
+
+ Routines for pitch scaling.
+
+ (c) Copyright 1993 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#include <stdlib.h>
+//#include <math.h>
+#include "dpmi.h"
+#include "standard.h"
+#include "pitch.h"
+
+#define MAXDETUNE 25
+
+static unsigned long PitchTable[ 12 ][ MAXDETUNE ] =
+ {
+ { 0x10000, 0x10097, 0x1012f, 0x101c7, 0x10260, 0x102f9, 0x10392, 0x1042c,
+ 0x104c6, 0x10561, 0x105fb, 0x10696, 0x10732, 0x107ce, 0x1086a, 0x10907,
+ 0x109a4, 0x10a41, 0x10adf, 0x10b7d, 0x10c1b, 0x10cba, 0x10d59, 0x10df8,
+ 0x10e98 },
+ { 0x10f38, 0x10fd9, 0x1107a, 0x1111b, 0x111bd, 0x1125f, 0x11302, 0x113a5,
+ 0x11448, 0x114eb, 0x1158f, 0x11634, 0x116d8, 0x1177e, 0x11823, 0x118c9,
+ 0x1196f, 0x11a16, 0x11abd, 0x11b64, 0x11c0c, 0x11cb4, 0x11d5d, 0x11e06,
+ 0x11eaf },
+ { 0x11f59, 0x12003, 0x120ae, 0x12159, 0x12204, 0x122b0, 0x1235c, 0x12409,
+ 0x124b6, 0x12563, 0x12611, 0x126bf, 0x1276d, 0x1281c, 0x128cc, 0x1297b,
+ 0x12a2b, 0x12adc, 0x12b8d, 0x12c3e, 0x12cf0, 0x12da2, 0x12e55, 0x12f08,
+ 0x12fbc },
+ { 0x1306f, 0x13124, 0x131d8, 0x1328d, 0x13343, 0x133f9, 0x134af, 0x13566,
+ 0x1361d, 0x136d5, 0x1378d, 0x13846, 0x138fe, 0x139b8, 0x13a72, 0x13b2c,
+ 0x13be6, 0x13ca1, 0x13d5d, 0x13e19, 0x13ed5, 0x13f92, 0x1404f, 0x1410d,
+ 0x141cb },
+ { 0x1428a, 0x14349, 0x14408, 0x144c8, 0x14588, 0x14649, 0x1470a, 0x147cc,
+ 0x1488e, 0x14951, 0x14a14, 0x14ad7, 0x14b9b, 0x14c5f, 0x14d24, 0x14dea,
+ 0x14eaf, 0x14f75, 0x1503c, 0x15103, 0x151cb, 0x15293, 0x1535b, 0x15424,
+ 0x154ee },
+ { 0x155b8, 0x15682, 0x1574d, 0x15818, 0x158e4, 0x159b0, 0x15a7d, 0x15b4a,
+ 0x15c18, 0x15ce6, 0x15db4, 0x15e83, 0x15f53, 0x16023, 0x160f4, 0x161c5,
+ 0x16296, 0x16368, 0x1643a, 0x1650d, 0x165e1, 0x166b5, 0x16789, 0x1685e,
+ 0x16934 },
+ { 0x16a09, 0x16ae0, 0x16bb7, 0x16c8e, 0x16d66, 0x16e3e, 0x16f17, 0x16ff1,
+ 0x170ca, 0x171a5, 0x17280, 0x1735b, 0x17437, 0x17513, 0x175f0, 0x176ce,
+ 0x177ac, 0x1788a, 0x17969, 0x17a49, 0x17b29, 0x17c09, 0x17cea, 0x17dcc,
+ 0x17eae },
+ { 0x17f91, 0x18074, 0x18157, 0x1823c, 0x18320, 0x18406, 0x184eb, 0x185d2,
+ 0x186b8, 0x187a0, 0x18888, 0x18970, 0x18a59, 0x18b43, 0x18c2d, 0x18d17,
+ 0x18e02, 0x18eee, 0x18fda, 0x190c7, 0x191b5, 0x192a2, 0x19391, 0x19480,
+ 0x1956f },
+ { 0x1965f, 0x19750, 0x19841, 0x19933, 0x19a25, 0x19b18, 0x19c0c, 0x19d00,
+ 0x19df4, 0x19ee9, 0x19fdf, 0x1a0d5, 0x1a1cc, 0x1a2c4, 0x1a3bc, 0x1a4b4,
+ 0x1a5ad, 0x1a6a7, 0x1a7a1, 0x1a89c, 0x1a998, 0x1aa94, 0x1ab90, 0x1ac8d,
+ 0x1ad8b },
+ { 0x1ae89, 0x1af88, 0x1b088, 0x1b188, 0x1b289, 0x1b38a, 0x1b48c, 0x1b58f,
+ 0x1b692, 0x1b795, 0x1b89a, 0x1b99f, 0x1baa4, 0x1bbaa, 0x1bcb1, 0x1bdb8,
+ 0x1bec0, 0x1bfc9, 0x1c0d2, 0x1c1dc, 0x1c2e6, 0x1c3f1, 0x1c4fd, 0x1c609,
+ 0x1c716 },
+ { 0x1c823, 0x1c931, 0x1ca40, 0x1cb50, 0x1cc60, 0x1cd70, 0x1ce81, 0x1cf93,
+ 0x1d0a6, 0x1d1b9, 0x1d2cd, 0x1d3e1, 0x1d4f6, 0x1d60c, 0x1d722, 0x1d839,
+ 0x1d951, 0x1da69, 0x1db82, 0x1dc9c, 0x1ddb6, 0x1ded1, 0x1dfec, 0x1e109,
+ 0x1e225 },
+ { 0x1e343, 0x1e461, 0x1e580, 0x1e6a0, 0x1e7c0, 0x1e8e0, 0x1ea02, 0x1eb24,
+ 0x1ec47, 0x1ed6b, 0x1ee8f, 0x1efb4, 0x1f0d9, 0x1f1ff, 0x1f326, 0x1f44e,
+ 0x1f576, 0x1f69f, 0x1f7c9, 0x1f8f3, 0x1fa1e, 0x1fb4a, 0x1fc76, 0x1fda3,
+ 0x1fed1 }
+ };
+
+
+//static int PITCH_Installed = FALSE;
+
+
+/*---------------------------------------------------------------------
+ Function: PITCH_Init
+
+ Initializes pitch table.
+---------------------------------------------------------------------*/
+/*
+void PITCH_Init
+ (
+ void
+ )
+
+ {
+ int note;
+ int detune;
+
+ if ( !PITCH_Installed )
+ {
+ for( note = 0; note < 12; note++ )
+ {
+ for( detune = 0; detune < MAXDETUNE; detune++ )
+ {
+ PitchTable[ note ][ detune ] = 0x10000 *
+ pow( 2, ( note * MAXDETUNE + detune ) / ( 12.0 * MAXDETUNE ) );
+ }
+ }
+
+ PITCH_Installed = TRUE;
+ }
+ }
+*/
+
+/**********************************************************************
+
+ Memory locked functions:
+
+**********************************************************************/
+
+
+#define PITCH_LockStart PITCH_GetScale
+
+
+/*---------------------------------------------------------------------
+ Function: PITCH_GetScale
+
+ Returns a fixed-point value to scale number the specified amount.
+---------------------------------------------------------------------*/
+
+unsigned long PITCH_GetScale
+ (
+ int pitchoffset
+ )
+
+ {
+ unsigned long scale;
+ int octaveshift;
+ int noteshift;
+ int note;
+ int detune;
+
+// if ( !PITCH_Installed )
+// {
+// PITCH_Init();
+// }
+
+ if ( pitchoffset == 0 )
+ {
+ return( PitchTable[ 0 ][ 0 ] );
+ }
+
+ noteshift = pitchoffset % 1200;
+ if ( noteshift < 0 )
+ {
+ noteshift += 1200;
+ }
+
+ note = noteshift / 100;
+ detune = ( noteshift % 100 ) / ( 100 / MAXDETUNE );
+ octaveshift = ( pitchoffset - noteshift ) / 1200;
+
+ if ( detune < 0 )
+ {
+ detune += ( 100 / MAXDETUNE );
+ note--;
+ if ( note < 0 )
+ {
+ note += 12;
+ octaveshift--;
+ }
+ }
+
+ scale = PitchTable[ note ][ detune ];
+
+ if ( octaveshift < 0 )
+ {
+ scale >>= -octaveshift;
+ }
+ else
+ {
+ scale <<= octaveshift;
+ }
+
+ return( scale );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PITCH_LockEnd
+
+ Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void PITCH_LockEnd
+ (
+ void
+ )
+
+ {
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PITCH_UnlockMemory
+
+ Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+void PITCH_UnlockMemory
+ (
+ void
+ )
+
+ {
+ DPMI_UnlockMemoryRegion( PITCH_LockStart, PITCH_LockEnd );
+ DPMI_Unlock( PitchTable );
+// DPMI_Unlock( PITCH_Installed );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: PITCH_LockMemory
+
+ Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+int PITCH_LockMemory
+ (
+ void
+ )
+
+ {
+ int status;
+
+ status = DPMI_LockMemoryRegion( PITCH_LockStart, PITCH_LockEnd );
+ status |= DPMI_Lock( PitchTable );
+// status |= DPMI_Lock( PITCH_Installed );
+
+ if ( status != DPMI_Ok )
+ {
+ PITCH_UnlockMemory();
+ return( PITCH_Error );
+ }
+
+ return( PITCH_Ok );
+ }
--- /dev/null
+++ b/rott/audiolib/pitch.h
@@ -1,0 +1,45 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: PITCH.H
+
+ author: James R. Dose
+ date: June 14, 1994
+
+ Public header for PITCH.C
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __PITCH_H
+#define __PITCH_H
+
+enum PITCH_ERRORS
+ {
+ PITCH_Warning = -2,
+ PITCH_Error = -1,
+ PITCH_Ok = 0,
+ };
+
+//void PITCH_Init( void );
+unsigned long PITCH_GetScale( int pitchoffset );
+void PITCH_UnlockMemory( void );
+int PITCH_LockMemory( void );
+#endif
--- /dev/null
+++ b/rott/audiolib/platform.h
@@ -1,0 +1,77 @@
+#ifndef _INCLUDE_PLATFORM_H_
+#define _INCLUDE_PLATFORM_H_
+
+/* this file originally from buildengine */
+#ifdef BUILDENGINE
+
+#if (defined PLATFORM_WIN32)
+#include "win32_compat.h"
+#elif (defined PLATFORM_UNIX)
+#include "unix_compat.h"
+#elif (defined PLATFORM_DOS)
+#include "doscmpat.h"
+#else
+#error Define your platform!
+#endif
+
+#if (!defined __EXPORT__)
+#define __EXPORT__
+#endif
+
+#if ((defined PLATFORM_SUPPORTS_SDL) && (!defined PLATFORM_TIMER_HZ))
+#define PLATFORM_TIMER_HZ 100
+#endif
+
+#if (!defined PLATFORM_TIMER_HZ)
+#error You need to define PLATFORM_TIMER_HZ for your platform.
+#endif
+
+#if (defined __WATCOMC__)
+#define snprintf _snprintf
+#endif
+
+#endif
+
+static __inline unsigned short _swap16(unsigned short D)
+{
+#if PLATFORM_MACOSX
+ register unsigned short returnValue;
+ __asm__ volatile("lhbrx %0,0,%1"
+ : "=r" (returnValue)
+ : "r" (&D)
+ );
+ return returnValue;
+#else
+ return((D<<8)|(D>>8));
+#endif
+}
+
+static __inline unsigned int _swap32(unsigned int D)
+{
+#if PLATFORM_MACOSX
+ register unsigned int returnValue;
+ __asm__ volatile("lwbrx %0,0,%1"
+ : "=r" (returnValue)
+ : "r" (&D)
+ );
+ return returnValue;
+#else
+ return((D<<24)|((D<<8)&0x00FF0000)|((D>>8)&0x0000FF00)|(D>>24));
+#endif
+}
+
+#if PLATFORM_MACOSX
+#define PLATFORM_BIGENDIAN 1
+#define BUILDSWAP_INTEL16(x) _swap16(x)
+#define BUILDSWAP_INTEL32(x) _swap32(x)
+#else
+#define PLATFORM_LITTLEENDIAN 1
+#define BUILDSWAP_INTEL16(x) (x)
+#define BUILDSWAP_INTEL32(x) (x)
+#endif
+
+#endif /* !defined _INCLUDE_PLATFORM_H_ */
+
+/* end of platform.h ... */
+
+
--- /dev/null
+++ b/rott/audiolib/sndcards.h
@@ -1,0 +1,55 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: SNDCARDS.H
+
+ author: James R. Dose
+ date: March 31, 1994
+
+ Contains enumerated type definitions for sound cards.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __SNDCARDS_H
+#define __SNDCARDS_H
+
+#define ASS_VERSION_STRING "1.12"
+
+typedef enum
+ {
+// ASS_NoSound,
+ SoundBlaster,
+ ProAudioSpectrum,
+ SoundMan16,
+ Adlib,
+ GenMidi,
+ SoundCanvas,
+ Awe32,
+ WaveBlaster,
+ SoundScape,
+ UltraSound,
+ SoundSource,
+ TandySoundSource,
+ PC,
+ NumSoundCards
+ } soundcardnames;
+
+#endif
--- /dev/null
+++ b/rott/audiolib/sndscape.c
@@ -1,0 +1,1661 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: SNDSCAPE.C
+
+ author: James R. Dose
+ date: October 25, 1994
+
+ Low level routines to support the Ensoniq Soundscape.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#include <dos.h>
+#include <conio.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include "interrup.h"
+#include "dpmi.h"
+#include "dma.h"
+#include "irq.h"
+#include "sndscape.h"
+#include "_sndscap.h"
+
+const int SOUNDSCAPE_Interrupts[ SOUNDSCAPE_MaxIrq + 1 ] =
+ {
+ INVALID, INVALID, 0xa, INVALID,
+ INVALID, 0xd, INVALID, 0xf,
+ INVALID, INVALID, 0x72, INVALID,
+ INVALID, INVALID, INVALID, INVALID
+ };
+
+const int SOUNDSCAPE_SampleSize[ SOUNDSCAPE_MaxMixMode + 1 ] =
+ {
+ MONO_8BIT_SAMPLE_SIZE, STEREO_8BIT_SAMPLE_SIZE,
+ MONO_16BIT_SAMPLE_SIZE, STEREO_16BIT_SAMPLE_SIZE
+ };
+
+static void ( __interrupt __far *SOUNDSCAPE_OldInt )( void );
+
+static int SOUNDSCAPE_Installed = FALSE;
+static int SOUNDSCAPE_FoundCard = FALSE;
+
+static char *SOUNDSCAPE_DMABuffer;
+static char *SOUNDSCAPE_DMABufferEnd;
+static char *SOUNDSCAPE_CurrentDMABuffer;
+static int SOUNDSCAPE_TotalDMABufferSize;
+
+static int SOUNDSCAPE_TransferLength = 0;
+static int SOUNDSCAPE_MixMode = SOUNDSCAPE_DefaultMixMode;
+static int SOUNDSCAPE_SamplePacketSize = MONO_16BIT_SAMPLE_SIZE;
+static unsigned SOUNDSCAPE_SampleRate = SOUNDSCAPE_DefaultSampleRate;
+
+volatile int SOUNDSCAPE_SoundPlaying;
+
+void ( *SOUNDSCAPE_CallBack )( void );
+
+static int SOUNDSCAPE_IntController1Mask;
+static int SOUNDSCAPE_IntController2Mask;
+
+// some globals for chip type, ports, DMA, IRQs ... and stuff
+static struct
+ {
+ int BasePort; // base address of the Ensoniq gate-array chip
+ int WavePort; // the AD-1848 base address
+ int DMAChan; // the DMA channel used for PCM
+ int WaveIRQ; // the PCM IRQ
+ int MIDIIRQ; // the MPU-401 IRQ
+ int ChipID; // the Ensoniq chip type
+ int SBEmul; // SoundBlaster emulation flag
+ int CDROM; // CD-ROM flag
+ int IRQIndx; // the Wave IRQ index - for hardware regs
+ int OldIRQs; // Old IRQs flag to support older HW
+ } SOUNDSCAPE_Config;
+
+// adequate stack size
+#define kStackSize 2048
+
+static unsigned short StackSelector = NULL;
+static unsigned long StackPointer;
+
+static unsigned short oldStackSelector;
+static unsigned long oldStackPointer;
+
+// These declarations are necessary to use the inline assembly pragmas.
+
+extern void GetStack(unsigned short *selptr,unsigned long *stackptr);
+extern void SetStack(unsigned short selector,unsigned long stackptr);
+
+// This function will get the current stack selector and pointer and save
+// them off.
+#pragma aux GetStack = \
+ "mov [edi],esp" \
+ "mov ax,ss" \
+ "mov [esi],ax" \
+ parm [esi] [edi] \
+ modify [eax esi edi];
+
+// This function will set the stack selector and pointer to the specified
+// values.
+#pragma aux SetStack = \
+ "mov ss,ax" \
+ "mov esp,edx" \
+ parm [ax] [edx] \
+ modify [eax edx];
+
+int SOUNDSCAPE_DMAChannel = -1;
+
+int SOUNDSCAPE_ErrorCode = SOUNDSCAPE_Ok;
+
+#define SOUNDSCAPE_SetErrorCode( status ) \
+ SOUNDSCAPE_ErrorCode = ( status );
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_ErrorString
+
+ Returns a pointer to the error message associated with an error
+ number. A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *SOUNDSCAPE_ErrorString
+ (
+ int ErrorNumber
+ )
+
+ {
+ char *ErrorString;
+
+ switch( ErrorNumber )
+ {
+ case SOUNDSCAPE_Warning :
+ case SOUNDSCAPE_Error :
+ ErrorString = SOUNDSCAPE_ErrorString( SOUNDSCAPE_ErrorCode );
+ break;
+
+ case SOUNDSCAPE_Ok :
+ ErrorString = "SoundScape ok.";
+ break;
+
+ case SOUNDSCAPE_EnvNotFound :
+ ErrorString = "SNDSCAPE environment variable not set. This is used to locate \n"
+ "SNDSCAPE.INI which is used to describe your sound card setup.";
+ break;
+
+ case SOUNDSCAPE_InitFileNotFound :
+ ErrorString = "Missing SNDSCAPE.INI file for SoundScape. This file should be \n"
+ "located in the directory indicated by the SNDSCAPE environment \n"
+ "variable or in 'C:\SNDSCAPE' if SNDSCAPE is not set.";
+ break;
+
+ case SOUNDSCAPE_MissingProductInfo :
+ ErrorString = "Missing 'Product' field in SNDSCAPE.INI file for SoundScape.";
+ break;
+
+ case SOUNDSCAPE_MissingPortInfo :
+ ErrorString = "Missing 'Port' field in SNDSCAPE.INI file for SoundScape.";
+ break;
+
+ case SOUNDSCAPE_MissingDMAInfo :
+ ErrorString = "Missing 'DMA' field in SNDSCAPE.INI file for SoundScape.";
+ break;
+
+ case SOUNDSCAPE_MissingIRQInfo :
+ ErrorString = "Missing 'IRQ' field in SNDSCAPE.INI file for SoundScape.";
+ break;
+
+ case SOUNDSCAPE_MissingSBIRQInfo :
+ ErrorString = "Missing 'SBIRQ' field in SNDSCAPE.INI file for SoundScape.";
+ break;
+
+ case SOUNDSCAPE_MissingSBENABLEInfo :
+ ErrorString = "Missing 'SBEnable' field in SNDSCAPE.INI file for SoundScape.";
+ break;
+
+ case SOUNDSCAPE_MissingWavePortInfo :
+ ErrorString = "Missing 'WavePort' field in SNDSCAPE.INI file for SoundScape.";
+ break;
+
+ case SOUNDSCAPE_HardwareError :
+ ErrorString = "Could not detect SoundScape. Make sure your SNDSCAPE.INI file \n"
+ "contains correct information about your hardware setup.";
+ break;
+
+ case SOUNDSCAPE_NoSoundPlaying :
+ ErrorString = "No sound playing on SoundScape.";
+ break;
+
+ case SOUNDSCAPE_InvalidSBIrq :
+ ErrorString = "Invalid SoundScape Irq in SBIRQ field of SNDSCAPE.INI.";
+ break;
+
+ case SOUNDSCAPE_UnableToSetIrq :
+ ErrorString = "Unable to set SoundScape IRQ. Try selecting an IRQ of 7 or below.";
+ break;
+
+ case SOUNDSCAPE_DmaError :
+ ErrorString = DMA_ErrorString( DMA_Error );
+ break;
+
+ case SOUNDSCAPE_DPMI_Error :
+ ErrorString = "DPMI Error in SoundScape.";
+ break;
+
+ case SOUNDSCAPE_OutOfMemory :
+ ErrorString = "Out of conventional memory in SoundScape.";
+ break;
+
+ default :
+ ErrorString = "Unknown SoundScape error code.";
+ break;
+ }
+
+ return( ErrorString );
+ }
+
+
+/**********************************************************************
+
+ Memory locked functions:
+
+**********************************************************************/
+
+
+#define SOUNDSCAPE_LockStart SOUNDSCAPE_EnableInterrupt
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_EnableInterrupt
+
+ Enables the triggering of the sound card interrupt.
+---------------------------------------------------------------------*/
+
+static void SOUNDSCAPE_EnableInterrupt
+ (
+ void
+ )
+
+ {
+ int mask;
+
+ // Unmask system interrupt
+ if ( SOUNDSCAPE_Config.WaveIRQ < 8 )
+ {
+ mask = inp( 0x21 ) & ~( 1 << SOUNDSCAPE_Config.WaveIRQ );
+ outp( 0x21, mask );
+ }
+ else
+ {
+ mask = inp( 0xA1 ) & ~( 1 << ( SOUNDSCAPE_Config.WaveIRQ - 8 ) );
+ outp( 0xA1, mask );
+
+ mask = inp( 0x21 ) & ~( 1 << 2 );
+ outp( 0x21, mask );
+ }
+
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_DisableInterrupt
+
+ Disables the triggering of the sound card interrupt.
+---------------------------------------------------------------------*/
+
+static void SOUNDSCAPE_DisableInterrupt
+ (
+ void
+ )
+
+ {
+ int mask;
+
+ // Restore interrupt mask
+ if ( SOUNDSCAPE_Config.WaveIRQ < 8 )
+ {
+ mask = inp( 0x21 ) & ~( 1 << SOUNDSCAPE_Config.WaveIRQ );
+ mask |= SOUNDSCAPE_IntController1Mask & ( 1 << SOUNDSCAPE_Config.WaveIRQ );
+ outp( 0x21, mask );
+ }
+ else
+ {
+ mask = inp( 0x21 ) & ~( 1 << 2 );
+ mask |= SOUNDSCAPE_IntController1Mask & ( 1 << 2 );
+ outp( 0x21, mask );
+
+ mask = inp( 0xA1 ) & ~( 1 << ( SOUNDSCAPE_Config.WaveIRQ - 8 ) );
+ mask |= SOUNDSCAPE_IntController2Mask & ( 1 << ( SOUNDSCAPE_Config.WaveIRQ - 8 ) );
+ outp( 0xA1, mask );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_ServiceInterrupt
+
+ Handles interrupt generated by sound card at the end of a voice
+ transfer. Calls the user supplied callback function.
+---------------------------------------------------------------------*/
+
+static void __interrupt __far SOUNDSCAPE_ServiceInterrupt
+ (
+ void
+ )
+
+ {
+ // save stack
+ GetStack( &oldStackSelector, &oldStackPointer );
+
+ // set our stack
+ SetStack( StackSelector, StackPointer );
+
+ if ( !( inp( SOUNDSCAPE_Config.WavePort + AD_STATUS ) & 0x01 ) )
+ {
+ // restore stack
+ SetStack( oldStackSelector, oldStackPointer );
+
+ // Wasn't our interrupt. Call the old one.
+ _chain_intr( SOUNDSCAPE_OldInt );
+ }
+
+ // clear the AD-1848 interrupt
+ outp( SOUNDSCAPE_Config.WavePort + AD_STATUS, 0x00 );
+
+ // Keep track of current buffer
+ SOUNDSCAPE_CurrentDMABuffer += SOUNDSCAPE_TransferLength;
+ if ( SOUNDSCAPE_CurrentDMABuffer >= SOUNDSCAPE_DMABufferEnd )
+ {
+ SOUNDSCAPE_CurrentDMABuffer = SOUNDSCAPE_DMABuffer;
+ }
+
+ // Call the caller's callback function
+ if ( SOUNDSCAPE_CallBack != NULL )
+ {
+ SOUNDSCAPE_CallBack();
+ }
+
+ // restore stack
+ SetStack( oldStackSelector, oldStackPointer );
+
+ // send EOI to Interrupt Controller
+ if ( SOUNDSCAPE_Config.WaveIRQ > 7 )
+ {
+ outp( 0xA0, 0x20 );
+ }
+ outp( 0x20, 0x20 );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: ga_read
+
+ Reads Ensoniq indirect registers.
+---------------------------------------------------------------------*/
+
+static int ga_read
+ (
+ int rnum
+ )
+
+ {
+ int data;
+
+ outp( SOUNDSCAPE_Config.BasePort + GA_REGADDR, rnum );
+ data = inp( SOUNDSCAPE_Config.BasePort + GA_REGDATA );
+ return( data );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: ga_write
+
+ Writes to Ensoniq indirect registers.
+---------------------------------------------------------------------*/
+
+static void ga_write
+ (
+ int rnum,
+ int value
+ )
+
+ {
+ outp( SOUNDSCAPE_Config.BasePort + GA_REGADDR, rnum );
+ outp( SOUNDSCAPE_Config.BasePort + GA_REGDATA, value );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: ad_read
+
+ Reads the AD-1848 indirect registers. This function should not be
+ used while the AD-1848 mode change is enabled
+---------------------------------------------------------------------*/
+
+static int ad_read
+ (
+ int rnum
+ )
+
+ {
+ int data;
+
+ outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, rnum );
+ data = inp( SOUNDSCAPE_Config.WavePort + AD_REGDATA );
+ return( data );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: ad_write
+
+ Writes to the AD-1848 indirect registers. This function should
+ not be used while the AD-1848 mode change is enabled.
+---------------------------------------------------------------------*/
+
+static void ad_write
+ (
+ int rnum,
+ int value
+ )
+
+ {
+ outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, rnum );
+ outp( SOUNDSCAPE_Config.WavePort + AD_REGDATA, value );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: tdelay
+
+ Delay function - 250ms - for AD-1848 re-synch and autocalibration.
+---------------------------------------------------------------------*/
+
+static void tdelay
+ (
+ void
+ )
+
+ {
+ long time;
+ unsigned flags;
+
+ flags = DisableInterrupts();
+ _enable();
+ time = clock() + CLOCKS_PER_SEC/4;
+ while(clock() < time)
+ ;
+
+ RestoreInterrupts( flags );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: pcm_format
+
+ Sets the PCM data format.
+---------------------------------------------------------------------*/
+
+static void pcm_format
+ (
+ void
+ )
+
+ {
+ int format;
+
+ // build the register value based on format
+ format = 0;
+
+ switch( SOUNDSCAPE_SampleRate )
+ {
+ case 11025:
+ format = 0x03;
+ break;
+
+ case 22050:
+ format = 0x07;
+ break;
+
+ case 44100:
+ format = 0x0b;
+ break;
+
+ default:
+ // Set it to 11025 hz
+ format = 0x03;
+ break;
+ }
+
+ // set other format bits and format globals
+ if ( SOUNDSCAPE_MixMode & SIXTEEN_BIT )
+ {
+ format |= 0x40;
+ }
+
+ if ( SOUNDSCAPE_MixMode & STEREO )
+ {
+ format |= 0x10;
+ }
+
+ // enable mode change, point to format reg
+ outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, 0x40 | AD_FORMAT );
+
+ // write the format
+ outp( SOUNDSCAPE_Config.WavePort + AD_REGDATA, format );
+
+ // delay for internal re-synch
+ tdelay();
+
+ // exit mode change state
+ outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, 0x00 );
+
+ // delay for autocalibration
+ tdelay();
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_SetPlaybackRate
+
+ Sets the rate at which the digitized sound will be played in
+ hertz.
+---------------------------------------------------------------------*/
+
+void SOUNDSCAPE_SetPlaybackRate
+ (
+ unsigned rate
+ )
+
+ {
+ if ( rate < 20000 )
+ {
+ rate = 11025;
+ }
+ else if ( rate < 30000 )
+ {
+ rate = 22050;
+ }
+ else
+ {
+ rate = 44100;
+ }
+
+ SOUNDSCAPE_SampleRate = rate;
+
+ // Set the rate
+ pcm_format();
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_GetPlaybackRate
+
+ Returns the rate at which the digitized sound will be played in
+ hertz.
+---------------------------------------------------------------------*/
+
+unsigned SOUNDSCAPE_GetPlaybackRate
+ (
+ void
+ )
+
+ {
+ return( SOUNDSCAPE_SampleRate );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_SetMixMode
+
+ Sets the sound card to play samples in mono or stereo.
+---------------------------------------------------------------------*/
+
+int SOUNDSCAPE_SetMixMode
+ (
+ int mode
+ )
+
+ {
+ SOUNDSCAPE_MixMode = mode & SOUNDSCAPE_MaxMixMode;
+ SOUNDSCAPE_SamplePacketSize = SOUNDSCAPE_SampleSize[ SOUNDSCAPE_MixMode ];
+
+ // Set the mixmode
+ pcm_format();
+
+ return( mode );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_StopPlayback
+
+ Ends the DMA transfer of digitized sound to the sound card.
+---------------------------------------------------------------------*/
+
+void SOUNDSCAPE_StopPlayback
+ (
+ void
+ )
+
+ {
+ // Don't allow anymore interrupts
+ SOUNDSCAPE_DisableInterrupt();
+
+ /* stop the AD-1848 */
+ ad_write( AD_CONFIG, 0x00 );
+
+ /* let it finish it's cycles */
+ tdelay();
+
+ // Disable the DMA channel
+ DMA_EndTransfer( SOUNDSCAPE_Config.DMAChan );
+
+ SOUNDSCAPE_SoundPlaying = FALSE;
+
+ SOUNDSCAPE_DMABuffer = NULL;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_SetupDMABuffer
+
+ Programs the DMAC for sound transfer.
+---------------------------------------------------------------------*/
+
+static int SOUNDSCAPE_SetupDMABuffer
+ (
+ char *BufferPtr,
+ int BufferSize,
+ int mode
+ )
+
+ {
+ int DmaStatus;
+
+ DmaStatus = DMA_SetupTransfer( SOUNDSCAPE_Config.DMAChan, BufferPtr, BufferSize, mode );
+ if ( DmaStatus == DMA_Error )
+ {
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_DmaError );
+ return( SOUNDSCAPE_Error );
+ }
+
+ SOUNDSCAPE_DMAChannel = SOUNDSCAPE_Config.DMAChan;
+ SOUNDSCAPE_DMABuffer = BufferPtr;
+ SOUNDSCAPE_CurrentDMABuffer = BufferPtr;
+ SOUNDSCAPE_TotalDMABufferSize = BufferSize;
+ SOUNDSCAPE_DMABufferEnd = BufferPtr + BufferSize;
+
+ return( SOUNDSCAPE_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_GetCurrentPos
+
+ Returns the offset within the current sound being played.
+---------------------------------------------------------------------*/
+
+int SOUNDSCAPE_GetCurrentPos
+ (
+ void
+ )
+
+ {
+ char *CurrentAddr;
+ int offset;
+
+ if ( !SOUNDSCAPE_SoundPlaying )
+ {
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_NoSoundPlaying );
+ return( SOUNDSCAPE_Error );
+ }
+
+ CurrentAddr = DMA_GetCurrentPos( SOUNDSCAPE_Config.DMAChan );
+
+ offset = ( int )( ( ( unsigned long )CurrentAddr ) -
+ ( ( unsigned long )SOUNDSCAPE_CurrentDMABuffer ) );
+
+ if ( SOUNDSCAPE_MixMode & SIXTEEN_BIT )
+ {
+ offset >>= 1;
+ }
+
+ if ( SOUNDSCAPE_MixMode & STEREO )
+ {
+ offset >>= 1;
+ }
+
+ return( offset );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_BeginPlayback
+
+ Starts playback of digitized sound.
+---------------------------------------------------------------------*/
+
+static int SOUNDSCAPE_BeginPlayback
+ (
+ int length
+ )
+
+ {
+ int SampleLength;
+ int LoByte;
+ int HiByte;
+
+ if ( SOUNDSCAPE_MixMode & SIXTEEN_BIT )
+ {
+ SampleLength = length / 2;
+ }
+ else
+ {
+ SampleLength = length;
+ }
+
+ if ( SOUNDSCAPE_MixMode & STEREO )
+ {
+ SampleLength >>= 1;
+ }
+
+ SampleLength--;
+
+ // setup the AD-1848 interrupt count
+ // set the interrupt count value based on the format.
+ // count will decrement every sample period and generate
+ // an interrupt when in rolls over. we want this always
+ // to be at every 1/2 buffer, regardless of the data format,
+ // so the count must be adjusted accordingly.
+ HiByte = hibyte( SampleLength );
+ LoByte = lobyte( SampleLength );
+ ad_write( AD_LCOUNT, LoByte );
+ ad_write( AD_UCOUNT, HiByte );
+
+ /* unmask the host DMA controller */
+ SOUNDSCAPE_EnableInterrupt();
+
+ /* start the AD-1848 */
+ ad_write(AD_CONFIG, 0x01);
+
+ SOUNDSCAPE_SoundPlaying = TRUE;
+
+ return( SOUNDSCAPE_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_BeginBufferedPlayback
+
+ Begins multibuffered playback of digitized sound on the sound card.
+---------------------------------------------------------------------*/
+
+int SOUNDSCAPE_BeginBufferedPlayback
+ (
+ char *BufferStart,
+ int BufferSize,
+ int NumDivisions,
+ unsigned SampleRate,
+ int MixMode,
+ void ( *CallBackFunc )( void )
+ )
+
+ {
+ int DmaStatus;
+ int TransferLength;
+
+ if ( SOUNDSCAPE_SoundPlaying )
+ {
+ SOUNDSCAPE_StopPlayback();
+ }
+
+ SOUNDSCAPE_SetMixMode( MixMode );
+
+ DmaStatus = SOUNDSCAPE_SetupDMABuffer( BufferStart, BufferSize,
+ DMA_AutoInitRead );
+ if ( DmaStatus == SOUNDSCAPE_Error )
+ {
+ return( SOUNDSCAPE_Error );
+ }
+
+ SOUNDSCAPE_SetPlaybackRate( SampleRate );
+
+ SOUNDSCAPE_SetCallBack( CallBackFunc );
+
+ SOUNDSCAPE_EnableInterrupt();
+
+ TransferLength = BufferSize / NumDivisions;
+ SOUNDSCAPE_TransferLength = TransferLength;
+
+ SOUNDSCAPE_BeginPlayback( TransferLength );
+
+ return( SOUNDSCAPE_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_GetCardInfo
+
+ Returns the maximum number of bits that can represent a sample
+ (8 or 16) and the number of channels (1 for mono, 2 for stereo).
+---------------------------------------------------------------------*/
+
+int SOUNDSCAPE_GetCardInfo
+ (
+ int *MaxSampleBits,
+ int *MaxChannels
+ )
+
+ {
+ int status;
+
+ status = SOUNDSCAPE_FindCard();
+ if ( status == SOUNDSCAPE_Ok )
+ {
+ *MaxChannels = 2;
+ *MaxSampleBits = 16;
+ return( SOUNDSCAPE_Ok );
+ }
+
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_SetCallBack
+
+ Specifies the user function to call at the end of a sound transfer.
+---------------------------------------------------------------------*/
+
+void SOUNDSCAPE_SetCallBack
+ (
+ void ( *func )( void )
+ )
+
+ {
+ SOUNDSCAPE_CallBack = func;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_LockEnd
+
+ Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void SOUNDSCAPE_LockEnd
+ (
+ void
+ )
+
+ {
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_UnlockMemory
+
+ Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+static void SOUNDSCAPE_UnlockMemory
+ (
+ void
+ )
+
+ {
+ DPMI_UnlockMemoryRegion( SOUNDSCAPE_LockStart, SOUNDSCAPE_LockEnd );
+ DPMI_Unlock( SOUNDSCAPE_Config );
+ DPMI_Unlock( SOUNDSCAPE_OldInt );
+ DPMI_Unlock( SOUNDSCAPE_Installed );
+ DPMI_Unlock( SOUNDSCAPE_DMABuffer );
+ DPMI_Unlock( SOUNDSCAPE_DMABufferEnd );
+ DPMI_Unlock( SOUNDSCAPE_CurrentDMABuffer );
+ DPMI_Unlock( SOUNDSCAPE_TotalDMABufferSize );
+ DPMI_Unlock( SOUNDSCAPE_TransferLength );
+ DPMI_Unlock( SOUNDSCAPE_MixMode );
+ DPMI_Unlock( SOUNDSCAPE_SamplePacketSize );
+ DPMI_Unlock( SOUNDSCAPE_SampleRate );
+ DPMI_Unlock( SOUNDSCAPE_SoundPlaying );
+ DPMI_Unlock( SOUNDSCAPE_CallBack );
+ DPMI_Unlock( SOUNDSCAPE_IntController1Mask );
+ DPMI_Unlock( SOUNDSCAPE_IntController2Mask );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_LockMemory
+
+ Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+static int SOUNDSCAPE_LockMemory
+ (
+ void
+ )
+
+ {
+ int status;
+
+ status = DPMI_LockMemoryRegion( SOUNDSCAPE_LockStart, SOUNDSCAPE_LockEnd );
+ status |= DPMI_Lock( SOUNDSCAPE_Config );
+ status |= DPMI_Lock( SOUNDSCAPE_OldInt );
+ status |= DPMI_Lock( SOUNDSCAPE_Installed );
+ status |= DPMI_Lock( SOUNDSCAPE_DMABuffer );
+ status |= DPMI_Lock( SOUNDSCAPE_DMABufferEnd );
+ status |= DPMI_Lock( SOUNDSCAPE_CurrentDMABuffer );
+ status |= DPMI_Lock( SOUNDSCAPE_TotalDMABufferSize );
+ status |= DPMI_Lock( SOUNDSCAPE_TransferLength );
+ status |= DPMI_Lock( SOUNDSCAPE_MixMode );
+ status |= DPMI_Lock( SOUNDSCAPE_SamplePacketSize );
+ status |= DPMI_Lock( SOUNDSCAPE_SampleRate );
+ status |= DPMI_Lock( SOUNDSCAPE_SoundPlaying );
+ status |= DPMI_Lock( SOUNDSCAPE_CallBack );
+ status |= DPMI_Lock( SOUNDSCAPE_IntController1Mask );
+ status |= DPMI_Lock( SOUNDSCAPE_IntController2Mask );
+
+ if ( status != DPMI_Ok )
+ {
+ SOUNDSCAPE_UnlockMemory();
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_DPMI_Error );
+ return( SOUNDSCAPE_Error );
+ }
+
+ return( SOUNDSCAPE_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: allocateTimerStack
+
+ Allocate a block of memory from conventional (low) memory and return
+ the selector (which can go directly into a segment register) of the
+ memory block or 0 if an error occured.
+---------------------------------------------------------------------*/
+
+static unsigned short allocateTimerStack
+ (
+ unsigned short size
+ )
+
+ {
+ union REGS regs;
+
+ // clear all registers
+ memset( ®s, 0, sizeof( regs ) );
+
+ // DPMI allocate conventional memory
+ regs.w.ax = 0x100;
+
+ // size in paragraphs
+ regs.w.bx = ( size + 15 ) / 16;
+
+ int386( 0x31, ®s, ®s );
+ if (!regs.w.cflag)
+ {
+ // DPMI call returns selector in dx
+ // (ax contains real mode segment
+ // which is ignored here)
+
+ return( regs.w.dx );
+ }
+
+ // Couldn't allocate memory.
+ return( NULL );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: deallocateTimerStack
+
+ Deallocate a block of conventional (low) memory given a selector to
+ it. Assumes the block was allocated with DPMI function 0x100.
+---------------------------------------------------------------------*/
+
+static void deallocateTimerStack
+ (
+ unsigned short selector
+ )
+
+ {
+ union REGS regs;
+
+ if ( selector != NULL )
+ {
+ // clear all registers
+ memset( ®s, 0, sizeof( regs ) );
+
+ regs.w.ax = 0x101;
+ regs.w.dx = selector;
+ int386( 0x31, ®s, ®s );
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: parse
+
+ Parses for the right hand string of an .INI file equate.
+---------------------------------------------------------------------*/
+
+static int parse
+ (
+ char *val,
+ char *str,
+ FILE *p1
+ )
+
+ {
+ int i;
+ int j;
+ char tmpstr[ 81 ];
+
+ rewind( p1 );
+
+ while( !feof( p1 ) )
+ {
+ // get a new string
+ fgets( tmpstr, 81, p1 );
+ if( ( tmpstr[ 0 ] == '[' ) || ( tmpstr[ 0 ] == ';' ) ||
+ ( tmpstr[ 0 ] == '\n' ) )
+ {
+ continue;
+ }
+
+ // parse up to the '='
+ i = 0;
+ while( ( tmpstr[ i ] != '=' ) && ( tmpstr[ i ] != '\n' ) )
+ {
+ i++;
+ }
+
+ if( tmpstr[ i ] != '=' )
+ {
+ continue;
+ }
+
+ tmpstr[ i ] = '\0';
+
+ // see if it's the one we want
+ if ( strcmp( tmpstr, str ) )
+ {
+ continue;
+ }
+
+ // copy the right hand value to the destination string
+ i++;
+ for( j = 0; j < 32; j++ )
+ {
+ if ( ( tmpstr[ i ] == ' ' ) || ( tmpstr[ i ] == '\t' ) ||
+ ( tmpstr[ i ] == ',' ) || ( tmpstr[ i ] == '\n' ) )
+ {
+ break;
+ }
+
+ val[ j ] = tmpstr[ i ];
+ i++;
+ }
+ val[j] = '\0';
+
+ return( TRUE );
+ }
+
+ return( FALSE );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_FindCard
+
+ Determines if a SoundScape is present and where it is located.
+---------------------------------------------------------------------*/
+
+static int SOUNDSCAPE_FindCard
+ (
+ void
+ )
+
+ {
+ int found;
+ int status;
+ int tmp;
+ char *cp;
+ char str[ 33 ];
+ FILE *fp;
+
+ if ( SOUNDSCAPE_FoundCard )
+ {
+ return( SOUNDSCAPE_Ok );
+ }
+
+ cp = getenv( "SNDSCAPE" );
+ if ( cp == NULL )
+ {
+ strcpy( str, "C:\\SNDSCAPE" );
+ }
+ else
+ {
+ strcpy( str, cp );
+ }
+
+ strcat(str, "\\SNDSCAPE.INI");
+
+ fp = fopen( str, "r" );
+ if ( fp == NULL )
+ {
+ if ( cp == NULL )
+ {
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_EnvNotFound );
+ return( SOUNDSCAPE_Error );
+ }
+
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_InitFileNotFound );
+ return( SOUNDSCAPE_Error );
+ }
+
+ found = parse( str, "Product", fp );
+ if ( !found )
+ {
+ fclose( fp );
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingProductInfo );
+ return( SOUNDSCAPE_Error );
+ }
+
+ if( strstr( str, "SoundFX" ) == NULL )
+ {
+ SOUNDSCAPE_Config.OldIRQs = FALSE;
+ }
+ else
+ {
+ SOUNDSCAPE_Config.OldIRQs = TRUE;
+ }
+
+ found = parse( str, "Port", fp );
+ if ( !found )
+ {
+ fclose( fp );
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingPortInfo );
+ return( SOUNDSCAPE_Error );
+ }
+
+ SOUNDSCAPE_Config.BasePort = strtol( str, ( char ** )0, 16);
+
+ found = parse( str, "DMA", fp );
+ if ( !found )
+ {
+ fclose( fp );
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingDMAInfo );
+ return( SOUNDSCAPE_Error );
+ }
+
+ SOUNDSCAPE_Config.DMAChan = ( int )strtol( str, ( char ** )0, 10 );
+ status = DMA_VerifyChannel( SOUNDSCAPE_Config.DMAChan );
+ if ( status == DMA_Error )
+ {
+ fclose( fp );
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_DmaError );
+ return( SOUNDSCAPE_Error );
+ }
+
+ found = parse( str, "IRQ", fp );
+ if ( !found )
+ {
+ fclose( fp );
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingIRQInfo );
+ return( SOUNDSCAPE_Error );
+ }
+
+ SOUNDSCAPE_Config.MIDIIRQ = ( int )strtol( str, ( char ** )0, 10 );
+ if ( SOUNDSCAPE_Config.MIDIIRQ == 2 )
+ {
+ SOUNDSCAPE_Config.MIDIIRQ = 9;
+ }
+
+ found = parse( str, "SBIRQ", fp );
+ if ( !found )
+ {
+ fclose( fp );
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingSBIRQInfo );
+ return( SOUNDSCAPE_Error );
+ }
+
+ SOUNDSCAPE_Config.WaveIRQ = ( int )strtol( str, ( char ** )0, 10 );
+ if ( SOUNDSCAPE_Config.WaveIRQ == 2 )
+ {
+ SOUNDSCAPE_Config.WaveIRQ = 9;
+ }
+
+ if ( !VALID_IRQ( SOUNDSCAPE_Config.WaveIRQ ) )
+ {
+ fclose( fp );
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_InvalidSBIrq );
+ return( SOUNDSCAPE_Error );
+ }
+
+ if ( SOUNDSCAPE_Interrupts[ SOUNDSCAPE_Config.WaveIRQ ] == INVALID )
+ {
+ fclose( fp );
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_InvalidSBIrq );
+ return( SOUNDSCAPE_Error );
+ }
+
+ found = parse( str, "SBEnable", fp );
+ if ( !found )
+ {
+ fclose( fp );
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingSBENABLEInfo );
+ return( SOUNDSCAPE_Error );
+ }
+
+ if( !strcmp( str, "false" ) )
+ {
+ SOUNDSCAPE_Config.SBEmul = FALSE;
+ }
+ else
+ {
+ SOUNDSCAPE_Config.SBEmul = TRUE;
+ }
+
+ // do a hardware test
+ outp( SOUNDSCAPE_Config.BasePort + GA_REGADDR, 0x00f5 );
+ tmp = inp( SOUNDSCAPE_Config.BasePort + GA_REGADDR );
+ if ( ( tmp & 0x000f ) != 0x0005 )
+ {
+ fclose( fp );
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_HardwareError );
+ return( SOUNDSCAPE_Error );
+ }
+
+ if( ( tmp & 0x00f0 ) == 0x00f0 )
+ {
+ fclose( fp );
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_HardwareError );
+ return( SOUNDSCAPE_Error );
+ }
+
+ // formulate the chip ID
+ tmp >>= 4;
+ if( tmp == 0 )
+ {
+ SOUNDSCAPE_Config.ChipID = ODIE;
+ }
+ else if ( !( tmp & 0x0008 ) )
+ {
+ SOUNDSCAPE_Config.ChipID = OPUS;
+ }
+ else
+ {
+ SOUNDSCAPE_Config.ChipID = MMIC;
+ }
+
+ // parse for the AD-1848 address if necessary
+ if( SOUNDSCAPE_Config.ChipID == ODIE )
+ {
+ found = parse( str, "WavePort", fp );
+ if ( !found )
+ {
+ fclose( fp );
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingWavePortInfo );
+ return( SOUNDSCAPE_Error );
+ }
+
+ SOUNDSCAPE_Config.WavePort = strtol( str, ( char ** )0, 16 );
+ }
+ else
+ {
+ // otherwise, the base address is fixed
+ SOUNDSCAPE_Config.WavePort = SOUNDSCAPE_Config.BasePort + AD_OFFSET;
+ }
+
+ // we're done with the file
+ fclose( fp );
+
+ // if it's an ODIE board, note CD-ROM decode enable
+ if ( SOUNDSCAPE_Config.ChipID == ODIE )
+ {
+ SOUNDSCAPE_Config.CDROM = ga_read( GA_CDCFG ) & 0x80;
+ }
+
+ // build the Wave IRQ index value
+ if( !SOUNDSCAPE_Config.OldIRQs )
+ {
+ switch( SOUNDSCAPE_Config.WaveIRQ )
+ {
+ case 9 :
+ SOUNDSCAPE_Config.IRQIndx = 0;
+ break;
+
+ case 5 :
+ SOUNDSCAPE_Config.IRQIndx = 1;
+ break;
+
+ case 7 :
+ SOUNDSCAPE_Config.IRQIndx = 2;
+ break;
+
+ default :
+ SOUNDSCAPE_Config.IRQIndx = 3;
+ break;
+ }
+ }
+ else
+ {
+ switch( SOUNDSCAPE_Config.WaveIRQ )
+ {
+ case 9 :
+ SOUNDSCAPE_Config.IRQIndx = 0;
+ break;
+
+ case 5 :
+ SOUNDSCAPE_Config.IRQIndx = 2;
+ break;
+
+ case 7 :
+ SOUNDSCAPE_Config.IRQIndx = 1;
+ break;
+
+ default :
+ SOUNDSCAPE_Config.IRQIndx = 3;
+ break;
+ }
+ }
+
+ SOUNDSCAPE_FoundCard = TRUE;
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_Ok );
+ return( SOUNDSCAPE_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_Setup
+
+ Setup the Soundscape card for native mode PCM.
+---------------------------------------------------------------------*/
+
+static int SOUNDSCAPE_Setup
+ (
+ void
+ )
+
+ {
+ int tmp;
+ int Interrupt;
+ int status;
+
+ // if necessary, clear any pending SB ints
+ if ( SOUNDSCAPE_Config.SBEmul )
+ {
+ inp( SB_IACK );
+ }
+
+ SOUNDSCAPE_DisableInterrupt();
+
+ // make sure the AD-1848 is not running
+ if ( ad_read( AD_CONFIG ) & 0x01 )
+ {
+ SOUNDSCAPE_StopPlayback();
+ }
+
+ // if necessary, do some signal re-routing
+ if( SOUNDSCAPE_Config.ChipID != MMIC )
+ {
+ // get the gate-array off of the DMA channel
+ ga_write( GA_DMACHB, 0x20 );
+
+ if ( !SOUNDSCAPE_Config.OldIRQs )
+ {
+ switch( SOUNDSCAPE_Config.MIDIIRQ )
+ {
+ case 5 :
+ tmp = 1;
+ break;
+
+ case 7 :
+ tmp = 2;
+ break;
+
+ case 9 :
+ tmp = 0;
+ break;
+
+ default :
+ tmp = 3;
+ break;
+ }
+ }
+ else
+ {
+ switch( SOUNDSCAPE_Config.MIDIIRQ )
+ {
+ case 5 :
+ tmp = 2;
+ break;
+
+ case 7 :
+ tmp = 1;
+ break;
+
+ case 9 :
+ tmp = 0;
+ break;
+
+ default :
+ tmp = 3;
+ break;
+ }
+ }
+
+ // set HostIRQ to MIDIIRQ for now
+ ga_write( GA_INTCFG, 0xf0 | ( tmp << 2 ) | tmp );
+
+ // now, route the AD-1848 stuff ...
+ if ( SOUNDSCAPE_Config.ChipID == OPUS )
+ {
+ // set the AD-1848 chip decode
+ ga_write( GA_HMCTL, ( ga_read( GA_HMCTL ) & 0xcf ) | 0x10 );
+ }
+ // setup the DMA polarity
+ ga_write( GA_DMACFG, 0x50 );
+
+ // init the CD-ROM (AD-1848) config register
+ ga_write( GA_CDCFG, 0x89 | ( SOUNDSCAPE_Config.DMAChan << 4 ) | ( SOUNDSCAPE_Config.IRQIndx << 1 ) );
+
+ // enable mode change, point to config reg
+ outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, 0x40 | AD_CONFIG );
+
+ // set interf cnfg reg for DMA mode, single chan, autocal on
+ outp( SOUNDSCAPE_Config.WavePort + AD_REGDATA, 0x0c );
+
+ // exit mode change state
+ outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, 0x00 );
+
+ // delay for autocalibration
+ tdelay();
+ }
+
+ // Install our interrupt handler
+ Interrupt = SOUNDSCAPE_Interrupts[ SOUNDSCAPE_Config.WaveIRQ ];
+ SOUNDSCAPE_OldInt = _dos_getvect( Interrupt );
+ if ( SOUNDSCAPE_Config.WaveIRQ < 8 )
+ {
+ _dos_setvect( Interrupt, SOUNDSCAPE_ServiceInterrupt );
+ }
+ else
+ {
+ status = IRQ_SetVector( Interrupt, SOUNDSCAPE_ServiceInterrupt );
+ if ( status != IRQ_Ok )
+ {
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_UnableToSetIrq );
+ return( SOUNDSCAPE_Error );
+ }
+ }
+
+ // max left and right volumes
+ ad_write( AD_LEFTOUT, 0 );
+ ad_write( AD_RIGHTOUT, 0 );
+
+ // clear any pending interrupt condition
+ outp( SOUNDSCAPE_Config.WavePort + AD_STATUS, 0x00 );
+
+ // enable the interrupt pin
+ ad_write( AD_PINCTRL, ad_read( AD_PINCTRL ) | 0x02 );
+
+ SOUNDSCAPE_EnableInterrupt();
+
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_Ok );
+ return( SOUNDSCAPE_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_GetMIDIPort
+
+ Gets the address of the SoundScape MIDI port.
+---------------------------------------------------------------------*/
+
+int SOUNDSCAPE_GetMIDIPort
+ (
+ void
+ )
+
+ {
+ int status;
+
+ status = SOUNDSCAPE_FindCard();
+ if ( status != SOUNDSCAPE_Ok )
+ {
+ return( status );
+ }
+
+ return( SOUNDSCAPE_Config.BasePort );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_Init
+
+ Initializes the sound card and prepares the module to play
+ digitized sounds.
+---------------------------------------------------------------------*/
+
+int SOUNDSCAPE_Init
+ (
+ void
+ )
+
+ {
+ int status;
+
+ if ( SOUNDSCAPE_Installed )
+ {
+ SOUNDSCAPE_Shutdown();
+ }
+
+ // Save the interrupt masks
+ SOUNDSCAPE_IntController1Mask = inp( 0x21 );
+ SOUNDSCAPE_IntController2Mask = inp( 0xA1 );
+
+ SOUNDSCAPE_SoundPlaying = FALSE;
+ SOUNDSCAPE_SetCallBack( NULL );
+ SOUNDSCAPE_DMABuffer = NULL;
+
+ status = SOUNDSCAPE_FindCard();
+ if ( status != SOUNDSCAPE_Ok )
+ {
+ return( status );
+ }
+
+ status = SOUNDSCAPE_LockMemory();
+ if ( status != SOUNDSCAPE_Ok )
+ {
+ SOUNDSCAPE_UnlockMemory();
+ return( status );
+ }
+
+ StackSelector = allocateTimerStack( kStackSize );
+ if ( StackSelector == NULL )
+ {
+ SOUNDSCAPE_UnlockMemory();
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_OutOfMemory );
+ return( SOUNDSCAPE_Error );
+ }
+
+ // Leave a little room at top of stack just for the hell of it...
+ StackPointer = kStackSize - sizeof( long );
+
+ SOUNDSCAPE_Installed = TRUE;
+
+ status = SOUNDSCAPE_Setup();
+ if ( status != SOUNDSCAPE_Ok )
+ {
+ SOUNDSCAPE_Shutdown();
+ return( status );
+ }
+
+// printf("Testing DMA and IRQ ...\n");
+// if( test_dma_irq() )
+// {
+// printf("\t\007Hardware Not Responding\n\n");
+// close_soundscape();
+// return( SOUNDSCAPE_Error );
+// }
+
+ SOUNDSCAPE_SetPlaybackRate( SOUNDSCAPE_DefaultSampleRate );
+ SOUNDSCAPE_SetMixMode( SOUNDSCAPE_DefaultMixMode );
+
+ SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_Ok );
+ return( SOUNDSCAPE_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SOUNDSCAPE_Shutdown
+
+ Ends transfer of sound data to the sound card and restores the
+ system resources used by the card.
+---------------------------------------------------------------------*/
+
+void SOUNDSCAPE_Shutdown
+ (
+ void
+ )
+
+ {
+ int Interrupt;
+
+ // Halt the DMA transfer
+ SOUNDSCAPE_StopPlayback();
+
+ // disable the AD-1848 interrupt pin
+ ad_write( AD_PINCTRL, ad_read( AD_PINCTRL ) & 0xfd );
+
+ // if necessary, do some signal re-routing
+ if ( SOUNDSCAPE_Config.ChipID != MMIC )
+ {
+ // re-init the CD-ROM (AD-1848) config register as needed.
+ // this will disable the AD-1848 interface.
+ if ( SOUNDSCAPE_Config.ChipID == ODIE )
+ {
+ ga_write( GA_CDCFG, SOUNDSCAPE_Config.CDROM );
+ }
+ else
+ {
+ ga_write( GA_CDCFG, ga_read( GA_CDCFG ) & 0x7f);
+ }
+
+ // if necessary, reset the SoundBlaster IRQ
+ if ( SOUNDSCAPE_Config.SBEmul )
+ {
+ ga_write( GA_INTCFG, ( ga_read( GA_INTCFG ) & 0xf3 ) |
+ ( SOUNDSCAPE_Config.IRQIndx << 2 ) );
+ }
+
+ // re-assign the gate-array DMA channel
+ ga_write( GA_DMACHB, 0x80 | ( SOUNDSCAPE_Config.DMAChan << 4 ) );
+ }
+
+ // Restore the original interrupt
+ Interrupt = SOUNDSCAPE_Interrupts[ SOUNDSCAPE_Config.WaveIRQ ];
+ if ( SOUNDSCAPE_Config.WaveIRQ >= 8 )
+ {
+ IRQ_RestoreVector( Interrupt );
+ }
+ _dos_setvect( Interrupt, SOUNDSCAPE_OldInt );
+
+ SOUNDSCAPE_SoundPlaying = FALSE;
+
+ SOUNDSCAPE_DMABuffer = NULL;
+
+ SOUNDSCAPE_SetCallBack( NULL );
+
+ SOUNDSCAPE_UnlockMemory();
+
+ if ( StackSelector != NULL )
+ {
+ deallocateTimerStack( StackSelector );
+ StackSelector = NULL;
+ }
+
+ SOUNDSCAPE_Installed = FALSE;
+ }
--- /dev/null
+++ b/rott/audiolib/sndscape.h
@@ -1,0 +1,73 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: SNDSCAPE.H
+
+ author: James R. Dose
+ date: October 26, 1994
+
+ Public header for SNDSCAPE.C
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __SNDSCAPE_H
+#define __SNDSCAPE_H
+
+extern int SOUNDSCAPE_DMAChannel;
+extern int SOUNDSCAPE_ErrorCode;
+
+enum SOUNDSCAPE_ERRORS
+ {
+ SOUNDSCAPE_Warning = -2,
+ SOUNDSCAPE_Error = -1,
+ SOUNDSCAPE_Ok = 0,
+ SOUNDSCAPE_EnvNotFound,
+ SOUNDSCAPE_InitFileNotFound,
+ SOUNDSCAPE_MissingProductInfo,
+ SOUNDSCAPE_MissingPortInfo,
+ SOUNDSCAPE_MissingDMAInfo,
+ SOUNDSCAPE_MissingIRQInfo,
+ SOUNDSCAPE_MissingSBIRQInfo,
+ SOUNDSCAPE_MissingSBENABLEInfo,
+ SOUNDSCAPE_MissingWavePortInfo,
+ SOUNDSCAPE_HardwareError,
+ SOUNDSCAPE_NoSoundPlaying,
+ SOUNDSCAPE_InvalidSBIrq,
+ SOUNDSCAPE_UnableToSetIrq,
+ SOUNDSCAPE_DmaError,
+ SOUNDSCAPE_DPMI_Error,
+ SOUNDSCAPE_OutOfMemory
+ };
+
+char *SOUNDSCAPE_ErrorString( int ErrorNumber );
+void SOUNDSCAPE_SetPlaybackRate( unsigned rate );
+unsigned SOUNDSCAPE_GetPlaybackRate( void );
+int SOUNDSCAPE_SetMixMode( int mode );
+void SOUNDSCAPE_StopPlayback( void );
+int SOUNDSCAPE_GetCurrentPos( void );
+int SOUNDSCAPE_BeginBufferedPlayback( char *BufferStart, int BufferSize, int NumDivisions, unsigned SampleRate, int MixMode, void ( *CallBackFunc )( void ) );
+int SOUNDSCAPE_GetCardInfo( int *MaxSampleBits, int *MaxChannels );
+void SOUNDSCAPE_SetCallBack( void ( *func )( void ) );
+int SOUNDSCAPE_GetMIDIPort( void );
+int SOUNDSCAPE_Init( void );
+void SOUNDSCAPE_Shutdown( void );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/sndsrc.c
@@ -1,0 +1,658 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: SNDSRC.C
+
+ author: James R. Dose
+ date: March 26, 1994
+
+ Low level routines to support the Disney Sound Source.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#define STEREO 1
+#define SIXTEEN_BIT 2
+
+#define MONO_8BIT 0
+#define STEREO_8BIT ( STEREO )
+#define MONO_16BIT ( SIXTEEN_BIT )
+#define STEREO_16BIT ( STEREO | SIXTEEN_BIT )
+
+#include <stdlib.h>
+#include <dos.h>
+#include <conio.h>
+#include "dpmi.h"
+#include "task_man.h"
+#include "sndcards.h"
+#include "user.h"
+#include "sndsrc.h"
+
+#define TRUE ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+static int SS_Installed = FALSE;
+
+static int SS_Port = SS_DefaultPort;
+static int SS_OffCommand = 0xc;
+
+static char *SS_BufferStart;
+static char *SS_BufferEnd;
+static char *SS_CurrentBuffer;
+static int SS_BufferNum = 0;
+static int SS_NumBuffers = 0;
+static int SS_TotalBufferSize = 0;
+static int SS_TransferLength = 0;
+static int SS_CurrentLength = 0;
+
+static char *SS_SoundPtr;
+volatile int SS_SoundPlaying;
+
+static task *SS_Timer;
+
+void ( *SS_CallBack )( void );
+
+int SS_ErrorCode = SS_Ok;
+
+#define SS_SetErrorCode( status ) \
+ SS_ErrorCode = ( status );
+
+/*---------------------------------------------------------------------
+ Function: SS_ErrorString
+
+ Returns a pointer to the error message associated with an error
+ number. A -1 returns a pointer the current error.
+---------------------------------------------------------------------*/
+
+char *SS_ErrorString
+ (
+ int ErrorNumber
+ )
+
+ {
+ char *ErrorString;
+
+ switch( ErrorNumber )
+ {
+ case SS_Error :
+ ErrorString = SS_ErrorString( SS_ErrorCode );
+ break;
+
+ case SS_Ok :
+ ErrorString = "Sound Source ok.";
+ break;
+
+ case SS_NotFound :
+ ErrorString = "Could not detect Sound Source.";
+ break;
+
+ case SS_NoSoundPlaying :
+ ErrorString = "No sound playing in SndSrc.";
+ break;
+
+ case SS_DPMI_Error :
+ ErrorString = "DPMI Error in SndSrc.";
+ break;
+
+ default :
+ ErrorString = "Unknown Sound Source error code.";
+ break;
+ }
+
+ return( ErrorString );
+ }
+
+
+/**********************************************************************
+
+ Memory locked functions:
+
+**********************************************************************/
+
+
+#define SS_LockStart SS_ServiceInterrupt
+
+
+/*---------------------------------------------------------------------
+ Function: SS_ServiceInterrupt
+
+ Handles interrupt generated by sound card at the end of a voice
+ transfer. Calls the user supplied callback function.
+---------------------------------------------------------------------*/
+
+static void SS_ServiceInterrupt
+ (
+ task *Task
+ )
+
+ {
+ int port = SS_Port;
+ int count;
+
+ count = 0;
+ while( ( inp( port + 1 ) & 0x40 ) == 0 )
+ {
+ outp( port, *SS_SoundPtr++ );
+ outp( port + 2, SS_OffCommand );
+ outp( port + 2, 4 );
+
+ SS_CurrentLength--;
+ if ( SS_CurrentLength == 0 )
+ {
+ // Keep track of current buffer
+ SS_CurrentBuffer += SS_TransferLength;
+ SS_BufferNum++;
+ if ( SS_BufferNum >= SS_NumBuffers )
+ {
+ SS_BufferNum = 0;
+ SS_CurrentBuffer = SS_BufferStart;
+ }
+
+ SS_CurrentLength = SS_TransferLength;
+ SS_SoundPtr = SS_CurrentBuffer;
+
+ // Call the caller's callback function
+ if ( SS_CallBack != NULL )
+ {
+ SS_CallBack();
+ }
+ }
+
+ count++;
+ // Only do at most 14 samples per tick
+ if ( count > 13 )
+ {
+ break;
+ }
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SS_StopPlayback
+
+ Ends the transfer of digitized sound to the Sound Source.
+---------------------------------------------------------------------*/
+
+void SS_StopPlayback
+ (
+ void
+ )
+
+ {
+ if ( SS_SoundPlaying )
+ {
+ TS_Terminate( SS_Timer );
+
+ outp( SS_Port, 0x80 );
+ outp( SS_Port + 2, SS_OffCommand );
+ outp( SS_Port + 2, 4 );
+
+ SS_SoundPlaying = FALSE;
+
+ SS_BufferStart = NULL;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SS_GetCurrentPos
+
+ Returns the offset within the current sound being played.
+---------------------------------------------------------------------*/
+
+int SS_GetCurrentPos
+ (
+ void
+ )
+
+ {
+ int offset;
+
+ if ( !SS_SoundPlaying )
+ {
+ SS_SetErrorCode( SS_NoSoundPlaying );
+ return( SS_Warning );
+ }
+
+ offset = ( int )( ( ( unsigned long )SS_SoundPtr ) -
+ ( ( unsigned long )SS_CurrentBuffer ) );
+
+ return( offset );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SS_LockEnd
+
+ Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void SS_LockEnd
+ (
+ void
+ )
+
+ {
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SS_BeginBufferedPlayback
+
+ Begins multibuffered playback of digitized sound on the Sound Source.
+---------------------------------------------------------------------*/
+
+int SS_BeginBufferedPlayback
+ (
+ char *BufferStart,
+ int BufferSize,
+ int NumDivisions,
+ void ( *CallBackFunc )( void )
+ )
+
+ {
+ if ( SS_SoundPlaying )
+ {
+ SS_StopPlayback();
+ }
+
+ SS_SetCallBack( CallBackFunc );
+
+ SS_BufferStart = BufferStart;
+ SS_CurrentBuffer = BufferStart;
+ SS_SoundPtr = BufferStart;
+ SS_TotalBufferSize = BufferSize;
+ SS_BufferEnd = BufferStart + BufferSize;
+ SS_TransferLength = BufferSize / NumDivisions;
+ SS_CurrentLength = SS_TransferLength;
+ SS_BufferNum = 0;
+ SS_NumBuffers = NumDivisions;
+
+ SS_SoundPlaying = TRUE;
+
+// SS_Timer = TS_ScheduleTask( SS_ServiceInterrupt, 438, 1, NULL );
+ SS_Timer = TS_ScheduleTask( SS_ServiceInterrupt, 510, 1, NULL );
+ TS_Dispatch();
+
+ return( SS_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SS_GetPlaybackRate
+
+ Returns the rate at which the digitized sound will be played in
+ hertz.
+---------------------------------------------------------------------*/
+
+int SS_GetPlaybackRate
+ (
+ void
+ )
+
+ {
+ return( SS_SampleRate );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SS_SetMixMode
+
+ Sets the sound card to play samples in mono or stereo.
+---------------------------------------------------------------------*/
+
+int SS_SetMixMode
+ (
+ int mode
+ )
+
+ {
+ mode = MONO_8BIT;
+ return( mode );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SS_SetPort
+
+ Selects which port to use to write to the Sound Source.
+---------------------------------------------------------------------*/
+
+int SS_SetPort
+ (
+ int port
+ )
+
+ {
+ if ( SS_Installed )
+ {
+ SS_Shutdown();
+ }
+
+ SS_Port = port;
+
+ return( SS_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SS_SetCallBack
+
+ Specifies the user function to call at the end of a sound transfer.
+---------------------------------------------------------------------*/
+
+void SS_SetCallBack
+ (
+ void ( *func )( void )
+ )
+
+ {
+ SS_CallBack = func;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SS_TestTimer
+
+ Used as a delay in SS_TestSoundSource.
+---------------------------------------------------------------------*/
+
+void SS_TestTimer
+ (
+ task *Task
+ )
+
+ {
+ ( *( int * )( Task->data ) )++;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SS_TestSoundSource
+
+ Detect if the Sound Source is located at the specified port.
+---------------------------------------------------------------------*/
+
+int SS_TestSoundSource
+ (
+ int port
+ )
+
+ {
+ int present;
+ task *timer;
+ volatile int ticks;
+ int i;
+
+ present = FALSE;
+
+ timer = TS_ScheduleTask( SS_TestTimer, 140, 1, &ticks );
+ TS_Dispatch();
+
+ outp( port + 2, 4 );
+
+ ticks = 0;
+
+ while( ticks < 4 )
+ {
+ // Do nothing for a while
+ }
+
+ TS_Terminate( timer );
+
+ if ( ( inp( port + 1 ) & 0x40 ) == 0 )
+ {
+ for( i = 32; i > 0; i-- )
+ {
+ outp( port, 0x80 );
+ outp( port + 2, SS_OffCommand );
+ outp( port + 2, 4 );
+ }
+
+ if ( inp( port + 1 ) & 0x40 )
+ {
+ present = TRUE;
+ }
+ }
+
+ outp( port + 2, SS_OffCommand );
+
+ return( present );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SS_DetectSoundSource
+
+ Detects which port the Sound Source is located.
+---------------------------------------------------------------------*/
+
+int SS_DetectSoundSource
+ (
+ void
+ )
+
+ {
+ if ( USER_CheckParameter( SELECT_SOUNDSOURCE_PORT1 ) )
+ {
+ SS_Port = SS_Port1;
+ return( TRUE );
+ }
+
+ if ( USER_CheckParameter( SELECT_SOUNDSOURCE_PORT2 ) )
+ {
+ SS_Port = SS_Port2;
+ return( TRUE );
+ }
+
+ if ( USER_CheckParameter( SELECT_SOUNDSOURCE_PORT3 ) )
+ {
+ SS_Port = SS_Port3;
+ return( TRUE );
+ }
+
+ if ( SS_TestSoundSource( SS_Port1 ) )
+ {
+ SS_Port = SS_Port1;
+ return( TRUE );
+ }
+
+ if ( SS_TestSoundSource( SS_Port2 ) )
+ {
+ SS_Port = SS_Port2;
+ return( TRUE );
+ }
+
+ if ( SS_TestSoundSource( SS_Port3 ) )
+ {
+ SS_Port = SS_Port3;
+ return( TRUE );
+ }
+
+ return( FALSE );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SS_Init
+
+ Initializes the Sound Source prepares the module to play digitized
+ sounds.
+---------------------------------------------------------------------*/
+
+int SS_Init
+ (
+ int soundcard
+ )
+
+ {
+ int status;
+
+ if ( SS_Installed )
+ {
+ SS_Shutdown();
+ }
+
+ if ( ( soundcard == TandySoundSource ) ||
+ ( USER_CheckParameter( SELECT_TANDY_SOUNDSOURCE ) ) )
+ {
+ // Tandy
+ SS_OffCommand = 0x0e;
+ }
+ else
+ {
+ // Disney
+ SS_OffCommand = 0x0c;
+ }
+
+ status = SS_DetectSoundSource();
+ if ( !status )
+ {
+ SS_SetErrorCode( SS_NotFound );
+ return( SS_Warning );
+ }
+
+ status = SS_LockMemory();
+ if ( status != SS_Ok )
+ {
+ SS_UnlockMemory();
+ return( status );
+ }
+
+ status = SS_Ok;
+
+ outp( SS_Port + 2, 4 );
+
+ SS_SoundPlaying = FALSE;
+
+ SS_SetCallBack( NULL );
+
+ SS_BufferStart = NULL;
+
+ SS_Installed = TRUE;
+
+ SS_SetErrorCode( status );
+ return( status );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SS_Shutdown
+
+ Ends transfer of sound data to the Sound Source.
+---------------------------------------------------------------------*/
+
+void SS_Shutdown
+ (
+ void
+ )
+
+ {
+ // Halt the transfer
+ SS_StopPlayback();
+
+ outp( SS_Port + 2, SS_OffCommand );
+
+ SS_SoundPlaying = FALSE;
+
+ SS_BufferStart = NULL;
+
+ SS_SetCallBack( NULL );
+
+ SS_UnlockMemory();
+
+ SS_Installed = FALSE;
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SS_UnlockMemory
+
+ Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+void SS_UnlockMemory
+ (
+ void
+ )
+
+ {
+ DPMI_UnlockMemoryRegion( SS_LockStart, SS_LockEnd );
+ DPMI_Unlock( SS_Installed );
+ DPMI_Unlock( SS_Port );
+ DPMI_Unlock( SS_OffCommand );
+ DPMI_Unlock( SS_BufferStart );
+ DPMI_Unlock( SS_BufferEnd );
+ DPMI_Unlock( SS_CurrentBuffer );
+ DPMI_Unlock( SS_BufferNum );
+ DPMI_Unlock( SS_NumBuffers );
+ DPMI_Unlock( SS_TotalBufferSize );
+ DPMI_Unlock( SS_TransferLength );
+ DPMI_Unlock( SS_CurrentLength );
+ DPMI_Unlock( SS_SoundPtr );
+ DPMI_Unlock( SS_SoundPlaying );
+ DPMI_Unlock( SS_Timer );
+ DPMI_Unlock( SS_CallBack );
+ DPMI_Unlock( SS_ErrorCode );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: SS_LockMemory
+
+ Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+int SS_LockMemory
+ (
+ void
+ )
+
+ {
+ int status;
+
+ status = DPMI_LockMemoryRegion( SS_LockStart, SS_LockEnd );
+ status |= DPMI_Lock( SS_Installed );
+ status |= DPMI_Lock( SS_Port );
+ status |= DPMI_Lock( SS_OffCommand );
+ status |= DPMI_Lock( SS_BufferStart );
+ status |= DPMI_Lock( SS_BufferEnd );
+ status |= DPMI_Lock( SS_CurrentBuffer );
+ status |= DPMI_Lock( SS_BufferNum );
+ status |= DPMI_Lock( SS_NumBuffers );
+ status |= DPMI_Lock( SS_TotalBufferSize );
+ status |= DPMI_Lock( SS_TransferLength );
+ status |= DPMI_Lock( SS_CurrentLength );
+ status |= DPMI_Lock( SS_SoundPtr );
+ status |= DPMI_Lock( SS_SoundPlaying );
+ status |= DPMI_Lock( SS_Timer );
+ status |= DPMI_Lock( SS_CallBack );
+ status |= DPMI_Lock( SS_ErrorCode );
+
+ if ( status != DPMI_Ok )
+ {
+ SS_UnlockMemory();
+ SS_SetErrorCode( SS_DPMI_Error );
+ return( SS_Error );
+ }
+
+ return( SS_Ok );
+ }
--- /dev/null
+++ b/rott/audiolib/sndsrc.h
@@ -1,0 +1,70 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: SNDSRC.H
+
+ author: James R. Dose
+ date: March 26, 1994
+
+ Public header for for SNDSRC.C
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __SNDSRC_H
+#define __SNDSRC_H
+
+enum SS_ERRORS
+ {
+ SS_Warning = -2,
+ SS_Error = -1,
+ SS_Ok = 0,
+ SS_NotFound,
+ SS_NoSoundPlaying,
+ SS_DPMI_Error
+ };
+
+#define SELECT_SOUNDSOURCE_PORT1 "ss1"
+#define SELECT_SOUNDSOURCE_PORT2 "ss2"
+#define SELECT_SOUNDSOURCE_PORT3 "ss3"
+#define SELECT_TANDY_SOUNDSOURCE "sst"
+
+#define SS_Port1 0x3bc
+#define SS_Port2 0x378
+#define SS_Port3 0x278
+
+#define SS_DefaultPort 0x378
+#define SS_SampleRate 7000
+#define SS_DMAChannel -1
+
+char *SS_ErrorString( int ErrorNumber );
+void SS_StopPlayback( void );
+int SS_GetCurrentPos( void );
+int SS_BeginBufferedPlayback( char *BufferStart, int BufferSize, int NumDivisions, void ( *CallBackFunc )( void ) );
+int SS_GetPlaybackRate( void );
+int SS_SetMixMode( int mode );
+int SS_SetPort( int port );
+void SS_SetCallBack( void ( *func )( void ) );
+int SS_Init( int soundcard );
+void SS_Shutdown( void );
+void SS_UnlockMemory( void );
+int SS_LockMemory( void );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/standard.h
@@ -1,0 +1,72 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: STANDARD.H
+
+ author: James R. Dose
+ date: May 25, 1994
+
+ Header containing standard definitions.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __STANDARD_H
+#define __STANDARD_H
+
+typedef int boolean;
+typedef int errorcode;
+
+#ifndef TRUE
+ #define TRUE ( 1 == 1 )
+ #define FALSE ( !TRUE )
+#endif
+
+enum STANDARD_ERRORS
+ {
+ Warning = -2,
+ FatalError = -1,
+ Success = 0
+ };
+
+#define BITSET( data, bit ) \
+ ( ( ( data ) & ( bit ) ) == ( bit ) )
+
+#define ARRAY_LENGTH( array ) \
+ ( sizeof( array ) / sizeof( ( array )[ 0 ] ) )
+
+#define WITHIN_BOUNDS( array, index ) \
+ ( ( 0 <= ( index ) ) && ( ( index ) < ARRAY_LENGTH( array ) ) )
+
+#define FOREVER for( ; ; )
+
+#ifdef NDEBUG
+ #define DEBUGGING 0
+#else
+ #define DEBUGGING 1
+#endif
+
+#define DEBUG_CODE \
+ if ( DEBUGGING == 0 ) \
+ { \
+ } \
+ else
+
+#endif
--- /dev/null
+++ b/rott/audiolib/task_man.c
@@ -1,0 +1,976 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: TASK_MAN.C
+
+ author: James R. Dose
+ date: July 25, 1994
+
+ Low level timer task scheduler.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#define TRUE ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+//#define USESTACK
+#define LOCKMEMORY
+#define NOINTS
+#define USE_USRHOOKS
+
+#include <stdlib.h>
+#include <dos.h>
+#include <conio.h>
+#include <string.h>
+#include "interrup.h"
+#include "linklist.h"
+#include "task_man.h"
+
+#ifdef USESTACK
+#include "dpmi.h"
+#endif
+#ifdef LOCKMEMORY
+#include "dpmi.h"
+#endif
+
+#ifdef USE_USRHOOKS
+#include "usrhooks.h"
+#define FreeMem( ptr ) USRHOOKS_FreeMem( ( ptr ) )
+#else
+#define FreeMem( ptr ) free( ( ptr ) )
+#endif
+
+typedef struct
+ {
+ task *start;
+ task *end;
+ } tasklist;
+
+
+/*---------------------------------------------------------------------
+ Global variables
+---------------------------------------------------------------------*/
+
+#ifdef USESTACK
+
+// adequate stack size
+#define kStackSize 2048
+
+static unsigned short StackSelector = NULL;
+static unsigned long StackPointer;
+
+static unsigned short oldStackSelector;
+static unsigned long oldStackPointer;
+
+#endif
+
+static task HeadTask;
+static task *TaskList = &HeadTask;
+
+static void ( __interrupt __far *OldInt8 )( void );
+
+static volatile long TaskServiceRate = 0x10000L;
+static volatile long TaskServiceCount = 0;
+
+#ifndef NOINTS
+static volatile int TS_TimesInInterrupt;
+#endif
+
+static char TS_Installed = FALSE;
+
+volatile int TS_InInterrupt = FALSE;
+
+/*---------------------------------------------------------------------
+ Function prototypes
+---------------------------------------------------------------------*/
+
+static void TS_FreeTaskList( void );
+static void TS_SetClockSpeed( long speed );
+static long TS_SetTimer( long TickBase );
+static void TS_SetTimerToMaxTaskRate( void );
+static void __interrupt __far TS_ServiceSchedule( void );
+static void __interrupt __far TS_ServiceScheduleIntEnabled( void );
+static void TS_AddTask( task *ptr );
+static int TS_Startup( void );
+static void RestoreRealTimeClock( void );
+
+// These declarations are necessary to use the inline assembly pragmas.
+
+extern void GetStack(unsigned short *selptr,unsigned long *stackptr);
+extern void SetStack(unsigned short selector,unsigned long stackptr);
+
+// This function will get the current stack selector and pointer and save
+// them off.
+#pragma aux GetStack = \
+ "mov [edi],esp" \
+ "mov ax,ss" \
+ "mov [esi],ax" \
+ parm [esi] [edi] \
+ modify [eax esi edi];
+
+// This function will set the stack selector and pointer to the specified
+// values.
+#pragma aux SetStack = \
+ "mov ss,ax" \
+ "mov esp,edx" \
+ parm [ax] [edx] \
+ modify [eax edx];
+
+
+/**********************************************************************
+
+ Memory locked functions:
+
+**********************************************************************/
+
+
+#define TS_LockStart TS_FreeTaskList
+
+
+/*---------------------------------------------------------------------
+ Function: TS_FreeTaskList
+
+ Terminates all tasks and releases any memory used for control
+ structures.
+---------------------------------------------------------------------*/
+
+static void TS_FreeTaskList
+ (
+ void
+ )
+
+ {
+ task *node;
+ task *next;
+ unsigned flags;
+
+ flags = DisableInterrupts();
+
+ node = TaskList->next;
+ while( node != TaskList )
+ {
+ next = node->next;
+ FreeMem( node );
+ node = next;
+ }
+
+ TaskList->next = TaskList;
+ TaskList->prev = TaskList;
+
+ RestoreInterrupts( flags );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: TS_SetClockSpeed
+
+ Sets the rate of the 8253 timer.
+---------------------------------------------------------------------*/
+
+static void TS_SetClockSpeed
+ (
+ long speed
+ )
+
+ {
+ unsigned flags;
+
+ flags = DisableInterrupts();
+
+ if ( ( speed > 0 ) && ( speed < 0x10000L ) )
+ {
+ TaskServiceRate = speed;
+ }
+ else
+ {
+ TaskServiceRate = 0x10000L;
+ }
+
+ outp( 0x43, 0x36 );
+ outp( 0x40, TaskServiceRate );
+ outp( 0x40, TaskServiceRate >> 8 );
+
+ RestoreInterrupts( flags );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: TS_SetTimer
+
+ Calculates the rate at which a task will occur and sets the clock
+ speed if necessary.
+---------------------------------------------------------------------*/
+
+static long TS_SetTimer
+ (
+ long TickBase
+ )
+
+ {
+ long speed;
+
+ speed = 1192030L / TickBase;
+ if ( speed < TaskServiceRate )
+ {
+ TS_SetClockSpeed( speed );
+ }
+
+ return( speed );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: TS_SetTimerToMaxTaskRate
+
+ Finds the fastest running task and sets the clock to operate at
+ that speed.
+---------------------------------------------------------------------*/
+
+static void TS_SetTimerToMaxTaskRate
+ (
+ void
+ )
+
+ {
+ task *ptr;
+ long MaxServiceRate;
+ unsigned flags;
+
+ flags = DisableInterrupts();
+
+ MaxServiceRate = 0x10000L;
+
+ ptr = TaskList->next;
+ while( ptr != TaskList )
+ {
+ if ( ptr->rate < MaxServiceRate )
+ {
+ MaxServiceRate = ptr->rate;
+ }
+
+ ptr = ptr->next;
+ }
+
+ if ( TaskServiceRate != MaxServiceRate )
+ {
+ TS_SetClockSpeed( MaxServiceRate );
+ }
+
+ RestoreInterrupts( flags );
+ }
+
+
+#ifdef NOINTS
+/*---------------------------------------------------------------------
+ Function: TS_ServiceSchedule
+
+ Interrupt service routine
+---------------------------------------------------------------------*/
+
+static void __interrupt __far TS_ServiceSchedule
+ (
+ void
+ )
+
+ {
+ task *ptr;
+ task *next;
+
+
+ TS_InInterrupt = TRUE;
+
+ #ifdef USESTACK
+ // save stack
+ GetStack( &oldStackSelector, &oldStackPointer );
+
+ // set our stack
+ SetStack( StackSelector, StackPointer );
+ #endif
+
+ ptr = TaskList->next;
+ while( ptr != TaskList )
+ {
+ next = ptr->next;
+
+ if ( ptr->active )
+ {
+ ptr->count += TaskServiceRate;
+//JIM
+// if ( ptr->count >= ptr->rate )
+ while( ptr->count >= ptr->rate )
+ {
+ ptr->count -= ptr->rate;
+ ptr->TaskService( ptr );
+ }
+ }
+ ptr = next;
+ }
+
+ #ifdef USESTACK
+ // restore stack
+ SetStack( oldStackSelector, oldStackPointer );
+ #endif
+
+ TaskServiceCount += TaskServiceRate;
+ if ( TaskServiceCount > 0xffffL )
+ {
+ TaskServiceCount &= 0xffff;
+ _chain_intr( OldInt8 );
+ }
+
+ outp( 0x20,0x20 );
+
+ TS_InInterrupt = FALSE;
+ }
+
+#else
+
+/*---------------------------------------------------------------------
+ Function: TS_ServiceScheduleIntEnabled
+
+ Interrupt service routine with interrupts enabled.
+---------------------------------------------------------------------*/
+
+static void __interrupt __far TS_ServiceScheduleIntEnabled
+ (
+ void
+ )
+
+ {
+ task *ptr;
+ task *next;
+
+ TS_TimesInInterrupt++;
+ TaskServiceCount += TaskServiceRate;
+ if ( TaskServiceCount > 0xffffL )
+ {
+ TaskServiceCount &= 0xffff;
+ _chain_intr( OldInt8 );
+ }
+
+ outp( 0x20,0x20 );
+
+ if ( TS_InInterrupt )
+ {
+ return;
+ }
+
+ TS_InInterrupt = TRUE;
+ _enable();
+
+ #ifdef USESTACK
+ // save stack
+ GetStack( &oldStackSelector, &oldStackPointer );
+
+ // set our stack
+ SetStack( StackSelector, StackPointer );
+ #endif
+
+ while( TS_TimesInInterrupt )
+ {
+ ptr = TaskList->next ;
+ while( ptr != TaskList )
+ {
+ next = ptr->next;
+
+ if ( ptr->active )
+ {
+ ptr->count += TaskServiceRate;
+ if ( ptr->count >= ptr->rate )
+ {
+ ptr->count -= ptr->rate;
+ ptr->TaskService( ptr );
+ }
+ }
+ ptr = next;
+ }
+ TS_TimesInInterrupt--;
+ }
+
+ _disable();
+
+ #ifdef USESTACK
+ // restore stack
+ SetStack( oldStackSelector, oldStackPointer );
+ #endif
+
+ TS_InInterrupt = FALSE;
+ }
+#endif
+
+
+#ifdef USESTACK
+
+/*---------------------------------------------------------------------
+ Function: allocateTimerStack
+
+ Allocate a block of memory from conventional (low) memory and return
+ the selector (which can go directly into a segment register) of the
+ memory block or 0 if an error occured.
+---------------------------------------------------------------------*/
+
+static unsigned short allocateTimerStack
+ (
+ unsigned short size
+ )
+
+ {
+ union REGS regs;
+
+ // clear all registers
+ memset( ®s, 0, sizeof( regs ) );
+
+ // DPMI allocate conventional memory
+ regs.w.ax = 0x100;
+
+ // size in paragraphs
+ regs.w.bx = ( size + 15 ) / 16;
+
+ int386( 0x31, ®s, ®s );
+ if (!regs.w.cflag)
+ {
+ // DPMI call returns selector in dx
+ // (ax contains real mode segment
+ // which is ignored here)
+
+ return( regs.w.dx );
+ }
+
+ // Couldn't allocate memory.
+ return( NULL );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: deallocateTimerStack
+
+ Deallocate a block of conventional (low) memory given a selector to
+ it. Assumes the block was allocated with DPMI function 0x100.
+---------------------------------------------------------------------*/
+
+static void deallocateTimerStack
+ (
+ unsigned short selector
+ )
+
+ {
+ union REGS regs;
+
+ if ( selector != NULL )
+ {
+ // clear all registers
+ memset( ®s, 0, sizeof( regs ) );
+
+ regs.w.ax = 0x101;
+ regs.w.dx = selector;
+ int386( 0x31, ®s, ®s );
+ }
+ }
+
+#endif
+
+/*---------------------------------------------------------------------
+ Function: TS_Startup
+
+ Sets up the task service routine.
+---------------------------------------------------------------------*/
+
+static int TS_Startup
+ (
+ void
+ )
+
+ {
+ if ( !TS_Installed )
+ {
+#ifdef LOCKMEMORY
+
+ int status;
+
+ status = TS_LockMemory();
+ if ( status != TASK_Ok )
+ {
+ TS_UnlockMemory();
+ return( status );
+ }
+
+#endif
+
+#ifdef USESTACK
+
+ StackSelector = allocateTimerStack( kStackSize );
+ if ( StackSelector == NULL )
+ {
+
+#ifdef LOCKMEMORY
+
+ TS_UnlockMemory();
+
+#endif
+ return( TASK_Error );
+ }
+
+ // Leave a little room at top of stack just for the hell of it...
+ StackPointer = kStackSize - sizeof( long );
+
+#endif
+
+//static const task *TaskList = &HeadTask;
+ TaskList->next = TaskList;
+ TaskList->prev = TaskList;
+
+ TaskServiceRate = 0x10000L;
+ TaskServiceCount = 0;
+
+#ifndef NOINTS
+ TS_TimesInInterrupt = 0;
+#endif
+
+ OldInt8 = _dos_getvect( 0x08 );
+ #ifdef NOINTS
+ _dos_setvect( 0x08, TS_ServiceSchedule );
+ #else
+ _dos_setvect( 0x08, TS_ServiceScheduleIntEnabled );
+ #endif
+
+ TS_Installed = TRUE;
+ }
+
+ return( TASK_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: TS_Shutdown
+
+ Ends processing of all tasks.
+---------------------------------------------------------------------*/
+
+void TS_Shutdown
+ (
+ void
+ )
+
+ {
+ if ( TS_Installed )
+ {
+ TS_FreeTaskList();
+
+ TS_SetClockSpeed( 0 );
+
+ _dos_setvect( 0x08, OldInt8 );
+
+#ifdef USESTACK
+
+ deallocateTimerStack( StackSelector );
+ StackSelector = NULL;
+
+#endif
+
+ // Set Date and Time from CMOS
+// RestoreRealTimeClock();
+
+#ifdef LOCKMEMORY
+
+ TS_UnlockMemory();
+
+#endif
+ TS_Installed = FALSE;
+ }
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: TS_ScheduleTask
+
+ Schedules a new task for processing.
+---------------------------------------------------------------------*/
+
+task *TS_ScheduleTask
+ (
+ void ( *Function )( task * ),
+ int rate,
+ int priority,
+ void *data
+ )
+
+ {
+ task *ptr;
+
+#ifdef USE_USRHOOKS
+ int status;
+
+ ptr = NULL;
+
+ status = USRHOOKS_GetMem( &ptr, sizeof( task ) );
+ if ( status == USRHOOKS_Ok )
+#else
+ ptr = malloc( sizeof( task ) );
+ if ( ptr != NULL )
+#endif
+ {
+ if ( !TS_Installed )
+ {
+ status = TS_Startup();
+ if ( status != TASK_Ok )
+ {
+ FreeMem( ptr );
+ return( NULL );
+ }
+ }
+
+ ptr->TaskService = Function;
+ ptr->data = data;
+ ptr->rate = TS_SetTimer( rate );
+ ptr->count = 0;
+ ptr->priority = priority;
+ ptr->active = FALSE;
+
+ TS_AddTask( ptr );
+ }
+
+ return( ptr );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: TS_AddTask
+
+ Adds a new task to our list of tasks.
+---------------------------------------------------------------------*/
+
+static void TS_AddTask
+ (
+ task *node
+ )
+
+ {
+ LL_SortedInsertion( TaskList, node, next, prev, task, priority );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: TS_Terminate
+
+ Ends processing of a specific task.
+---------------------------------------------------------------------*/
+
+int TS_Terminate
+ (
+ task *NodeToRemove
+ )
+
+ {
+ task *ptr;
+ task *next;
+ unsigned flags;
+
+ flags = DisableInterrupts();
+
+ ptr = TaskList->next;
+ while( ptr != TaskList )
+ {
+ next = ptr->next;
+
+ if ( ptr == NodeToRemove )
+ {
+ LL_RemoveNode( NodeToRemove, next, prev );
+ NodeToRemove->next = NULL;
+ NodeToRemove->prev = NULL;
+ FreeMem( NodeToRemove );
+
+ TS_SetTimerToMaxTaskRate();
+
+ RestoreInterrupts( flags );
+
+ return( TASK_Ok );
+ }
+
+ ptr = next;
+ }
+
+ RestoreInterrupts( flags );
+
+ return( TASK_Warning );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: TS_Dispatch
+
+ Begins processing of all inactive tasks.
+---------------------------------------------------------------------*/
+
+void TS_Dispatch
+ (
+ void
+ )
+
+ {
+ task *ptr;
+ unsigned flags;
+
+ flags = DisableInterrupts();
+
+ ptr = TaskList->next;
+ while( ptr != TaskList )
+ {
+ ptr->active = TRUE;
+ ptr = ptr->next;
+ }
+
+ RestoreInterrupts( flags );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: TS_SetTaskRate
+
+ Sets the rate at which the specified task is serviced.
+---------------------------------------------------------------------*/
+
+void TS_SetTaskRate
+ (
+ task *Task,
+ int rate
+ )
+
+ {
+ unsigned flags;
+
+ flags = DisableInterrupts();
+
+ Task->rate = TS_SetTimer( rate );
+ TS_SetTimerToMaxTaskRate();
+
+ RestoreInterrupts( flags );
+ }
+
+
+#ifdef LOCKMEMORY
+
+/*---------------------------------------------------------------------
+ Function: TS_LockEnd
+
+ Used for determining the length of the functions to lock in memory.
+---------------------------------------------------------------------*/
+
+static void TS_LockEnd
+ (
+ void
+ )
+
+ {
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: TS_UnlockMemory
+
+ Unlocks all neccessary data.
+---------------------------------------------------------------------*/
+
+void TS_UnlockMemory
+ (
+ void
+ )
+
+ {
+ DPMI_UnlockMemoryRegion( TS_LockStart, TS_LockEnd );
+ DPMI_Unlock( TaskList );
+ DPMI_Unlock( OldInt8 );
+ DPMI_Unlock( TaskServiceRate );
+ DPMI_Unlock( TaskServiceCount );
+ DPMI_Unlock( TS_Installed );
+
+#ifndef NOINTS
+ DPMI_Unlock( TS_TimesInInterrupt );
+#endif
+
+#ifdef USESTACK
+ DPMI_Unlock( StackSelector );
+ DPMI_Unlock( StackPointer );
+ DPMI_Unlock( oldStackSelector );
+ DPMI_Unlock( oldStackPointer );
+#endif
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: TS_LockMemory
+
+ Locks all neccessary data.
+---------------------------------------------------------------------*/
+
+int TS_LockMemory
+ (
+ void
+ )
+
+ {
+ int status;
+
+ status = DPMI_LockMemoryRegion( TS_LockStart, TS_LockEnd );
+ status |= DPMI_Lock( TaskList );
+ status |= DPMI_Lock( OldInt8 );
+ status |= DPMI_Lock( TaskServiceRate );
+ status |= DPMI_Lock( TaskServiceCount );
+ status |= DPMI_Lock( TS_Installed );
+
+#ifndef NOINTS
+ status |= DPMI_Lock( TS_TimesInInterrupt );
+#endif
+
+#ifdef USESTACK
+ status |= DPMI_Lock( StackSelector );
+ status |= DPMI_Lock( StackPointer );
+ status |= DPMI_Lock( oldStackSelector );
+ status |= DPMI_Lock( oldStackPointer );
+#endif
+
+ if ( status != DPMI_Ok )
+ {
+ TS_UnlockMemory();
+ return( TASK_Error );
+ }
+
+ return( TASK_Ok );
+ }
+
+#endif
+
+/*
+// Converts a hex byte to an integer
+
+static int btoi
+ (
+ unsigned char bcd
+ )
+
+ {
+ unsigned b;
+ unsigned c;
+ unsigned d;
+
+ b = bcd / 16;
+ c = bcd - b * 16;
+ d = b * 10 + c;
+ return( d );
+ }
+
+
+static void RestoreRealTimeClock
+ (
+ void
+ )
+
+ {
+ int read;
+ int i;
+ int hr;
+ int min;
+ int sec;
+ int cent;
+ int yr;
+ int mo;
+ int day;
+ int year;
+ union REGS inregs;
+
+ // Read Real Time Clock Time.
+ read = FALSE;
+ inregs.h.ah = 0x02;
+ for( i = 1; i <= 3; i++ )
+ {
+ int386( 0x1A, &inregs, &inregs );
+ if ( inregs.x.cflag == 0 )
+ {
+ read = TRUE;
+ }
+ }
+
+ if ( read )
+ {
+ //and convert BCD to integer format
+ hr = btoi( inregs.h.ch );
+ min = btoi( inregs.h.cl );
+ sec = btoi( inregs.h.dh );
+
+ // Read Real Time Clock Date.
+ inregs.h.ah = 0x04;
+ int386( 0x1A, &inregs, &inregs );
+ if ( inregs.x.cflag == 0 )
+ {
+ //and convert BCD to integer format
+ cent = btoi( inregs.h.ch );
+ yr = btoi( inregs.h.cl );
+ mo = btoi( inregs.h.dh );
+ day = btoi( inregs.h.dl );
+ year = cent * 100 + yr;
+
+ // Set System Time.
+ inregs.h.ch = hr;
+ inregs.h.cl = min;
+ inregs.h.dh = sec;
+ inregs.h.dl = 0;
+ inregs.h.ah = 0x2D;
+ int386( 0x21, &inregs, &inregs );
+
+ // Set System Date.
+ inregs.w.cx = year;
+ inregs.h.dh = mo;
+ inregs.h.dl = day;
+ inregs.h.ah = 0x2B;
+ int386( 0x21, &inregs, &inregs );
+ }
+ }
+ }
+*/
+/*
+ struct dostime_t time;
+ struct dosdate_t date;
+
+ outp(0x70,0);
+ time.second=inp(0x71);
+ outp(0x70,2);
+ time.minute=inp(0x71);
+ outp(0x70,4);
+ time.hour=inp(0x71);
+
+ outp(0x70,7);
+ date.day=inp(0x71);
+ outp(0x70,8);
+ date.month=inp(0x71);
+ outp(0x70,9);
+ date.year=inp(0x71);
+
+ time.second=(time.second&0x0f)+((time.second>>4)*10);
+ time.minute=(time.minute&0x0f)+((time.minute>>4)*10);
+ time.hour=(time.hour&0x0f)+((time.hour>>4)*10);
+
+ date.day=(date.day&0x0f)+((date.day>>4)*10);
+ date.month=(date.month&0x0f)+((date.month>>4)*10);
+ date.year=(date.year&0x0f)+((date.year>>4)*10);
+
+ _dos_settime(&time);
+ _dos_setdate(&date);
+
+*/
--- /dev/null
+++ b/rott/audiolib/task_man.h
@@ -1,0 +1,68 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: TASK_MAN.C
+
+ author: James R. Dose
+ date: July 25, 1994
+
+ Public header for TASK_MAN.C, a low level timer task scheduler.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __TASK_MAN_H
+#define __TASK_MAN_H
+
+enum TASK_ERRORS
+ {
+ TASK_Warning = -2,
+ TASK_Error = -1,
+ TASK_Ok = 0
+ };
+
+typedef struct task
+{
+ struct task *next;
+ struct task *prev;
+ void ( *TaskService )( struct task * );
+ void *data;
+ long rate;
+ volatile long count;
+ int priority;
+ int active;
+} task;
+
+// TS_InInterrupt is TRUE during a taskman interrupt.
+// Use this if you have code that may be used both outside
+// and within interrupts.
+
+extern volatile int TS_InInterrupt;
+
+void TS_Shutdown( void );
+task *TS_ScheduleTask( void ( *Function )( task * ), int rate,
+ int priority, void *data );
+int TS_Terminate( task *ptr );
+void TS_Dispatch( void );
+void TS_SetTaskRate( task *Task, int rate );
+void TS_UnlockMemory( void );
+int TS_LockMemory( void );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/user.c
@@ -1,0 +1,133 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: USER.C
+
+ author: James R. Dose
+ date: April 26, 1994
+
+ Routines to parse command line options.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifdef PLAT_DOS
+#include <dos.h>
+#endif
+
+#include <string.h>
+#include "user.h"
+
+#define TRUE ( 1 == 1 )
+#define FALSE ( !TRUE )
+
+#ifdef PLAT_DOS
+extern int _argc;
+extern char **_argv;
+#endif
+
+/*---------------------------------------------------------------------
+ Function: USER_CheckParameter
+
+ Checks if the specified string is present in the command line.
+---------------------------------------------------------------------*/
+
+int USER_CheckParameter
+ (
+ const char *parameter
+ )
+
+ {
+#ifdef PLAT_DOS
+ int i;
+ int found;
+ char *ptr;
+
+ found = FALSE;
+ i = 1;
+ while( i < _argc )
+ {
+ ptr = _argv[ i ];
+
+ // Only check parameters preceded by - or /
+ if ( ( *ptr == '-' ) || ( *ptr == '/' ) )
+ {
+ ptr++;
+ if ( stricmp( parameter, ptr ) == 0 )
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ i++;
+ }
+
+ return( found );
+#else
+ return FALSE;
+#endif
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: USER_GetText
+
+ Checks if the specified string is present in the command line
+ and returns a pointer to the text following it.
+---------------------------------------------------------------------*/
+
+char *USER_GetText
+ (
+ const char *parameter
+ )
+
+ {
+#ifdef PLAT_DOS
+ int i;
+ char *text;
+ char *ptr;
+
+ text = NULL;
+ i = 1;
+ while( i < _argc )
+ {
+ ptr = _argv[ i ];
+
+ // Only check parameters preceded by - or /
+ if ( ( *ptr == '-' ) || ( *ptr == '/' ) )
+ {
+ ptr++;
+ if ( stricmp( parameter, ptr ) == 0 )
+ {
+ i++;
+ text = _argv[ i ];
+ break;
+ }
+ }
+
+ i++;
+ }
+
+ return( text );
+#else
+ return NULL;
+#endif
+ }
--- /dev/null
+++ b/rott/audiolib/user.h
@@ -1,0 +1,38 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: USER.H
+
+ author: James R. Dose
+ phone: (214)-271-1365 Ext #221
+ date: April 26, 1994
+
+ Public header for USER.C
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __USER_H
+#define __USER_H
+
+int USER_CheckParameter( const char *parameter );
+char *USER_GetText( const char *parameter );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/usrhooks.c
@@ -1,0 +1,84 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: USRHOOKS.C
+
+ author: James R. Dose
+ date: July 26, 1994
+
+ This module contains cover functions for operations the library
+ needs that may be restricted by the calling program. This code
+ is left public for you to modify.
+**********************************************************************/
+
+#include <stdlib.h>
+#include "usrhooks.h"
+
+
+/*---------------------------------------------------------------------
+ Function: USRHOOKS_GetMem
+
+ Allocates the requested amount of memory and returns a pointer to
+ its location, or NULL if an error occurs. NOTE: pointer is assumed
+ to be dword aligned.
+---------------------------------------------------------------------*/
+
+int USRHOOKS_GetMem
+ (
+ void **ptr,
+ unsigned long size
+ )
+
+ {
+ void *memory;
+
+ memory = malloc( size );
+ if ( memory == NULL )
+ {
+ return( USRHOOKS_Error );
+ }
+
+ *ptr = memory;
+
+ return( USRHOOKS_Ok );
+ }
+
+
+/*---------------------------------------------------------------------
+ Function: USRHOOKS_FreeMem
+
+ Deallocates the memory associated with the specified pointer.
+---------------------------------------------------------------------*/
+
+int USRHOOKS_FreeMem
+ (
+ void *ptr
+ )
+
+ {
+ if ( ptr == NULL )
+ {
+ return( USRHOOKS_Error );
+ }
+
+ free( ptr );
+
+ return( USRHOOKS_Ok );
+ }
--- /dev/null
+++ b/rott/audiolib/usrhooks.h
@@ -1,0 +1,55 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: USRHOOKS.H
+
+ author: James R. Dose
+ date: July 26, 1994
+
+ Public header file for USRHOOKS.C.
+
+ This module contains cover functions for operations the library
+ needs that may be restricted by the calling program. The function
+ prototypes in this header should not be modified.
+**********************************************************************/
+
+#ifndef __USRHOOKS_H
+#define __USRHOOKS_H
+
+/*---------------------------------------------------------------------
+ Error definitions
+---------------------------------------------------------------------*/
+
+enum USRHOOKS_Errors
+ {
+ USRHOOKS_Warning = -2,
+ USRHOOKS_Error = -1,
+ USRHOOKS_Ok = 0
+ };
+
+
+/*---------------------------------------------------------------------
+ Function Prototypes
+---------------------------------------------------------------------*/
+
+int USRHOOKS_GetMem( void **ptr, unsigned long size );
+int USRHOOKS_FreeMem( void *ptr );
+
+#endif
--- /dev/null
+++ b/rott/audiolib/util.h
@@ -1,0 +1,13 @@
+#ifndef AUDIOLIB__UTIL_H
+#define AUDIOLIB__UTIL_H
+
+#ifndef min
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef max
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+#endif
+
--- /dev/null
+++ b/rott/byteordr.c
@@ -1,0 +1,84 @@
+/*
+Copyright (C) 2002 John R. Hall
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// byteordr.c - Byte order conversion routines.
+//
+//***************************************************************************
+
+#include "rt_def.h"
+#include "rt_util.h"
+#include "byteordr.h"
+#include "lumpy.h"
+
+#define DEFINE_CONVERTER(type) \
+void Cvt_##type(void *lmp, int num) \
+{ \
+ int i; \
+ type *recs = (type *)lmp; \
+ for (i = 0; i < num; i++, recs++) { \
+ CONVERT_ENDIAN_##type(recs); \
+ } \
+}
+
+DEFINE_CONVERTER(pic_t);
+DEFINE_CONVERTER(lpic_t);
+DEFINE_CONVERTER(font_t);
+DEFINE_CONVERTER(lbm_t);
+DEFINE_CONVERTER(patch_t);
+DEFINE_CONVERTER(transpatch_t);
+DEFINE_CONVERTER(cfont_t);
+
+
+void CvtNull(void *lmp, int num)
+{
+ Debug("No-op endian converter on %p.\n", lmp);
+}
+
+// Returns converter for the designated type
+converter_t CvtForType(int type)
+{
+ switch(type) {
+ case cache_pic_t:
+ return Cvt_pic_t;
+ break;
+ case cache_lpic_t:
+ return Cvt_lpic_t;
+ break;
+ case cache_font_t:
+ return Cvt_font_t;
+ break;
+ case cache_lbm_t:
+ return Cvt_lbm_t;
+ break;
+ case cache_patch_t:
+ return Cvt_patch_t;
+ break;
+ case cache_transpatch_t:
+ return Cvt_transpatch_t;
+ break;
+ case cache_cfont_t:
+ return Cvt_cfont_t;
+ break;
+ default:
+ return CvtNull;
+ break;
+ }
+}
--- /dev/null
+++ b/rott/byteordr.h
@@ -1,0 +1,43 @@
+/*
+Copyright (C) 2002 John R. Hall
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// byteordr.c - Byte order conversion routines.
+//
+//***************************************************************************
+
+#ifndef BYTEORDER_H
+#define BYTEORDER_H
+
+typedef void (*converter_t)(void *, int);
+
+#define DECLARE_CONVERTER(type) void Cvt_##type(void *lmp, int num);
+
+DECLARE_CONVERTER(pic_t);
+DECLARE_CONVERTER(lpic_t);
+DECLARE_CONVERTER(font_t);
+DECLARE_CONVERTER(lbm_t);
+DECLARE_CONVERTER(patch_t);
+DECLARE_CONVERTER(transpatch_t);
+DECLARE_CONVERTER(cfont_t);
+void CvtNull(void *lmp, int num);
+converter_t CvtForType(int type);
+
+#endif
--- /dev/null
+++ b/rott/cin_actr.c
@@ -1,0 +1,305 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "cin_glob.h"
+#include "cin_def.h"
+#include "cin_actr.h"
+#include "cin_efct.h"
+#include "modexlib.h"
+//MED
+#include "memcheck.h"
+
+actortype * firstcinematicactor;
+actortype * lastcinematicactor;
+
+
+// LOCALS
+
+boolean cinematicactorsystemstarted=false;
+static int numcinematicactors;
+
+/*
+===============
+=
+= AddCinematicActor
+=
+===============
+*/
+
+void AddCinematicActor ( actortype * actor )
+{
+ if (!firstcinematicactor)
+ {
+ firstcinematicactor = actor;
+ }
+ else
+ {
+ actor->prev = lastcinematicactor;
+ lastcinematicactor->next = actor;
+ }
+ lastcinematicactor = actor;
+}
+
+
+/*
+===============
+=
+= DeleteCinematicActor
+=
+===============
+*/
+
+void DeleteCinematicActor ( actortype * actor)
+{
+ if (actor == lastcinematicactor)
+ {
+ lastcinematicactor = actor->prev;
+ }
+ else
+ {
+ actor->next->prev = actor->prev;
+ }
+
+ if (actor == firstcinematicactor)
+ {
+ firstcinematicactor = actor->next;
+ }
+ else
+ {
+ actor->prev->next = actor->next;
+ }
+
+ actor->prev = NULL;
+ actor->next = NULL;
+
+ if (actor->effect != NULL)
+ SafeFree(actor->effect);
+ SafeFree(actor);
+}
+
+/*
+===============
+=
+= GetNewCinematicActor
+=
+===============
+*/
+
+actortype * GetNewCinematicActor ( void )
+{
+ actortype * actor;
+
+ numcinematicactors++;
+
+ if ( numcinematicactors > MAXCINEMATICACTORS )
+ Error ("Too many Cinematic actors\n");
+
+ actor = SafeMalloc( sizeof (actortype) );
+
+ actor->next=NULL;
+ actor->prev=NULL;
+
+ AddCinematicActor ( actor );
+
+ return actor;
+}
+
+/*
+===============
+=
+= StartupCinematicActors
+=
+===============
+*/
+
+void StartupCinematicActors ( void )
+{
+ if (cinematicactorsystemstarted==true)
+ return;
+ cinematicactorsystemstarted=true;
+ firstcinematicactor = NULL;
+ lastcinematicactor = NULL;
+
+ numcinematicactors=0;
+}
+
+/*
+===============
+=
+= ShutdownCinematicActors
+=
+===============
+*/
+
+void ShutdownCinematicActors ( void )
+{
+ actortype * actor;
+ if (cinematicactorsystemstarted==false)
+ return;
+ cinematicactorsystemstarted=false;
+
+ actor=firstcinematicactor;
+ while (actor != NULL)
+ {
+ actortype * nextactor;
+
+ nextactor=actor->next;
+ DeleteCinematicActor(actor);
+ actor=nextactor;
+ }
+}
+
+/*
+===============
+=
+= SpawnCinematicActor
+=
+===============
+*/
+
+void SpawnCinematicActor ( enum_eventtype type, void * effect )
+{
+ actortype * actor;
+
+ actor = GetNewCinematicActor ();
+ actor->effecttype=type;
+ actor->effect=effect;
+}
+
+/*
+===============
+=
+= UpdateCinematicActors
+=
+===============
+*/
+void UpdateCinematicActors ( void )
+{
+ actortype * actor;
+
+ for (actor=firstcinematicactor; actor != NULL;)
+ {
+ if (UpdateCinematicEffect ( actor->effecttype, actor->effect ) == false)
+ {
+ actortype * nextactor;
+
+ nextactor=actor->next;
+ DeleteCinematicActor(actor);
+ actor=nextactor;
+ }
+ else
+ actor=actor->next;
+ }
+}
+
+/*
+===============
+=
+= DrawCinematicActors
+=
+===============
+*/
+typedef enum {
+ screenfunctions,
+ background,
+ backgroundsprites,
+ backdrop,
+ foregroundsprites,
+ palettefunctions,
+ numdrawphases
+} enum_drawphases;
+
+void DrawCinematicActors ( void )
+{
+ actortype * actor;
+ actortype * nextactor;
+ boolean draw;
+ enum_drawphases sequence;
+#if DUMP
+ int numactors=0;
+#endif
+ boolean flippage=true;
+
+ for (sequence=screenfunctions; sequence<numdrawphases; sequence++)
+ {
+ for (actor=firstcinematicactor; actor != NULL;)
+ {
+ draw=false;
+ switch (actor->effecttype)
+ {
+ case fadeout:
+ case blankscreen:
+ case clearbuffer:
+ case cinematicend:
+ case flic:
+ if (sequence==screenfunctions)
+ draw=true;
+ flippage=false;
+ break;
+ case palette:
+ if (sequence==palettefunctions)
+ draw=true;
+ flippage=false;
+ break;
+ case background_noscrolling:
+ case background_scrolling:
+ case background_multi:
+ if (sequence==background)
+ draw=true;
+ break;
+ case sprite_background:
+ if (sequence==backgroundsprites)
+ draw=true;
+ break;
+ case backdrop_noscrolling:
+ case backdrop_scrolling:
+ if (sequence==backdrop)
+ draw=true;
+ break;
+ case sprite_foreground:
+ if (sequence==foregroundsprites)
+ draw=true;
+ break;
+ }
+ nextactor=actor->next;
+ if (draw==true)
+ {
+#if DUMP
+ printf("drawing type=%ld\n",actor->effecttype);
+#endif
+ if (DrawCinematicEffect ( actor->effecttype, actor->effect ) == false)
+ {
+ DeleteCinematicActor(actor);
+ }
+#if DUMP
+ numactors++;
+#endif
+ }
+ actor=nextactor;
+ }
+ }
+ if (flippage==true)
+ XFlipPage ();
+#if DUMP
+ printf("Total actors drawn=%ld\n",numactors);
+#endif
+}
+
+
--- /dev/null
+++ b/rott/cin_actr.h
@@ -1,0 +1,40 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _cin_actr_public
+#define _cin_actr_public
+
+#include "cin_glob.h"
+#include "cin_def.h"
+
+extern actortype * firstcinematicactor;
+extern actortype * lastcinematicactor;
+
+void AddCinematicActor ( actortype * actor );
+void DeleteCinematicActor ( actortype * actor);
+
+actortype * GetNewCinematicActor ( void );
+void StartupCinematicActors ( void );
+void ShutdownCinematicActors ( void );
+void SpawnCinematicActor ( enum_eventtype type, void * effect );
+void DrawCinematicActors ( void );
+void UpdateCinematicActors ( void );
+
+#endif
+
--- /dev/null
+++ b/rott/cin_def.h
@@ -1,0 +1,104 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _cin_def_public
+#define _cin_def_public
+
+#define MAXCINEMATICEVENTS 100
+#define MAXCINEMATICACTORS 30
+
+#define FRACTIONBITS (16)
+#define FRACTIONUNIT (1<<FRACTIONBITS)
+
+typedef enum {
+ background_noscrolling,
+ background_scrolling,
+ background_multi,
+ sprite_background,
+ sprite_foreground,
+ backdrop_scrolling,
+ backdrop_noscrolling,
+ palette,
+ flic,
+ fadeout,
+ cinematicend,
+ blankscreen,
+ clearbuffer
+} enum_eventtype;
+
+typedef struct eventtype
+{
+ int time;
+ enum_eventtype effecttype;
+ void * effect;
+ struct eventtype * next;
+ struct eventtype * prev;
+} eventtype;
+
+typedef struct actortype
+{
+ enum_eventtype effecttype;
+ void * effect;
+ struct actortype * next;
+ struct actortype * prev;
+} actortype;
+
+typedef struct
+{
+ char name[10];
+ boolean loop;
+ boolean usefile;
+} flicevent;
+
+typedef struct
+{
+ char name[10];
+ int duration;
+ int frame;
+ int frametime;
+ int numframes;
+ int framedelay;
+ int x;
+ int y;
+ int scale;
+ int dx;
+ int dy;
+ int dscale;
+} spriteevent;
+
+typedef struct
+{
+ char name[10];
+ int duration;
+ int backdropwidth;
+ int currentoffset;
+ int dx;
+ int yoffset;
+ int height;
+ byte * data;
+} backevent;
+
+typedef struct
+{
+ char name[10];
+} paletteevent;
+
+
+#endif
+
--- /dev/null
+++ b/rott/cin_efct.c
@@ -1,0 +1,957 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "cin_glob.h"
+#include "cin_util.h"
+#include "cin_def.h"
+#include "cin_main.h"
+#include "f_scale.h"
+#include "watcom.h"
+#include "lumpy.h"
+#include "w_wad.h"
+#include "z_zone.h"
+#include <string.h>
+
+#ifdef DOS
+#include <conio.h>
+#endif
+
+#include "modexlib.h"
+#include "fli_glob.h"
+//MED
+#include "memcheck.h"
+
+static int cin_sprtopoffset;
+static int cin_invscale;
+
+void DrawFadeout ( void );
+void DrawBlankScreen ( void );
+void DrawClearBuffer ( void );
+
+/*
+===============
+=
+= SpawnCinematicFlic
+=
+===============
+*/
+
+flicevent * SpawnCinematicFlic ( char * name, boolean loop, boolean usefile )
+{
+ flicevent * flic;
+
+ flic = SafeMalloc ( sizeof(flicevent) );
+
+ // copy name of flic
+
+ strcpy ( flic->name, name );
+
+ flic->loop=loop;
+
+ flic->usefile=usefile;
+
+ return flic;
+}
+
+/*
+===============
+=
+= SpawnCinematicSprite
+=
+===============
+*/
+
+spriteevent * SpawnCinematicSprite ( char * name,
+ int duration,
+ int numframes,
+ int framedelay,
+ int x,
+ int y,
+ int scale,
+ int endx,
+ int endy,
+ int endscale
+ )
+{
+ spriteevent * sprite;
+ patch_t *p;
+
+ sprite = SafeMalloc ( sizeof (spriteevent) );
+
+ // copy name of sprite
+
+ strcpy ( sprite->name, name );
+
+ // copy rest of sprite information
+
+ sprite->duration = duration;
+ sprite->numframes = numframes;
+ sprite->framedelay = framedelay;
+ sprite->frame=0;
+ sprite->frametime=framedelay;
+
+ p=(patch_t *)W_CacheLumpNum( W_GetNumForName(sprite->name), PU_CACHE, Cvt_patch_t, 1);
+
+ sprite->x=x << FRACTIONBITS;
+ sprite->y=y << FRACTIONBITS;
+
+// sprite->y+=(p->width-p->height)<<(FRACTIONBITS-1);
+
+ sprite->scale=scale << FRACTIONBITS;
+ sprite->dx= ( (endx-x) << FRACTIONBITS ) / duration;
+ sprite->dy= ( (endy-y) << FRACTIONBITS ) / duration;
+ sprite->dscale= ( (endscale-scale) << FRACTIONBITS ) / duration;
+
+ return sprite;
+}
+
+/*
+===============
+=
+= SpawnCinematicBack
+=
+===============
+*/
+
+backevent * SpawnCinematicBack ( char * name,
+ int duration,
+ int width,
+ int startx,
+ int endx,
+ int yoffset
+ )
+{
+ backevent * back;
+
+ back = SafeMalloc ( sizeof (backevent) );
+
+ // copy name of back
+
+ strcpy ( back->name, name );
+
+ // copy rest of back information
+
+ back->duration = duration;
+ back->backdropwidth = width;
+ back->dx = ((endx-startx) << FRACTIONBITS)/duration;
+ back->currentoffset = startx << FRACTIONBITS;
+ back->yoffset=yoffset;
+
+ return back;
+}
+
+/*
+===============
+=
+= SpawnCinematicMultiBack
+=
+===============
+*/
+
+backevent * SpawnCinematicMultiBack ( char * name,
+ char * name2,
+ int duration,
+ int startx,
+ int endx,
+ int yoffset
+ )
+{
+ backevent * back;
+ lpic_t * pic1;
+ lpic_t * pic2;
+
+ pic1=(lpic_t *)W_CacheLumpName(name,PU_CACHE, Cvt_lpic_t, 1);
+ pic2=(lpic_t *)W_CacheLumpName(name2,PU_CACHE, Cvt_lpic_t, 1);
+
+ back = SafeMalloc ( sizeof (backevent) );
+
+ // copy name of back
+
+ strcpy ( back->name, name );
+
+ // copy rest of back information
+
+ back->duration = duration;
+ back->dx = ((endx-startx) << FRACTIONBITS)/duration;
+ back->currentoffset = startx << FRACTIONBITS;
+ back->yoffset=yoffset;
+ if (pic1->height != pic2->height)
+ {
+ Error("SpawnCinematicMultiBack: heights are not the same\n"
+ " name1=%s name2=%s\n",name,name2);
+ }
+ back->backdropwidth=pic1->width+pic2->width;
+ back->height=pic1->height;
+ back->data=SafeMalloc (back->backdropwidth*back->height);
+ memcpy( back->data, &(pic1->data), pic1->width*pic1->height);
+ memcpy( back->data+(pic1->width*pic1->height),
+ &(pic2->data),
+ pic2->width*pic2->height
+ );
+ return back;
+}
+
+/*
+===============
+=
+= SpawnCinematicPalette
+=
+===============
+*/
+
+paletteevent * SpawnCinematicPalette ( char * name )
+{
+ paletteevent * palette;
+
+ palette = SafeMalloc ( sizeof (paletteevent) );
+
+ // copy name of palette
+
+ strcpy ( palette->name, name );
+
+ return palette;
+}
+
+
+/*
+=================
+=
+= ScaleFilmPost
+=
+=================
+*/
+void ScaleFilmPost (byte * src, byte * buf)
+{
+ int offset;
+ int length;
+ int topscreen;
+ int bottomscreen;
+
+
+ offset=*(src++);
+ for (; offset!=255;)
+ {
+ length=*(src++);
+ topscreen = cin_sprtopoffset + (cin_invscale*offset);
+ bottomscreen = topscreen + (cin_invscale*length);
+ cin_yl = (topscreen+FRACTIONUNIT-1)>>FRACTIONBITS;
+ cin_yh = (bottomscreen-FRACTIONUNIT)>>FRACTIONBITS;
+ if (cin_yh >= iGLOBAL_SCREENHEIGHT)
+ cin_yh = iGLOBAL_SCREENHEIGHT-1;
+ if (cin_yl < 0)
+ cin_yl = 0;
+ if (cin_yl <= cin_yh)
+ {
+ cin_source=src-offset;
+ R_DrawFilmColumn (buf);
+ }
+ src+=length;
+ offset=*(src++);
+ }
+
+}
+
+/*
+=================
+=
+= DrawFlic
+=
+=================
+*/
+void DrawFlic ( flicevent * flic )
+{
+ byte * curpal;
+ byte * buf;
+ char flicname[40];
+
+ curpal = SafeMalloc (768);
+
+ CinematicGetPalette (curpal);
+
+ DrawFadeout ( );
+
+ if (flic->usefile==false)
+ {
+ buf=W_CacheLumpName(flic->name,PU_CACHE, CvtNull, 1);
+ strcpy(flicname,flic->name);
+ }
+ else
+ {
+ strcpy(flicname,flic->name);
+ strcat(flicname,".fli");
+ }
+
+// med
+// PlayFlic ( flicname, buf, flic->usefile, flic->loop);
+
+ if (flic->loop==true)
+ ClearCinematicAbort();
+
+ DrawFadeout ( );
+
+ DrawBlankScreen ( );
+
+#ifdef DOS
+ VL_SetVGAPlaneMode ();
+#endif
+
+ CinematicSetPalette (curpal);
+
+ SafeFree (curpal);
+ GetCinematicTics ();
+ GetCinematicTics ();
+}
+
+/*
+=================
+=
+= PrecacheFlic
+=
+=================
+*/
+
+void PrecacheFlic (flicevent * flic)
+{
+ if (flic->usefile==false)
+ {
+ W_CacheLumpName(flic->name,PU_CACHE, CvtNull, 1);
+ }
+}
+
+/*
+===============
+=
+= DrawCinematicBackground
+=
+===============
+*/
+
+void DrawCinematicBackground ( backevent * back )
+{
+ byte * src;
+ byte * buf;
+ lpic_t * pic;
+ int i;
+ int plane;
+ int offset;
+ int height;
+
+ pic=(lpic_t *)W_CacheLumpName(back->name,PU_CACHE, Cvt_lpic_t, 1);
+
+ height = pic->height;
+ if (height+back->yoffset>iGLOBAL_SCREENHEIGHT)
+ height=iGLOBAL_SCREENHEIGHT-back->yoffset;
+
+ if (height!=iGLOBAL_SCREENHEIGHT)
+ DrawClearBuffer ();
+
+ plane = 0;
+
+#ifdef DOS
+ for (plane=0; plane<4; plane++)
+#endif
+ {
+ buf=(byte *)bufferofs+ylookup[back->yoffset];
+ offset=(back->currentoffset>>FRACTIONBITS)+plane;
+
+ VGAWRITEMAP(plane);
+
+#ifdef DOS
+ for (i=plane; i<iGLOBAL_SCREENWIDTH; i+=4,offset+=4,buf++)
+#else
+ for (i=0; i<iGLOBAL_SCREENWIDTH; i++,offset++,buf++)
+#endif
+ {
+ if (offset>=back->backdropwidth)
+ src=&(pic->data) + ( (offset - back->backdropwidth) * (pic->height) );
+ else if (offset<0)
+ src=&(pic->data) + ( (offset + back->backdropwidth) * (pic->height) );
+ else
+ src=&(pic->data) + ( offset * (pic->height) );
+ DrawFilmPost(buf,src,height);
+ }
+ }
+}
+
+/*
+===============
+=
+= DrawCinematicMultiBackground
+=
+===============
+*/
+
+void DrawCinematicMultiBackground ( backevent * back )
+{
+ byte * src;
+ byte * buf;
+ int i;
+ int plane;
+ int offset;
+ int height;
+
+ height = back->height;
+ if (height+back->yoffset>iGLOBAL_SCREENHEIGHT)
+ height=iGLOBAL_SCREENHEIGHT-back->yoffset;
+
+ if (height!=iGLOBAL_SCREENHEIGHT)
+ DrawClearBuffer ();
+
+ plane = 0;
+
+#ifdef DOS
+ for (plane=0; plane<4; plane++)
+#endif
+ {
+ buf=(byte *)bufferofs+ylookup[back->yoffset];
+ offset=(back->currentoffset>>FRACTIONBITS)+plane;
+
+ VGAWRITEMAP(plane);
+
+#ifdef DOS
+ for (i=plane; i<iGLOBAL_SCREENWIDTH; i+=4,offset+=4,buf++)
+#else
+ for (i=0; i<iGLOBAL_SCREENWIDTH; i++,offset++,buf++)
+#endif
+ {
+ if (offset>=back->backdropwidth)
+ src=back->data + ( (offset - back->backdropwidth) * (back->height) );
+ else if (offset<0)
+ src=back->data + ( (offset + back->backdropwidth) * (back->height) );
+ else
+ src=back->data + ( offset * (back->height) );
+ DrawFilmPost(buf,src,height);
+ }
+ }
+}
+
+/*
+===============
+=
+= DrawCinematicBackdrop
+=
+===============
+*/
+
+void DrawCinematicBackdrop ( backevent * back )
+{
+ byte * src;
+ byte * shape;
+ byte * buf;
+ patch_t * p;
+ int i;
+ int plane;
+ int offset;
+ int postoffset;
+ int postlength;
+ int toppost;
+
+ shape=W_CacheLumpName(back->name,PU_CACHE, Cvt_patch_t, 1);
+ p=(patch_t *)shape;
+
+ toppost=-p->topoffset+back->yoffset;
+
+ plane = 0;
+
+#ifdef DOS
+ for (plane=0; plane<4; plane++)
+#endif
+ {
+ buf=(byte *)bufferofs;
+ offset=(back->currentoffset>>FRACTIONBITS)+plane;
+
+ VGAWRITEMAP(plane);
+
+#ifdef DOS
+ for (i=plane; i<iGLOBAL_SCREENWIDTH; i+=4,offset+=4,buf++)
+#else
+ for (i=0; i<iGLOBAL_SCREENWIDTH; i++,offset++,buf++)
+#endif
+ {
+ if (offset>=back->backdropwidth)
+ src = shape + p->collumnofs[offset - back->backdropwidth];
+ else if (offset<0)
+ src=shape + p->collumnofs[offset + back->backdropwidth];
+ else
+ src = shape + p->collumnofs[offset];
+
+ postoffset=*(src++);
+ for (; postoffset!=255;)
+ {
+ postlength=*(src++);
+ DrawFilmPost(buf + ylookup[toppost+postoffset],src,postlength);
+ src+=postlength;
+ postoffset=*(src++);
+ }
+ }
+ }
+}
+
+/*
+=================
+=
+= PrecacheBack
+=
+=================
+*/
+void PrecacheBack ( backevent * back )
+{
+ W_CacheLumpName( back->name, PU_CACHE, CvtNull, 1);
+}
+
+
+/*
+=================
+=
+= DrawCinematicSprite
+=
+=================
+*/
+void DrawCinematicSprite ( spriteevent * sprite )
+{
+ byte *shape;
+ int frac;
+ patch_t *p;
+ int x1,x2;
+ int tx;
+ int xcent;
+ byte * buf;
+ int height;
+
+ height = sprite->scale >> FRACTIONBITS;
+
+ if (height<2)
+ return;
+
+ shape=W_CacheLumpNum( W_GetNumForName(sprite->name)+sprite->frame, PU_CACHE, Cvt_patch_t, 1);
+ p=(patch_t *)shape;
+
+
+ cin_ycenter=sprite->y >> FRACTIONBITS;
+ cin_invscale = (height<<FRACTIONBITS)/p->origsize;
+ buf=(byte *)bufferofs;
+ tx=-p->leftoffset;
+ xcent=(sprite->x & 0xffff0000)-(height<<(FRACTIONBITS-1))+(FRACTIONUNIT>>1);
+
+//
+// calculate edges of the shape
+//
+ x1 = (xcent+(tx*cin_invscale))>>FRACTIONBITS;
+ if (x1 >= iGLOBAL_SCREENWIDTH)
+ return; // off the right side
+ tx+=p->width;
+ x2 = ((xcent+(tx*cin_invscale)) >>FRACTIONBITS) - 1 ;
+ if (x2 < 0)
+ return; // off the left side
+
+ cin_iscale=(p->origsize<<FRACTIONBITS)/height;
+
+ if (x1<0)
+ {
+ frac=cin_iscale*(-x1);
+ x1=0;
+ }
+ else
+ frac=0;
+ x2 = x2 >= iGLOBAL_SCREENWIDTH ? (iGLOBAL_SCREENWIDTH-1) : x2;
+
+ cin_texturemid = (((p->origsize>>1)+p->topoffset)<<FRACTIONBITS)+(FRACTIONUNIT>>1);
+ cin_sprtopoffset = (cin_ycenter<<16) - FixedMul(cin_texturemid,cin_invscale);
+
+ for (; x1<=x2 ; x1++, frac += cin_iscale)
+ {
+ VGAWRITEMAP(x1&3);
+#ifdef DOS
+ ScaleFilmPost(((p->collumnofs[frac>>FRACTIONBITS])+shape),buf+(x1>>2));
+#else
+ ScaleFilmPost(((p->collumnofs[frac>>FRACTIONBITS])+shape),buf+x1);
+#endif
+ }
+}
+
+/*
+=================
+=
+= PrecacheCinematicSprite
+=
+=================
+*/
+void PrecacheCinematicSprite ( spriteevent * sprite )
+{
+ int i;
+
+ for (i=0; i<sprite->numframes; i++)
+ {
+ W_CacheLumpNum( W_GetNumForName(sprite->name)+i, PU_CACHE, Cvt_patch_t, 1);
+ }
+}
+
+
+/*
+=================
+=
+= DrawPalette
+=
+=================
+*/
+
+void DrawPalette (paletteevent * event)
+{
+ byte * pal;
+
+ pal=W_CacheLumpName(event->name,PU_CACHE, CvtNull, 1);
+ XFlipPage ();
+ CinematicSetPalette (pal);
+}
+
+/*
+=================
+=
+= PrecachePalette
+=
+=================
+*/
+
+void PrecachePalette (paletteevent * event)
+{
+ W_CacheLumpName(event->name,PU_CACHE, CvtNull, 1);
+}
+
+
+/*
+=================
+=
+= DrawFadeout
+=
+=================
+*/
+#define FADEOUTTIME 20
+
+void DrawFadeout ( void )
+{
+ byte origpal[768];
+ byte newpal[768];
+ int i,j;
+
+ CinematicGetPalette (&origpal[0]);
+ for (j = 0; j < FADEOUTTIME; j++)
+ {
+ for (i = 0; i < 768; i++)
+ {
+ newpal[i] = ( origpal[i] * (FADEOUTTIME - j - 1) ) / FADEOUTTIME;
+ }
+ WaitVBL();
+ CinematicSetPalette (&newpal[0]);
+ CinematicDelay();
+ }
+ VL_ClearVideo (0);
+ GetCinematicTics ();
+ GetCinematicTics ();
+}
+
+/*
+=================
+=
+= DrawBlankScreen
+=
+=================
+*/
+void DrawBlankScreen ( void )
+{
+ VL_ClearVideo (0);
+}
+
+/*
+=================
+=
+= DrawClearBuffer
+=
+=================
+*/
+void DrawClearBuffer ( void )
+{
+#ifdef DOS
+ VGAMAPMASK(15);
+ memset((byte *)bufferofs,0,iGLOBAL_SCREENBWIDE*iGLOBAL_SCREENHEIGHT);
+#else
+ memset((byte *)bufferofs,0,iGLOBAL_SCREENWIDTH*iGLOBAL_SCREENHEIGHT);
+#endif
+}
+
+/*
+===============
+=
+= UpdateCinematicBack
+=
+===============
+*/
+
+boolean UpdateCinematicBack ( backevent * back )
+{
+ back->duration--;
+
+ if (back->duration<0)
+ return false;
+
+ back->currentoffset += back->dx;
+
+ return true;
+}
+
+/*
+=================
+=
+= UpdateCinematicSprite
+=
+=================
+*/
+boolean UpdateCinematicSprite ( spriteevent * sprite )
+{
+ sprite->duration--;
+
+ if (sprite->duration<0)
+ return false;
+
+ sprite->framedelay--;
+
+ if (sprite->framedelay==0)
+ {
+ sprite->frame++;
+ if (sprite->frame==sprite->numframes)
+ sprite->frame=0;
+ sprite->framedelay=sprite->frametime;
+ }
+
+ sprite->x+=sprite->dx;
+ sprite->y+=sprite->dy;
+ sprite->scale+=sprite->dscale;
+
+ return true;
+}
+
+/*
+=================
+=
+= UpdateCinematicEffect
+=
+=================
+*/
+boolean UpdateCinematicEffect ( enum_eventtype type, void * effect )
+{
+ switch (type)
+ {
+ case background_noscrolling:
+ case background_scrolling:
+ case backdrop_scrolling:
+ case backdrop_noscrolling:
+ case background_multi:
+ return UpdateCinematicBack ( (backevent *) effect );
+ break;
+ case sprite_background:
+ case sprite_foreground:
+ return UpdateCinematicSprite ( (spriteevent *) effect );
+ break;
+ case flic:
+ return true;
+ break;
+ case palette:
+ case fadeout:
+ case blankscreen:
+ case clearbuffer:
+ return true;
+ break;
+ case cinematicend:
+ cinematicdone=true;
+ return true;
+ break;
+ }
+ return true;
+}
+/*
+=================
+=
+= DrawCinematicEffect
+=
+=================
+*/
+boolean DrawCinematicEffect ( enum_eventtype type, void * effect )
+{
+ switch (type)
+ {
+ case background_noscrolling:
+ case background_scrolling:
+ DrawCinematicBackground ( (backevent *) effect );
+ return true;
+ break;
+ case background_multi:
+ DrawCinematicMultiBackground ( (backevent *) effect );
+ return true;
+ break;
+ case backdrop_scrolling:
+ case backdrop_noscrolling:
+ DrawCinematicBackdrop ( (backevent *) effect );
+ return true;
+ break;
+ case sprite_background:
+ case sprite_foreground:
+ DrawCinematicSprite ( (spriteevent *) effect );
+ return true;
+ break;
+ case flic:
+ DrawFlic ( (flicevent *) effect );
+ return false;
+ break;
+ case palette:
+ DrawPalette ( (paletteevent *) effect );
+ return false;
+ break;
+ case fadeout:
+ DrawFadeout ();
+ return false;
+ break;
+ case blankscreen:
+ DrawBlankScreen ();
+ return false;
+ break;
+ case clearbuffer:
+ DrawClearBuffer ();
+ return false;
+ break;
+ case cinematicend:
+ return true;
+ break;
+ }
+ return true;
+}
+
+/*
+=================
+=
+= PrecacheCinematicEffect
+=
+=================
+*/
+void PrecacheCinematicEffect ( enum_eventtype type, void * effect )
+{
+ switch (type)
+ {
+ case background_noscrolling:
+ case background_scrolling:
+ case backdrop_scrolling:
+ case backdrop_noscrolling:
+ PrecacheBack ( (backevent *) effect );
+ break;
+ case sprite_background:
+ case sprite_foreground:
+ PrecacheCinematicSprite ( (spriteevent *) effect );
+ break;
+ case palette:
+ PrecachePalette ( (paletteevent *) effect );
+ break;
+ case flic:
+ PrecacheFlic ( (flicevent *) effect );
+ break;
+ default:
+ ;
+ }
+}
+
+/*
+===============
+=
+= ProfileDisplay
+=
+===============
+*/
+
+void ProfileDisplay ( void )
+{
+ byte * buf;
+ int i;
+ int plane;
+ byte src[200];
+ int width = StretchScreen? 320:iGLOBAL_SCREENWIDTH;
+
+ DrawClearBuffer ();
+
+ plane = 0;
+
+#ifdef DOS
+ for (plane=0; plane<4; plane++)
+#endif
+ {
+ buf=(byte *)bufferofs;
+ VGAWRITEMAP(plane);
+
+#ifdef DOS
+ for (i=plane; i<width; i+=4,buf++)
+#else
+ for (i=0; i<width; i++,buf++)
+#endif
+ {
+ DrawFilmPost(buf,&src[0],200);
+ }
+ }
+}
+
+/*
+===============
+=
+= DrawPostPic
+=
+===============
+*/
+
+void DrawPostPic ( int lumpnum )
+{
+ byte * src;
+ byte * buf;
+ lpic_t * pic;
+ int i;
+ int plane;
+ int height;
+ int width = StretchScreen? 320:iGLOBAL_SCREENWIDTH;
+
+ pic=(lpic_t *)W_CacheLumpNum(lumpnum,PU_CACHE, Cvt_lpic_t, 1);
+
+ height = pic->height;
+
+ plane = 0;
+
+#ifdef DOS
+ for (plane=0; plane<4; plane++)
+#endif
+ {
+ buf=(byte *)bufferofs;
+
+ src=&(pic->data) + (plane*pic->height);
+
+ VGAWRITEMAP(plane);
+
+#ifdef DOS
+ for (i=plane; i<width; i+=4,src+=(pic->height<<2),buf++)
+#else
+ for (i=0; i<width; i++,src+=pic->height,buf++)
+#endif
+ {
+ DrawFilmPost(buf,src,height);
+ }
+ }
+}
--- /dev/null
+++ b/rott/cin_efct.h
@@ -1,0 +1,70 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _cin_efct_public
+#define _cin_efct_public
+
+#include "cin_glob.h"
+#include "cin_def.h"
+
+flicevent * SpawnCinematicFlic ( char * name, boolean loop, boolean usefile );
+spriteevent * SpawnCinematicSprite ( char * name,
+ int duration,
+ int numframes,
+ int framedelay,
+ int x,
+ int y,
+ int scale,
+ int endx,
+ int endy,
+ int endscale
+ );
+backevent * SpawnCinematicBack ( char * name,
+ int duration,
+ int width,
+ int startx,
+ int endx,
+ int yoffset
+ );
+
+backevent * SpawnCinematicMultiBack ( char * name,
+ char * name2,
+ int duration,
+ int startx,
+ int endx,
+ int yoffset
+ );
+paletteevent * SpawnCinematicPalette ( char * name );
+void DrawFlic ( flicevent * flic );
+void DrawCinematicBackdrop ( backevent * back );
+void DrawCinematicBackground ( backevent * back );
+void DrawPalette (paletteevent * event);
+void DrawCinematicSprite ( spriteevent * sprite );
+void DrawClearBuffer ( void );
+void DrawBlankScreen ( void );
+boolean DrawCinematicEffect ( enum_eventtype type, void * effect );
+boolean UpdateCinematicBack ( backevent * back );
+boolean UpdateCinematicSprite ( spriteevent * sprite );
+boolean UpdateCinematicEffect ( enum_eventtype type, void * effect );
+void PrecacheCinematicEffect ( enum_eventtype type, void * effect );
+void ProfileDisplay ( void );
+void DrawPostPic ( int lumpnum );
+
+#endif
+
--- /dev/null
+++ b/rott/cin_evnt.c
@@ -1,0 +1,530 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "cin_glob.h"
+#include "cin_evnt.h"
+#include "cin_efct.h"
+#include "cin_actr.h"
+#include "cin_def.h"
+#include "scriplib.h"
+#include "lumpy.h"
+#include "w_wad.h"
+#include "z_zone.h"
+#include <string.h>
+//MED
+#include "memcheck.h"
+
+eventtype * firstevent;
+eventtype * lastevent;
+
+// LOCALS
+
+static int numevents=0;
+static boolean eventsystemstarted=false;
+
+
+/*
+===============
+=
+= AddEvent
+=
+===============
+*/
+
+void AddEvent (eventtype * event)
+{
+ if (!firstevent)
+ firstevent = event;
+ else
+ {
+ event->prev = lastevent;
+ lastevent->next = event;
+ }
+ lastevent = event;
+}
+
+
+/*
+===============
+=
+= DeleteEvent
+=
+===============
+*/
+
+void DeleteEvent(eventtype * event)
+{
+ if (event == lastevent)
+ lastevent = event->prev;
+ else
+ event->next->prev = event->prev;
+
+ if (event == firstevent)
+ firstevent = event->next;
+ else
+ event->prev->next = event->next;
+
+ event->prev = NULL;
+ event->next = NULL;
+
+ SafeFree ( event );
+}
+
+/*
+===============
+=
+= GetNewEvent
+=
+===============
+*/
+
+eventtype * GetNewEvent ( void )
+{
+ eventtype * event;
+
+ numevents++;
+
+ if ( numevents > MAXCINEMATICEVENTS )
+ Error ("Too many Cinematic events\n");
+
+ event = SafeMalloc( sizeof (eventtype) );
+
+ event->next=NULL;
+ event->prev=NULL;
+
+ return event;
+}
+
+/*
+===============
+=
+= StartupEvents
+=
+===============
+*/
+
+void StartupEvents ( void )
+{
+ if (eventsystemstarted==true)
+ return;
+ eventsystemstarted=true;
+ firstevent = NULL;
+ lastevent = NULL;
+
+ numevents=0;
+}
+
+/*
+===============
+=
+= ShutdownEvents
+=
+===============
+*/
+
+void ShutdownEvents ( void )
+{
+ eventtype * event;
+
+ if (eventsystemstarted==false)
+ return;
+ eventsystemstarted=false;
+
+ event=firstevent;
+ while (event != NULL)
+ {
+ eventtype * nextevent;
+
+ nextevent=event->next;
+ DeleteEvent(event);
+ event=nextevent;
+ }
+}
+
+/*
+===============
+=
+= CreateEvent
+=
+===============
+*/
+eventtype * CreateEvent ( int time, int type )
+{
+ eventtype * event;
+
+ event = GetNewEvent ();
+
+ event->time = time;
+ event->effecttype = type;
+ event->effect = NULL;
+
+ AddEvent (event);
+
+ return event;
+}
+
+/*
+===============
+=
+= GetEventType
+=
+= Gets event type from token
+=
+===============
+*/
+enum_eventtype GetEventType ( void )
+{
+ // Get Event Token
+
+ GetToken (false);
+
+ if (!strcmpi (token,"BACKGROUND"))
+ {
+ GetToken (false);
+ if (!strcmpi (token,"SCROLL"))
+ {
+ return background_scrolling;
+ }
+ else if (!strcmpi (token,"NOSCROLL"))
+ {
+ return background_noscrolling;
+ }
+ else if (!strcmpi (token,"MULTISCROLL"))
+ {
+ return background_multi;
+ }
+ else
+ {
+ Error("Illegal Background Scrolling token\n");
+ }
+ }
+ else if (!strcmpi (token,"BACKDROP"))
+ {
+ GetToken (false);
+ if (!strcmpi (token,"SCROLL"))
+ {
+ return backdrop_scrolling;
+ }
+ else if (!strcmpi (token,"NOSCROLL"))
+ {
+ return backdrop_noscrolling;
+ }
+ else
+ {
+ Error("Illegal Backdrop Scrolling token\n");
+ }
+ }
+ else if (!strcmpi (token,"BACKGROUNDSPRITE"))
+ {
+ return sprite_background;
+ }
+ else if (!strcmpi (token,"FOREGROUNDSPRITE"))
+ {
+ return sprite_foreground;
+ }
+ else if (!strcmpi (token,"PALETTE"))
+ {
+ return palette;
+ }
+ else if (!strcmpi (token,"FADEOUT"))
+ {
+ return fadeout;
+ }
+ else if (!strcmpi (token,"FLIC"))
+ {
+ return flic;
+ }
+ else if (!strcmpi (token,"MOVIEEND"))
+ {
+ return cinematicend;
+ }
+ else if (!strcmpi (token,"BLANKSCREEN"))
+ {
+ return blankscreen;
+ }
+ else if (!strcmpi (token,"CLEARBUFFER"))
+ {
+ return clearbuffer;
+ }
+ else
+ {
+ Error("GetEventType: Illegal Token %s\n",token);
+ }
+ return -1;
+}
+
+/*
+===============
+=
+= ParseBack
+=
+===============
+*/
+void ParseBack ( eventtype * event )
+{
+ char name[10];
+ char name2[10];
+ int duration;
+ int yoffset;
+ int width;
+ int startx;
+ int endx;
+
+ GetToken (false);
+ strcpy(&(name[0]),token);
+
+ if (event->effecttype==background_multi)
+ {
+ GetToken (false);
+ strcpy(&(name2[0]),token);
+ }
+
+ GetToken (false);
+ duration=ParseNum(token);
+ GetToken (false);
+ yoffset=ParseNum(token);
+ if (
+ (event->effecttype==background_noscrolling) ||
+ (event->effecttype==background_scrolling)
+ )
+ {
+ lpic_t * lpic;
+
+ lpic = (lpic_t *)W_CacheLumpName(name,PU_CACHE, Cvt_lpic_t, 1);
+ width = lpic->width;
+ }
+ else if (event->effecttype!=background_multi)
+ {
+ patch_t * patch;
+
+ patch = (patch_t *)W_CacheLumpName(name,PU_CACHE, Cvt_lpic_t, 1);
+ width = patch->width;
+ }
+
+ startx=0;
+ endx=0;
+ if (
+ (event->effecttype==backdrop_scrolling) ||
+ (event->effecttype==background_scrolling) ||
+ (event->effecttype==background_multi)
+ )
+ {
+ GetToken (false);
+ startx=ParseNum(token);
+ GetToken (false);
+ endx=ParseNum(token);
+ }
+
+ if (event->effecttype==background_multi)
+ event->effect = SpawnCinematicMultiBack ( name, name2, duration, startx, endx, yoffset);
+ else
+ event->effect = SpawnCinematicBack ( name, duration, width, startx, endx, yoffset);
+}
+
+/*
+===============
+=
+= ParseSprite
+=
+===============
+*/
+void ParseSprite ( eventtype * event )
+{
+ char name[10];
+ int duration;
+ int numframes;
+ int framedelay;
+ int x,y,scale;
+ int endx,endy,endscale;
+
+ GetToken (false);
+ strcpy(&(name[0]),token);
+ GetToken (false);
+ duration=ParseNum(token);
+ GetToken (false);
+ numframes=ParseNum(token);
+ GetToken (false);
+ framedelay=ParseNum(token);
+ GetToken (false);
+ x=ParseNum(token);
+ GetToken (false);
+ y=ParseNum(token);
+ GetToken (false);
+ scale=ParseNum(token);
+ GetToken (false);
+ endx=ParseNum(token);
+ GetToken (false);
+ endy=ParseNum(token);
+ GetToken (false);
+ endscale=ParseNum(token);
+
+ event->effect = SpawnCinematicSprite ( name, duration, numframes,
+ framedelay, x, y, scale,
+ endx, endy, endscale
+ );
+}
+
+/*
+===============
+=
+= ParseFlic
+=
+===============
+*/
+void ParseFlic ( eventtype * event )
+{
+ char name[10];
+ boolean loop;
+ boolean usefile;
+
+ GetToken (false);
+ strcpy(&(name[0]),token);
+
+ GetToken (false);
+ if (!strcmpi (token,"LOOP"))
+ {
+ loop = true;
+ }
+ else if (!strcmpi (token,"NOLOOP"))
+ {
+ loop = false;
+ }
+ else
+ Error("ParseFlic: Illegal or missing flic loop token %s\n",token);
+
+ GetToken (false);
+ if (!strcmpi (token,"FILE"))
+ {
+ usefile=true;
+ }
+ else if (!strcmpi (token,"LUMP"))
+ {
+ usefile=false;
+ }
+ else
+ Error("ParseFlic: Illegal or missing flic use token %s\n",token);
+
+ event->effect = SpawnCinematicFlic ( name, loop, usefile );
+}
+
+/*
+===============
+=
+= ParsePalette
+=
+===============
+*/
+void ParsePalette ( eventtype * event )
+{
+ char name[10];
+
+ GetToken (false);
+ strcpy(&(name[0]),token);
+
+ event->effect = SpawnCinematicPalette ( name );
+}
+
+/*
+===============
+=
+= ParseEvent
+=
+===============
+*/
+void ParseEvent ( int time )
+{
+ eventtype * event;
+
+ event = CreateEvent ( time, GetEventType() );
+
+ switch (event->effecttype)
+ {
+ case background_noscrolling:
+ case background_scrolling:
+ case background_multi:
+ case backdrop_scrolling:
+ case backdrop_noscrolling:
+ ParseBack(event);
+ break;
+ case sprite_background:
+ case sprite_foreground:
+ ParseSprite(event);
+ break;
+ case palette:
+ ParsePalette(event);
+ break;
+ case flic:
+ ParseFlic(event);
+ break;
+ case fadeout:
+ case blankscreen:
+ case clearbuffer:
+ case cinematicend:
+ break;
+ }
+}
+
+/*
+===============
+=
+= UpdateCinematicEvents
+=
+===============
+*/
+void UpdateCinematicEvents ( int time )
+{
+ eventtype * event;
+
+ for (event=firstevent; event != NULL;)
+ {
+ if (event->time==time)
+ {
+ eventtype * nextevent;
+
+ nextevent=event->next;
+ SpawnCinematicActor ( event->effecttype, event->effect );
+ DeleteEvent(event);
+ event=nextevent;
+ }
+ else if (event->time>time)
+ break;
+ else
+ event=event->next;
+ }
+}
+
+/*
+===============
+=
+= PrecacheCinematic
+=
+===============
+*/
+void PrecacheCinematic ( void )
+{
+ eventtype * event;
+
+ for (event=firstevent; event != NULL;)
+ {
+ PrecacheCinematicEffect ( event->effecttype, event->effect );
+ event=event->next;
+ }
+}
+
--- /dev/null
+++ b/rott/cin_evnt.h
@@ -1,0 +1,41 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _cin_evnt_public
+#define _cin_evnt_public
+
+#include "cin_glob.h"
+#include "cin_def.h"
+
+extern eventtype * firstevent;
+extern eventtype * lastevent;
+
+void AddEvent (eventtype * event);
+void DeleteEvent(eventtype * event);
+
+eventtype * GetNewEvent ( void );
+void StartupEvents ( void );
+void ShutdownEvents ( void );
+eventtype * CreateEvent ( int time, int type );
+void ParseEvent ( int time );
+void UpdateCinematicEvents ( int time );
+void PrecacheCinematic ( void );
+
+#endif
+
--- /dev/null
+++ b/rott/cin_glob.c
@@ -1,0 +1,45 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "cin_glob.h"
+#include "rt_in.h"
+#include "rt_draw.h"
+//MED
+#include "memcheck.h"
+
+void CinematicDelay ( void )
+{
+ CalcTics();
+}
+
+int GetCinematicTime ( void )
+{
+ return GetTicCount ();
+}
+
+boolean CinematicAbort( void )
+{
+ return (IN_CheckAck ());
+}
+
+void ClearCinematicAbort( void )
+{
+ IN_StartAck ();
+}
+
--- /dev/null
+++ b/rott/cin_glob.h
@@ -1,0 +1,37 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "rt_def.h"
+#include "rt_util.h"
+#include "isr.h"
+#include <time.h>
+
+#ifndef CIN_GLOB_H
+#define CIN_GLOB_H
+
+#define DUMP 0
+
+#define CLOCKSPEED (VBLCOUNTER)
+
+void CinematicDelay( void );
+int GetCinematicTime( void );
+boolean CinematicAbort( void );
+void ClearCinematicAbort( void );
+
+#endif
--- /dev/null
+++ b/rott/cin_main.c
@@ -1,0 +1,286 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#ifdef DOS
+#include <malloc.h>
+#include <dos.h>
+#include <io.h>
+#include <conio.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include "cin_glob.h"
+#include "scriplib.h"
+#include "watcom.h"
+#include "z_zone.h"
+#include "w_wad.h"
+#include "cin_main.h"
+#include "modexlib.h"
+#include "lumpy.h"
+
+#include "cin_actr.h"
+#include "cin_evnt.h"
+#include "cin_efct.h"
+//MED
+#include "memcheck.h"
+
+boolean cinematicdone;
+static int cinematictime;
+static int cinematictics;
+static int cinematictictime;
+static int profiletics=-1;
+
+/*
+================
+=
+= ProfileMachine
+=
+================
+*/
+void ProfileMachine ( void )
+{
+ int i;
+ int time;
+ int endtime;
+
+ if (profiletics>0)
+ return;
+ time=GetCinematicTime();
+ for (i=0; i<4; i++)
+ {
+ ProfileDisplay();
+ }
+ endtime=GetCinematicTime();
+
+ profiletics = (endtime-time)>>2;
+ if (profiletics<1)
+ profiletics=1;
+}
+
+/*
+================
+=
+= StartupCinematic
+=
+================
+*/
+void StartupCinematic ( void )
+{
+ StartupEvents ();
+ StartupCinematicActors ();
+ cinematicdone=false;
+ cinematictime=0;
+ GetCinematicTics ();
+ ClearCinematicAbort();
+ ProfileMachine();
+}
+
+
+/*
+================
+=
+= ShutdownCinematic
+=
+================
+*/
+void ShutdownCinematic ( void )
+{
+ ShutdownEvents ();
+ ShutdownCinematicActors ();
+}
+
+
+/*
+================
+=
+= ParseCinematicScript
+=
+================
+*/
+
+void ParseCinematicScript (void)
+{
+ int time;
+
+ time=0;
+ do
+ {
+ //
+ // get next command time
+ //
+ GetToken (true);
+ if (endofscript)
+ break;
+ time+=ParseNum(token);
+ ParseEvent ( time );
+ }
+ while (script_p < scriptend_p);
+}
+
+
+/*
+==============
+=
+= CacheScriptFile
+=
+==============
+*/
+
+void CacheScriptFile (char *filename)
+{
+ long size;
+ int lump;
+
+ lump=W_GetNumForName(filename);
+
+ scriptbuffer=W_CacheLumpNum(lump,PU_CACHE, CvtNull, 1);
+ size = W_LumpLength(lump);
+
+ script_p = scriptbuffer;
+ scriptend_p = script_p + size;
+ scriptline = 1;
+ endofscript = false;
+ tokenready = false;
+}
+
+
+/*
+=================
+=
+= GrabCinematicScript
+=
+=================
+*/
+
+void GrabCinematicScript (char const *basename, boolean uselumpy)
+{
+ char script[256];
+
+//
+// read in the script file
+//
+ strcpy (script, basename);
+ strcat (script,".ms");
+ if (uselumpy==false)
+ LoadScriptFile (script);
+ else
+ CacheScriptFile ((char *)basename);
+
+ ParseCinematicScript ();
+}
+
+/*
+==============
+=
+= GetCinematicTics
+=
+==============
+*/
+
+void GetCinematicTics ( void )
+{
+ int time;
+
+ time=GetCinematicTime();
+ while (time==cinematictictime)
+ {
+ time=GetCinematicTime();
+ }
+ cinematictics=(time-cinematictictime);
+ cinematictictime=time;
+ cinematictics=profiletics;
+}
+
+
+void PlayMovie ( char * name, boolean uselumpy )
+{
+ int i;
+
+ StartupCinematic ( );
+ GrabCinematicScript (name, uselumpy);
+
+ PrecacheCinematic ( );
+ GetCinematicTics();
+ while (cinematicdone==false)
+ {
+ cinematicdone=CinematicAbort();
+#if DUMP
+ printf("time=%ld\n",cinematictime);
+#endif
+ for (i=0; i<cinematictics; i++)
+ {
+ UpdateCinematicEvents ( cinematictime );
+ UpdateCinematicActors ( );
+ cinematictime++;
+ }
+ DrawCinematicActors ();
+ GetCinematicTics();
+ }
+
+ ShutdownCinematic ();
+}
+
+#ifndef DOS
+int cin_iscale;
+byte *cin_source;
+int cin_texturemid;
+int cin_ycenter;
+int cin_yh;
+int cin_yl;
+
+/* f_scale.asm */
+
+void R_DrawFilmColumn (byte * buf)
+{
+ // This is *NOT* 100% correct - DDOI
+ int count;
+ int frac, fracstep;
+ byte *dest;
+
+ count = cin_yh - cin_yl;
+ if (count < 0) return;
+
+ dest = buf + ylookup[cin_yl];
+
+ fracstep = cin_iscale;
+ frac = cin_texturemid + (cin_yl-cin_ycenter)*fracstep;
+
+ while (count--) {
+ *dest = cin_source[(frac>>SFRACBITS)];
+ dest += iGLOBAL_SCREENWIDTH;
+ frac += fracstep;
+ }
+}
+
+void DrawFilmPost (byte * buf, byte * src, int height)
+{
+ while (height--) {
+ *buf = *src;
+
+ src++;
+
+ buf += linewidth;
+ }
+}
+#endif
+
--- /dev/null
+++ b/rott/cin_main.h
@@ -1,0 +1,36 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _cin_main_public
+#define _cin_main_public
+
+//***************************************************************************
+//
+// CIN_MAIN.H
+//
+//***************************************************************************
+#include "cin_glob.h"
+
+void GrabMovieScript (char const *basename, boolean uselumpy);
+void PlayMovie (char * name, boolean uselumpy);
+void GetCinematicTics ( void );
+
+extern boolean cinematicdone;
+
+#endif
--- /dev/null
+++ b/rott/cin_util.c
@@ -1,0 +1,72 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "cin_glob.h"
+#include "modexlib.h"
+
+#ifdef DOS
+#include <conio.h>
+#endif
+
+//MED
+#include "memcheck.h"
+
+/*
+==============
+=
+= CinematicGetPalette
+=
+= Return an 8 bit / color palette
+=
+==============
+*/
+
+void CinematicGetPalette (byte *pal)
+{
+#ifdef DOS
+ int i;
+
+ outp (PEL_READ_ADR,0);
+ for (i=0 ; i<768 ; i++)
+ pal[i] = ((inp (PEL_DATA))<<2);
+#else
+#endif
+}
+
+/*
+==============
+=
+= CinematicSetPalette
+=
+= Sets an 8 bit / color palette
+=
+==============
+*/
+
+void CinematicSetPalette (byte *pal)
+{
+#ifdef DOS
+ int i;
+
+ outp (PEL_WRITE_ADR,0);
+ for (i=0 ; i<768 ; i++)
+ outp (PEL_DATA, pal[i]>>2);
+#else
+#endif
+}
--- /dev/null
+++ b/rott/cin_util.h
@@ -1,0 +1,28 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _cin_util_public
+#define _cin_util_public
+
+
+void CinematicGetPalette (byte *pal);
+void CinematicSetPalette (byte *pal);
+
+#endif
+
--- /dev/null
+++ b/rott/develop.h
@@ -1,0 +1,82 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _develop_public
+#define _develop_public
+
+#define NOMEMCHECK
+#define DEBUG 0
+#define DEVELOPMENT 0
+#define BETA 0
+#define SOUNDTEST 0
+#define PRECACHETEST 0
+#define ELEVATORTEST 0
+#define TEAMTEST 0
+#define LOADSAVETEST 0
+#define WEAPONCHEAT 1
+#define MEMORYCORRUPTIONTEST 0
+#define SYNCCHECK 1
+#define DATACORRUPTIONTEST 0
+#define BATTLECHECK 0 // This should be turned off for release, on for beta
+#define BATTLEINFO 0 // This should be turned off for release
+
+#define DELUXE 0
+#define LOWCOST 0
+
+#define BNACRASHPREVENT 1 //bna added
+// Flavor selection (shareware, registered, cd version, site license) has moved to the Makefile
+#ifndef SHAREWARE
+#define SHAREWARE 0
+#endif
+
+// cute little dopefish thing, only works with special patch?
+#define DOPEFISH 0
+
+// okay?
+
+#define TEDLAUNCH 0
+#define SOFTERROR 0
+#define RANDOMTEST 0
+#define WHEREAMI 0
+
+
+
+
+#if (WHEREAMI==1)
+
+#define wami(val) \
+ { \
+ programlocation=val;\
+ }
+
+#define waminot()
+/*
+ { \
+ programlocation=-1;\
+ }
+*/
+
+#else
+
+#define wami(val)
+#define waminot()
+
+#endif
+
+#endif
--- /dev/null
+++ b/rott/dosutil.c
@@ -1,0 +1,394 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <sys/stat.h>
+#if PLATFORM_UNIX
+#include <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+#endif
+
+#include <fcntl.h>
+
+#include "rt_def.h"
+
+#if defined(USE_SDL)
+#include "SDL.h"
+#endif
+
+/*
+ Copied over from Wolf3D Linux: http://www.icculus.org/wolf3d/
+ Modified for ROTT.
+ */
+
+int _argc;
+char **_argv;
+
+#if PLATFORM_UNIX
+long filelength(int handle)
+{
+ struct stat buf;
+
+ if (fstat(handle, &buf) == -1) {
+ perror("filelength");
+ exit(EXIT_FAILURE);
+ }
+
+ return buf.st_size;
+}
+
+char *strlwr(char *s)
+{
+ char *p = s;
+
+ while (*p) {
+ *p = tolower(*p);
+ p++;
+ }
+
+ return s;
+}
+
+char *strupr(char *s)
+{
+ char *p = s;
+
+ while (*p) {
+ *p = toupper(*p);
+ p++;
+ }
+
+ return s;
+}
+
+char *itoa(int value, char *string, int radix)
+{
+ switch (radix) {
+ case 10:
+ sprintf(string, "%d", value);
+ break;
+ case 16:
+ sprintf(string, "%x", value);
+ break;
+ default:
+ STUB_FUNCTION;
+ break;
+ }
+
+ return string;
+}
+
+char *ltoa(long value, char *string, int radix)
+{
+ switch (radix) {
+ case 10:
+ sprintf(string, "%ld", value);
+ break;
+ case 16:
+ sprintf(string, "%lx", value);
+ break;
+ default:
+ STUB_FUNCTION;
+ break;
+ }
+
+ return string;
+}
+
+char *ultoa(unsigned long value, char *string, int radix)
+{
+ switch (radix) {
+ case 10:
+ sprintf(string, "%lu", value);
+ break;
+ case 16:
+ sprintf(string, "%lux", value);
+ break;
+ default:
+ STUB_FUNCTION;
+ break;
+ }
+
+ return string;
+}
+#endif
+
+char getch(void)
+{
+ getchar();
+ return 0;
+}
+
+extern char ApogeePath[256];
+
+int setup_homedir (void)
+{
+#if PLATFORM_UNIX && !defined(__MINGW32__)
+ int err;
+
+ /* try to create the root directory */
+ snprintf (ApogeePath, sizeof (ApogeePath), "%s/.rott/", getenv ("HOME"));
+ err = mkdir (ApogeePath, S_IRWXU);
+
+ /* keep the shareware and registered game data separated */
+#if (SHAREWARE == 1)
+ snprintf (ApogeePath, sizeof (ApogeePath), "%s/.rott/", getenv ("HOME"));
+#else
+ snprintf (ApogeePath, sizeof (ApogeePath), "%s/.rott/darkwar/", getenv ("HOME"));
+#endif
+
+ err = mkdir (ApogeePath, S_IRWXU);
+ if (err == -1 && errno != EEXIST)
+ {
+ fprintf (stderr, "Couldn't create preferences directory: %s\n",
+ strerror (errno));
+ return -1;
+ }
+#else
+ sprintf(ApogeePath, ".%s", PATH_SEP_STR);
+#endif
+
+ return 0;
+}
+
+/* from Dan Olson */
+void put_dos2ansi(byte attrib)
+{
+ int lookup[] = {30,34,32,36,31,35,33,37};
+ byte fore,back,blink=0,intens=0;
+
+ fore = attrib&15; /* bits 0-3 */
+ back = attrib&112; /* bits 4-6 */
+ blink = attrib&128; /* bit 7 */
+
+ /* Fix background, blink is either on or off. */
+ back = back>>4;
+
+ /* Fix foreground */
+ if (fore > 7) {
+ intens = 1;
+ fore-=8;
+ }
+
+ /* Convert fore/back */
+ fore = lookup[fore];
+ back = lookup[back]+10;
+
+ // 'Render"
+ if (blink)
+ printf ("\033[%d;5;%dm\033[%dm", intens, fore, back);
+ else
+ printf ("\033[%d;25;%dm\033[%dm", intens, fore, back);
+}
+
+void DisplayTextSplash(byte *text, int l)
+{
+ int i;
+ int bound = 80*l*2;
+
+ for (i=0; i<bound; i+=2)
+ {
+ put_dos2ansi(text[i+1]);
+ putchar (text[i]);
+ }
+
+ printf ("\033[m");
+}
+
+#if !defined(__CYGWIN__) && !defined(__MINGW32__)
+#include <execinfo.h>
+
+void print_stack (int level)
+{
+ void *array[64];
+ char **syms;
+ int size, i;
+
+ printf ("Stack dump:\n");
+ printf ("{\n");
+ size = backtrace (array, (sizeof (array))/(sizeof (array[0])));
+ syms = backtrace_symbols (array, size);
+ for (i=level+1; i<size; ++i) {
+ printf ("\t%s\n",syms[i]);
+ }
+ free (syms);
+ /*
+ for (i = 2; i <size; ++i) {
+ printf ("\t%p\n", array[i]);
+ }
+ */
+ printf ("}\n");
+}
+#else
+
+void print_stack (int level)
+{
+ printf("Stack dump not implemented.\n");
+}
+
+#endif
+
+void crash_print (int sig)
+{
+ printf ("OH NO OH NO ROTT CRASHED!\n");
+ printf ("Here is where:\n");
+ print_stack (1);
+#if defined(USE_SDL)
+ SDL_Quit ();
+#endif
+ exit (1);
+}
+
+#if 0
+/* ** */
+
+uint16_t SwapInt16L(uint16_t i)
+{
+#if BYTE_ORDER == BIG_ENDIAN
+ return ((uint16_t)i >> 8) | ((uint16_t)i << 8);
+#else
+ return i;
+#endif
+}
+
+uint32_t SwapInt32L(uint32_t i)
+{
+#if BYTE_ORDER == BIG_ENDIAN
+ return ((uint32_t)(i & 0xFF000000) >> 24) |
+ ((uint32_t)(i & 0x00FF0000) >> 8) |
+ ((uint32_t)(i & 0x0000FF00) << 8) |
+ ((uint32_t)(i & 0x000000FF) << 24);
+#else
+ return i;
+#endif
+}
+
+/* ** */
+
+int OpenWrite(char *_fn)
+{
+ int fp;
+ char fn[MAX_PATH];
+ strncpy(fn, _fn, sizeof (fn));
+ fn[sizeof (fn) - 1] = '\0';
+ FixFilePath(fn);
+
+ fp = open(fn, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+ return fp;
+}
+
+int OpenWriteAppend(char *_fn)
+{
+ int fp;
+ char fn[MAX_PATH];
+ strncpy(fn, _fn, sizeof (fn));
+ fn[sizeof (fn) - 1] = '\0';
+ FixFilePath(fn);
+
+ fp = open(fn, O_CREAT|O_WRONLY|O_BINARY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+ return fp;
+}
+
+void CloseWrite(int fp)
+{
+ close(fp);
+}
+
+int WriteSeek(int fp, int offset, int whence)
+{
+ return lseek(fp, offset, whence);
+}
+
+int WritePos(int fp)
+{
+ return lseek(fp, 0, SEEK_CUR);
+}
+
+int WriteInt8(int fp, int8_t d)
+{
+ return write(fp, &d, 1);
+}
+
+int WriteInt16(int fp, int16_t d)
+{
+ int16_t b = SwapInt16L(d);
+
+ return write(fp, &b, 2) / 2;
+}
+
+int WriteInt32(int fp, int32_t d)
+{
+ int32_t b = SwapInt32L(d);
+
+ return write(fp, &b, 4) / 4;
+}
+
+int WriteBytes(int fp, byte *d, int len)
+{
+ return write(fp, d, len);
+}
+
+
+int OpenRead(char *_fn)
+{
+ int fp;
+ char fn[MAX_PATH];
+ strncpy(fn, _fn, sizeof (fn));
+ fn[sizeof (fn) - 1] = '\0';
+ FixFilePath(fn);
+
+ fp = open(fn, O_RDONLY | O_BINARY);
+
+ return fp;
+}
+
+void CloseRead(int fp)
+{
+ close(fp);
+}
+
+int ReadSeek(int fp, int offset, int whence)
+{
+ return lseek(fp, offset, whence);
+}
+
+int ReadLength(int fp)
+{
+ return filelength(fp);
+}
+
+int8_t ReadInt8(int fp)
+{
+ byte d[1];
+
+ read(fp, d, 1);
+
+ return d[0];
+}
+
+int16_t ReadInt16(int fp)
+{
+ byte d[2];
+
+ read(fp, d, 2);
+
+ return (d[0]) | (d[1] << 8);
+}
+
+int32_t ReadInt32(int fp)
+{
+ byte d[4];
+
+ read(fp, d, 4);
+
+ return (d[0]) | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
+}
+
+int ReadBytes(int fp, byte *d, int len)
+{
+ return read(fp, d, len);
+}
+
+#endif
--- /dev/null
+++ b/rott/dukemusc.c
@@ -1,0 +1,507 @@
+/*
+ * A reimplementation of Jim Dose's FX_MAN routines, using SDL_mixer 1.2.
+ * Whee. FX_MAN is also known as the "Apogee Sound System", or "ASS" for
+ * short. How strangely appropriate that seems.
+ *
+ * Written by Ryan C. Gordon. (icculus@clutteredmind.org)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <assert.h>
+
+#define ROTT
+
+#ifdef DUKE3D
+#include "duke3d.h"
+#include "buildengine/cache1d.h"
+#endif
+
+#if PLATFORM_DOS
+// Use the original Apogee Sound System libs instead. --ryan.
+#error you probably should not compile this.
+#endif
+
+#if (defined __WATCOMC__)
+// This is probably out of date. --ryan.
+#include "dukesnd_watcom.h"
+#endif
+
+#if (!defined __WATCOMC__)
+#define cdecl
+#endif
+
+#include "SDL.h"
+#include "SDL_mixer.h"
+#ifdef ROTT
+#include "rt_def.h" // ROTT music hack
+#include "rt_cfg.h" // ROTT music hack
+#include "rt_util.h" // ROTT music hack
+#endif
+#include "music.h"
+
+#define __FX_TRUE (1 == 1)
+#define __FX_FALSE (!__FX_TRUE)
+
+#define DUKESND_DEBUG "DUKESND_DEBUG"
+
+#ifndef min
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef max
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+int MUSIC_ErrorCode = MUSIC_Ok;
+
+static char warningMessage[80];
+static char errorMessage[80];
+static int fx_initialized = 0;
+static int numChannels = MIX_CHANNELS;
+static void (*callback)(unsigned long);
+static int reverseStereo = 0;
+static int reverbDelay = 256;
+static int reverbLevel = 0;
+static int fastReverb = 0;
+static FILE *debug_file = NULL;
+static int initialized_debugging = 0;
+static int mixerIsStereo = 1;
+
+// This gets called all over the place for information and debugging messages.
+// If the user set the DUKESND_DEBUG environment variable, the messages
+// go to the file that is specified in that variable. Otherwise, they
+// are ignored for the expense of the function call. If DUKESND_DEBUG is
+// set to "-" (without the quotes), then the output goes to stdout.
+static void musdebug(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (debug_file)
+ {
+ fprintf(debug_file, "DUKEMUS: ");
+ va_start(ap, fmt);
+ vfprintf(debug_file, fmt, ap);
+ va_end(ap);
+ fprintf(debug_file, "\n");
+ fflush(debug_file);
+ } // if
+} // musdebug
+
+static void init_debugging(void)
+{
+ const char *envr;
+
+ if (initialized_debugging)
+ return;
+
+ envr = getenv(DUKESND_DEBUG);
+ if (envr != NULL)
+ {
+ if (strcmp(envr, "-") == 0)
+ debug_file = stdout;
+ else
+ debug_file = fopen(envr, "w");
+
+ if (debug_file == NULL)
+ fprintf(stderr, "DUKESND: -WARNING- Could not open debug file!\n");
+ else
+ setbuf(debug_file, NULL);
+ } // if
+
+ initialized_debugging = 1;
+} // init_debugging
+
+static void setWarningMessage(const char *msg)
+{
+ strncpy(warningMessage, msg, sizeof (warningMessage));
+ // strncpy() doesn't add the null char if there isn't room...
+ warningMessage[sizeof (warningMessage) - 1] = '\0';
+ musdebug("Warning message set to [%s].", warningMessage);
+} // setErrorMessage
+
+
+static void setErrorMessage(const char *msg)
+{
+ strncpy(errorMessage, msg, sizeof (errorMessage));
+ // strncpy() doesn't add the null char if there isn't room...
+ errorMessage[sizeof (errorMessage) - 1] = '\0';
+ musdebug("Error message set to [%s].", errorMessage);
+} // setErrorMessage
+
+// The music functions...
+
+char *MUSIC_ErrorString(int ErrorNumber)
+{
+ switch (ErrorNumber)
+ {
+ case MUSIC_Warning:
+ return(warningMessage);
+
+ case MUSIC_Error:
+ return(errorMessage);
+
+ case MUSIC_Ok:
+ return("OK; no error.");
+
+ case MUSIC_ASSVersion:
+ return("Incorrect sound library version.");
+
+ case MUSIC_SoundCardError:
+ return("General sound card error.");
+
+ case MUSIC_InvalidCard:
+ return("Invalid sound card.");
+
+ case MUSIC_MidiError:
+ return("MIDI error.");
+
+ case MUSIC_MPU401Error:
+ return("MPU401 error.");
+
+ case MUSIC_TaskManError:
+ return("Task Manager error.");
+
+ case MUSIC_FMNotDetected:
+ return("FM not detected error.");
+
+ case MUSIC_DPMI_Error:
+ return("DPMI error.");
+
+ default:
+ return("Unknown error.");
+ } // switch
+
+ assert(0); // shouldn't hit this point.
+ return(NULL);
+} // MUSIC_ErrorString
+
+
+static int music_initialized = 0;
+static int music_context = 0;
+static int music_loopflag = MUSIC_PlayOnce;
+static char *music_songdata = NULL;
+static Mix_Music *music_musicchunk = NULL;
+
+int MUSIC_Init(int SoundCard, int Address)
+{
+ init_debugging();
+
+ musdebug("INIT! card=>%d, address=>%d...", SoundCard, Address);
+
+ if (music_initialized)
+ {
+ setErrorMessage("Music system is already initialized.");
+ return(MUSIC_Error);
+ } // if
+
+ if (SoundCard != SoundScape) // We pretend there's a SoundScape installed.
+ {
+ setErrorMessage("Card not found.");
+ musdebug("We pretend to be an Ensoniq SoundScape only.");
+ return(MUSIC_Error);
+ } // if
+
+ music_initialized = 1;
+ return(MUSIC_Ok);
+} // MUSIC_Init
+
+
+int MUSIC_Shutdown(void)
+{
+ musdebug("shutting down sound subsystem.");
+
+ if (!music_initialized)
+ {
+ setErrorMessage("Music system is not currently initialized.");
+ return(MUSIC_Error);
+ } // if
+
+ MUSIC_StopSong();
+ music_context = 0;
+ music_initialized = 0;
+ music_loopflag = MUSIC_PlayOnce;
+
+ return(MUSIC_Ok);
+} // MUSIC_Shutdown
+
+
+void MUSIC_SetMaxFMMidiChannel(int channel)
+{
+ musdebug("STUB ... MUSIC_SetMaxFMMidiChannel(%d).\n", channel);
+} // MUSIC_SetMaxFMMidiChannel
+
+
+void MUSIC_SetVolume(int volume)
+{
+ Mix_VolumeMusic(volume >> 1); // convert 0-255 to 0-128.
+} // MUSIC_SetVolume
+
+
+void MUSIC_SetMidiChannelVolume(int channel, int volume)
+{
+ musdebug("STUB ... MUSIC_SetMidiChannelVolume(%d, %d).\n", channel, volume);
+} // MUSIC_SetMidiChannelVolume
+
+
+void MUSIC_ResetMidiChannelVolumes(void)
+{
+ musdebug("STUB ... MUSIC_ResetMidiChannelVolumes().\n");
+} // MUSIC_ResetMidiChannelVolumes
+
+
+int MUSIC_GetVolume(void)
+{
+ return(Mix_VolumeMusic(-1) << 1); // convert 0-128 to 0-255.
+} // MUSIC_GetVolume
+
+
+void MUSIC_SetLoopFlag(int loopflag)
+{
+ music_loopflag = loopflag;
+} // MUSIC_SetLoopFlag
+
+
+int MUSIC_SongPlaying(void)
+{
+ return((Mix_PlayingMusic()) ? __FX_TRUE : __FX_FALSE);
+} // MUSIC_SongPlaying
+
+
+void MUSIC_Continue(void)
+{
+ if (Mix_PausedMusic())
+ Mix_ResumeMusic();
+ else if (music_songdata)
+ MUSIC_PlaySong(music_songdata, MUSIC_PlayOnce);
+} // MUSIC_Continue
+
+
+void MUSIC_Pause(void)
+{
+ Mix_PauseMusic();
+} // MUSIC_Pause
+
+
+int MUSIC_StopSong(void)
+{
+ //if (!fx_initialized)
+ if (!Mix_QuerySpec(NULL, NULL, NULL))
+ {
+ setErrorMessage("Need FX system initialized, too. Sorry.");
+ return(MUSIC_Error);
+ } // if
+
+ if ( (Mix_PlayingMusic()) || (Mix_PausedMusic()) )
+ Mix_HaltMusic();
+
+ if (music_musicchunk)
+ Mix_FreeMusic(music_musicchunk);
+
+ music_songdata = NULL;
+ music_musicchunk = NULL;
+ return(MUSIC_Ok);
+} // MUSIC_StopSong
+
+
+int MUSIC_PlaySong(unsigned char *song, int loopflag)
+{
+ //SDL_RWops *rw;
+
+ MUSIC_StopSong();
+
+ music_songdata = song;
+
+ // !!! FIXME: This could be a problem...SDL/SDL_mixer wants a RWops, which
+ // !!! FIXME: is an i/o abstraction. Since we already have the MIDI data
+ // !!! FIXME: in memory, we fake it with a memory-based RWops. None of
+ // !!! FIXME: this is a problem, except the RWops wants to know how big
+ // !!! FIXME: its memory block is (so it can do things like seek on an
+ // !!! FIXME: offset from the end of the block), and since we don't have
+ // !!! FIXME: this information, we have to give it SOMETHING.
+
+ /* !!! ARGH! There's no LoadMUS_RW ?!
+ rw = SDL_RWFromMem((void *) song, (10 * 1024) * 1024); // yikes.
+ music_musicchunk = Mix_LoadMUS_RW(rw);
+ Mix_PlayMusic(music_musicchunk, (loopflag == MUSIC_PlayOnce) ? 0 : -1);
+ */
+
+ musdebug("Need to use PlaySongROTT. :(");
+
+ return(MUSIC_Ok);
+} // MUSIC_PlaySong
+
+
+extern char ApogeePath[256];
+
+#ifdef DUKE3D
+// Duke3D-specific. --ryan.
+void PlayMusic(char *_filename)
+{
+ //char filename[MAX_PATH];
+ //strcpy(filename, _filename);
+ //FixFilePath(filename);
+
+ char filename[MAX_PATH];
+ long handle;
+ long size;
+ void *song;
+ long rc;
+
+ MUSIC_StopSong();
+
+ // Read from a groupfile, write it to disk so SDL_mixer can read it.
+ // Lame. --ryan.
+ handle = kopen4load(_filename, 0);
+ if (handle == -1)
+ return;
+
+ size = kfilelength(handle);
+ if (size == -1)
+ {
+ kclose(handle);
+ return;
+ } // if
+
+ song = malloc(size);
+ if (song == NULL)
+ {
+ kclose(handle);
+ return;
+ } // if
+
+ rc = kread(handle, song, size);
+ kclose(handle);
+ if (rc != size)
+ {
+ free(song);
+ return;
+ } // if
+
+ // save the file somewhere, so SDL_mixer can load it
+ GetPathFromEnvironment(filename, MAX_PATH, "tmpsong.mid");
+ handle = SafeOpenWrite(filename, filetype_binary);
+
+ SafeWrite(handle, song, size);
+ close(handle);
+ free(song);
+
+ //music_songdata = song;
+
+ music_musicchunk = Mix_LoadMUS(filename);
+ if (music_musicchunk != NULL)
+ {
+ // !!! FIXME: I set the music to loop. Hope that's okay. --ryan.
+ Mix_PlayMusic(music_musicchunk, -1);
+ } // if
+}
+#endif
+
+#ifdef ROTT
+// ROTT Special - SBF
+int MUSIC_PlaySongROTT(unsigned char *song, int size, int loopflag)
+{
+ char filename[MAX_PATH];
+ int handle;
+
+ MUSIC_StopSong();
+
+ // save the file somewhere, so SDL_mixer can load it
+ GetPathFromEnvironment(filename, ApogeePath, "tmpsong.mid");
+ handle = SafeOpenWrite(filename);
+
+ SafeWrite(handle, song, size);
+ close(handle);
+
+ music_songdata = song;
+
+ // finally, we can load it with SDL_mixer
+ music_musicchunk = Mix_LoadMUS(filename);
+ if (music_musicchunk == NULL) {
+ return MUSIC_Error;
+ }
+
+ Mix_PlayMusic(music_musicchunk, (loopflag == MUSIC_PlayOnce) ? 0 : -1);
+
+ return(MUSIC_Ok);
+} // MUSIC_PlaySongROTT
+#endif
+
+
+void MUSIC_SetContext(int context)
+{
+ musdebug("STUB ... MUSIC_SetContext().\n");
+ music_context = context;
+} // MUSIC_SetContext
+
+
+int MUSIC_GetContext(void)
+{
+ return(music_context);
+} // MUSIC_GetContext
+
+
+void MUSIC_SetSongTick(unsigned long PositionInTicks)
+{
+ musdebug("STUB ... MUSIC_SetSongTick().\n");
+} // MUSIC_SetSongTick
+
+
+void MUSIC_SetSongTime(unsigned long milliseconds)
+{
+ musdebug("STUB ... MUSIC_SetSongTime().\n");
+}// MUSIC_SetSongTime
+
+
+void MUSIC_SetSongPosition(int measure, int beat, int tick)
+{
+ musdebug("STUB ... MUSIC_SetSongPosition().\n");
+} // MUSIC_SetSongPosition
+
+
+void MUSIC_GetSongPosition(songposition *pos)
+{
+ musdebug("STUB ... MUSIC_GetSongPosition().\n");
+} // MUSIC_GetSongPosition
+
+
+void MUSIC_GetSongLength(songposition *pos)
+{
+ musdebug("STUB ... MUSIC_GetSongLength().\n");
+} // MUSIC_GetSongLength
+
+
+int MUSIC_FadeVolume(int tovolume, int milliseconds)
+{
+ Mix_FadeOutMusic(milliseconds);
+ return(MUSIC_Ok);
+} // MUSIC_FadeVolume
+
+
+int MUSIC_FadeActive(void)
+{
+ return((Mix_FadingMusic() == MIX_FADING_OUT) ? __FX_TRUE : __FX_FALSE);
+} // MUSIC_FadeActive
+
+
+void MUSIC_StopFade(void)
+{
+ musdebug("STUB ... MUSIC_StopFade().\n");
+} // MUSIC_StopFade
+
+
+void MUSIC_RerouteMidiChannel(int channel, int cdecl (*function)( int event, int c1, int c2 ))
+{
+ musdebug("STUB ... MUSIC_RerouteMidiChannel().\n");
+} // MUSIC_RerouteMidiChannel
+
+
+void MUSIC_RegisterTimbreBank(unsigned char *timbres)
+{
+ musdebug("STUB ... MUSIC_RegisterTimbreBank().\n");
+} // MUSIC_RegisterTimbreBank
+
+
+// end of fx_man.c ...
--- /dev/null
+++ b/rott/engine.c
@@ -1,0 +1,419 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "rt_def.h"
+#include "watcom.h"
+#include "engine.h"
+#include "_engine.h"
+#include "rt_draw.h"
+#include "rt_door.h"
+#include "rt_stat.h"
+#include "rt_ted.h"
+#include "rt_view.h"
+#include <stdlib.h>
+//MED
+#include "memcheck.h"
+
+
+/*
+=============================================================================
+
+Global Variables GLOBAL VARIABLES
+
+=============================================================================
+*/
+//wallcast_t posts[642];//bna++
+wallcast_t posts[800+2];//bna++
+//wallcast_t posts[321];
+int lasttilex;
+int lasttiley;
+/*
+=============================================================================
+
+Local Variables GLOBAL VARIABLES
+
+=============================================================================
+*/
+
+static int xtilestep,ytilestep;
+static int c_vx,c_vy;
+
+void InitialCast ( void );
+void Cast ( int curx );
+
+void Interpolate (int x1, int x2)
+{
+ int i;
+ int dtexture;
+ int frac;
+ int dheight;
+ int hfrac;
+ int dx;
+
+ dx=x2-x1;
+ dtexture=(((posts[x2].texture-posts[x1].texture)<<12)+0x800)/dx;
+ dheight=(((posts[x2].wallheight-posts[x1].wallheight)<<8)+0x80)/dx;
+ frac=dtexture+(posts[x1].texture<<12);
+ hfrac=dheight+(posts[x1].wallheight<<8);
+ for (i=x1+1; i<=x2-1; i++,frac+=dtexture,hfrac+=dheight)
+ {
+ posts[i].lump=posts[x1].lump;
+ posts[i].posttype=posts[x1].posttype;
+ posts[i].offset=posts[x1].offset;
+ posts[i].alttile=posts[x1].alttile;
+ posts[i].texture=(frac>>12);
+ posts[i].wallheight=hfrac>>8;
+ }
+}
+
+void Refresh ( void )
+{
+ int x;
+
+// Cast Initial comb filter
+
+ InitialCast();
+
+ for (x=0; x<=viewwidth-4; x+=4)
+ {
+ if NOTSAMETILE(x,x+4)
+ {
+ Cast(x+2);
+ if NOTSAMETILE(x,x+2)
+ {
+ Cast(x+1);
+ }
+ else
+ Interpolate (x,x+2);
+ if NOTSAMETILE(x+2,x+4)
+ {
+ Cast(x+3);
+ }
+ else
+ Interpolate (x+2,x+4);
+ }
+ else
+ Interpolate(x,x+4);
+ }
+}
+
+
+void HitWall(int curx, int vertical, int xtile, int ytile)
+{
+ int num;
+
+ posts[curx].offset=(xtile<<7)+ytile;
+ posts[curx].lump = tilemap[xtile][ytile];
+ posts[curx].alttile=0;
+ posts[curx].posttype=0;
+
+ if (vertical<0)
+ {
+ xintercept=xtile<<16;
+ if (xtilestep<0)
+ xintercept+=0xffff;
+ yintercept=FixedScale(xintercept-viewx,c_vy,c_vx)+viewy;
+ if (posts[curx].lump & 0x4000)
+ {
+ if (tilemap[xtile-(xtilestep>>7)][ytile]&0x8000)
+ {
+ num=tilemap[xtile-(xtilestep>>7)][ytile];
+ if (num&0x4000)
+ {
+ if (maskobjlist[num&0x3ff]->sidepic)
+ posts[curx].lump = maskobjlist[num&0x3ff]->sidepic;
+ else
+ posts[curx].lump &= 0x3ff;
+ }
+ else
+ posts[curx].lump = doorobjlist[num&0x3ff]->sidepic;
+ }
+ else
+ {
+ if (posts[curx].lump&0x1000)
+ posts[curx].lump=animwalls[posts[curx].lump&0x3ff].texture;
+ else
+ posts[curx].lump &= 0x3ff;
+ }
+ }
+ else if (posts[curx].lump & 0x2000)
+ {
+ if (IsWindow(xtile,ytile))
+ posts[curx].alttile=-1;
+ else
+ posts[curx].alttile=(MAPSPOT(xtile,ytile,2))+1;
+ posts[curx].lump &= 0x3ff;
+ }
+ else if (posts[curx].lump & 0x1000)
+ posts[curx].lump=animwalls[posts[curx].lump&0x3ff].texture;
+ else if (posts[curx].lump & 0x800)
+ {
+ posts[curx].lump &= 0x3ff;
+ posts[curx].posttype=2;
+ }
+ posts[curx].texture=yintercept-(ytile<<16);
+// posts[curx].texture&=0xffff;
+ if (posts[curx].texture<0)
+ posts[curx].texture=0;
+ if (posts[curx].texture>65535)
+ posts[curx].texture=65535;
+ if (xtilestep<0)
+ posts[curx].texture^=0xffff;
+ posts[curx].posttype+=1;
+// posts[curx].texture=(posts[curx].texture+firstcoloffset)&65535;
+ }
+ else
+ {
+ yintercept=ytile<<16;
+ if (ytilestep<0)
+ yintercept+=0xffff;
+ xintercept=FixedScale(yintercept-viewy,c_vx,c_vy)+viewx;
+ if (posts[curx].lump & 0x4000)
+ { // check for adjacent doors
+ if (tilemap[xtile][ytile-ytilestep]&0x8000)
+ {
+ num=tilemap[xtile][ytile-ytilestep];
+ if (num&0x4000)
+ {
+ if (maskobjlist[num&0x3ff]->sidepic)
+ posts[curx].lump = maskobjlist[num&0x3ff]->sidepic;
+ else
+ posts[curx].lump &= 0x3ff;
+ }
+ else
+ posts[curx].lump = doorobjlist[num&0x3ff]->sidepic;
+ }
+ else
+ {
+ if (posts[curx].lump&0x1000)
+ posts[curx].lump=animwalls[posts[curx].lump&0x3ff].texture;
+ else
+ posts[curx].lump &= 0x3ff;
+ }
+ }
+ else if (posts[curx].lump & 0x2000)
+ {
+ if (IsWindow(xtile,ytile))
+ posts[curx].alttile=-1;
+ else
+ posts[curx].alttile=(MAPSPOT(xtile,ytile,2))+1;
+ posts[curx].lump &= 0x3ff;
+ }
+ else if (posts[curx].lump & 0x1000)
+ posts[curx].lump=animwalls[posts[curx].lump&0x3ff].texture;
+ else if (posts[curx].lump & 0x800)
+ {
+ posts[curx].lump &= 0x3ff;
+ posts[curx].posttype=2;
+ }
+ posts[curx].texture=xintercept-(xtile<<16);
+// posts[curx].texture&=0xffff;
+ if (posts[curx].texture<0)
+ posts[curx].texture=0;
+ if (posts[curx].texture>65535)
+ posts[curx].texture=65535;
+ if (ytilestep>0)
+ posts[curx].texture^=0xffff;
+// posts[curx].posttype+=0;
+// posts[curx].texture=(posts[curx].texture+firstcoloffset)&65535;
+ }
+ posts[curx].wallheight=CalcHeight();
+}
+
+void InitialCast ( void )
+{
+ int snx,sny;
+ int incr[2];
+ int thedir[2];
+ int cnt;
+ int grid[2];
+ int index;
+ int curx;
+
+ c_vx=c_startx;
+ c_vy=c_starty;
+ for (curx=0; curx<=viewwidth; curx+=4)
+ {
+ snx=viewx&0xffff;
+ sny=viewy&0xffff;
+
+ if (c_vx>0)
+ {
+ thedir[0]=1;
+ xtilestep=0x80;
+ snx^=0xffff;
+ incr[1]=-c_vx;
+ }
+ else
+ {
+ thedir[0]=-1;
+ xtilestep=-0x80;
+ incr[1]=c_vx;
+ }
+ if (c_vy>0)
+ {
+ thedir[1]=1;
+ ytilestep=1;
+ sny^=0xffff;
+ incr[0]=c_vy;
+ }
+ else
+ {
+ thedir[1]=-1;
+ ytilestep=-1;
+ incr[0]=-c_vy;
+ }
+ cnt=FixedMul(snx,incr[0])+FixedMul(sny,incr[1]);
+ grid[0]=viewx>>16;
+ grid[1]=viewy>>16;
+ do
+ {
+ int tile;
+
+ index=(cnt>=0);
+ cnt+=incr[index];
+ spotvis[grid[0]][grid[1]]=1;
+ grid[index]+=thedir[index];
+
+ if ((tile=tilemap[grid[0]][grid[1]])!=0)
+ {
+ if (tile&0x8000)
+ {
+ if ( (!(tile&0x4000)) && (doorobjlist[tile&0x3ff]->action==dr_closed))
+ {
+ spotvis[grid[0]][grid[1]]=1;
+ if (doorobjlist[tile&0x3ff]->flags&DF_MULTI)
+ MakeWideDoorVisible(tile&0x3ff);
+ do
+ {
+ index=(cnt>=0);
+ cnt+=incr[index];
+ grid[index]+=thedir[index];
+ if ((tilemap[grid[0]][grid[1]]!=0) &&
+ (!(tilemap[grid[0]][grid[1]]&0x8000)) )
+ break;
+ }
+ while (1);
+ break;
+ }
+ else
+ continue;
+ }
+ else
+ {
+ mapseen[grid[0]][grid[1]]=1;
+ break;
+ }
+ }
+ }
+ while (1);
+ HitWall(curx, cnt-incr[index], grid[0], grid[1]);
+ c_vx+=viewsin<<2;
+ c_vy+=viewcos<<2;
+ }
+}
+
+
+void Cast ( int curx )
+{
+ int snx,sny;
+ int incr[2];
+ int thedir[2];
+ int cnt;
+ int grid[2];
+ int index;
+
+ c_vx=c_startx+(curx*viewsin);
+ c_vy=c_starty+(curx*viewcos);
+ snx=viewx&0xffff;
+ sny=viewy&0xffff;
+
+ if (c_vx>0)
+ {
+ thedir[0]=1;
+ xtilestep=0x80;
+ snx^=0xffff;
+ incr[1]=-c_vx;
+ }
+ else
+ {
+ thedir[0]=-1;
+ xtilestep=-0x80;
+ incr[1]=c_vx;
+ }
+ if (c_vy>0)
+ {
+ thedir[1]=1;
+ ytilestep=1;
+ sny^=0xffff;
+ incr[0]=c_vy;
+ }
+ else
+ {
+ thedir[1]=-1;
+ ytilestep=-1;
+ incr[0]=-c_vy;
+ }
+ cnt=FixedMul(snx,incr[0])+FixedMul(sny,incr[1]);
+ grid[0]=viewx>>16;
+ grid[1]=viewy>>16;
+ do
+ {
+ int tile;
+
+ index=(cnt>=0);
+ cnt+=incr[index];
+ spotvis[grid[0]][grid[1]]=1;
+ grid[index]+=thedir[index];
+
+ if ((tile=tilemap[grid[0]][grid[1]])!=0)
+ {
+ if (tile&0x8000)
+ {
+ if ( (!(tile&0x4000)) && (doorobjlist[tile&0x3ff]->action==dr_closed))
+ {
+ spotvis[grid[0]][grid[1]]=1;
+ if (doorobjlist[tile&0x3ff]->flags&DF_MULTI)
+ MakeWideDoorVisible(tile&0x3ff);
+ do
+ {
+ index=(cnt>=0);
+ cnt+=incr[index];
+ grid[index]+=thedir[index];
+ if ((tilemap[grid[0]][grid[1]]!=0) &&
+ (!(tilemap[grid[0]][grid[1]]&0x8000)) )
+ break;
+ }
+ while (1);
+ break;
+ }
+ else
+ continue;
+ }
+ else
+ {
+ mapseen[grid[0]][grid[1]]=1;
+ break;
+ }
+ }
+ }
+ while (1);
+ HitWall(curx, cnt-incr[index], grid[0], grid[1]);
+}
+
--- /dev/null
+++ b/rott/engine.h
@@ -1,0 +1,52 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _engine_public
+#define _engine_public
+
+#include "modexlib.h"
+//***************************************************************************
+//
+// ENGINE.C
+//
+//***************************************************************************
+
+typedef struct
+{
+ int offset;
+ int wallheight;
+ int ceilingclip;
+ int floorclip;
+ int texture;
+ int lump;
+ int posttype;
+ int alttile;
+} wallcast_t;
+extern wallcast_t posts[800+2];//bna++ JUST MAKE IT MAX RES
+//extern wallcast_t posts[642];//bna++
+//extern wallcast_t posts[321];
+
+extern int lasttilex;
+extern int lasttiley;
+
+void Refresh ( void );
+
+#define IsWindow(x,y) (MAPSPOT((x),(y),2)==13)
+
+#endif
--- /dev/null
+++ b/rott/f_scale.h
@@ -1,0 +1,38 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _f_scale_public
+#define _f_scale_public
+
+extern int cin_yl;
+extern int cin_yh;
+extern int cin_ycenter;
+extern int cin_iscale;
+extern int cin_texturemid;
+extern byte * cin_source;
+
+void R_DrawFilmColumn (byte * buf);
+void DrawFilmPost (byte * buf, byte * src, int height);
+
+#if (defined __WATCOMC__)
+#pragma aux R_DrawFilmColumn parm [EDI] modify exact [eax ebx ecx edx esi edi]
+#pragma aux DrawFilmPost parm [EDI] [ESI] [ECX] modify exact [eax ecx edx edi esi ebx]
+#endif
+
+#endif
--- /dev/null
+++ b/rott/fli_def.h
@@ -1,0 +1,104 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/* Flic.h - header file containing structure of a flic file.
+ *
+ * Copyright (c) 1992 Jim Kent. This file may be freely used, modified,
+ * copied and distributed. This file was first published as part of
+ * an article for Dr. Dobb's Journal March 1993 issue.
+ */
+
+#ifndef FLIC_H /* Keep this from being included twice */
+#define FLIC_H
+
+#pragma pack (1)
+/* Flic Header */
+
+#warning fli_def structures need to be packed
+
+typedef struct
+{
+ Long size; /* Size of flic including this header. */
+ Ushort type; /* Either FLI_TYPE or FLC_TYPE below. */
+ Ushort frames; /* Number of frames in flic. */
+ Ushort width; /* Flic width in pixels. */
+ Ushort height; /* Flic height in pixels. */
+ Ushort depth; /* Bits per pixel. (Always 8 now.) */
+ Ushort flags; /* FLI_FINISHED | FLI_LOOPED ideally. */
+ Long speed; /* Delay between frames. */
+ Short reserved1; /* Set to zero. */
+ Ulong created; /* Date of flic creation. (FLC only.) */
+ Ulong creator; /* Serial # of flic creator. (FLC only.) */
+ Ulong updated; /* Date of flic update. (FLC only.) */
+ Ulong updater; /* Serial # of flic updater. (FLC only.) */
+ Ushort aspect_dx; /* Width of square rectangle. (FLC only.) */
+ Ushort aspect_dy; /* Height of square rectangle. (FLC only.) */
+ Char reserved2[38];/* Set to zero. */
+ Long oframe1; /* Offset to frame 1. (FLC only.) */
+ Long oframe2; /* Offset to frame 2. (FLC only.) */
+ Char reserved3[40];/* Set to zero. */
+} FlicHead;
+/* Values for FlicHead.type */
+#define FLI_TYPE 0xAF11u /* 320x200 .FLI type ID */
+#define FLC_TYPE 0xAF12u /* Variable rez .FLC type ID */
+/* Values for FlicHead.flags */
+#define FLI_FINISHED 0x0001
+#define FLI_LOOPED 0x0002
+
+/* Optional Prefix Header */
+typedef struct
+{
+ Long size; /* Size of prefix including header. */
+ Ushort type; /* Always PREFIX_TYPE. */
+ Short chunks; /* Number of subchunks in prefix. */
+ Char reserved[8];/* Always 0. */
+} PrefixHead;
+/* Value for PrefixHead.type */
+#define PREFIX_TYPE 0xF100u
+
+/* Frame Header */
+typedef struct
+{
+ Long size; /* Size of frame including header. */
+ Ushort type; /* Always FRAME_TYPE */
+ Short chunks; /* Number of chunks in frame. */
+ Char reserved[8];/* Always 0. */
+} FrameHead;
+/* Value for FrameHead.type */
+#define FRAME_TYPE 0xF1FAu
+
+/* Chunk Header */
+typedef struct
+{
+ Long size; /* Size of chunk including header. */
+ Ushort type; /* Value from ChunkTypes below. */
+} ChunkHead;
+enum ChunkTypes
+{
+ COLOR_256 = 4, /* 256 level color pallette info. (FLC only.) */
+ DELTA_FLC = 7, /* Word-oriented delta compression. (FLC only.) */
+ COLOR_64 = 11, /* 64 level color pallette info. */
+ DELTA_FLI = 12, /* Byte-oriented delta compression. */
+ BLACK = 13, /* whole frame is color 0 */
+ BYTE_RUN = 15, /* Byte run-length compression. */
+ LITERAL = 16, /* Uncompressed pixels. */
+ PSTAMP = 18, /* "Postage stamp" chunk. (FLC only.) */
+};
+
+#endif /* FLIC_H */
--- /dev/null
+++ b/rott/fli_glob.h
@@ -1,0 +1,22 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+void PlayFlic ( char * name, unsigned char * buffer, int usefile, int loop);
+
+
--- /dev/null
+++ b/rott/fli_main.c
@@ -1,0 +1,603 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/* readflic.c - This module contains the routines to read and decompress
+ * a flic. They assume Intel byte ordering, but otherwise should be
+ * fairly portable. They call machine specific stuff in pcclone.c.
+ * This file starts with the low level decompression routines - first
+ * for colors and then for pixels. Then it goes to the higher level
+ * exported flic_xxxx routines as prototyped in readflic.h.
+ *
+ * Copyright (c) 1992 Jim Kent. This file may be freely used, modified,
+ * copied and distributed. This file was first published as part of
+ * an article for Dr. Dobb's Journal March 1993 issue.
+ */
+
+#include "cin_glob.h"
+#include <errno.h>
+#include <string.h>
+#include <io.h>
+#include "fli_type.h"
+#include "fli_util.h"
+#include "fli_def.h"
+#include "fli_main.h"
+//MED
+#include "memcheck.h"
+
+
+
+typedef void ColorOut(Screen *s, int start, Color *colors, int count);
+/* This is the type of output parameter to our decode_color below.
+ * Not coincedently screen_put_color is of this type. */
+
+static void decode_color(Uchar *data
+ , Flic *flic, Screen *s, ColorOut *output)
+/* Decode color map. Put results into output. The two color
+ * compressions are identical except for whether the RGB values
+ * are 0-63 or 0-255. Passing in an output that does the appropriate
+ * shifting on the way to the real pallete lets us use the same
+ * code for both COLOR_64 and COLOR_256 compression.
+ */
+{
+ int start = 0;
+ Uchar *cbuf = (Uchar *)data;
+ Short *wp = (Short *)cbuf;
+ Short ops;
+ int count;
+
+ ops = *wp;
+ cbuf += sizeof(*wp);
+ while (--ops >= 0)
+ {
+ start += *cbuf++;
+ if ((count = *cbuf++) == 0)
+ count = 256;
+ (*output)(s, start, (Color *)cbuf, count);
+ cbuf += 3*count;
+ start += count;
+ }
+}
+
+static void decode_color_256(Uchar *data, Flic *flic, Screen *s)
+/* Decode COLOR_256 chunk. */
+{
+ decode_color(data, flic, s, screen_put_colors);
+}
+
+static void decode_color_64(Uchar *data, Flic *flic, Screen *s)
+/* Decode COLOR_64 chunk. */
+{
+ decode_color(data, flic, s, screen_put_colors_64);
+}
+
+
+static void decode_byte_run(Uchar *data, Flic *flic, Screen *s)
+/* Byte-run-length decompression. */
+{
+ int x,y;
+ int width = flic->head.width;
+ int height = flic->head.height;
+ Char psize;
+ Char *cpt = data;
+ int end;
+
+ y = flic->yoff;
+ end = flic->xoff + width;
+ while (--height >= 0)
+ {
+ x = flic->xoff;
+ cpt += 1; /* skip over obsolete opcount byte */
+ psize = 0;
+ while ((x+=psize) < end)
+ {
+ psize = *cpt++;
+ if (psize >= 0)
+ {
+ screen_repeat_one(s, x, y, *cpt++, psize);
+ }
+ else
+ {
+ psize = -psize;
+ screen_copy_seg(s, x, y, (Pixel *)cpt, psize);
+ cpt += psize;
+ }
+ }
+ y++;
+ }
+}
+
+static void decode_delta_fli(Uchar *data, Flic *flic, Screen *s)
+/* Fli style delta decompression. */
+{
+ int xorg = flic->xoff;
+ int yorg = flic->yoff;
+ Short *wpt = (Short *)data;
+ Uchar *cpt = (Uchar *)(wpt + 2);
+ int x,y;
+ Short lines;
+ Uchar opcount;
+ Char psize;
+
+ y = yorg + *wpt++;
+ lines = *wpt;
+ while (--lines >= 0)
+ {
+ x = xorg;
+ opcount = *cpt++;
+ while (opcount > 0)
+ {
+ x += *cpt++;
+ psize = *cpt++;
+ if (psize < 0)
+ {
+ psize = -psize;
+ screen_repeat_one(s, x, y, *cpt++, psize);
+ x += psize;
+ opcount-=1;
+ }
+ else
+ {
+ screen_copy_seg(s, x, y, (Pixel *)cpt, psize);
+ cpt += psize;
+ x += psize;
+ opcount -= 1;
+ }
+ }
+ y++;
+ }
+}
+
+
+static void decode_delta_flc(Uchar *data, Flic *flic, Screen *s)
+/* Flc-style delta decompression. The data is word oriented though
+* a lot of the control info (how to skip, how many words to
+ * copy) are byte oriented still to save space. */
+{
+ int xorg = flic->xoff;
+ int yorg = flic->yoff;
+ int width = flic->head.width;
+ int x,y;
+ Short lp_count;
+ Short opcount;
+ int psize;
+ union {
+ Short *w;
+ Uchar *ub;
+ Char *b;
+ Pixels2 *p2;
+ } wpt;
+ int lastx;
+
+
+ lastx = xorg + width - 1;
+ wpt.ub = data;
+ lp_count = *wpt.w++;
+ y = yorg;
+ goto LPACK;
+
+SKIPLINES: /* Advance over some lines. */
+ y -= opcount;
+
+LPACK: /* do next line */
+ if ((opcount = *wpt.w++) >= 0)
+ goto DO_SS2OPS;
+ if( ((Ushort)opcount) & 0x4000) /* skip lines */
+ goto SKIPLINES;
+ screen_put_dot(s,(Uchar)opcount,lastx,y); /* put dot at eol with low byte */
+ if((opcount = *wpt.w++) == 0)
+ {
+ ++y;
+ if (--lp_count > 0)
+ goto LPACK;
+ goto OUT;
+ }
+DO_SS2OPS:
+ x = xorg;
+
+PPACK: /* do next packet */
+ x += *wpt.ub++;
+ psize = *wpt.b++;
+ if ((psize += psize) >= 0)
+ {
+ screen_copy_seg(s, x, y, (Pixel *)wpt.ub, psize);
+ x += psize;
+ wpt.ub += psize;
+ if (--opcount != 0)
+ goto PPACK;
+ ++y;
+ if (--lp_count > 0)
+ goto LPACK;
+ }
+ else
+ {
+ psize = -psize;
+ screen_repeat_two(s, x, y, *wpt.p2++, psize>>1);
+ x += psize;
+ if (--opcount != 0)
+ goto PPACK;
+ ++y;
+ if (--lp_count > 0)
+ goto LPACK;
+ }
+OUT:
+ return;
+}
+
+static void decode_black(Uchar *data, Flic *flic, Screen *s)
+/* Decode a BLACK chunk. Set frame to solid color 0 one
+ * line at a time. */
+{
+ Pixels2 black;
+ int i;
+ int height = flic->head.height;
+ int width = flic->head.width;
+ int x = flic->xoff;
+ int y = flic->yoff;
+
+ black.pixels[0] = black.pixels[1] = 0;
+ for (i=0; i<height; ++i)
+ {
+ screen_repeat_two(s, x, y+i, black, width/2);
+ if (width & 1) /* if odd set last pixel */
+ screen_put_dot(s, x+width-1, y+i, 0);
+ }
+}
+
+static void decode_literal(Uchar *data, Flic *flic, Screen *s)
+/* Decode a LITERAL chunk. Just copy data to screen one line at
+ * a time. */
+{
+ int i;
+ int height = flic->head.height;
+ int width = flic->head.width;
+ int x = flic->xoff;
+ int y = flic->yoff;
+
+ for (i=0; i<height; ++i)
+ {
+ screen_copy_seg(s, x, y+i, (Pixel *)data, width);
+ data += width;
+ }
+}
+
+ErrCode SetupFlicAccess (Flic * flic)
+{
+ if (flic->usefile==TRUE)
+ {
+ return file_open_to_read(&flic->handle, flic->name);
+ }
+ else
+ {
+ flic->flicoffset=0;
+ return Success;
+ }
+}
+
+ErrCode CopyNextFlicBlock (Flic * flic, MemPtr buf, Ulong size)
+{
+ ErrCode err;
+
+ if (flic->usefile==TRUE)
+ {
+ err = file_read_big_block(flic->handle, buf, size);
+ return err;
+ }
+ else
+ {
+ memcpy(buf, flic->flicbuffer+flic->flicoffset, size);
+ flic->flicoffset+=size;
+ return Success;
+ }
+}
+
+void SetFlicOffset (Flic * flic, Ulong offset )
+{
+ if (flic->usefile==TRUE)
+ {
+ lseek(flic->handle,offset,SEEK_SET);
+ }
+ else
+ {
+ flic->flicoffset = offset;
+ }
+}
+
+
+ErrCode flic_open(Flic *flic, char *name, MemPtr buf, Boolean usefile)
+/* Open flic file. Read header and verify it's a flic.
+ * Seek to first frame. */
+{
+ ErrCode err;
+
+ ClearStruct(flic); /* Start at a known state. */
+ flic->usefile=usefile; /* use file or buffer */
+ flic->name = name; /* Save name for future use. */
+ flic->flicbuffer=buf; /* save address of flicbuffer */
+
+ if ((err = SetupFlicAccess (flic)) >= Success)
+ {
+ if ((err = CopyNextFlicBlock (flic, (Uchar *)&flic->head, sizeof(flic->head)))
+ >= Success)
+ {
+ if (flic->head.type == FLC_TYPE)
+ {
+ /* Seek frame 1. */
+ SetFlicOffset (flic, flic->head.oframe1 );
+ return Success;
+ }
+ if (flic->head.type == FLI_TYPE)
+ {
+ /* Do some conversion work here. */
+ flic->head.oframe1 = sizeof(flic->head);
+ flic->head.speed = flic->head.speed * 1000L / 70L;
+ return Success;
+ }
+ else
+ {
+ err = ErrBadFlic;
+ }
+ }
+ }
+ flic_close(flic); /* Close down and scrub partially opened flic. */
+ return err;
+}
+
+
+void flic_close(Flic *flic)
+/* Close flic file and scrub flic. */
+{
+ if (flic->usefile==TRUE)
+ {
+ close(flic->handle);
+ }
+ ClearStruct(flic); /* Discourage use after close. */
+}
+
+static ErrCode decode_frame(Flic *flic
+ , FrameHead *frame, Uchar *data, Screen *s)
+/* Decode a frame that is in memory already into screen.
+ * Here we just loop through each chunk calling appropriate
+ * chunk decoder.
+ */
+{
+ int i;
+ ChunkHead *chunk;
+
+ for (i=0; i<frame->chunks; ++i)
+ {
+ chunk = (ChunkHead *)data;
+ data += chunk->size;
+ switch (chunk->type)
+ {
+ case COLOR_256:
+ decode_color_256((Uchar *)(chunk+1), flic, s);
+ break;
+ case DELTA_FLC:
+ decode_delta_flc((Uchar *)(chunk+1), flic, s);
+ break;
+ case COLOR_64:
+ decode_color_64((Uchar *)(chunk+1), flic, s);
+ break;
+ case DELTA_FLI:
+ decode_delta_fli((Uchar *)(chunk+1), flic, s);
+ break;
+ case BLACK:
+ decode_black((Uchar *)(chunk+1), flic, s);
+ break;
+ case BYTE_RUN:
+ decode_byte_run((Uchar *)(chunk+1), flic, s);
+ break;
+ case LITERAL:
+ decode_literal((Uchar *)(chunk+1), flic, s);
+ break;
+ default:
+ break;
+ }
+ }
+ return Success;
+}
+
+ErrCode flic_next_frame(Flic *flic, Screen *screen)
+/* Advance to next frame of flic. */
+{
+ FrameHead head;
+ ErrCode err;
+ MemPtr bb;
+ long size;
+
+ if ((err = CopyNextFlicBlock (flic, (Uchar *)&head, sizeof(head))) >= Success)
+ {
+ if (head.type == FRAME_TYPE)
+ {
+ size = head.size - sizeof(head); /* Don't include head. */
+ if (size > 0)
+ {
+ if ((err = big_alloc(&bb, size)) >= Success)
+ {
+ if ((err = CopyNextFlicBlock (flic, bb, size)) >= Success)
+ {
+ err = decode_frame(flic, &head, bb, screen);
+ }
+ big_free(&bb);
+ }
+ }
+ }
+ else
+ {
+ err = ErrBadFrame;
+ }
+ }
+ return err;
+}
+
+
+static Ulong calc_end_time(Ulong millis)
+/* Little helper subroutine to find out when to start on next
+ * frame. */
+{
+ return (GetCinematicTime() + ( (millis * CLOCKSPEED) / 4000l) );
+}
+
+static ErrCode wait_til(Ulong end_time, Machine *machine)
+/* This waits until key is hit or end_time arrives.
+ * Return Success if timed out, ErrCancel if key hit.
+ * Insures keyboard will be polled at least once.
+ */
+{
+ do
+ {
+ if (CinematicAbort()!=0)
+ return ErrCancel;
+ }
+ while (GetCinematicTime() < end_time);
+ return Success;
+}
+
+ErrCode flic_play_once(Flic *flic, Machine *machine)
+/* Play a flic through once. */
+{
+ ErrCode err;
+ int i;
+ Ulong end_time;
+
+ for (i=0; i<flic->head.frames; ++i)
+ {
+ end_time = calc_end_time(flic->head.speed);
+ if ((err = flic_next_frame(flic, &machine->screen)) < Success)
+ break;
+ if ((err = wait_til(end_time, machine)) < Success)
+ break;
+ }
+ return err;
+}
+
+static ErrCode fill_in_frame2(Flic *flic)
+/* This figures out where the second frame of the flic is
+ * (useful for playing in a loop). */
+{
+ FrameHead head;
+ ErrCode err;
+
+ SetFlicOffset (flic, flic->head.oframe1 );
+ if ((err = CopyNextFlicBlock (flic, (MemPtr)&head, sizeof(head))) < Success)
+ return err;
+ flic->head.oframe2 = flic->head.oframe1 + head.size;
+ return Success;
+}
+
+ErrCode flic_play_loop(Flic *flic, Machine *machine)
+/* Play a flic until key is pressed. */
+{
+ int i;
+ Ulong end_time;
+ ErrCode err;
+
+ if (flic->head.oframe2 == 0)
+ {
+ fill_in_frame2(flic);
+ }
+ /* Seek to first frame. */
+ SetFlicOffset (flic, flic->head.oframe1 );
+ /* Save time to move on. */
+ end_time = calc_end_time(flic->head.speed);
+ /* Display first frame. */
+ if ((err = flic_next_frame(flic, &machine->screen)) < Success)
+ return err;
+ for (;;)
+ {
+ /* Seek to second frame */
+ SetFlicOffset (flic, flic->head.oframe2 );
+ /* Loop from 2nd frame thru ring frame*/
+ for (i=0; i<flic->head.frames; ++i)
+ {
+ if (wait_til(end_time, machine) < Success)
+ return Success; /* Time out is a success here. */
+ if ((err = flic_next_frame(flic, &machine->screen)) < Success)
+ return err;
+ end_time = calc_end_time(flic->head.speed);
+ }
+ }
+}
+
+
+static char *err_strings[] =
+{
+ "Unspecified error",
+ "Not enough memory",
+ "Not a flic file",
+ "Bad frame in flic",
+ NULL,
+ NULL,
+ "Couldn't open display",
+ "Couldn't open keyboard",
+ "User canceled action",
+};
+
+char *flic_err_string(ErrCode err)
+/* Return a string that describes an error. */
+{
+ if (err >= Success)
+ return "Success"; /* Shouldn't happen really... */
+ if (err == ErrOpen || err == ErrRead)
+ return strerror(errno); /* Get Disk IO error from DOS. */
+ err = -err;
+ err -= 1;
+ if (err > ArrayEls(err_strings))
+ return "Unknown error";
+ return err_strings[err];
+}
+
+
+static void center_flic(Flic *flic, Screen *s)
+/* Set flic.xoff and flic.yoff so flic plays centered rather
+ * than in upper left corner of display. */
+{
+ flic->xoff = (screen_width(s) - (signed)flic->head.width)/2;
+ flic->yoff = (screen_height(s) - (signed)flic->head.height)/2;
+}
+
+void PlayFlic ( char * name, unsigned char * buffer, int usefile, int loop)
+{
+ ErrCode err;
+ Flic flic;
+ Machine machine;
+
+ if ((err = machine_open(&machine)) >= Success)
+ {
+ if ((err = flic_open(&flic, name, buffer, usefile)) >= Success)
+ {
+ center_flic(&flic, &machine.screen);
+ if (loop==0)
+ {
+ err = flic_play_once(&flic, &machine);
+ }
+ else
+ {
+ err = flic_play_loop(&flic, &machine);
+ }
+ flic_close(&flic);
+ }
+ machine_close(&machine);
+ }
+ if (err < Success && err != ErrCancel)
+ {
+ Error("Play Flic had troubles with %s.\n%s.\n",name, flic_err_string(err));
+ }
+}
+
--- /dev/null
+++ b/rott/fli_main.h
@@ -1,0 +1,92 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/* Readflic.h - file containing prototypes and other
+ * structural info for readflic program.
+ *
+ * Copyright (c) 1992 Jim Kent. This file may be freely used, modified,
+ * copied and distributed. This file was first published as part of
+ * an article for Dr. Dobb's Journal March 1993 issue.
+ */
+
+/* Some handy macros I use in lots of programs: */
+
+#define ArrayEls(a) (sizeof(a)/sizeof((a)[0]))
+/* Count up number of elements in an array */
+
+#define ClearMem(buf,size) memset(buf, 0, size)
+/* Clear a block of memory. */
+
+#define ClearStruct(pt) ClearMem(pt, sizeof(*(pt)))
+/* Clear a structure (pass in pointer) */
+
+
+/* Data structures peculiar to readflic program: */
+
+typedef struct
+{
+ FlicHead head; /* Flic file header. */
+ int handle; /* File handle. */
+ int frame; /* Current frame in flic. */
+ char *name; /* Name from flic_open. Helps error reporting. */
+ int xoff,yoff; /* Offset to display flic at. */
+ MemPtr flicbuffer; // address of flicbuffer in memory
+ int flicoffset;
+ Boolean usefile;
+} Flic;
+
+
+/* Prototypes peculiar to readflic program: */
+
+ErrCode flic_open(Flic *flic, char *name, MemPtr buf, Boolean usefile);
+/* Open flic file. Read header and verify it's a flic. */
+
+void flic_close(Flic *flic);
+/* Close flic file and scrub flic. */
+
+ErrCode flic_play_once(Flic *flic, Machine *machine);
+/* Play a flic through once. */
+
+ErrCode flic_play_loop(Flic *flic, Machine *machine);
+/* Play a flic until key is pressed. */
+
+ErrCode flic_next_frame(Flic *flic, Screen *screen);
+/* Advance to next frame of flic. */
+
+ErrCode SetupFlicAccess (Flic * flic);
+
+ErrCode CopyNextFlicBlock (Flic * flic, MemPtr buf, Ulong size);
+
+void SetFlicOffset (Flic * flic, Ulong offset );
+
+
+char *flic_err_string(ErrCode err);
+
+/* Various error codes flic reader can get. */
+#define ErrNoMemory -2 /* Not enough memory. */
+#define ErrBadFlic -3 /* File isn't a flic. */
+#define ErrBadFrame -4 /* Bad frame in flic. */
+#define ErrOpen -5 /* Couldn't open file. Check errno. */
+#define ErrRead -6 /* Couldn't read file. Check errno. */
+#define ErrDisplay -7 /* Couldn't open display. */
+#define ErrClock -8 /* Couldn't open clock. */
+#define ErrKey -9 /* Couldn't open keyboard. */
+#define ErrCancel -10 /* User cancelled. */
+
+
--- /dev/null
+++ b/rott/fli_type.h
@@ -1,0 +1,53 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/* Types.h - integer types defined for portability between compilers and
+ * notational convenience.
+ *
+ * Copyright (c) 1992 Jim Kent. This file may be freely used, modified,
+ * copied and distributed. This file was first published as part of
+ * an article for Dr. Dobb's Journal March 1993 issue.
+ */
+
+#ifndef TYPES_H /* Prevent file from being included twice. */
+#define TYPES_H
+
+typedef signed char Char; /* Signed 8 bits. */
+typedef unsigned char Uchar; /* Unsigned 8 bits. */
+typedef short Short; /* Signed 16 bits please. */
+typedef unsigned short Ushort; /* Unsigned 16 bits please. */
+typedef int Long; /* Signed 32 bits. */
+typedef unsigned int Ulong; /* Unsigned 32 bits. */
+
+typedef int Boolean; /* TRUE or FALSE value. */
+typedef int ErrCode; /* ErrXXX or Success. */
+typedef int FileHandle; /* OS file handle. */
+
+/* Values for Boolean types */
+#define FALSE 0
+#define TRUE (!FALSE)
+
+/* Values for ErrCodes */
+#define Success 0 /* Things are fine. */
+#define AError -1 /* Unclassified error. */
+
+#define int86 int386
+#define inportb inp
+#define outportb outp
+#endif /* TYPES_H */
--- /dev/null
+++ b/rott/fli_util.c
@@ -1,0 +1,414 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/* pcclone.c - This file contains all the machine specific bits of the
+ * flic reader. It's job is to set up data structures and routines for
+ * the Screen, Clock, and Key structures, and the Machine structure
+ * that contains them all.
+ *
+ * For optimum performance a flic-reader should be coded in assembler.
+ * However you can get significantly greater performance merely by
+ * recoding in assembler the three routines: screen_copy_seg(),
+ * screen_repeat_one() and screen_repeat_two().
+ *
+ * Copyright (c) 1992 Jim Kent. This file may be freely used, modified,
+ * copied and distributed. This file was first published as part of
+ * an article for Dr. Dobb's Journal March 1993 issue.
+ */
+
+#include "cin_glob.h"
+#include <bios.h>
+#include <dos.h>
+#include <time.h>
+#include <stdlib.h>
+#include <mem.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <io.h>
+#include <conio.h>
+#include "fli_type.h"
+#include "fli_util.h"
+#include "fli_def.h"
+#include "fli_main.h"
+//MED
+#include "memcheck.h"
+
+static Ushort screenlookup[200];
+
+/** Screen oriented stuff. **/
+
+static Boolean set_vmode(Uchar mode)
+/* Ask bios to set video mode. */
+{
+ union REGS regs;
+
+ regs.h.ah = 0; /* Set Video Mode request. */
+ regs.h.al = mode; /* For our specific mode. */
+ int86(0x10, ®s, ®s);
+ return TRUE;
+// return (regs.x.cflag == 0); /* Carry flag clear? */
+}
+
+static Uchar get_vmode()
+/* Ask bios for current video mode. */
+{
+ union REGS regs;
+
+ regs.h.ah = 0xF; /* Get Video Mode request. */
+ int86(0x10, ®s, ®s);
+ return regs.h.al;
+}
+
+ErrCode screen_open(Screen *s)
+/* Put machine into graphics mode and fill out screen structure. */
+{
+ ClearStruct(s); /* Start in a known state... */
+ s->old_mode = get_vmode();
+ if (set_vmode(0x13))
+ {
+ if (get_vmode() == 0x13)
+ {
+ int i;
+
+ s->is_open = TRUE; /* Now it's open. */
+ s->width = 320;
+ s->height = 200;
+ for (i=0; i<200; i++)
+ screenlookup[i]=320*i;
+ s->pixels = (unsigned char *)0xA0000; /* Base video screen address. */
+ return Success;
+ }
+ }
+ /* If got to here have failed. Restore old video mode and return
+ * failure code. */
+ set_vmode(s->old_mode);
+ return ErrDisplay;
+}
+
+void screen_close(Screen *s)
+/* Close screen. Restore original display mode. */
+{
+ if (s->is_open) /* Don't do this twice... */
+ {
+// set_vmode(s->old_mode);
+ ClearStruct(s); /* Discourage use after it's closed... */
+ }
+}
+
+int screen_width(Screen *s)
+/* Return width of screen. */
+{
+ return s->width;
+}
+
+int screen_height(Screen *s)
+/* Return height of screen. */
+{
+ return s->height;
+}
+
+void screen_put_dot(Screen *s, int x, int y, Pixel color)
+/* Set one dot. */
+{
+ /* First clip it. */
+ if (x < 0 || y < 0 || x >= s->width || y >= s->height)
+ return;
+
+ /* Then set it. */
+ s->pixels[screenlookup[y] + x] = color;
+}
+
+static Boolean line_clip(Screen *s, int *px, int *py, int *pwidth)
+/* Clip a horizontal line segment so that it fits on the screen.
+ * Return FALSE if clipped out entirely. */
+{
+ int x = *px;
+ int y = *py;
+ int width = *pwidth;
+ int xend = x + width;
+
+ if (y < 0 || y >= s->height || xend < 0 || x >= s->width)
+ return FALSE; /* Clipped off screen. */
+ if (x < 0)
+ {
+ *pwidth = width = width + x; /* and shortens width. */
+ *px = 0;
+ }
+ if (xend > s->width)
+ {
+ *pwidth = width = width - (xend - s->width);
+ }
+ if (width < 0)
+ return FALSE;
+ return TRUE;
+}
+
+void screen_copy_seg(Screen *s, int x, int y, Pixel *pixels, int count)
+/* Copy pixels from memory into screen. */
+{
+ Pixel *pt;
+ int unclipped_x = x;
+
+ /* First let's do some clipping. */
+ if (!line_clip(s, &x, &y, &count))
+ return;
+
+ pixels += (x - unclipped_x); /* Clipping change in start position. */
+
+ /* Calculate start screen address. */
+ pt = s->pixels + (unsigned)screenlookup[y] + (unsigned)x;
+
+ /* Copy pixels to display. */
+ memcpy (pt,pixels,count);
+}
+
+void screen_repeat_one(Screen *s, int x, int y, Pixel color, int count)
+/* Draw a horizontal line of a solid color */
+{
+ Pixel *pt;
+
+ /* First let's do some clipping. */
+ if (!line_clip(s, &x, &y, &count))
+ return;
+
+ /* Calculate start screen address. */
+ pt = s->pixels + (unsigned)screenlookup[y] + (unsigned)x;
+
+ /* Repeat pixel on display. */
+ memset (pt,color,count);
+}
+
+void screen_repeat_two(Screen *s, int x, int y, Pixels2 pixels2, int count)
+/* Repeat 2 pixels count times on screen. */
+{
+ Pixels2 *pt;
+ int is_odd;
+
+ /* First let's do some clipping. */
+ count <<= 1; /* Convert from word to pixel count. */
+ if (!line_clip(s, &x, &y, &count))
+ return;
+ is_odd = (count&1); /* Did it turn odd after clipping? Ack! */
+ count >>= 1; /* Convert back to word count. */
+
+ /* Calculate start screen address. */
+ pt = (Pixels2 *)(s->pixels + (unsigned)screenlookup[y] + (unsigned)x);
+
+ while (--count >= 0) /* Go set screen 2 pixels at a time. */
+ *pt++ = pixels2;
+
+ if (is_odd) /* Deal with pixel at end of screen if needed. */
+ {
+ Pixel *end = (Pixel *)pt;
+ *end = pixels2.pixels[0];
+ }
+}
+
+
+void screen_put_colors(Screen *s, int start, Color *colors, int count)
+/* Set count colors in color map starting at start. RGB values
+ * go from 0 to 255. */
+{
+ int end = start + count;
+ int ix;
+
+ for (ix = start; ix < end; ++ix)
+ {
+ outportb(0x3C8, ix);
+ outportb(0x3C9, colors->r>>2);
+ outportb(0x3C9, colors->g>>2);
+ outportb(0x3C9, colors->b>>2);
+ ++colors;
+ }
+}
+
+void screen_put_colors_64(Screen *s, int start, Color *colors, int count)
+/* Set count colors in color map starting at start. RGB values
+ * go from 0 to 64. */
+{
+ int end = start + count;
+ int ix;
+
+ for (ix = start; ix < end; ++ix)
+ {
+ outportb(0x3C8, ix);
+ outportb(0x3C9, colors->r);
+ outportb(0x3C9, colors->g);
+ outportb(0x3C9, colors->b);
+ ++colors;
+ }
+}
+
+#if 0
+/** Clock oriented stuff. **/
+
+#define CMODE 0x43
+#define CDATA 0x40
+
+ErrCode clock_open(Clock *c)
+/* Set up clock and store speed of clock. */
+{
+ c->speed = 4608; /* Our peculiar speed. */
+ outportb(CMODE, 0x34); /* Change from divide by two to linear. */
+ outportb(CDATA, 0); /* Set period to highest available. */
+ outportb(CDATA, 0);
+ return Success;
+}
+
+void clock_close(Clock *c)
+/* Return clock to normal. */
+{
+ outportb(CMODE, 0x36); /* Change from linear to divide by two. */
+ outportb(CDATA, 0); /* Set period to highest available. */
+ outportb(CDATA, 0);
+}
+
+Ulong clock_ticks(Clock *c)
+/* Get current clock tick. */
+{
+ /* This routine returns a clock with occassional spikes where time will
+ * look like its running backwards 1/18th of a second. The resolution
+ * of the clock is 1/(18*256) = 1/4608 second. The spikes are ok for
+ * our purposes since the wait loop will just ignore them. */
+ union REGS regs;
+ Uchar chip_time;
+ Ulong time;
+
+ regs.h.ah = 0; /* Go ask BIOS timer services */
+ int86(0x1A, ®s, ®s); /* for time in 1/18ths second. */
+ outportb(CMODE,0); /* Latch time at timer chip. */
+ inportb(CDATA); /* Read in LSB of chip time and discard. */
+ chip_time = inportb(CDATA); /* Read in MSB of chip time and save. */
+ chip_time = -(signed char)chip_time;
+ /* We calculate the time using 3 bytes from the BIOS 18hz counter
+ * and one byte from the timer chip itself. We discard the hi
+ * byte of the BIOS time, shift the rest left by 8, and
+ * fill in the low byte with the MSB from the chip timer.
+ * This looks a little more complicated than this because
+ * the bios time is in various registers - cx for the hi word
+ * and dx for the low word. */
+ time = (Ulong)regs.h.cl << 24L; /* Get MSB of our final time. */
+ time += (Ulong)regs.w.dx << 8L; /* Fold in middle two bytes. */
+ time += (Ulong)chip_time; /* Add in LSB from chip. */
+ return time;
+}
+
+
+/** Keyboard oriented stuff. **/
+
+ErrCode key_open(Key *key)
+/* Set up keyboard. */
+{
+ return Success; /* Pretty easy on a PC. */
+}
+
+void key_close(Key *key)
+/* Close keyboard. */
+{
+ return; /* Also very easy under DOS. */
+}
+
+Boolean key_ready(Key *key)
+/* See if a key is ready. */
+{
+ unsigned val;
+
+ if ((val = _bios_keybrd(_KEYBRD_READY)) == 0)
+ return FALSE;
+ else
+ {
+ key->ascii = val;
+ key->scancode = val;
+ return TRUE;
+ }
+}
+
+Uchar key_read(Key *key)
+/* Get next key. */
+{
+ unsigned val;
+
+ val = _bios_keybrd(_KEYBRD_READ);
+ key->ascii = val;
+ key->scancode = val;
+ return key->ascii;
+}
+
+#endif
+
+/** MemPtr stuff - to allocate and free blocks of memory > 64K. */
+
+ErrCode big_alloc(MemPtr *bb, Ulong size)
+/* Allocate a big block. */
+{
+ (*bb) = SafeMalloc (size);
+ return Success;
+}
+
+void big_free(MemPtr *bb)
+/* Free up a big block. */
+{
+ SafeFree(*bb);
+}
+
+/** Stuff for reading files - regular and over 64k blocks at a time. **/
+
+ErrCode file_open_to_read(FileHandle *phandle, char *name)
+/* Open a binary file to read. */
+{
+ *phandle = SafeOpenRead(name);
+ return Success;
+}
+
+ErrCode file_read_big_block(FileHandle handle, MemPtr bb, Ulong size)
+/* Read in a big block. Could be bigger than 64K. */
+{
+ SafeRead (handle,bb,size);
+ return Success;
+}
+
+
+/** Machine oriented stuff - open and close the whole banana. **/
+
+ErrCode machine_open(Machine *machine)
+/* Open up machine: keyboard, clock, and screen. */
+{
+ ErrCode err;
+
+ ClearStruct(machine); /* Start it in a known state. */
+//if ((err = key_open(&machine->key)) >= Success)
+ {
+// if ((err = clock_open(&machine->clock)) >= Success)
+ {
+ if ((err = screen_open(&machine->screen)) >= Success)
+ return Success;
+// clock_close(&machine->clock);
+ }
+// key_close(&machine->key);
+ }
+ return err;
+}
+
+void machine_close(Machine *machine)
+/* Close down machine. */
+{
+ screen_close(&machine->screen);
+//clock_close(&machine->clock);
+//key_close(&machine->key);
+}
--- /dev/null
+++ b/rott/fli_util.h
@@ -1,0 +1,164 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/* pcclone.h - machine specific parts of readflic. Structures and
+ * prototypes for polling the keyboard, checking the time,
+ * writing to the video screen, allocating large blocks of memory
+ * and reading files.
+ *
+ * Copyright (c) 1992 Jim Kent. This file may be freely used, modified,
+ * copied and distributed. This file was first published as part of
+ * an article for Dr. Dobb's Journal March 1993 issue.
+ */
+
+#ifndef PCCLONE_H /* Prevent file from being included twice. */
+#define PCCLONE_H
+
+typedef Uchar Pixel; /* Pixel type. */
+
+typedef struct
+{
+ Uchar r,g,b;
+} Color; /* One color map entry r,g,b 0-255. */
+
+typedef struct
+{
+ Pixel pixels[2];
+} Pixels2; /* For word-oriented run length encoding */
+
+typedef struct
+{
+ Pixel *pixels; /* Set to AOOO:0000 for hardware. */
+ int width, height; /* Dimensions of screen. (320x200) */
+ int old_mode; /* Mode screen was in originally. */
+ Boolean is_open; /* Is screen open? */
+} Screen; /* Device specific screen type. */
+
+
+/* Prototypes for routines that work on display screen. */
+
+ErrCode screen_open(Screen *s);
+/* Put machine into graphics mode and fill out screen structure. */
+
+void screen_close(Screen *s);
+/* Close screen. Restore original display mode. */
+
+int screen_width(Screen *s);
+/* Return width of screen. */
+
+int screen_height(Screen *s);
+/* Return height of screen. */
+
+void screen_put_dot(Screen *s, int x, int y, Pixel color);
+/* Set one dot. */
+
+void screen_copy_seg(Screen *s, int x, int y, Pixel *pixels, int count);
+/* Copy pixels from memory into screen. */
+
+void screen_repeat_one(Screen *s, int x, int y, Pixel color, int count);
+/* Draw a horizontal line of a solid color */
+
+void screen_repeat_two(Screen *s, int x,int y, Pixels2 pixels2, int count);
+/* Repeat 2 pixels count times on screen. */
+
+void screen_put_colors(Screen *s, int start, Color *colors, int count);
+/* Set count colors in color map starting at start. RGB values
+ * go from 0 to 255. */
+
+void screen_put_colors_64(Screen *s, int start, Color *colors, int count);
+/* Set count colors in color map starting at start. RGB values
+ * go from 0 to 64. */
+
+
+/* Clock structure and routines. */
+
+typedef struct
+{
+ Ulong speed; /* Number of clock ticks per second. */
+} Clock;
+
+ErrCode clock_open(Clock *clock);
+/* Set up millisecond clock. */
+
+void clock_close(Clock *clock);
+/* Return clock to normal. */
+
+Ulong clock_ticks(Clock *clock);
+/* Get time in terms of clock->speed. */
+
+/* Keyboard structure and routines. */
+
+typedef struct
+{
+ Uchar ascii;
+ Ushort scancode;
+} Key;
+
+ErrCode key_open(Key *key);
+/* Set up keyboard. */
+
+void key_close(Key *key);
+/* Close keyboard. */
+
+Boolean key_ready(Key *key);
+/* See if a key is ready. */
+
+Uchar key_read(Key *key);
+/* Get next key. */
+
+
+/** MemPtr - handles allocating big blocks of memory (>64K) on the
+ ** PC. On other machines may be much simpler. */
+
+typedef Uchar * MemPtr;
+
+ErrCode big_alloc(MemPtr *bb, Ulong size);
+/* Allocate a big block. */
+
+void big_free(MemPtr *bb);
+/* Free up a big block. */
+
+/** Stuff for reading files - regular and over 64k blocks at a time. **/
+
+ErrCode file_open_to_read(FileHandle *phandle, char *name);
+/* Open a binary file to read. */
+
+ErrCode file_read_block(FileHandle handle, void *block, unsigned size);
+/* Read in a block. If read less than size return error code. */
+
+ErrCode file_read_big_block(FileHandle handle, MemPtr bb, Ulong size);
+/* Read in a big block. Could be bigger than 64K. */
+
+
+
+/** Machine structure - contains all the machine dependent stuff. **/
+
+typedef struct
+{
+ Screen screen;
+ Clock clock;
+ Key key;
+} Machine;
+
+ErrCode machine_open(Machine *machine);
+/* Open up machine: keyboard, clock, screen. */
+
+void machine_close(Machine *machine);
+/* Close down machine. */
+#endif /* PCCLONE_H */
--- /dev/null
+++ b/rott/fx_man.c
@@ -1,0 +1,1307 @@
+/*
+ * A reimplementation of Jim Dose's FX_MAN routines, using SDL_mixer 1.2.
+ * Whee. FX_MAN is also known as the "Apogee Sound System", or "ASS" for
+ * short. How strangely appropriate that seems.
+ *
+ * Written by Ryan C. Gordon. (icculus@clutteredmind.org)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <assert.h>
+
+#if (defined __WATCOMC__)
+#include "dukesnd_watcom.h"
+#endif
+
+#if (!defined __WATCOMC__)
+#define cdecl
+#endif
+
+#include "SDL.h"
+#include "SDL_mixer.h"
+#include "rt_def.h" // ROTT music hack
+#include "rt_cfg.h" // ROTT music hack
+#include "rt_util.h" // ROTT music hack
+#include "fx_man.h"
+#include "music.h"
+
+#define __FX_TRUE (1 == 1)
+#define __FX_FALSE (!__FX_TRUE)
+
+#define DUKESND_DEBUG "DUKESND_DEBUG"
+
+#ifndef min
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef max
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+typedef struct __DUKECHANINFO
+{
+ int in_use; // 1 or 0.
+ int priority; // priority, defined by application.
+ Uint32 birthday; // ticks when channel was grabbed.
+ unsigned long callbackval; // callback value from application.
+} duke_channel_info;
+
+
+static char warningMessage[80];
+static char errorMessage[80];
+static int fx_initialized = 0;
+static int numChannels = MIX_CHANNELS;
+static void (*callback)(unsigned long);
+static int reverseStereo = 0;
+static int reverbDelay = 256;
+static int reverbLevel = 0;
+static int fastReverb = 0;
+static FILE *debug_file = NULL;
+static int initialized_debugging = 0;
+static int maxReverbDelay = 256;
+static int mixerIsStereo = 1;
+static duke_channel_info *chaninfo = NULL;
+
+#define HandleOffset 1
+
+/* these come from the real ASS */
+#define MV_MaxPanPosition 31
+#define MV_NumPanPositions ( MV_MaxPanPosition + 1 )
+#define MV_MaxVolume 63
+
+#define MIX_VOLUME( volume ) \
+ ( ( max( 0, min( ( volume ), 255 ) ) * ( MV_MaxVolume + 1 ) ) >> 8 )
+
+typedef struct
+{
+ unsigned char left;
+ unsigned char right;
+} Pan;
+
+static Pan MV_PanTable[ MV_NumPanPositions ][ MV_MaxVolume + 1 ];
+
+static void MV_CalcPanTable
+(
+ void
+)
+
+{
+ int level;
+ int angle;
+ int distance;
+ int HalfAngle;
+ int ramp;
+
+ HalfAngle = ( MV_NumPanPositions / 2 );
+
+ for( distance = 0; distance <= MV_MaxVolume; distance++ )
+ {
+ level = ( 255 * ( MV_MaxVolume - distance ) ) / MV_MaxVolume;
+ for( angle = 0; angle <= HalfAngle / 2; angle++ )
+ {
+ ramp = level - ( ( level * angle ) /
+ ( MV_NumPanPositions / 4 ) );
+
+ MV_PanTable[ angle ][ distance ].left = ramp;
+ MV_PanTable[ HalfAngle - angle ][ distance ].left = ramp;
+ MV_PanTable[ HalfAngle + angle ][ distance ].left = level;
+ MV_PanTable[ MV_MaxPanPosition - angle ][ distance ].left = level;
+
+ MV_PanTable[ angle ][ distance ].right = level;
+ MV_PanTable[ HalfAngle - angle ][ distance ].right = level;
+ MV_PanTable[ HalfAngle + angle ][ distance ].right = ramp;
+ MV_PanTable[ MV_MaxPanPosition - angle ][ distance ].right = ramp;
+ }
+ }
+}
+/* end ASS copy-pastage */
+
+#ifdef __WATCOMC__
+#pragma aux (__cdecl) channelDoneCallback;
+#endif
+
+// This function is called whenever an SDL_mixer channel completes playback.
+// We use this for state management and calling the application's callback.
+static void channelDoneCallback(int channel)
+{
+ Mix_FreeChunk(Mix_GetChunk(channel));
+ if (callback)
+ {
+ callback(chaninfo[channel].callbackval);
+ chaninfo[channel].in_use = 0;
+ } // if
+} // channelDoneCallback
+
+
+// This gets called all over the place for information and debugging messages.
+// If the user set the DUKESND_DEBUG environment variable, the messages
+// go to the file that is specified in that variable. Otherwise, they
+// are ignored for the expense of the function call. If DUKESND_DEBUG is
+// set to "-" (without the quotes), then the output goes to stdout.
+static void snddebug(const char *fmt, ...) __attribute__((format(printf,1,2)));
+static void snddebug(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (debug_file)
+ {
+ fprintf(debug_file, "DUKESND: ");
+ va_start(ap, fmt);
+ vfprintf(debug_file, fmt, ap);
+ va_end(ap);
+ fprintf(debug_file, "\n");
+ fflush(debug_file);
+ } // if
+} // snddebug
+
+
+// FIXME: Consolidate this code.
+// Same as snddebug(), but a different tag is put on each line.
+static void musdebug(const char *fmt, ...) __attribute__((format(printf,1,2)));
+static void musdebug(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (debug_file)
+ {
+ fprintf(debug_file, "DUKEMUS: ");
+ va_start(ap, fmt);
+ vfprintf(debug_file, fmt, ap);
+ va_end(ap);
+ fprintf(debug_file, "\n");
+ fflush(debug_file);
+ } // if
+} // snddebug
+
+
+static void init_debugging(void)
+{
+ const char *envr;
+
+ if (initialized_debugging)
+ return;
+
+ envr = getenv(DUKESND_DEBUG);
+ if (envr != NULL)
+ {
+ if (strcmp(envr, "-") == 0)
+ debug_file = stdout;
+ else
+ debug_file = fopen(envr, "w");
+
+ if (debug_file == NULL)
+ fprintf(stderr, "DUKESND: -WARNING- Could not open debug file!\n");
+ else
+ setbuf(debug_file, NULL);
+ } // if
+
+ initialized_debugging = 1;
+} // init_debugging
+
+
+// find an available SDL_mixer channel, and reserve it.
+// This would be a race condition, but hey, it's for a DOS game. :)
+static int grabMixerChannel(int priority)
+{
+ int replaceable = -1;
+ int i;
+
+ for (i = 0; i < numChannels; i++)
+ {
+ if (chaninfo[i].in_use == 0)
+ {
+ chaninfo[i].in_use = 1;
+ chaninfo[i].priority = priority;
+ chaninfo[i].birthday = SDL_GetTicks();
+ return(i);
+ } // if
+
+ // !!! FIXME: Should this just be lower priority, or equal too?
+ if (chaninfo[i].priority <= priority)
+ {
+ if ((replaceable == -1) ||
+ (chaninfo[i].birthday < chaninfo[replaceable].birthday))
+ {
+ replaceable = i;
+ } // if
+ } // if
+ } // for
+
+ // if you land here, all mixer channels are playing...
+ if (replaceable != -1) // nothing expendable right now.
+ {
+ chaninfo[replaceable].in_use = 1;
+ chaninfo[replaceable].priority = priority;
+ chaninfo[replaceable].birthday = SDL_GetTicks();
+ } // if
+
+ return(replaceable);
+} // grabMixerChannel
+
+
+// !!! FIXME: Is this correct behaviour?
+char *FX_ErrorString( int ErrorNumber )
+{
+ switch (ErrorNumber)
+ {
+ case FX_Warning:
+ return(warningMessage);
+
+ case FX_Error:
+ return(errorMessage);
+
+ case FX_Ok:
+ return("OK; no error.");
+
+ case FX_ASSVersion:
+ return("Incorrect sound library version.");
+
+ case FX_BlasterError:
+ return("SoundBlaster Error.");
+
+ case FX_SoundCardError:
+ return("General sound card error.");
+
+ case FX_InvalidCard:
+ return("Invalid sound card.");
+
+ case FX_MultiVocError:
+ return("Multiple voc error.");
+
+ case FX_DPMI_Error:
+ return("DPMI error.");
+
+ default:
+ return("Unknown error.");
+ } // switch
+
+ assert(0); // shouldn't hit this point.
+ return(NULL);
+} // FX_ErrorString
+
+
+static void setWarningMessage(const char *msg)
+{
+ strncpy(warningMessage, msg, sizeof (warningMessage));
+ // strncpy() doesn't add the null char if there isn't room...
+ warningMessage[sizeof (warningMessage) - 1] = '\0';
+ snddebug("Warning message set to [%s].", warningMessage);
+} // setErrorMessage
+
+
+static void setErrorMessage(const char *msg)
+{
+ strncpy(errorMessage, msg, sizeof (errorMessage));
+ // strncpy() doesn't add the null char if there isn't room...
+ errorMessage[sizeof (errorMessage) - 1] = '\0';
+ snddebug("Error message set to [%s].", errorMessage);
+} // setErrorMessage
+
+int FX_SetupCard( int SoundCard, fx_device *device )
+{
+ init_debugging();
+
+ snddebug("FX_SetupCard looking at card id #%d...", SoundCard);
+
+ if (device == NULL) // sanity check.
+ {
+ setErrorMessage("fx_device is NULL in FX_SetupCard!");
+ return(FX_Error);
+ } // if
+
+ // Since the actual hardware is abstracted out on modern operating
+ // systems, we just pretend that the system's got a SoundScape.
+ // I always liked that card, even though Ensoniq screwed me on OS/2
+ // drivers back in the day. :)
+ if (SoundCard != SoundScape)
+ {
+ setErrorMessage("Card not found.");
+ snddebug("We pretend to be an Ensoniq SoundScape only.");
+ return(FX_Error);
+ } // if
+
+ device->MaxVoices = 8;
+ device->MaxSampleBits = 16; // SDL_mixer downsamples if needed.
+ device->MaxChannels = 2; // SDL_mixer converts to mono if needed.
+
+ return(FX_Ok);
+} // FX_SetupCard
+
+
+static void output_versions(const char *libname, const SDL_version *compiled,
+ const SDL_version *linked)
+{
+ snddebug("This program was compiled against %s %d.%d.%d,\n"
+ " and is dynamically linked to %d.%d.%d.\n", libname,
+ compiled->major, compiled->minor, compiled->patch,
+ linked->major, linked->minor, linked->patch);
+}
+
+
+static void output_version_info(void)
+{
+ SDL_version compiled;
+ const SDL_version *linked;
+
+ snddebug("Library check...");
+
+ SDL_VERSION(&compiled);
+ linked = SDL_Linked_Version();
+ output_versions("SDL", &compiled, linked);
+
+ MIX_VERSION(&compiled);
+ linked = Mix_Linked_Version();
+ output_versions("SDL_mixer", &compiled, linked);
+} // output_version_info
+
+
+int FX_Init(int SoundCard, int numvoices, int numchannels,
+ int samplebits, unsigned mixrate)
+{
+ Uint16 audio_format = 0;
+ int blocksize;
+
+ init_debugging();
+
+ snddebug("INIT! card=>%d, voices=>%d, chan=>%d, bits=>%d, rate=>%du...",
+ SoundCard, numvoices, numchannels, samplebits, mixrate);
+
+ if (fx_initialized)
+ {
+ setErrorMessage("Sound system is already initialized.");
+ return(FX_Error);
+ } // if
+
+ if (SoundCard != SoundScape) // We pretend there's a SoundScape installed.
+ {
+ setErrorMessage("Card not found.");
+ snddebug("We pretend to be an Ensoniq SoundScape only.");
+ return(FX_Error);
+ } // if
+
+ // other sanity checks...
+ if ((numvoices < 0) || (numvoices > 8))
+ {
+ setErrorMessage("Invalid number of voices to mix (must be 0-8).");
+ return(FX_Error);
+ } // if
+
+ if ((numchannels != MonoFx) && (numchannels != StereoFx))
+ {
+ setErrorMessage("Invalid number of channels (must be 1 or 2).");
+ return(FX_Error);
+ } // if
+
+ if ((samplebits != 8) && (samplebits != 16))
+ {
+ setErrorMessage("Invalid sample size (must be 8 or 16).");
+ return(FX_Error);
+ } // if
+
+ // build pan tables
+ MV_CalcPanTable();
+
+ SDL_ClearError();
+ if (SDL_Init(SDL_INIT_AUDIO) < 0)
+ {
+ setErrorMessage("SDL_Init(SDL_INIT_AUDIO) failed!");
+ snddebug("SDL_GetError() reports: [%s].", SDL_GetError());
+ return(FX_Error);
+ } // if
+
+ audio_format = (samplebits == 8) ? AUDIO_U8 : AUDIO_S16SYS;
+ if (Mix_OpenAudio(mixrate, audio_format, numchannels, 256) < 0)
+ {
+ setErrorMessage(SDL_GetError());
+ return(FX_Error);
+ } // if
+
+ output_version_info();
+
+ numChannels = Mix_AllocateChannels(numvoices);
+ if (numChannels != numvoices)
+ {
+ setErrorMessage(SDL_GetError());
+ Mix_CloseAudio();
+ return(FX_Error);
+ } // if
+
+ blocksize = sizeof (duke_channel_info) * numvoices;
+ chaninfo = malloc(blocksize);
+ if (chaninfo == NULL) // uhoh.
+ {
+ setErrorMessage("Out of memory");
+ Mix_CloseAudio();
+ return(FX_Error);
+ } // if
+ memset(chaninfo, '\0', blocksize);
+
+ Mix_ChannelFinished(channelDoneCallback);
+ maxReverbDelay = (int) (((float) mixrate) * 0.5);
+
+ Mix_QuerySpec(NULL, NULL, &mixerIsStereo);
+ mixerIsStereo = (mixerIsStereo == 2);
+
+ fx_initialized = 1;
+ return(FX_Ok);
+} // FX_Init
+
+
+int FX_Shutdown( void )
+{
+ snddebug("shutting down sound subsystem.");
+
+ if (!fx_initialized)
+ {
+ setErrorMessage("Sound system is not currently initialized.");
+ return(FX_Error);
+ } // if
+
+ Mix_CloseAudio();
+ callback = NULL;
+ free(chaninfo);
+ chaninfo = NULL;
+ reverseStereo = 0;
+ reverbLevel = 0;
+ fastReverb = 0;
+ fx_initialized = 0;
+ maxReverbDelay = 256;
+ return(FX_Ok);
+} // FX_Shutdown
+
+
+int FX_SetCallBack(void (*func)(unsigned long))
+{
+ callback = func;
+ return(FX_Ok);
+} // FX_SetCallBack
+
+
+void FX_SetVolume(int volume)
+{
+ snddebug("setting master volume to %f.2 percent.", (volume / 255.0) * 100);
+ Mix_Volume(-1, volume >> 1); // it's 0-128 in SDL_mixer, not 0-255.
+} // FX_SetVolume
+
+
+int FX_GetVolume(void)
+{
+ return(Mix_Volume(-1, -1) << 1);
+} // FX_GetVolume
+
+
+void FX_SetReverseStereo(int setting)
+{
+ snddebug("Reverse stereo set to %s.\n", setting ? "ON" : "OFF");
+ Mix_SetReverseStereo(MIX_CHANNEL_POST, setting);
+ reverseStereo = setting;
+} // FX_SetReverseStereo
+
+
+int FX_GetReverseStereo(void)
+{
+ return(reverseStereo);
+} // FX_GetReverseStereo
+
+
+void FX_SetReverb(int reverb)
+{
+ reverbLevel = reverb;
+ fastReverb = 0;
+
+#if 1
+ // !!! FIXME
+ if (reverbLevel)
+ setWarningMessage("reverb filter is not yet implemented!");
+#endif
+} // FX_SetReverb
+
+
+void FX_SetFastReverb(int reverb)
+{
+ reverbLevel = reverb;
+ fastReverb = 1;
+
+#if 1
+ // !!! FIXME
+ if (reverbLevel)
+ setWarningMessage("fast reverb filter is not yet implemented!");
+#endif
+} // FX_SetFastReverb
+
+
+int FX_GetMaxReverbDelay(void)
+{
+ return(maxReverbDelay);
+} // FX_GetMaxReverbDelay
+
+
+int FX_GetReverbDelay(void)
+{
+ return(reverbDelay);
+} // FX_GetReverbDelay
+
+
+void FX_SetReverbDelay(int delay)
+{
+ // !!! FIXME: Should I be clamping these values?
+ if (delay < 256)
+ delay = 256;
+
+ if (delay > maxReverbDelay)
+ delay = maxReverbDelay;
+
+ reverbDelay = delay;
+
+#if 1
+ // !!! FIXME
+ setWarningMessage("reverb delay is not yet implemented!");
+#endif
+} // FX_SetReverbDelay
+
+
+int FX_VoiceAvailable(int priority)
+{
+ int chan = grabMixerChannel(priority);
+ int rc = (chan != -1);
+
+ if (rc)
+ chaninfo[chan].in_use = 0;
+
+ return(rc);
+} // FX_VoiceAvailable
+
+
+static int doSetPan(int handle, int vol, int left,
+ int right, int checkIfPlaying)
+{
+ int retval = FX_Warning;
+
+ if ((handle < 0) || (handle >= numChannels))
+ setWarningMessage("Invalid handle in doSetPan().");
+ else if ((checkIfPlaying) && (!Mix_Playing(handle)))
+ setWarningMessage("voice is no longer playing in doSetPan().");
+ else
+ {
+ if (mixerIsStereo)
+ {
+ if ((left < 0) || (left > 255) ||
+ (right < 0) || (right > 255))
+ {
+ setErrorMessage("Invalid argument to FX_SetPan().");
+ retval = FX_Error;
+ } // if
+
+ else
+ {
+ Mix_SetPanning(handle, left, right);
+ } // else
+ } // if
+ else
+ {
+ if ((vol < 0) || (vol > 255))
+ {
+ setErrorMessage("Invalid argument to FX_SetPan().");
+ retval = FX_Error;
+ } // if
+ else
+ {
+ // volume must be from 0-128, so the ">> 1" converts.
+ Mix_Volume(handle, vol >> 1);
+ } // else
+ } // else
+
+ retval = FX_Ok;
+ } // else
+
+ return(retval);
+} // doSetPan
+
+
+int FX_SetPan(int handle, int vol, int left, int right)
+{
+ return(doSetPan(handle - HandleOffset, vol, left, right, 1));
+} // FX_SetPan
+
+
+int FX_SetPitch(int handle, int pitchoffset)
+{
+ snddebug("FX_SetPitch() ... NOT IMPLEMENTED YET!");
+ return(FX_Ok);
+} // FX_SetPitch
+
+
+int FX_SetFrequency(int handle, int frequency)
+{
+ snddebug("FX_SetFrequency() ... NOT IMPLEMENTED YET!");
+ return(FX_Ok);
+} // FX_SetFrequency
+
+
+
+// If this returns FX_Ok, then chunk and chan will be filled with the
+// the block of audio data in the format desired by the audio device
+// and the SDL_mixer channel it will play on, respectively.
+// If the value is not FX_Ok, then the warning or error message is set,
+// and you should bail.
+// size added by SBF for ROTT
+static int setupVocPlayback(char *ptr, int size, int priority, unsigned long callbackval,
+ int *chan, Mix_Chunk **chunk)
+{
+ SDL_RWops *rw;
+
+ *chan = grabMixerChannel(priority);
+ if (*chan == -1)
+ {
+ setErrorMessage("No available channels");
+ return(FX_Error);
+ } // if
+
+ if (size == -1) {
+ // !!! FIXME: This could be a problem...SDL/SDL_mixer wants a RWops, which
+ // !!! FIXME: is an i/o abstraction. Since we already have the VOC data
+ // !!! FIXME: in memory, we fake it with a memory-based RWops. None of
+ // !!! FIXME: this is a problem, except the RWops wants to know how big
+ // !!! FIXME: its memory block is (so it can do things like seek on an
+ // !!! FIXME: offset from the end of the block), and since we don't have
+ // !!! FIXME: this information, we have to give it SOMETHING. My VOC
+ // !!! FIXME: decoder never does seeks from EOF, nor checks for
+ // !!! FIXME: end-of-file, so we should be fine. However, we've got a
+ // !!! FIXME: limit of 10 megs for one file. I hope that'll cover it. :)
+
+ rw = SDL_RWFromMem((void *) ptr, (10 * 1024) * 1024); /* yikes. */
+ } else {
+ // A valid file size! Excellent.
+ rw = SDL_RWFromMem((void *) ptr, size);
+ }
+
+ *chunk = Mix_LoadWAV_RW(rw, 1);
+ if (*chunk == NULL)
+ {
+ setErrorMessage("Couldn't decode voice sample.");
+ chaninfo[*chan].in_use = 0;
+ return(FX_Error);
+ } // if
+
+ chaninfo[*chan].callbackval = callbackval;
+ return(FX_Ok);
+} // setupVocPlayback
+
+static int _FX_SetPosition(int chan, int angle, int distance)
+{
+ int left;
+ int right;
+ int mid;
+ int volume;
+ int status;
+
+ if ( distance < 0 ) {
+ distance = -distance;
+ angle += MV_NumPanPositions / 2;
+ }
+
+ volume = MIX_VOLUME( distance );
+
+ // Ensure angle is within 0 - 31
+ angle &= MV_MaxPanPosition;
+
+ left = MV_PanTable[ angle ][ volume ].left;
+ right = MV_PanTable[ angle ][ volume ].right;
+ mid = max( 0, 255 - distance );
+
+ status = doSetPan( chan, mid, left, right, 0 );
+
+ return status;
+}
+
+int FX_PlayVOC(char *ptr, int pitchoffset,
+ int vol, int left, int right,
+ int priority, unsigned long callbackval)
+{
+ int rc;
+ int chan;
+ Mix_Chunk *chunk;
+
+ snddebug("Playing voice: mono (%d), left (%d), right (%d), priority (%d).\n",
+ vol, left, right, priority);
+
+ rc = setupVocPlayback(ptr, -1, priority, callbackval, &chan, &chunk);
+ if (rc != FX_Ok)
+ return(rc);
+
+ // !!! FIXME: Need to do something with pitchoffset.
+
+ rc = doSetPan(chan, vol, left, right, 0);
+ if (rc != FX_Ok)
+ {
+ chaninfo[chan].in_use = 0;
+ return(rc);
+ } // if
+
+ Mix_PlayChannel(chan, chunk, 0);
+ return(HandleOffset + chan);
+} // FX_PlayVOC
+
+
+// get the size of a single sample, in bytes.
+static int getSampleSize(void)
+{
+ Uint16 format;
+ int channels;
+
+ Mix_QuerySpec(NULL, &format, &channels);
+ return( ((format & 0xFF) / 8) * channels );
+} // getSampleSize
+
+
+int FX_PlayLoopedVOC(char *ptr, long loopstart, long loopend,
+ int pitchoffset, int vol, int left, int right, int priority,
+ unsigned long callbackval)
+{
+ int rc;
+ int chan;
+ int samplesize = getSampleSize();
+ Uint32 totalsamples;
+ Mix_Chunk *chunk;
+
+ snddebug("Playing voice: mono (%d), left (%d), right (%d), priority (%d).\n",
+ vol, left, right, priority);
+ snddebug("Looping: start (%ld), end (%ld).\n", loopstart, loopend);
+
+ rc = setupVocPlayback(ptr, -1, priority, callbackval, &chan, &chunk);
+ if (rc != FX_Ok)
+ return(rc);
+
+ // !!! FIXME: Need to do something with pitchoffset.
+
+ totalsamples = chunk->alen / samplesize;
+
+ if ((loopstart >= 0) && ((unsigned int)loopstart < totalsamples))
+ {
+ if (loopend < 0) loopend = 0;
+ if ((unsigned int)loopend > totalsamples) loopend = totalsamples;
+
+ if (loopend < loopstart)
+ {
+ Mix_FreeChunk(chunk);
+ chaninfo[chan].in_use = 0;
+ setErrorMessage("Loop end is before loop start.");
+ return(FX_Error);
+ } // if
+
+ chunk->alen = loopend * samplesize;
+
+ if (loopstart > 0)
+ {
+ loopstart *= samplesize;
+ memcpy(chunk->abuf, ((Uint8 *) chunk->abuf) + loopstart,
+ chunk->alen - loopstart);
+ chunk->alen -= loopstart;
+ } // if
+ } // if
+
+ Mix_PlayChannel(chan, chunk, -1); /* -1 == looping. */
+ return(HandleOffset + chan);
+} // FX_PlayLoopedVOC
+
+int FX_PlayVOC3D(char *ptr, int pitchoffset, int angle, int distance,
+ int priority, unsigned long callbackval)
+{
+ int rc;
+ int chan;
+ Mix_Chunk *chunk;
+
+ snddebug("Playing voice at angle (%d), distance (%d), priority (%d).\n",
+ angle, distance, priority);
+
+ rc = setupVocPlayback(ptr, -1, priority, callbackval, &chan, &chunk);
+ if (rc != FX_Ok)
+ return(rc);
+
+ // !!! FIXME: Need to do something with pitchoffset.
+
+ _FX_SetPosition(chan, angle, distance);
+
+ Mix_PlayChannel(chan, chunk, 0);
+ return(HandleOffset + chan);
+} // FX_PlayVOC3D
+
+// ROTT Special - SBF
+int FX_PlayVOC3D_ROTT(char *ptr, int size, int pitchoffset, int angle, int distance,
+ int priority, unsigned long callbackval)
+{
+ int rc;
+ int chan;
+ Mix_Chunk *chunk;
+
+ snddebug("Playing voice at angle (%d), distance (%d), priority (%d).\n",
+ angle, distance, priority);
+
+ rc = setupVocPlayback(ptr, size, priority, callbackval, &chan, &chunk);
+ if (rc != FX_Ok)
+ return(rc);
+
+ // !!! FIXME: Need to do something with pitchoffset.
+
+ _FX_SetPosition(chan, angle, distance);
+
+ Mix_PlayChannel(chan, chunk, 0);
+
+ return(HandleOffset + chan);
+} // FX_PlayVOC3D_ROTT
+
+
+// it's all the same to SDL_mixer. :)
+int FX_PlayWAV( char *ptr, int pitchoffset, int vol, int left, int right,
+ int priority, unsigned long callbackval )
+{
+ return(FX_PlayVOC(ptr, pitchoffset, vol, left, right, priority, callbackval));
+} // FX_PlayWAV
+
+
+int FX_PlayLoopedWAV( char *ptr, long loopstart, long loopend,
+ int pitchoffset, int vol, int left, int right, int priority,
+ unsigned long callbackval )
+{
+ return(FX_PlayLoopedVOC(ptr, loopstart, loopend, pitchoffset, vol, left,
+ right, priority, callbackval));
+} // FX_PlayLoopedWAV
+
+
+int FX_PlayWAV3D( char *ptr, int pitchoffset, int angle, int distance,
+ int priority, unsigned long callbackval )
+{
+ return(FX_PlayVOC3D(ptr, pitchoffset, angle, distance, priority, callbackval));
+} // FX_PlayWAV3D
+
+// ROTT Special - SBF
+int FX_PlayWAV3D_ROTT( char *ptr, int size, int pitchoffset, int angle, int distance,
+ int priority, unsigned long callbackval )
+{
+ return(FX_PlayVOC3D_ROTT(ptr, size, pitchoffset, angle, distance, priority, callbackval));
+} // FX_PlayWAV3D_ROTT
+
+
+int FX_PlayRaw( char *ptr, unsigned long length, unsigned rate,
+ int pitchoffset, int vol, int left, int right, int priority,
+ unsigned long callbackval )
+{
+ setErrorMessage("FX_PlayRaw() ... NOT IMPLEMENTED!");
+ return(FX_Error);
+} // FX_PlayRaw
+
+
+int FX_PlayLoopedRaw( char *ptr, unsigned long length, char *loopstart,
+ char *loopend, unsigned rate, int pitchoffset, int vol, int left,
+ int right, int priority, unsigned long callbackval )
+{
+ setErrorMessage("FX_PlayLoopedRaw() ... NOT IMPLEMENTED!");
+ return(FX_Error);
+} // FX_PlayLoopedRaw
+
+
+int FX_Pan3D(int handle, int angle, int distance)
+{
+ int retval = FX_Warning;
+
+ handle -= HandleOffset;
+
+ if ((handle < 0) || (handle >= numChannels))
+ setWarningMessage("Invalid handle in FX_Pan3D().");
+ else if (!Mix_Playing(handle))
+ setWarningMessage("voice is no longer playing in FX_Pan3D().");
+ else
+ {
+ _FX_SetPosition(handle, angle, distance);
+
+ retval = FX_Ok;
+ } // else
+
+ return(retval);
+} // FX_Pan3D
+
+
+int FX_SoundActive(int handle)
+{
+ handle -= HandleOffset;
+
+ if (chaninfo == NULL)
+ return(__FX_FALSE);
+
+ if ((handle < 0) || (handle >= numChannels))
+ {
+ setWarningMessage("Invalid handle in FX_SoundActive().");
+ return(__FX_FALSE);
+ } // if
+
+ return(chaninfo[handle].in_use != 0);
+} // FX_SoundActive
+
+
+int FX_SoundsPlaying(void)
+{
+ return(Mix_Playing(-1));
+} // FX_SoundsPlaying
+
+
+int FX_StopSound(int handle)
+{
+ int retval = FX_Ok;
+
+ snddebug("explicitly halting channel (%d).", handle);
+ // !!! FIXME: Should the user callback fire for this?
+
+ handle -= HandleOffset;
+
+ if ((handle < 0) || (handle >= numChannels))
+ {
+ setWarningMessage("Invalid handle in FX_Pan3D().");
+ retval = FX_Warning;
+ } // if
+ else
+ {
+ Mix_HaltChannel(handle);
+ } // else
+
+ return(retval);
+} // FX_StopSound
+
+
+int FX_StopAllSounds(void)
+{
+ snddebug("halting all channels.");
+ // !!! FIXME: Should the user callback fire for this?
+ Mix_HaltGroup(-1);
+ return(FX_Ok);
+} // FX_StopAllSounds
+
+
+int FX_StartDemandFeedPlayback( void ( *function )( char **ptr, unsigned long *length ),
+ int rate, int pitchoffset, int vol, int left, int right,
+ int priority, unsigned long callbackval )
+{
+ setErrorMessage("FX_StartDemandFeedPlayback() ... NOT IMPLEMENTED!");
+ return(FX_Error);
+}
+
+
+int FX_StartRecording(int MixRate, void (*function)(char *ptr, int length))
+{
+ setErrorMessage("FX_StartRecording() ... NOT IMPLEMENTED!");
+ return(FX_Error);
+} // FX_StartRecording
+
+
+void FX_StopRecord( void )
+{
+ setErrorMessage("FX_StopRecord() ... NOT IMPLEMENTED!");
+} // FX_StopRecord
+
+
+
+// The music functions...
+
+
+char *MUSIC_ErrorString(int ErrorNumber)
+{
+ switch (ErrorNumber)
+ {
+ case MUSIC_Warning:
+ return(warningMessage);
+
+ case MUSIC_Error:
+ return(errorMessage);
+
+ case MUSIC_Ok:
+ return("OK; no error.");
+
+ case MUSIC_ASSVersion:
+ return("Incorrect sound library version.");
+
+ case MUSIC_SoundCardError:
+ return("General sound card error.");
+
+ case MUSIC_InvalidCard:
+ return("Invalid sound card.");
+
+ case MUSIC_MidiError:
+ return("MIDI error.");
+
+ case MUSIC_MPU401Error:
+ return("MPU401 error.");
+
+ case MUSIC_TaskManError:
+ return("Task Manager error.");
+
+ case MUSIC_FMNotDetected:
+ return("FM not detected error.");
+
+ case MUSIC_DPMI_Error:
+ return("DPMI error.");
+
+ default:
+ return("Unknown error.");
+ } // switch
+
+ assert(0); // shouldn't hit this point.
+ return(NULL);
+} // MUSIC_ErrorString
+
+
+static int music_initialized = 0;
+static int music_context = 0;
+static int music_loopflag = MUSIC_PlayOnce;
+static char *music_songdata = NULL;
+static Mix_Music *music_musicchunk = NULL;
+
+int MUSIC_Init(int SoundCard, int Address)
+{
+ init_debugging();
+
+ musdebug("INIT! card=>%d, address=>%d...", SoundCard, Address);
+
+ if (music_initialized)
+ {
+ setErrorMessage("Music system is already initialized.");
+ return(MUSIC_Error);
+ } // if
+
+ if (SoundCard != SoundScape) // We pretend there's a SoundScape installed.
+ {
+ setErrorMessage("Card not found.");
+ musdebug("We pretend to be an Ensoniq SoundScape only.");
+ return(MUSIC_Error);
+ } // if
+
+ music_initialized = 1;
+ return(MUSIC_Ok);
+} // MUSIC_Init
+
+
+int MUSIC_Shutdown(void)
+{
+ musdebug("shutting down sound subsystem.");
+
+ if (!music_initialized)
+ {
+ setErrorMessage("Music system is not currently initialized.");
+ return(MUSIC_Error);
+ } // if
+
+ MUSIC_StopSong();
+ music_context = 0;
+ music_initialized = 0;
+ music_loopflag = MUSIC_PlayOnce;
+
+ return(MUSIC_Ok);
+} // MUSIC_Shutdown
+
+
+void MUSIC_SetMaxFMMidiChannel(int channel)
+{
+ musdebug("STUB ... MUSIC_SetMaxFMMidiChannel(%d).\n", channel);
+} // MUSIC_SetMaxFMMidiChannel
+
+
+void MUSIC_SetVolume(int volume)
+{
+ Mix_VolumeMusic(volume >> 1); // convert 0-255 to 0-128.
+} // MUSIC_SetVolume
+
+
+void MUSIC_SetMidiChannelVolume(int channel, int volume)
+{
+ musdebug("STUB ... MUSIC_SetMidiChannelVolume(%d, %d).\n", channel, volume);
+} // MUSIC_SetMidiChannelVolume
+
+
+void MUSIC_ResetMidiChannelVolumes(void)
+{
+ musdebug("STUB ... MUSIC_ResetMidiChannelVolumes().\n");
+} // MUSIC_ResetMidiChannelVolumes
+
+
+int MUSIC_GetVolume(void)
+{
+ return(Mix_VolumeMusic(-1) << 1); // convert 0-128 to 0-255.
+} // MUSIC_GetVolume
+
+
+void MUSIC_SetLoopFlag(int loopflag)
+{
+ music_loopflag = loopflag;
+} // MUSIC_SetLoopFlag
+
+
+int MUSIC_SongPlaying(void)
+{
+ return((Mix_PlayingMusic()) ? __FX_TRUE : __FX_FALSE);
+} // MUSIC_SongPlaying
+
+
+void MUSIC_Continue(void)
+{
+ if (Mix_PausedMusic())
+ Mix_ResumeMusic();
+ else if (music_songdata)
+ MUSIC_PlaySong(music_songdata, MUSIC_PlayOnce);
+} // MUSIC_Continue
+
+
+void MUSIC_Pause(void)
+{
+ Mix_PauseMusic();
+} // MUSIC_Pause
+
+
+int MUSIC_StopSong(void)
+{
+ if (!fx_initialized)
+ {
+ setErrorMessage("Need FX system initialized, too. Sorry.");
+ return(MUSIC_Error);
+ } // if
+
+ if ( (Mix_PlayingMusic()) || (Mix_PausedMusic()) )
+ Mix_HaltMusic();
+
+ if (music_musicchunk)
+ Mix_FreeMusic(music_musicchunk);
+
+ music_songdata = NULL;
+ music_musicchunk = NULL;
+ return(MUSIC_Ok);
+} // MUSIC_StopSong
+
+
+int MUSIC_PlaySong(unsigned char *song, int loopflag)
+{
+ //SDL_RWops *rw;
+
+ MUSIC_StopSong();
+
+ music_songdata = song;
+
+ // !!! FIXME: This could be a problem...SDL/SDL_mixer wants a RWops, which
+ // !!! FIXME: is an i/o abstraction. Since we already have the MIDI data
+ // !!! FIXME: in memory, we fake it with a memory-based RWops. None of
+ // !!! FIXME: this is a problem, except the RWops wants to know how big
+ // !!! FIXME: its memory block is (so it can do things like seek on an
+ // !!! FIXME: offset from the end of the block), and since we don't have
+ // !!! FIXME: this information, we have to give it SOMETHING.
+
+ /* !!! ARGH! There's no LoadMUS_RW ?!
+ rw = SDL_RWFromMem((void *) song, (10 * 1024) * 1024); // yikes.
+ music_musicchunk = Mix_LoadMUS_RW(rw);
+ Mix_PlayMusic(music_musicchunk, (loopflag == MUSIC_PlayOnce) ? 0 : -1);
+ */
+
+ return(MUSIC_Ok);
+} // MUSIC_PlaySong
+
+// ROTT Special - SBF
+int MUSIC_PlaySongROTT(unsigned char *song, int size, int loopflag)
+{
+ char filename[MAX_PATH];
+ int handle;
+
+ MUSIC_StopSong();
+
+ // save the file somewhere, so SDL_mixer can load it
+ GetPathFromEnvironment(filename, ApogeePath, "tmpsong.mid");
+ handle = SafeOpenWrite(filename);
+
+ SafeWrite(handle, song, size);
+ close(handle);
+
+ music_songdata = song;
+
+ // finally, we can load it with SDL_mixer
+ music_musicchunk = Mix_LoadMUS(filename);
+ if (music_musicchunk == NULL) {
+ return MUSIC_Error;
+ }
+
+ Mix_PlayMusic(music_musicchunk, (loopflag == MUSIC_PlayOnce) ? 0 : -1);
+
+ return(MUSIC_Ok);
+} // MUSIC_PlaySongROTT
+
+void MUSIC_SetContext(int context)
+{
+ musdebug("STUB ... MUSIC_SetContext().\n");
+ music_context = context;
+} // MUSIC_SetContext
+
+
+int MUSIC_GetContext(void)
+{
+ return(music_context);
+} // MUSIC_GetContext
+
+
+void MUSIC_SetSongTick(unsigned long PositionInTicks)
+{
+ musdebug("STUB ... MUSIC_SetSongTick().\n");
+} // MUSIC_SetSongTick
+
+
+void MUSIC_SetSongTime(unsigned long milliseconds)
+{
+ musdebug("STUB ... MUSIC_SetSongTime().\n");
+}// MUSIC_SetSongTime
+
+
+void MUSIC_SetSongPosition(int measure, int beat, int tick)
+{
+ musdebug("STUB ... MUSIC_SetSongPosition().\n");
+} // MUSIC_SetSongPosition
+
+
+void MUSIC_GetSongPosition(songposition *pos)
+{
+ musdebug("STUB ... MUSIC_GetSongPosition().\n");
+} // MUSIC_GetSongPosition
+
+
+void MUSIC_GetSongLength(songposition *pos)
+{
+ musdebug("STUB ... MUSIC_GetSongLength().\n");
+} // MUSIC_GetSongLength
+
+
+int MUSIC_FadeVolume(int tovolume, int milliseconds)
+{
+ Mix_FadeOutMusic(milliseconds);
+ return(MUSIC_Ok);
+} // MUSIC_FadeVolume
+
+
+int MUSIC_FadeActive(void)
+{
+ return((Mix_FadingMusic() == MIX_FADING_OUT) ? __FX_TRUE : __FX_FALSE);
+} // MUSIC_FadeActive
+
+
+void MUSIC_StopFade(void)
+{
+ musdebug("STUB ... MUSIC_StopFade().\n");
+} // MUSIC_StopFade
+
+
+void MUSIC_RerouteMidiChannel(int channel, int cdecl function( int event, int c1, int c2 ))
+{
+ musdebug("STUB ... MUSIC_RerouteMidiChannel().\n");
+} // MUSIC_RerouteMidiChannel
+
+
+void MUSIC_RegisterTimbreBank(unsigned char *timbres)
+{
+ musdebug("STUB ... MUSIC_RegisterTimbreBank().\n");
+} // MUSIC_RegisterTimbreBank
+
+
+// end of fx_man.c ...
--- /dev/null
+++ b/rott/fx_man.h
@@ -1,0 +1,132 @@
+
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: FX_MAN.H
+
+ author: James R. Dose
+ date: March 17, 1994
+
+ Public header for FX_MAN.C
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __FX_MAN_H
+#define __FX_MAN_H
+
+#include "sndcards.h"
+
+typedef struct
+{
+ int MaxVoices;
+ int MaxSampleBits;
+ int MaxChannels;
+} fx_device;
+
+#define MonoFx 1
+#define StereoFx 2
+
+enum FX_ERRORS
+{
+ FX_Warning = -2,
+ FX_Error = -1,
+ FX_Ok = 0,
+ FX_ASSVersion,
+ FX_BlasterError,
+ FX_SoundCardError,
+ FX_InvalidCard,
+ FX_MultiVocError,
+ FX_DPMI_Error
+};
+
+#ifdef DOS
+enum fx_BLASTER_Types
+{
+ fx_SB = 1,
+ fx_SBPro = 2,
+ fx_SB20 = 3,
+ fx_SBPro2 = 4,
+ fx_SB16 = 6
+};
+#endif
+
+
+char *FX_ErrorString( int ErrorNumber );
+int FX_SetupCard( int SoundCard, fx_device *device );
+int FX_Init( int SoundCard, int numvoices, int numchannels, int samplebits, unsigned mixrate );
+int FX_Shutdown( void );
+int FX_SetCallBack( void ( *function )( unsigned long ) );
+void FX_SetVolume( int volume );
+int FX_GetVolume( void );
+
+void FX_SetReverseStereo( int setting );
+int FX_GetReverseStereo( void );
+void FX_SetReverb( int reverb );
+void FX_SetFastReverb( int reverb );
+int FX_GetMaxReverbDelay( void );
+int FX_GetReverbDelay( void );
+void FX_SetReverbDelay( int delay );
+
+int FX_VoiceAvailable( int priority );
+int FX_EndLooping( int handle );
+int FX_SetPan( int handle, int vol, int left, int right );
+int FX_SetPitch( int handle, int pitchoffset );
+int FX_SetFrequency( int handle, int frequency );
+
+int FX_PlayVOC( char *ptr, int pitchoffset, int vol, int left, int right,
+ int priority, unsigned long callbackval );
+int FX_PlayLoopedVOC( char *ptr, long loopstart, long loopend,
+ int pitchoffset, int vol, int left, int right, int priority,
+ unsigned long callbackval );
+int FX_PlayWAV( char *ptr, int pitchoffset, int vol, int left, int right,
+ int priority, unsigned long callbackval );
+int FX_PlayLoopedWAV( char *ptr, long loopstart, long loopend,
+ int pitchoffset, int vol, int left, int right, int priority,
+ unsigned long callbackval );
+int FX_PlayVOC3D( char *ptr, int pitchoffset, int angle, int distance,
+ int priority, unsigned long callbackval );
+int FX_PlayWAV3D( char *ptr, int pitchoffset, int angle, int distance,
+ int priority, unsigned long callbackval );
+int FX_PlayRaw( char *ptr, unsigned long length, unsigned rate,
+ int pitchoffset, int vol, int left, int right, int priority,
+ unsigned long callbackval );
+int FX_PlayLoopedRaw( char *ptr, unsigned long length, char *loopstart,
+ char *loopend, unsigned rate, int pitchoffset, int vol, int left,
+ int right, int priority, unsigned long callbackval );
+int FX_Pan3D( int handle, int angle, int distance );
+int FX_SoundActive( int handle );
+int FX_SoundsPlaying( void );
+int FX_StopSound( int handle );
+int FX_StopAllSounds( void );
+int FX_StartDemandFeedPlayback( void ( *function )( char **ptr, unsigned long *length ),
+ int rate, int pitchoffset, int vol, int left, int right,
+ int priority, unsigned long callbackval );
+int FX_StartRecording( int MixRate, void ( *function )( char *ptr, int length ) );
+void FX_StopRecord( void );
+
+// ROTT Special - SBF
+int FX_PlayVOC3D_ROTT( char *ptr, int size, int pitchoffset, int angle, int distance,
+ int priority, unsigned long callbackval );
+int FX_PlayWAV3D_ROTT( char *ptr, int size, int pitchoffset, int angle, int distance,
+ int priority, unsigned long callbackval );
+// End ROTT hacks
+
+#endif
--- /dev/null
+++ b/rott/gmove.h
@@ -1,0 +1,25 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _gmove
+#define _gmove
+
+#define GMOVE 8
+
+#endif
--- /dev/null
+++ b/rott/isr.c
@@ -1,0 +1,842 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+
+
+/*
+============================================================================
+
+ TIMER INTERRUPT
+
+============================================================================
+*/
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef DOS
+#include <dos.h>
+#include <mem.h>
+#include <conio.h>
+#endif
+
+#include "rt_def.h"
+#include "task_man.h"
+#include "isr.h"
+#include "_isr.h"
+#include "rt_in.h"
+#include "rt_util.h"
+#include "profile.h"
+#include "develop.h"
+#include "rt_main.h"
+
+#if (DEVELOPMENT == 1)
+
+#include "rt_vid.h"
+
+#endif
+//MED
+#include "memcheck.h"
+
+// Global Variables
+
+static volatile boolean ExtendedKeyFlag;
+
+volatile int Keyboard[MAXKEYBOARDSCAN];
+volatile int KeyboardQueue[KEYQMAX];
+volatile int Keystate[MAXKEYBOARDSCAN];
+volatile int Keyhead;
+volatile int Keytail;
+
+#ifdef DOS
+volatile int ticcount;
+volatile int fasttics;
+#endif
+
+volatile boolean PausePressed = false;
+volatile boolean PanicPressed = false;
+int KeyboardStarted=false;
+
+const int ASCIINames[] = // Unshifted ASCII for scan codes
+{
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0,27,'1','2','3','4','5','6','7','8','9','0','-','=',8,9, // 0
+ 'q','w','e','r','t','y','u','i','o','p','[',']',13,0,'a','s', // 1
+ 'd','f','g','h','j','k','l',';',39,'`',0,92,'z','x','c','v', // 2
+ 'b','n','m',',','.','/',0,'*',0,' ',0,0,0,0,0,0, // 3
+ 0,0,0,0,0,0,0,'7','8','9','-','4','5','6','+','1', // 4
+ '2','3','0',127,0,0,0,0,0,0,0,0,0,0,0,0, // 5
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 6
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // 7
+};
+
+const int ShiftNames[] = // Shifted ASCII for scan codes
+{
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0,27,'!','@','#','$','%','^','&','*','(',')','_','+',8,9, // 0
+ 'Q','W','E','R','T','Y','U','I','O','P','{','}',13,0,'A','S', // 1
+ 'D','F','G','H','J','K','L',':',34,'~',0,'|','Z','X','C','V', // 2
+ 'B','N','M','<','>','?',0,'*',0,' ',0,0,0,0,0,0, // 3
+ 0,0,0,0,0,0,0,'7','8','9','-','4','5','6','+','1', // 4
+ '2','3','0',127,0,0,0,0,0,0,0,0,0,0,0,0, // 5
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 6
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // 7
+};
+
+#ifdef DOS
+
+// Local Variables
+
+static task * timertask;
+#if (DEVELOPMENT == 1)
+static task * fasttimertask;
+#endif
+static int TimerStarted=false;
+static volatile int pausecount=0;
+static struct dostime_t starttime;
+
+void (__interrupt __far *oldtimerisr) ();
+void (__interrupt __far *oldkeyboardisr) () = NULL;
+
+static int LEDs;
+static volatile int KBFlags;
+
+/*
+================
+=
+= I_TimerISR
+=
+================
+*/
+
+void __interrupt I_TimerISR (void)
+{
+// acknowledge the interrupt
+
+ OUTP(0x20,0x20);
+ ticcount++;
+}
+
+/*
+================
+=
+= ISR_Timer
+=
+================
+*/
+#if 0
+#if (DEVELOPMENT == 1)
+static int time=0;
+static int t1=0;
+static int t2=0;
+static int t3=0;
+static int insettime=0;
+#endif
+#endif
+/*
+================
+=
+= ISR_SetTime
+=
+================
+*/
+void ISR_SetTime(int settime)
+{
+#if 0
+#if (DEVELOPMENT == 1)
+ int i;
+ int t;
+ int savetime;
+#endif
+#endif
+
+ ticcount=settime;
+#if 0
+#if (DEVELOPMENT == 1)
+ {
+ insettime=1;
+ savetime=time;
+ t1=0;
+ t2=0;
+ t3=0;
+ t=0;
+
+ for (i=0; i<settime; i++)
+ {
+ t++;
+ if (t==VBLCOUNTER)
+ {
+ t=0;
+ t1++;
+ if (t1==2)
+ {
+ t1=0;
+ t2++;
+ if (t2==2)
+ {
+ t2=0;
+ t3++;
+ if (t3==2)
+ t3=0;
+ }
+ }
+ }
+ }
+ time=t+(time-savetime);
+ if (time>=VBLCOUNTER)
+ {
+ time-=VBLCOUNTER;
+ t1++;
+ if (t1==2)
+ {
+ t1=0;
+ t2++;
+ if (t2==2)
+ {
+ t2=0;
+ t3++;
+ if (t3==2)
+ t3=0;
+ }
+ }
+ }
+ insettime=0;
+ }
+#endif
+#endif
+}
+
+static void ISR_Timer (task *Task)
+{
+// (*(int *)(Task->data))=((*(int *)(Task->data))+1)&0xffff;
+ (*(int *)(Task->data))++;
+
+#if 0
+#if (DEVELOPMENT == 1)
+ {
+ if (Task==timertask)
+ {
+ time++;
+ if ((time==VBLCOUNTER) && (insettime==0))
+ {
+ time=0;
+ VL_SetColor(0,(t1<<5)+20,(t2<<5)+20,(t3<<5)+20);
+ t1++;
+ if (t1==2)
+ {
+ t1=0;
+ t2++;
+ if (t2==2)
+ {
+ t2=0;
+ t3++;
+ if (t3==2)
+ t3=0;
+ }
+ }
+ }
+ }
+ }
+#endif
+#endif
+}
+
+
+/*
+=====================
+=
+= I_SetTimer0
+=
+= Sets system timer 0 to the specified speed
+=
+=====================
+*/
+
+void I_SetTimer0(int speed)
+{
+ unsigned s;
+ if (!((speed > 0 && speed < 150)))
+ Error ("INT_SetTimer0: %i is a bad value",speed);
+ s=1192030U/(unsigned)speed;
+ OUTP(0x43,0x36); // Change timer 0
+ OUTP(0x40,s);
+ OUTP(0x40,s >> 8);
+}
+
+/*
+================
+=
+= I_Delay
+=
+================
+*/
+
+void I_Delay ( int delay )
+{
+ int time;
+
+ delay=(VBLCOUNTER*delay)/10;
+ IN_ClearKeysDown();
+ time=ticcount;
+ while (ticcount<time+delay)
+ {
+ if (LastScan)
+ break;
+ }
+}
+
+/*
+===============
+=
+= I_StartupTimer
+=
+===============
+*/
+
+void I_StartupTimer (void)
+{
+#if PROFILE
+ return;
+#else
+ struct dostime_t cmostime;
+
+ if (TimerStarted==true)
+ return;
+ TimerStarted=true;
+
+ I_GetCMOSTime ( &cmostime );
+ _dos_settime ( &cmostime );
+
+// I_SetTimer0(VBLCOUNTER);
+// oldtimerisr = _dos_getvect(TIMERINT);
+// _dos_setvect (TIMERINT, I_TimerISR);
+
+ timertask=TS_ScheduleTask( &ISR_Timer, VBLCOUNTER, 10, &ticcount);
+#if (DEVELOPMENT == 1)
+ fasttimertask=TS_ScheduleTask( &ISR_Timer, VBLCOUNTER*4, 10, &fasttics);
+#endif
+ TS_Dispatch();
+ I_GetCMOSTime ( &cmostime );
+ memcpy(&starttime,&cmostime,sizeof(starttime));
+ ticcount=0;
+ if (!quiet)
+ printf("I_StartupTimer: Timer Started\n");
+#endif
+}
+
+void I_ShutdownTimer (void)
+{
+#if PROFILE
+ return;
+#else
+ struct dostime_t dostime;
+ struct dostime_t cmostime;
+#if (DEVELOPMENT == 1)
+ int totaltime;
+#endif
+
+ if (TimerStarted==false)
+ return;
+ TimerStarted=false;
+
+// OUTP(0x43,0x36); // Change timer 0
+// OUTP(0x40,0);
+// OUTP(0x40,0);
+// _dos_setvect (TIMERINT, oldtimerisr);
+
+ I_GetCMOSTime ( &cmostime );
+ _dos_gettime ( &dostime );
+
+#if (DEVELOPMENT == 1)
+ SoftError("Time difference in seconds (DOS-CMOS) %ld\n",dostime.second-cmostime.second);
+ SoftError("Time difference in minutes (DOS-CMOS) %ld\n",dostime.minute-cmostime.minute);
+ SoftError("Time difference in hour (DOS-CMOS) %ld\n",dostime.hour-cmostime.hour);
+ totaltime=( ((cmostime.hour-starttime.hour)*3600) +
+ ((cmostime.minute-starttime.minute)*60) +
+ (cmostime.second-starttime.second)
+ );
+ SoftError("Total seconds = %ld Total Tics = %ld Game Tics = %ld\n",totaltime,totaltime*VBLCOUNTER,ticcount);
+#endif
+
+ TS_Terminate( timertask );
+#if (DEVELOPMENT == 1)
+ TS_Terminate( fasttimertask );
+#endif
+ TS_Shutdown();
+// TS_Halt();
+ /*
+ if (oldtimerisr)
+ {
+ OUTP(0x43,0x36); // Change timer 0
+ OUTP(0x40,0);
+ OUTP(0x40,0);
+ _dos_setvect (TIMERINT, oldtimerisr);
+ // Set Date and Time from CMOS
+
+ OUTP(0x70,0);
+ time.second=inp(0x71);
+ OUTP(0x70,2);
+ time.minute=inp(0x71);
+ OUTP(0x70,4);
+ time.hour=inp(0x71);
+ time.second=(time.second&0x0f)+((time.second>>4)*10);
+ time.minute=(time.minute&0x0f)+((time.minute>>4)*10);
+ time.hour=(time.hour&0x0f)+((time.hour>>4)*10);
+ _dos_settime(&time);
+
+ OUTP(0x70,7);
+ date.day=inp(0x71);
+ OUTP(0x70,8);
+ date.month=inp(0x71);
+ OUTP(0x70,9);
+ date.year=inp(0x71);
+ date.day=(date.day&0x0f)+((date.day>>4)*10);
+ date.month=(date.month&0x0f)+((date.month>>4)*10);
+ date.year=(date.year&0x0f)+((date.year>>4)*10);
+ _dos_setdate(&date);
+ // }
+ */
+#endif
+}
+
+/*
+===============
+=
+= I_GetCMOSTime
+=
+===============
+*/
+void I_GetCMOSTime ( struct dostime_t * cmostime )
+{
+ OUTP(0x70,0);
+ cmostime->second=inp(0x71);
+ OUTP(0x70,2);
+ cmostime->minute=inp(0x71);
+ OUTP(0x70,4);
+ cmostime->hour=inp(0x71);
+ cmostime->second=(cmostime->second&0x0f)+((cmostime->second>>4)*10);
+ cmostime->minute=(cmostime->minute&0x0f)+((cmostime->minute>>4)*10);
+ cmostime->hour=(cmostime->hour&0x0f)+((cmostime->hour>>4)*10);
+}
+
+/*
+============================================================================
+
+ KEYBOARD
+
+============================================================================
+*/
+#define ena_kbd 0xae
+#define caps_state 0x40
+#define num_state 0x20
+#define scroll_state 0x10
+
+#define kb_resend 0xfe
+#define kb_ack 0xfa
+#define kb_pr_led 0x40
+#define kb_error 0x80
+#define kb_fe 0x20
+#define kb_fa 0x10
+
+#define porta 0x60
+#define kb_status_port 0x64
+#define input_buffer_full 0x02
+#define led_cmd 0xed
+#define kb_enable 0xf4
+#define leds_off 0
+#define caps_led_on 0x04
+#define num_led_on 0x02
+#define scroll_led_on 0x01
+
+/*
+================
+=
+= I_SendKeyboardData
+=
+================
+*/
+
+void I_SendKeyboardData
+(
+ int val
+)
+
+{
+ int retry;
+ volatile int count;
+
+ _disable();
+
+ KBFlags &= ~( kb_fe | kb_fa );
+
+ count = 0xffff;
+ while( count-- )
+ {
+ if ( !( inp( kb_status_port ) & input_buffer_full ) )
+ {
+ break;
+ }
+ }
+
+ outp( porta, val );
+
+ _enable();
+
+ retry = 3;
+ while( retry-- )
+ {
+ count = 0x1a00;
+ while( count-- )
+ {
+ if ( KBFlags & kb_fe )
+ {
+ break;
+ }
+
+ if ( KBFlags & kb_fa )
+ {
+ return;
+ }
+ }
+ }
+
+ KBFlags |= kb_error;
+}
+
+/*
+================
+=
+= I_SetKeyboardLEDs
+=
+================
+*/
+
+void I_SetKeyboardLEDs
+(
+ int which,
+ boolean val
+)
+
+{
+ int mask;
+ int count;
+
+ _disable();
+ KBFlags |= kb_pr_led;
+
+ switch( which )
+ {
+ case scroll_lock :
+ mask = scroll_led_on;
+ break;
+
+ case num_lock :
+ mask = num_led_on;
+ break;
+
+ case caps_lock :
+ mask = caps_led_on;
+ break;
+
+ default :
+ mask = 0;
+ break;
+ }
+
+ if ( val )
+ {
+ LEDs |= mask;
+ }
+ else
+ {
+ LEDs &= ~mask;
+ }
+
+ count = 0;
+ do
+ {
+ if ( count > 3 )
+ {
+ break;
+ }
+
+ I_SendKeyboardData( led_cmd );
+ _disable();
+ I_SendKeyboardData( LEDs );
+ _disable();
+ I_SendKeyboardData( kb_enable );
+ _disable();
+ count++;
+ }
+ while( KBFlags & kb_error );
+
+ _enable();
+ KBFlags &= ~(kb_pr_led|kb_error);
+}
+
+
+/*
+================
+=
+= I_KeyboardISR
+=
+================
+*/
+void __interrupt I_KeyboardISR (void)
+{
+ int k;
+ int temp;
+ int keyon;
+ int strippedkey;
+
+ // Get the scan code
+ k = inp( 0x60 );
+
+ // Tell the XT keyboard controller to clear the key
+ temp = inp( 0x61 );
+ OUTP ( 0x61, temp | 0x80 );
+ OUTP ( 0x61, temp );
+
+ if ( KBFlags & kb_pr_led )
+ {
+ if ( k == kb_resend )
+ {
+ // Handle resend
+ KBFlags |= kb_fe;
+ }
+ else if (k == kb_ack)
+ {
+ // Handle ack
+ KBFlags |= kb_fa;
+ }
+ }
+ else if ( pausecount )
+ {
+ pausecount--;
+ }
+ else if ( k == 0xe1 ) // Handle Pause key
+ {
+ PausePressed = true;
+ pausecount = 5;
+ }
+ else if ( k == 0x46 ) // Handle Panic key (Scroll Lock)
+ {
+ PanicPressed = true;
+ }
+ else
+ {
+ if ( k == 0xE0 )
+ {
+ ExtendedKeyFlag = true;
+ }
+ else
+ {
+ keyon = k & 0x80;
+ strippedkey = k & 0x7f;
+
+ if ( ExtendedKeyFlag )
+ {
+ if ( ( strippedkey == sc_LShift ) ||
+ ( strippedkey == sc_RShift ) )
+ {
+ k = sc_None;
+ }
+ /*
+ else
+ {
+ if ( strippedkey == sc_Alt )
+ {
+ k = sc_RightAlt | keyon;
+ }
+ if ( strippedkey == sc_Control )
+ {
+ k = sc_RightCtrl | keyon;
+ }
+ }
+ */
+ }
+
+ if ( k != sc_None )
+ {
+ if ( strippedkey == sc_LShift )
+ {
+ k = sc_RShift | keyon;
+ }
+
+ if ( !keyon )
+ {
+ LastScan = k;
+ }
+
+ if (k & 0x80) // Up event
+ {
+ Keystate[k&0x7f]=0;
+ }
+ else // Down event
+ {
+ Keystate[k]=1;
+ }
+
+ KeyboardQueue[ Keytail ] = k;
+ Keytail = ( Keytail + 1 )&( KEYQMAX - 1 );
+ }
+
+ ExtendedKeyFlag = false;
+ }
+ }
+
+ // acknowledge the interrupt
+ OUTP ( 0x20, 0x20 );
+}
+
+
+/*
+===============
+=
+= I_StartupKeyboard
+=
+===============
+*/
+
+void I_StartupKeyboard (void)
+{
+ if (KeyboardStarted==true)
+ return;
+ KeyboardStarted=true;
+
+ LEDs = 0;
+ KBFlags = 0;
+ ExtendedKeyFlag = false;
+
+ oldkeyboardisr = _dos_getvect(KEYBOARDINT);
+ _dos_setvect (0x8000 | KEYBOARDINT, I_KeyboardISR);
+
+// I_SetKeyboardLEDs( scroll_lock, 0 );
+
+ Keyhead = Keytail = 0;
+ memset(Keystate,0,sizeof(Keystate));
+ if (!quiet)
+ printf("I_StartupKeyboard: Keyboard Started\n");
+}
+
+void I_ShutdownKeyboard (void)
+{
+ if (KeyboardStarted==false)
+ return;
+ KeyboardStarted=false;
+
+ // Clear LEDS
+// *( (byte *)0x417 ) &= ~0x70;
+
+ _dos_setvect (KEYBOARDINT, oldkeyboardisr);
+ *(short *)0x41c = *(short *)0x41a; // clear bios key buffer
+}
+#else
+
+#include "SDL.h"
+
+static int ticoffset; /* offset for SDL_GetTicks() */
+static int ticbase; /* game-supplied base */
+
+int GetTicCount (void)
+{
+ return ((SDL_GetTicks() - ticoffset) * VBLCOUNTER) / 1000 + ticbase;
+}
+
+/*
+================
+=
+= ISR_SetTime
+=
+================
+*/
+void ISR_SetTime(int settime)
+{
+ ticoffset = SDL_GetTicks();
+ ticbase = settime;
+}
+
+/* developer-only */
+
+int GetFastTics (void)
+{
+ /* STUB_FUNCTION; */
+
+ return 0;
+}
+
+void SetFastTics (int settime)
+{
+ /* STUB_FUNCTION; */
+}
+
+/*
+================
+=
+= I_Delay
+=
+================
+*/
+
+void I_Delay ( int delay )
+{
+ int time;
+
+ delay=(VBLCOUNTER*delay)/10;
+ IN_ClearKeysDown();
+ time=GetTicCount();
+ while (!LastScan && !IN_GetMouseButtons() && GetTicCount()<time+delay)
+ {
+ IN_UpdateKeyboard();
+ }
+}
+
+/*
+===============
+=
+= I_StartupTimer
+=
+===============
+*/
+
+void I_StartupTimer (void)
+{
+}
+
+void I_ShutdownTimer (void)
+{
+}
+
+/*
+===============
+=
+= I_StartupKeyboard
+=
+===============
+*/
+
+void I_StartupKeyboard (void)
+{
+}
+
+
+void I_ShutdownKeyboard (void)
+{
+}
+#endif
--- /dev/null
+++ b/rott/isr.h
@@ -1,0 +1,89 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _isr_public
+#define _isr_public
+
+#include "keyb.h"
+
+//***************************************************************************
+//
+// ISR.C - Interrupt Service Routines (Keyboard, timer)
+//
+//***************************************************************************
+
+//***************************************************************************
+//
+// ISR Constants
+//
+//***************************************************************************
+
+#define VBLCOUNTER 35
+
+
+#define KEYQMAX 256
+#define MAXKEYBOARDSCAN 128
+
+#define scroll_lock 0
+#define num_lock 1
+#define caps_lock 2
+
+extern volatile int KeyboardQueue[KEYQMAX];
+extern volatile int Keyhead;
+extern volatile int Keytail;
+
+extern volatile int Keyboard[MAXKEYBOARDSCAN]; // Keyboard status array
+extern volatile int Keystate[MAXKEYBOARDSCAN]; // Keyboard state array
+
+#ifdef DOS
+extern volatile int ticcount; // Current ticcount (usually 70Hz)
+extern volatile int fasttics;
+
+#define GetTicCount() ticcount
+#define GetFastTics() fasttics
+
+#define SetFastTics(a) {fasttics=a;}
+#else
+int GetTicCount (void);
+int GetFastTics (void);
+
+void SetFastTics(int);
+#endif
+
+extern int KeyboardStarted;
+
+extern const int ASCIINames[]; // Ascii -> scan code conversion
+extern const int ShiftNames[]; // Shifted Ascii->scancode conversion
+extern volatile boolean PausePressed; //Game paused variable
+extern volatile boolean PanicPressed; //Panic key variable
+
+void I_StartupTimer (void); // Start up timer isr
+void I_SetTimer0(int speed); // Set the timer to a given speed
+void I_ShutdownTimer (void); // Shutdown timer isr
+void I_SetKeyboardLEDs( int which, boolean val ); // Turns LED's on or off
+void I_StartupKeyboard (void); // Startup Keyboard isr
+void I_ShutdownKeyboard (void); // Shutdown keyboard isr
+void I_Delay ( int delay );
+void ISR_SetTime(int settime);
+void I_SendKeyboardData
+(
+ int val
+);
+
+#endif
--- /dev/null
+++ b/rott/keyb.h
@@ -1,0 +1,106 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _keyb
+#define _keyb
+
+#define sc_None 0
+#define sc_Bad 0xff
+#define sc_Comma 0x33
+#define sc_Period 0x34
+#define sc_Return 0x1c
+#define sc_Enter sc_Return
+#define sc_Escape 0x01
+#define sc_Space 0x39
+#define sc_BackSpace 0x0e
+#define sc_Tab 0x0f
+#define sc_Alt 0x38
+#define sc_Control 0x1d
+#define sc_CapsLock 0x3a
+#define sc_LShift 0x2a
+#define sc_RShift 0x36
+#define sc_UpArrow 0x48
+#define sc_DownArrow 0x50
+#define sc_LeftArrow 0x4b
+#define sc_RightArrow 0x4d
+#define sc_Insert 0x52
+#define sc_Delete 0x53
+#define sc_Home 0x47
+#define sc_End 0x4f
+#define sc_PgUp 0x49
+#define sc_PgDn 0x51
+#define sc_F1 0x3b
+#define sc_F2 0x3c
+#define sc_F3 0x3d
+#define sc_F4 0x3e
+#define sc_F5 0x3f
+#define sc_F6 0x40
+#define sc_F7 0x41
+#define sc_F8 0x42
+#define sc_F9 0x43
+#define sc_F10 0x44
+#define sc_F11 0x57
+#define sc_F12 0x58
+#define sc_PrintScreen 0x37
+
+#define sc_OpenBracket 0x1a
+#define sc_CloseBracket 0x1b
+
+#define sc_1 0x02
+#define sc_2 0x03
+#define sc_3 0x04
+#define sc_4 0x05
+#define sc_5 0x06
+#define sc_6 0x07
+#define sc_7 0x08
+#define sc_8 0x09
+#define sc_9 0x0a
+#define sc_0 0x0b
+#define sc_Minus 0x0c
+#define sc_Equals 0x0d
+#define sc_Plus 0x0d
+
+#define sc_A 0x1e
+#define sc_B 0x30
+#define sc_C 0x2e
+#define sc_D 0x20
+#define sc_E 0x12
+#define sc_F 0x21
+#define sc_G 0x22
+#define sc_H 0x23
+#define sc_I 0x17
+#define sc_J 0x24
+#define sc_K 0x25
+#define sc_L 0x26
+#define sc_M 0x32
+#define sc_N 0x31
+#define sc_O 0x18
+#define sc_P 0x19
+#define sc_Q 0x10
+#define sc_R 0x13
+#define sc_S 0x1f
+#define sc_T 0x14
+#define sc_U 0x16
+#define sc_V 0x2f
+#define sc_W 0x11
+#define sc_X 0x2d
+#define sc_Y 0x15
+#define sc_Z 0x2c
+
+#endif
--- /dev/null
+++ b/rott/lookups.c
@@ -1,0 +1,223 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "rt_def.h"
+#include "rt_util.h"
+#include "rt_view.h"
+#include <math.h>
+#include <dos.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <conio.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <io.h>
+#include <stdlib.h>
+#include <sys\stat.h>
+
+//MED
+#include "memcheck.h"
+
+#define PANGLES 512
+#define NUMSINANGLES FINEANGLES+FINEANGLEQUAD+1
+
+fixed pangle[PANGLES];
+long sintable[NUMSINANGLES];
+short tantable[FINEANGLES];
+byte gammatable[GAMMAENTRIES];
+
+extern int _argc;
+extern char ** _argv;
+
+/*
+=================
+=
+= Error
+=
+= For abnormal program terminations
+=
+=================
+*/
+
+void Error (char *error, ...)
+{
+ va_list argptr;
+
+ va_start (argptr,error);
+ vprintf (error,argptr);
+ va_end (argptr);
+ printf ("\n");
+ exit (1);
+}
+
+
+int SafeOpenWrite (char *_filename)
+{
+ int handle;
+ char filename[MAX_PATH];
+ strncpy(filename, _filename, sizeof (filename));
+ filename[sizeof (filename) - 1] = '\0';
+ FixFilePath(filename);
+
+ handle = open(filename,O_RDWR | O_BINARY | O_CREAT | O_TRUNC
+ , S_IREAD | S_IWRITE);
+
+ if (handle == -1)
+ Error ("Error opening %s: %s",filename,strerror(errno));
+
+ return handle;
+}
+
+
+void SafeWrite (int handle, void *buffer, long count)
+{
+ unsigned iocount;
+
+ while (count)
+ {
+ iocount = count > 0x8000 ? 0x8000 : count;
+ if (write (handle,buffer,iocount) != iocount)
+ Error ("File write failure");
+ buffer = (void *)( (byte *)buffer + iocount );
+ count -= iocount;
+ }
+}
+
+
+
+
+void CalcPixelAngles ( void )
+{
+ int i;
+ long intang;
+ double angle;
+ double tang;
+
+ const double radtoint = (double)FINEANGLES/2/PI;
+
+
+ for (i=0; i<PANGLES; i++)
+ {
+ // start 1/2 pixel over, so viewangle bisects two middle pixels
+ //tang = ((((double)i*160.0)+80.0)/(FPFOCALWIDTH*(double)PANGLES));
+ tang = ((((double)i*160.0)+80.0)/(dGLOBAL_FPFOCALWIDTH*(double)PANGLES));
+ angle = atan(tang);
+ intang = ((long)(angle*radtoint));
+ pangle[i] = intang;
+ }
+}
+
+
+
+void BuildSinTable (void)
+{
+ int i;
+ double angle,anglestep;
+ double sinangle;
+ fixed value;
+
+ angle = 0;
+ anglestep = (double)(PI/2/FINEANGLEQUAD);
+ for (i=0; i<=FINEANGLEQUAD; i++)
+ {
+ sinangle=sin(angle);
+ value=(fixed)((double)GLOBAL1*sinangle);
+ sintable[i] =
+ sintable[i+FINEANGLES] =
+ sintable[FINEANGLES/2-i] = value;
+ sintable[FINEANGLES-i] = -value;
+ sintable[FINEANGLES/2+i] = -value;
+ angle += anglestep;
+ }
+}
+
+void BuildTanTable (void)
+{
+ int i;
+ double angle,anglestep;
+ double tanangle;
+ fixed value;
+
+ angle = 0;
+ anglestep = (double)(PI*2/FINEANGLES);
+ for (i=0; i<FINEANGLES; i++)
+ {
+ tanangle=tan(angle);
+ value=(fixed)((double)GLOBAL1*tanangle);
+ tantable[i] =(short) (value>>1);
+ angle += anglestep;
+ }
+}
+
+void BuildGammaTable (void)
+{
+ int l, i, inf;
+ int j;
+ int gGamma=0x100;
+ j=0;
+ for (l=0 ; l<NUMGAMMALEVELS ; l++,gGamma+=32)
+ {
+ double nGamma = (double)256 / gGamma;
+ double nScale = (double)63 / pow(63, nGamma);
+
+ for ( i = 0; i < 64; i++ )
+ {
+ inf = pow(i, nGamma) * nScale;
+ if (inf < 0)
+ inf = 0;
+ if (inf > 63)
+ inf = 63;
+ gammatable[j++]=inf;
+ }
+ }
+}
+
+void main ()
+{
+ int handle;
+ int size;
+
+ if (_argc!=2)
+ {
+ printf("LOOKUPS -- Apogee Software (c) 1994\n");
+ printf("\n USAGE: lookups <name.dat>\n");
+ exit(0);
+ }
+ handle=SafeOpenWrite (_argv[1]);
+ CalcPixelAngles();
+ BuildSinTable();
+ BuildTanTable();
+ BuildGammaTable();
+ size=PANGLES;
+ SafeWrite(handle,&size,sizeof(int));
+ SafeWrite(handle,&pangle[0],sizeof(fixed)*size);
+ size=NUMSINANGLES;
+ SafeWrite(handle,&size,sizeof(int));
+ SafeWrite(handle,&sintable[0],sizeof(fixed)*size);
+ size=FINEANGLES;
+ SafeWrite(handle,&size,sizeof(int));
+ SafeWrite(handle,&tantable[0],sizeof(short)*size);
+ size=GAMMAENTRIES;
+ SafeWrite(handle,&size,sizeof(int));
+ SafeWrite(handle,&gammatable[0],sizeof(byte)*size);
+ close (handle);
+}
--- /dev/null
+++ b/rott/lumpy.h
@@ -1,0 +1,151 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _lumpy_
+#define _lumpy_
+
+//****************************************************************************
+//
+// Public header for LUMPY typedefs
+//
+//****************************************************************************
+
+
+typedef struct
+{
+ byte width,height;
+ byte data;
+} pic_t;
+
+#define CONVERT_ENDIAN_pic_t(pp) { }
+
+typedef struct
+{
+ short width,height;
+ short orgx,orgy;
+ byte data;
+} lpic_t;
+
+#define CONVERT_ENDIAN_lpic_t(lp) \
+ { \
+ SwapIntelShort(&lp->width); \
+ SwapIntelShort(&lp->height); \
+ SwapIntelShort(&lp->orgx); \
+ SwapIntelShort(&lp->orgy); \
+ }
+
+typedef struct
+{
+ short height;
+ char width[256];
+ short charofs[256];
+ byte data; // as much as required
+} font_t;
+
+#define CONVERT_ENDIAN_font_t(fp) \
+ { \
+ int i; \
+ SwapIntelShort(&fp->height); \
+ for (i = 0; i < 256; i++) { \
+ SwapIntelShort(&fp->charofs[i]); \
+ } \
+ }
+
+typedef struct
+{
+ short width;
+ short height;
+ byte palette[768];
+ byte data;
+} lbm_t;
+
+#define CONVERT_ENDIAN_lbm_t(lp) \
+ { \
+ SwapIntelShort(&lp->width); \
+ SwapIntelShort(&lp->height); \
+ }
+
+typedef struct
+{
+ short origsize; // the orig size of "grabbed" gfx
+ short width; // bounding box size
+ short height;
+ short leftoffset; // pixels to the left of origin
+ short topoffset; // pixels above the origin
+ unsigned short collumnofs[320]; // only [width] used, the [0] is &collumnofs[width]
+} patch_t;
+
+#define CONVERT_ENDIAN_patch_t(pp) \
+ { \
+ int i; \
+ SwapIntelShort(&pp->origsize); \
+ SwapIntelShort(&pp->width); \
+ SwapIntelShort(&pp->height); \
+ SwapIntelShort(&pp->leftoffset); \
+ SwapIntelShort(&pp->topoffset); \
+ for (i = 0; i < pp->width; i++) { \
+ SwapIntelShort((short*)&pp->collumnofs[i]); \
+ } \
+ }
+
+typedef struct
+{
+ short origsize; // the orig size of "grabbed" gfx
+ short width; // bounding box size
+ short height;
+ short leftoffset; // pixels to the left of origin
+ short topoffset; // pixels above the origin
+ short translevel;
+ short collumnofs[320]; // only [width] used, the [0] is &collumnofs[width]
+} transpatch_t;
+
+#define CONVERT_ENDIAN_transpatch_t(pp) \
+ { \
+ int i; \
+ SwapIntelShort(&pp->origsize); \
+ SwapIntelShort(&pp->width); \
+ SwapIntelShort(&pp->height); \
+ SwapIntelShort(&pp->leftoffset); \
+ SwapIntelShort(&pp->topoffset); \
+ SwapIntelShort(&pp->translevel); \
+ for (i = 0; i < pp->width; i++) { \
+ SwapIntelShort((short*)&pp->collumnofs[i]); \
+ } \
+ }
+
+typedef struct
+{
+ byte color;
+ short height;
+ char width[256];
+ short charofs[256];
+ byte pal[0x300];
+ byte data; // as much as required
+} cfont_t;
+
+#define CONVERT_ENDIAN_cfont_t(pp) \
+ { \
+ int i; \
+ SwapIntelShort(&pp->height); \
+ for (i = 0; i < 256; i++) { \
+ SwapIntelShort(&pp->charofs[i]); \
+ } \
+ }
+
+#endif
--- /dev/null
+++ b/rott/memcheck.h
@@ -1,0 +1,1 @@
+/* old header removed */
--- /dev/null
+++ b/rott/modexlib.c
@@ -1,0 +1,847 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef DOS
+#include <malloc.h>
+#include <dos.h>
+#include <conio.h>
+#include <io.h>
+#endif
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include "modexlib.h"
+//MED
+#include "memcheck.h"
+#include "rt_util.h"
+#include "rt_net.h" // for GamePaused
+#include "myprint.h"
+
+static void StretchMemPicture ();
+// GLOBAL VARIABLES
+
+boolean StretchScreen=0;//bn�++
+extern boolean iG_aimCross;
+extern boolean sdl_fullscreen;
+extern int iG_X_center;
+extern int iG_Y_center;
+char *iG_buf_center;
+
+int linewidth;
+//int ylookup[MAXSCREENHEIGHT];
+int ylookup[600];//just set to max res
+byte *page1start;
+byte *page2start;
+byte *page3start;
+int screensize;
+byte *bufferofs;
+byte *displayofs;
+boolean graphicsmode=false;
+char *bufofsTopLimit;
+char *bufofsBottomLimit;
+
+void DrawCenterAim ();
+
+#ifdef DOS
+
+/*
+====================
+=
+= GraphicsMode
+=
+====================
+*/
+void GraphicsMode ( void )
+{
+ union REGS regs;
+
+ regs.w.ax = 0x13;
+ int386(0x10,®s,®s);
+ graphicsmode=true;
+}
+
+/*
+====================
+=
+= SetTextMode
+=
+====================
+*/
+void SetTextMode ( void )
+{
+
+ union REGS regs;
+
+ regs.w.ax = 0x03;
+ int386(0x10,®s,®s);
+ graphicsmode=false;
+
+}
+
+/*
+====================
+=
+= TurnOffTextCursor
+=
+====================
+*/
+void TurnOffTextCursor ( void )
+{
+
+ union REGS regs;
+
+ regs.w.ax = 0x0100;
+ regs.w.cx = 0x2000;
+ int386(0x10,®s,®s);
+
+}
+
+#if 0
+/*
+====================
+=
+= TurnOnTextCursor
+=
+====================
+*/
+void TurnOnTextCursor ( void )
+{
+
+ union REGS regs;
+
+ regs.w.ax = 0x03;
+ int386(0x10,®s,®s);
+
+}
+#endif
+
+/*
+====================
+=
+= WaitVBL
+=
+====================
+*/
+void WaitVBL( void )
+{
+ unsigned char i;
+
+ i=inp(0x03da);
+ while ((i&8)==0)
+ i=inp(0x03da);
+ while ((i&8)==1)
+ i=inp(0x03da);
+}
+
+
+/*
+====================
+=
+= VL_SetLineWidth
+=
+= Line witdh is in WORDS, 40 words is normal width for vgaplanegr
+=
+====================
+*/
+
+void VL_SetLineWidth (unsigned width)
+{
+ int i,offset;
+
+//
+// set wide virtual screen
+//
+ outpw (CRTC_INDEX,CRTC_OFFSET+width*256);
+
+//
+// set up lookup tables
+//
+ linewidth = width*2;
+
+ offset = 0;
+
+ for (i=0; i<iGLOBAL_SCREENHEIGHT; i++)
+ {
+ ylookup[i]=offset;
+ offset += linewidth;
+ }
+}
+
+/*
+=======================
+=
+= VL_SetVGAPlaneMode
+=
+=======================
+*/
+
+void VL_SetVGAPlaneMode ( void )
+{
+ GraphicsMode();
+ VL_DePlaneVGA ();
+ VL_SetLineWidth (48);
+ screensize=208*iGLOBAL_SCREENBWIDE*2;//bna++ *2
+ page1start=0xa0200;
+ page2start=0xa0200+screensize;
+ page3start=0xa0200+(2u*screensize);
+ displayofs = page1start;
+ bufferofs = page2start;
+ XFlipPage ();
+}
+
+/*
+=======================
+=
+= VL_CopyPlanarPage
+=
+=======================
+*/
+void VL_CopyPlanarPage ( byte * src, byte * dest )
+{
+ int plane;
+
+ for (plane=0; plane<4; plane++)
+ {
+ VGAREADMAP(plane);
+ VGAWRITEMAP(plane);
+ memcpy(dest,src,screensize);
+ }
+}
+
+/*
+=======================
+=
+= VL_CopyPlanarPageToMemory
+=
+=======================
+*/
+void VL_CopyPlanarPageToMemory ( byte * src, byte * dest )
+{
+ byte * ptr;
+ int plane,a,b;
+
+ for (plane=0; plane<4; plane++)
+ {
+ ptr=dest+plane;
+ VGAREADMAP(plane);
+ for (a=0; a<200; a++)
+ for (b=0; b<80; b++,ptr+=4)
+ *(ptr)=*(src+(a*linewidth)+b);
+ }
+}
+
+/*
+=======================
+=
+= VL_CopyBufferToAll
+=
+=======================
+*/
+void VL_CopyBufferToAll ( byte *buffer )
+{
+ int plane;
+
+ for (plane=0; plane<4; plane++)
+ {
+ VGAREADMAP(plane);
+ VGAWRITEMAP(plane);
+ if (page1start!=buffer)
+ memcpy((byte *)page1start,(byte *)buffer,screensize);
+ if (page2start!=buffer)
+ memcpy((byte *)page2start,(byte *)buffer,screensize);
+ if (page3start!=buffer)
+ memcpy((byte *)page3start,(byte *)buffer,screensize);
+ }
+}
+
+/*
+=======================
+=
+= VL_CopyDisplayToHidden
+=
+=======================
+*/
+void VL_CopyDisplayToHidden ( void )
+{
+ VL_CopyBufferToAll ( displayofs );
+}
+
+/*
+=================
+=
+= VL_ClearBuffer
+=
+= Fill the entire video buffer with a given color
+=
+=================
+*/
+
+void VL_ClearBuffer (unsigned buf, byte color)
+{
+ VGAMAPMASK(15);
+ memset((byte *)buf,color,screensize);
+}
+
+/*
+=================
+=
+= VL_ClearVideo
+=
+= Fill the entire video buffer with a given color
+=
+=================
+*/
+
+void VL_ClearVideo (byte color)
+{
+ VGAMAPMASK(15);
+ memset((byte *)(0xa000<<4),color,0x10000);
+}
+
+/*
+=================
+=
+= VL_DePlaneVGA
+=
+=================
+*/
+
+void VL_DePlaneVGA (void)
+{
+
+//
+// change CPU addressing to non linear mode
+//
+
+//
+// turn off chain 4 and odd/even
+//
+ outp (SC_INDEX,SC_MEMMODE);
+ outp (SC_DATA,(inp(SC_DATA)&~8)|4);
+
+ outp (SC_INDEX,SC_MAPMASK); // leave this set throughout
+
+//
+// turn off odd/even and set write mode 0
+//
+ outp (GC_INDEX,GC_MODE);
+ outp (GC_DATA,inp(GC_DATA)&~0x13);
+
+//
+// turn off chain
+//
+ outp (GC_INDEX,GC_MISCELLANEOUS);
+ outp (GC_DATA,inp(GC_DATA)&~2);
+
+//
+// clear the entire buffer space, because int 10h only did 16 k / plane
+//
+ VL_ClearVideo (0);
+
+//
+// change CRTC scanning from doubleword to byte mode, allowing >64k scans
+//
+ outp (CRTC_INDEX,CRTC_UNDERLINE);
+ outp (CRTC_DATA,inp(CRTC_DATA)&~0x40);
+
+ outp (CRTC_INDEX,CRTC_MODE);
+ outp (CRTC_DATA,inp(CRTC_DATA)|0x40);
+}
+
+
+/*
+=================
+=
+= XFlipPage
+=
+=================
+*/
+
+void XFlipPage ( void )
+{
+ displayofs=bufferofs;
+
+// _disable();
+
+ outp(CRTC_INDEX,CRTC_STARTHIGH);
+ outp(CRTC_DATA,((displayofs&0x0000ffff)>>8));
+
+// _enable();
+
+ bufferofs += screensize;
+ if (bufferofs > page3start)
+ bufferofs = page1start;
+}
+
+#else
+
+#include "SDL.h"
+
+#ifndef STUB_FUNCTION
+
+/* rt_def.h isn't included, so I just put this here... */
+#if !defined(ANSIESC)
+#define STUB_FUNCTION fprintf(stderr,"STUB: %s at " __FILE__ ", line %d, thread %d\n",__FUNCTION__,__LINE__,getpid())
+#else
+#define STUB_FUNCTION
+#endif
+
+#endif
+
+/*
+====================
+=
+= GraphicsMode
+=
+====================
+*/
+static SDL_Surface *sdl_surface = NULL;
+static SDL_Surface *unstretch_sdl_surface = NULL;
+
+void GraphicsMode ( void )
+{
+ Uint32 flags = 0;
+
+ if (SDL_InitSubSystem (SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
+ {
+ Error ("Could not initialize SDL\n");
+ }
+
+#if defined(PLATFORM_WIN32) || defined(PLATFORM_MACOSX)
+ // FIXME: remove this. --ryan.
+ flags = SDL_FULLSCREEN;
+ SDL_WM_GrabInput(SDL_GRAB_ON);
+#endif
+
+ SDL_WM_SetCaption ("Rise of the Triad", "ROTT");
+ SDL_ShowCursor (0);
+// sdl_surface = SDL_SetVideoMode (320, 200, 8, flags);
+ if (sdl_fullscreen)
+ flags = SDL_FULLSCREEN;
+ sdl_surface = SDL_SetVideoMode (iGLOBAL_SCREENWIDTH, iGLOBAL_SCREENHEIGHT, 8, flags);
+ if (sdl_surface == NULL)
+ {
+ Error ("Could not set video mode\n");
+ }
+}
+
+/*
+====================
+=
+= SetTextMode
+=
+====================
+*/
+void SetTextMode ( void )
+{
+ if (SDL_WasInit(SDL_INIT_VIDEO) == SDL_INIT_VIDEO) {
+ if (sdl_surface != NULL) {
+ SDL_FreeSurface(sdl_surface);
+
+ sdl_surface = NULL;
+ }
+
+ SDL_QuitSubSystem (SDL_INIT_VIDEO);
+ }
+}
+
+/*
+====================
+=
+= TurnOffTextCursor
+=
+====================
+*/
+void TurnOffTextCursor ( void )
+{
+}
+
+/*
+====================
+=
+= WaitVBL
+=
+====================
+*/
+void WaitVBL( void )
+{
+ SDL_Delay (16667/1000);
+}
+
+/*
+=======================
+=
+= VL_SetVGAPlaneMode
+=
+=======================
+*/
+
+void VL_SetVGAPlaneMode ( void )
+{
+ int i,offset;
+
+ GraphicsMode();
+
+//
+// set up lookup tables
+//
+//bna-- linewidth = 320;
+ linewidth = iGLOBAL_SCREENWIDTH;
+
+ offset = 0;
+
+ for (i=0; i<iGLOBAL_SCREENHEIGHT; i++)
+ {
+ ylookup[i]=offset;
+ offset += linewidth;
+ }
+
+// screensize=MAXSCREENHEIGHT*MAXSCREENWIDTH;
+ screensize=iGLOBAL_SCREENHEIGHT*iGLOBAL_SCREENWIDTH;
+
+
+
+ page1start=sdl_surface->pixels;
+ page2start=sdl_surface->pixels;
+ page3start=sdl_surface->pixels;
+ displayofs = page1start;
+ bufferofs = page2start;
+
+ iG_X_center = iGLOBAL_SCREENWIDTH / 2;
+ iG_Y_center = (iGLOBAL_SCREENHEIGHT / 2)+10 ;//+10 = move aim down a bit
+
+ iG_buf_center = bufferofs + (screensize/2);//(iG_Y_center*iGLOBAL_SCREENWIDTH);//+iG_X_center;
+
+ bufofsTopLimit = bufferofs + screensize - iGLOBAL_SCREENWIDTH;
+ bufofsBottomLimit = bufferofs + iGLOBAL_SCREENWIDTH;
+
+ // start stretched
+ EnableScreenStretch();
+ XFlipPage ();
+}
+
+/*
+=======================
+=
+= VL_CopyPlanarPage
+=
+=======================
+*/
+void VL_CopyPlanarPage ( byte * src, byte * dest )
+{
+#ifdef DOS
+ int plane;
+
+ for (plane=0; plane<4; plane++)
+ {
+ VGAREADMAP(plane);
+ VGAWRITEMAP(plane);
+ memcpy(dest,src,screensize);
+ }
+#else
+ memcpy(dest,src,screensize);
+#endif
+}
+
+/*
+=======================
+=
+= VL_CopyPlanarPageToMemory
+=
+=======================
+*/
+void VL_CopyPlanarPageToMemory ( byte * src, byte * dest )
+{
+#ifdef DOS
+ byte * ptr;
+ int plane,a,b;
+
+ for (plane=0; plane<4; plane++)
+ {
+ ptr=dest+plane;
+ VGAREADMAP(plane);
+ for (a=0; a<200; a++)
+ for (b=0; b<80; b++,ptr+=4)
+ *(ptr)=*(src+(a*linewidth)+b);
+ }
+#else
+ memcpy(dest,src,screensize);
+#endif
+}
+
+/*
+=======================
+=
+= VL_CopyBufferToAll
+=
+=======================
+*/
+void VL_CopyBufferToAll ( byte *buffer )
+{
+#ifdef DOS
+ int plane;
+
+ for (plane=0; plane<4; plane++)
+ {
+ VGAREADMAP(plane);
+ VGAWRITEMAP(plane);
+ if (page1start!=buffer)
+ memcpy((byte *)page1start,(byte *)buffer,screensize);
+ if (page2start!=buffer)
+ memcpy((byte *)page2start,(byte *)buffer,screensize);
+ if (page3start!=buffer)
+ memcpy((byte *)page3start,(byte *)buffer,screensize);
+ }
+#endif
+}
+
+/*
+=======================
+=
+= VL_CopyDisplayToHidden
+=
+=======================
+*/
+void VL_CopyDisplayToHidden ( void )
+{
+ VL_CopyBufferToAll ( displayofs );
+}
+
+/*
+=================
+=
+= VL_ClearBuffer
+=
+= Fill the entire video buffer with a given color
+=
+=================
+*/
+
+void VL_ClearBuffer (byte *buf, byte color)
+{
+#ifdef DOS
+ VGAMAPMASK(15);
+ memset((byte *)buf,color,screensize);
+#else
+ memset((byte *)buf,color,screensize);
+#endif
+}
+
+/*
+=================
+=
+= VL_ClearVideo
+=
+= Fill the entire video buffer with a given color
+=
+=================
+*/
+
+void VL_ClearVideo (byte color)
+{
+#ifdef DOS
+ VGAMAPMASK(15);
+ memset((byte *)(0xa000<<4),color,0x10000);
+#else
+ memset (sdl_surface->pixels, color, iGLOBAL_SCREENWIDTH*iGLOBAL_SCREENHEIGHT);
+#endif
+}
+
+/*
+=================
+=
+= VL_DePlaneVGA
+=
+=================
+*/
+
+void VL_DePlaneVGA (void)
+{
+}
+
+
+/* C version of rt_vh_a.asm */
+
+void VH_UpdateScreen (void)
+{
+
+ if (StretchScreen) { //bna++
+ StretchMemPicture ();
+ } else {
+ DrawCenterAim ();
+ }
+ SDL_UpdateRect (SDL_GetVideoSurface (), 0, 0, 0, 0);
+}
+
+
+/*
+=================
+=
+= XFlipPage
+=
+=================
+*/
+
+void XFlipPage ( void )
+{
+#ifdef DOS
+ displayofs=bufferofs;
+
+// _disable();
+
+ outp(CRTC_INDEX,CRTC_STARTHIGH);
+ outp(CRTC_DATA,((displayofs&0x0000ffff)>>8));
+
+// _enable();
+
+ bufferofs += screensize;
+ if (bufferofs > page3start)
+ bufferofs = page1start;
+#else
+ if (StretchScreen) { //bna++
+ StretchMemPicture ();
+ } else {
+ DrawCenterAim ();
+ }
+ SDL_UpdateRect (sdl_surface, 0, 0, 0, 0);
+
+#endif
+}
+
+#endif
+
+
+void EnableScreenStretch(void)
+{
+ int i,offset;
+
+ if (iGLOBAL_SCREENWIDTH <= 320 || StretchScreen) return;
+
+ if (unstretch_sdl_surface == NULL)
+ {
+ /* should really be just 320x200, but there is code all over the
+ places which crashes then */
+ unstretch_sdl_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
+ iGLOBAL_SCREENWIDTH, iGLOBAL_SCREENHEIGHT, 8, 0, 0, 0, 0);
+ }
+
+ displayofs = unstretch_sdl_surface->pixels +
+ (displayofs - (byte *)sdl_surface->pixels);
+ bufferofs = unstretch_sdl_surface->pixels;
+ page1start = unstretch_sdl_surface->pixels;
+ page2start = unstretch_sdl_surface->pixels;
+ page3start = unstretch_sdl_surface->pixels;
+ StretchScreen = 1;
+}
+
+void DisableScreenStretch(void)
+{
+ if (iGLOBAL_SCREENWIDTH <= 320 || !StretchScreen) return;
+
+ displayofs = sdl_surface->pixels +
+ (displayofs - (byte *)unstretch_sdl_surface->pixels);
+ bufferofs = sdl_surface->pixels;
+ page1start = sdl_surface->pixels;
+ page2start = sdl_surface->pixels;
+ page3start = sdl_surface->pixels;
+ StretchScreen = 0;
+}
+
+
+// bna section -------------------------------------------
+static void StretchMemPicture ()
+{
+ SDL_Rect src;
+ SDL_Rect dest;
+
+ src.x = 0;
+ src.y = 0;
+ src.w = 320;
+ src.h = 200;
+
+ dest.x = 0;
+ dest.y = 0;
+ dest.w = iGLOBAL_SCREENWIDTH;
+ dest.h = iGLOBAL_SCREENHEIGHT;
+ SDL_SoftStretch(unstretch_sdl_surface, &src, sdl_surface, &dest);
+}
+
+// bna function added start
+extern boolean ingame;
+extern exit_t playstate;
+int iG_playerTilt;
+
+void DrawCenterAim ()
+{
+ int x;
+
+ int percenthealth = (locplayerstate->health * 10) / MaxHitpointsForCharacter(locplayerstate);
+ int color = percenthealth < 3 ? egacolor[RED] : percenthealth < 4 ? egacolor[YELLOW] : egacolor[GREEN];
+
+ if (iG_aimCross && !GamePaused && playstate != ex_died) {
+ if (( ingame == true )&&(iGLOBAL_SCREENWIDTH>320)) {
+ if ((iG_playerTilt <0 )||(iG_playerTilt >iGLOBAL_SCREENHEIGHT/2)) {
+ iG_playerTilt = -(2048 - iG_playerTilt);
+ }
+ if (iGLOBAL_SCREENWIDTH == 640) {
+ x = iG_playerTilt;
+ iG_playerTilt=x/2;
+ }
+ iG_buf_center = bufferofs + ((iG_Y_center-iG_playerTilt)*iGLOBAL_SCREENWIDTH);//+iG_X_center;
+
+ for (x=iG_X_center-10; x<=iG_X_center-4; x++) {
+ if ((iG_buf_center+x < bufofsTopLimit)&&(iG_buf_center+x > bufofsBottomLimit)) {
+ *(iG_buf_center+x) = color;
+ }
+ }
+ for (x=iG_X_center+4; x<=iG_X_center+10; x++) {
+ if ((iG_buf_center+x < bufofsTopLimit)&&(iG_buf_center+x > bufofsBottomLimit)) {
+ *(iG_buf_center+x) = color;
+ }
+ }
+ for (x=10; x>=4; x--) {
+ if (((iG_buf_center-(x*iGLOBAL_SCREENWIDTH)+iG_X_center) < bufofsTopLimit)&&((iG_buf_center-(x*iGLOBAL_SCREENWIDTH)+iG_X_center) > bufofsBottomLimit)) {
+ *(iG_buf_center-(x*iGLOBAL_SCREENWIDTH)+iG_X_center) = color;
+ }
+ }
+ for (x=4; x<=10; x++) {
+ if (((iG_buf_center+(x*iGLOBAL_SCREENWIDTH)+iG_X_center) < bufofsTopLimit)&&((iG_buf_center+(x*iGLOBAL_SCREENWIDTH)+iG_X_center) > bufofsBottomLimit)) {
+ *(iG_buf_center+(x*iGLOBAL_SCREENWIDTH)+iG_X_center) = color;
+ }
+ }
+ }
+ }
+}
+// bna function added end
+
+
+
+
+// bna section -------------------------------------------
+
+
+
--- /dev/null
+++ b/rott/modexlib.h
@@ -1,0 +1,173 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// MODEXLIB.C - various utils palette funcs and modex stuff
+//
+//***************************************************************************
+
+#ifndef _modexlib_public
+#define _modexlib_public
+
+#include "WinRott.h"
+#include "rt_def.h"
+/*
+int iGLOBAL_SCREENWIDTH;//bna val 800
+int iGLOBAL_SCREENHEIGHT;//bna val 600
+
+
+#define MAXSCREENHEIGHT 600// 200*2
+#define MAXSCREENWIDTH 800// 320*2
+#define SCREENBWIDE 800*(96/320)// 96*2
+#define MAXVIEWWIDTH 800// 320*2
+#define SCREENWIDTH 800*(96/320)// 96*2 // default screen width in bytes
+*/
+//***************************************************************************
+//
+// Video (ModeX) Constants
+//
+//***************************************************************************
+
+#ifdef DOS
+#define SC_INDEX 0x3C4
+#define SC_DATA 0x3C5
+#define SC_RESET 0
+#define SC_CLOCK 1
+#define SC_MAPMASK 2
+#define SC_CHARMAP 3
+#define SC_MEMMODE 4
+
+#define CRTC_INDEX 0x3D4
+#define CRTC_DATA 0x3D5
+#define CRTC_H_TOTAL 0
+#define CRTC_H_DISPEND 1
+#define CRTC_H_BLANK 2
+#define CRTC_H_ENDBLANK 3
+#define CRTC_H_RETRACE 4
+#define CRTC_H_ENDRETRACE 5
+#define CRTC_V_TOTAL 6
+#define CRTC_OVERFLOW 7
+#define CRTC_ROWSCAN 8
+#define CRTC_MAXSCANLINE 9
+#define CRTC_CURSORSTART 10
+#define CRTC_CURSOREND 11
+#define CRTC_STARTHIGH 12
+#define CRTC_STARTLOW 13
+#define CRTC_CURSORHIGH 14
+#define CRTC_CURSORLOW 15
+#define CRTC_V_RETRACE 16
+#define CRTC_V_ENDRETRACE 17
+#define CRTC_V_DISPEND 18
+#define CRTC_OFFSET 19
+#define CRTC_UNDERLINE 20
+#define CRTC_V_BLANK 21
+#define CRTC_V_ENDBLANK 22
+#define CRTC_MODE 23
+#define CRTC_LINECOMPARE 24
+
+#define GC_INDEX 0x3CE
+#define GC_DATA 0x3CF
+#define GC_SETRESET 0
+#define GC_ENABLESETRESET 1
+#define GC_COLORCOMPARE 2
+#define GC_DATAROTATE 3
+#define GC_READMAP 4
+#define GC_MODE 5
+#define GC_MISCELLANEOUS 6
+#define GC_COLORDONTCARE 7
+#define GC_BITMASK 8
+
+#define ATR_INDEX 0x3c0
+#define ATR_MODE 16
+#define ATR_OVERSCAN 17
+#define ATR_COLORPLANEENABLE 18
+#define ATR_PELPAN 19
+#define ATR_COLORSELECT 20
+
+#define STATUS_REGISTER_1 0x3da
+
+#define PEL_WRITE_ADR 0x3c8
+#define PEL_READ_ADR 0x3c7
+#define PEL_DATA 0x3c9
+#endif
+
+extern boolean StretchScreen;//bn�++
+
+//extern int ylookup[MAXSCREENHEIGHT]; // Table of row offsets
+extern int ylookup[600]; // just set to max res
+extern int linewidth;
+extern byte *page1start;
+extern byte *page2start;
+extern byte *page3start;
+extern int screensize;
+extern byte *bufferofs;
+extern byte *displayofs;
+extern boolean graphicsmode;
+
+
+void GraphicsMode ( void );
+void SetTextMode ( void );
+void VL_SetVGAPlaneMode ( void );
+void VL_ClearBuffer (byte *buf, byte color);
+void VL_ClearVideo (byte color);
+void VL_DePlaneVGA (void);
+void VL_CopyDisplayToHidden ( void );
+void VL_CopyBufferToAll ( byte *buffer );
+void VL_CopyPlanarPage ( byte * src, byte * dest );
+void VL_CopyPlanarPageToMemory ( byte * src, byte * dest );
+void XFlipPage ( void );
+void WaitVBL( void );
+void TurnOffTextCursor ( void );
+
+#ifdef __WATCOMC__
+#pragma aux VGAWRITEMAP = \
+ "mov eax,01H" \
+ "mov edx,03c5h" \
+ "shl eax,cl" \
+ "out dx,al" \
+ parm [ecx] \
+ modify exact [eax edx]
+
+#pragma aux VGAMAPMASK = \
+ "mov edx,03c5h" \
+ "out dx,al" \
+ parm [eax] \
+ modify exact [edx]
+
+#pragma aux VGAREADMAP = \
+ "shl eax,08H" \
+ "mov edx,03ceh" \
+ "add eax,04H" \
+ "out dx,ax" \
+ parm [eax] \
+ modify exact [eax edx]
+#endif
+
+#ifdef DOS
+void VGAMAPMASK (int x);
+void VGAREADMAP (int x);
+void VGAWRITEMAP(int x);
+#else
+#define VGAMAPMASK(a)
+#define VGAREADMAP(a)
+#define VGAWRITEMAP(a)
+#endif
+
+#endif
--- /dev/null
+++ b/rott/music.h
@@ -1,0 +1,96 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: MUSIC.H
+
+ author: James R. Dose
+ date: March 25, 1994
+
+ Public header for MUSIC.C
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __MUSIC_H
+#define __MUSIC_H
+
+#include "sndcards.h"
+
+extern int MUSIC_ErrorCode;
+
+enum MUSIC_ERRORS
+{
+ MUSIC_Warning = -2,
+ MUSIC_Error = -1,
+ MUSIC_Ok = 0,
+ MUSIC_ASSVersion,
+ MUSIC_SoundCardError,
+ MUSIC_MPU401Error,
+ MUSIC_InvalidCard,
+ MUSIC_MidiError,
+ MUSIC_TaskManError,
+ MUSIC_FMNotDetected,
+ MUSIC_DPMI_Error
+};
+
+typedef struct
+{
+ unsigned long tickposition;
+ unsigned long milliseconds;
+ unsigned int measure;
+ unsigned int beat;
+ unsigned int tick;
+} songposition;
+
+#define MUSIC_LoopSong ( 1 == 1 )
+#define MUSIC_PlayOnce ( !MUSIC_LoopSong )
+
+char *MUSIC_ErrorString( int ErrorNumber );
+int MUSIC_Init( int SoundCard, int Address );
+int MUSIC_Shutdown( void );
+void MUSIC_SetMaxFMMidiChannel( int channel );
+void MUSIC_SetVolume( int volume );
+void MUSIC_SetMidiChannelVolume( int channel, int volume );
+void MUSIC_ResetMidiChannelVolumes( void );
+int MUSIC_GetVolume( void );
+void MUSIC_SetLoopFlag( int loopflag );
+int MUSIC_SongPlaying( void );
+void MUSIC_Continue( void );
+void MUSIC_Pause( void );
+int MUSIC_StopSong( void );
+int MUSIC_PlaySong( unsigned char *song, int loopflag );
+
+// ROTT Special - SBF
+int MUSIC_PlaySongROTT(unsigned char *song, int size, int loopflag);
+
+void MUSIC_SetContext( int context );
+int MUSIC_GetContext( void );
+void MUSIC_SetSongTick( unsigned long PositionInTicks );
+void MUSIC_SetSongTime( unsigned long milliseconds );
+void MUSIC_SetSongPosition( int measure, int beat, int tick );
+void MUSIC_GetSongPosition( songposition *pos );
+void MUSIC_GetSongLength( songposition *pos );
+int MUSIC_FadeVolume( int tovolume, int milliseconds );
+int MUSIC_FadeActive( void );
+void MUSIC_StopFade( void );
+void MUSIC_RerouteMidiChannel( int channel, int cdecl ( *function )( int event, int c1, int c2 ) );
+void MUSIC_RegisterTimbreBank( unsigned char *timbres );
+
+#endif
--- /dev/null
+++ b/rott/myprint.h
@@ -1,0 +1,43 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef __MYPRINT_H
+#define __MYPRINT_H
+
+enum COLORS
+{
+ BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LIGHTGRAY, DARKGRAY,
+ LIGHTBLUE, LIGHTGREEN, LIGHTCYAN, LIGHTRED, LIGHTMAGENTA, YELLOW, WHITE
+};
+
+#define NONE -1
+#define SINGLE_FRAME -1
+#define DOUBLE_FRAME -2
+
+void DrawRottText( int x, int y, int ch, int foreground, int background );
+void TextBox( int x1, int y1, int x2, int y2, int ch, int foreground, int background );
+void TextFrame( int x1, int y1, int x2, int y2, int type, int foreground, int background );
+void mysetxy( int x, int y );
+void myputch( char ch );
+int printstring( char *string );
+int printnum( int number );
+int printunsigned( unsigned long number, int radix );
+int myprintf( char *fmt, ... ) __attribute__((format(printf,1,2)));
+
+#endif
--- /dev/null
+++ b/rott/profile.h
@@ -1,0 +1,26 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _profile
+#define _profile
+
+#define PROFILE 0
+#define PROFILETICS 2
+
+#endif
--- /dev/null
+++ b/rott/rottnet.h
@@ -1,0 +1,102 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// rottnet.h
+#ifndef rottnet_public
+#define rottnet_public
+
+#include "develop.h"
+
+#ifdef DOS
+#define PEL_WRITE_ADR 0x3c8
+#define PEL_DATA 0x3c9
+
+#define I_ColorBlack(r,g,b) {outp(PEL_WRITE_ADR,0);outp(PEL_DATA,r);outp(PEL_DATA,g);outp(PEL_DATA,b);};
+#endif
+
+#define MAXNETNODES 14 // max computers in a game
+
+#if ( SHAREWARE == 1 )
+#define MAXPLAYERS 5 // 5 players max + drones
+#else
+#define MAXPLAYERS 11 // 11 players max + drones
+#endif
+
+#define CMD_SEND 1
+#define CMD_GET 2
+#define CMD_OUTQUEBUFFERSIZE 3
+#define CMD_INQUEBUFFERSIZE 4
+
+#define ROTTCOM_ID 0x12345678l
+
+#define MAXPACKETSIZE 2048
+#define MAXCOMBUFFERSIZE 2048
+
+#if __WATCOMC__
+#pragma pack (1)
+#endif
+
+typedef struct
+{
+ short intnum; // ROTT executes an int to send commands
+
+// communication between ROTT and the driver
+ short command; // CMD_SEND or CMD_GET
+ short remotenode; // dest for send, set by get (-1 = no packet)
+ short datalength; // bytes in rottdata to be sent / bytes read
+
+// info specific to this node
+ short consoleplayer; // 0-3 = player number
+ short numplayers; // 1-4
+ short client; // 0 = server 1 = client
+ short gametype; // 0 = modem 1 = network
+ short ticstep; // 1 for every tic 2 for every other tic ...
+ short remoteridicule; // 0 = remote ridicule is off 1= rr is on
+
+// packet data to be sent
+ char data[MAXPACKETSIZE];
+} rottcom_t;
+
+#if __WATCOMC__
+#pragma pack (4)
+#endif
+
+#define MODEM_GAME 0
+#define NETWORK_GAME 1
+
+#define ROTTLAUNCHER ("ROTT.EXE")
+
+#if defined(DOS) && (__WATCOMC__ == 0)
+
+extern rottcom_t rottcom;
+extern boolean pause;
+
+void ShutdownROTTCOM ( void );
+int CheckParm (char *check);
+void LaunchROTT (void);
+void NetISR (void);
+long GetVector (void);
+
+#else
+
+extern rottcom_t * rottcom;
+
+#endif
+
+#endif
--- /dev/null
+++ b/rott/rt_actor.c
@@ -1,0 +1,14028 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+
+#include <string.h>
+#include <stdlib.h>
+#include "rt_def.h"
+#include "rt_sound.h"
+#include "rt_door.h"
+#include "rt_ted.h"
+#include "rt_draw.h"
+#include "watcom.h"
+#include "z_zone.h"
+#include "w_wad.h"
+#include "lumpy.h"
+#include "gmove.h"
+#include "states.h"
+#include "rt_sqrt.h"
+#include "rt_stat.h"
+#include "sprites.h"
+#include "rt_actor.h"
+#include "rt_game.h"
+#include "rt_main.h"
+#include "rt_playr.h"
+#include "rt_util.h"
+#include "rt_rand.h"
+#include "rt_menu.h"
+#include "rt_swift.h"
+#include "_rt_acto.h"
+#include "rt_cfg.h"
+#include "rt_floor.h"
+#include "engine.h"
+#include "develop.h"
+#include "rt_view.h"
+#include "isr.h"
+#include "rt_com.h"
+#include "rt_scale.h"
+#include "modexlib.h"
+#include "rt_net.h"
+#include "rt_msg.h"
+#include "fx_man.h"
+//MED
+#include "memcheck.h"
+
+
+
+
+#define SGN(x) (((x) > 0)?(1):(-1))
+
+
+
+#define WILEYBLITZCHANCE 20
+#define GIBSOUND SD_GIBSPLASHSND
+#define ACTORTHUDSND SD_BODYLANDSND
+#define ACTORLANDSND SD_PLAYERLANDSND
+
+//========================== Global Variables ===================================================
+
+#define SHP(difficulty,ob) (starthitpoints[difficulty][ob->obclass])
+
+#define CAP_OSCUROS_HITPOINTS(ob) \
+ { \
+ if (ob->hitpoints > (SHP(gamestate.difficulty,ob)<<1)) \
+ ob->hitpoints = (SHP(gamestate.difficulty,ob)<<1); \
+ }
+
+
+boolean ludicrousgibs=false;
+
+short colheight[15];
+
+byte deathshapeoffset[8] = {0,7,7,8,8,9,8,7};
+
+unsigned long MAXFUNCTION,MINFUNCTION,MAXSTATE,MINSTATE;
+
+objtype *PLAYER0MISSILE;
+objtype *SCREENEYE;
+objtype *FIRSTACTOR,*LASTACTOR;
+
+objtype *FIRSTFREE,*LASTFREE;
+objtype *lastactive,*firstactive,**objlist;
+objtype *firstareaactor[NUMAREAS+1],*lastareaactor[NUMAREAS+1];
+int objcount;
+
+byte RANDOMACTORTYPE[10];
+
+#if (SHAREWARE == 0)
+_2Dpoint SNAKEPATH[512];
+#endif
+misc_stuff mstruct,*MISCVARS = &mstruct;
+int angletodir[ANGLES];
+objtype *new;
+
+void *actorat[MAPSIZE][MAPSIZE];
+#if (DEVELOPMENT == 1)
+FILE * williamdebug;
+#endif
+exit_t playstate;
+
+void T_SlideDownScreen(objtype*);
+
+basic_actor_sounds BAS[NUMCLASSES+3] =
+{ {0,0,0,0,0},
+ {0,0,0,0,0},
+ {0,SD_LOWGUARD1SEESND,SD_LOWGUARDFIRESND,SD_LOWGUARDOUCHSND,SD_LOWGUARD1DIESND},
+ {0,SD_HIGHGUARD1SEESND,SD_HIGHGUARDFIRESND,SD_HIGHGUARDOUCHSND,SD_HIGHGUARDDIESND},
+ {0,SD_OVERP1SEESND,SD_OVERPFIRESND,SD_OVERPOUCHSND,SD_OVERPDIESND},
+ {0,SD_STRIKE1SEESND,SD_STRIKEFIRESND,SD_STRIKEOUCHSND,SD_STRIKEDIESND},
+ {0,SD_BLITZ1SEESND,SD_BLITZFIRESND,SD_BLITZOUCHSND,SD_BLITZDIESND},
+ {0,SD_ENFORCERSEESND,SD_ENFORCERFIRESND,SD_ENFORCEROUCHSND,SD_ENFORCERDIESND},
+ {0,SD_MONKSEESND,SD_MONKGRABSND,SD_MONKOUCHSND,SD_MONKDIESND},
+ {0,SD_FIREMONKSEESND,SD_FIREMONKFIRESND,SD_FIREMONKOUCHSND,SD_FIREMONKDIESND},
+ {0,SD_ROBOTSEESND,SD_ROBOTFIRESND,0,SD_ROBOTDIESND},
+
+ //bosses
+ {SD_DARIANSAY1,SD_DARIANSEESND,SD_DARIANFIRESND,0,SD_DARIANDIESND},
+ {SD_KRISTSAY1,SD_KRISTSEESND,SD_KRISTFIRESND,0,SD_KRISTDIESND},
+ {0,SD_NMESEESND,SD_NMEFIRE1SND,0,SD_NMEDIESND},
+ {SD_DARKMONKSAY1,SD_DARKMONKSEESND,SD_DARKMONKFIRE1SND,0,SD_DARKMONKDIESND},
+ {SD_SNAKESAY1,SD_SNAKESEESND,SD_SNAKESPITSND,0,SD_SNAKEDIESND},
+
+ //specials
+ {0,SD_EMPLACEMENTSEESND,SD_EMPLACEMENTFIRESND,0,0},
+ {0,SD_ROBOTSEESND,SD_ROBOTFIRESND,0,SD_ROBOTDIESND}, //wallop
+ {0,0,0,0,0}, //pillar
+ {SD_FIREJETSND,0,0,0,0}, //firejet
+ {SD_BLADESPINSND,0,0,0,0}, //blade
+ {SD_CYLINDERMOVESND,0,0,0,0}, //crushcol
+ {SD_BOULDERROLLSND,0,0,SD_BOULDERHITSND,0}, //boulder
+ {SD_SPEARSTABSND,0,0,0,0}, //spear
+ {0,0,0,0,0}, //gasgrate
+ {SD_SPRINGBOARDSND,0,0,0,0}, //spring
+ {0,0,0,0,0}, //shuriken
+ {SD_FIREBALLSND,0,0,SD_FIREBALLHITSND,0}, //wallfire
+ {0,0,0,0,0}, //net
+ {SD_KRISTMINEBEEPSND,0,0,0,0}, //h_mine
+ {0,0,0,0,0}, //grenade
+ {0,0,0,0,0}, //fireball
+ {0,0,0,0,0}, //dmfball
+ {0,0,0,0,0}, //bigshuriken
+ {0,0,0,0,0}, //missile
+ {0,0,0,0,0}, //NMEsaucer
+ {0,0,0,0,0}, //dm_weapon
+ {0,0,0,0,0}, //dm_heatseek
+ {0,0,0,0,0}, //dm_spit
+ {SD_MISSILEFLYSND,0,SD_BAZOOKAFIRESND,SD_MISSILEHITSND,0},
+ {SD_MISSILEFLYSND,0,SD_FIREBOMBFIRESND,SD_MISSILEHITSND,0},
+ {SD_MISSILEFLYSND,0,SD_HEATSEEKFIRESND,SD_MISSILEHITSND,0},
+ {SD_MISSILEFLYSND,0,SD_DRUNKFIRESND,SD_MISSILEHITSND,0},
+ {SD_FLAMEWALLSND,0,SD_FLAMEWALLFIRESND,SD_FIREHITSND,0},
+ {SD_MISSILEFLYSND,0,SD_SPLITFIRESND,SD_MISSILEHITSND,0},
+ {SD_GRAVSND,0,SD_GRAVFIRESND,SD_GRAVHITSND,0},
+ {SD_GRAVSND,0,SD_GODMODEFIRESND,SD_GRAVHITSND,0}
+
+};
+
+
+//========================== Local Variables ==================================================
+
+extern boolean dopefish;
+
+
+boolean Masterdisk;
+
+static objtype *SNAKEHEAD,*SNAKEEND,*PARTICLE_GENERATOR,*EXPLOSIONS;
+#if (SHAREWARE == 0)
+static int OLDTILEX,OLDTILEY;
+#endif
+
+
+static char *debugstr[] = {
+
+ "inerttype",
+ "player",
+ "lowguard",
+ "highguard",
+ "overpatrol",
+ "strikeguard",
+ "blitzguard",
+ "triadenforcer",
+ "deathmonk",
+ "dfiremonk",
+ "roboguard",
+ "b_darian",
+ "b_heinrich",
+ "b_darkmonk",
+ "b_roboboss",
+ "b_darksnake",
+ "patrolgun",
+ "wallop",
+ "pillar",
+ "firejet",
+ "blade",
+ "crushcol",
+ "boulder",
+ "spear",
+ "gasgrate",
+ "spring",
+ "shuriken",
+ "wallfire",
+ "net",
+ "h_mine",
+ "grenade",
+ "fireball",
+ "dmfball",
+ "bigshuriken",
+ "missile",
+ "NMEsaucer",
+ "dm_weapon",
+ "dm_heatseek",
+ "dm_spit",
+ "p_bazooka",
+ "p_firebomb",
+ "p_heatseek",
+ "p_drunkmissile",
+ "p_firewall",
+ "p_splitmissile",
+ "p_kes",
+ "p_godball",
+ "collectorobj"
+};
+
+
+
+
+
+
+
+static int starthitpoints[4][NUMENEMIES+2] =
+
+{ {0,0,30,35,50,40,45,425,200,200,100,1500,2500,3000,3000,-1,200,2},
+ {0,0,40,50,55,50,50,475,250,250,125,2300,3400,4500,3600,-1,250,2},
+ {0,0,50,65,60,60,60,525,275,300,150,2400,3600,5000,4500,-1,300,2},
+ {0,0,60,80,70,70,75,525,300,350,175,2800,3800,5900,4800,-1,350,2}
+};
+
+
+static statobj_t *touchsprite = NULL;
+
+
+static const byte dirdiff[8][8] = {{0,1,2,3,4,3,2,1},{1,0,1,2,3,4,3,2},
+ {2,1,0,1,2,3,4,3},{3,2,1,0,1,2,3,4},
+ {4,3,2,1,0,1,2,3},{3,4,3,2,1,0,1,2},
+ {2,3,4,3,2,1,0,1},{1,2,3,4,3,2,1,0}
+};
+
+static const byte dirorder[8][2] = {{southeast,northeast},{east,north},
+ {northeast,northwest},{north,west},
+ {northwest,southwest},{west,south},
+ {southwest,southeast},{south,east}
+};
+
+#if (SHAREWARE == 0)
+
+static const byte dirdiff16[16][16] = {
+ {0,1,2,3,4,5,6,7,8,7,6,5,4,3,2,1},
+ {1,0,1,2,3,4,5,6,7,8,7,6,5,4,3,2},
+ {2,1,0,1,2,3,4,5,6,7,8,7,6,5,4,3},
+ {3,2,1,0,1,2,3,4,5,6,7,8,7,6,5,4},
+ {4,3,2,1,0,1,2,3,4,5,6,7,8,7,6,5},
+ {5,4,3,2,1,0,1,2,3,4,5,6,7,8,7,6},
+ {6,5,4,3,2,1,0,1,2,3,4,5,6,7,8,7},
+ {7,6,5,4,3,2,1,0,1,2,3,4,5,6,7,8},
+ {8,7,6,5,4,3,2,1,0,1,2,3,4,5,6,7},
+ {7,8,7,6,5,4,3,2,1,0,1,2,3,4,5,6},
+ {6,7,8,7,6,5,4,3,2,1,0,1,2,3,4,5},
+ {5,6,7,8,7,6,5,4,3,2,1,0,1,2,3,4},
+ {4,5,6,7,8,7,6,5,4,3,2,1,0,1,2,3},
+ {3,4,5,6,7,8,7,6,5,4,3,2,1,0,1,2},
+ {2,3,4,5,6,7,8,7,6,5,4,3,2,1,0,1},
+ {1,2,3,4,5,6,7,8,7,6,5,4,3,2,1,0}
+};
+#endif
+
+static const byte dirorder16[16][2] = {
+ {15,1}, {0,2}, {1,3}, {2,4},
+ {3,5}, {4,6}, {5,7}, {6,8},
+ {7,9}, {8,10}, {9,11}, {10,12},
+ {11,13}, {12,14}, {13,15}, {14,0}
+};
+
+//static byte opposite16[16] = {8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7};
+
+#if (SHAREWARE == 0)
+
+static statetype * UPDATE_STATES[NUMSTATES][NUMENEMIES] =
+
+{ { &s_lowgrdstand,&s_highgrdstand,&s_opstand,&s_strikestand,
+ &s_blitzstand,&s_enforcerstand,&s_dmonkstand,&s_firemonkstand,
+ &s_robogrdstand,&s_darianstand,&s_heinrichstand,NULL,
+ &s_darkmonkstand,NULL,&s_gunstand,&s_wallstand
+ },
+
+ { &s_lowgrdpath1,&s_highgrdpath1,&s_oppath1,&s_strikepath1,
+ &s_blitzpath1,&s_enforcerpath1,&s_dmonkpath1,&s_firemonkpath1,
+ &s_robogrdpath1,NULL,NULL,NULL,
+ NULL,NULL,NULL,&s_wallpath
+ },
+
+ { &s_lowgrdcollide,&s_highgrdcollide,&s_opcollide,&s_strikecollide,
+ &s_blitzcollide,&s_enforcercollide,&s_dmonkcollide,&s_firemonkcollide,
+ &s_robogrdcollide,&s_dariancollide,NULL,NULL,
+ NULL,NULL,NULL,&s_wallcollide
+ },
+
+ { &s_lowgrdcollide2,&s_highgrdcollide2,&s_opcollide2,&s_strikecollide2,
+ &s_blitzcollide2,&s_enforcercollide2,&s_dmonkcollide2,&s_firemonkcollide2,
+ &s_robogrdcollide2,&s_dariancollide2,NULL,NULL,
+ NULL,NULL,NULL,&s_wallcollide
+ },
+
+ { &s_lowgrdchase1,&s_highgrdchase1,&s_opchase1,&s_strikechase1,
+ &s_blitzchase1,&s_enforcerchase1,&s_dmonkchase1,&s_firemonkchase1,
+ NULL/*se1*/,&s_darianchase1,&s_heinrichchase,&s_NMEchase,
+ &s_darkmonkchase1,NULL,&s_gunstand,&s_wallpath
+ },
+
+ /*
+ {&s_lowgrduse1,&s_highgrduse1,&s_opuse1,&s_strikeuse1,
+ &s_blitzuse,&s_enforceruse1,NULL,NULL,
+ NULL,&s_darianuse1,NULL,NULL,
+ NULL,NULL,NULL,NULL},*/
+ {0},
+
+ { &s_lowgrdshoot1,&s_highgrdshoot1,&s_opshoot1,&s_strikeshoot1,
+ &s_blitzshoot1,&s_enforcershoot1,NULL,&s_firemonkcast1,
+ &s_robogrdshoot1,&s_darianshoot1,&s_heinrichshoot1,NULL,
+ NULL,NULL,&s_gunfire1,&s_wallshoot
+ },
+
+ { &s_lowgrddie1,&s_highgrddie1,&s_opdie1,&s_strikedie1,
+ &s_blitzdie1,&s_enforcerdie1,&s_dmonkdie1,&s_firemonkdie1,
+ &s_robogrddie1,&s_dariandie1,&s_heinrichdie1,&s_NMEdie,
+ &s_darkmonkdie1,NULL,&s_gundie1,NULL
+ },
+
+ {0},
+
+ { NULL,NULL,NULL,&s_strikewait,
+ &s_blitzstand,&s_enforcerdie1,&s_dmonkdie1,&s_firemonkdie1,
+ &s_robogrddie1,&s_dariandie1,&s_heinrichdie1,NULL,
+ &s_darkmonkdie1,NULL,NULL,NULL
+ },
+
+ { &s_lowgrdcrushed1,&s_highgrdcrushed1,&s_opcrushed1,&s_strikecrushed1,
+ &s_blitzcrushed1,&s_enforcercrushed1,&s_dmonkcrushed1,&s_firemonkcrushed1,
+ &s_robogrddie1,NULL,NULL,NULL,
+ NULL,NULL,NULL,NULL
+ }
+
+};
+
+#else
+
+static statetype * UPDATE_STATES[NUMSTATES][NUMENEMIES] =
+
+{ { &s_lowgrdstand,&s_highgrdstand,NULL,&s_strikestand,
+ &s_blitzstand,&s_enforcerstand,NULL,NULL,
+ &s_robogrdstand,NULL,NULL,NULL,
+ NULL,NULL,NULL,NULL
+ },
+
+ { &s_lowgrdpath1,&s_highgrdpath1,NULL,&s_strikepath1,
+ &s_blitzpath1,&s_enforcerpath1,NULL,NULL,
+ &s_robogrdpath1,NULL,NULL,NULL,
+ NULL,NULL,NULL,NULL
+ },
+
+ { &s_lowgrdcollide,&s_highgrdcollide,NULL,&s_strikecollide,
+ &s_blitzcollide,&s_enforcercollide,NULL,NULL,
+ NULL,NULL,NULL,NULL,
+ NULL,NULL,NULL,NULL
+ },
+
+ { &s_lowgrdcollide2,&s_highgrdcollide2,NULL,&s_strikecollide2,
+ &s_blitzcollide2,&s_enforcercollide2,NULL,NULL,
+ &s_robogrdcollide2,NULL,NULL,NULL,
+ NULL,NULL,NULL,NULL
+ },
+
+ { &s_lowgrdchase1,&s_highgrdchase1,NULL,&s_strikechase1,
+ &s_blitzchase1,&s_enforcerchase1,NULL,NULL,
+ NULL,NULL,NULL,NULL,
+ NULL,NULL,NULL,NULL
+ },
+
+ /*
+ {&s_lowgrduse1,&s_highgrduse1,&s_opuse1,&s_strikeuse1,
+ &s_blitzuse,&s_enforceruse1,NULL,NULL,
+ NULL,&s_darianuse1,NULL,NULL,
+ NULL,NULL,NULL,NULL},*/
+ {0},
+
+ { &s_lowgrdshoot1,&s_highgrdshoot1,NULL,&s_strikeshoot1,
+ &s_blitzshoot1,&s_enforcershoot1,NULL,NULL,
+ &s_robogrdshoot1,NULL,NULL,NULL,
+ NULL,NULL,NULL,NULL
+ },
+
+ { &s_lowgrddie1,&s_highgrddie1,NULL,&s_strikedie1,
+ &s_blitzdie1,&s_enforcerdie1,NULL,NULL,
+ &s_robogrddie1,NULL,NULL,NULL,
+ NULL,NULL,NULL,NULL
+ },
+
+ {0},
+
+ { NULL,NULL,NULL,&s_strikewait,
+ &s_blitzstand,&s_enforcerdie1,NULL,NULL,
+ &s_robogrddie1,NULL,NULL,NULL,
+ NULL,NULL,NULL,NULL
+ },
+
+ { &s_lowgrdcrushed1,&s_highgrdcrushed1,NULL,&s_strikecrushed1,
+ &s_blitzcrushed1,&s_enforcercrushed1,NULL,NULL,
+ &s_robogrddie1,NULL,NULL,NULL,
+ NULL,NULL,NULL,NULL
+ }
+
+};
+
+#endif
+
+
+
+#define TABLE_ACTOR(ob) ((ob->obclass >= lowguardobj) && (ob->obclass <= wallopobj))
+
+
+void T_Reset(objtype*ob);
+void ApplyGravity(objtype *ob);
+void BeginEnemyHurt(objtype *ob);
+void T_PlayDead(objtype *ob);
+void SpawnFirewall(objtype*ob,int which,int newz);
+void SelectKristChaseDir(objtype*ob);
+void ExplodeStatic(statobj_t*tempstat);
+void AvoidPlayerMissile(objtype*ob);
+int EnvironmentDamage(objtype *ob);
+
+static int STOPSPEED = 0x200;
+static int PLAYERFRICTION = 0xe000;
+static int ACTORFRICTION = 0xf000;
+static int DIAGADJUST = 0xb504;
+static boolean MissileSound = true;
+
+
+
+
+boolean FirstExplosionState(statetype *state)
+{
+ if (DoPanicMapping())
+ {
+ if (state == &s_altexplosion1)
+ return true;
+ else
+ return false;
+ }
+ else
+ {
+ if ((state == &s_explosion1) ||
+ (state == &s_grexplosion1) ||
+ (state == &s_staticexplosion1)
+ )
+ return true;
+ else
+ return false;
+ }
+
+}
+
+
+
+
+
+void SetGibSpeed(int speed)
+{
+ MISCVARS->gibspeed = speed;
+}
+
+void ResetGibSpeed(void)
+{
+ MISCVARS->gibspeed = NORMALGIBSPEED;
+}
+
+int ValidAreanumber (int areanumber)
+{ if ((areanumber >=0) && (areanumber <= NUMAREAS))
+ return 1;
+ return 0;
+}
+
+int GetIndexForState (statetype * state)
+{
+ int i;
+
+ if (state == NULL)
+ return -1;
+
+ for (i=0; i<MAXSTATES; i++)
+ {
+ if (statetable[i]==state)
+ return i;
+ }
+ Error("Cannot find the state in 'GetIndexForState', state->shapenum = %d\n",state->shapenum);
+ return -1;
+}
+
+
+
+statetype * GetStateForIndex (int index)
+{
+ if (index == -1)
+ return NULL;
+
+ return statetable[index];
+}
+
+
+statobj_t* GetStaticForIndex(int index)
+{ statobj_t* temp;
+
+ for(temp=FIRSTSTAT; temp; temp=temp->statnext)
+ if (index == temp->whichstat)
+ return temp;
+
+ Error("Cannot find the static in 'GetStaticForIndex', statindex %d\n",index);
+ return NULL;
+
+}
+
+
+
+void SaveActors(byte **buffer,int*size)
+{ objtype*temp,*tact;
+ saved_actor_type dummy;
+ byte*tptr;
+ int actorcount;
+
+
+ for(actorcount=0,temp=FIRSTACTOR; temp; temp=temp->next)
+ temp->whichactor = actorcount++;
+
+
+
+ *size = sizeof(int) + sizeof(numplayers) + sizeof(misc_stuff) + objcount*sizeof(saved_actor_type);
+ *buffer = (byte*)SafeMalloc(*size);
+ tptr = *buffer;
+
+ memcpy(tptr,MISCVARS,sizeof(misc_stuff));
+ tptr += sizeof(misc_stuff);
+
+ memcpy(tptr,&numplayers,sizeof(numplayers));
+ tptr += sizeof(numplayers);
+
+ memcpy(tptr,&consoleplayer,sizeof(consoleplayer));
+ tptr += sizeof(consoleplayer);
+
+ for(temp=FIRSTACTOR; temp; temp=temp->next)
+ { dummy.x = temp->x;
+ dummy.y = temp->y;
+ dummy.z = temp->z;
+ dummy.flags = temp->flags;
+ dummy.areanumber = temp->areanumber;
+ //dummy.whichactor = temp->whichactor;
+ dummy.hitpoints = temp->hitpoints;
+ dummy.ticcount = temp->ticcount;
+ dummy.obclass = (byte)(temp->obclass);
+ dummy.stateindex = GetIndexForState(temp->state);
+ dummy.shapeoffset = temp->shapeoffset;
+ dummy.dirchoosetime = temp->dirchoosetime;
+ dummy.door_to_open = temp->door_to_open;
+ dummy.targetx = temp->targettilex;
+ dummy.targety = temp->targettiley;
+ dummy.dir = (signed char)temp->dir;
+ dummy.angle = temp->angle;
+ dummy.yzangle = temp->yzangle;
+ dummy.speed = temp->speed;
+ dummy.momentumx = temp->momentumx;
+ dummy.momentumy = temp->momentumy;
+ dummy.momentumz = temp->momentumz;
+
+ dummy.temp1 = temp->temp1;
+ dummy.temp2 = temp->temp2;
+ dummy.temp3 = temp->temp3;
+ if (temp->whatever)
+ { /*if ((temp->flags & FL_USE) && (temp!=player))
+ {dummy.whateverindex = (GetIndexForState((statetype*)(temp->whatever))|SG_PSTATE);
+ if ((dummy.whateverindex < 0) && (dummy.whateverindex != -1))
+ Error("Bad actor whatever save value of %d\n",dummy.whateverindex);
+ }
+ else*/
+ { tact = (objtype*)(temp->whatever);
+ if (tact->which == ACTOR)
+ dummy.whateverindex = tact->whichactor;
+ else
+ { statobj_t *tstat;
+
+ tstat = (statobj_t*)(temp->whatever);
+ dummy.whateverindex = (tstat->whichstat|SG_PSTAT);
+
+ }
+ }
+ }
+ else
+ dummy.whateverindex = -1;
+
+
+ if (temp->target)
+ { tact = (objtype*)(temp->target);
+ if (tact->which == ACTOR)
+ { dummy.targetindex = tact->whichactor;
+ Debug("\nsave actor %d, type %d has target %d",temp->whichactor,temp->obclass,tact->whichactor);
+ }
+ else if (tact->which == SPRITE)
+ { statobj_t *tstat;
+
+ tstat = (statobj_t*)(temp->target);
+ dummy.targetindex = (tstat->whichstat|SG_PSTAT);
+ }
+ else // It must be a push wall, and we don't save that
+ dummy.targetindex=-1;
+ }
+ else
+ dummy.targetindex = -1;
+
+
+ memcpy(tptr,&(dummy.x),sizeof(saved_actor_type));
+ tptr += sizeof(saved_actor_type);
+
+ }
+
+}
+
+
+
+void LoadActors(byte *buffer,int size)
+{
+ int numactors,i,playerindex;
+ saved_actor_type dummy;
+ objtype *temp;
+ short *targetindices,*whateverindices;
+
+ InitActorList();
+
+ memcpy(MISCVARS,buffer,sizeof(misc_stuff));
+ buffer += sizeof(misc_stuff);
+
+ memcpy(&numplayers,buffer,sizeof(numplayers));
+ buffer += sizeof(numplayers);
+
+ memcpy(&playerindex,buffer,sizeof(playerindex));
+ buffer += sizeof(playerindex);
+
+ size -= (sizeof(misc_stuff)+sizeof(numplayers)+sizeof(playerindex));
+ numactors = size/sizeof(saved_actor_type);
+
+
+ objlist = (objtype**)SafeMalloc(numactors*sizeof(objtype*));
+ targetindices = (short*)SafeMalloc(numactors*sizeof(short));
+ whateverindices = (short*)SafeMalloc(numactors*sizeof(short));
+
+ for(i=0; i<numactors; i++)
+ {
+ targetindices[i] = 0;
+ whateverindices[i] = 0;
+ objlist[i] = NULL;
+ }
+
+
+ for(i=0; i<numactors; i++)
+ {
+ GetNewActor();
+ objlist[i] = new;
+ if (i < numplayers)
+ {
+ PLAYER[i]=new;
+ if (i==playerindex)
+ player=new;
+ }
+
+ memcpy(&(dummy.x),buffer,sizeof(saved_actor_type));
+
+ //new->x = dummy.x;
+ //new->y = dummy.y;
+ SetFinePosition(new,dummy.x,dummy.y);
+ SetVisiblePosition(new,dummy.x,dummy.y);
+ new->z = dummy.z;
+ new->flags = dummy.flags;
+ new->hitpoints = dummy.hitpoints;
+ new->ticcount = dummy.ticcount;
+ new->shapeoffset = dummy.shapeoffset;
+ new->obclass = (classtype)(dummy.obclass);
+
+
+ new->state = GetStateForIndex(dummy.stateindex);
+ if (new->state == &s_superparticles)
+ PARTICLE_GENERATOR = new;
+ else if
+ (new->state->think == T_SlideDownScreen)
+ SCREENEYE = new;
+ new->dirchoosetime = dummy.dirchoosetime;
+ new->door_to_open = dummy.door_to_open;
+ new->targettilex = dummy.targetx;
+ new->targettiley = dummy.targety;
+ new->dir = (dirtype)(dummy.dir);
+ new->angle = dummy.angle;
+ new->yzangle = dummy.yzangle;
+ new->speed = dummy.speed;
+ new->momentumx = dummy.momentumx;
+ new->momentumy = dummy.momentumy;
+ new->momentumz = dummy.momentumz;
+ new->temp1 = dummy.temp1;
+ new->temp2 = dummy.temp2;
+ new->temp3 = dummy.temp3;
+ if (dummy.whateverindex == -1)
+ new->whatever = NULL;
+
+ else if (dummy.whateverindex & SG_PSTAT)
+ new->whatever = GetStaticForIndex(dummy.whateverindex & ~SG_PSTAT);
+ else
+ whateverindices[i] = dummy.whateverindex+1;
+
+
+ if (dummy.targetindex == -1)
+ new->target = NULL;
+ else if (dummy.targetindex & SG_PSTAT)
+ new->target = GetStaticForIndex(dummy.targetindex & ~SG_PSTAT);
+ else
+ {
+ targetindices[i] = dummy.targetindex+1;
+ Debug("\nload actor %d, type %d has target %d",i,new->obclass,dummy.targetindex);
+ }
+
+
+ new->areanumber = dummy.areanumber;
+ new->shapenum = new->state->shapenum + new->shapeoffset;
+ new->which = ACTOR;
+ if (new->flags & FL_ABP)
+ MakeActive(new);
+ if (new->obclass != inertobj)
+ MakeLastInArea(new);
+
+ if (!(new->flags & (FL_NEVERMARK|FL_NONMARK)))
+ actorat[new->tilex][new->tiley] = new;
+
+ PreCacheActor(new->obclass,-1);
+ buffer += sizeof(saved_actor_type);
+ }
+
+
+ // find unique links between actors,
+ // searching list AFTER all have been spawned
+
+ for(i=0; i<numactors; i++)
+ { temp=objlist[i];
+ if (whateverindices[i])
+ temp->whatever = objlist[whateverindices[i]-1];
+ if (targetindices[i])
+ temp->target = objlist[targetindices[i]-1];
+ }
+
+
+ for(temp=FIRSTACTOR; temp; temp=temp->next)
+ { if (temp->obclass == b_darksnakeobj)
+ { if (!SNAKEHEAD)
+ SNAKEHEAD = temp;
+ else if (!temp->whatever)
+ SNAKEEND = temp;
+ }
+
+ }
+
+ if (SNAKEHEAD)
+ for(temp=FIRSTACTOR; temp; temp=temp->next)
+ { if (temp->state == &s_megaexplosions)
+ EXPLOSIONS = temp;
+ }
+
+ //SafeFree(objlist);
+ SafeFree(targetindices);
+ SafeFree(whateverindices);
+
+}
+
+
+
+int RandomSign(void)
+{
+ if (GameRandomNumber("random sign",0) < 128)
+ return -1;
+ return 1;
+
+
+}
+
+
+void AddToFreeList(objtype*ob)
+{ if (!FIRSTFREE)
+ FIRSTFREE = ob;
+ else
+ { ob->prev = LASTFREE;
+ LASTFREE->next = ob;
+ }
+ LASTFREE = ob;
+
+}
+
+void RemoveFromFreeList(objtype*ob)
+{
+ if (ob == LASTFREE)
+ LASTFREE = ob->prev;
+ else
+ ob->next->prev = ob->prev;
+
+ if (ob == FIRSTFREE)
+ FIRSTFREE = ob->next;
+ else
+ ob->prev->next = ob->next;
+
+ ob->prev = NULL;
+ ob->next = NULL;
+
+}
+
+
+void MakeActive(objtype *ob)
+{ if ((ob == firstactive) || (ob->prevactive) || (ob->nextactive))
+ {
+ SoftError("\ndouble make active try");
+ //AddEndGameCommand ();
+ return;
+ }
+
+ if (!firstactive)
+ firstactive = ob;
+ else
+ { ob->prevactive = lastactive;
+ lastactive->nextactive = ob;
+ }
+ lastactive = ob;
+
+#if ((DEVELOPMENT == 1))
+#if ((LOADSAVETEST == 1))
+ if (!lastactive)
+ Debug("\nlastactive = NULL !");
+ else
+ Debug("\nlastactive = %8x",lastactive);
+
+#endif
+#endif
+}
+
+
+
+void MakeLastInArea(objtype *ob)
+{
+ if (!ValidAreanumber(ob->areanumber))
+ Error("\n ob type %s at %d,%d has illegal areanumber of %d",
+ debugstr[ob->obclass],ob->tilex,ob->tiley,ob->areanumber);
+
+
+ if ((ob == firstareaactor[ob->areanumber]) || (ob->previnarea) || (ob->nextinarea))
+ {
+ SoftError("\ndouble make last in area try");
+ //AddEndGameCommand ();
+ return;
+ }
+ if (!firstareaactor[ob->areanumber])
+ firstareaactor[ob->areanumber] = ob;
+ else
+ { ob->previnarea = lastareaactor[ob->areanumber];
+ lastareaactor[ob->areanumber]->nextinarea = ob;
+ }
+ lastareaactor[ob->areanumber] = ob;
+}
+
+
+
+void RemoveFromArea(objtype*ob)
+{
+ if (!((ob == firstareaactor[ob->areanumber]) || (ob->previnarea) || (ob->nextinarea)))
+ {
+ SoftError("\ndouble remove from area try");
+ //AddEndGameCommand ();
+ return;
+ }
+
+ if (ob == lastareaactor[ob->areanumber]) // remove from master list
+ lastareaactor[ob->areanumber] = ob->previnarea;
+ else
+ ob->nextinarea->previnarea = ob->previnarea;
+
+ if (ob == firstareaactor[ob->areanumber])
+ firstareaactor[ob->areanumber] = ob->nextinarea;
+ else
+ ob->previnarea->nextinarea = ob->nextinarea;
+
+ ob->previnarea = NULL;
+ ob->nextinarea = NULL;
+}
+
+
+void MakeInactive(objtype*ob)
+{
+ if (!ACTIVE(ob))
+// if (!((ob == firstactive) || (ob->prevactive) || (ob->nextactive)))
+ {
+ SoftError("\n trying to remove inactive object");
+ //AddEndGameCommand ();
+ return;
+ }
+
+ //if (ob->flags & FL_ABP)
+ {
+
+ if (ob == lastactive) // remove from master list
+ lastactive = ob->prevactive;
+ else
+ ob->nextactive->prevactive = ob->prevactive;
+
+ if (ob == firstactive)
+ firstactive = ob->nextactive;
+ else
+ ob->prevactive->nextactive = ob->nextactive;
+
+
+ ob->prevactive = NULL;
+ ob->nextactive = NULL;
+ }
+
+}
+
+
+
+void A_Steal(objtype*ob)
+{
+ int dx,dy,dz;
+
+ ActorMovement(ob);
+
+ dx = abs(ob->x - PLAYER[0]->x);
+ dy = abs(ob->y - PLAYER[0]->y);
+ dz = abs(ob->z - PLAYER[0]->z);
+
+ if ((dx > TOUCHDIST) || (dy > TOUCHDIST) || (dz > (TOUCHDIST >> 10)))
+ {
+ NewState(ob,&s_blitzchase1);
+ return;
+ }
+
+ if (ob->ticcount)
+ return;
+ //"Gimme That!"
+ SD_PlaySoundRTP(SD_BLITZSTEALSND,ob->x,ob->y);
+ if (PLAYER[0]->flags & FL_GASMASK)
+ {
+ PLAYER[0]->flags &= ~FL_GASMASK;
+ PLAYERSTATE[0].protectiontime = 1;
+ ob->temp3 = stat_gasmask;
+ GM_UpdateBonus (PLAYERSTATE[0].poweruptime, true);
+
+ }
+ else if(PLAYER[0]->flags & FL_BPV)
+ {
+ PLAYER[0]->flags &= ~FL_BPV;
+ PLAYERSTATE[0].protectiontime = 1;
+ ob->temp3 = stat_bulletproof;
+ GM_UpdateBonus (PLAYERSTATE[0].poweruptime, true);
+
+ }
+ else if(PLAYER[0]->flags & FL_AV)
+ {
+ PLAYER[0]->flags &= ~FL_AV;
+ PLAYERSTATE[0].protectiontime = 1;
+ ob->temp3 = stat_asbesto;
+ GM_UpdateBonus (PLAYERSTATE[0].poweruptime, true);
+
+ }
+ else if (PLAYERSTATE[0].missileweapon != -1)
+ {
+ NewState(PLAYER[0],&s_player);
+ PLAYERSTATE[0].attackframe = PLAYERSTATE[0].weaponframe = 0;
+ PLAYERSTATE[0].new_weapon = PLAYERSTATE[0].bulletweapon;
+ ob->temp3 = GetItemForWeapon(PLAYERSTATE[0].missileweapon);
+ ob->temp2 = PLAYERSTATE[0].ammo;
+ //ob->temp1 = oldpolltime;
+ PLAYERSTATE[0].ammo = -1;
+
+ if (PLAYERSTATE[0].weapon == PLAYERSTATE[0].missileweapon)
+ PLAYERSTATE[0].weapondowntics = WEAPONS[PLAYERSTATE[0].weapon].screenheight/GMOVE;
+ PLAYERSTATE[0].missileweapon = -1;
+
+ if ( SHOW_BOTTOM_STATUS_BAR() )
+ DrawBarAmmo (false);
+
+ }
+}
+
+
+void FindAddresses(void)
+{
+ int i;
+ unsigned long tstate,tfunct;
+
+ MINFUNCTION = -1l;
+ MAXFUNCTION = 0x00000000;
+ MINSTATE = -1l;
+ MAXSTATE = 0x00000000;
+
+ for(i=0; i<MAXSTATES; i++)
+ {
+ tstate = (unsigned long)(statetable[i]);
+ if (tstate < MINSTATE)
+ MINSTATE = tstate;
+
+ if (tstate > MAXSTATE)
+ MAXSTATE = tstate;
+ if (statetable[i]!=NULL)
+ {
+ tfunct = (unsigned long)(statetable[i]->think);
+ if (tfunct < MINFUNCTION)
+ MINFUNCTION = tfunct;
+
+ if (tfunct > MAXFUNCTION)
+ MAXFUNCTION = tfunct;
+ }
+ }
+}
+
+void CheckBounds(objtype*ob)
+{
+ unsigned long tstate,tfunct;
+
+ tstate = (unsigned long)(ob->state);
+ tfunct = (unsigned long)(ob->state->think);
+
+ if ((tfunct < MINFUNCTION) || (tfunct > MAXFUNCTION) ||
+ (tstate < MINSTATE) || (tstate > MAXSTATE))
+ {
+ if (tfunct < MINFUNCTION)
+ Error("%s has thinking function less than MINFUNCTION",debugstr[ob->obclass]);
+
+ else if (tfunct > MAXFUNCTION)
+ Error("%s has thinking function greater than MAXFUNCTION",debugstr[ob->obclass]);
+
+ if (tstate < MINSTATE)
+ Error("%s has state less than MINSTATE",debugstr[ob->obclass]);
+
+ else if (tstate > MAXSTATE)
+ Error("%s has state greater than MAXSTATE",debugstr[ob->obclass]);
+
+ }
+
+
+}
+
+/*************************************************************/
+
+
+/*
+=====================
+=
+= DoActor
+=
+=====================
+*/
+
+void DoActor (objtype *ob)
+{
+ void (*think)(objtype *);
+ int door;
+
+
+// for(i=0;i<tics;i++)
+// {
+
+#if (BNACRASHPREVENT == 1)//
+ if (ob->state == 0) {
+ return;
+ }
+#endif
+ ApplyGravity(ob);
+ M_CheckDoor(ob);
+ M_CheckBossSounds(ob);
+ if ((ob->obclass >= b_darianobj) &&
+ (ob->obclass < b_darksnakeobj) &&
+ MISCVARS->REDTIME
+ )
+ {
+ MISCVARS->REDTIME --;
+ MISCVARS->redindex = (MISCVARS->REDTIME & 15);
+ }
+
+ if (ob->obclass == playerobj)
+ ControlPlayerObj(ob);
+
+ think = ob->state->think;
+ if (think)
+ {
+ //CheckBounds(ob);
+ think (ob);
+
+ if (!ob->state)
+ {
+ RemoveObj (ob);
+ return;
+ }
+ }
+
+ if (ob->ticcount)
+ ob->ticcount --;
+
+ else
+ {
+ if (!(ob->state->next))
+ {
+ RemoveObj (ob);
+ return;
+ }
+ else
+ NewState(ob,ob->state->next);
+ }
+
+
+ if (ob->flags&FL_NEVERMARK)
+ return;
+
+ if ((ob->flags&FL_NONMARK) && actorat[ob->tilex][ob->tiley])
+ return;
+
+ actorat[ob->tilex][ob->tiley] = ob;
+}
+
+
+
+
+
+void ApplyGravity(objtype *ob)
+{
+ int oldmomentumz;
+
+ if (((ob->momentumz) || (ob->z != nominalheight)) &&
+ (ob->obclass > playerobj) &&
+ ((ob->obclass <= roboguardobj) || (ob->obclass == collectorobj) ||
+ (ob->obclass == b_heinrichobj)) &&
+ (ob->state->think != T_Stand)
+ )
+ {
+ ob->z += (ob->momentumz>>16);
+ ob->momentumz += GRAVITY;
+ if (ob->z >= nominalheight)
+ {
+ ob->z = nominalheight;
+ oldmomentumz = ob->momentumz;
+ ob->momentumz = 0;
+ if (oldmomentumz > 2*GRAVITY)
+ {
+ if (ob->flags & FL_DYING)
+ SD_PlaySoundRTP(ACTORTHUDSND,ob->x,ob->y);
+ else
+ {
+ int oldviolence = gamestate.violence;
+
+ SD_PlaySoundRTP(ACTORLANDSND,ob->x,ob->y);
+ gamestate.violence = vl_low;
+ BeginEnemyHurt(ob);
+ gamestate.violence = oldviolence;
+ }
+ }
+ if (ob->flags&FL_FALLINGOBJECT)
+ {
+ RemoveObj(ob);
+ return;
+ }
+ }
+ }
+}
+
+
+
+/*
+===================
+=
+= NewState
+=
+= Changes ob to a new state, setting ticcount to the max for that state
+=
+===================
+*/
+
+void NewState (objtype *ob, statetype *newstate)
+{
+ if (DoPanicMapping() &&
+ ((newstate == &s_explosion1) ||
+ (newstate == &s_grexplosion1) ||
+ (newstate == &s_staticexplosion1)
+ )
+ )
+ ob->state = &s_altexplosion1;
+ else {
+#if (BNACRASHPREVENT == 1)//crashed here when oscuro and larves were all killed
+ if (ob == 0) {
+ return;
+ }
+#endif
+ ob->state = newstate;
+ }
+ SetVisiblePosition(ob,ob->x,ob->y);
+#if (BNACRASHPREVENT == 1)
+ if (ob->state == 0) {
+ return;
+ }
+#endif
+
+ ob->ticcount = (ob->state->tictime>>1);
+ ob->shapenum = ob->state->shapenum + ob->shapeoffset;
+
+}
+
+
+/*
+=========================
+=
+= InitActorList
+=
+= Call to clear out the actor object lists returning them all to the free
+= list. Allocates a special spot for the player.
+=
+=========================
+*/
+
+
+
+void InitActorList (void)
+{
+ //====== NETWORK STUFF =======================================
+ memset(&DEADPLAYER[0],0,sizeof(DEADPLAYER));
+ NUMDEAD = 0;
+
+
+
+ //======= NULLIFY GLOBAL POINTERS ============================
+
+ LASTACTOR=FIRSTACTOR=NULL;
+ FIRSTFREE = LASTFREE = NULL;
+ firstactive = lastactive = NULL;
+ memset(firstareaactor,0,sizeof(firstareaactor));
+ memset(lastareaactor,0,sizeof(lastareaactor));
+ NUMSPAWNLOCATIONS = 0;
+
+
+ PARTICLE_GENERATOR = NULL;
+ EXPLOSIONS = NULL;
+ SNAKEEND=SNAKEHEAD=NULL;
+ SCREENEYE = NULL;
+ PLAYER0MISSILE = NULL;
+
+ //============================================================
+
+ objcount = 0;
+ memset(MISCVARS,0,sizeof(misc_stuff));
+ MISCVARS->gibgravity = -1;
+ MISCVARS->gibspeed = NORMALGIBSPEED;
+
+ memset(&RANDOMACTORTYPE[0],0,sizeof(RANDOMACTORTYPE));
+ FindAddresses();
+ MissileSound = true;
+ Masterdisk = false;
+
+}
+
+//===========================================================================
+
+/*
+=========================
+=
+= GetNewActor
+=
+= Sets the global variable new to point to a free spot in objlist.
+= The free spot is inserted at the end of the liked list
+=
+= When the object list is full, the caller can either have it bomb out ot
+= return a dummy object pointer that will never get used
+=
+=========================
+*/
+
+void GetNewActor (void)
+{
+ objtype *temp;
+
+ if (!FIRSTFREE)
+ {
+ temp = (objtype*)Z_LevelMalloc(sizeof(objtype),PU_LEVELSTRUCT,NULL);
+ //SoftError("\nMalloc-ing actor");
+ //if (insetupgame)
+ // SoftError("in setup");
+ }
+
+ else
+ {
+ temp = LASTFREE;
+ //SoftError("\nfree actor available");
+ RemoveFromFreeList(LASTFREE);
+ }
+
+ if (temp)
+ {
+ new = temp;
+ memset(new,0,sizeof(*new));
+
+ if (FIRSTACTOR)
+ {
+ new->prev = LASTACTOR;
+ LASTACTOR->next = new;
+ }
+ else
+ FIRSTACTOR = new;
+ LASTACTOR = new;
+
+ new->door_to_open = -1;
+ new->soundhandle = -1;
+ objcount ++;
+ }
+ else
+ Error("Z_LevelMalloc failed in GetNewActor");
+}
+
+
+
+
+//===========================================================================
+
+
+
+
+/*
+=========================
+=
+= RemoveObj
+=
+= Add the given object back into the free list, and unlink it from it's
+= neighbors
+=
+=========================
+*/
+
+
+void RemoveObj (objtype *gone)
+{
+ if (gone == PLAYER[0])
+ Error ("RemoveObj: Tried to remove the player!");
+
+ gone->state=NULL;
+
+ MakeInactive(gone);
+
+ if (gone->obclass!=inertobj) {
+ if (ValidAreanumber(gone->areanumber))
+ RemoveFromArea(gone);
+ else
+ Error("tried to remove an instance of %s with invalid areanumber %d",debugstr[gone->obclass],gone->areanumber);
+ }
+
+ if (gone == LASTACTOR)
+ LASTACTOR = gone->prev;
+ else
+ gone->next->prev = gone->prev;
+
+ if (gone == FIRSTACTOR)
+ FIRSTACTOR = gone->next;
+ else
+ gone->prev->next = gone->next;
+
+ if (gone == EXPLOSIONS)
+ EXPLOSIONS = NULL;
+ gone->next = NULL;
+ gone->prev = NULL;
+// SoftError("\nremoving instance of %s",debugstr[gone->obclass]);
+ if (actorat[gone->tilex][gone->tiley] == (void*)gone)
+ actorat[gone->tilex][gone->tiley] = NULL;
+
+ gone->flags |= FL_NEVERMARK;
+
+ if (gone->flags & FL_TARGET)
+ UnTargetActor(gone);
+
+ //Add_To_Delete_Array(gone);
+ //Z_Free(gone);
+ AddToFreeList(gone);
+
+ objcount--;
+}
+
+
+//============== World Physics Model Functions =========================
+
+
+void ParseMomentum(objtype *ob,int angle)
+{
+ ob->momentumx += FixedMul(ob->speed,costable[angle]);
+ ob->momentumy -= FixedMul(ob->speed,sintable[angle]);
+}
+
+void Set_3D_Momenta(objtype *ob, int speed, int theta, int phi)
+{
+ int _2Ddiag;
+
+ ob->momentumz = -FixedMul(speed,sintable[phi]);
+ _2Ddiag = FixedMul(speed,costable[phi]);
+ ob->momentumx = FixedMul(_2Ddiag,costable[theta]);
+ ob->momentumy = -FixedMul(_2Ddiag,sintable[theta]);
+
+
+}
+
+
+int AngleBetween(objtype *source,objtype*target)
+{
+ int dx,dy;
+
+ dx = target->x - source->x;
+ dy = source->y - target->y;
+ return (atan2_appx(dx,dy));
+}
+
+
+void GetMomenta(objtype *target, objtype *source, int *newmomx,
+ int *newmomy, int *newmomz, int magnitude
+ )
+{
+ int angle,dx,dy,dz,yzangle,xydist,_2Ddiag;
+
+ dx = target->x - source->x;
+ dy = source->y - target->y;
+ dz = source->z - target->z;
+ xydist = FindDistance(dx,dy);
+ angle = atan2_appx(dx,dy);
+ yzangle = atan2_appx(xydist,(dz<<10));
+ _2Ddiag = FixedMul(magnitude,costable[yzangle]);
+
+ *newmomz = -FixedMul(magnitude,sintable[yzangle]);
+ *newmomx = FixedMul(_2Ddiag,costable[angle]);
+ *newmomy = -FixedMul(_2Ddiag,sintable[angle]);
+}
+
+//=======================================================================
+
+
+
+
+
+void SpawnNewObj (unsigned tilex, unsigned tiley, statetype *state, classtype which)
+{
+ int newarea;
+
+ GetNewActor ();
+ new->obclass = which;
+ SetTilePosition(new,tilex,tiley);
+ SetVisiblePosition(new,new->x,new->y);
+ new->dir = nodir;
+ new->which = ACTOR;
+ if (FirstExplosionState(state))
+ new->flags |= (FL_NEVERMARK|FL_NOFRICTION);
+
+ if ((which != inertobj) && (which != diskobj))
+ actorat[tilex][tiley] = new;
+
+ newarea = AREANUMBER(tilex,tiley);
+ if ((which <= springobj) && (which != inertobj))
+ {
+ if (ValidAreanumber(newarea))
+ new->areanumber = newarea;
+ else
+ Error("illegal initial areanumber of %d for actor type %s"
+ "trying to spawn at %d, %d",newarea,debugstr[which],tilex,tiley);
+ }
+ else
+ new->areanumber = newarea;
+
+ if ((which != inertobj) && (!Masterdisk))
+ MakeLastInArea(new);
+ NewState(new,state);
+ new->z = nominalheight;
+ if (which==springobj)
+ new->z+=2;
+
+}
+
+
+//====================================================================
+
+void ConsiderAlternateActor(objtype *ob,classtype which)
+{
+ if (((which >= lowguardobj) && (which <= blitzguardobj)) ||
+ (which == dfiremonkobj))
+ { if (GameRandomNumber("SpawnStand",which) < 128)
+ { switch(which)
+ {
+ case lowguardobj:
+ ob->shapeoffset = W_GetNumForName("MARSHOO1") -
+ W_GetNumForName("LWGSHOO1");
+ break;
+ case highguardobj:
+ ob->shapeoffset = W_GetNumForName("HIGSHOO1") -
+ W_GetNumForName("HG2SHOO1");
+ break;
+ case overpatrolobj:
+ ob->shapeoffset = W_GetNumForName("PATSHOO1") -
+ W_GetNumForName("OBPSHOO1");
+ break;
+ case strikeguardobj:
+ ob->shapeoffset = W_GetNumForName("XYGSHOO1") -
+ W_GetNumForName("ANGSHOO1");
+ break;
+ /*case blitzguardobj:
+ altstartlabel = "WIGSHOO1";
+ new->shapeoffset = 80;
+ break;*/
+ case dfiremonkobj:
+ ob->shapeoffset = W_GetNumForName("MRKKSH1") -
+ W_GetNumForName("ALLKSH1");
+ break;
+ default:
+ ;
+ }
+ }
+
+ }
+
+ //if (new->shapeoffset)
+ // {if (W_CheckNumForName(altstartlabel) == -1)
+ // new->shapeoffset = 0;
+ // }
+
+}
+
+
+
+
+
+/*
+===================
+=
+= StandardEnemyInit
+=
+===================
+*/
+
+void StandardEnemyInit(objtype *ob,int dir)
+{
+ int zoffset;
+
+ if ((ob->obclass == deathmonkobj) || (ob->obclass == dfiremonkobj))
+ ob->temp2 = DRAINTIME;
+
+ else if ((ob->obclass == highguardobj) || (ob->obclass == triadenforcerobj))
+ ob->flags |= FL_HASAUTO;
+
+ ob->hitpoints = starthitpoints[gamestate.difficulty][ob->obclass];
+ ob->dir = dir*2;
+ ob->flags |= (FL_SHOOTABLE|FL_BLOCK);
+ ob->speed = ENEMYRUNSPEED;
+ ob->dirchoosetime = 0;
+ ob->door_to_open = -1;
+
+ zoffset = MAPSPOT(ob->tilex,ob->tiley,2);
+ if ((zoffset&0xff00)==0xb000)
+ Set_NewZ_to_MapValue(&(ob->z),zoffset,"standard enemy",ob->tilex,ob->tiley);
+ else
+ ob->z = PlatformHeight(ob->tilex,ob->tiley);
+
+}
+
+
+//LT added
+//if under ext actor options BLITZ RANDOM WEP is enabled, this will decide what missile weapon a blitzguard will get
+void OutfitBlitzguardWith(objtype *ob)
+{
+ int number = GameRandomNumber("outfitting blitzguard",0);
+
+ if (number < 100)
+ {
+ ob->temp3 = stat_bazooka;
+ ob->temp2 = 3;
+ }
+ else if (number > 100 && number <= 150)
+ {
+ ob->temp3 = stat_heatseeker;
+ ob->temp2 = 3;
+ }
+ else if (number > 150 && number <= 200)
+ {
+ ob->temp3 = stat_drunkmissile;
+ ob->temp2 = 3;
+ }
+ else if (number > 200 && number <= 225)
+ {
+ ob->temp3 = stat_firewall;
+ ob->temp2 = 3;
+ }
+ else if (number > 225 && number <= 250)
+ {
+ ob->temp3 = stat_firebomb;
+ ob->temp2 = 3;
+ }
+#if (SHAREWARE == 0)
+ else if (number > 250)
+ {
+ //dark staff
+ ob->temp3 = stat_kes;
+ ob->temp2 = 3;
+ }
+ //TODO: Figure out a way to allow biltzguards to attack with excalibat w/o crashing the game
+
+#endif
+ else
+ {
+ ob->temp3 = stat_bazooka;
+ ob->temp2 = 3;
+ }
+}
+
+extern boolean allowBlitzMoreMissileWeps;
+
+//This decides if a Blitzguard (green dude) gets a rocket launcher
+void ConsiderOutfittingBlitzguard(objtype *ob)
+{
+ //WILEYBLITZCHANCE is defined to be 20
+ if ((GameRandomNumber("wiley blitzguard",0) < WILEYBLITZCHANCE) &&
+ (gamestate.difficulty >= gd_medium)
+ )
+ {
+ if (allowBlitzMoreMissileWeps)
+ {
+ OutfitBlitzguardWith(ob);
+ }
+ else {
+ ob->temp3 = stat_bazooka;
+ ob->temp2 = 3;
+ }
+ }
+}
+
+
+/*
+===============
+=
+= SpawnStand
+=
+===============
+*/
+
+
+void SpawnStand (classtype which, int tilex, int tiley, int dir, int ambush)
+{ statetype *temp;
+
+#if (SHAREWARE == 1)
+ switch(which)
+ {
+ case overpatrolobj:
+ case wallopobj:
+ case deathmonkobj:
+ case dfiremonkobj:
+ case b_darianobj:
+ case b_heinrichobj:
+ case b_darkmonkobj:
+ Error("\n%s actor at %d,%d not allowed in shareware !",debugstr[which],tilex,tiley);
+ break;
+ default:
+ ;
+ }
+
+
+
+#endif
+
+ if ((which == lowguardobj) && (GameRandomNumber("SpawnStand",which) < 128))
+ which = blitzguardobj;
+
+
+ if ((temp = UPDATE_STATES[STAND][which-lowguardobj]) != NULL)
+ {
+ SpawnNewObj(tilex,tiley,temp,which);
+ if (!loadedgame)
+ gamestate.killtotal++;
+
+
+ if (ambush)
+ new->flags |= FL_AMBUSH;
+
+
+#if 0
+ if (gamestate.Product == ROTT_SUPERCD)
+ ConsiderAlternateActor(new,which);
+#endif
+
+ StandardEnemyInit(new,dir);
+
+ if (which == b_darkmonkobj)
+ {
+ new->flags |= (FL_NOFRICTION);//|FL_INVULNERABLE);
+ new->speed = ENEMYRUNSPEED*2;
+ }
+
+ if (which == blitzguardobj)
+ ConsiderOutfittingBlitzguard(new);
+
+
+ if ((new->obclass >= lowguardobj) && (new->obclass <= dfiremonkobj))
+ RANDOMACTORTYPE[new->obclass]++;
+
+ if (MAPSPOT(tilex,tiley,2) == 0xdead)
+ {
+ new->flags |= FL_KEYACTOR;
+ MISCVARS->KEYACTORSLEFT++;
+ }
+
+ PreCacheActor(which,0);
+ }
+//else
+ //Error("NULL initialization error");
+}
+
+
+
+
+
+/*
+===============
+=
+= SpawnPatrol
+=
+===============
+*/
+
+void SpawnPatrol (classtype which, int tilex, int tiley, int dir)
+{ statetype *temp;
+ int path=PATH;
+#if 0
+ if (gamestate.Product == ROTT_SUPERCD)
+ char *altstartlabel;
+#endif
+
+
+
+#if (SHAREWARE==1)
+ switch(which)
+ {
+ case overpatrolobj:
+ case wallopobj:
+ case deathmonkobj:
+ case dfiremonkobj:
+ case b_darianobj:
+ case b_heinrichobj:
+ case b_darkmonkobj:
+ Error("\n%s actor at %d,%d not allowed in shareware !",debugstr[which],tilex,tiley);
+ break;
+ default:
+ ;
+ }
+
+#endif
+
+ if ((which == lowguardobj) && (GameRandomNumber("SpawnStand",which) < 128))
+ which = blitzguardobj;
+
+
+
+
+ if ((temp= UPDATE_STATES[path][(int)(which-lowguardobj)]) != NULL)
+ {
+ SpawnNewObj(tilex,tiley,temp,which);
+
+ if (!loadedgame)
+ gamestate.killtotal++;
+
+
+#if 0
+ if (gamestate.Product == ROTT_SUPERCD)
+ ConsiderAlternateActor(new,which);
+#endif
+
+ StandardEnemyInit(new,dir);
+
+ if ((which == wallopobj) || (which == roboguardobj))
+ { new->flags |= FL_NOFRICTION;
+ //new->flags &= ~FL_SHOOTABLE;
+ new->dir <<= 1;
+ ParseMomentum(new,dirangle16[new->dir]);
+ }
+ else
+ ParseMomentum(new,dirangle8[new->dir]);
+
+
+ if (which == blitzguardobj)
+ ConsiderOutfittingBlitzguard(new);
+
+
+ if (MAPSPOT(tilex,tiley,2) == 0xdead)
+ { new->flags |= FL_KEYACTOR;
+ MISCVARS->KEYACTORSLEFT++;
+ }
+
+ PreCacheActor(which,0);
+ }
+
+}
+
+
+
+
+//==========================================================================
+
+
+
+void SpawnDisk(int tilex, int tiley, int type, boolean master)
+{ int zoffset;
+
+
+
+ if (master == true)
+ {
+ Masterdisk = true;
+ SpawnNewObj(tilex,tiley,&s_diskmaster,diskobj);
+ Masterdisk = false;
+ new->flags |= FL_MASTER;
+ new->momentumz = -(DISKMOMZ << 16);
+ new->flags |= FL_SYNCED;
+ new->flags |= FL_NEVERMARK;
+ new->temp1 = 1;
+ //RemoveFromArea(new);
+
+ }
+
+ else
+ {
+ if (!type)
+ {
+ SpawnNewObj(tilex,tiley,&s_elevdisk,diskobj);
+ new->momentumz = -(DISKMOMZ << 16);
+ //new->flags |= FL_SYNCED;
+ zoffset = MAPSPOT(tilex,tiley,2);
+ if ((zoffset&0xff00)==0xb000)
+ Set_NewZ_to_MapValue((fixed*)(&(new->temp2)),zoffset,"elev disk",tilex,tiley);
+ else
+ new->temp2 = 32;
+ new->temp1 = 1;
+ }
+ else
+ {
+ SpawnNewObj(tilex,tiley,&s_pathdisk,diskobj);
+ zoffset = MAPSPOT(tilex,tiley,2);
+ if ((zoffset&0xff00)==0xb000)
+ Set_NewZ_to_MapValue((fixed*)(&(new->z)),zoffset,"path disk",tilex,tiley);
+
+ new->dir = (type-1) << 1;
+ new->speed = 0x1000;
+
+ //ParseMomentum(new,dirangle8[new->dir]);
+ }
+ actorat[tilex][tiley] = NULL;
+ new->flags |= FL_BLOCK;
+ new->flags |= (FL_NOFRICTION|FL_ACTIVE|FL_NEVERMARK);
+ }
+}
+
+
+
+
+objtype* DiskAt(int tilex,int tiley)
+{ int area;
+ objtype *temp;
+ statobj_t *tstat;
+
+ area = AREANUMBER(tilex,tiley);
+ for(temp = firstareaactor[area]; temp; temp = temp->nextinarea)
+ { if ((temp->tilex != tilex) || (temp->tiley != tiley) ||
+ (temp->obclass != diskobj))
+ continue;
+ return temp;
+
+ }
+
+ for(tstat = firstactivestat; tstat; tstat = tstat->nextactive)
+ {
+ if ((tstat->tilex != tilex) || (tstat->tiley != tiley) ||
+ (tstat->itemnumber != stat_disk))
+ continue;
+ return (objtype*)tstat;
+ }
+
+
+ return NULL;
+
+}
+
+
+void SetElevatorDiskVariables(objtype *ob,int newz, int newmomentumz,
+ int newtemp1,int newtemp3,int newdirchoose)
+{
+ ob->z = newz;
+ ob->momentumz = newmomentumz;
+ ob->temp1 = newtemp1;
+ ob->temp3 = newtemp3;
+ ob->dirchoosetime = newdirchoose;
+}
+
+
+void T_ElevDisk(objtype*ob)
+{
+ objtype *temp = (objtype*)(actorat[ob->tilex][ob->tiley]);
+ objtype *master;
+
+ if (ob->flags & FL_MASTER)
+ goto masterlabel;
+
+ master = (objtype*)(ob->target);
+ if (!master)
+ Error("disk without master !");
+
+
+ //SoftError("\n ob->z:%d %s, master z:%d",ob->z,
+ // (ob->flags & FL_SYNCED)?("SYNCED"):("UNSYNCED"),master->z);
+
+
+ if (M_ISACTOR(temp) && (temp != ob) && (!(temp->flags & FL_DYING)))
+ {
+ int dz = abs(ob->z - temp->z),
+ dx = abs(ob->x - temp->x),
+ dy = abs(ob->y - temp->y);
+
+ if ((dx < 0x7000) && (dy < 0x7000) && (dz < 68) && (temp->z > ob->z))
+ {
+ ob->flags &= ~FL_SYNCED;
+ return;
+ }
+ }
+
+ if (master && (!(ob->flags & FL_SYNCED)))
+ {
+ int dz;
+
+ dz = abs(master->z - ob->z);
+ if ((dz > 0) && (dz < 8))
+ {
+ SetElevatorDiskVariables(ob,master->z,master->momentumz,master->temp1,
+ master->temp3,master->dirchoosetime);
+ ob->flags |= FL_SYNCED;
+ //return;
+ }
+ return;
+ }
+
+
+masterlabel:
+
+ if (ob->dirchoosetime)
+ {
+ ob->dirchoosetime --;
+ return;
+ }
+
+
+ if (ob->temp1) // moving
+ {
+ ob->z += (ob->momentumz >> 16);
+ if (ob->momentumz > 0) // down
+ {
+ if (ob->z >= nominalheight + 40 + DISKMOMZ)
+ SetElevatorDiskVariables(ob,ob->z - (ob->momentumz>>16),0,0,0,35);
+ }
+ else
+ {
+ if (ob->z < ob->temp2) // temp2 has max height
+ SetElevatorDiskVariables(ob,ob->z - (ob->momentumz>>16),0,0,1,35);
+ }
+ }
+ else
+ {
+ if (ob->temp3)
+ ob->momentumz = (DISKMOMZ << 16);
+ else
+ ob->momentumz = -(DISKMOMZ << 16);
+ ob->temp1 = 1;
+ }
+}
+
+
+
+
+void SpawnInertActor(int newx,int newy, int newz)
+{
+ GetNewActor ();
+ MakeActive(new);
+
+ new->obclass = inertobj;
+ new->which = ACTOR;
+ SetFinePosition(new,newx,newy);
+ SetVisiblePosition(new,new->x,new->y);
+ new->z = newz;
+ new->dir = 0;
+ new->speed = 0;
+ new->flags = (FL_NEVERMARK|FL_ABP);
+
+}
+
+
+
+
+#if (SHAREWARE == 0)
+void SpawnGroundExplosion(int x, int y, int z)
+{
+ SpawnInertActor(x,y,z);
+ NewState(new,&s_grexplosion1);
+ new->temp2 = GameRandomNumber("SpawnGroundExplosion",0)>>2;
+
+}
+#endif
+
+void SpawnSlowParticles(int which, int numgibs, int x,int y,int z)
+{ objtype *prevlast,*temp;
+ int tilex,tiley;
+
+ tilex = x>>16;
+ tiley = y>>16;
+
+ SpawnNewObj(tilex,tiley,&s_gibs1,inertobj);
+ SetFinePosition(new,x,y);
+ SetVisiblePosition(new,x,y);
+ prevlast = new;
+ prevlast->flags |= FL_ABP;
+ MakeActive(prevlast);
+ SpawnParticles(new,which,numgibs);
+
+ for(temp = prevlast->next; temp; temp=temp->next)
+ { temp->z = z;
+ temp->momentumx >>= 1;
+ temp->momentumy >>= 1;
+ temp->momentumz >>= 1;
+ }
+ RemoveObj(prevlast);
+
+}
+
+
+void ResolveDoorSpace(int tilex,int tiley)
+{
+ statobj_t* tstat,*temp;
+
+ for(tstat = firstactivestat; tstat;)
+ {
+ temp = tstat->nextactive;
+
+ if (tstat->flags & FL_DEADBODY)
+ {
+ if ((tstat->tilex == tilex) && (tstat->tiley == tiley))
+ {
+ if ((tstat->flags & FL_DEADBODY) && (tstat->linked_to != -1))
+ DEADPLAYER[tstat->linked_to] = NULL;
+ RemoveStatic(tstat);
+ if (tstat->flags & FL_DEADBODY)
+ SpawnSlowParticles(GUTS,8,tstat->x,tstat->y,tstat->z);
+ else
+ SpawnSlowParticles(gt_sparks,8,tstat->x,tstat->y,tstat->z);
+ SD_PlaySoundRTP(SD_ACTORSQUISHSND,tstat->x,tstat->y);
+ }
+ }
+ tstat = temp;
+ }
+}
+
+
+void SpawnSpear(int tilex,int tiley,int up)
+{
+ int count,i;
+ statetype *tstate;
+
+
+ if (BATTLEMODE && (!gamestate.BattleOptions.SpawnDangers))
+ return;
+
+ if (!up)
+ {
+#if (SHAREWARE == 1)
+ Error("\ndownspear at %d,%d in shareware!",tilex,tiley);
+#else
+ SpawnNewObj(tilex,tiley,&s_speardown1,spearobj);
+ new->z = 0;
+#endif
+ }
+ else
+
+ SpawnNewObj(tilex,tiley,&s_spearup1,spearobj);
+
+ count = (int)(GameRandomNumber("Spawn Spear",0) % 16);
+ for(i=0,tstate = new->state; i<count; i++,tstate=tstate->next);
+ NewState(new,tstate);
+
+ PreCacheActor(spearobj,up);
+ new->flags |= (FL_ABP);//|FL_INVULNERABLE);
+ MakeActive(new);
+}
+
+
+
+void SpawnSpring(int tilex,int tiley)
+{
+ int iconvalue;
+
+ iconvalue = MAPSPOT(tilex,tiley,2);
+ if (iconvalue == 3)
+ {
+ SpawnNewObj(tilex,tiley,&s_autospring1,springobj);
+ new->ticcount = (GameRandomNumber("Spawn Spring",0) % new->ticcount)+1;
+ new->temp1 = iconvalue;
+ }
+ else
+ {
+ SpawnNewObj(tilex,tiley,&s_spring1,springobj);
+ if (iconvalue == 2)
+ new->temp1 = iconvalue;
+ }
+
+ PreCacheActor(springobj,0);
+ new->flags &= ~(FL_SHOOTABLE|FL_BLOCK);
+}
+
+
+
+
+void T_Spring(objtype*ob)
+{
+ objtype *temp;
+ int op,dx,dy,dz;
+
+
+ if ((ob->state->condition & SF_DOWN) && (ob->temp1))
+ {
+ if (ob->ticcount)
+ return;
+ ob->shapenum++;
+ TurnActorIntoSprite(ob);
+ return;
+ }
+
+ for(temp=firstareaactor[ob->areanumber]; temp; temp=temp->nextinarea)
+ {
+ if (temp == ob)
+ continue;
+
+ if (temp->obclass >= roboguardobj)
+ continue;
+
+ dx = abs(ob->x-temp->x);
+ dy = abs(ob->y-temp->y);
+ dz = abs(ob->z-temp->z);
+ if ((dx > ACTORSIZE+0x2800) || (dy > ACTORSIZE+0x2800) || (dz > 40))
+ continue;
+ if (!temp->momentumz)
+ {
+ op = FixedMul(GRAVITY,(temp->z-5)<<16) << 1;
+ temp->momentumz = -FixedSqrtHP(op);
+ SD_PlaySoundRTP(SD_SPRINGBOARDSND,ob->x,ob->y);
+ }
+ }
+}
+
+
+
+void T_Count(objtype*ob)
+{
+ int index;
+ wall_t* tswitch;
+ touchplatetype *temp;
+ objtype* tempactor;
+
+ if (ob->dirchoosetime)
+ {
+ ob->dirchoosetime --;
+ if (ob->dirchoosetime>980)
+ MISCVARS->gasindex=((1050-ob->dirchoosetime)<<4)/70;
+ else if (ob->dirchoosetime<35)
+ MISCVARS->gasindex=(ob->dirchoosetime<<4)/35;
+ if (ob->temp3)
+ {
+ ob->temp3 --;
+ if (ob->temp3 & 1)
+ SD_PlaySoundRTP(SD_GASHISSSND,ob->x,ob->y);
+ }
+ else
+ {
+ ob->temp3 = 105;
+ for(tempactor=firstareaactor[ob->areanumber]; tempactor; tempactor=tempactor->nextinarea)
+ {
+ if (tempactor == ob)
+ continue;
+ if (!(tempactor->flags & FL_SHOOTABLE))
+ continue;
+ if (tempactor->obclass != playerobj)
+ {
+ if ((tempactor->obclass >= lowguardobj) &&
+ (tempactor->obclass <= dfiremonkobj))
+ {
+ int oldviolence = gamestate.violence;
+
+ gamestate.violence = vl_low;
+ DamageThing(tempactor,EnvironmentDamage(ob));
+ Collision(tempactor,ob,-(tempactor->momentumx),-(tempactor->momentumy));
+ gamestate.violence = oldviolence;
+
+ }
+ }
+ else if (!(tempactor->flags & FL_GASMASK))
+ {
+ DamageThing(tempactor,EnvironmentDamage(ob));
+ Collision(tempactor,ob,0,0);
+ M_CheckPlayerKilled(tempactor);
+ }
+ }
+ }
+ }
+
+ else
+ {
+ int i;
+ playertype *pstate;
+
+ for(i=0; i<numplayers; i++)
+ {
+ M_LINKSTATE(PLAYER[i],pstate);
+ PLAYER[i]->flags &= ~FL_GASMASK;
+ pstate->protectiontime = 1;
+ }
+
+ NewState(ob,&s_gas1);
+ SD_PlaySoundRTP(SD_GASENDSND,ob->x,ob->y);
+ ob->flags &= ~FL_ACTIVE;
+ MISCVARS->gasindex=0;
+ MU_StartSong(song_level);
+ MU_RestoreSongPosition();
+ MISCVARS->GASON = 0;
+
+ index = touchindices[ob->temp1][ob->temp2]-1;
+ TRIGGER[index] = 0;
+ for(temp = touchplate[index]; temp; temp = temp->nextaction)
+ if (temp->action == EnableObject)
+ {
+ tempactor = (objtype*)(temp->whichobj);
+ tempactor->flags &= ~FL_ACTIVE;
+ }
+
+ tswitch = (wall_t*)actorat[ob->temp1][ob->temp2];
+ /*
+ if (tswitch && (tswitch->which != ACTOR))
+ {
+ tilemap[ob->temp1][ob->temp2]--;
+ tswitch->flags &= ~FL_ON;
+ }
+ */
+
+ }
+}
+
+
+
+
+void SpawnBlade(int tilex, int tiley,int dir,int upordown,int moving)
+{ int count,i;
+ statetype *nstate;
+
+#if (SHAREWARE == 1)
+ if (!upordown)
+ Error("\ndown spinblade at %d,%d not allowed in shareware !",tilex,tiley);
+ if (moving)
+ Error("\nupdown spinblade at %d,%d not allowed in shareware !",tilex,tiley);
+
+#endif
+
+
+ if (BATTLEMODE && (!gamestate.BattleOptions.SpawnDangers))
+ return;
+
+ if (moving)
+
+ {
+#if (SHAREWARE == 0)
+
+ if (upordown)
+ SpawnNewObj(tilex,tiley,&s_spinupblade1,bladeobj);
+ else
+ { SpawnNewObj(tilex,tiley,&s_spindownblade1,bladeobj);
+ new->z = 0;
+ }
+#endif
+ }
+ else
+ { if (upordown)
+ SpawnNewObj(tilex,tiley,&s_upblade1,bladeobj);
+
+#if (SHAREWARE == 0)
+
+ else
+ { SpawnNewObj(tilex,tiley,&s_downblade1,bladeobj);
+ new->z = 0;
+ }
+#endif
+ }
+
+
+ count = (int)(GameRandomNumber("SpawnBlade",0) % 16);
+ for(nstate=new->state,i=0; i<count; nstate = nstate->next,i++);
+ NewState(new,nstate);
+
+ new->flags |= (FL_BLOCK);
+ new->flags &= ~FL_SHOOTABLE;
+ new->dir = dir;
+ if (dir != nodir)
+ { new->flags |= FL_NOFRICTION;
+ new->speed = ENEMYRUNSPEED;
+
+ }
+ if (!MAPSPOT(tilex,tiley,2))
+ { new->flags |= FL_ACTIVE;
+ ParseMomentum(new,dirangle8[new->dir]);
+ }
+ PreCacheActor(bladeobj,(moving<<1)+upordown);
+}
+
+
+void SpawnCrushingColumn(int tilex, int tiley, int upordown)
+{ int i,count;
+ statetype * nstate;
+
+
+#if (SHAREWARE == 1)
+ if (!upordown)
+ Error("\ncrush-up column at %d,%d not allowed in shareware!",tilex,tiley);
+#endif
+
+
+ if (BATTLEMODE && (!gamestate.BattleOptions.SpawnDangers))
+ return;
+#if (SHAREWARE == 0)
+ if (!upordown)
+ SpawnNewObj(tilex,tiley,&s_columnupup1,crushcolobj);
+ else
+#endif
+ { SpawnNewObj(tilex,tiley,&s_columndowndown1,crushcolobj);
+ new->z = 0;
+ }
+
+ count = (int)(GameRandomNumber("SpawnCrushingColumn",0) % 8);
+ for(nstate=new->state,i=0; i<count; nstate = nstate->next,i++)
+ { if ((!upordown) && (nstate->condition & SF_UP))
+ new->temp1 += (((nstate->tictime>>1) + 1)<<2);
+
+ }
+ NewState(new,nstate);
+ new->flags |= (FL_BLOCK);
+
+ new->flags &= ~FL_SHOOTABLE;
+ PreCacheActor(crushcolobj,upordown);
+}
+
+
+
+void SpawnFirejet(int tilex, int tiley, int dir, int upordown)
+{
+ int statecount,i;
+ statetype *tstate;
+
+
+ statecount = (int)(GameRandomNumber("SpawnFirejet",0) % 22);
+
+ if (upordown)
+ {
+ for(i=0,tstate=&s_firejetup1; i<statecount; i++,tstate=tstate->next);
+ SpawnNewObj(tilex,tiley,tstate,firejetobj);
+ }
+ else
+ {
+#if (SHAREWARE == 1)
+ Error("\ndown firejet at %d,%d not allowed in shareware",tilex,tiley);
+#else
+ for(i=0,tstate=&s_firejetdown1; i<statecount; i++,tstate=tstate->next);
+ SpawnNewObj(tilex,tiley,tstate,firejetobj);
+ new->z = 0;
+#endif
+ }
+
+ PreCacheActor(firejetobj,upordown);
+
+ new->flags &= ~FL_SHOOTABLE;
+
+ if (dir != nodir)
+ {
+ new->dir = dir*2;
+ new->flags |= FL_NOFRICTION;
+ new->speed = ENEMYRUNSPEED;
+ ParseMomentum(new,dirangle8[new->dir]);
+ }
+ else
+ new->dir = dir;
+}
+
+
+void SpawnFirebomb(objtype*ob,int damage,int which)
+{
+ int i,low,high,doorat;
+ wall_t *tempwall;
+ doorobj_t*tempdoor;
+
+ if (which == 0)
+ {
+ low = (ob->dir>>1);
+ high = low;
+ }
+ else
+ {
+ low = 0;
+ high = which-1;
+
+ if ((FindDistance((ob->x-player->x), (ob->y-player->y))<0x120000) &&
+ (player->z==nominalheight)
+ )
+ SHAKETICS = 35;
+ }
+
+ for (i=low; i<=high; i++)
+ {
+ MissileSound = false;
+ /*
+ if (((which == 0) && ((low == 5) || (low == 6))) ||
+ ((which == 6) && ((i==4) || (i==5)))
+ )
+ {
+
+ if (((which == 0) && (low == 5)) ||
+ ((which == 6) && (i == 4))
+ )
+ {
+ newz = ob->z + 64;
+ if (newz > maxheight)
+ continue;
+ SpawnMissile(ob,p_firebombobj,0,0,&s_grexplosion1,0);
+ new->z = newz;
+ new->dir = 10;
+
+
+ }
+ else
+ {
+ newz = ob->z - 64;
+ if ((sky == 0) && (newz < 0))
+ continue;
+ SpawnMissile(ob,p_firebombobj,0,0,&s_grexplosion1,0);
+ new->z = newz;
+ new->dir = 12;
+
+ }
+
+
+ }
+ else */
+ {
+ SpawnMissile(ob,p_firebombobj,0,dirangle8[2*i],&s_grexplosion1,0x10000);
+ new->z = ob->z;
+ new->dir = (i<<1);
+
+ }
+
+ MissileSound = true;
+
+
+ SD_PlaySoundRTP(SD_EXPLODEFLOORSND,ob->x,ob->y);
+ new->temp2 = FixedMul(damage,DIAGADJUST);
+
+
+ tempwall = (wall_t*)actorat[new->tilex][new->tiley];
+ doorat= 0;
+ if (M_ISDOOR(new->tilex,new->tiley))
+ {
+ tempdoor = doorobjlist[tilemap[new->tilex][new->tiley]&0x3ff];
+ if (tempdoor->position<0x8000)
+ doorat = 1;
+ }
+
+ if ((tempwall && M_ISWALL(tempwall)) || doorat ||
+ (new->tilex <=0) || (new->tilex > MAPSIZE-1) ||
+ (new->tiley <=0) || (new->tiley > MAPSIZE-1)
+ )
+ {
+ new->z = ob->z;
+ SetFinePosition(new,ob->x,ob->y);
+ SetVisiblePosition(new,ob->x,ob->y);
+ }
+ new->whatever = ob->whatever;
+ new->temp3 = ob->temp3 - 1;
+ }
+}
+
+
+
+
+
+
+void MissileHitActor(objtype *owner, objtype *missile, objtype *victim,
+ int damage, int hitmomx, int hitmomy
+ )
+{
+ int tcl = victim->obclass;
+ int ocl = missile->obclass;
+
+ if (
+ (victim->flags & FL_DYING) || // hey, they're dying already;
+ (victim->flags & FL_HEAD) || // don't hurt overrobot's head, wheels
+ (tcl == wallopobj) || // bcraft is invulnerable
+ (tcl == b_darkmonkobj) || // darkmonk is invulnerable
+ (!(victim->flags & FL_SHOOTABLE)) || // don't hurt environment dangers, dead guys
+ ((tcl == b_darksnakeobj) &&
+ ((SNAKELEVEL != 3) || (!victim->temp3))// return for non-red snake
+ )
+ )
+ return;
+
+
+ if ((tcl == playerobj) || (tcl == b_heinrichobj))
+ victim->target = owner;
+
+
+ if (tcl == NMEsaucerobj) // can shoot over's saucer
+ {
+ NewState(victim,&s_explosion1);
+ victim->flags &= ~FL_SHOOTABLE;
+ victim->temp2 = damage;
+ return;
+ }
+
+ else if (tcl == roboguardobj) // check roboguard
+ {
+ DamageThing(victim,damage);
+ Collision(victim,owner,0,0);
+ }
+
+ else if (tcl == collectorobj)
+ {
+ if (gamestate.SpawnEluder)
+ return;
+
+ DamageThing(victim,damage);
+ Collision(victim,owner,0,0);
+ }
+
+ else if (tcl == patrolgunobj)
+ {
+ DamageThing(victim,damage);
+ if (victim->hitpoints <= 0)
+ {
+ victim->momentumx = victim->momentumy = victim->momentumz = 0;
+ victim->flags |= FL_DYING;
+ if (victim->temp1 == -1) // this is 4-way gun
+ NewState(victim,&s_robogrddie1);
+#if (SHAREWARE == 0)
+ else // this is normal
+ NewState(victim,&s_gundie1);
+#endif
+ }
+ }
+
+// bosses are "special" ==========================
+
+ else if ((tcl >= b_darianobj) && (tcl < b_darkmonkobj))
+
+ {
+ DamageThing(victim,damage);
+ if (!(victim->flags & FL_ATTACKMODE))
+ FirstSighting (victim); // put into combat mode
+ if (victim->hitpoints <= 0)
+ {
+ victim->momentumx = victim->momentumy = victim->momentumz = 0;
+ victim->flags |= FL_DYING;
+ NewState(victim,UPDATE_STATES[DIE][victim->obclass-lowguardobj]);
+ switch (victim->obclass)
+ {
+ case b_darianobj:
+ AddMessage("Darian defeated!",MSG_CHEAT);
+ break;
+
+ case b_heinrichobj:
+ AddMessage("Krist defeated!",MSG_CHEAT);
+ break;
+
+ case b_robobossobj:
+ AddMessage("NME defeated!",MSG_CHEAT);
+ break;
+ default:
+ ;
+ }
+ MU_StartSong(song_bossdie);
+ }
+#if (SHAREWARE == 0)
+ else
+ {
+ MISCVARS->REDTIME = (damage >> 1);
+ if (victim->obclass == b_heinrichobj)
+ {
+ NewState(victim,&s_heinrichdefend);
+ if (Near(victim,PLAYER[0],3))
+ {
+ MISCVARS->HRAMMING = 1;
+ MISCVARS->HMINING = 0;
+ victim->dirchoosetime = 0;
+ }
+ else
+ {
+ MISCVARS->HMINING = 1;
+ MISCVARS->HRAMMING = 0;
+ victim->dirchoosetime = 5;//10;
+ }
+ victim->targettilex = victim->targettiley = 0;
+ victim->target = NULL;
+ }
+ }
+#endif
+ }
+
+#if (SHAREWARE == 0)
+ else if ((tcl == b_darksnakeobj) && (victim->temp3)) // red snake
+ {
+ DamageThing(SNAKEEND,damage);
+ if (victim->state->think == T_DarkSnakeChase)
+ NewState(victim,&s_redheadhit);
+ else
+ NewState(victim,&s_redlinkhit);
+ victim->temp3 = 0;
+ }
+#endif
+
+//===============================================
+ else // all other actors
+ {
+
+ if ((tcl == playerobj) &&
+ (victim->flags & FL_AV) &&
+ (ocl != p_godballobj)
+ )
+ {
+ playertype *pstate;
+
+ M_LINKSTATE(victim,pstate);
+ pstate->protectiontime -= ((damage<<1) + damage);
+ if (pstate->protectiontime < 1)
+ pstate->protectiontime = 1;
+ if (victim==player)
+ GM_UpdateBonus (pstate->protectiontime, false);
+
+ return; // asbestos vest prevents victim damage
+ }
+
+ DamageThing(victim,damage);
+
+
+
+ if ((tcl < roboguardobj) && (victim->hitpoints <= 0))
+ {
+ if (ocl != p_godballobj)
+ victim->flags |= FL_HBM;
+ else
+ victim->flags |= (FL_GODSTRUCK | FL_FULLLIGHT);
+ }
+
+ if (tcl == playerobj)
+ {
+ playertype *pstate;
+
+ M_LINKSTATE(victim,pstate);
+ if (pstate->health <= 0)
+ {
+ if (ocl != p_godballobj)
+ victim->flags |= FL_HBM;
+ else
+ victim->flags |= (FL_GODSTRUCK | FL_FULLLIGHT);
+
+ if (M_ISACTOR(owner))
+ {
+ if (owner->obclass == playerobj)
+ {
+ if (!victim->momentumz)
+ BATTLE_PlayerKilledPlayer(battle_kill_with_missile,owner->dirchoosetime,victim->dirchoosetime);
+ else
+ BATTLE_PlayerKilledPlayer(battle_kill_with_missile_in_air,owner->dirchoosetime,victim->dirchoosetime);
+ }
+ else
+ BATTLE_CheckGameStatus(battle_player_killed,missile->dirchoosetime);
+ }
+ else
+ BATTLE_CheckGameStatus(battle_player_killed,missile->dirchoosetime);
+ }
+ }
+
+
+
+ if ((owner->obclass == playerobj) && (victim->flags & FL_HBM))
+ {
+ MISCVARS->supergibflag = true;
+ //GivePoints(starthitpoints[gamestate.difficulty][victim->obclass]*5);
+ }
+
+ Collision(victim,owner,hitmomx,hitmomy);
+ MISCVARS->supergibflag = false;
+ if ((tcl == blitzguardobj) && (owner->obclass == playerobj))
+ victim->flags |= FL_TARGET;
+
+ }
+
+}
+
+
+
+void MissileHit (objtype *ob,void *hitwhat)
+{
+ int damage=0, random,tcl=0,ocl,fireweapon=0,sound,hitmomx,hitmomy;
+ objtype* tempactor=NULL,*owner;
+
+
+
+ if (ob==missobj)
+ missobj=NULL;
+
+ if (ob == PLAYER0MISSILE)
+ PLAYER0MISSILE = NULL;
+
+
+ ob->momentumz = 0;
+ hitmomx = ob->momentumx;
+ hitmomy = ob->momentumy;
+ if (ob->soundhandle != -1)
+ SD_StopSound(ob->soundhandle);
+
+ ob->flags &= ~FL_SHOOTABLE;
+ if (FirstExplosionState(ob->state))
+ return;
+
+ /*
+ if ((ob->z < -28) || (IsWindow(ob->tilex,ob->tiley)))
+ {
+ NewState(ob,&s_megaremove);
+ return;
+ }
+ */
+
+ tempactor = (objtype*)hitwhat;
+ owner = (objtype*)(ob->whatever);
+
+ random = GameRandomNumber("MissileHit",0);
+ ocl = ob->obclass;
+ if (tempactor)
+ {
+ if (tempactor->which == ACTOR)
+ tcl = tempactor->obclass;
+ else if (tempactor->which == SPRITE)
+ tcl = -1;
+ }
+
+ if ((!tcl) && (ob->z < -30))
+ {
+ if (ob->soundhandle != -1)
+ SD_StopSound(ob->soundhandle);
+
+ NewState(ob,&s_megaremove);
+ return;
+
+ }
+
+
+ if (((ocl != p_kesobj) && (ocl != p_godballobj)) || (!tcl))
+ ZEROMOM;
+
+ if (tcl == b_darianobj)
+ MISCVARS->ESAU_SHOOTING = false;
+
+ switch(ocl)
+ {
+
+
+ case p_bazookaobj:
+ NewState(ob,&s_explosion1);
+ if (M_ISACTOR(owner) && (owner->obclass == blitzguardobj))
+ damage = 30 + (random >> 4);
+ else
+ damage = 2*((random>>3)+80);
+ break;
+
+ case p_heatseekobj:
+ NewState(ob,&s_explosion1);
+ damage = 2*((random>>3)+50);
+ break;
+
+
+ case p_drunkmissileobj:
+ NewState(ob,&s_explosion1);
+ damage = ((random>>3)+25);
+ break;
+
+ case p_firebombobj:
+ NewState(ob,&s_explosion1);
+ damage = 2*((random>>3)+90);
+ ob->temp3 = 4;
+ SpawnFirebomb(ob,damage,4);
+ break;
+
+ case p_firewallobj:
+
+ if (tcl == playerobj)
+ gamestate.DOGROUNDZEROBONUS = true;
+ NewState(ob,&s_explosion1);
+ damage = 2*((random>>3)+50);
+ break;
+
+
+ case p_godballobj:
+ if ((tcl >= pillarobj) || (!tcl) || ((tcl == -1) && (!(tempactor->flags & FL_SHOOTABLE))))
+ NewState(ob,&s_explosion1);
+ ob->target = NULL;
+ damage = 500;
+ break;
+
+
+ case shurikenobj:
+ NewState(ob,&s_explosion1);
+ damage = ((random >>3) + 30)>>2;
+ break;
+
+
+ case grenadeobj:
+ NewState(ob,&s_explosion1);
+ damage = (random >>3) + 20;
+ break;
+
+ case fireballobj:
+ NewState(ob,&s_explosion1);
+ damage = (random >> 3) + 10;
+ fireweapon = 1;
+ break;
+
+ case missileobj:
+ NewState(ob,&s_explosion1);
+ if (M_ISACTOR(owner) && (owner->obclass == wallopobj))
+ damage = (random >> 5);
+ else
+ damage = (random >>3) + 30;
+ if (tcl && (tcl != b_heinrichobj))
+ damage = 3*damage>>3;
+ break;
+
+ case wallfireobj:
+ if ((!tempactor) ||
+ (tempactor->which == ACTOR) ||
+ (tempactor->which == SPRITE)
+ )
+ NewState(ob,&s_explosion1);
+ else if (M_ISWALL(tempactor) || (tempactor->which == DOOR))
+ NewState(ob,&s_crossdone1);
+ damage = EnvironmentDamage(ob);
+ fireweapon = 1;
+ break;
+
+
+
+ case inertobj:
+ ob->state = NULL;
+ return;
+ break;
+
+
+#if (SHAREWARE == 0)
+
+
+ case p_splitmissileobj:
+ NewState(ob,&s_explosion1);
+ damage = 2*((random>>3)+50);
+ break;
+
+
+ case p_kesobj:
+ if ((tcl >= pillarobj) ||
+ (!tcl) ||
+ ((tcl == -1) && (!(tempactor->flags & FL_SHOOTABLE)))
+ )
+ NewState(ob,&s_explosion1);
+ damage = 2*((random>>3)+140);
+ break;
+
+
+ case netobj:
+ ob->state=NULL;
+ MISCVARS->NET_IN_FLIGHT = false;
+ if (tempactor == PLAYER[0])
+ {
+ if ((tempactor->flags & FL_GODMODE) ||
+ (tempactor->flags & FL_DOGMODE) ||
+ godmode
+ )
+ damage = 0;
+ else
+ {
+ damage = (random >>4) + 5;
+ PLAYERSTATE[0].NETCAPTURED = -1;
+ PLAYERSTATE[0].weapondowntics = WEAPONS[PLAYERSTATE[0].weapon].screenheight/GMOVE;
+ NewState(PLAYER[0],&s_player);
+ PLAYERSTATE[0].attackframe = PLAYERSTATE[0].weaponframe = 0;
+ PLAYERSTATE[0].batblast = 0;
+ if (PLAYERSTATE[0].HASKNIFE == false)
+ AddMessage("Wiggle left and right to get out of net!",
+ MSG_GAME);
+ }
+ }
+ break;
+
+
+ case bigshurikenobj:
+ NewState(ob,&s_oshurikenhit1);
+ if (owner->obclass == wallopobj)
+ damage = (random >> 5);
+ else
+ damage = 4*((random >>3) + 30)/10;
+
+ break;
+
+
+ case dm_spitobj:
+ NewState(ob,&s_spithit1);
+ damage = 30;
+ if (gamestate.difficulty == gd_hard)
+ damage += 15;
+ break;
+
+ case dm_weaponobj:
+ damage = 20;
+ NewState(ob,&s_explosion1);
+ break;
+
+ case dm_heatseekobj:
+ damage = 20;
+ NewState(ob,&s_explosion1);
+ break;
+
+ case dmfballobj:
+ NewState(ob,&s_explosion1);
+ damage = (random >>3) + 20;
+ fireweapon = 1;
+ break;
+
+ case h_mineobj:
+ NewState(ob,&s_explosion1);
+ damage = (random >>3) + 20;
+ break;
+
+ case NMEsaucerobj:
+ NewState(ob,&s_explosion1);
+ damage = 2*((random>>3)+30);
+ break;
+
+
+#endif
+
+
+ //default:
+ //Error("Unknown ob %d called MissileHit",ob->obclass);
+ }
+
+ //if (!ob->state)
+ //return;
+ if ((sound = BAS[ob->obclass].hit)!=0)
+ SD_PlaySoundRTP(sound,ob->x,ob->y);
+
+
+ if (FirstExplosionState(ob->state))
+ SD_PlaySoundRTP(SD_EXPLODESND,ob->x,ob->y);
+
+
+ if (tcl>0) // actors
+ {
+ MissileHitActor(owner,ob,tempactor,damage,hitmomx,hitmomy);
+ if ((ocl == p_kesobj) && (tcl < roboguardobj))
+ {
+ tempactor->momentumx = hitmomx; // kes gives wus targets its momentum
+ tempactor->momentumy = hitmomy;
+ //missile->flags |= FL_NOFRICTION;
+ }
+ }
+
+ else if (tcl < 0) // static
+ {
+ DamageThing(hitwhat,damage);
+ if (FirstExplosionState(new->state))
+ new->whatever = ob->whatever;
+ }
+
+
+}
+
+
+
+
+void T_Spears(objtype*ob)
+{ int dx,dy,dz,i;
+
+
+ for(i=0; i<numplayers; i++)
+ { if (PLAYER[i]->flags & FL_DYING)
+ continue;
+
+ dx = abs(PLAYER[i]->x - ob->x);
+ dy = abs(PLAYER[i]->y - ob->y);
+ dz = abs(PLAYER[i]->z - ob->z);
+
+
+ if ((!ob->ticcount)&&(ob->state->condition&SF_SOUND) &&
+ areabyplayer[ob->areanumber])
+ SD_PlaySoundRTP(BAS[ob->obclass].operate,ob->x,ob->y);
+
+ if ((dx < STANDDIST) && (dy < STANDDIST) && (dz < 20))
+ { ob->flags &= ~FL_BLOCK;
+ if ((!ob->ticcount) && (ob->state->condition & SF_CRUSH))
+ { DamageThing(PLAYER[i],EnvironmentDamage(ob));
+ Collision(PLAYER[i],ob,0,0);
+ M_CheckPlayerKilled(PLAYER[i]);
+ return;
+ }
+ }
+ else
+ { if (ob->state->condition & SF_DOWN)
+ ob->flags &= ~FL_BLOCK;
+ else
+ ob->flags |= FL_BLOCK;
+ }
+ }
+}
+
+
+
+void T_CrushUp(objtype*ob)
+{ int dx, dy,dist,dz,i,playeron;
+
+
+ if ((!ob->ticcount) && (ob->state->condition & SF_SOUND) &&
+ areabyplayer[ob->areanumber])
+ SD_PlaySoundRTP(BAS[ob->obclass].operate,ob->x,ob->y);
+ dist = ACTORSIZE+0x2000;
+ if (ob->state->condition & SF_UP)
+ { ob->temp1 += 4;
+// Debug("\ncol momz = 4");
+ }
+ else if (ob->state->condition & SF_DOWN)
+ { ob->temp1 -= 4;
+// Debug("\ncol mom z = -4");
+ }
+ else
+ { //ob->momentumz = 0;
+ // Debug("\ncol mom z = 0");
+ }
+
+ ob->temp2 = maxheight - ob->temp1 + 32;
+
+
+ playeron = 0;
+ for(i=0; i<numplayers; i++)
+ { dx = abs(PLAYER[i]->x - ob->x);
+ dy = abs(PLAYER[i]->y - ob->y);
+ dz = abs(ob->temp2-PLAYER[i]->z);
+
+ if ((dx < dist) && (dy < dist) && (dz < 65))
+ { ob->flags &= ~FL_BLOCK;
+ //player->temp2 = 0;
+ playeron = 1;
+ if ((!ob->ticcount) && (ob->state->condition & SF_CRUSH) &&
+ (levelheight<2) && (!(ob->flags & FL_DYING)))
+ { DamageThing(PLAYER[i],EnvironmentDamage(ob));
+ if (PLAYER[i]->hitpoints <= 0)
+ PLAYER[i]->flags |= FL_HBM;
+ Collision(PLAYER[i],ob,0,0);
+ M_CheckPlayerKilled(PLAYER[i]);
+ //NewState(ob,ob->state); //reset ticcount
+ return;
+ }
+ if (ob->state->condition & SF_UP)
+ {
+ PLAYER[i]->momentumz = -(4<<16);
+ if (PLAYER[i]->z < -30)
+ PLAYER[i]->z = -30;
+ }
+ else if (ob->state->condition & SF_DOWN)
+ { PLAYER[i]->momentumz = (4<<16);
+ if (PLAYER[i]->z >= nominalheight)
+ PLAYER[i]->z = nominalheight;
+ }
+ else
+ PLAYER[i]->momentumz = 0;
+ PLAYER[i]->whatever = ob;
+ ob->whatever = PLAYER[i];
+ //PLAYER[i]->flags |= FL_RIDING;
+
+ }
+
+ }
+
+ //if (!playeron)
+ { if (ob->state->condition & SF_BLOCK)
+ ob->flags |= FL_BLOCK;
+ else
+ ob->flags &= ~FL_BLOCK;
+
+ }
+
+
+}
+
+
+void T_CrushDown(objtype*ob)
+{ int dx,dy,dz,i,playeron;
+
+
+ if ((!ob->ticcount) && (ob->state->condition & SF_SOUND)&&
+ areabyplayer[ob->areanumber])
+ SD_PlaySoundRTP(BAS[ob->obclass].operate,ob->x,ob->y);
+
+ ob->temp2 = ob->z;
+ playeron = 0;
+ for(i=0; i<numplayers; i++)
+ { dx = abs(PLAYER[i]->x - ob->x);
+ dy = abs(PLAYER[i]->y - ob->y);
+ dz = abs(PLAYER[i]->z - ob->z);
+
+ if ((dx < STANDDIST) && (dy < STANDDIST) && (dz < 20))
+ { //PLAYER[i]->temp2 = 0;
+ playeron = 1;
+ ob->flags &= ~FL_BLOCK;
+ if ((!ob->ticcount) && (ob->state->condition & SF_CRUSH) &&
+ (!(ob->flags & FL_DYING)))
+ { DamageThing(PLAYER[i],EnvironmentDamage(ob));
+ if (PLAYER[i]->hitpoints <= 0)
+ PLAYER[i]->flags |= FL_HBM;
+ Collision(PLAYER[i],ob,0,0);
+ M_CheckPlayerKilled(PLAYER[i]);
+ //NewState(ob,ob->state); //reset ticcount
+ return;
+ }
+ if ((ob->state->condition & SF_DOWN) &&
+ ((ob->state != &s_columndowndown1) &&
+ (ob->state != s_columndowndown1.next)))
+ { PLAYER[i]->temp2 = COLUMNCRUSH;
+ PLAYER[i]->whatever = ob;
+ }
+ }
+
+ }
+ //if (!playeron)
+ { if (ob->state->condition & SF_BLOCK)
+ ob->flags |= FL_BLOCK;
+ else
+ ob->flags &= ~FL_BLOCK;
+ }
+
+
+}
+
+
+void T_Explosion(objtype* ob)
+{
+ int momx,momy,momz;
+ int dx,dy,dz;
+ int pdamage,dist,blastradius=0x20000,
+ fatalradius=0x9000,impulse,damage,
+ scalefactor;
+
+
+
+ statobj_t* checkstat;
+ objtype* check,*owner;
+
+ if (ob->ticcount)
+ return;
+
+ damage = EXPLOSION_DAMAGE;
+ owner = (objtype*)(ob->whatever);
+ if ((ob->temp3) && (ob->obclass == p_firebombobj))
+ {
+ SpawnFirebomb(ob,damage,0);
+ ob->temp3 = 0;
+ }
+//================== check surrounding actors ============================//
+
+
+ for(check = firstactive; check; check=check->nextactive)
+ {
+ if (check == ob)
+ continue;
+
+// if (check == owner)
+// continue;
+
+ dx = abs(check->x - ob->x);
+ if (dx > blastradius)
+ continue;
+
+ dy = abs(ob->y - check->y);
+ if (dy > blastradius)
+ continue;
+
+ dz = ((abs(ob->z - check->z))<<10);
+ if (dz > blastradius)
+ continue;
+
+
+ if (check->flags & FL_HEAD)
+ continue;
+
+ if (check->flags & FL_DYING)
+ continue;
+
+ if (!(check->flags & FL_SHOOTABLE))
+ continue;
+
+
+
+ if ((check->obclass >= roboguardobj) && (check->obclass != b_darkmonkobj))
+ //(check->obclass <= wallopobj))
+ continue;
+
+
+ if (!CheckLine(ob,check,SIGHT))
+ continue;
+
+
+ if (check->obclass == NMEsaucerobj)
+ {
+ NewState(check,&s_explosion1);
+ check->flags &= ~FL_SHOOTABLE;
+ return;
+ }
+#if 0
+ dist = FindDistance(dx,dy);
+ scalefactor = (blastradius-dist)>>4;
+ if (scalefactor > 0xffff)
+ scalefactor = 0xffff;
+ pdamage = FixedMul(damage,scalefactor);
+#endif
+//#if 0
+ //magdx = abs(dx);
+ //magdy = abs(dy);
+
+ dist = Find_3D_Distance(dx,dy,dz);
+ SoftError("\ndist: %x\n",dist);
+
+
+ //if (dist < 0x10000)
+ // dist = 0x10000;
+
+ scalefactor = FixedDiv2(1<<16,FixedMul(dist,dist));
+ //scalefactor = FixedDiv2(1<<16,dist);
+
+ if (scalefactor > 0x12000)
+ scalefactor = 0x12000;
+ pdamage = FixedMul(damage,scalefactor);
+ SoftError("\ndamage: %d, scalefactor: %x\n",pdamage,scalefactor);
+//#endif
+ impulse = FixedMul(EXPLOSION_IMPULSE,scalefactor);
+ if (check->obclass == playerobj)
+ {
+ check->target = owner;
+ if (check->flags & FL_AV)
+ pdamage = 0;
+ }
+
+ if (check->obclass < roboguardobj)
+ {
+ SoftError("\nhitpoints before: %d",check->hitpoints);
+ DamageThing(check,pdamage);
+ SoftError("\nhitpoints after: %d",check->hitpoints);
+ if ((check->hitpoints <= 0) && (gamestate.violence == vl_excessive) &&
+ ((ob->obclass == p_firebombobj) ||
+ ((dx < fatalradius) && (dy < fatalradius) && (dz < 20)))
+ )
+ check->flags |= FL_HBM;
+
+ GetMomenta(check,ob,&momx,&momy,&momz,impulse);
+ //Debug("\nhitmomx = %d, hitmomy = %d",momx,momy);
+
+ /*if (M_ISACTOR(owner) &&
+ (owner->obclass == playerobj) &&
+ (check->hitpoints <=0)
+ )
+ GivePoints(starthitpoints[gamestate.difficulty][check->obclass]*5);
+ */
+ Collision(check,owner,momx,momy);
+ check->momentumz += (momz<<6);
+ if ((check->obclass == playerobj) && (check->flags & FL_DYING) &&
+ M_ISACTOR(owner))
+ {
+ if (owner->obclass == playerobj)
+ {
+ if (check->z != nominalheight)
+ BATTLE_PlayerKilledPlayer(battle_kill_with_missile_in_air,owner->dirchoosetime,check->dirchoosetime);
+ else
+ BATTLE_PlayerKilledPlayer(battle_kill_with_missile,owner->dirchoosetime,check->dirchoosetime);
+ }
+ else
+ BATTLE_CheckGameStatus(battle_player_killed,check->dirchoosetime);
+ }
+
+ }
+ else
+ {
+ if (check->obclass != b_darkmonkobj) {
+ SoftError("non-darkmonk actor %d being helped by explosion",check->obclass);
+ }
+ check->hitpoints += pdamage;
+ }
+ }
+
+//======================== check surrounding statics ================
+
+
+ for(checkstat = firstactivestat; checkstat; checkstat=checkstat->nextactive)
+ {
+
+ if ((!(checkstat->flags & FL_SHOOTABLE)) && (checkstat->itemnumber != stat_priestporridge))
+ continue;
+
+ if ((checkstat->itemnumber >= stat_lifeitem1) &&
+ (checkstat->itemnumber <= stat_lifeitem4))
+ continue;
+
+ dx = abs(checkstat->x - ob->x);
+ dy = abs(checkstat->y - ob->y);
+ dz = ((abs(checkstat->z - ob->z))<<10);
+
+ if ((dx < blastradius) && (dy < blastradius) && (dz < blastradius))
+ {
+ dist = Find_3D_Distance(dx,dy,dz)+0xc00;
+
+ if (dist < 0x10000)
+ dist = 0x10000;
+
+ scalefactor = FixedDiv2(1<<16,FixedMul(dist,dist));
+ pdamage = FixedMul(damage,scalefactor);
+
+ if (checkstat->itemnumber != stat_priestporridge)
+ DamageThing(checkstat,pdamage);
+ else if (!(checkstat->flags & FL_ACTIVE))
+ {
+ checkstat->flags |= FL_ACTIVE;
+ checkstat->count = 1;
+ //checkstat->numanims = 6;
+ SD_PlaySoundRTP(SD_COOKHEALTHSND,ob->x,ob->y);
+ }
+ }
+ }
+
+//======================== check surrounding walls ================
+ {
+ int tilexlow,tilexhigh;
+ int tileylow,tileyhigh;
+ int radius =0x10000;
+ int x,y;
+
+ tilexlow = (int)((ob->x-radius) >>TILESHIFT);
+ tileylow = (int)((ob->y-radius) >>TILESHIFT);
+
+ tilexhigh = (int)((ob->x+radius) >>TILESHIFT);
+ tileyhigh = (int)((ob->y+radius) >>TILESHIFT);
+
+ for (y=tileylow; y<=tileyhigh; y++)
+ {
+ for (x=tilexlow; x<=tilexhigh; x++)
+ {
+ if ((tilemap[x][y]&0x8000) && (tilemap[x][y]&0x4000) && (abs(ob->z - nominalheight) < 32))
+ {
+ maskedwallobj_t * mw;
+
+ mw=maskobjlist[tilemap[x][y]&0x3ff];
+ if (mw->flags&MW_SHOOTABLE)
+ UpdateMaskedWall(tilemap[x][y]&0x3ff);
+ }
+ }
+ }
+ }
+
+}
+
+
+
+void SpawnScreenEye(objtype *ob)
+{
+ SpawnNewObj(ob->tilex,ob->tiley,&s_eye1,inertobj);
+ new->targettiley = 0;
+ new->targettilex = GameRandomNumber("eye position",0) + 20;
+ SCREENEYE = new;
+ //RemoveFromArea(new);
+ new->flags |= FL_ABP;
+ MakeActive(new);
+
+}
+
+
+
+
+
+
+void SpawnSuperFatalityGibs(objtype *ob,objtype *attacker)
+{
+ int crazygibs = (GameRandomNumber("crazy gibs",0) % 6) + 4;
+ int i;
+
+
+ if ((MISCVARS->supergibflag == true) &&
+ ((crazygibs == 9) || (ludicrousgibs == true))
+ )
+
+ {
+ int olddirect = MISCVARS->directgibs;
+
+ MISCVARS->directgibs = false;
+ if (ludicrousgibs == false)
+ {
+ if (attacker == player)
+ {
+ AddMessage("Ludicrous Gibs!",MSG_GAME);
+ if (!(attacker->flags&FL_DOGMODE))
+ SD_Play(PlayerSnds[locplayerstate->player]);
+ }
+ }
+ else
+ {
+ MISCVARS->randgibspeed = true;
+
+#ifdef MEDGIBS
+ SpawnParticles(ob,GUTS,150);
+#else
+ SpawnParticles(ob,GUTS,75);
+#endif
+
+ MISCVARS->randgibspeed = false;
+ }
+ SpawnParticles(ob,GUTS,40);
+ MISCVARS->directgibs = olddirect;
+
+ }
+
+ for (i=gt_head; i<=crazygibs; i++)
+ {
+
+ if (((ob->obclass == dfiremonkobj) || (ob->obclass == deathmonkobj)) &&
+ (i == gt_leg)
+ )
+ SpawnParticles(ob,gt_arm,1);
+ else
+ SpawnParticles(ob,i,1);
+ }
+
+
+}
+
+
+
+
+
+boolean Vicious_Annihilation(objtype *ob, objtype *attacker)
+{
+ if ((ob->flags & FL_HBM) && (gamestate.violence >= vl_high))
+ {
+ ob->shapeoffset = 0;
+ ob->flags &= ~FL_FULLLIGHT;
+ NewState(ob,(ob->obclass == playerobj)?(&s_remoteguts1):(&s_guts1));
+ SD_PlaySoundRTP(SD_ACTORSQUISHSND,ob->x,ob->y);
+ if (gamestate.violence == vl_excessive)
+ {
+ int numgibs;
+ objtype *prevlast;
+
+ numgibs = (GameRandomNumber("excessive guts",0) & 7) + 4;
+ //SoftError("\nnumgibs = %d,gamestate.difficulty = %d",numgibs,gamestate.difficulty);
+ prevlast = LASTACTOR;
+ MISCVARS->fulllightgibs = true;
+ SpawnParticles(ob,GUTS,numgibs);
+ MISCVARS->fulllightgibs = false;
+ for(prevlast = prevlast->next; prevlast; prevlast = prevlast->next)
+ prevlast->momentumz += (prevlast->momentumz >> 1);
+
+ if ((GameRandomNumber("super gib chance",0) < 100) ||
+ (ludicrousgibs == true)
+ )
+ {
+ MISCVARS->directgibs = true;
+//MED
+ MISCVARS->gibgravity = GRAVITY/2;
+// MISCVARS->gibgravity = GRAVITY*2;
+ MISCVARS->fulllightgibs = true;
+ SpawnSuperFatalityGibs(ob,attacker);
+ MISCVARS->fulllightgibs = false;
+ MISCVARS->gibgravity = -1;
+ MISCVARS->directgibs = false;
+ }
+ }
+ return true;
+
+ }
+
+
+ if (ob->flags & FL_GODSTRUCK)
+ {
+ ob->shapeoffset = 0;
+ ob->flags |= (FL_FULLLIGHT);
+ ob->flags &= ~FL_COLORED;
+ ob->momentumx = ob->momentumy = ob->momentumz = 0;
+ KillActor(ob);
+ NewState(ob,&s_vaporized1);
+ return true;
+ }
+
+ if (ob->flags & FL_SKELETON)
+ {
+ KillActor(ob);
+ ob->shapeoffset = 0;
+ ob->flags &= ~FL_COLORED;
+ ob->momentumx = ob->momentumy = ob->momentumz = 0;
+ NewState(ob,&s_skeleton1);
+ SD_PlaySoundRTP(SD_ACTORBURNEDSND,ob->x,ob->y);
+ return true;
+ }
+
+ return false;
+
+}
+
+void SetReverseDeathState(objtype * actor)
+{
+ switch(actor->obclass)
+ {
+ case lowguardobj:
+ NewState(actor, &s_lowgrddie4rev);
+ //actor->state = &s_lowgrddie4rev;
+ break;
+ case highguardobj:
+ NewState(actor, &s_highgrddie5rev);
+ break;
+ case strikeguardobj:
+ NewState(actor, &s_strikedie4rev);
+ //actor->state = &s_strikedie4rev;
+ break;
+ case blitzguardobj:
+ NewState(actor, &s_blitzdie4rev);
+ //actor->state = &s_blitzdie4rev;
+ break;
+ case triadenforcerobj:
+ NewState(actor, &s_enforcerdie4rev);
+ //actor->state = &s_enforcerdie4rev;
+ break;
+ case overpatrolobj:
+ NewState(actor, &s_opdie5rev);
+ //actor->state = &s_opdie5rev;
+ break;
+ case deathmonkobj:
+ NewState(actor, &s_dmonkdie4rev);
+ //actor->state = &s_dmonkdie4rev;
+ break;
+ case dfiremonkobj:
+ NewState(actor, &s_firemonkdie4rev);
+ //actor->state = &s_firemonkdie4rev;
+ break;
+ default:
+ Error("SetReverseDeathState was called with something that can't be handled!");
+ break;
+ }
+}
+
+extern objtype* enemiesToRes;
+extern unsigned int freeSlot;
+void AddEnemyToResurrectList(objtype * ob)
+{
+ SetReverseDeathState(ob);
+ enemiesToRes[freeSlot] = *ob;
+ freeSlot++;
+}
+
+void CleanUpResurrectList()
+{
+ memset(enemiesToRes, 0, sizeof(*enemiesToRes));
+ freeSlot = 0;
+}
+
+void FreeUpResurrectList()
+{
+ free(enemiesToRes);
+}
+
+void SetAfterResurrectState(objtype * actor, statetype * doWhat)
+{
+ statetype * state = actor->state;
+
+ while(state->next != NULL)
+ {
+ state = state->next;
+ }
+ state->next = doWhat;
+}
+
+void SpawnDuringGameWithState (classtype which, int tilex, int tiley, int dir, int ambush, statetype * temp)
+{
+ //statetype *temp;
+
+#if (SHAREWARE == 1)
+ switch(which)
+ {
+ case overpatrolobj:
+ case wallopobj:
+ case deathmonkobj:
+ case dfiremonkobj:
+ case b_darianobj:
+ case b_heinrichobj:
+ case b_darkmonkobj:
+ Error("\n%s actor at %d,%d not allowed in shareware !",debugstr[which],tilex,tiley);
+ break;
+ default:
+ ;
+ }
+
+#endif
+ if (which > dfiremonkobj)
+ {
+ return;
+ }
+
+ if (!CheckTile(tilex,tiley))
+ FindEmptyTile(&tilex, &tiley);
+
+ SpawnNewObj(tilex,tiley,temp,which);
+
+ if (ambush)
+ new->flags |= FL_AMBUSH;
+
+ StandardEnemyInit(new,dir);
+
+ if (which == b_darkmonkobj)
+ {
+ new->flags |= (FL_NOFRICTION);//|FL_INVULNERABLE);
+ new->speed = ENEMYRUNSPEED*2;
+ }
+
+ ConnectAreas();
+}
+
+void ResurrectEnemies()
+{
+ objtype * actor;
+
+ for (actor = &enemiesToRes[0]; actor < &enemiesToRes[freeSlot]; actor++)
+ {
+ SD_PlaySoundRTP(SD_PLAYERSPAWNSND, actor->x, actor->y);
+ SpawnDuringGameWithState (actor->obclass,actor->tilex,actor->tiley,actor->dir, 1, actor->state);
+ }
+
+ CleanUpResurrectList();
+
+}
+
+/*
+void SetStandAfterResurrect(objtype * actor)
+{
+ switch(actor->obclass)
+ {
+ case lowguardobj:
+ SetAfterResurrectState(actor, &s_lowgrdstand);
+ //actor->state = &s_lowgrdchase1;
+ break;
+ case highguardobj:
+ SetAfterResurrectState(actor, &s_highgrdstand);
+ //actor->state = &s_highgrdchase1;
+ break;
+ case strikeguardobj:
+ SetAfterResurrectState(actor, &s_strikestand);
+ //actor->state = &s_strikechase1;
+ break;
+ case blitzguardobj:
+ SetAfterResurrectState(actor, &s_blitzstand);
+ //actor->state = &s_blitzchase1;
+ break;
+ case triadenforcerobj:
+ SetAfterResurrectState(actor, &s_enforcerstand);
+ //actor->state = &s_enforcerchase1;
+ break;
+ case overpatrolobj:
+ SetAfterResurrectState(actor, &s_opstand);
+ //actor->state = &s_opchase1;
+ break;
+ case deathmonkobj:
+ SetAfterResurrectState(actor, &s_dmonkstand);
+ //actor->state = &s_dmonkchase1;
+ break;
+ case dfiremonkobj:
+ SetAfterResurrectState(actor, &s_firemonkstand);
+ //actor->state = &s_firemonkchase1;
+ break;
+ default:
+ Error("SetStandAfterResurrect was called with something that can't be handled!");
+ break;
+ }
+}
+*/
+
+
+
+void SpawnDuringGame (classtype which, int tilex, int tiley, int dir, int ambush)
+{
+ statetype *temp;
+
+#if (SHAREWARE == 1)
+ switch(which)
+ {
+ case overpatrolobj:
+ case wallopobj:
+ case deathmonkobj:
+ case dfiremonkobj:
+ case b_darianobj:
+ case b_heinrichobj:
+ case b_darkmonkobj:
+ Error("\n%s actor at %d,%d not allowed in shareware !",debugstr[which],tilex,tiley);
+ break;
+ default:
+ ;
+ }
+
+#endif
+ if (which > dfiremonkobj)
+ {
+ return;
+ }
+
+ if ((temp = UPDATE_STATES[STAND][which-lowguardobj]) != NULL)
+ {
+ if (!CheckTile(tilex, tiley))
+ FindEmptyTile(&tilex, &tiley);
+
+ SpawnNewObj(tilex,tiley,temp,which);
+
+ if (ambush)
+ new->flags |= FL_AMBUSH;
+
+ StandardEnemyInit(new,dir);
+
+ if (which == b_darkmonkobj)
+ {
+ new->flags |= (FL_NOFRICTION);//|FL_INVULNERABLE);
+ new->speed = ENEMYRUNSPEED*2;
+ }
+ }
+ ConnectAreas();
+}
+
+void SaveResurrectList(byte ** buffer, int *size)
+{
+ byte*tptr;
+
+ *size = sizeof(enemiesToRes);
+ *buffer = (byte*)SafeMalloc(*size);
+ tptr = *buffer;
+
+ memcpy(tptr, enemiesToRes, sizeof(*enemiesToRes));
+ tptr += sizeof(enemiesToRes);
+
+}
+
+/*
+========================
+=
+= BeginEnemyFatality
+=
+========================
+*/
+
+extern boolean enableZomROTT;
+
+void BeginEnemyFatality(objtype *ob,objtype *attacker)
+{
+ if ((attacker == player) && (ob->obclass < (NUMENEMIES + 2)))
+ {
+ GivePoints(starthitpoints[gamestate.difficulty][ob->obclass]*5);
+ if (timelimitenabled)
+ timelimit+=VBLCOUNTER;
+ }
+
+ ob->flags |= FL_DYING;
+ ob->soundhandle = -1;
+
+#if 0
+ if ((ob->obclass == blitzguardobj) &&
+ (ob->state->condition & SF_DOWN)
+ )
+
+ SD_Play(PlayerSnds[locplayerstate->player]);
+#endif
+
+ if (Vicious_Annihilation(ob,attacker))
+ return;
+ else if (enableZomROTT)
+ {
+ objtype * copyOfObject = malloc(sizeof(objtype));
+
+ memcpy(copyOfObject, ob, sizeof(objtype));
+
+ AddEnemyToResurrectList(copyOfObject);
+ }
+
+ if ((ob->obclass == patrolgunobj) && (ob->temp1 == -1))
+ NewState(ob,&s_robogrddie1);
+ else if (ob->obclass == collectorobj)
+ {
+ if ((!M_ISACTOR(attacker)) || (attacker->obclass != playerobj))
+ RespawnEluder();
+ else
+ BATTLE_CheckGameStatus(battle_shot_deluder,attacker->dirchoosetime);
+
+ NewState(ob,&s_explosion1);
+ MISCVARS->gibgravity = GRAVITY/2;
+ MISCVARS->fulllightgibs = true;
+ SpawnParticles(ob,gt_sparks,100);
+ MISCVARS->fulllightgibs = false;
+ MISCVARS->gibgravity = -1;
+ }
+ else
+ {
+ statetype *temp;
+
+ if ((ob->obclass == blitzguardobj) &&
+ (ob->state->condition & SF_FAKING)
+ )
+ {
+ NewState(ob,&s_blitzstruggledie1);
+ ob->flags &= ~FL_FULLLIGHT;
+ }
+ else if
+ ((ob->obclass == blitzguardobj) &&
+ (ob->state->condition & SF_DOWN)
+ )
+ {
+ NewState(ob,&s_blitzplead7);
+ ob->flags &= ~FL_FULLLIGHT;
+ }
+
+ else if
+ ((temp= M_S(DIE)) != NULL)
+ {
+ if (LOW_VIOLENCE_DEATH_SHOULD_BE_SET(ob))
+ SET_DEATH_SHAPEOFFSET(ob);
+ NewState(ob,temp);
+ ob->flags &= ~FL_FULLLIGHT;
+ }
+ else
+ Error("Null dead state called in Collision, obclass %d",ob->obclass);
+ }
+
+
+}
+
+
+
+/*
+========================
+=
+= BeginPlayerFatality
+=
+========================
+*/
+
+
+
+
+void BeginPlayerFatality(objtype *ob,objtype *attacker)
+{
+ playertype *pstate;
+ M_LINKSTATE(ob,pstate);
+
+
+ ob->flags &= ~(FL_ELASTO|FL_GODMODE|FL_DOGMODE|FL_NOFRICTION|FL_RIDING);
+
+ ob->flags |= FL_DYING;
+ pstate->weapon = -1;
+
+
+ if (BATTLEMODE)
+ SD_PlaySoundRTP (SD_PLAYERTCDEATHSND+(pstate->player),ob->x,ob->y);
+
+ if (Vicious_Annihilation(ob,attacker) == false)
+ {
+ if (LOW_VIOLENCE_DEATH_SHOULD_BE_SET(ob))
+ SET_DEATH_SHAPEOFFSET(ob);
+
+ NewState(ob,&s_remotedie1);
+ ob->flags &= ~FL_FULLLIGHT;
+ }
+
+
+
+}
+
+
+
+/*
+========================
+=
+= BeginEnemyHurt
+=
+========================
+*/
+
+
+void BeginEnemyHurt(objtype *ob)
+{
+ statetype *temp;
+
+ if ((temp= M_S(COLLIDE1)) != NULL)
+ {
+
+
+ if ((ob->obclass == blitzguardobj) &&
+ (ob->state->condition & SF_FAKING)
+ )
+ {
+ ob->temp1 = 1;
+ ob->dirchoosetime = 0;
+ T_PlayDead(ob);
+
+ }
+
+ else
+ {
+ if ((ob->obclass == triadenforcerobj) &&
+ (GameRandomNumber("george pain chance",0) <
+ (50 + (gamestate.difficulty<<6))
+ )
+ )
+ {
+ ob->flags &= ~FL_FULLLIGHT;
+ return;
+
+ }
+
+
+ if (LOW_VIOLENCE_PAIN_SHOULD_BE_SET(ob))
+ SET_PAIN_SHAPEOFFSET(ob);
+
+ if (GameRandomNumber("Collision",0) < 128)
+ NewState(ob,temp);
+ else
+ NewState(ob,M_S(COLLIDE2));
+ }
+
+ ob->flags &= ~FL_FULLLIGHT;
+ ob->ticcount = PAINTIME;
+ if (ob->obclass == strikeguardobj)
+ ob->ticcount >>= 1;
+ }
+}
+
+
+void Collision(objtype*ob,objtype *attacker,int hitmomentumx,int hitmomentumy)
+{
+ int ocl;
+
+ if ((!(ob->flags & FL_SHOOTABLE)) || (ob->flags & FL_DYING))
+ return;
+
+ ocl = ob->obclass;
+
+ ob->momentumx += hitmomentumx;
+ ob->momentumy += hitmomentumy;
+
+ if ((ocl == playerobj) && (gamestate.battlemode == battle_Eluder))
+ return;
+
+ //insertion 5
+
+ if (ocl != playerobj)
+ {
+ if ((!(ob->flags & FL_ATTACKMODE)) && (TABLE_ACTOR(ob)))
+ ActivateEnemy(ob);
+
+
+ if (ob->hitpoints <= 0)
+ BeginEnemyFatality(ob,attacker);
+
+ else if (ocl != roboguardobj)// && (ob->state->think != T_Collide))
+ BeginEnemyHurt(ob);
+ }
+ else
+ {
+ playertype *pstate;
+
+ if ((ob->flags & FL_GODMODE) || (ob->flags & FL_DOGMODE) || godmode)
+ return;
+
+ M_LINKSTATE(ob,pstate);
+ if (pstate->health<=0)
+ BeginPlayerFatality(ob,attacker);
+ else
+ ob->flags |= FL_PAIN;
+
+ }
+
+}
+
+
+
+
+void T_BossExplosions(objtype*ob)
+{
+
+ if (ob->temp1)
+ { if (ob->dirchoosetime)
+ ob->dirchoosetime --;
+ else
+ { int randtime,randangle,randdist,sound;
+ statetype *nstate;
+
+ ob->temp1 --;
+ randtime = GameRandomNumber("Boss Explosion Time",0);
+ ob->dirchoosetime = 10;
+ if (randtime < 128)
+ ob->dirchoosetime >>= 1;
+ randangle = (GameRandomNumber("Boss Explosion Angle",0) << 3);
+ randdist = (GameRandomNumber("Boss Explosion Distance",0) << 7)+0x4000;
+ sound = SD_EXPLODEFLOORSND;
+ if (randtime < 128)
+ { nstate = &s_explosion1;
+ sound++;
+ }
+#if (SHAREWARE == 0)
+ else
+ nstate = &s_grexplosion1;
+#endif
+
+
+ SpawnMissile(ob,inertobj,0,randangle,nstate,randdist);
+ SD_PlaySoundRTP(sound,new->x,new->y);
+ }
+ }
+}
+
+
+
+
+gib_t RandomGutsType(void)
+{
+ int rand = GameRandomNumber("gut random",0);
+
+
+ if (rand < 128)
+ return gt_organ;
+
+ //if (rand < 160)
+ return gt_rib;
+
+ //return gt_pinkorgan;
+
+
+}
+
+
+//MED
+void SpawnParticles(objtype*ob,int which,int numparticles)
+{
+ int randphi,randtheta,i,nspeed;
+ boolean eyespawned = false;
+ int gibtype;
+ int randadj;
+
+
+ if ((ob->z <= -64) && (sky == 0)) //shouldn't happen
+ return;
+
+
+ if (((which == GUTS) || (which == RANDOM)) && (gamestate.violence < vl_high))
+ which = gt_sparks;
+
+ gibtype = which;
+
+
+ for(i=0; i<numparticles; i++)
+ {
+ int ordertemp; /* DDOI - Watcom evaluates the mult order diff */
+ randphi = (GameRandomNumber("particle generate phi",0) << 3);
+ // randadj = RandomSign() * (GameRandomNumber("rand gib adjust",0) >> 4);
+ ordertemp = (GameRandomNumber("rand gib adjust",0) >> 4);
+ randadj = RandomSign() * ordertemp;
+
+
+
+ if (ob->z > (nominalheight - 32))
+ randphi &= ((ANGLES/2) - 1);
+
+ randtheta = (GameRandomNumber("particle generate theta",0) << 3);
+ nspeed = MISCVARS->gibspeed;
+
+
+ if (which == RANDOM)
+ {
+ if (GameRandomNumber("random gib",0) < 128)
+ gibtype = RandomGutsType();
+ else
+ gibtype = gt_sparks;
+
+ }
+
+ if ((which == GUTS) || (which == DISEMBOWEL))
+ {
+
+ gibtype = RandomGutsType();
+ if (which == DISEMBOWEL)
+ {
+ randphi>>=2;
+ randtheta=ob->temp1+(randtheta>>3)-(randtheta>>4);
+ }
+
+ }
+
+ if (lowmemory && (gibtype >= gt_rib) && (gibtype <= gt_limb))
+ gibtype = gt_organ;
+
+ if
+ (
+ // (gibtype >= gt_organ) && (gibtype <= gt_limb) &&
+ (MISCVARS->numgibs >= MAXGIBS)
+ )
+ return;
+
+
+
+ if (gibtype == gt_lsoul)
+ {
+ SpawnNewObj(ob->tilex,ob->tiley,&s_littlesoul,inertobj);
+ randphi = 0;
+ }
+
+
+#if (SHAREWARE == 0)
+ else if (gibtype == gt_spit)
+
+ SpawnNewObj(ob->tilex,ob->tiley,&s_slop1,inertobj);
+#endif
+ else
+ {
+ SpawnNewObj(ob->tilex,ob->tiley,&s_gibs1,inertobj);
+ new->shapeoffset = gibtype*12;
+ NewState(new,new->state);
+ }
+
+ if (MISCVARS->directgibs == true)
+ {
+ int dx,dy,dz;
+
+ dx = PLAYER[0]->x - ob->x;
+ dy = ob->y - PLAYER[0]->y;
+ randtheta = AngleBetween(ob,PLAYER[0]) +
+ (randadj<<4);
+ dz = 100 + (randadj<<3);
+
+#ifdef MEDGIBS
+ nspeed = 0x2800;
+#else
+ nspeed = 0x2800 + (randadj<<7);
+#endif
+
+ randphi = atan2_appx(FindDistance(dx,dy),dz<<10);
+ }
+
+
+ if ((eyespawned == false) && (which == GUTS) &&
+ (ob->obclass != playerobj)
+ )
+ {
+ eyespawned = true;
+ new->flags |= FL_EYEBALL;
+ }
+
+ if ((gibtype >= gt_organ) && (gibtype <= gt_limb))
+ {
+ new->dirchoosetime = GIBVALUE;
+ MISCVARS->numgibs ++;
+ }
+ new->temp2 = gibtype;
+ new->temp3 = (MISCVARS->gibgravity == -1)?(GRAVITY):(MISCVARS->gibgravity);
+
+ new->speed = nspeed>>1;
+
+#ifndef MEDGIBS
+ if (MISCVARS->randgibspeed == true)
+ new->speed += (randadj << 11);
+#endif
+
+// if (ob->state == &s_snakefireworks)
+ new->z = ob->z;
+
+ Fix(randphi);
+ Fix(randtheta);
+
+ Set_3D_Momenta(new,new->speed,randtheta,randphi);
+ new->momentumz <<= 6;
+ new->flags |= (FL_NOFRICTION|FL_CRAZY|FL_ABP|FL_NEVERMARK);
+ if (MISCVARS->fulllightgibs == true)
+ new->flags |= FL_FULLLIGHT;
+ new->dir = west;
+ new->whatever = ob;
+ MakeActive(new);
+ }
+}
+
+
+
+void T_SlideDownScreen(objtype *ob)
+{
+
+ ob->targettiley += 12;
+ if (ob->targettiley > 300)
+ {
+ NewState(ob,&s_megaremove);
+ SCREENEYE = NULL;
+ }
+
+}
+
+void T_SpawnSoul(objtype*ob)
+{
+ if (ob->ticcount)
+ return;
+
+ SpawnNewObj(ob->tilex,ob->tiley,&s_bigsoul,inertobj);
+ new->momentumz = -4000;
+ new->flags |= (FL_NOFRICTION|FL_CRAZY|FL_ABP|FL_NEVERMARK);
+ new->z = ob->z;
+ new->dir = west;
+ MakeActive(new);
+
+ SpawnParticles(ob,gt_lsoul,6);
+
+
+}
+
+
+void BloodDrip(objtype *ob,int tilex,int tiley)
+{ int dx,dy,x,y,scale;
+
+ dx = ob->tilex - tilex;
+ dy = ob->tiley - tiley;
+
+ if (!dy)
+ {
+ scale = (ob->momentumx)?(FixedDiv2(ob->momentumy,ob->momentumx)):(0);
+ x = (dx < 0)?(tilex << 16):((tilex+1) << 16);
+ y = FixedMul(x - ob->x,scale) + ob->y;
+ }
+
+ else if (!dx)
+ {
+ scale = (ob->momentumy)?(FixedDiv2(ob->momentumx,ob->momentumy)):(0);
+ y = (dy < 0)?(tiley << 16):((tiley+1) << 16);
+ x = FixedMul(y - ob->y,scale) + ob->x;
+ }
+
+ ob->temp2 = (GameRandomNumber("BloodDrip",0) << 9) + 0xc000;
+ ob->temp1 = (ob->z<<16);
+ SetFinePosition(ob,x,y);
+ ob->shapeoffset = 0;
+ NewState(ob,&s_blooddrip1);
+
+}
+
+
+
+void T_BloodFall(objtype*ob)
+{
+ ob->temp1 += ob->temp2;
+ ob->z = (ob->temp1 >> 16);
+ if (ob->z >= maxheight)
+ {
+ ob->shapeoffset = 12;
+ MISCVARS->numgibs--;
+ NewState(ob,&s_gibsdone1);
+ ob->z = nominalheight;
+ }
+
+}
+
+
+
+
+void T_Xylophone(objtype*ob)
+{
+ if (!ob->ticcount)
+ SD_PlaySoundRTP(SD_ACTORSKELETONSND,ob->x,ob->y);
+}
+
+
+
+void T_ParticleGenerate(objtype*ob)
+{
+
+ if (ob->dirchoosetime)
+ ob->dirchoosetime--;
+ else
+ {
+ SetGibSpeed(0x3000);
+ SpawnParticles(ob,gt_sparks,(GameRandomNumber("particle count",0) % 10) + 7);
+ ResetGibSpeed();
+ ob->dirchoosetime = 10;
+ if (GameRandomNumber("particle generator choose time",0) < 128)
+ ob->dirchoosetime >>= 1;
+ }
+
+}
+
+
+
+void T_Particle(objtype*ob)
+{ int dx,dy,dz;
+
+ ob->z += (ob->momentumz>>16);
+
+ if ((ob->z >= nominalheight) || (!ob->momentumz))
+
+ {
+ if (ob->z >= nominalheight)
+ ob->z = nominalheight;
+//done:
+ if (ob->temp2 == gt_spit)
+ ob->state = NULL;
+ else
+ {
+ if (ob->dirchoosetime == GIBVALUE)
+ {
+ MISCVARS->numgibs--;
+ SD_PlaySoundRTP(GIBSOUND,ob->x,ob->y);
+ }
+ NewState(ob,&s_gibsdone1);
+ }
+ return;
+ }
+ else if ((ob->z < -64) && (sky == 0))
+ {
+ ob->momentumz = 1; //any positive value will do
+ ob->z = -64;
+
+ }
+
+
+ ob->momentumz += ob->temp3;
+ ActorMovement(ob);
+
+
+ if (!BATTLEMODE)
+ {
+ dx = abs(ob->x - PLAYER[0]->x);
+ dy = abs(ob->y - PLAYER[0]->y);
+ dz = abs(ob->z - PLAYER[0]->z);
+
+#if (SHAREWARE==0)
+ if ((ob->flags & FL_EYEBALL) && (dx < 0x20000) && (dy < 0x20000) &&
+ (dz < 64) && (GameRandomNumber("eye chance",0) < 15) &&
+ (SCREENEYE == NULL) && (locplayerstate->weapon != wp_dog)
+ )
+#else
+ if ((ob->flags & FL_EYEBALL) && (dx < 0x20000) && (dy < 0x20000) &&
+ (dz < 64) && (GameRandomNumber("eye chance",0) < 15) &&
+ (SCREENEYE == NULL)
+ )
+#endif
+ SpawnScreenEye(ob);
+ }
+
+//MoveActor(ob);
+//if ((!ob->momentumx) && (!ob->momentumy))
+ //goto done;
+
+
+}
+
+
+
+void DropItemInEmptyTile(int item,int tilex,int tiley)
+{
+ int stilex = tilex;
+ int stiley = tiley;
+
+ FindEmptyTile(&stilex,&stiley);
+ SpawnStatic(stilex,stiley,item,9);
+ LASTSTAT->flags |= FL_ABP;
+ MakeStatActive(LASTSTAT);
+
+}
+
+extern boolean enableExtraPistolDrops;
+
+void KillActor(objtype*ob)
+{ int ocl;
+
+ ocl = ob->obclass;
+
+
+//GivePoints(starthitpoints[gamestate.difficulty][ob->obclass]*5);
+ if ((ocl == highguardobj) &&
+ (GameRandomNumber("Drop mp40 chance",0) < 25))
+ {
+ DropItemInEmptyTile(stat_mp40,ob->tilex,ob->tiley);
+ }
+
+ else if ((ocl == blitzguardobj) && (ob->temp3))
+ {
+ DropItemInEmptyTile(ob->temp3,ob->tilex,ob->tiley);
+ LASTSTAT->ammo = ob->temp2;
+ }
+ else if ((ocl >= lowguardobj && ocl != highguardobj && ocl <= blitzguardobj) &&
+ (GameRandomNumber("Drop extra pistol chance", 0) < 25) && enableExtraPistolDrops)
+ {
+ DropItemInEmptyTile(stat_twopistol, ob->tilex, ob->tiley);
+ }
+
+
+ if (actorat[ob->tilex][ob->tiley] == (void*)ob)
+ actorat[ob->tilex][ob->tiley] = NULL;
+
+ gamestate.killcount++;
+ ob->flags &= ~FL_SHOOTABLE;
+ ob->flags &= ~FL_BLOCK;
+ ob->flags |= FL_NEVERMARK;
+#if (SHAREWARE == 0)
+ if (ocl == b_darksnakeobj)
+ { if (ob == SNAKEHEAD)
+ { SpawnNewObj(ob->tilex,ob->tiley,&s_megaexplosions,inertobj);
+ new->temp1 = 7000;
+ new->flags |= FL_ABP;
+ EXPLOSIONS = new;
+ NewState(ob,&s_darkmonkheaddie1);
+ MakeActive(new);
+ ob->dirchoosetime = 0;
+
+ }
+ else
+ { objtype *temp;
+
+ SNAKEEND = (objtype*)(ob->target);
+ SNAKEEND->whatever = NULL;
+ NewState(ob,&s_explosion1);
+ for(temp=SNAKEHEAD; temp; temp = (objtype*)(temp->whatever))
+ temp->speed += 0x500;
+ }
+ }
+ else
+#endif
+ { ob->whatever = NULL;
+ if (ob->obclass!=playerobj)
+ ob->target = NULL;
+ }
+
+ if ((ob->flags & FL_KEYACTOR) && (ocl!=playerobj) && (ocl != blitzguardobj))
+ { MISCVARS->KEYACTORSLEFT --;
+ if (!MISCVARS->KEYACTORSLEFT)
+ { SpawnNewObj(ob->tilex,ob->tiley,&s_timekeeper,inertobj);
+ new->flags |= FL_ABP;
+ MakeActive(new);
+ }
+ }
+
+}
+
+
+void T_End(objtype *ob)
+{
+ if (ob->ticcount)
+ return;
+
+ if (MAPSPOT(0,5,2) == LASTLEVELVALUE)
+ playstate = ex_gameover;
+ else
+ playstate = ex_bossdied;
+
+}
+
+
+
+void T_Convert(objtype*ob)
+{
+ if (ob->ticcount)
+ return;
+
+ if (ob->obclass == playerobj)
+ {
+ if (ob->state == &s_vaporized8)
+ {
+ T_SpawnSoul(ob);
+ NewState(ob,&s_voidwait);
+ }
+ else if (ob->state == &s_skeleton48)
+ {
+ playertype *pstate;
+
+ M_LINKSTATE(ob,pstate);
+ if ((pstate->falling == true) ||
+ (!ob->momentumz)
+ )
+ NewState(ob,&s_ashwait);
+ else
+ CheckPlayerSpecials(ob);
+
+
+ }
+ }
+ else
+ {
+ if (ob->state == &s_vaporized8)
+ T_SpawnSoul(ob);
+ else if (ob->state == &s_skeleton48)
+ TurnActorIntoSprite(ob);
+ }
+}
+
+void TurnActorIntoSprite(objtype *ob)
+{ statobj_t*temp;
+ objtype *tactor;
+
+
+ if (!firstemptystat)
+ temp = (statobj_t*)Z_LevelMalloc(sizeof(statobj_t),PU_LEVELSTRUCT,NULL);
+
+ else
+ { temp = lastemptystat;
+ //SoftError("\nfree actor available");
+ RemoveFromFreeStaticList(lastemptystat);
+ }
+
+
+ if (temp)
+ {
+ if ((ob->obclass == blitzguardobj) &&
+ ((ob->flags & FL_PLEADING) || (ob->flags & FL_UNDEAD))
+ )
+ MISCVARS->NUMBEGGINGKEVINS = 0;
+
+
+ if (ob->obclass == roboguardobj)
+ { for(tactor=firstareaactor[ob->areanumber]; tactor; tactor=tactor->nextinarea)
+ { if (tactor == ob)
+ continue;
+ if (tactor->obclass != ob->obclass)
+ continue;
+
+ if (tactor->flags & FL_DYING)
+ continue;
+ if (!tactor->state->think)
+ NewState(tactor,UPDATE_STATES[PATH][tactor->obclass-lowguardobj]);
+
+ }
+ }
+
+ memset(temp,0,sizeof(*temp));
+ temp->shapenum = ob->shapenum;
+ temp->linked_to = -1;
+ temp->whichstat = statcount ++;
+ SetFinePosition(temp,ob->x,ob->y);
+ temp->areanumber = MAPSPOT(temp->tilex,temp->tiley,0)-AREATILE;
+// if ((temp->areanumbers<=0) || (temp->areanumber>NUMAREAS))
+ // Error ("Sprite at x=%ld y=%ld type=%ld has an illegal areanumber\n",tilex,tiley,mtype);
+
+ temp->visspot = &spotvis[temp->tilex][temp->tiley];
+ temp->which = SPRITE;
+ temp->itemnumber = -1;
+ temp->flags = FL_DEADBODY;
+ if (ob->flags & FL_COLORED)
+ { playertype *pstate;
+
+ M_LINKSTATE(ob,pstate);
+ temp->flags |= FL_COLORED;
+ temp->hitpoints = pstate->uniformcolor;
+ }
+ temp->z = ob->z;
+ AddStatic(temp);
+// sprites[temp->tilex][temp->tiley] = temp;
+
+ if (areabyplayer[temp->areanumber])
+ { temp->flags |= FL_ABP;
+ MakeStatActive(temp);
+ }
+ if (ob->state != &s_guts12)
+ actorat[ob->tilex][ob->tiley] = temp;
+ ob->state = NULL; // say goodbye actor
+ }
+ else
+ Error("Z_LevelMalloc failed in TurnActorIntoSprite!");
+
+}
+
+
+void T_Blood(objtype*ob)
+{
+ if (ob->dirchoosetime)
+ { ob->dirchoosetime --;
+ return;
+ }
+
+ ob->dirchoosetime = 35 + (GameRandomNumber("blood time",0) % 20);
+ NewState(ob,&s_deadblood1);
+
+}
+
+
+
+
+void ActorDeath(objtype*ob)
+{
+#if (SHAREWARE == 0)
+ if (ob->obclass == b_heinrichobj)
+ {
+ KillActor(ob);
+ ob->temp1 = ob->dirchoosetime = 5;//10; // init. spin counter for heinrich
+ ob->temp3 = 7; //number of times to stay at fast spin
+ ob->temp2 = ob->dir; //temp2 holds orig. dir.
+ }
+
+ else if (ob->obclass == b_robobossobj)
+ {
+ objtype *wheels,*head;
+
+
+ head = (objtype*)(ob->whatever);
+ wheels = (objtype*)(ob->target);
+ head->flags &= ~(FL_HEAD|FL_SHOOTABLE|FL_BLOCK);
+ head->temp2 = 5;
+ head->flags |= (FL_NOFRICTION|FL_CRAZY);
+// head->obclass = inertobj;
+ //RemoveObj(wheels); // remove wheels
+ KillActor(ob);
+ ob->whatever = head;
+ ob->target = wheels;
+ //ob->temp1 = 25;
+ //ob->shapeoffset = 0;
+ SpawnNewObj(ob->tilex,ob->tiley,&s_megaexplosions,inertobj);
+ new->temp1 = 18;
+ new->flags |= FL_ABP;
+ MakeActive(new);
+ //ob->state = NULL;
+ NewState(ob,&s_NMEdeathbuildup);
+ }
+ else
+#endif
+ if ((ob->state == ob->state->next) &&
+ (ob->flags & FL_DYING)
+ )
+ {
+ KillActor(ob);
+ TurnActorIntoSprite(ob);
+ if (LASTSTAT->z < nominalheight)
+ {
+ if ((!IsPlatform(LASTSTAT->tilex,LASTSTAT->tiley)) &&
+ (DiskAt(LASTSTAT->tilex,LASTSTAT->tiley) == NULL)
+ )
+ {
+ SpawnParticles(ob,GUTS,10 + gamestate.difficulty);
+ RemoveStatic(LASTSTAT);
+ }
+ }
+ /*
+ else if ((GameRandomNumber("blood spray",0) < 300) && areabyplayer[ob->areanumber])
+ {ob->shapeoffset = 0;
+ ob->temp2 = ob->temp3 = 0;
+ ob->temp1 = 10;
+ NewState(ob,&s_deadblood1);
+ return;
+ }
+ */
+ }
+}
+
+
+
+
+void BeginPostPainAction(objtype *ob)
+{
+
+ if ((ob->obclass == strikeguardobj) &&
+ (ob->target == (void*)PLAYER[0])
+ )
+ { //ob->target = NULL;
+ if (LOW_VIOLENCE_DEATH_IS_SET(ob))
+ RESET_DEATH_SHAPEOFFSET(ob);
+
+ if (GameRandomNumber("T_Collide",0) < 128)
+ NewState(ob,&s_strikerollright1);
+ else
+ NewState(ob,&s_strikerollleft1);
+
+ SelectRollDir(ob);
+
+ if (ob->dirchoosetime)
+ {
+ SD_PlaySoundRTP(SD_STRIKEROLLSND,ob->x,ob->y);
+ return;
+ }
+
+ }
+
+ if (LOW_VIOLENCE_PAIN_IS_SET(ob))
+ RESET_PAIN_SHAPEOFFSET(ob);
+
+ if (ob->obclass < roboguardobj)
+ ob->flags &= ~FL_NOFRICTION;
+
+ if (
+ (ob->obclass == blitzguardobj) &&
+ (gamestate.violence == vl_excessive) &&
+ (GameRandomNumber("blitzplead",0) < 128) &&
+ (MISCVARS->NUMBEGGINGKEVINS == 0) &&
+ (ob->flags & FL_TARGET) &&
+
+ (ob->hitpoints < (starthitpoints[gamestate.difficulty][ob->obclass] >> 1)) &&
+ (ob->momentumz == 0) &&
+ (!(ob->flags & FL_UNDEAD))
+ )
+
+ {
+ NewState(ob,&s_blitzplead1);
+ MISCVARS->NUMBEGGINGKEVINS = 1;
+ ob->momentumx = ob->momentumy = 0;
+ ob->flags |= FL_PLEADING;
+ ob->flags &= ~FL_TARGET;
+ ob->dirchoosetime = 165;
+ ob->hitpoints = 1;
+ }
+
+ else
+ {
+ NewState(ob,M_S(CHASE));
+ ob->targettilex = ob->targettiley = 0;
+ ob->dirchoosetime = 0;
+ }
+
+}
+
+
+
+void T_Collide(objtype*ob)
+{
+ if (!(ob->flags & FL_SHOOTABLE))
+ return;
+
+ ActorMovement(ob);
+
+ if (ob->state == NULL)
+ return;
+
+ if (ob->ticcount)
+ return;
+
+ if (ob->hitpoints <= 0)
+ {
+
+ if ((ob->soundhandle == -1) &&
+ (!ob->ticcount) &&
+ (ob->state->next->tictime == 0)
+ )
+ {
+ ob->soundhandle = SD_PlaySoundRTP(ACTORTHUDSND,ob->x,ob->y);
+
+ }
+
+ if (ob->momentumx || ob->momentumy || ob->momentumz)
+ return;
+
+ ActorDeath(ob);
+ return;
+ }
+
+ BeginPostPainAction(ob);
+
+}
+
+
+
+/*
+=========================================================================
+=
+= Special Blitzguard Functions
+=
+=========================================================================
+*/
+
+
+/*
+=================
+=
+= T_Plead
+=
+=================
+*/
+
+
+
+void T_Plead(objtype*ob)
+{
+ int handle;
+
+ ActorMovement(ob);
+ if (ob->dirchoosetime)
+ {
+ if (!(ob->dirchoosetime & 31))
+ {
+ int random = GameRandomNumber("blitz plead sound",0);
+ if (random < 80)
+ SD_PlaySoundRTP(SD_BLITZPLEADSND,ob->x,ob->y);
+ else if (random < 160)
+ SD_PlaySoundRTP(SD_BLITZPLEAD1SND,ob->x,ob->y);
+ else
+ SD_PlaySoundRTP(SD_BLITZPLEAD2SND,ob->x,ob->y);
+ }
+ ob->dirchoosetime --;
+ return;
+ }
+ ob->hitpoints = (starthitpoints[gamestate.difficulty][blitzguardobj]>>1);
+//ob->flags |= FL_DYING;
+ ob->flags |= FL_UNDEAD;
+ SET_DEATH_SHAPEOFFSET(ob);
+ NewState(ob,&s_blitzfakedie1);
+ ob->flags &= ~FL_PLEADING;
+ ob->dirchoosetime = (GameRandomNumber("blitz fake time",0) >> 2) + 70;
+ handle = SD_PlaySoundRTP(SD_BLITZOUCHSND,ob->x,ob->y);
+ SD_SetSoundPitch (handle,-500);
+ ob->temp1 = 0;
+ ob->temp1 = (GameRandomNumber("blitz visible rise",0) < 60);
+
+}
+
+
+
+/*
+=================
+=
+= T_ReallyDead
+=
+=================
+*/
+
+
+void T_ReallyDead(objtype *ob)
+{
+ ActorMovement(ob);
+ if ((!ob->ticcount) && (LOW_VIOLENCE_DEATH_SHOULD_BE_SET(ob)))
+ SET_DEATH_SHAPEOFFSET(ob);
+
+
+}
+
+
+
+/*
+=================
+=
+= T_PlayDead
+=
+=================
+*/
+
+
+
+void T_PlayDead(objtype *ob)
+{
+ int dangle;
+
+ ob->flags &= ~FL_DYING;
+
+ ActorMovement(ob);
+ if (ob->dirchoosetime)
+ {
+ ob->dirchoosetime--;
+ return;
+ }
+
+ dangle = abs(player->angle - AngleBetween(player,ob));
+ if (dangle > ANGLES/2)
+ dangle = ANGLES - dangle;
+
+ if (ob->temp1 || (dangle > ANGLES/4))
+ {
+ if (LOW_VIOLENCE_DEATH_IS_SET(ob))
+ RESET_DEATH_SHAPEOFFSET(ob);
+ ob->temp1 = 0;
+
+ NewState(ob,&s_blitzrise2);
+
+ }
+
+}
+
+
+void AdjustAngle(int maxadjust, short int *currangle,int targetangle)
+{
+ int dangle,i,magangle;
+
+ for(i=0; i<maxadjust; i++)
+ {
+ dangle = *currangle - targetangle;
+
+ if (dangle)
+ {
+ magangle = abs(dangle);
+ if (magangle > (ANGLES/2))
+ {
+ if (dangle > 0)
+ (*currangle) ++;
+ else
+ (*currangle) --;
+ }
+ else
+ {
+ if (dangle > 0)
+ (*currangle) --;
+ else
+ (*currangle) ++;
+ }
+ Fix(*currangle);
+ }
+ }
+}
+
+
+void ResolveMinimumDistance(objtype *heatseeker, objtype *potential_target,
+ int *currmin)
+{
+ int currdist,angle,magangle;
+
+
+ currdist = FindDistance((heatseeker->x-potential_target->x),
+ (heatseeker->y-potential_target->y));
+ angle = AngleBetween(heatseeker,potential_target);
+
+
+ if (heatseeker->obclass != p_godballobj)
+ {
+ magangle = abs(heatseeker->angle - angle);
+ if (magangle > VANG180)
+ magangle = ANGLES - magangle;
+ if (magangle > ANGLESDIV8)
+ return;
+ }
+
+ if (currdist > LOOKAHEAD)
+ return;
+
+ if (currdist < (*currmin))
+ {
+ *currmin = currdist;
+ heatseeker->target = potential_target;
+ }
+}
+
+
+
+
+void HeatSeek(objtype*ob)
+{ int xydist;
+
+ int mindist;
+ objtype* tactor;
+ objtype* owner;
+ statobj_t* tstat;
+ int angle,dz,yzangle,adjust;
+ int dx,dy;
+
+
+ owner=(objtype *)ob->whatever;
+
+ if (ob->dirchoosetime)
+ ob->dirchoosetime --;
+
+ else
+ {
+ if (!ob->target)
+ { mindist = 0x7fffffff;
+
+ for (tactor=firstactive; tactor; tactor=tactor->nextactive)
+ {
+ if (tactor == owner)
+ continue;
+
+ if (tactor->flags & FL_HEAD)
+ continue;
+
+ if ((tactor == ob) ||
+ (!(tactor->flags & FL_SHOOTABLE)) ||
+ (tactor->flags & FL_DYING))
+ continue;
+
+ if (!CheckLine(ob,tactor,SIGHT))
+ continue;
+
+ if ((tactor->obclass == bladeobj) || (tactor->obclass == NMEsaucerobj))
+ continue;
+
+
+ ResolveMinimumDistance(ob,tactor,&mindist);
+
+ }
+
+ if (ob->obclass != p_godballobj)
+ {
+ for(tstat=firstactivestat; tstat; tstat=tstat->nextactive)
+ {
+ if (!(tstat->flags & FL_HEAT))
+ continue;
+
+ if (!CheckLine(ob,tstat,SHOOT))
+ continue;
+
+ ResolveMinimumDistance(ob,(objtype*)tstat,&mindist);
+ }
+ }
+
+
+ if (!ob->target)
+ ob->dirchoosetime = 5;
+ }
+
+ else //if (ob->target != owner)
+ {
+ tactor = (objtype*)ob->target;
+
+ if ((!tactor->nextactive) && (!tactor->prevactive))
+ {
+ ob->target = NULL;
+ return;
+ }
+ dx = tactor->x - ob->x;
+ dy = ob->y - tactor->y;
+ dz = ob->z - tactor->z;
+ //xydist = FixedSqrtHP((FixedMul(dx,dx) + FixedMul(dy,dy))>>16);
+ xydist = FindDistance(dx,dy);
+ angle = atan2_appx(dx,dy);
+ adjust = (ob->obclass == p_godballobj)?(GODHAPT):(HAAPT);
+ AdjustAngle(adjust,&(ob->angle),angle);
+ ob->dir = angletodir[ob->angle];
+ ob->momentumx = FixedMul(ob->speed,costable[ob->angle]);
+ ob->momentumy = -FixedMul(ob->speed,sintable[ob->angle]);
+
+ yzangle = atan2_appx(xydist,(dz<<10));
+ adjust = (ob->obclass == p_godballobj)?(GODVAPT):(VAAPT);
+ AdjustAngle(adjust,&(ob->yzangle),yzangle);
+ ob->momentumz = -(FixedMul(ob->speed,sintable[ob->yzangle]));
+
+ }
+ }
+
+}
+
+
+void Stagger(objtype*ob)
+{
+ int randadj;
+
+
+ randadj = (int)(GameRandomNumber("Stagger",1) >> 3);
+
+ if (!ob->dirchoosetime)
+ {
+ ob->momentumz = ob->temp1 + (RandomSign() << 12);
+ ob->dirchoosetime = 6;
+ }
+ else
+ ob->dirchoosetime --;
+
+ if ((ob->z + (ob->momentumz >> 10)) > (maxheight-12))
+ ob->momentumz = -ob->momentumz;
+ else if ((ob->z < 5) && (!sky))
+ ob->z = 5;
+
+ ob->angle += (RandomSign()*randadj);
+ Fix(ob->angle);
+ ob->momentumx = FixedMul(ob->speed,costable[ob->angle]);
+ ob->momentumy = -FixedMul(ob->speed,sintable[ob->angle]);
+ ob->dir = angletodir[ob->angle];
+
+}
+
+
+
+
+void SpawnSplit(objtype *ob,int angle)
+{
+ Fix(angle);
+ SpawnMissile(ob,p_heatseekobj,ob->speed,angle,&s_p_bazooka1,0x4000);
+ new->momentumz = ob->momentumz;
+ new->whatever = ob->whatever;
+
+}
+
+
+
+void SplitMissile(objtype*ob)
+{
+
+ SD_PlaySoundRTP(SD_SPLITSND,ob->x,ob->y);
+ if (ob->soundhandle != -1)
+ SD_StopSound(ob->soundhandle);
+
+ SpawnSplit(ob,ob->angle + ANGLES/12);
+ SpawnSplit(ob,ob->angle - ANGLES/12);
+
+ if (missobj == ob)
+ {
+ if (GameRandomNumber("split misscam",0)<128)
+ missobj = LASTACTOR;
+ else
+ missobj = LASTACTOR->prev;
+ }
+
+ ob->state=NULL; // get rid of current missile
+
+}
+
+
+
+
+void SpawnMissileSmoke(objtype *ob)
+{
+ if (!ValidAreanumber(AREANUMBER(ob->tilex,ob->tiley)))
+ return;
+
+ SpawnStatic(ob->tilex,ob->tiley,stat_missmoke,-1);
+ LASTSTAT->flags |= FL_ABP;
+ MakeStatActive(LASTSTAT);
+ SetFinePosition(LASTSTAT,ob->x,ob->y);
+ LASTSTAT->z = ob->z+3;
+
+}
+
+
+void T_Projectile (objtype *ob)
+{
+ objtype *owner;
+ playertype * pstate;
+
+ owner = (objtype*)(ob->whatever);
+
+ if (owner->obclass == playerobj)
+ M_LINKSTATE(owner,pstate);
+
+ if ((ob->soundhandle != -1) &&
+ (!(oldpolltime & 7))
+ )
+ SD_PanRTP(ob->soundhandle,ob->x,ob->y);
+#if (SHAREWARE == 0)
+ if (ob->obclass == h_mineobj)
+ {
+ if (!ob->dirchoosetime)
+ {
+ NewState(ob,&s_grexplosion1);
+ SD_PlaySoundRTP(SD_KRISTMINEHITSND,ob->x,ob->y);
+ }
+ else
+ ob->dirchoosetime --;
+ if (
+ (ob->state == &s_mine1) &&
+ (!ob->ticcount)
+ )
+ SD_PlaySoundRTP(BAS[ob->obclass].operate,ob->x,ob->y);
+
+ }
+#endif
+
+
+ if (!ob->ticcount)
+ {
+ if (ob->state == &s_p_grenade)
+ ob->momentumz += (GRAVITY>>6);
+ else if
+ (ob->state == &s_grenade_fall6)
+ {
+ NewState(ob,&s_explosion1);
+ return;
+ }
+ }
+
+
+
+
+ if (ob->obclass == p_drunkmissileobj)
+ {
+ if (ob->temp3 > 0)
+ {
+ ob->temp3 --;
+ Stagger(ob);
+ }
+ else
+ {
+ if (ob->target == NULL)
+ Stagger(ob);
+ HeatSeek(ob);
+ }
+
+ }
+
+ else if (ob->temp1 == NME_DRUNKTYPE)
+
+ Stagger(ob);
+
+
+ else if ((ob->obclass == p_heatseekobj) ||
+ (ob->obclass == dm_heatseekobj) ||
+ (ob->temp1 == NME_HEATSEEKINGTYPE) ||
+ (ob->obclass == p_godballobj)
+ )
+ HeatSeek(ob);
+
+
+ else if
+ ((ob->obclass == p_splitmissileobj) &&
+ (!pstate->buttonstate[bt_attack])
+ )
+ {
+ SplitMissile(ob);
+ return;
+ }
+
+
+
+
+ if ((!BATTLEMODE) &&
+ (!(ob->ticcount & 7)) &&
+ (ob->obclass != p_firewallobj) &&
+ (ob->obclass != p_kesobj) &&
+ (ob->obclass != p_godballobj) &&
+ ((ob->obclass >= p_bazookaobj) || (ob->obclass == missileobj))
+ )// &&
+
+ SpawnMissileSmoke(ob);
+
+ MissileMovement(ob);
+
+ if (ob->obclass == grenadeobj)
+
+ {
+ if (ob->temp1 > 0)
+ ob->temp1 -= ob->speed;
+ else if (!(ob->flags & FL_DONE))
+ {
+ NewState(ob,&s_grenade_fall1);
+ ob->flags |= FL_DONE;
+ }
+ }
+}
+
+
+
+void StartFirewall(objtype*ob, int newz)
+{
+ objtype *owner = (objtype*)(ob->whatever);
+
+ MISCVARS->firespawned = 0;
+ owner->temp1 = 0;
+ SpawnFirewall(ob,2,newz);
+ if (missobj == ob)
+ missobj = LASTACTOR;
+ NewState(ob,&s_megaremove);
+
+}
+
+
+
+void MissileMovement(objtype*ob)
+{ int tryx, tryy,tryz;
+
+ tryx = ob->x + ob->momentumx;
+ tryy = ob->y + ob->momentumy;
+ tryz = ob->z + (ob->momentumz >> 10);
+ if (!MissileTryMove (ob, tryx, tryy, tryz))
+ return;
+ ob->z += (ob->momentumz >> 10);
+ MoveActor(ob);
+}
+
+
+
+#define DetonateMissile(x,y) \
+{MissileHit(x,y); \
+ return false; \
+} \
+
+#define QuietDetonate(ob) \
+ { \
+ if (ob->soundhandle != -1) \
+ SD_StopSound(ob->soundhandle); \
+ if (ob == missobj) \
+ missobj = NULL; \
+ NewState(ob,&s_megaremove); \
+ return false; \
+ }
+
+extern boolean ricochetingRocketsEnabled = 0;
+
+boolean MissileTryMove(objtype*ob,int tryx,int tryy,int tryz)
+{
+ int tilexlow,tileylow,tilexhigh,tileyhigh,x,y,
+ trytilex,trytiley,dx,dy,dzt,dztp1,radius,
+ sprrad,actrad,tcl,ocl,oldsrad,area,zdist,
+ wall;
+
+ objtype *temp;
+ wall_t *tempwall;
+ doorobj_t *tempdoor;
+ int doorn;
+ statobj_t *tempstat;
+ boolean areatried[NUMAREAS] = {0};
+
+ sprrad = 0x4500;
+ actrad = ACTORSIZE+0x2800;
+ ocl = ob->obclass;
+ radius = PROJSIZE-0x2200;
+ if (ocl==wallfireobj)
+ radius-=0x3000;
+ trytilex = (tryx >> TILESHIFT);
+ trytiley = (tryy >> TILESHIFT);
+
+
+ if (IsWindow(trytilex,trytiley) || (!InMapBounds((tryx>>16),(tryy>>16))))
+ {
+ QuietDetonate(ob);
+ }
+
+
+
+ /*
+ */
+//==== ceiling/floor clipping =================//
+
+ if (tryz < -30)
+ { if ((sky==0) || (ocl == inertobj))
+ {
+ DetonateMissile(ob,NULL);
+ }
+ /*
+ else
+ return true;
+ */
+ /*
+ else
+ {
+ NewState(ob,&s_megaremove);
+ if (missobj == ob)
+ missobj = NULL;
+
+ return false;
+ }
+ */
+ }
+
+
+ if (tryz > (maxheight-10))
+ {
+ if ((ocl == p_firewallobj) && (!(ob->flags & FL_ISFIRE)))
+ StartFirewall(ob,nominalheight);
+ else
+ MissileHit(ob,NULL);
+ return false;
+ }
+
+//=============================================//
+
+ sprrad = PROJSIZE+0x1000;
+
+
+ tilexlow = (int)((tryx-radius) >>TILESHIFT);
+ tileylow = (int)((tryy-radius) >>TILESHIFT);
+
+ tilexhigh = (int)((tryx+radius) >>TILESHIFT);
+ tileyhigh = (int)((tryy+radius) >>TILESHIFT);
+
+ oldsrad = sprrad;
+
+
+ if (ocl == inertobj)
+ goto walls;
+
+ area = ob->areanumber;
+ areatried[area] = true;
+actors:
+ for(temp=firstareaactor[area]; temp; temp=temp->nextinarea)
+ {
+ if (temp == ob)
+ continue;
+
+ dx = abs(tryx - temp->x);
+ dy = abs(tryy - temp->y);
+ if ((dx > actrad) || (dy > actrad))
+ continue;
+
+ if (temp->flags & FL_HEAD)
+ continue;
+
+ if ((!(temp->flags & FL_BLOCK)) || (temp->flags & FL_DYING))
+ continue;
+
+ tcl = temp->obclass;
+
+
+ zdist = 32;
+ dzt = abs(tryz - temp->z);
+
+ if ((tcl == playerobj) && (temp->flags & FL_DOGMODE))
+ {
+ dzt = abs(tryz - (temp->z + 30));
+ zdist = 10;
+ }
+ else if (tcl == diskobj)
+ {
+ zdist = 50;
+ }
+
+ if (dzt > zdist)
+ continue;
+
+
+
+ //if ((ocl==wallfireobj) && (tcl==playerobj) && (temp->flags&FL_DOGMODE) && (dz>15))
+ // continue;
+
+ //if ((ocl==playerobj) &&
+ // (ob->whatever == (void*)temp))
+ //continue;
+
+ if (ob->whatever && (ob->whatever == temp->whatever))// &&
+ // (ocl == tcl))// missiles with same owner
+ // go through each other
+ continue;
+
+ if (!(ob->flags & FL_ISFIRE))
+ {
+
+ int random;
+
+ if (tcl != b_darkmonkobj)
+ {
+ MissileHit(ob,temp);
+ ob->target = NULL;
+ if (tcl == wallfireobj)
+ MissileHit(temp,NULL);
+ if (((ocl == p_kesobj) || (ocl == p_godballobj)) && (tcl < pillarobj))
+ continue;
+ else
+ return false;
+ }
+ random = GameRandomNumber("empower darkmonk",0);
+#if (SHAREWARE == 0)
+
+ if (ocl == p_kesobj)
+ {
+ NewState(ob,&s_megaremove);
+ //ob->state = NULL;
+ temp->hitpoints += (((random>>3)+140)<<1);
+ CAP_OSCUROS_HITPOINTS(temp);
+ }
+ else if (ocl == p_firebombobj)
+ {
+ NewState(ob,&s_explosion1);
+ temp->hitpoints += (((random>>3)+70)<<1);
+ CAP_OSCUROS_HITPOINTS(temp);
+
+ ob->target = NULL;
+ }
+ else
+ {
+ NewState(ob,&s_explosion1);
+ temp->hitpoints += (((random>>3)+50)<<1);
+ CAP_OSCUROS_HITPOINTS(temp);
+
+ ob->target = NULL;
+ }
+ temp->temp3 = ocl;
+ temp->speed = 5*SPDPATROL;
+ NewState(temp,&s_darkmonkreact);
+#endif
+ return false;
+ }
+
+ else if (tcl < roboguardobj)
+ { if ((temp->z == nominalheight) &&
+ (!((tcl == playerobj) && ((temp->flags & FL_GODMODE) || (temp->flags & FL_DOGMODE) || godmode))))
+ {
+ if (tcl == playerobj)
+ {
+ playertype *pstate;
+ objtype *owner = (objtype*)(ob->whatever);
+
+ M_LINKSTATE(temp,pstate);
+ if (temp->flags & FL_AV)
+ { pstate->protectiontime = 1;
+ if (temp==player)
+ GM_UpdateBonus (pstate->protectiontime, false);
+ continue;
+ }
+
+
+ //temp->flags &= ~FL_COLORED;
+ pstate->health = 0;
+ pstate->weapon = -1;
+ if (owner->obclass == playerobj)
+ BATTLE_PlayerKilledPlayer(battle_kill_with_missile,owner->dirchoosetime,temp->dirchoosetime);
+
+
+ }
+
+
+ temp->flags |= FL_SKELETON;
+ temp->hitpoints = 0;
+ Collision(temp,ob->whatever,-temp->momentumx,-temp->momentumy);
+ }
+ continue;
+ }
+
+
+
+ else
+ {
+ NewState(ob,&s_megaremove);
+ ob->target = NULL;
+#if (SHAREWARE == 0)
+ if (tcl == b_darkmonkobj)
+ NewState(temp,&s_darkmonkfspark1);
+#endif
+ }
+
+ return false;
+
+ }
+
+
+ for (y=tileylow; y<=tileyhigh; y++)
+ for (x=tilexlow; x<=tilexhigh; x++)
+ {
+ area = AREANUMBER(x,y);
+ if (ValidAreanumber(area) && (areatried[area]==false))
+ {
+ areatried[area] = true;
+ goto actors;
+ }
+ }
+
+
+ /******************* WALLS/PWALLS *****************************************/
+
+walls:
+
+ for (y=tileylow; y<=tileyhigh; y++)
+ for (x=tilexlow; x<=tilexhigh; x++)
+ {
+
+
+ tempwall = (wall_t*)actorat[x][y];
+ wall=tilemap[x][y];
+
+ if (tempwall && M_ISWALL(tempwall) && (tempwall->which!=MWALL))
+ { if (ocl == h_mineobj)
+ {
+ if (WallCheck(ob->x-ob->momentumx, tryy))
+ { ob->momentumx = -ob->momentumx;
+ continue;
+ }
+ else if (WallCheck(tryx, ob->y-ob->momentumy))
+ { ob->momentumy = -ob->momentumy;
+ continue;
+ }
+ }
+ //richocheting rockets stuff
+ if ((ocl == p_bazookaobj ||
+ ocl == p_firebombobj ||
+ ocl == p_heatseekobj ||
+ ocl == p_drunkmissileobj ||
+ ocl == p_firewallobj ||
+ ocl == p_splitmissileobj ||
+ ocl == p_kesobj) && ricochetingRocketsEnabled)
+ {
+ if (WallCheck(ob->x-ob->momentumx, tryy))
+ {
+ ob->momentumx = -ob->momentumx;
+ int rand;
+
+ rand = RandomNumber("Spawn Ricochet Sound in SpawnGunSmoke",0);
+ if (rand < 80)
+ SD_PlaySoundRTP(SD_RICOCHET1SND,ob->x,ob->y);
+ else if (rand < 160)
+ SD_PlaySoundRTP(SD_RICOCHET2SND,ob->x,ob->y);
+ else
+ SD_PlaySoundRTP(SD_RICOCHET3SND,ob->x,ob->y);
+ continue;
+ }
+ else if (WallCheck(tryx, ob->y-ob->momentumy))
+ {
+ ob->momentumy = -ob->momentumy;
+ int rand;
+
+ rand = RandomNumber("Spawn Ricochet Sound in SpawnGunSmoke",0);
+ if (rand < 80)
+ SD_PlaySoundRTP(SD_RICOCHET1SND,ob->x,ob->y);
+ else if (rand < 160)
+ SD_PlaySoundRTP(SD_RICOCHET2SND,ob->x,ob->y);
+ else
+ SD_PlaySoundRTP(SD_RICOCHET3SND,ob->x,ob->y);
+
+ continue;
+ }
+ else
+ {
+ DetonateMissile(ob,tempwall);
+ }
+ }
+ else {
+ DetonateMissile(ob,tempwall);
+ }
+ //MissileHit(ob,tempwall);
+ //return false;
+ }
+
+
+ tempstat = sprites[x][y];
+ sprrad = oldsrad;
+
+ if (tempstat &&
+ ((tempstat->flags & FL_SHOOTABLE) || (tempstat->flags & FL_BLOCK)))
+ {
+
+ if ((tempstat->itemnumber >= stat_bcolumn) &&
+ (tempstat->itemnumber <= stat_icolumn))
+ sprrad += 0x5000;
+
+ dx = tryx - tempstat->x;
+ if ((dx < -sprrad) || (dx > sprrad))
+ continue;
+
+ dy = tryy - tempstat->y;
+ if ((dy < -sprrad) || (dy > sprrad))
+ continue;
+
+//#define MINSTATZDIFF 60
+
+ dzt = abs(ob->z - tempstat->z);
+ dztp1 = abs(tryz - tempstat->z);
+ /*
+ if (ocl == p_firewallobj)// && (dztp1 <= MINSTATZDIFF))
+ {
+ if (ob->flags & FL_ISFIRE)
+ {
+ int cz = (ob->z - tempstat->z + MINSTATZDIFF);
+
+ if ((cz >= -MAXSTEPHEIGHT) && (cz <= 0))
+ {
+ ob->z = tempstat->z - MINSTATZDIFF;
+ tryz = ob->z + (ob->momentumz >> 16);
+ dzt = MINSTATZDIFF;
+ }
+ }
+
+ if ((dztp1 >= MINSTATZDIFF) || (dzt >= MINSTATZDIFF))
+ continue;
+
+ if (!(ob->flags & FL_ISFIRE))
+ {
+ StartFirewall(ob,tempstat->z - MINSTATZDIFF);
+ return false;
+ }
+ }
+
+
+ else*/
+ {
+ if (dztp1 > 50)
+ continue;
+
+ DetonateMissile(ob,tempstat);
+ }
+ //MissileHit(ob,tempstat);
+ //return false;
+ }
+ }
+
+
+//mwalls:
+
+
+
+ if (M_ISMWALL(trytilex,trytiley))
+ {
+ maskedwallobj_t * mw;
+
+ wall=tilemap[trytilex][trytiley];
+ //tempwall = (wall_t*)actorat[trytilex][trytiley];
+
+
+ mw=maskobjlist[wall&0x3ff];
+
+ if (!(mw->flags&MW_BLOCKING))
+ {
+
+ if ((levelheight > 1) &&
+ (((!(mw->flags & MW_ABOVEPASSABLE)) && (tryz <= 32)) ||
+ ((!(mw->flags & MW_MIDDLEPASSABLE)) && (tryz > 25) && (tryz < nominalheight-32)) ||
+ ((!(mw->flags & MW_BOTTOMPASSABLE)) && (tryz > maxheight - 74))
+ )
+ )
+ DetonateMissile(ob,NULL);
+
+ }
+
+ else if (mw->flags&MW_SHOOTABLE)
+ {
+ if (ob->z >= maxheight-64)
+ {
+ UpdateMaskedWall(tilemap[trytilex][trytiley]&0x3ff);
+ }
+ else
+ DetonateMissile(ob,NULL);
+
+ }
+
+ else
+ DetonateMissile(ob,NULL);
+ //MissileHit(ob,tempwall);
+ //return false;
+ }
+
+
+
+ /******************* DOOR STUFF ******************************************/
+
+
+ else if (M_ISDOOR(trytilex,trytiley))
+ {
+ doorn = tilemap[trytilex][trytiley];
+ tempdoor = doorobjlist[doorn&0x3ff];
+ if (tempdoor->position>=0x8000)
+ {
+ if (ob->z>maxheight-64)
+ return true;
+ }
+ DetonateMissile(ob,tempdoor);
+ }
+
+ return true;
+
+
+}
+
+
+
+void SpawnFirewall(objtype*ob,int which,int newz)
+{ int i,j,count,newx,newy;
+ objtype* owner;
+ wall_t*tempwall;
+ statetype* frame;
+ int offset;
+
+ owner = (objtype*)(ob->whatever);
+
+ if ((owner->temp1 < 2) && (MISCVARS->firespawned < 14))
+ { for(i=0; i<=which; i++)
+ {
+ GetNewActor ();
+ MakeActive(new);
+ MISCVARS->firespawned ++;
+ new->obclass = p_firewallobj;
+ new->which = ACTOR;
+ new->areanumber = ob->areanumber;
+ MakeLastInArea(new);
+ offset = 0x6000;
+ if (!which)
+ new->temp1 = ob->temp1;
+ else if (i==1)
+ new->temp1 = ob->angle + ANGLES/4;
+ else if (i==2)
+ new->temp1 = ob->angle - ANGLES/4;
+ else
+ {
+ new->temp1 = 0;
+ offset = 0;
+ new->flags |= FL_DONE;
+ }
+
+ Fix(new->temp1);
+
+ new->speed = 0x8000;
+ new->angle = ob->angle;
+ ParseMomentum(new,new->angle);
+ newx = ob->x + FixedMul(offset,costable[new->temp1]);
+ newy = ob->y - FixedMul(offset,sintable[new->temp1]);
+ SetFinePosition(new,newx,newy);
+ SetVisiblePosition(new,newx,newy);
+ new->whatever = ob->whatever;
+ new->dirchoosetime = 2;
+ new->flags |= (FL_NEVERMARK|FL_ABP|FL_NOFRICTION);
+ count = (int)(GameRandomNumber("SpawFireWall",0) & 15);
+
+ for(frame = &s_fireunit1,j=0; j<count; frame = frame->next,j++);
+
+ NewState(new,frame);
+ new->flags |= FL_ISFIRE;
+ //SD_Play(SD_EXPL);
+ tempwall = (wall_t*)actorat[new->tilex][new->tiley];
+ new->z = newz;
+ if (tempwall && M_ISWALL(tempwall))
+ {
+ SetFinePosition(new,ob->x,ob->y);
+ SetVisiblePosition(new,ob->x,ob->y);
+ owner->temp1++;
+ }
+ }
+ }
+
+}
+
+
+void T_Firethink(objtype*ob)
+{
+
+ if (ob->dirchoosetime)
+ ob->dirchoosetime--;
+ else if (!(ob->flags & FL_DONE))
+ {
+ SpawnFirewall(ob,0,ob->z);
+ ob->flags |= FL_DONE;
+ }
+
+ MissileMovement(ob);
+
+}
+
+
+
+void ResolveRide(objtype *ob)
+{
+ objtype *ride = (objtype*)(ob->whatever);
+
+ if (M_ISACTOR(ride) && (ob->obclass != playerobj))
+ {
+ if (ob->flags & FL_RIDING)
+ {
+ int dx,dy;
+
+ dx = ob->x - ride->x;
+ dy = ob->y - ride->y;
+ if ((dx < -MINACTORDIST) || (dx > MINACTORDIST) ||
+ (dy < -MINACTORDIST) || (dy > MINACTORDIST) )
+ {
+ ride->whatever = NULL;
+ ob->whatever = NULL;
+ ob->flags &= ~FL_RIDING;
+ }
+ }
+ }
+
+}
+
+
+
+
+void MoveActor(objtype*ob)
+{
+ int linked,oldarea,newarea,
+ tilex,tiley,oldtilex,oldtiley;
+
+ linked = 0;
+
+ ResolveRide(ob);
+
+ oldtilex = ob->tilex;
+ oldtiley = ob->tiley;
+
+ SetFinePosition(ob,ob->x+ob->momentumx,ob->y+ob->momentumy);
+ /*
+ if (ob->state == &s_explosion1)
+ Error("moving explosion"); */
+
+ if ((ob->obclass == playerobj) || (ob->flags & FL_NOFRICTION) || (ob->state->think == T_Collide) ||
+ (ob->obclass == b_heinrichobj) || (ob->obclass == h_mineobj))
+
+ SetVisiblePosition(ob,ob->x,ob->y);
+
+
+
+ if (ob->obclass == inertobj)
+ return;
+
+ if ((ob->obclass == b_darksnakeobj) && (ob != SNAKEHEAD))
+ {
+ oldarea = ob->areanumber;
+ newarea = SNAKEHEAD->areanumber;
+ if (oldarea != newarea)
+ {
+ RemoveFromArea(ob);
+ ob->areanumber = newarea;
+ MakeLastInArea(ob);
+ }
+ return;
+
+ }
+
+
+ oldarea = ob->areanumber;
+ newarea = AREANUMBER(ob->tilex,ob->tiley);
+ if (!(ob->flags & (FL_NONMARK|FL_NEVERMARK)))
+ {
+ if ((oldtilex != ob->tilex) || (oldtiley != ob->tiley))
+ {
+ if (actorat[oldtilex][oldtiley] == (void*)ob)
+ actorat[oldtilex][oldtiley] = NULL;
+ if (actorat[ob->tilex][ob->tiley])
+ {
+ objtype* temp;
+
+ temp = (objtype*)actorat[ob->tilex][ob->tiley];
+ if (temp->which != SPRITE)
+ actorat[ob->tilex][ob->tiley] = ob;
+ }
+ else
+ actorat[ob->tilex][ob->tiley] = ob;
+ }
+ }
+
+
+#define CheckAdjacentArea(x,y) \
+ { \
+ if (InMapBounds(x,y)) \
+ { \
+ temparea = AREANUMBER(x,y); \
+ if (ValidAreanumber(temparea)) \
+ newarea = temparea; \
+ } \
+ }
+
+
+ if (!ValidAreanumber(newarea)) //find empty tile
+ {
+ int temparea;
+ tilex = ob->tilex;
+ tiley = ob->tiley;
+
+ CheckAdjacentArea(tilex+1,tiley);
+ CheckAdjacentArea(tilex-1,tiley);
+ CheckAdjacentArea(tilex,tiley+1);
+ CheckAdjacentArea(tilex,tiley-1);
+
+ }
+ //Error("new area invalid for actor %d, class %d",
+ // ob-&objlist[0],ob->obclass);
+
+
+//====================== swap in linked lists =====================
+ if (oldarea != newarea)
+ {
+ RemoveFromArea(ob);
+ ob->areanumber = newarea;
+ MakeLastInArea(ob);
+ }
+}
+
+
+
+void SpawnPushColumn(int tilex,int tiley,int which,int dir, int linked)
+{
+ if (which==0)
+ {
+ SpawnNewObj(tilex,tiley,&s_pushcolumn1,pillarobj);
+// for (i=0;i<(levelheight-1);i++)
+// SpawnStatic(tilex,tiley,stat_bcolumn,-(i<<6));
+ }
+ else if (which==1)
+ {
+ SpawnNewObj(tilex,tiley,&s_pushcolumn2,pillarobj);
+// for (i=0;i<(levelheight-1);i++)
+// SpawnStatic(tilex,tiley,stat_gcolumn,-(i<<6));
+ }
+ else
+ {
+ SpawnNewObj(tilex,tiley,&s_pushcolumn3,pillarobj);
+// for (i=0;i<(levelheight-1);i++)
+// SpawnStatic(tilex,tiley,stat_icolumn,-(i<<6));
+ }
+ PreCacheActor(pillarobj,which);
+
+ gamestate.secrettotal++;
+ new->speed = PILLARMOM;
+ new->temp1 = 0x20000;
+ new->temp2 = linked;
+ new->flags |= (FL_BLOCK|FL_NOFRICTION);
+ new->flags &= ~FL_SHOOTABLE;
+ new->flags |= FL_HEIGHTFLIPPABLE;
+ new->dir = dir;
+ if (dir != nodir)
+ ParseMomentum(new,dirangle8[new->dir]);
+
+
+}
+
+
+
+void SpawnWallfire(int tilex, int tiley, int dir)
+{ int offx,offy;
+
+
+ GetNewActor();
+ new->speed = 0x2000;
+ SetTilePosition(new,tilex,tiley);
+ SetVisiblePosition(new,new->x,new->y);
+ new->obclass = wallfireobj;
+ new->dir = dir*2;
+ new->flags |= (FL_BLOCK|FL_NOFRICTION|FL_NEVERMARK);
+ new->flags &= ~FL_SHOOTABLE;
+ new->which = ACTOR;
+ new->angle = dirangle8[new->dir];
+ offx = FixedMul(0x10000,costable[new->angle])>>TILESHIFT;
+ offy = -(FixedMul(0x10000,sintable[new->angle])>>TILESHIFT);
+
+ new->areanumber = MAPSPOT(new->tilex+offx,new->tiley+offy,0)-AREATILE;
+ MakeLastInArea(new);
+
+ NewState(new,&s_wallfireball);
+
+}
+
+
+
+void SpawnSneaky(int tilex,int tiley)
+{
+
+ SpawnNewObj(tilex,tiley,&s_sneakydown,lowguardobj);
+ new->temp3 = SNEAKY;
+ if (!loadedgame)
+ gamestate.killtotal++;
+ StandardEnemyInit(new,north>>1);
+
+ PreCacheActor(lowguardobj,0);
+}
+
+
+void RespawnEluder(void)
+{
+ int rand,count;
+ int nx,ny;
+
+ rand = (GameRandomNumber("eluder respawn",0) % NUMSPAWNLOCATIONS);
+
+ for(count=0; count < NUMSPAWNLOCATIONS; count++)
+ {
+ if (!actorat[SPAWNLOC[rand].x][SPAWNLOC[rand].y])
+ {
+ SpawnCollector(SPAWNLOC[rand].x,SPAWNLOC[rand].y);
+ return;
+ }
+ rand= ((rand + 1) % NUMSPAWNLOCATIONS);
+
+ }
+
+//MED
+ nx = SPAWNLOC[rand].x;
+ ny = SPAWNLOC[rand].y;
+ FindEmptyTile(&nx,&ny);
+ SpawnCollector(nx,ny);
+}
+
+//****************************************************************************
+//
+//
+//
+//****************************************************************************
+
+void SpawnCollector(int tilex, int tiley)
+{
+#if (SHAREWARE == 0)
+ if ( dopefish==true )
+ {
+ SpawnNewObj(tilex,tiley,&s_scottwander1,collectorobj);
+ }
+ else
+#endif
+ {
+ SpawnNewObj(tilex,tiley,&s_collectorwander1,collectorobj);
+ }
+
+ new->flags |= (FL_SHOOTABLE|FL_BLOCK|FL_NOFRICTION|FL_FULLLIGHT);
+ new->hitpoints = 500;
+ new->speed = 0x3000;
+ new->dir = north;
+ new->dirchoosetime = 175;
+ new->z = PlatformHeight(tilex,tiley);
+ if (new->z == -10)
+ new->z = 0;
+ if (areabyplayer[new->areanumber])
+ { new->flags |= FL_ABP;
+ MakeActive(new);
+ }
+
+}
+
+
+
+void SelectDoorDir(objtype*ob)
+{ int dx,dy,actrad;
+ dirtype dtry1,dtry2,tdir,olddir;
+
+ dx= ob->targettilex - ob->x;
+ dy= ob->y - ob->targettiley;
+ olddir = ob->dir;
+ if ((abs(dx) < 0x4000) && (abs(dy) < 0x4000))
+ { ZEROMOM;
+ SetFinePosition(ob,ob->targettilex,ob->targettiley);
+ SetVisiblePosition(ob,ob->x,ob->y);
+ ParseMomentum(ob,dirangle8[ob->temp2]);
+ ActorMovement(ob);
+ ob->temp2 = 0;
+ ob->temp1 = 20;
+#if (SHAREWARE == 0)
+ if ( dopefish==true )
+ {
+ NewState(ob,&s_scottwander1);
+ }
+ else
+#endif
+ {
+ NewState(ob,&s_collectorwander1);
+ }
+ ob->targettilex = ob->targettiley = 0;
+ ob->dirchoosetime = 165;
+ return;
+ }
+
+
+ ZEROMOM;
+
+ ParseMomentum(ob,atan2_appx(dx,dy));
+ ActorMovement(ob);
+ if (ob->momentumx || ob->momentumy)
+ return;
+ actrad = ACTORSIZE;
+ dtry1=nodir;
+ dtry2=nodir;
+
+ if (dx> actrad)
+ dtry1= east;
+ else if (dx< -actrad)
+ dtry1= west;
+ if (dy> actrad)
+ dtry2= north;
+ else if (dy < -actrad)
+ dtry2= south;
+
+
+ if (abs(dy)>abs(dx))
+ { tdir=dtry1;
+ dtry1=dtry2;
+ dtry2=tdir;
+ }
+
+
+ if (dtry1 != nodir)
+ M_CHECKDIR(ob,dtry1);
+
+ if (dtry2 != nodir)
+ M_CHECKDIR(ob,dtry2);
+
+ if (dtry1 != nodir)
+ M_CHECKDIR(ob,dirorder[dtry1][NEXT]);
+
+ if (dtry2 != nodir)
+ M_CHECKDIR(ob,dirorder[dtry2][NEXT]);
+
+ for(tdir = dirorder[olddir][NEXT]; tdir != olddir; tdir = dirorder[tdir][NEXT])
+ M_CHECKDIR(ob,tdir);
+ ob->dir = olddir;
+
+}
+
+
+boolean EluderCaught(objtype*ob)
+{
+ objtype *temp;
+ int dx,dy,dz;
+ playertype *pstate;
+ int dist = 0xc000;
+
+ for(temp = PLAYER[0]; temp != PLAYER[numplayers-1]->next; temp=temp->next)
+ {
+#if (SHAREWARE == 0)
+ if (temp->state != &s_doguse)
+ continue;
+#endif
+
+ dx = M_ABS(temp->x - ob->x);
+ if (dx > dist)
+ continue;
+
+ dy = M_ABS(temp->y - ob->y);
+ if (dy > dist)
+ continue;
+
+ dz = M_ABS(temp->z - ob->z);
+ if (dz > (dist>>10))
+ continue;
+
+ M_LINKSTATE(temp,pstate);
+ //if (DOGSCRATCH.attackinfo[pstate->attackframe].attack == at_pulltrigger)
+ { BATTLE_CheckGameStatus(battle_caught_eluder,temp->dirchoosetime);
+ SpawnNewObj(ob->tilex,ob->tiley,&s_itemspawn1,inertobj);
+ new->flags |= FL_ABP;
+ SetFinePosition(new,ob->x,ob->y);
+ SetVisiblePosition(new,ob->x,ob->y);
+ new->z = ob->z;
+ SD_PlaySoundRTP(SD_GETBONUSSND,ob->x,ob->y);
+ MakeActive(new);
+ NewState(ob,&s_megaremove);
+ return true;
+ }
+
+ }
+
+ return false;
+}
+
+
+void T_CollectorFindDoor(objtype*ob)
+{
+
+ if (EluderCaught(ob))
+ return;
+
+ if (!(gamestate.TimeCount % 17))
+ SD_PlaySoundRTP(SD_MONKGRABSND,ob->x,ob->y);
+
+
+ if ((ob->z != nominalheight) && (!IsPlatform(ob->tilex,ob->tiley)))
+ ZEROMOM;
+
+
+
+ if (ob->dirchoosetime)
+ ob->dirchoosetime --;
+ else
+ {
+#if (SHAREWARE == 0)
+ if ( dopefish==true )
+ {
+ NewState(ob,&s_scottwander1);
+ }
+ else
+#endif
+ {
+ NewState(ob,&s_collectorwander1);
+ }
+ ob->dirchoosetime = 165;
+ ob->targettilex = ob->targettiley = 0;
+ return;
+ }
+
+ if (ob->temp1)
+ { int dx,dy;
+
+ ob->temp1 --;
+ ActorMovement(ob);
+ dx = ob->targettilex-ob->x;
+ dy = ob->targettiley-ob->y;
+ if ((abs(dx) < 0x4000) && (abs(dy) < 0x4000))
+ { ZEROMOM;
+ SetFinePosition(ob,ob->targettilex,ob->targettiley);
+ SetVisiblePosition(ob,ob->x,ob->y);
+
+ ParseMomentum(ob,dirangle8[ob->temp2]);
+ ActorMovement(ob);
+ ob->temp2 = 0;
+ ob->temp1 = 35;
+#if (SHAREWARE == 0)
+ if ( dopefish==true )
+ {
+ NewState(ob,&s_scottwander1);
+ }
+ else
+#endif
+ {
+ NewState(ob,&s_collectorwander1);
+ }
+ ob->targettilex = ob->targettiley = 0;
+ ob->dirchoosetime = 165;
+ return;
+ }
+ if (NOMOM)
+ ob->temp1 = 0;
+ return;
+ }
+
+
+
+ ob->temp1 = 5;
+
+ if (ob->targettilex || ob->targettiley)
+ SelectDoorDir(ob);
+
+ else
+ { int i;
+ doorobj_t* dptr;
+
+//==========================================================================
+#define SetCollectorTarget(xoffset,yoffset,newdir) \
+ { \
+ ob->targettilex = ((dptr->tilex + (xoffset)) << TILESHIFT) + HALFGLOBAL1; \
+ ob->targettiley = ((dptr->tiley + (yoffset)) << TILESHIFT) + HALFGLOBAL1; \
+ ob->temp2 = newdir; \
+ if (GameRandomNumber("collector door search",0) < 100) \
+ return; \
+ }
+//==========================================================================
+
+ for(i=0; i<doornum; i++)
+ { dptr = doorobjlist[i];
+ if (dptr->vertical)
+ {
+ int area1 = AREANUMBER(dptr->tilex-1,dptr->tiley),
+ area2 = AREANUMBER(dptr->tilex+1,dptr->tiley);
+
+ if (area1 == ob->areanumber)
+ SetCollectorTarget(-1,0,east)
+
+ else if (area2 == ob->areanumber)
+ SetCollectorTarget(1,0,west);
+
+ }
+ else
+ {
+ int area1 = AREANUMBER(dptr->tilex,dptr->tiley-1),
+ area2 = AREANUMBER(dptr->tilex,dptr->tiley+1);
+
+ if (area1 == ob->areanumber)
+ SetCollectorTarget(0,-1,south)
+
+ else if (area2 == ob->areanumber)
+ SetCollectorTarget(0,1,north);
+
+ }
+ }
+ }
+
+}
+
+
+void T_CollectorWander(objtype*ob)
+{
+
+ int newtilex,newtiley;
+
+ if (EluderCaught(ob))
+ return;
+
+ if ((ob->z != nominalheight) && (!IsPlatform(ob->tilex,ob->tiley)))
+ ZEROMOM;
+
+ if (!(gamestate.TimeCount & 15))//%17
+ SD_PlaySoundRTP(SD_MONKGRABSND,ob->x,ob->y);
+
+ if (ob->dirchoosetime)
+ {
+ if (doornum > 0)
+ ob->dirchoosetime --;
+ }
+
+ else
+ {
+#if (SHAREWARE == 0)
+ if ( dopefish==true )
+ {
+ NewState(ob,&s_scottwanderdoor1);
+ }
+ else
+#endif
+ {
+ NewState(ob,&s_collectorfdoor1);
+ }
+ ob->temp1 = 0;
+ ob->dirchoosetime = 165;
+ ob->targettilex = ob->targettiley = 0;
+ return;
+ }
+
+ if (ob->temp1) // temp1 holds direction time
+ ob->temp1 --;
+ else
+ {
+ dirtype bestdir,tempdir;
+
+ bestdir = angletodir[GameRandomNumber("collector theta",0) << 3];
+
+ for(tempdir = bestdir; tempdir != dirorder[bestdir][PREV]; tempdir = dirorder[tempdir][NEXT])
+ {
+ ParseMomentum(ob,dirangle8[tempdir]);
+ newtilex = ((ob->x + ob->momentumx)>>16);
+ newtiley = ((ob->y + ob->momentumy)>>16);
+ if (IsWindow(newtilex,newtiley))
+ continue;
+ ActorMovement(ob);
+ if (ob->momentumx || ob->momentumy)
+ {
+ ob->temp1 = (GameRandomNumber("collector choose time",0) >> 2);
+ return;
+ }
+ }
+
+ }
+
+ newtilex = ((ob->x + ob->momentumx)>>16);
+ newtiley = ((ob->y + ob->momentumy)>>16);
+
+
+ if (IsWindow(newtilex,newtiley))
+ {
+ ob->temp1 = 0;
+ return;
+ }
+
+
+ ActorMovement(ob);
+
+ if (NOMOM)
+ ob->temp1 = 0;
+}
+
+
+
+
+
+boolean CheckDoor(objtype *ob,doorobj_t * door,int trytilex,int trytiley)
+{ boolean doorok=false;
+
+
+ switch(ob->dir)
+ {
+ case north:
+ if ((ob->tiley == (door->tiley + 1)) && (trytilex == ob->tilex))
+ doorok = true;
+ break;
+
+ case east:
+ if ((ob->tilex == (door->tilex - 1)) && (trytiley == ob->tiley))
+ doorok = true;
+ break;
+
+ case south:
+ if ((ob->tiley == (door->tiley - 1)) && (trytilex == ob->tilex))
+ doorok = true;
+ break;
+
+ case west:
+ if ((ob->tilex == (door->tilex + 1)) && (trytiley == ob->tiley))
+ doorok = true;
+ break;
+ default:
+ ;
+ }
+
+
+ if (doorok)
+ { SetTilePosition(ob,ob->tilex,ob->tiley);
+ SetVisiblePosition(ob,ob->x,ob->y);
+ return true;
+ }
+ return false;
+}
+
+
+boolean WallCheck(int tryx,int tryy)
+{ int tilexlow,tilexhigh,tileylow,tileyhigh,y,x;
+
+ tilexlow = (int)((tryx -PLAYERSIZE) >>TILESHIFT);
+ tileylow = (int)((tryy -PLAYERSIZE) >>TILESHIFT);
+
+ tilexhigh = (int)((tryx + PLAYERSIZE) >>TILESHIFT);
+ tileyhigh = (int)((tryy + PLAYERSIZE) >>TILESHIFT);
+
+
+ for (y=tileylow; y<=tileyhigh; y++)
+ for (x=tilexlow; x<=tilexhigh; x++)
+ { //tempwall = (wall_t*)actorat[x][y];
+ //if (tempwall && M_ISWALL(tempwall))
+ if (tilemap[x][y])
+ return false;
+ }
+
+ return true;
+
+}
+
+
+boolean QuickSpaceCheck(objtype*ob,int tryx, int tryy)
+{ int xlow,xhigh,ylow,yhigh,x,y,dx,dy;
+ objtype* temp;
+
+ xlow = (int)((tryx-ACTORSIZE) >>TILESHIFT);
+ ylow = (int)((tryy-ACTORSIZE) >>TILESHIFT);
+
+ xhigh = (int)((tryx+ACTORSIZE) >>TILESHIFT);
+ yhigh = (int)((tryy+ACTORSIZE) >>TILESHIFT);
+ /******************* WALLS/PWALLS *****************************************/
+
+ for (y=ylow; y<=yhigh; y++)
+ for (x=xlow; x<=xhigh; x++)
+ { temp = (objtype*)actorat[x][y];
+ if ((temp && (temp->which != ACTOR)) ||
+ (sprites[x][y] && (sprites[x][y]->flags & FL_BLOCK))
+
+ || tilemap[x][y])
+ return false;
+ }
+
+ for(temp=firstareaactor[ob->areanumber]; temp; temp=temp->nextinarea)
+ { if (temp == ob)
+ continue;
+ if ((temp->flags & FL_NONMARK) || (temp->flags & FL_NEVERMARK))
+ continue;
+ dx = tryx - temp->x;
+ if ((dx < -MINACTORDIST) || (dx > MINACTORDIST))
+ continue;
+ dy = tryy - temp->y;
+ if ((dy < -MINACTORDIST) || (dy > MINACTORDIST))
+ continue;
+ if (ob->whatever == (void*)temp)
+ continue;
+ if (temp->whatever == ob->whatever)
+ continue;
+ return false;
+ }
+
+ return true;
+
+
+}
+
+
+//=========================================================================
+//
+// ACTOR TRY MOVE MADNESS
+//
+//=========================================================================
+
+typedef enum
+{
+ NO_MOVEMENT,
+ Z_MOVEMENT_ONLY,
+ OK_TO_CONTINUE
+
+} movement_status;
+
+
+
+//==================== Some ActorTryMove macros ==============================
+
+#define CheckProximitySpecials(ob,temp) \
+{ \
+ if (ocl == b_heinrichobj) \
+ { \
+ if (tcl == playerobj) \
+ { \
+ playertype *pstate; \
+ \
+ M_LINKSTATE(temp,pstate); \
+ DamageThing(temp,5); \
+ temp->whatever = ob; \
+ temp->temp2 = COLUMNCRUSH; \
+ pstate->heightoffset += 4; \
+ if (pstate->heightoffset >= 30) \
+ pstate->heightoffset = 30; \
+ pstate->oldheightoffset = pstate->heightoffset; \
+ } \
+ else \
+ { \
+ temp->momentumx = temp->momentumy = temp->momentumz = 0; \
+ temp->hitpoints = 0; \
+ } \
+ if (temp->hitpoints <= 0) \
+ temp->flags |= FL_HBM; \
+ Collision(temp,ob,0,0); \
+ continue; \
+ } \
+ \
+ else if ((ocl == b_darksnakeobj) && (tcl == playerobj)) \
+ { \
+ DamageThing(temp,1); \
+ Collision(temp,ob,0,0); \
+ M_CheckPlayerKilled(temp); \
+ } \
+ \
+ if ((ocl == boulderobj) && (tcl >= lowguardobj) && (tcl < roboguardobj))\
+ {temp->momentumx = temp->momentumy = temp->momentumz = 0; \
+ temp->hitpoints = 0; \
+ temp->flags |= FL_HBM; \
+ Collision(temp,ob,0,0); \
+ SD_PlaySoundRTP(SD_ACTORSQUISHSND,temp->x,temp->y); \
+ continue; \
+ } \
+ \
+ if (pusher && (ocl != tcl) && (!(temp->flags & FL_DYING)) && \
+ (tcl < roboguardobj) \
+ ) \
+ {if ((!ob->ticcount) && (ocl != collectorobj) && (ocl != diskobj))\
+ DamageThing(temp,5); \
+ \
+ if (tcl == playerobj) \
+ temp->flags |= FL_PUSHED; \
+ Collision(temp,ob,ob->momentumx-temp->momentumx,ob->momentumy-temp->momentumy);\
+ M_CheckPlayerKilled(temp); \
+ continue; \
+ } \
+ \
+ if (bouncer) \
+ {ob->momentumx = -ob->momentumx; \
+ continue; \
+ } \
+ }
+
+
+
+#define CheckStepping(ob,step,minzdiff) \
+{ \
+ int cz = (ob->z - step->z + minzdiff); \
+ \
+ if ((cz >= -MAXSTEPHEIGHT) && (cz <= MAXSTEPHEIGHT)) \
+ {if ((ob->obclass == playerobj) && (ob->temp2 == 0) && \
+ (ob->z != (step->z - minzdiff)) \
+ ) \
+ { \
+ playertype *pstate; \
+ \
+ M_LINKSTATE(ob,pstate); \
+ \
+ pstate->heightoffset = pstate->oldheightoffset + cz; \
+ ob->temp2 = (cz >= 0)?(STEPUP):(STEPDOWN); \
+ } \
+ ob->z = step->z - minzdiff; \
+ tryz = ob->z + (ob->momentumz >> 16); \
+ dzt = minzdiff; \
+ } \
+} \
+
+
+
+
+//============ Players crushing other players =====================
+
+void BattleCrushCheck(objtype *ob,objtype *listrover) \
+{
+ if ((ob->obclass == playerobj) && (listrover->obclass == playerobj))
+ {
+ playertype * pstate;
+
+ M_LINKSTATE(listrover,pstate);
+ if (pstate->health <= 0)
+ BATTLE_PlayerKilledPlayer(battle_kill_by_crushing,ob->dirchoosetime,
+ listrover->dirchoosetime);
+ }
+}
+
+
+//=================================================================
+
+
+
+
+
+movement_status CheckOtherActors(objtype*ob,int tryx,int tryy,int tryz)
+{
+ objtype *listrover;
+ int area;
+ int op;
+ int areatried[NUMAREAS]= {0};
+ int tilexlow,tilexhigh,tileylow,tileyhigh;
+ int radius,actrad,oldrad;
+ boolean bouncer,pusher,thinkingactor,zstoppable,ACTORSTOP;
+ int dzt,dztp1,checkz;
+ int x,y,dx,dy;
+ int ocl,tcl;
+ int ISPLAYER = 0;
+ int hoffset;
+
+ ocl = ob->obclass;
+
+ actrad = MINACTORDIST;//ACTORSIZE+0x2800;
+ pusher = ((ocl == wallopobj) || (ocl == pillarobj) ||
+ (ocl == roboguardobj) || (ocl == collectorobj) ||
+ (ocl == boulderobj) || (ocl == diskobj)
+ );
+
+ thinkingactor = ((ocl != playerobj) && (ob->state->think != T_Collide) &&
+ (ocl < roboguardobj)
+ );
+
+ zstoppable = (!(ob->flags & FL_DYING));
+ bouncer = ((ocl == playerobj) && (ob->flags & FL_ELASTO));
+ radius = ACTORSIZE;
+
+
+ if (ocl != playerobj)
+ {
+ //actrad = MINACTORDIST;
+ //if ((ob->dir == nodir) && (ocl != b_robobossobj) &&
+ // (ocl != wallopobj) && (ocl != roboguardobj) && (ocl != diskobj)
+ // )
+ // Error("ob called with nodir");
+ if (ocl == boulderobj)
+ radius += (ACTORSIZE/4);
+ else if (ocl == b_darksnakeobj)
+ radius -= 6000;
+ else if (ocl == inertobj)
+ radius -= 0x2000;
+ }
+
+ else
+ {
+ ISPLAYER = 1;
+ if (ob->flags & FL_DOGMODE)
+ hoffset = 10;
+ }
+
+
+
+ tilexlow = (int)((tryx-radius) >>TILESHIFT);
+ tileylow = (int)((tryy-radius) >>TILESHIFT);
+
+ tilexhigh = (int)((tryx+radius) >>TILESHIFT);
+ tileyhigh = (int)((tryy+radius) >>TILESHIFT);
+
+ area = ob->areanumber;
+ areatried[area] = 1;
+ ACTORSTOP = false;
+ oldrad = actrad;
+
+actors:
+ for(listrover=firstareaactor[area]; listrover; listrover=listrover->nextinarea)
+ {
+ actrad = oldrad;
+
+ if (listrover == ob)
+ continue;
+
+
+ tcl = listrover->obclass;
+
+ if ((tcl == b_darksnakeobj) && (listrover != SNAKEHEAD))
+ continue;
+
+ if (((tcl == bladeobj) || (tcl == firejetobj)) && thinkingactor)
+
+ actrad += 0x3000;
+
+
+ dx = tryx - listrover->x;
+ if ((dx < -actrad) || (dx > actrad))
+ continue;
+
+ dy = tryy - listrover->y;
+ if ((dy < -actrad) || (dy > actrad))
+ continue;
+
+
+ if ((ocl == b_darksnakeobj) && (tcl == ocl))
+ continue;
+
+ if ((tcl == springobj) && (listrover->state->condition & SF_UP) &&
+ (listrover->temp1!=3) && (levelheight > 1) &&
+ (abs(listrover->z - ob->z) < 5) && (!ob->momentumz)
+ )
+ {
+ {
+ op = (FixedMul((int)GRAVITY,(int)((ob->z-10)<<16))<<1);
+ ob->momentumz = -FixedSqrtHP(op);
+ }
+ SD_PlaySoundRTP(SD_SPRINGBOARDSND,listrover->x,listrover->y);
+ NewState(listrover,&s_spring2);
+
+ }
+
+
+
+ if ((tcl == firejetobj) && (ob->z < listrover->z))
+ continue;
+
+ if ((!(listrover->flags & FL_BLOCK)) && (actrad == oldrad)) // if not blocking
+ // and actor not avoiding
+ // env. danger
+ continue;
+
+
+
+ if (tcl == crushcolobj)
+ checkz = listrover->temp2;
+ else
+ checkz = listrover->z;
+
+#define MINACTORZDIFF 58
+
+ dzt = abs(checkz - ob->z);
+ dztp1 = abs(checkz - tryz);
+
+ if ((tcl == diskobj) && (dztp1 <= MINACTORZDIFF) && zstoppable &&
+ (ocl != b_heinrichobj)
+ )
+ CheckStepping(ob,listrover,MINACTORZDIFF);
+
+ dztp1 = abs(checkz - tryz);
+
+
+
+ if ((dzt > (MINACTORZDIFF - 25)) && (dzt < MINACTORZDIFF) &&
+ (dztp1 < MINACTORZDIFF) && (tcl < roboguardobj) &&
+ (ocl < roboguardobj)
+ )
+ {
+ int rdx,rdy;
+
+ rdx = abs(ob->x - listrover->x);
+ rdy = abs(ob->y - listrover->y);
+ if ((rdx < actrad) && (rdy < actrad))
+ {
+ if (ob->z > listrover->z)
+ listrover->z = ob->z - MINACTORZDIFF;
+ else
+ ob->z = listrover->z - MINACTORZDIFF;
+
+ dzt = dztp1 = MINACTORZDIFF;
+ }
+
+ }
+
+
+ if ((dztp1 >= MINACTORZDIFF) || (dzt >= MINACTORZDIFF))
+ {
+ if ((dzt >= MINACTORZDIFF) && (dztp1 <= MINACTORZDIFF) &&
+ zstoppable
+ )
+ { //ob->momentumz = 0;
+ if (ob->z < listrover->z)
+ {
+ ob->z = listrover->z - MINACTORZDIFF;
+ ob->momentumz = 0;
+ }
+ else
+ ob->momentumz = 2*GRAVITY;
+ if ((listrover->z > ob->z) && (tcl < roboguardobj) && (ocl < roboguardobj) &&
+ (!(listrover->flags & FL_DYING))
+ )
+
+ {
+ DamageThing(listrover,5);
+ BattleCrushCheck(ob,listrover);
+ Collision(listrover,ob,listrover->momentumx,listrover->momentumy);
+ /*
+ if ((ocl == playerobj) && (listrover->flags & FL_DYING))
+ GivePoints(starthitpoints[gamestate.difficulty][tcl]);
+ */
+ }
+
+ if (((tcl == bladeobj) || (tcl == diskobj)) && (ob->z < listrover->z))
+ {
+ ob->whatever = listrover;
+ if (listrover->flags & FL_ACTIVE)
+ ob->flags |= FL_RIDING;
+ listrover->whatever = ob;
+ }
+
+ //Debug("\nplayerz %d, tryz %d momz zeroed at %d, clearances %d and %d",
+ // ob->z,tryz,listrover->z-64 + (listrover->momentumz >> 16),dzt,dztp1);
+
+ }
+
+ continue;
+ }
+
+
+ CheckProximitySpecials(ob,listrover);
+
+
+ ACTORSTOP = true;
+ if (!ob->momentumz)
+ return NO_MOVEMENT;
+
+ }
+
+
+ for (y=tileylow; y<=tileyhigh; y++)
+ for (x=tilexlow; x<=tilexhigh; x++)
+ {
+ area = AREANUMBER(x,y);
+ if (ValidAreanumber(area) && (areatried[area]==0))
+ {
+ areatried[area] = 1;
+ goto actors;
+ }
+ }
+
+
+
+ if (ACTORSTOP==true)
+ return Z_MOVEMENT_ONLY;
+
+ return OK_TO_CONTINUE;
+}
+
+
+
+movement_status CheckRegularWalls(objtype *ob,int tryx,int tryy,int tryz)
+{
+ int tilexlow,tilexhigh,tileylow,tileyhigh,x,y,radius;
+ classtype ocl;
+ boolean WALLSTOP,ISPLAYER=false;
+
+ ocl = ob->obclass;
+ tryz=tryz;
+
+
+ if (ocl != playerobj)
+ {
+ radius = ACTORSIZE - 0x1000;
+ //actrad = MINACTORDIST;
+ //if ((ob->dir == nodir) && (ocl != b_robobossobj) &&
+ // (ocl != wallopobj) && (ocl != roboguardobj) && (ocl != diskobj)
+ // )
+ // Error("ob called with nodir");
+ if (ocl == boulderobj)
+ radius += (ACTORSIZE/4);
+ else if (ocl == b_darksnakeobj)
+ radius -= 6000;
+ else if (ocl == inertobj)
+ radius -= 0x2000;
+ }
+
+ else
+ {
+ radius = PLAYERSIZE;
+ ISPLAYER = true;
+ }
+
+
+ tilexlow = (int)((tryx-radius) >>TILESHIFT);
+ tileylow = (int)((tryy-radius) >>TILESHIFT);
+
+ tilexhigh = (int)((tryx+radius) >>TILESHIFT);
+ tileyhigh = (int)((tryy+radius) >>TILESHIFT);
+
+
+ WALLSTOP = false;
+
+ for (y=tileylow; y<=tileyhigh; y++)
+ for (x=tilexlow; x<=tilexhigh; x++)
+ {
+ wall_t *tempwall;
+ int wall;
+
+ tempwall = (wall_t*)actorat[x][y];
+ wall=tilemap[x][y];
+ if (tempwall)
+ {
+ if (tempwall->which==WALL)// && IsWindow(x,y)==false)
+ {
+ if (ocl == boulderobj)
+ {
+#if (SHAREWARE == 0)
+ NewState(ob,&s_bouldersink1);
+#endif
+ SD_PlaySoundRTP(SD_BOULDERHITSND,ob->x,ob->y);
+ }
+ else if (ISPLAYER && (!(ob->flags & FL_DYING)) &&
+ (!(ob->flags & FL_AV)) &&
+ (tempwall->flags & FL_W_DAMAGE))
+ {
+ DamageThing(ob,5);
+ Collision(ob,(objtype*)tempwall,0,0);
+ M_CheckPlayerKilled(ob);
+ SD_PlaySoundRTP(SD_PLAYERBURNEDSND,ob->x,ob->y);
+ }
+
+ //return false;
+ WALLSTOP = true;
+ if ((ocl == inertobj) &&
+ (ob->dirchoosetime == GIBVALUE) &&
+
+ (((ob->tilex - x) == 0) != ((ob->tiley - y) == 0)) &&
+ (ob->z > -28)
+
+ )
+ {
+ // SoftError ("Blood Dripping oldpolltime=%ld\n",oldpolltime);
+ BloodDrip(ob,x,y);
+ return NO_MOVEMENT;
+ }
+
+ if (!ob->momentumz)
+ return NO_MOVEMENT;
+ else// if (ocl != inertobj)
+ return Z_MOVEMENT_ONLY;
+ //else
+ //goto doors;
+ }
+
+ else if (tempwall->which==PWALL)
+ {
+ pwallobj_t*pw;
+ int dx,dy;
+
+ pw=(pwallobj_t *)tempwall;
+ dx = abs(pw->x - tryx);
+ if (dx > PWALLRAD+0x5000)
+ continue;
+
+ dy = abs(pw->y - tryy);
+ if (dy > PWALLRAD+0x5000)
+ continue;
+
+ return NO_MOVEMENT;
+ }
+
+ }
+ }
+
+ return OK_TO_CONTINUE;
+
+}
+
+
+
+movement_status CheckStaticObjects(objtype *ob,int tryx,int tryy,int tryz)
+{
+ int dx,dy,dzt,dztp1,x,y;
+ statobj_t*tempstat;
+ int sprrad,oldsrad,sprtrad;
+ boolean specialstat=false,widestat=false,zstoppable;
+ int sprxlow,sprxhigh,sprylow,spryhigh;
+ boolean SPRSTOP;
+ classtype ocl;
+
+ ocl = ob->obclass;
+
+ if (ocl != playerobj)
+ sprtrad = ACTORSIZE - 0x1000;
+ else
+ sprtrad = ACTORSIZE - 0x1000 + 0x10000;
+
+
+
+ sprxlow = (int)((tryx-sprtrad) >>TILESHIFT);
+ sprylow = (int)((tryy-sprtrad) >>TILESHIFT);
+
+ sprxhigh = (int)((tryx+sprtrad) >>TILESHIFT);
+ spryhigh = (int)((tryy+sprtrad) >>TILESHIFT);
+
+ if (sprxlow < 0)
+ sprxlow = 0;
+
+ if (sprxhigh > (MAPSIZE-1))
+ sprxhigh = MAPSIZE-1;
+
+ if (sprylow < 0)
+ sprylow = 0;
+
+ if (spryhigh > (MAPSIZE-1))
+ spryhigh = MAPSIZE-1;
+
+ SPRSTOP = false;
+ sprrad = 0x4500;
+ zstoppable = (!(ob->flags & FL_DYING));
+ oldsrad = sprrad;
+
+ for (y=sprylow; y<=spryhigh; y++)
+ for (x=sprxlow; x<=sprxhigh; x++)
+ {
+ tempstat = sprites[x][y];
+ sprrad = oldsrad;
+
+ if (tempstat)
+ {
+ specialstat = ((tempstat->itemnumber == stat_heatgrate) ||
+ (tempstat->itemnumber == stat_pit)
+ );
+
+ widestat = (((tempstat->itemnumber >= stat_bcolumn) &&
+ (tempstat->itemnumber <= stat_icolumn)) ||
+ (tempstat->itemnumber == stat_disk)
+ );
+
+ if ((tempstat->flags & FL_BLOCK) || (specialstat==true))
+ {
+ if ((specialstat==true) && (ocl !=playerobj) &&
+ (ob->state->think != T_Collide)
+ )
+ sprrad += 0x5000;
+
+ if (widestat==true)
+ sprrad += 0x3b00;
+
+
+ if ((tempstat->itemnumber == stat_ironbarrel) ||
+ (tempstat->itemnumber == stat_bonusbarrel))
+ sprrad += 0x5000;
+
+ dx = abs(tryx - tempstat->x);
+ if (dx > sprrad)
+ continue;
+ dy = abs(tryy - tempstat->y);
+ if (dy > sprrad)
+ continue;
+
+#define MINSTATZDIFF 58
+
+ dzt = abs(ob->z - tempstat->z);
+ dztp1 = abs(tryz - tempstat->z);
+
+ if (widestat && (dztp1 <= MINSTATZDIFF) && zstoppable &&
+ (ocl != b_heinrichobj)
+ )
+ CheckStepping(ob,tempstat,MINSTATZDIFF);
+
+
+ dztp1 = abs(tryz - tempstat->z);
+
+#if (SHAREWARE == 0)
+ if ((ocl == b_darksnakeobj) && (tempstat->itemnumber == stat_heatgrate))
+ {
+ if (ob->state->think == T_DarkSnakeChase)
+ NewState(ob,&s_darkmonkredhead);
+ else
+ NewState(ob,&s_darkmonkredlink);
+ ob->temp3 ++; // make shootable
+ }
+#endif
+
+ if (specialstat==true)
+ continue;
+
+
+ if ((dztp1 >= MINSTATZDIFF) || (dzt >= MINSTATZDIFF))
+ { if ((dzt >= MINSTATZDIFF) && (dztp1 <= MINSTATZDIFF) && zstoppable)
+ { //ob->momentumz = 0;
+ if (ob->z <= tempstat->z)
+ {
+ ob->z = tempstat->z - MINSTATZDIFF;
+ ob->momentumz = 0;
+ }
+ else
+ ob->momentumz = 2*GRAVITY; // ((2*GRAVITY + GRAVITY) >> 16) = 1
+ }
+ continue;
+ }
+
+
+ if (ocl == boulderobj)
+ { if ((tempstat->itemnumber < stat_bcolumn) ||
+ (tempstat->itemnumber > stat_icolumn)
+ )
+ {
+ tempstat->flags |= FL_SHOOTABLE;
+ DamageThing(tempstat,tempstat->hitpoints);
+ continue;
+ }
+#if (SHAREWARE == 0)
+ else
+ NewState(ob,&s_bouldersink1);
+#endif
+ }
+ //ob->momentumz=0;
+ //return false;
+ SPRSTOP=true;
+ if (!ob->momentumz)
+ return NO_MOVEMENT;
+ }
+ }
+ }
+ if (SPRSTOP == true)
+ return Z_MOVEMENT_ONLY;
+
+ return OK_TO_CONTINUE;
+
+}
+
+
+
+
+
+//============== Platform craziness ======================================
+
+
+#define ClipHeight(ob,clipz) \
+{ ob->momentumz = 0; \
+ \
+ if (ISPLAYER && (ob->z != clipz) && (ob->temp2 == 0)) \
+ {playertype *pstate; \
+ int dz = ob->z - clipz; \
+ \
+ M_LINKSTATE(ob,pstate); \
+ \
+ pstate->heightoffset = pstate->oldheightoffset + dz; \
+ ob->temp2 = (dz >= 0)?(STEPUP):(STEPDOWN); \
+ } \
+ \
+ ob->z = clipz; \
+}
+
+//======================
+
+#define CheckSpecialGibMovement(blocker) \
+ { \
+ int centerx = ((trytilex<<16) + 0x8000); \
+ int centery = ((trytiley<<16) + 0x8000); \
+ \
+ if (blocker->vertical==false) \
+ { \
+ int dyt = centery - ob->y; \
+ int dytp1 = centery - tryy; \
+ \
+ if ((abs(dytp1) > abs(dyt)) && \
+ (SGN(dyt) == SGN(dytp1)) \
+ ) \
+ return OK_TO_CONTINUE; \
+ \
+ } \
+ else \
+ { \
+ int dxt = centerx - ob->x; \
+ int dxtp1 = centerx - tryx; \
+ \
+ if ((abs(dxtp1) > abs(dxt)) && \
+ (SGN(dxt) == SGN(dxtp1)) \
+ ) \
+ return OK_TO_CONTINUE; \
+ \
+ } \
+ }
+
+
+movement_status CheckMaskedWalls(objtype *ob,int tryx,int tryy,int tryz)
+{
+ int trytilex,trytiley;
+ boolean MWALLSTOP;
+ int ISPLAYER = (ob->obclass == playerobj);
+ classtype ocl = ob->obclass;
+
+ trytilex = (tryx >> TILESHIFT);
+ trytiley = (tryy >> TILESHIFT);
+ MWALLSTOP = false;
+//for (y=tileylow;y<=tileyhigh;y++)
+// for (x=tilexlow;x<=tilexhigh;x++)
+
+ if (M_ISMWALL(trytilex,trytiley))
+ {
+ int wall = tilemap[trytilex][trytiley];
+ maskedwallobj_t * mw;
+
+ mw=maskobjlist[wall&0x3ff];
+
+ if (ocl == inertobj)
+ CheckSpecialGibMovement(mw);
+
+ if (!(mw->flags&MW_BLOCKING))
+ {
+ if (mw->flags&MW_NONDOGBLOCKING)
+ {
+ if ((ocl==playerobj)&&(ob->flags&FL_DOGMODE))
+ {
+ if (ob->z < nominalheight)
+ {
+ MWALLSTOP = true;
+ if (!ob->momentumz)
+ return NO_MOVEMENT;
+ }
+ }
+ else
+ {
+ MWALLSTOP = true;
+ if (!ob->momentumz)
+ return NO_MOVEMENT;
+ }
+ }
+
+
+ else
+ {
+ if (mw->flags & MW_ABOVEPASSABLE)
+ { if (mw->flags & MW_MIDDLEPASSABLE) // ==> not bottom
+ { if (ob->z > LOWFALLCLIPZ+MAXSTEPHEIGHT)
+ MWALLSTOP = true;
+ else if (tryz >= LOWFALLCLIPZ)
+ ClipHeight(ob,LOWFALLCLIPZ);
+ }
+ else if (mw->flags & MW_BOTTOMPASSABLE)
+ { if ((ob->z > HIGHFALLCLIPZ+MAXSTEPHEIGHT) && (ob->z < LOWRISECLIPZ))
+ MWALLSTOP = true;
+ else if (ob->z <= HIGHFALLCLIPZ+MAXSTEPHEIGHT)
+ { if (tryz >= HIGHFALLCLIPZ)
+ ClipHeight(ob,HIGHFALLCLIPZ);
+ }
+ else if (tryz <= LOWRISECLIPZ)
+ ob->momentumz = 0;
+
+ }
+ else // ==> above only
+ { if (ob->z > HIGHFALLCLIPZ+MAXSTEPHEIGHT)
+ MWALLSTOP = true;
+ else if (tryz >= HIGHFALLCLIPZ)
+ ClipHeight(ob,HIGHFALLCLIPZ);
+ }
+
+ }
+ else if (mw->flags & MW_MIDDLEPASSABLE)
+ { if (mw->flags & MW_BOTTOMPASSABLE) //==> not above passable
+ { if (ob->z >= HIGHRISECLIPZ)
+ { if (tryz <= HIGHRISECLIPZ)
+ ob->momentumz = 0;
+ }
+ else if (tryz <= HIGHRISECLIPZ)
+ MWALLSTOP = true;
+ }
+
+ else //==> middle only
+ { if (ob->z > LOWFALLCLIPZ+MAXSTEPHEIGHT)
+ MWALLSTOP = true;
+ else if (tryz >= LOWFALLCLIPZ)
+ ClipHeight(ob,LOWFALLCLIPZ)
+ else
+ { if (ob->z >= HIGHRISECLIPZ)
+ { if (tryz <= HIGHRISECLIPZ)
+ ob->momentumz = 0;
+ }
+ else if (tryz <= HIGHRISECLIPZ)
+ MWALLSTOP = true;
+ }
+ }
+
+ }
+ else // ==> bottompassable only
+ { if (ob->z < LOWRISECLIPZ)
+ MWALLSTOP = true;
+ else if (tryz < LOWRISECLIPZ)
+ ob->momentumz = 0;
+ }
+
+ }
+ }
+ else
+ {
+ if ( (mw->flags&MW_SHOOTABLE) &&
+ (mw->flags&MW_BLOCKINGCHANGES) &&
+ (ob->z >= nominalheight)
+
+ )
+ {
+ int speed=FindDistance(ob->momentumx,ob->momentumy);
+ if ((speed>0x2800) && (!(ob->flags & FL_DYING)))
+ {
+ if (ob->obclass == playerobj)
+ {
+ DamageThing(ob,10);
+ Collision(ob,(objtype*)mw,0,0);
+ }
+ UpdateMaskedWall(wall&0x3ff);
+ if (tryz < nominalheight)
+ ob->momentumz = 0;
+ }
+ else
+ {
+ MWALLSTOP = true;
+ if (!ob->momentumz)
+ return NO_MOVEMENT;
+ }
+ }
+ else
+ {
+ MWALLSTOP = true;
+ if (!ob->momentumz)
+ return NO_MOVEMENT;
+ }
+ }
+ }
+
+ if (MWALLSTOP == true)
+ return Z_MOVEMENT_ONLY;
+
+ return OK_TO_CONTINUE;
+
+}
+
+
+
+movement_status CheckDoors(objtype *ob,int tryx,int tryy,int tryz)
+{
+ int trytilex,trytiley;
+ int ocl;
+
+
+ trytilex = (tryx >> TILESHIFT);
+ trytiley = (tryy >> TILESHIFT);
+ ocl = ob->obclass;
+
+
+ if (M_ISDOOR(trytilex,trytiley))
+ {
+ doorobj_t*tempdoor;
+ int doorn;
+
+ doorn = tilemap[trytilex][trytiley];
+
+ tempdoor = doorobjlist[doorn&0x3ff];
+ if (tempdoor->action == dr_open)
+ {
+
+ if (ob->z >= nominalheight)
+ {
+ if (tryz < nominalheight)
+ ob->momentumz = 0;
+ return OK_TO_CONTINUE;
+ }
+
+ }
+ if (ocl == inertobj)
+ {
+ CheckSpecialGibMovement(tempdoor);
+ }
+ else if ((ocl == playerobj) || (ocl > b_darksnakeobj))
+ return NO_MOVEMENT;
+ else if (ob->state->think != T_Collide)
+ {
+
+#define DOOR_LOCKED(door) \
+ (((door->flags & DF_ELEVLOCKED) || (door->lock)) && \
+ (ob->obclass != b_darianobj) \
+ )
+#define GAS_DOOR(x,y) (MISCVARS->GASON && (MAPSPOT(x,y,1) == GASVALUE))
+
+ if ((!DOOR_LOCKED(tempdoor)) &&
+ (!GAS_DOOR(trytilex,trytiley))
+ )
+
+
+ //)
+ {
+ ob->door_to_open = doorn&0x3ff;
+ LinkedOpenDoor(ob->door_to_open);
+ if (tempdoor->eindex != -1)
+ OperateElevatorDoor(doorn&0x3ff);
+ }
+
+ //if ((nstate = M_S(USE)) != NULL)
+ //{ob->whatever = ob->state;
+ // NewState(ob,nstate);
+ // ob->flags |= FL_USE;
+ // }
+ return NO_MOVEMENT;
+ }
+ else
+ return NO_MOVEMENT;
+ }
+
+ return OK_TO_CONTINUE;
+}
+
+
+
+boolean ActorTryMove(objtype*ob,int tryx, int tryy, int tryz)
+{
+
+ movement_status (*reduced_movement_check[3])(objtype*,int,int,int)=
+ {
+ CheckRegularWalls,
+ CheckMaskedWalls,
+ CheckDoors,
+ };
+
+
+ movement_status (*complete_movement_check[5])(objtype*,int,int,int)=
+ {
+ CheckOtherActors,
+ CheckRegularWalls,
+ CheckStaticObjects,
+ CheckMaskedWalls,
+ CheckDoors,
+ };
+
+ movement_status (**movement_function)(objtype*,int,int,int);
+ movement_status movement_check_result;
+ int numcheckfunctions;
+ int i;
+ boolean xyblocked;
+
+
+
+
+ if ((tryz < -30) && (sky==0) && (ob->obclass != inertobj))
+ {
+ ob->z = -28;
+ ob->momentumz = 0;
+ return false;
+ }
+
+ if ((!InMapBounds(tryx>>16,tryy>>16)) ||
+ ((ob->obclass != playerobj) && (IsWindow((tryx>>16),(tryy>>16))))
+ )
+ return false;
+
+ switch(ob->obclass)
+ {
+ case inertobj:
+ case bladeobj:
+ case firejetobj:
+ movement_function = &reduced_movement_check[0];
+ numcheckfunctions = 3;
+ break;
+
+ default:
+ movement_function = &complete_movement_check[0];
+ numcheckfunctions = 5;
+ break;
+ }
+
+
+ for(xyblocked=false,i=0; i<numcheckfunctions; i++)
+ {
+ movement_check_result = movement_function[i](ob,tryx,tryy,tryz);
+ if (movement_check_result == Z_MOVEMENT_ONLY)
+ xyblocked = true;
+
+ else if (movement_check_result == NO_MOVEMENT)
+ return false;
+ }
+
+ if (xyblocked == true)
+ return false;
+
+
+ return true;
+
+}
+
+
+void PushWallMove(int num)
+{
+ int tcl;
+ pwallobj_t *pwall;
+ int dx,dy;
+ int actrad;
+ objtype *temp;
+ boolean pushem;
+ int tryx,tryy,areanumber,trytilex,trytiley;
+
+
+ pwall=pwallobjlist[num];
+
+ actrad = PWALLRAD + 0x5000;
+ tryx = (pwall->x + pwall->momentumx);
+ tryy = (pwall->y + pwall->momentumy);
+ trytilex = (tryx >> 16);
+ trytiley = (tryy >> 16);
+
+ areanumber = AREANUMBER(trytilex,trytiley);
+
+
+ for(temp=firstareaactor[areanumber]; temp; temp=temp->nextinarea)
+ {
+ tcl = temp->obclass;
+
+ if (temp->flags & FL_HEAD) //ignore NME's head and wheels
+ continue;
+
+ if ((temp->flags & FL_DYING) || (!(temp->flags & FL_SHOOTABLE)))
+ continue;
+
+ if (tcl > b_darianobj)
+ continue;
+
+
+ dx = abs(tryx - temp->x);
+ if (dx > actrad)
+ continue;
+
+ dy = abs(tryy - temp->y);
+ if (dy > actrad)
+ continue;
+
+ if (pwall->flags&PW_DAMAGE)
+ { if (!((tcl == playerobj) && (temp->flags & FL_AV)))
+ DamageThing(temp,5);
+
+ Collision(temp,(objtype*)pwall,0,0);
+ M_CheckPlayerKilled(temp);
+ if (temp->flags & FL_DYING)
+ return;
+
+ }
+
+ pushem=false;
+ switch (pwall->dir)
+ {
+
+#define PWALLTOL (0xc000)
+
+ case north:
+ if ((temp->y<pwall->y) && (dx<PWALLTOL))
+ pushem=true;
+ break;
+ case east:
+ if ((temp->x>pwall->x) && (dy<PWALLTOL))
+ pushem=true;
+ break;
+ case northeast:
+ if ((temp->y<pwall->y) && (dx<PWALLTOL))
+ pushem=true;
+ else if ((temp->x>pwall->x) && (dy<PWALLTOL))
+ pushem=true;
+ break;
+ case northwest:
+ if ((temp->y<pwall->y) && (dx<PWALLTOL))
+ pushem=true;
+ else if ((temp->x<pwall->x) && (dy<PWALLTOL))
+ pushem=true;
+ break;
+ case south:
+ if ((temp->y>pwall->y) && (dx<PWALLTOL))
+ pushem=true;
+ break;
+ case west:
+ if ((temp->x<pwall->x) && (dy<PWALLTOL))
+ pushem=true;
+ break;
+ case southeast:
+ if ((temp->y>pwall->y) && (dx<PWALLTOL))
+ pushem=true;
+ else if ((temp->x>pwall->x) && (dy<PWALLTOL))
+ pushem=true;
+ break;
+ case southwest:
+ if ((temp->y>pwall->y) && (dx<PWALLTOL))
+ pushem=true;
+ else if ((temp->x<pwall->x) && (dy<PWALLTOL))
+ pushem=true;
+ break;
+ default:
+ //Error ("Pushwall #%d has an illegal direction %d \n",num,pwall->dir);
+ break;
+ }
+
+
+ //if (!pushem)
+ //continue;
+
+ //temp->momentumx = temp->momentumy = 0;
+ if (temp->obclass==playerobj)
+ temp->flags|=FL_PUSHED;
+
+ if (!pushem)
+ {
+ Collision(temp,(objtype*)pwall,-temp->momentumx,-temp->momentumy);
+ continue;
+ }
+
+ if ((temp->obclass >= lowguardobj) && (temp->obclass < roboguardobj))
+ {
+
+ temp->momentumx = temp->momentumy = temp->momentumz = 0;
+ temp->hitpoints = 0;
+
+ if (gamestate.violence >= vl_high)
+ temp->flags |= FL_HBM;
+ Collision(temp,(objtype*)pwall,0,0);
+ /*
+ if (gamestate.violence < vl_high)
+ {if ((tstate = UPDATE_STATES[CRUSH][temp->obclass - lowguardobj])!=NULL)
+ NewState(temp,tstate);
+
+ else
+ Error("\n\Null low-violence crush state in push wall crush, instance of %s",debugstr[temp->obclass]);
+ }
+ else
+ {temp->shapeoffset = 0;
+ //tactor->flags|=FL_HBM;
+ NewState(temp,&s_guts1);
+ //KillActor(temp);
+ }*/
+
+ SD_PlaySoundRTP(SD_ACTORSQUISHSND,temp->x,temp->y);
+ }
+ else
+ {
+ if (!ActorTryMove(temp,temp->x + temp->momentumx,temp->y + temp->momentumy,
+ temp->z + (temp->momentumz >> 16))
+ )
+ {
+ DamageThing(temp,30);
+ if ((temp->obclass==playerobj) && (temp->hitpoints <= 0))
+ temp->target = (objtype *)pwall;
+ }
+
+ Collision(temp,(objtype*)pwall,pwall->momentumx-temp->momentumx,pwall->momentumy-temp->momentumy);
+ M_CheckPlayerKilled(temp);
+ }
+
+
+
+ }
+}
+
+void ActorMovement (objtype *ob)
+{ int tryx,tryy,tryz,limitok,max,friction,ocl;
+
+
+
+ if ((ob->obclass == strikeguardobj) && (!(ob->flags & FL_DYING)) &&
+ (gamestate.difficulty > gd_easy)
+ )
+ {
+ AvoidPlayerMissile(ob);
+ ob->flags &= ~FL_FULLLIGHT;
+ }
+
+
+ if ((!ob->momentumx) && (!ob->momentumy) && (!ob->momentumz))
+ { if (ob->flags & FL_RIDING)
+ goto ride;
+ else
+ return;
+ }
+
+
+ limitok = 1;
+
+ friction = ACTORFRICTION;
+ if (!(ob->flags & FL_DYING))
+ friction >>= 1;
+ ocl = ob->obclass;
+ if (ocl == playerobj)
+ {
+ playertype *pstate;
+
+ M_LINKSTATE(ob,pstate);
+ max = pstate->topspeed;
+ friction = PLAYERFRICTION;
+ if ((ob->temp2 == PITFALL) || (ob->temp2 == PITRISE))
+ friction >>= 4;
+ }
+
+
+ else if (/*(ob->state->think != T_Collide) &&*/ (ocl != b_robobossobj) &&
+ (ocl != boulderobj) && (ocl !=b_darkmonkobj) && (ocl != b_darksnakeobj) &&
+ (ocl != inertobj) && (ocl != collectorobj))
+ max = MAXMOVE;
+
+ else
+ limitok = 0;
+
+ if (limitok)
+ { if (ocl == playerobj)
+ { int dist,scale;
+
+ dist = FindDistance(ob->momentumx,ob->momentumy);
+ if (dist > max)
+ { scale = FixedDiv2(max,dist);
+ ob->momentumx = FixedMul(ob->momentumx,scale);
+ ob->momentumy = FixedMul(ob->momentumy,scale);
+ }
+ }
+ else
+ {
+ if (ob->momentumx > max)
+ ob->momentumx = max;
+ else if (ob->momentumx < -max)
+ ob->momentumx = -max;
+ if (ob->momentumy > max)
+ ob->momentumy = max;
+ else if (ob->momentumy < -max)
+ ob->momentumy = -max;
+ }
+
+ }
+
+ tryx = ob->x + ob->momentumx;
+ tryy = ob->y + ob->momentumy;
+ tryz = ob->z + (ob->momentumz >> 16);
+
+ if (ocl != playerobj)
+ ob->flags &= ~FL_STUCK;
+
+
+ if (!ActorTryMove (ob, tryx, tryy, tryz))
+ { if (ocl == playerobj)
+ { if (!(ob->flags & FL_ELASTO))
+ PlayerSlideMove (ob);
+ else
+ { if (ActorTryMove(ob,tryx, ob->y-ob->momentumy,tryz))
+ ob->momentumy = -(ob->momentumy);
+ else if (ActorTryMove(ob,ob->x-ob->momentumx,tryy,tryz))
+ ob->momentumx = -(ob->momentumx);
+ else
+ ZEROMOM;
+ }
+ }
+
+ else
+ { ZEROMOM;
+ ob->flags |= FL_STUCK;
+ return;
+ }
+ }
+
+ MoveActor(ob);
+
+
+ride:
+
+ if (ob->flags & FL_RIDING)
+ {
+ objtype *ride = (objtype*)(ob->whatever);
+
+ ob->z += (ride->momentumz >> 16);
+
+ if ((ride->momentumx || ride->momentumy) &&
+ ActorTryMove(ob,ob->x+ride->momentumx,ob->y+ride->momentumy,tryz)
+ )
+ SetFinePosition(ob,ob->x+ride->momentumx,ob->y+ride->momentumy);
+ }
+
+
+#define SLIDER(ob) ((ob->flags & FL_NOFRICTION) && (ob->state->think != T_Collide))
+#define AIRBORNE(ob) ((ob->obclass != playerobj) && (ob->z != nominalheight) &&\
+ (!IsPlatform(ob->tilex,ob->tiley)) && \
+ (DiskAt(ob->tilex,ob->tiley) == NULL) \
+ )
+
+ if (SLIDER(ob) || AIRBORNE(ob))
+ return;
+
+ if ( (abs(ob->momentumx) < STOPSPEED) &&
+ (abs(ob->momentumy) < STOPSPEED)
+ )
+ {
+ ZEROMOM;
+ }
+
+ else if ((ob->flags & FL_DYING) && (ob->state == ob->state->next))
+ { ob->momentumx = FixedMul (ob->momentumx, DEADFRICTION);
+ ob->momentumy = FixedMul (ob->momentumy, DEADFRICTION);
+
+ }
+
+ else
+ { ob->momentumx = FixedMul (ob->momentumx, friction);
+ ob->momentumy = FixedMul (ob->momentumy, friction);
+
+ }
+
+
+
+}
+
+
+
+
+void T_Guts(objtype*ob)
+{ if (ob->ticcount)
+ return;
+ SpawnParticles(ob,GUTS,50);
+
+}
+
+
+void T_Special(objtype*ob)
+{
+ if (ob->ticcount)
+ return;
+
+#if (SHAREWARE == 0)
+ if (ob->state == &s_NMEheadexplosion)
+ {
+ ob->z -= 42;
+ SetGibSpeed(0x4000);
+ SpawnParticles(ob,gt_sparks,100);
+ ResetGibSpeed();
+ SD_PlaySoundRTP(SD_EXPLODESND,ob->x,ob->y);
+ return;
+ }
+#endif
+ if (ob->obclass != b_robobossobj)
+ return;
+
+ NewState(ob,&s_bossdeath);
+}
+
+
+
+
+void SpawnBoulder(int tilex,int tiley,int dir)
+{
+#if (SHAREWARE == 1)
+ tilex = tilex;
+ tiley = tiley;
+ dir = dir;
+ Error("Boulders aren't allowed in shareware!");
+#endif
+#if (SHAREWARE == 0)
+ SpawnNewObj(tilex,tiley,&s_boulderspawn,inertobj);
+ new->z = 0;
+ PreCacheActor(boulderobj,0);
+ new->dir = 2*dir;
+#endif
+
+}
+
+
+
+#define InitSprayPart(newflags) \
+ { \
+ new->hitpoints = starthitpoints[gamestate.difficulty][b_robobossobj]; \
+ new->dir = dir*4; \
+ new->speed = 7*SPDPATROL; \
+ new->door_to_open = -1; \
+ new->flags |= (newflags); \
+ } \
+
+
+void SpawnMultiSpriteActor(classtype actorclass, int tilex,int tiley,int dir)
+{
+
+
+
+#if (SHAREWARE==1)
+
+ actorclass = actorclass;
+ tilex = tilex;
+ tiley = tiley;
+ dir = dir;
+ Error("\nSPRAY not allowed in shareware !");
+
+#else
+
+ {
+ objtype *temp;
+
+ gamestate.killtotal++;
+
+ SpawnNewObj(tilex,tiley,&s_NMEstand,actorclass);
+ InitSprayPart(FL_BLOCK|FL_NOFRICTION|FL_SHOOTABLE);
+
+ new->temp1 = -1; // temp1 used as one-event queue for directions when chasing
+ // -1 when isn't waiting to try new dir, dirnumber when waiting
+ temp = new;
+
+ SpawnNewObj(tilex,tiley,&s_NMEhead1,actorclass);
+ InitSprayPart(FL_NOFRICTION|FL_SHOOTABLE|FL_HEAD|FL_NEVERMARK);
+
+ //new->whatever = temp; // head points to body
+
+ temp->whatever = new; // body points to head
+
+ SpawnNewObj(tilex,tiley,&s_NMEwheels2,actorclass);
+ InitSprayPart(FL_NOFRICTION|FL_SHOOTABLE|FL_HEAD|FL_NEVERMARK);
+
+
+ //new->whatever = temp; // head points to body
+ temp->target = new; // body also points to wheels
+ actorat[tilex][tiley] = NULL;
+ PreCacheActor(b_robobossobj,0);
+ }
+#endif
+}
+
+
+void SpawnSnake(int tilex,int tiley)
+{
+
+#if (SHAREWARE == 1)
+ tilex = tilex;
+ tiley = tiley;
+ Error("snake not allowed in shareware!");
+#else
+
+ GetNewActor();
+ MakeActive(new);
+ new->flags |= (FL_DONE|FL_ABP|FL_NEVERMARK);
+ SetTilePosition(new,tilex,tiley);
+ SetVisiblePosition(new,new->x,new->y);
+ new->obclass = b_darkmonkobj;
+ new->which = ACTOR;
+ new->z = nominalheight;
+ if (SNAKELEVEL == 2)
+ NewState(new,&s_darkmonkfastspawn);
+ else
+ NewState(new,&s_darkmonkhspawn);
+#endif
+
+}
+
+void SpawnGunThingy(classtype which, int tilex, int tiley, int dir)
+{
+#if (SHAREWARE == 1)
+ which = which;
+ tilex = tilex;
+ tiley = tiley;
+ dir = dir;
+
+ Error("no emplacements allowed in shareware!");
+#else
+ SpawnNewObj(tilex,tiley,&s_gunstand,which);
+
+
+ if (!loadedgame)
+ gamestate.killtotal++;
+
+ PreCacheActor(patrolgunobj,0);
+
+ new->hitpoints = starthitpoints[gamestate.difficulty][which];
+ new->dir = dir*2;
+// new->speed = 0x500;
+// ParseMomentum(new,dirangle8[new->dir]);
+ new->flags |= (FL_BLOCK|FL_SHOOTABLE);
+#endif
+}
+
+
+void SpawnFourWayGun(int tilex, int tiley)
+{
+#if (SHAREWARE == 1)
+ tilex = tilex;
+ tiley = tiley;
+ Error("no 4-way emplacements allowed in shareware!");
+#else
+
+
+ SpawnNewObj(tilex,tiley,&s_4waygun,patrolgunobj);
+ if (!loadedgame)
+ gamestate.killtotal++;
+
+ PreCacheActor(patrolgunobj,0);
+ new->temp1 = -1;
+ new->hitpoints = starthitpoints[gamestate.difficulty][patrolgunobj]*3;
+ new->flags |= (FL_BLOCK|FL_SHOOTABLE);
+#endif
+}
+
+
+
+
+/*
+=======================================================================
+=
+= NON-SHAREWARE CODE
+=
+=======================================================================
+*/
+
+#if (SHAREWARE == 0)
+
+void T_BoulderSpawn(objtype*ob)
+{ objtype *tactor;
+ int dx,dy,cl;
+
+ if (!(ob->flags & FL_ACTIVE))
+ return;
+
+ else if (!ob->ticcount)
+ { for(tactor = firstareaactor[ob->areanumber]; tactor; tactor = tactor->nextinarea)
+ { cl = tactor->obclass;
+ if (tactor == ob)
+ continue;
+
+ if (!(tactor->flags & FL_SHOOTABLE))
+ continue;
+ dx = abs(tactor->x - ob->x);
+ if (dx > MINACTORDIST)
+ continue;
+ dy = abs(tactor->y - ob->y);
+ if (dy > MINACTORDIST)
+ continue;
+ if ((cl == b_heinrichobj) || (cl== b_darkmonkobj) ||
+ (cl == b_darianobj) || (cl == b_robobossobj) ||
+ (cl == pillarobj) || (cl == wallopobj) ||
+ (cl == boulderobj))
+ return;
+ else break;
+ }
+
+
+ SpawnNewObj(ob->tilex,ob->tiley,&s_boulderdrop1,boulderobj);
+ new->z = 0;
+ new->dir = ob->dir;
+ //new->angle = dirangle8[new->dir];
+ new->speed = 0x4000;
+ ParseMomentum(new,dirangle8[new->dir]);
+ new->flags |= (FL_BLOCK|FL_NOFRICTION);
+ new->flags &= ~FL_SHOOTABLE;
+ new->whatever = ob;
+ if (tactor)
+ new->target = tactor;
+ MakeActive(new);
+ new->flags |= FL_ABP;
+
+ }
+
+}
+
+void T_BoulderDrop(objtype*ob)
+{ int dx,dy,dz;
+ objtype * tactor;
+ statetype *tstate;
+
+
+ if (ob->state == &s_boulderdrop12)
+ {
+
+ if (ob->z == nominalheight)
+ NewState(ob,&s_boulderroll1);
+ else if (ob->momentumz)
+ { ob->z += (ob->momentumz>>16);
+ ob->momentumz += (GRAVITY<<1);
+ if (ob->z > nominalheight)
+ { ob->z = nominalheight;
+ ob->momentumz = 0;
+ //ob->flags &= ~FL_NOFRICTION;
+ }
+ }
+ else if (!ob->temp1)
+ { ob->momentumz = (GRAVITY<<6);
+ ob->temp1 = 1;
+ }
+
+ }
+
+ if (ob->ticcount)
+ return;
+ if (ob->state->condition & SF_SOUND)
+
+ SD_PlaySoundRTP(SD_BOULDERFALLSND,ob->x,ob->y);
+ tactor = (objtype*)(ob->target);
+ if (tactor && (!(tactor->flags & FL_DYING)))
+ { dx = tactor->x - ob->x;
+ dy = tactor->y - ob->y;
+ dz = tactor->z - ob->z;
+ if ((abs(dx) < MINACTORDIST) && (abs(dy) < MINACTORDIST) &&
+ (abs(dz) < 50))
+ { if (tactor->obclass != playerobj)
+ { tactor->momentumx = tactor->momentumy = tactor->momentumz = 0;
+ tactor->flags |= FL_DYING;
+ tactor->hitpoints = 0;
+ if (gamestate.violence < vl_high)
+ { if ((tstate = UPDATE_STATES[CRUSH][tactor->obclass - lowguardobj])!=NULL)
+ NewState(tactor,tstate);
+
+ //else
+ //Error("\n\Null low-violence crush state in boulder drop, instance of %s",debugstr[tactor->obclass]);
+ }
+ else
+ { tactor->shapeoffset = 0;
+ //tactor->flags|=FL_HBM;
+ NewState(tactor,&s_guts1);
+ }
+ }
+ else
+ { DamageThing(tactor,200);
+ Collision(tactor,ob,0,0);
+ M_CheckPlayerKilled(tactor);
+ }
+ SD_PlaySoundRTP(SD_ACTORSQUISHSND,tactor->x,tactor->y);
+ ob->target = NULL;
+ }
+
+ }
+}
+
+
+void CheckCrush(objtype*ob)
+{
+ objtype *temp;
+ int dx,dy,dz;
+
+ for(temp = PLAYER[0]; temp != PLAYER[numplayers-1]->next; temp=temp->next)
+ {
+ if (ob->flags & FL_DYING)
+ continue;
+
+ dx = abs(temp->x - ob->x);
+ if (dx > MINACTORDIST)
+ continue;
+
+ dy = abs(temp->y - ob->y);
+ if (dy > MINACTORDIST)
+ continue;
+
+ dz = abs(temp->z - ob->z);
+ if (dz > (MINACTORDIST>>10))
+ continue;
+
+ if (!ob->ticcount)
+ DamageThing(temp,EnvironmentDamage(ob));
+ Collision(temp,ob,ob->momentumx-temp->momentumx,ob->momentumy-temp->momentumy);
+ M_CheckPlayerKilled(temp);
+ }
+}
+
+
+void T_BoulderMove(objtype*ob)
+{
+
+
+ if (MAPSPOT(ob->tilex,ob->tiley,1) == 395)
+ { NewState(ob,&s_bouldersink1);
+ return;
+ }
+ if (NOMOM)
+ ParseMomentum(ob,dirangle8[ob->dir]);
+ if ((!ob->ticcount) && (ob->state->condition & SF_SOUND) &&
+ areabyplayer[ob->areanumber])
+ SD_PlaySoundRTP(BAS[ob->obclass].operate,ob->x,ob->y);
+ SelectPathDir(ob);
+
+}
+
+
+/*
+=========================================================================
+=
+= Boss Functions
+=
+=========================================================================
+*/
+
+//***************************** Esau ************************************
+
+
+enum {
+ ESAU_USING_HOLES=1,
+ ESAU_LEAVING_CONTROL_ROOM,
+ ESAU_USING_TOUCH_PEDASTALS,
+ ESAU_CHASING_PLAYER
+};
+
+
+
+
+void T_EsauWait(objtype*ob)
+{
+ int dist;
+
+ dist = FindDistance(ob->tilex-PLAYER[0]->tilex,ob->tiley-PLAYER[0]->tiley);
+ MISCVARS->ESAU_SHOOTING = false;
+
+ if (ob->dirchoosetime)
+ ob->dirchoosetime --;
+
+ if ((dist>81) || (dist<36))
+ {
+ if (CheckLine(ob,PLAYER[0],MISSILE))
+ {
+ NewState(ob,&s_darianshoot1);
+ ob->momentumx = ob->momentumy = 0;
+ }
+ return;
+ }
+ else if ((!ob->dirchoosetime) && (CheckLine(ob,PLAYER[0],SHOOT)))
+ {
+ NewState(ob,&s_dariandefend1);
+ ob->dirchoosetime = (GameRandomNumber("T_EsauWait",0) % 35) + 17;//35;
+ return;
+ }
+}
+
+
+void T_EsauRise(objtype*ob)
+{
+ int newarea,oldarea;
+
+ // if (gamestate.victoryflag)
+ // return;
+
+ if (!ob->ticcount)
+ { //Debug("\n tx before: %d, ty before: %d",
+ // ob->targettilex,ob->targettiley);
+
+ SelectTouchDir(ob);
+ if (ob->targettilex || ob->targettiley)
+ { //Debug("\n ob->tilex: %d, ob->tiley: %d, targettilex: %d, targettiley: %d",
+ // ob->tilex, ob->tiley, ob->targettilex, ob->targettiley);
+
+ SetTilePosition(ob,ob->targettilex,ob->targettiley);
+ SetVisiblePosition(ob,ob->x,ob->y);
+ oldarea = ob->areanumber;
+ newarea = AREANUMBER(ob->tilex,ob->tiley);
+ if (oldarea != newarea)
+ {
+ RemoveFromArea(ob);
+ ob->areanumber = newarea;
+ MakeLastInArea(ob);
+ }
+ }
+ else
+ MISCVARS->EPOP[ob->temp3].x = MISCVARS->EPOP[ob->temp3].y = 0;
+
+ ob->dirchoosetime= (GameRandomNumber("T_EsauRise",0) % 35) + 17;
+ MISCVARS->ESAU_HIDING = false;
+ MISCVARS->ESAU_SHOOTING = true;
+ ob->flags |= FL_SHOOTABLE;
+ }
+}
+
+
+
+void T_EsauChase(objtype*ob)
+{
+ int dx,dy,chance,dist;
+ statetype *temp;
+
+
+
+ if ((ob->tilex == ob->targettilex) && (ob->tiley == ob->targettiley))
+ {
+ if (MISCVARS->DSTATE == ESAU_USING_HOLES)
+ {
+ MISCVARS->ESAU_HIDING = true;
+ MISCVARS->ESAU_SHOOTING = false;
+ SD_PlaySoundRTP(SD_DARIANHIDESND,ob->x,ob->y);
+ NewState(ob,&s_dariansink1);
+ ob->flags &= ~FL_SHOOTABLE;
+ return;
+ }
+ else if (MISCVARS->DSTATE == ESAU_LEAVING_CONTROL_ROOM)
+ {
+ if (!MISCVARS->doorcount)
+ {
+ SetTilePosition(ob,ob->tilex,ob->tiley);
+ SetVisiblePosition(ob,ob->x,ob->y);
+ }
+ MISCVARS->doorcount ++;
+ if (MISCVARS->doorcount == 4)
+ MISCVARS->DSTATE = ESAU_USING_HOLES;
+ else // hack to FORCE esau to walk through door
+ {
+ switch (ob->temp1)
+ {
+ case east:
+ ob->targettilex ++;
+ break;
+ case west:
+ ob->targettilex --;
+ break;
+ case north:
+ ob->targettiley --;
+ break;
+ case south:
+ ob->targettiley ++;
+ break;
+ }
+ }
+ SelectTouchDir(ob);
+ return;
+ }
+ }
+
+ if (touchsprite && (touchsprite->itemnumber == stats[stat_dariantouch].type))
+ {
+ dx = touchsprite->x - ob->x;
+ dy = touchsprite->y - ob->y;
+
+ if (((dx > -0x5000) && (dx < 0x5000)) &&
+ ((dy > -0x5000) && (dy < 0x5000)))
+ {
+ SD_PlaySoundRTP(SD_DARIANGONNAUSESND,ob->x,ob->y);
+ NewState(ob,&s_darianuse1);
+ return;
+ }
+ }
+
+ if (ob->dirchoosetime)
+ ob->dirchoosetime --;
+
+ if (NOMOM || (!ob->dirchoosetime))
+ {
+ SelectTouchDir(ob);
+ ob->dirchoosetime = M_CHOOSETIME(ob);
+ }
+ else
+ ActorMovement(ob);
+
+
+ if (!ob->ticcount)
+ {
+ if (CheckLine(ob,PLAYER[0],MISSILE)) // got a shot at player?
+ {
+ if (Near(ob,PLAYER[0],1))
+ chance = 300;
+ else
+ {
+ dx = abs(PLAYER[0]->tilex-ob->tilex);
+ dy = abs(PLAYER[0]->tiley-ob->tiley);
+ dist = (dx>dy)?dx:dy;
+ chance = 400/dist;
+ }
+ if (GameRandomNumber("T_EsauChase",0) <chance)
+ {
+ if ((temp=M_S(AIM)) != NULL)
+ {
+ NewState(ob,temp);
+ ob->dirchoosetime = 0;
+ ob->momentumx = ob->momentumy = 0;
+ SetVisiblePosition(ob,ob->x,ob->y);
+ return;
+ }
+ }
+ if (MISCVARS->ESAU_SHOOTING)
+ {
+ SetVisiblePosition(ob,ob->x,ob->y);
+ return;
+ }
+ }
+ }
+}
+
+
+void T_EsauSpears(objtype*ob)
+{
+
+ if (ob->ticcount == (ob->state->tictime>>1)-1)
+ {
+ OLDTILEX = PLAYER[0]->tilex;
+ OLDTILEY = PLAYER[0]->tiley;
+ }
+
+ else if (!ob->ticcount)
+ {
+ SpawnNewObj(OLDTILEX,OLDTILEY,&s_speardown1,spearobj);
+ new->flags |= FL_ABP;
+ MakeActive(new);
+ }
+}
+
+
+
+void FindDoor(objtype*ob)
+{
+ int i,area1,area2,min,curr,
+ dest1x,dest1y,dest2x,dest2y,
+ d1,d2;
+
+ dirtype tdir1,tdir2;
+ doorobj_t*dr;
+
+ min = 0x7fffffff;
+ for(i=0; i<doornum; i++)
+ {
+ dr = doorobjlist[i];
+ if (dr->vertical)
+ {
+ area1 = MAPSPOT(dr->tilex-1,dr->tiley,0)-AREATILE;
+ dest1x = dr->tilex-1;
+ dest1y = dr->tiley;
+ tdir1 = east;
+ area2 = MAPSPOT(dr->tilex+1,dr->tiley,0)-AREATILE;
+ dest2x = dr->tilex+1;
+ dest2y = dr->tiley;
+ tdir2 = west;
+ }
+ else
+ {
+ area1 = MAPSPOT(dr->tilex,dr->tiley-1,0)-AREATILE;
+ dest1x = dr->tilex;
+ dest1y = dr->tiley-1;
+ tdir1 = south;
+ area2 = MAPSPOT(dr->tilex,dr->tiley+1,0)-AREATILE;
+ dest2x = dr->tilex;
+ dest2y = dr->tiley+1;
+ tdir2 = north;
+ }
+
+//============================================================
+#define CheckMinDist(destx,desty,dir) \
+ { \
+ curr = FindDistance(destx-ob->tilex,desty-ob->tiley); \
+ if (curr < min) \
+ { \
+ min = curr; \
+ ob->targettilex = destx; \
+ ob->targettiley = desty; \
+ ob->temp1 = dir; \
+ } \
+ }
+//============================================================
+
+ if (area1 == ob->areanumber)
+ {
+ if (area1 == area2)
+ {
+ d1 = FindDistance(dest1x-ob->tilex,dest1y-ob->tiley);
+ d2 = FindDistance(dest2x-ob->tilex,dest2y-ob->tiley);
+ if (d2 < d1) //swap areas
+ {
+ CheckMinDist(dest2x,dest2y,tdir2);
+ continue;
+ }
+ }
+
+ CheckMinDist(dest1x,dest1y,tdir1);
+
+ }
+ else if (area2 == ob->areanumber)
+ CheckMinDist(dest2x,dest2y,tdir2);
+
+ }
+}
+
+
+int FindTouch(objtype *ob)
+{
+ int i,curr,min,tx,ty,noneleft;
+ statobj_t* tempstat;
+
+
+ min = 0x7fffffff;
+ noneleft = 1;
+ for(i=0; i<MISCVARS->nexttouch; i++)
+ {
+ if (MISCVARS->ETOUCH[i].x || MISCVARS->ETOUCH[i].y)
+ {
+ noneleft = 0;
+ tx = MISCVARS->ETOUCH[i].x;
+ ty = MISCVARS->ETOUCH[i].y;
+ tempstat = sprites[tx][ty];
+ curr = FindDistance(tx-ob->tilex,ty-ob->tiley);
+
+ if (curr < min)
+ {
+ min = curr;
+ ob->targettilex = tx;
+ ob->targettiley = ty;
+ touchsprite = tempstat;
+ }
+ }
+ }
+ return (!noneleft);
+}
+
+
+
+
+typedef enum
+{
+ down_in_a_hole=-1,
+ no_holes_available=0,
+ holes_unreachable=1,
+ hole_targetted=2
+
+} hiding_status;
+
+
+
+hiding_status HoleStatus(objtype*ob)
+{
+ int i,tx,ty,dist,noneleft,invisible,curr,min;
+ tpoint dummy,*dptr = &dummy;
+ objtype *tactor;
+ _2Dpoint *tdptr;
+
+ min = 0x7fffffff;
+ noneleft = 1;
+
+
+
+ for(i=0; i<MISCVARS->nextpop; i++)
+ {
+ tdptr = &(MISCVARS->EPOP[i]);
+
+ if (tdptr->x || tdptr->y)
+ {
+ tactor = (objtype*)actorat[tdptr->x][tdptr->y];
+ if (tactor && (tactor->obclass == pillarobj))
+ {
+ tdptr->x = 0;
+ tdptr->y = 0;
+ MISCVARS->popsleft --;
+ }
+ }
+ }
+
+
+ if (MISCVARS->popsleft > 1)
+ {
+ for(i=0; i<MISCVARS->nextpop; i++)
+ {
+ tdptr = &(MISCVARS->EPOP[i]);
+
+ if (tdptr->x || tdptr->y)
+ {
+ tx = tdptr->x;
+ ty = tdptr->y;
+
+ if ((PLAYER[0]->tilex == tx) || (PLAYER[0]->tiley == ty))
+ continue;
+
+ if (MISCVARS->ESAU_HIDING)
+ {
+ dist = FindDistance(PLAYER[0]->tilex-tx,PLAYER[0]->tiley-ty);
+ if ((ob->tilex == tx) && (ob->tiley == ty) && (MISCVARS->popsleft != 1))
+ continue;
+ noneleft = 0;
+ if ((MAPSPOT(tx,ty,0)-AREATILE) == ob->areanumber)
+ {
+ ob->targettilex = tx;
+ ob->targettiley = ty;
+ ob->temp3 = i;
+ if ((dist < 81) && (dist > 36))
+ return down_in_a_hole;
+ }
+ }
+
+ else if (!MISCVARS->ESAU_SHOOTING)
+ {
+ curr = FindDistance(tx-ob->tilex,ty-ob->tiley);
+ if (curr < min)
+ {
+ min = curr;
+ noneleft = 0;
+ dptr->which = ACTOR;
+ SetTilePosition(dptr,tx,ty);
+ //dptr->x = (tx << TILESHIFT) + TILEGLOBAL/2;
+ //dptr->y = (ty << TILESHIFT) + TILEGLOBAL/2;
+ dptr->z = ob->z;
+ invisible = 0;
+ if ((!CheckLine(ob,dptr,SHOOT)) && (MISCVARS->DSTATE != ESAU_USING_HOLES))
+ {
+ invisible = 1;
+ MISCVARS->DSTATE = ESAU_LEAVING_CONTROL_ROOM;
+ }
+ else
+ MISCVARS->DSTATE = ESAU_USING_HOLES;
+ ob->targettilex = tx;
+ ob->targettiley = ty;
+ }
+ }
+ }
+ }
+ }
+
+ if (MISCVARS->ESAU_HIDING)
+ return down_in_a_hole;
+
+ if (noneleft)
+ {
+ MISCVARS->DSTATE = ESAU_CHASING_PLAYER;
+ return no_holes_available;
+ }
+
+ if (invisible) //leave present room
+ return holes_unreachable;
+
+ return hole_targetted;
+}
+
+
+void SelectTouchDir (objtype *ob)
+{
+ int dx,dy,noneleft,invisible;
+ hiding_status hole;
+
+
+ dirtype d[3];
+ dirtype tdir, olddir, turnaround;
+
+
+ olddir=ob->dir;
+ turnaround= opposite[olddir];
+
+
+ invisible = 0;
+ noneleft = 1;
+
+ if (!MISCVARS->notouch)
+ {
+ if (!FindTouch(ob))
+ MISCVARS->notouch = 1;
+ else
+ MISCVARS->DSTATE = ESAU_USING_TOUCH_PEDASTALS;
+ }
+
+ else if ((!MISCVARS->noholes) && (MISCVARS->DSTATE != ESAU_LEAVING_CONTROL_ROOM))
+ {
+ hole = HoleStatus(ob);
+
+ switch(hole)
+ {
+ case down_in_a_hole:
+ return;
+
+ case no_holes_available:
+ MISCVARS->noholes = 1;
+ break;
+
+ case holes_unreachable:
+ FindDoor(ob);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ else if (MISCVARS->DSTATE == ESAU_CHASING_PLAYER)
+
+ // only gets here if all gimmicks (touch tables,
+ // holes) are inoperative
+ {
+ ob->flags |= FL_SHOOTABLE;
+ ob->targettilex = PLAYER[0]->tilex;
+ ob->targettiley = PLAYER[0]->tiley;
+ }
+ /*
+ if (DSTATE == SDOOR)
+ {dx = ((ob->targettilex<<16)+TILEGLOBAL/2) - ob->x;
+ dy = ob->y - ((ob->targettiley<<16)+TILEGLOBAL/2);
+ angle = atan2_appx(dx,dy);
+ ZEROMOM;
+ ParseMomentum(ob,angle);
+ ActorMovement(ob);
+ if (ob->momentumx || ob->momentumy)
+ {ob->angle = angle;
+ ob->dir = angletodir[ob->angle];
+ return;
+ }
+ }
+ else */
+ dx = ob->targettilex - ob->tilex;
+ dy = ob->tiley - ob->targettiley;
+
+
+
+
+ d[1]=nodir;
+ d[2]=nodir;
+
+
+ if (dx>0)
+ d[1]= east;
+ else if (dx<0)
+ d[1]= west;
+ if (dy>0)
+ d[2]=north;
+ else if (dy<0)
+ d[2]=south;
+
+
+ if (GameRandomNumber("SelectTouchDir",0)<128)
+ {
+ tdir=d[1];
+ d[1]=d[2];
+ d[2]=tdir;
+ }
+
+ ZEROMOM;
+
+
+ if (d[1]!=nodir)
+ M_CHECKDIR(ob,d[1]);
+
+
+ if (d[2]!=nodir)
+ M_CHECKDIR(ob,d[2]);
+
+
+
+ if (GameRandomNumber("SelectTouchDir",ob->obclass)>128) //randomly determine direction of search
+ {
+ for (tdir=north; tdir<=west; tdir++)
+ {
+ if (tdir!=turnaround)
+ M_CHECKDIR(ob,tdir);
+ }
+ }
+ else
+ {
+ for (tdir=west; tdir>=north; tdir--)
+ {
+ if (tdir!=turnaround)
+ M_CHECKDIR(ob,tdir);
+ }
+ }
+
+ if (turnaround != nodir)
+ M_CHECKDIR(ob,turnaround);
+
+
+ if (olddir!=nodir)
+ M_CHECKDIR(ob,olddir);
+
+}
+
+
+
+
+//************** Krist ****************************************************
+
+
+
+void CheckRunover(objtype*ob)
+{ int dx,dy,dz;
+
+ dx = abs(PLAYER[0]->x - ob->x);
+ if (dx > MINACTORDIST)
+ return;
+
+ dy = abs(PLAYER[0]->y - ob->y);
+ if (dy > MINACTORDIST)
+ return;
+
+ dz = abs(PLAYER[0]->z - ob->z);
+ if (dz > 10)
+ return;
+
+ locplayerstate->heightoffset = 18 + locplayerstate->playerheight;
+ locplayerstate->oldheightoffset = locplayerstate->heightoffset;
+ PLAYER[0]->temp2 = RENORMALIZE;
+ DamageThing(PLAYER[0],30);
+ Collision(PLAYER[0],ob,0,0);
+ M_CheckPlayerKilled(PLAYER[0]);
+
+}
+
+
+void T_HeinrichChase(objtype*ob)
+{
+ int dx,dy,dist,chance,perpangle;
+// statetype *temp;
+ boolean doorok;
+
+ CheckRunover(ob);
+
+ // ob->flags &= ~FL_DODGE;
+ if (CheckLine(ob,PLAYER[0],SIGHT))
+ { ob->targettilex = PLAYER[0]->x;
+ ob->targettiley = PLAYER[0]->y;
+ }
+
+ if (!ob->ticcount)
+ {
+
+// if (gamestate.victoryflag)
+// return;
+
+
+ if (CheckLine(ob,PLAYER[0],SHOOT)) // got a shot at PLAYER[0]?
+ { dx = abs(ob->tilex - PLAYER[0]->tilex);
+ dy = abs(ob->tiley - PLAYER[0]->tiley);
+ dist = dx>dy ? dx : dy;
+ if (!dist || dist==1)
+ chance = 300;
+ else
+ chance = 2400/dist;
+
+ if (GameRandomNumber("T_HeinrichChase",0) <chance)
+ { tpoint dummy,*dptr=&dummy;
+
+ if (Near(ob,PLAYER[0],2))
+ goto cdoor;
+
+
+ perpangle = AngleBetween(ob,PLAYER[0]) + ANGLES/4;
+ Fix(perpangle);
+ dptr->which = ACTOR;
+ dptr->x = ob->x + FixedMul(0x10000l,costable[perpangle]);
+ dptr->y = ob->y - FixedMul(0x10000l,sintable[perpangle]);
+
+ dptr->z = ob->z;
+ if (!CheckLine(dptr,PLAYER[0],SHOOT))
+ goto cdoor;
+
+ ob->target = PLAYER[0];
+ NewState(ob,M_S(AIM));
+ ob->dirchoosetime = 0;
+ return;
+
+
+ }
+ }
+
+ }
+
+cdoor:
+ doorok = NextToDoor(ob);
+
+
+ if (ob->dirchoosetime)
+ ob->dirchoosetime--;
+
+ if ((ob->flags & FL_STUCK) || (!ob->dirchoosetime) || doorok)
+ { /*if ((ob->flags & FL_DODGE) && (!doorok))
+ SelectKristDodgeDir (ob);
+ else */
+ SD_PlaySoundRTP(SD_KRISTMOTORSND,ob->x,ob->y);
+ SelectKristChaseDir(ob);
+
+ ob->dirchoosetime = 4*M_CHOOSETIME(ob);
+
+ }
+
+ else
+ { if (NOMOM)
+ ParseMomentum(ob,dirangle8[ob->dir]);
+ ActorMovement(ob);
+
+ }
+
+}
+
+void T_Heinrich_Defend (objtype*ob)
+{
+ CheckRunover(ob);
+
+ if (ob->dirchoosetime)
+ ob->dirchoosetime--;
+
+
+ if (MISCVARS->HRAMMING)
+ ParseMomentum(ob,dirangle8[ob->dir]);
+
+
+ if ((ob->flags & FL_STUCK) || (!ob->dirchoosetime))
+ { if (MISCVARS->HRAMMING)
+ { if (!Near(ob,PLAYER[0],3))
+ { NewState(ob,M_S(CHASE));
+ ob->dirchoosetime = 0;
+ return;
+ }
+ SelectKristChaseDir(ob);
+ }
+ else if (MISCVARS->HMINING)
+ { SelectMineDir(ob);
+ if (!MISCVARS->HMINING)
+ goto hchase;
+ ob->dirchoosetime = 5;//10;
+ return;
+ }
+ else
+hchase:
+ NewState(ob,M_S(CHASE));
+ ob->dirchoosetime = 0;
+ }
+ else
+ { if (NOMOM)
+ ParseMomentum(ob,dirangle8[ob->dir]);
+ ActorMovement(ob);
+ }
+}
+
+
+void T_Heinrich_Out_of_Control(objtype*ob)
+{
+ if (ob->dirchoosetime)
+ ob->dirchoosetime --;
+ else
+ {
+ if (!ob->temp1)
+ {
+ SetGibSpeed(0x4000);
+ SpawnParticles(ob,RANDOM,120);
+ ResetGibSpeed();
+
+ NewState(ob,&s_dexplosion1);
+ SD_PlaySoundRTP(SD_EXPLODESND,ob->x,ob->y);
+ }
+ else
+ {
+ ob->dir = dirorder[ob->dir][PREV];
+ ob->angle = dirangle8[ob->dir];
+ if (ob->dir == (unsigned)ob->temp2)
+ {
+ if (ob->temp1 > 1)
+ ob->temp1--;
+ else
+ {
+ if (ob->temp3 == 7)
+ {
+ SpawnNewObj(ob->tilex,ob->tiley,&s_megaexplosions,inertobj);
+ new->temp1 = 25;
+ new->flags |= FL_ABP;
+ MakeActive(new);
+ SpawnNewObj(ob->tilex,ob->tiley,&s_superparticles,inertobj);
+ new->flags |= FL_ABP;
+ PARTICLE_GENERATOR = new;
+ MakeActive(new);
+ }
+ if (ob->temp3)
+ ob->temp3 --;
+ else
+ ob->temp1 --;
+ }
+ }
+
+ if (ob->temp1)
+ ob->dirchoosetime = ob->temp1;
+ else
+ {
+ ob->dirchoosetime = 70; // end of spin wait for megaexplosion
+ if (PARTICLE_GENERATOR)
+ {
+ NewState(PARTICLE_GENERATOR,&s_megaremove);
+ PARTICLE_GENERATOR = NULL;
+ }
+ }
+ }
+ }
+}
+
+
+
+
+void SelectKristChaseDir(objtype*ob)
+{ int dx,dy,tx,ty,angle;
+ dirtype dtry1,dtry2,tdir,olddir,next,prev,straight;
+//tpoint dummy,*dptr=&dummy;
+
+ olddir=ob->dir;
+
+
+//dptr->which = ACTOR;
+//dptr->z = ob->z;
+ if (ob->targettilex || ob->targettiley)
+ { tx = ob->targettilex;
+ ty = ob->targettiley;
+ dx= tx - ob->x;
+ dy= ob->y - ty;
+ // SetFinePosition(dptr,tx,ty);
+ if ( ((dx < 0x20000) && (dx > -0x20000)) &&
+ ((dy < 0x20000) && (dy > -0x20000)))
+ {
+ dx= PLAYER[0]->x-ob->x;
+ dy= ob->y-PLAYER[0]->y;
+ // SetFinePosition(dptr,PLAYER[0]->x,PLAYER[0]->y);
+ }
+ }
+ else
+ {
+ dx= PLAYER[0]->x-ob->x;
+ dy= ob->y-PLAYER[0]->y;
+ //SetFinePosition(dptr,PLAYER[0]->x,PLAYER[0]->y);
+
+ }
+
+ angle = atan2_appx(dx,dy);
+ straight = angletodir[angle];
+ /*
+ if (ob->areanumber == PLAYER[0]->areanumber)
+ {//tpoint newpos1,newpos2;
+ //dirtype leftdir;
+ //int leftangle1,leftangle2;
+
+ if (CheckLine(ob,&dummy,DIRCHECK))
+ {//Debug("\ntrying straight dir %d",straight);
+ M_CHECKTURN(ob,straight);
+ //Debug("\nstraight dir %d failed",straight);
+ }
+ //leftdir = dirorder[straight][PREV];
+ //leftangle1 = dirangle8[leftdir];
+ //newpos1.which = ACTOR;
+ //rightangle = dirangle[dirorder[straight][NEXT]];
+ //newpos1.x = ob->x + FixedMul(0x10000,costable[leftangle1]);
+ //newpos1.y = ob->y - FixedMul(0x10000,sintable[leftangle1]);
+ //newpos1.z = ob->z;
+
+ //leftangle2 = dirangle8[dirorder[leftdir][PREV]];
+ //newpos2.which = ACTOR;
+ //rightangle = dirangle[dirorder[straight][NEXT]];
+ //newpos2.x = ob->x + FixedMul(0x10000,costable[leftangle2]);
+ //newpos2.y = ob->y - FixedMul(0x10000,sintable[leftangle2]);
+ //newpos2.z = ob->z;
+ //if (CheckLine(&newpos1,&dummy,SHOOT))// || CheckLine(&newpos2,&dummy,SHOOT))
+ {for(tdir = dirorder[straight][PREV];tdir != dirorder[straight][NEXT];tdir = dirorder[tdir][PREV])
+ {//Debug("\ntried left-hand rule dir %d",tdir);
+ M_CHECKTURN(ob,tdir);
+ }
+ }
+ //else
+ //{for(tdir = dirorder[straight][NEXT];tdir != dirorder[straight][PREV];tdir = dirorder[tdir][NEXT])
+ // {//Debug("\ntrying right-hand rule dir %d",tdir);
+ // M_CHECKTURN(ob,tdir);
+ //Debug("\nright-hand rule dir %d failed\n",tdir);
+ // }
+ // }
+ }
+ else*/
+ { dtry1=nodir;
+ dtry2=nodir;
+
+ if (dx> ACTORSIZE)
+ dtry1= east;
+ else if (dx< -ACTORSIZE)
+ dtry1= west;
+ if (dy> ACTORSIZE)
+ dtry2=north;
+ else if (dy < -ACTORSIZE)
+ dtry2= south;
+
+
+ if (abs(dy)>abs(dx))
+ { tdir=dtry1;
+ dtry1=dtry2;
+ dtry2=tdir;
+ }
+
+ // ZEROMOM;
+ ob->momentumx = FixedMul (ob->momentumx, DEADFRICTION>>gamestate.difficulty);
+ ob->momentumy = FixedMul (ob->momentumy, DEADFRICTION>>gamestate.difficulty);
+
+
+ M_CHECKTURN(ob,straight);
+
+ if (dtry1 != nodir)
+ M_CHECKTURN(ob,dtry1);
+
+ if (dtry2 != nodir)
+ M_CHECKTURN(ob,dtry2);
+
+ if (dtry1 != nodir)
+ { M_CHECKTURN(ob,dirorder[dtry1][NEXT]);
+ M_CHECKTURN(ob,dirorder[dtry1][PREV]);
+ }
+
+ for(tdir = dirorder[olddir][NEXT]; tdir != olddir; tdir = dirorder[tdir][NEXT])
+ M_CHECKTURN(ob,tdir);
+
+ ob->dir = olddir;
+ }
+
+
+
+}
+
+
+
+void T_KristLeft(objtype*ob)
+{ CheckRunover(ob);
+ ActorMovement(ob);
+ if (!ob->ticcount)
+ { SD_PlaySoundRTP(SD_KRISTTURNSND,ob->x,ob->y);
+ if (ob->dir != (unsigned)ob->temp1)
+ ob->dir = dirorder[ob->dir][NEXT];
+ else
+ { ob->temp1 = 0;
+ NewState(ob,&s_heinrichchase);
+ }
+ }
+
+}
+
+void T_KristRight(objtype*ob)
+{ CheckRunover(ob);
+ ActorMovement(ob);
+ if (!ob->ticcount)
+ { SD_PlaySoundRTP(SD_KRISTTURNSND,ob->x,ob->y);
+ if (ob->dir != (unsigned)ob->temp1)
+ ob->dir = dirorder[ob->dir][PREV];
+ else
+ { ob->temp1 = 0;
+ NewState(ob,&s_heinrichchase);
+ }
+ }
+}
+
+
+void T_KristCheckFire(objtype*ob)
+{ int perpangle,angle;
+ tpoint dummy;
+
+ if (!ob->ticcount)
+ { angle = AngleBetween(ob,PLAYER[0]);
+
+ if (ob->state == &s_heinrichshoot1)
+ perpangle = angle + ANGLES/4;
+ else
+ perpangle = angle - ANGLES/4;
+
+ Fix(perpangle);
+
+
+ dummy.which = ACTOR;
+ dummy.x = ob->x + FixedMul(0x4000,costable[angle]) + FixedMul(0x4000l,costable[perpangle]) +
+ FixedMul(PROJSIZE,costable[perpangle]); // offset ahead plus
+ // offset for left/right missile plus offset for missile
+ // radius (will missile reach player without hitting wall,etc.)
+
+ dummy.y = ob->y - FixedMul(0x4000,sintable[angle]) - FixedMul(0x4000l,sintable[perpangle]) -
+ FixedMul(PROJSIZE,sintable[perpangle]);
+
+ dummy.x -= (FixedMul(PROJSIZE,costable[perpangle])<<1);
+
+ dummy.y += (FixedMul(PROJSIZE,sintable[perpangle])<<1);
+ dummy.z = ob->z;
+
+ if (!CheckLine(&dummy,PLAYER[0],SHOOT))
+ { NewState(ob,&s_heinrichchase);
+ return;
+ }
+
+
+ }
+}
+
+
+
+void SelectMineDir(objtype*ob)
+{ int angle,missangle;
+ dirtype olddir,tdir,next,prev,destdir;
+ static int nummines=0;
+
+ if (!CheckLine(ob,PLAYER[0],SIGHT))
+ { NewState(ob,M_S(CHASE));
+ MISCVARS->HMINING = 0;
+ return;
+ }
+
+ olddir = ob->dir;
+
+ angle = AngleBetween(ob,PLAYER[0]);
+ tdir = angletodir[angle];
+ destdir = opposite[tdir];
+
+ if (destdir != olddir)
+ { next = dirorder[olddir][NEXT];
+ prev = dirorder[olddir][PREV];
+ if (dirdiff[destdir][next] < dirdiff[destdir][prev])
+ ob->dir = next;
+ else
+ ob->dir = prev;
+ return;
+ }
+
+ nummines ++;
+ missangle = angle;
+ if (nummines == 2)
+ missangle -= (ANGLES/36);
+ else if (nummines == 3)
+ missangle += (ANGLES/36);
+
+ Fix(missangle);
+// if (missangle > (ANGLES - 1))
+// missangle -= ANGLES;
+// else if (missangle < 0)
+// missangle += ANGLES;
+
+
+ SpawnMissile(ob,h_mineobj,0x2000,missangle,&s_mine1,0xa000);
+ new->dirchoosetime = 140;
+ SD_PlaySoundRTP(SD_KRISTDROPSND,ob->x,ob->y);
+
+ if (nummines == 3)
+ { MISCVARS->HMINING = 0;
+ nummines = 0;
+ }
+}
+
+
+
+void A_HeinrichShoot(objtype* ob)
+{ int angle,perpangle;
+
+ if (!ob->ticcount)
+ { angle = AngleBetween(ob,PLAYER[0]);
+ if (ob->state == &s_heinrichshoot4)
+ perpangle = angle + ANGLES/4;
+ else
+ perpangle = angle - ANGLES/4;
+
+ Fix(perpangle);
+
+ SpawnMissile(ob,missileobj,0x4000,angle,&s_missile1,0x8000);
+ SD_PlaySoundRTP(BAS[ob->obclass].fire,ob->x,ob->y);
+
+ SetFinePosition(new,new->x + FixedMul(0x4000l,costable[perpangle]),
+ new->y - FixedMul(0x4000l,sintable[perpangle]));
+ SetVisiblePosition(new,new->x,new->y);
+ }
+
+
+}
+
+
+//***************************///////**************************************
+//***************************/ NME /**************************************
+//***************************///////**************************************
+
+
+
+
+
+void UpdateNMELinkedActors(objtype*ob)
+{
+ objtype *head,*wheels;
+ int oldarea;
+
+
+ head = (objtype*)(ob->whatever);
+ wheels = (objtype*)(ob->target);
+
+ oldarea = head->areanumber;
+
+ SetFinePosition(head,ob->x,ob->y);
+ SetFinePosition(wheels,ob->x,ob->y);
+ SetVisiblePosition(head,ob->x,ob->y);
+ SetVisiblePosition(wheels,ob->x,ob->y);
+
+ if (oldarea != ob->areanumber)
+ {
+ RemoveFromArea(head);
+ head->areanumber = ob->areanumber;
+ MakeLastInArea(head);
+ RemoveFromArea(wheels);
+ wheels->areanumber = ob->areanumber;
+ MakeLastInArea(wheels);
+ }
+
+}
+
+
+void T_OrobotChase(objtype*ob)
+{
+ int dx,dy;
+
+
+ if (CheckLine(ob,PLAYER[0],SIGHT))
+ {
+
+ ob->targettilex = PLAYER[0]->tilex;
+ ob->targettiley = PLAYER[0]->tiley;
+ }
+
+
+
+ if (!ob->ticcount)
+ {
+ if (NMEspincheck(ob))
+ return;
+
+ dx = PLAYER[0]->x - ob->x;
+ dy = ob->y - PLAYER[0]->y;
+ /*
+ if ((dx > -0x18000) && (dx < 0x18000) && (dy > -0x18000) && (dy < 0x18000))
+ {NewState(ob,&s_NMEavoid);
+ return;
+ }
+ */
+
+ if (CheckLine(ob,PLAYER[0],SIGHT))
+ {
+ int inrange;
+
+ switch(gamestate.difficulty)
+ {
+ case gd_baby:
+ inrange = Near(ob,PLAYER[0],6);
+ break;
+ case gd_easy:
+ inrange = Near(ob,PLAYER[0],9);
+ break;
+ case gd_medium:
+ inrange = Near(ob,PLAYER[0],12);
+ break;
+ case gd_hard:
+ inrange = 1;
+ break;
+ }
+
+ if ((!Near(ob,PLAYER[0],3)) && inrange)
+ {
+ SD_PlaySoundRTP(SD_NMEREADYSND,ob->x,ob->y);
+ if ((ob->hitpoints < 2000) && (GameRandomNumber("NME special attack",0) < 120))
+ {
+ int next,prev;
+
+ next = dirorder16[ob->dir][NEXT];
+ prev = dirorder16[ob->dir][PREV];
+ ob->targettilex = (angletodir[atan2_appx(dx,dy)]<<1);
+
+ if (dirdiff16[prev][ob->targettilex] < dirdiff16[next][ob->targettiley])
+ ob->temp3 = PREV;
+ else
+ ob->temp3 = NEXT;
+ NewState(ob,&s_NMEspinfire);
+ }
+ else
+ {
+ NewState(ob,&s_NMEwindup);
+ ob->temp3 = 0;
+ }
+ //NewState((objtype*)(ob->target),&s_NMEwheelspin);
+
+ NewState((objtype*)(ob->target),&s_NMEwheels120);
+ return;
+ }
+ }
+ }
+
+ if (ob->dirchoosetime)
+ ob->dirchoosetime --;
+
+ if ((ob->flags & FL_STUCK) || (!ob->dirchoosetime))
+ {
+ SelectOrobotChaseDir(ob);
+ ob->dirchoosetime = 4;//8;
+ }
+
+ else
+ {
+ ActorMovement(ob);
+ UpdateNMELinkedActors(ob);
+ }
+}
+
+
+
+void T_Saucer(objtype*ob)
+{ int angle,dangle;
+
+ if (!ob->ticcount) // if on track at end of each state, accelerate
+ // towards PLAYER[0]
+ { if (ob->state->condition & SF_SOUND)
+ SD_PlaySoundRTP(SD_NMEREADYSND,ob->x,ob->y);
+ angle = AngleBetween(ob,PLAYER[0]);
+ dangle = ob->angle - angle;
+ if ((dangle > -(ANGLES/72)) && (dangle < (ANGLES/72)))
+ { if (ob->speed < 0x10000)
+ { ob->speed += 0x200;
+ ZEROMOM;
+ ParseMomentum(ob,ob->angle);
+ }
+ }
+ else // off track; zero mom. and select new dir.
+ { ob->speed = 0x1000;
+ ZEROMOM;
+ ob->angle = angle;
+ ParseMomentum(ob,ob->angle);
+ }
+ }
+ MissileMovement(ob);
+
+
+}
+
+
+void T_NME_WindUp(objtype*ob)
+{ objtype *head,*wheels;
+
+ head = (objtype*)(ob->whatever);
+ wheels = (objtype*)(ob->target);
+
+ if (ob->dirchoosetime)
+ { ob->dirchoosetime--;
+ return;
+ }
+
+ ob->dirchoosetime = 0;//3;
+
+ if (MISCVARS->NMErotate < 3)
+ { head->dir = dirorder16[head->dir][NEXT];
+ MISCVARS->NMErotate ++;
+ }
+ else if (MISCVARS->NMErotate < 6)
+ { head->dir = dirorder16[head->dir][PREV];
+ MISCVARS->NMErotate ++;
+ }
+ else if (MISCVARS->NMErotate < 9)
+ { ob->dir = dirorder16[ob->dir][NEXT];
+ wheels->dir = ob->dir;
+ MISCVARS->NMErotate++;
+ }
+ else if (MISCVARS->NMErotate < 12)
+ { ob->dir = dirorder16[ob->dir][PREV];
+ wheels->dir = ob->dir;
+ MISCVARS->NMErotate ++;
+ }
+ else
+ { MISCVARS->NMErotate = 0;
+
+ NewState(ob,&s_NMEattack);
+ ob->dirchoosetime = 0;
+ //ob->dirchoosetime = 50 - (ob->shapeoffset >> 2) - (gamestate.difficulty << 2);//70;
+ if (!ob->temp2)
+ NewState((objtype*)(ob->whatever),&s_NMEhead1rl);
+ else
+ NewState((objtype*)(ob->whatever),&s_NMEhead2rl);
+ NewState(wheels,&s_NMEwheels2);
+ }
+
+}
+
+#define SPRAYDIST 0x12000
+
+void SelectOrobotChaseDir(objtype*ob) // this code is for head
+{
+ int dx,dy,angle,tx,ty;
+ int tdir,olddir,nextdir,prevdir;
+ objtype* head,*wheels;
+
+
+
+ head = (objtype*)(ob->whatever);
+ wheels = (objtype*)(ob->target);
+ olddir=head->dir;
+
+findplayer:
+ if (ob->temp1 == -1)
+ {
+ if (ob->targettilex || ob->targettiley)
+ {
+ tx = (int)((ob->targettilex << TILESHIFT) + HALFGLOBAL1);
+ ty = (int)((ob->targettiley << TILESHIFT) + HALFGLOBAL1);
+ dx= tx - ob->x;
+ dy= ob->y - ty;
+ if (((dx <SPRAYDIST ) && (dx > -SPRAYDIST)) &&
+ ((dy <SPRAYDIST ) && (dy > -SPRAYDIST)))
+ {
+ dx= PLAYER[0]->x-ob->x;
+ dy= ob->y - PLAYER[0]->y;
+ }
+ }
+ else
+ {
+ dx= PLAYER[0]->x - ob->x;
+ dy= ob->y - PLAYER[0]->y;
+ }
+
+ angle = atan2_appx(dx,dy);
+
+ tdir = (((angletodir[angle])<<1) & 0xf);
+ }
+ else
+ {
+ tdir = (ob->temp1 & 0xf);
+
+ if ((head->dir == (unsigned)tdir) && (ob->dir == (unsigned)tdir)) // increment
+ // tried dir if robot will attempt to move at tdir =>
+ // head and body are at move try dir
+ { //Debug("\ntrying next queue dir %d",tdir);
+ MISCVARS->NMEdirstried ++;
+ if (MISCVARS->NMEdirstried == MISCVARS->NMEqueuesize) //gone through all queue entries
+ { //Debug("\nqueue exhausted");
+ ob->temp1 = -1;
+ MISCVARS->NMEdirstried = 0;
+ goto findplayer;
+ }
+ }
+ }
+
+
+ if (tdir != olddir) //rotate head to new chase direction
+ {
+ nextdir = dirorder16[olddir][NEXT];
+ prevdir = dirorder16[olddir][PREV];
+ if (dirdiff16[tdir][nextdir] < dirdiff16[tdir][prevdir])
+ head->dir = nextdir;
+ else
+ head->dir = prevdir;
+ return;
+ }
+ //Debug("\nhead aligned to dir %d",tdir);
+
+ //oddir = ob->dir;
+ if (ob->dir != head->dir) // align body and wheels with head
+ {
+ ZEROMOM;
+ NewState(wheels,&s_NMEwheels120); //rotate wheels for spinning
+ nextdir = dirorder16[ob->dir][NEXT];
+ prevdir = dirorder16[ob->dir][PREV];
+ if (dirdiff16[head->dir][nextdir] < dirdiff16[head->dir][prevdir])
+ ob->dir = nextdir;
+ else
+ ob->dir = prevdir;
+ wheels->dir = ob->dir;
+ return;
+ }
+
+ // Debug("\nbody aligned to head at dir %d",ob->dir);
+
+ ZEROMOM;
+ ParseMomentum(ob,dirangle16[head->dir]);
+ // Debug("\ntrying to move at dir %d",head->dir);
+ ActorMovement(ob);
+ UpdateNMELinkedActors(ob);
+
+ if (ob->momentumx || ob->momentumy)
+ {
+ NewState(wheels,&s_NMEwheels2); // align wheels for movement
+ //Debug("\nmove at dir %d succesful, resetting queue",head->dir);
+ ob->temp1 = -1; //clear direction queue
+ return;
+ }
+ else if (ob->temp1 == -1) // if queue is empty
+ //make a queue of directions (byte packed)
+ {
+ //Debug("\nmove at dir %d failed and queue empty",head->dir);
+ ob->temp1 = 0;
+ MISCVARS->NMEdirstried = 0;
+ MISCVARS->NMEqueuesize = 0;
+
+ nextdir = ((tdir + 6) & 0xf);
+ prevdir = ((tdir - 6) & 0xf);
+
+ for(; MISCVARS->NMEqueuesize < 6; MISCVARS->NMEqueuesize += 2)
+ {
+ ob->temp1 <<= 4;
+ ob->temp1 += nextdir;
+ ob->temp1 <<= 4;
+ ob->temp1 += prevdir;
+ nextdir = ((nextdir-2) & 0xf);
+ prevdir = ((prevdir+2) & 0xf);
+
+ }
+#if 0
+ SoftError("\n straight dir: %d\n queue dirs ",tdir);
+ for(count = 0; count < MISCVARS->NMEqueuesize; count++)
+ {
+ SoftError("\n dir %d: %d",MISCVARS->NMEqueuesize-count,
+ ((ob->temp1 >> (4*count)) &0xf)
+ );
+
+ }
+#endif
+ }
+ else // else goto next queue dir;
+ {
+ ob->temp1 >>= 4;
+ }
+
+}
+
+
+
+void T_NME_Explode(objtype*ob)
+{
+
+ if (ob->ticcount == 35)
+ { objtype*head;
+ int op;
+
+ head = (objtype*)(ob->whatever);
+
+ op = FixedMul(GRAVITY,(head->z-25)<<16) << 1;
+ head->momentumz = -FixedSqrtHP(op);
+ head->momentumx = (GameRandomNumber("NME head momx",0) << 2);
+ head->momentumy = (GameRandomNumber("NME head momy",0) << 2);
+ head->hitpoints = 0;
+ head->flags |= FL_DYING;
+ NewState(head,&s_shootinghead);
+
+ //RemoveObj((objtype*)(ob->whatever)); // remove head
+ }
+ else if (!ob->ticcount)
+ { ob->shapeoffset = 0;
+ NewState(ob,&s_explosion1);
+ SetGibSpeed(0x4000);
+ SpawnParticles(ob,gt_sparks,200);
+ ResetGibSpeed();
+ RemoveObj((objtype*)(ob->target));
+ }
+
+}
+
+void T_NME_HeadShoot(objtype*ob)
+{ //int randtheta,i,offx,offy;
+
+ ob->z += (ob->momentumz>>16);
+
+ /*if (ob->momentumz < 0)
+ {for(i=0;i<3;i++)
+ {randtheta = (GameRandomNumber("NME spark drop",0) << 3);
+ SpawnNewObj(ob->tilex,ob->tiley,&s_particle1,inertobj);
+ new->temp2 = 1;
+ offx = FixedMul(0x400,costable[randtheta]);
+ offy = -FixedMul(0x400,sintable[randtheta]);
+ new->x = new->drawx = ob->x + offx;
+ new->y = new->drawy = ob->y + offy;
+ new->z = ob->z-15;
+ new->flags |= (FL_NOFRICTION|FL_CRAZY|FL_ABP);
+ new->dir = west;
+ MakeActive(new);
+ }
+ }*/
+
+ ob->momentumz += GRAVITY;
+ if (ob->z >= (nominalheight+45))
+ { ob->z = nominalheight+45;
+ if (ob->temp2)
+ { ob->momentumz = -30000*ob->temp2;
+ ob->temp2--;
+ }
+ else
+ { ob->momentumx = ob->momentumy = ob->momentumz = 0;
+ ob->shapeoffset = 0;
+ NewState(ob,&s_NMEheadexplosion);
+
+ return;
+ }
+ }
+ ActorMovement(ob);
+
+}
+
+
+boolean NMEspincheck(objtype*ob)
+{
+ int dx,dy,dz;
+
+ dx = abs(PLAYER[0]->x - ob->x);
+ dy = abs(PLAYER[0]->y - ob->y);
+ dz = abs(PLAYER[0]->z - ob->z);
+ if ((dx < 0x10000) && (dy < 0x10000) && (dz < 32))
+ {
+ NewState(ob,&s_NMEspinattack);
+ NewState((objtype*)(ob->target),&s_NMEwheelspin);
+ if (!ob->temp2)
+ NewState((objtype*)(ob->whatever),&s_NMEhead1);
+ else
+ NewState((objtype*)(ob->whatever),&s_NMEhead2);
+ ob->dirchoosetime = 1;
+ return true;
+ }
+ return false;
+}
+
+
+
+
+
+void T_NME_SpinAttack(objtype* ob)
+{ int mx,my,mz;
+ objtype*head,*wheels;
+
+
+
+ if (ob->ticcount == 30) // knock player back
+ { GetMomenta(PLAYER[0],ob,&mx,&my,&mz,0x4000);
+ DamageThing(PLAYER[0],20);
+ Collision(PLAYER[0],ob,mx,my);
+ M_CheckPlayerKilled(PLAYER[0]);
+ }
+ if (ob->dirchoosetime)
+ ob->dirchoosetime --;
+ else
+ { head = (objtype*)(ob->whatever);
+ wheels = (objtype*)(ob->target);
+ wheels->dir = head->dir = ob->dir = dirorder16[dirorder16[ob->dir][NEXT]][NEXT];
+
+ ob->dirchoosetime = 1;
+ }
+
+
+}
+
+
+void T_NME_SpinFire(objtype*ob)
+{
+ int randtheta,oldyzangle,dx,dy,xydist,dz;
+ objtype *head,*wheels;
+
+
+ head = (objtype*)(ob->whatever);
+ wheels = (objtype*)(ob->target);
+
+ if (ob->dir != (unsigned)ob->targettilex)
+ { ob->dir = head->dir = wheels->dir = dirorder16[ob->dir][ob->temp3];
+ return;
+ }
+
+ if (ob->dirchoosetime)
+ { ob->dirchoosetime --;
+ return;
+ }
+
+ if (ob->temp3 < 20)
+ { //randphi = (GameRandomNumber("NME generate phi",0) << 3) & ((ANGLES/2) -1);
+ if (GameRandomNumber("NME generate theta",0) < 128)
+ randtheta = (GameRandomNumber("NME generate theta",0)>>4);
+ else
+ randtheta = -(GameRandomNumber("NME generate theta",0)>>4);
+ dx = PLAYER[0]->x-ob->x;
+ dy = ob->y-PLAYER[0]->y;
+ if (GameRandomNumber("bcraft shoot up/down",0) < 128)
+ dz = 5;
+ else
+ dz = -5;
+ xydist = FindDistance(dx,dy);
+ randtheta += atan2_appx(dx,dy);
+ Fix(randtheta);
+ oldyzangle = ob->yzangle;
+ ob->yzangle = atan2_appx(xydist,dz<<10);
+ //ob->yzangle = randphi;
+ SD_PlaySoundRTP(BAS[ob->obclass].fire+1,ob->x,ob->y);
+ //wheels->dir = head->dir = ob->dir = dirorder16[dirorder16[ob->dir][NEXT]][NEXT];
+ SpawnMissile(ob,fireballobj,0x6000,randtheta,&s_NMEminiball1,0x10000);
+ ob->dirchoosetime = 1;
+ ob->yzangle = oldyzangle;
+ ob->temp3 ++;
+ }
+ else
+ { ob->temp3 = 0;
+ NewState(ob,&s_NMEchase);
+ NewState((objtype*)(ob->target),&s_NMEwheels2);
+ if (!ob->temp2)
+ NewState((objtype*)(ob->whatever),&s_NMEhead1);
+ else
+ NewState((objtype*)(ob->whatever),&s_NMEhead2);
+
+
+ }
+
+
+}
+
+void T_NME_Attack(objtype*ob)
+{ int angle,perpangle,i;
+
+
+
+ if (NMEspincheck(ob))
+ { //ob->temp3 = 0;
+ return;
+ }
+ if (ob->dirchoosetime)
+ { ob->dirchoosetime --;
+ return;
+ }
+
+
+ if (!CheckLine(ob,PLAYER[0],SIGHT))
+ { //ob->temp3 = 0;
+ //#if ((DEVELOPMENT == 1))
+ //Debug("\nCheckLine failed in NME Attack");
+ //#endif
+ NewState(ob,&s_NMEchase);
+ NewState((objtype*)(ob->target),&s_NMEwheels2);
+ if (!ob->temp2)
+ NewState((objtype*)(ob->whatever),&s_NMEhead1);
+ else
+ NewState((objtype*)(ob->whatever),&s_NMEhead2);
+ return;
+ }
+ //sound = BAS[ob->obclass].fire;
+ angle = AngleBetween(ob,PLAYER[0]);
+
+
+
+ if ((ob->temp3 == 0) || (ob->temp3 == 1)) //heatseek
+
+ { SD_PlaySoundRTP(BAS[ob->obclass].fire+2,ob->x,ob->y);
+ angle = AngleBetween(ob,PLAYER[0]);
+ SpawnMissile(ob,missileobj,0x6000,angle,&s_missile1,0x8000);
+ if (ob->temp3 == 3)
+ perpangle = angle + ANGLES/4;
+ else
+ perpangle = angle - ANGLES/4;
+ Fix(perpangle);
+
+ new->temp1 = NME_HEATSEEKINGTYPE;
+ SetFinePosition(new,new->x + FixedMul(0x8000l,costable[perpangle]),
+ new->y - FixedMul(0x8000l,sintable[perpangle]));
+ SetVisiblePosition(new,new->x,new->y);
+ if (!ob->temp3)
+ ob->dirchoosetime = 20;
+ else
+ { ob->dirchoosetime = 35 - (ob->shapeoffset >> 2) - (gamestate.difficulty << 2);//70;
+ if (!ob->temp2)
+ NewState((objtype*)(ob->whatever),&s_NMEhead1);
+ else
+ NewState((objtype*)(ob->whatever),&s_NMEhead2);
+ }
+ ob->temp3 ++;
+
+ }
+
+ else if (ob->temp3 == 2) // saucer
+ { SpawnMissile(ob,NMEsaucerobj,0x1000,angle,&s_NMEsaucer1,0xc000);
+ new->flags |= FL_SHOOTABLE;
+ ob->temp3++;
+ ob->dirchoosetime = 35 - (ob->shapeoffset >> 2) - (gamestate.difficulty << 2);//70;
+ if (!ob->temp2)
+ NewState((objtype*)(ob->whatever),&s_NMEhead1rl);
+ else
+ NewState((objtype*)(ob->whatever),&s_NMEhead2rl);
+ }
+
+ else if ((ob->temp3 == 3) || (ob->temp3 == 4)) // drunk
+ { SD_PlaySoundRTP(BAS[ob->obclass].fire+2,ob->x,ob->y);
+ if (!ob->temp3)
+ perpangle = angle + ANGLES/4;
+ else
+ perpangle = angle - ANGLES/4;
+ Fix(perpangle);
+ for(i=0; i<(2+gamestate.difficulty); i++)
+ {
+ SpawnMissile(ob,missileobj,0x6000,angle,&s_missile1,0x8000);
+ new->temp1 = NME_DRUNKTYPE;
+ SetFinePosition(new,new->x + FixedMul(0x8000l,costable[perpangle]),
+ new->y - FixedMul(0x8000l,sintable[perpangle]));
+ SetVisiblePosition(new,new->x,new->y);
+ }
+
+ if (ob->temp3 == 3)
+ ob->dirchoosetime = 20;
+ else
+ { ob->temp3 = 0;
+ NewState(ob,&s_NMEchase);
+ if (!ob->temp2)
+ NewState((objtype*)(ob->whatever),&s_NMEhead1);
+ else
+ NewState((objtype*)(ob->whatever),&s_NMEhead2);
+ }
+
+ ob->temp3 ++;
+
+ }
+
+
+
+}
+
+
+
+//================== Tom/Snake ============================================
+
+
+
+
+
+void T_DarkSnakeSpawn(objtype*ob)
+{
+ objtype * linkinfront;
+
+ if (((ob->state == &s_darkmonkhspawn) && (!(ob->ticcount%8))) ||
+ ((ob->state == &s_darkmonkfastspawn) && (!(ob->ticcount%4))))
+ {
+ GetNewActor();
+ MakeActive(new);
+ SetFinePosition(new,ob->x,ob->y);
+ SetVisiblePosition(new,ob->x,ob->y);
+ new->z = nominalheight;
+ new->areanumber = MAPSPOT(new->tilex,new->tiley,0)-AREATILE;
+ MakeLastInArea(new);
+ new->obclass = b_darksnakeobj;
+ new->which = ACTOR;
+ new->angle = AngleBetween(ob,PLAYER[0]);
+ new->dir = angletodir[new->angle];
+ if (SNAKELEVEL == 1)
+ new->speed = 0x5000;
+ else if (SNAKELEVEL == 2)
+ new->speed = 0x5800;
+ else
+ new->speed = 0x2000;
+
+
+ new->hitpoints = 1000;
+ new->dirchoosetime = 0;
+ new->door_to_open = -1;
+
+ new->flags |= (FL_ABP|FL_NOFRICTION|FL_SHOOTABLE|FL_BLOCK);
+
+ if (ob->whatever)
+ {
+ linkinfront = (objtype*)(ob->whatever);
+ linkinfront->whatever = new;
+ new->target = linkinfront;
+ new->targettilex = linkinfront->x;
+ new->targettiley = linkinfront->y;
+ new->angle = AngleBetween(new,linkinfront);
+ new->dir = angletodir[new->angle];
+ new->flags |= FL_NEVERMARK;
+ ParseMomentum(new,new->angle);
+ NewState(new,&s_darkmonksnakelink);
+ }
+
+ else
+ {
+ SNAKEHEAD = new;
+ if (SNAKELEVEL == 3)
+ NewState(new,&s_darkmonkhead);
+ else if (SNAKELEVEL == 1)
+ {
+ NewState(new,&s_snakefindpath);
+ new->flags |= FL_ATTACKMODE;
+ }
+ else if (SNAKELEVEL == 2)
+ {
+ NewState(new,&s_snakepath);
+ new->angle = 3*ANGLES/4;
+ new->dir = angletodir[new->angle];
+ new->flags |= FL_ATTACKMODE;
+
+ }
+ ob->targettilex = ob->targettiley = 0;
+ ParseMomentum(new,new->angle);
+ }
+
+ if (!ob->ticcount)
+ SNAKEEND = new;
+
+ ob->whatever = new;
+
+ }
+}
+
+
+void T_GenericMove(objtype*ob)
+{ int dx,dy;
+
+ if (ob->temp3 == -1)
+ return;
+
+
+ if (!(SNAKEHEAD->flags & FL_ATTACKMODE))
+ return;
+
+ if (ob->hitpoints <= 0)
+ { KillActor(ob);
+ ob->temp3 = 0;
+ return;
+ }
+
+ if (!ob->ticcount)
+ { if (ob->state == &s_darkmonkredlink)
+ ob->temp3 = 0;
+ else if ((ob!=SNAKEEND) && (ob->state == &s_redlinkhit))
+ NewState((objtype*)(ob->whatever),&s_redlinkhit);
+ }
+
+ dx = ob->targettilex-ob->x;
+ dy = ob->y-ob->targettiley;
+ if ((dx > -0xa000) && (dx < 0xa000) && (dy > -0xa000) && (dy < 0xa000))
+ { if (ob->temp1 && ob->temp2)
+ { dx = ob->temp1 - ob->x;
+ dy = ob->y - ob->temp2;
+ ZEROMOM;
+ /*
+ if ((ob->targettilex == ob->temp1) && (ob->targettiley == ob->temp2))
+ return; */
+ //ob->x = ob->drawx = ob->targettilex;
+ //ob->y = ob->drawy = ob->targettiley;
+ //ob->tilex = ob->x >> TILESHIFT;
+ //ob->tiley = ob->y >> TILESHIFT;
+ //#if ((DEVELOPMENT == 1))
+ // Debug("\nfollower %d being moved to targetx %4x and targety %4x",
+ // ob-SNAKEHEAD,ob->x,ob->y);
+ // #endif
+ ob->targettilex = ob->temp1;
+ ob->targettiley = ob->temp2;
+#if (0)
+ Debug("\nfollower %d's new targetx %4x, targety %4x",
+ ob-SNAKEHEAD,ob->temp1,ob->temp2);
+#endif
+ ob->angle = atan2_appx(dx,dy);
+ ob->dir = angletodir[ob->angle];
+ ParseMomentum(ob,ob->angle);
+ }
+ }
+ else if (NOMOM)
+ { //SNAKEHEAD->dirchoosetime = 0;
+ ParseMomentum(ob,ob->angle);
+ }
+ if (ob->momentumx || ob->momentumy)
+ MoveActor(ob);
+
+// ActorMovement(ob);
+
+}
+
+
+/*
+===============
+=
+= SelectSnakeDir
+=
+===============
+*/
+
+
+void SelectSnakeDir (objtype *ob)
+{
+ int spot,centerx,centery,dx,dy;
+
+ spot = MAPSPOT(ob->tilex,ob->tiley,1)-ICONARROWS;
+
+ if ((spot >= 0) && (spot<= 7) && ((ob->dir!=(unsigned)spot)||(!(ob->flags & FL_DONE))))
+ { centerx= (ob->tilex << 16) + HALFGLOBAL1;
+ centery= (ob->tiley << 16) + HALFGLOBAL1;
+ dx = abs(centerx - ob->x);
+ dy = abs(centery - ob->y);
+
+ if ((dx < SNAKERAD) && (dy < SNAKERAD))
+ // new direction
+ { ZEROMOM;
+ ob->dir = spot;
+ ob->flags |= FL_DONE;
+ ParseMomentum(ob,dirangle8[ob->dir]);
+ SetFinePosition(ob,centerx,centery);
+ SetVisiblePosition(ob,ob->x,ob->y);
+
+ if (ob==SNAKEHEAD) {
+ SoftError("\n path changed at %d, %d",ob->tilex,ob->tiley);
+ }
+ }
+ }
+
+ MoveActor(ob);
+
+}
+
+
+void T_SnakePath(objtype*ob)
+{ objtype*temp,*follower;
+
+ if (SNAKEEND && (SNAKELEVEL == 2))
+ { if (CheckLine(SNAKEEND,PLAYER[0],SIGHT))
+ { if (ob->temp3 == -1) //if snake can see player
+ //and he's presently stopped, restart
+ { for(temp=ob; temp; temp=(objtype*)(temp->whatever))
+ { temp->temp3 = 0;
+ temp->momentumx = temp->temp1;
+ temp->momentumy = temp->temp2;
+ }
+ ob->dirchoosetime = 0;
+ }
+ }
+ else if (ob->temp3 != -1) //else if he hasn't been stopped, stop him
+ { for(temp=ob; temp; temp = (objtype*)(temp->whatever))
+ { temp->temp1 = temp->momentumx;
+ temp->temp2 = temp->momentumy;
+ temp->temp3 = -1;
+ temp->momentumx = temp->momentumy = 0;
+ }
+ }
+ else
+ return;
+ }
+
+
+ if (ob->dirchoosetime)
+ ob->dirchoosetime--;
+
+ else
+ { int count = 0;
+
+ for(temp=ob; temp->whatever; temp=(objtype*)(temp->whatever))
+ { follower = (objtype*)(temp->whatever);
+ follower->temp1 = temp->x;
+ follower->temp2 = temp->y;
+
+ SoftError("\n follower %d temp1 set to %4x, temp2 set to %4x",
+ count,temp->x,temp->y);
+ count ++;
+ }
+ ob->dirchoosetime = 2 ;//15
+ }
+
+ if (ob->momentumx || ob->momentumy)
+ SelectSnakeDir(ob);
+//else
+// {ParseMomentum(ob,ob->angle);
+// MoveActor(ob);
+// }
+
+
+}
+
+void FindClosestPath(objtype*ob)
+{ int tx,ty,dx,dy,angle;
+
+
+ tx = (ob->targettilex << 16) + TILEGLOBAL/2;
+ ty = (ob->targettiley << 16) + TILEGLOBAL/2;
+
+ dx= tx - ob->x;
+ dy= ob->y - ty;
+ angle = atan2_appx(dx,dy);
+
+ ZEROMOM;
+ ParseMomentum(ob,angle);
+ MoveActor(ob);
+
+}
+
+
+void T_SnakeFindPath(objtype*ob)
+{ int i,dx,dy,currdist,mindist,map;
+ tpoint dstruct,*dummy=&dstruct;
+ objtype*temp,*follower;
+
+ if (ob->targettilex || ob->targettiley)
+ { FindClosestPath(ob);
+ dx = ob->targettilex - ob->tilex;
+ dy = ob->targettiley - ob->tiley;
+ if ((!dx) && (!dy))
+ { SetTilePosition(ob,ob->tilex,ob->tiley);
+ SetVisiblePosition(ob,ob->x,ob->y);
+ ob->y = ob->drawy = (ob->tiley << TILESHIFT) + TILEGLOBAL/2;
+ NewState(ob,&s_snakepath);
+ return;
+ }
+ }
+
+ else
+ { dummy->which = ACTOR;
+ mindist = 0x7fffffff;
+ for(i=0; i<whichpath; i++)
+ {
+ SetTilePosition(dummy,SNAKEPATH[i].x,SNAKEPATH[i].y);
+ dummy->z = ob->z;
+ if (CheckLine(ob,dummy,SIGHT))
+ { currdist = FindDistance(ob->tilex-dummy->tilex,ob->tiley-dummy->tiley);
+ map = MAPSPOT(ob->tilex,ob->tiley,0)-AREATILE;
+ if ((currdist < mindist) && (map >= 0) && (map <= NUMAREAS))
+ { ob->targettilex = dummy->tilex;
+ ob->targettiley = dummy->tiley;
+ mindist = currdist;
+ }
+ }
+ }
+ }
+
+ if (ob->dirchoosetime)
+ ob->dirchoosetime--;
+ else
+ { for(temp=ob; temp->whatever; temp=(objtype*)(temp->whatever))
+ { follower = (objtype*)(temp->whatever);
+ follower->temp1 = temp->x;
+ follower->temp2 = temp->y;
+ }
+ ob->dirchoosetime = 2 ;//15
+ }
+}
+
+
+
+void T_SnakeFinale(objtype*ob)
+{
+
+ if ((ob->state == &s_snakefireworks1)||(ob->state == &s_snakefireworks2))
+ {
+ if (ob->z != (maxheight-200))
+ {
+ ob->z --;
+ return;
+ }
+ SetGibSpeed(0x4500);
+ SpawnParticles(ob,RANDOM,100);
+
+ SpawnParticles(ob,gt_spit,100);
+ ResetGibSpeed();
+ NewState(ob,&s_dexplosion1);
+ }
+
+ else
+ {
+ if (!ob->ticcount)
+ {
+ NewState(EXPLOSIONS,&s_megaremove);
+ // SpawnParticles(ob,RANDOM,100);
+ // SpawnParticles(ob,SPIT,100);
+ return;
+ }
+
+ if (ob->dirchoosetime)
+ ob->dirchoosetime --;
+ else
+ {
+ ob->dirchoosetime = (GameRandomNumber("snake finale choose",0) % 7) + 15;
+ SetGibSpeed(0x3000);
+ SpawnParticles(ob,RANDOM,30);
+ SpawnParticles(ob,gt_spit,20);
+ ResetGibSpeed();
+ }
+ }
+}
+
+
+
+void T_DarkSnakeChase(objtype*ob)
+{
+ objtype* temp,*follower;
+ int tdir,angle;
+
+
+ if (!(ob->flags & FL_ATTACKMODE))
+ {
+ if (!(CheckSight(ob,player) || Near(ob,player,4)))
+ return;
+ else
+ {
+ ob->flags |= FL_ATTACKMODE;
+ MU_StartSong(song_bosssee);
+ }
+
+ }
+
+
+
+ if (ob->hitpoints <= 0)
+ {
+ MU_StartSong(song_bossdie);
+ KillActor(ob);
+ AddMessage("Oscuro defeated!",MSG_CHEAT);
+ return;
+ }
+
+ angle = AngleBetween(ob,PLAYER[0]);
+ tdir = angletodir[angle];
+ if (Near(ob,PLAYER[0],6) && (ob->dir == (unsigned)tdir) && (!(ob->state->condition & SF_DOWN)))
+ {
+ NewState(ob,&s_snakefire1);
+ SD_PlaySoundRTP(SD_SNAKEREADYSND,ob->x,ob->y);
+ }
+
+ if (!ob->ticcount)
+ {
+ if (ob->state == &s_darkmonkredhead)
+ ob->temp3 = 0; // no longer hitable
+ else if ((ob->state == &s_redheadhit) && (ob != SNAKEEND))
+ NewState((objtype*)(ob->whatever),&s_redlinkhit);
+ else if (ob->state->condition & SF_UP)
+ {
+ SpawnMissile(ob,dm_spitobj,0x6000,angle,&s_spit1,0x6000);
+ SD_PlaySoundRTP(BAS[ob->obclass].fire,ob->x,ob->y);
+ //new->z -= 5;
+ }
+ //spawn spit;
+ }
+
+ if (CheckLine(ob,PLAYER[0],SIGHT))
+ {
+ ob->targettilex = PLAYER[0]->x;
+ ob->targettiley = PLAYER[0]->y;
+ }
+
+ if (ob->dirchoosetime)
+ {
+ ob->dirchoosetime--;
+ ActorMovement(ob);
+ if (NOMOM)
+ ob->dirchoosetime = 0;
+ }
+
+ else
+ { //if (ob)
+ for(temp=ob; temp->whatever; temp=(objtype*)(temp->whatever))
+ {
+ follower = (objtype*)(temp->whatever);
+ follower->temp1 = temp->x;
+ follower->temp2 = temp->y;
+ }
+ SelectChaseDir(ob);
+ ob->dirchoosetime = 7 ;//15
+ }
+}
+
+
+
+void T_DarkmonkReact(objtype*ob)
+{
+ if (ob->z < nominalheight)
+ { MISCVARS->monkz += MZADJUST;
+ ob->z = nominalheight + (MISCVARS->monkz >> 16);
+ //ob->z++;
+ return;
+ }
+
+ else
+ { int ocl;
+
+ ocl = ob->temp3;
+
+ if (ocl == p_kesobj)
+ NewState(ob,&s_darkmonkabsorb1);
+ else if (ocl == p_heatseekobj)
+ NewState(ob,&s_darkmonkhball1);
+ else if (ocl == p_firebombobj)
+ NewState(ob,&s_darkmonkbreathe1);
+ else
+ NewState(ob,&s_darkmonkchase1);
+ ob->dirchoosetime = 0;
+ }
+
+}
+
+
+
+void T_DarkmonkCharge(objtype*ob)
+{ int dx,dy;
+
+ dx = abs(PLAYER[0]->x - ob->x);
+ dy = abs(PLAYER[0]->y - ob->y);
+ if ((dx < 0xa000) && (dy < 0xa000))
+ { DamageThing(PLAYER[0],10);
+ Collision(PLAYER[0],ob,0,0);
+ M_CheckPlayerKilled(PLAYER[0]);
+ }
+
+ if (!ob->ticcount)
+ ob->speed >>= 1;
+
+ if (ob->dirchoosetime)
+ ob->dirchoosetime --;
+
+ if (NOMOM || (!ob->dirchoosetime))
+ { ob->angle = AngleBetween(ob,PLAYER[0]);
+ ob->dir = angletodir[ob->angle];
+ ParseMomentum(ob,ob->angle);
+ ob->dirchoosetime = 5;
+ }
+
+ ActorMovement(ob);
+
+
+}
+
+
+void T_DarkmonkLandAndFire(objtype*ob)
+{
+
+ if (ob->z < nominalheight)
+ { MISCVARS->monkz += MZADJUST;
+ ob->z = nominalheight + (MISCVARS->monkz >> 16);
+ //ob->z++;
+ return;
+ }
+ if (Near(ob,PLAYER[0],3))
+ { if (GameRandomNumber("darkmonkland",0)<128)
+ NewState(ob,&s_darkmonkbball1);
+ else
+ { ob->angle = AngleBetween(ob,PLAYER[0]);
+ ob->dir = angletodir[ob->angle];
+ ob->speed <<= 1; // goes twice as fast
+ ZEROMOM;
+ ParseMomentum(ob,ob->angle);
+ ob->dirchoosetime = 5; // change dir every 5 tics
+ ob->hitpoints -= 200; // big penalty for charging
+ if (ob->hitpoints <= 0)
+ { objtype*column = (objtype*)(ob->whatever);
+
+ EnableObject((long)column);
+ ob->whatever = NULL;
+
+ KillActor(ob);
+ NewState(ob,&s_darkmonkfastspawn);
+ AddMessage("Oscuro flees!",MSG_CHEAT);
+ return;
+ }
+ NewState(ob,&s_darkmonkcharge1);
+ }
+
+ }
+ else if (ob->temp1)
+ NewState(ob,&s_darkmonklightning1);
+ else
+ NewState(ob,&s_dmgreenthing1);
+ ob->temp1 ^= 1;
+ ob->dirchoosetime = 0;
+
+}
+
+
+void T_DarkmonkChase(objtype*ob)
+{ int chance,dx,dy,dist;
+
+
+ if (!Near(ob,PLAYER[0],2))
+ { if (ob->z > (maxheight - 100))
+ { MISCVARS->monkz -= MZADJUST;
+ ob->z = nominalheight + (MISCVARS->monkz >> 16);
+ //ob->z--;
+ return;
+ }
+ }
+ else if (ob->z < nominalheight)
+ { MISCVARS->monkz += MZADJUST;
+ ob->z = nominalheight + (MISCVARS->monkz >> 16);
+ //ob->z++;
+ return;
+ }
+
+
+ if (CheckLine(ob,PLAYER[0],SIGHT))
+ { ob->targettilex = PLAYER[0]->x;
+ ob->targettiley = PLAYER[0]->y;
+ }
+
+ if (!ob->ticcount)
+ {
+ if (CheckLine(ob,PLAYER[0],SHOOT)) // got a shot at player?
+ { dx = abs(ob->tilex - PLAYER[0]->tilex);
+ dy = abs(ob->tiley - PLAYER[0]->tiley);
+ dist = dx>dy ? dx : dy;
+ if (!dist || dist==1)
+ chance = 300;//300;
+ else
+ chance = 400/dist;//300/dist;
+
+ if (GameRandomNumber("T_DarkMonkChase",0) < chance)
+ { NewState(ob,&s_dmlandandfire);
+ return;
+ }
+ }
+ }
+
+ if (ob->dirchoosetime)
+ ob->dirchoosetime--;
+
+ if ((ob->flags & FL_STUCK) || (!ob->dirchoosetime))
+ { SelectChaseDir(ob);
+ ob->dirchoosetime = M_CHOOSETIME(ob);
+ }
+
+ else
+ { if (NOMOM)
+ ParseMomentum(ob,dirangle8[ob->dir]);
+ ActorMovement(ob);
+
+ }
+
+}
+
+
+//====================== End of Boss Functions ===========================//
+
+
+
+
+
+
+void T_GunStand(objtype*ob)
+{ int dy,dx,infrontof,dz;
+ objtype* temp;
+
+// if (ob->target)
+// Error("gun reset with non-null target");
+ for(temp = firstareaactor[ob->areanumber]; temp; temp= temp->nextinarea)
+ { if (temp == ob)
+ continue;
+ if (temp->obclass == ob->obclass)
+ continue;
+ if ((!(temp->flags & FL_SHOOTABLE)) || (temp->flags & FL_DYING))
+ continue;
+
+ dy = ob->y - temp->y;
+ dx = ob->x - temp->x;
+ dz = ob->z - temp->z;
+ if ((abs(dy)>0x40000) || (abs(dx)>0x40000) || (abs(dz) > 20))
+ continue;
+
+
+ infrontof = 0;
+
+ switch (ob->dir)
+ {
+ case north:
+ if ((dy > 0) && (abs(dx)<0x8000))
+ infrontof = 1;
+ break;
+
+ case east:
+ if ((dx < 0) && (abs(dy)<0x8000))
+ infrontof = 1;
+ break;
+
+ case south:
+ if ((dy < 0) && (abs(dx)<0x8000))
+ infrontof = 1;
+ break;
+
+ case west:
+ if ((dx > 0) && (abs(dy)<0x8000))
+ infrontof = 1;
+ break;
+
+ default:
+ break;
+ }
+
+ if (infrontof && CheckLine(ob,temp,SHOOT))
+ { ob->target = temp;
+ NewState(ob,&s_gunraise1);
+ return;
+ }
+ }
+
+}
+
+
+void T_4WayGunStand(objtype*ob)
+{
+ int dy,dx,dz;
+ objtype* temp;
+
+ if (ob->target)
+ Error("gun reset with non-null target");
+ for(temp = firstareaactor[ob->areanumber]; temp; temp= temp->nextinarea)
+ {
+ if (temp == ob)
+ continue;
+
+ if (temp->obclass == ob->obclass)
+ continue;
+
+ if ((!(temp->flags & FL_SHOOTABLE)) || (temp->flags & FL_DYING))
+ continue;
+
+ dy = abs(ob->x-temp->x);
+ dx = abs(ob->y-temp->y);
+ dz = abs(ob->z-temp->z);
+ if ((dx < 0x40000) && (dy < 0x40000) && (dz< 20) && CheckLine(ob,temp,SHOOT))
+ { //if ((dx < 0x8000) || (dy <0x8000))
+ ob->target = temp;
+ NewState(ob,&s_4waygunfire1);
+ return;
+ }
+ }
+}
+
+
+void A_GunShoot(objtype*ob)
+{ int dx,dy,dz,damage,infrontof,tnear,savedangle;
+ objtype * target;
+
+ if (!ob->ticcount)
+ { target = (objtype*)(ob->target);
+ if (!target)
+ Error("an instance of %s called gunshoot without a target\n",debugstr[ob->obclass]);
+ if ((!(target->flags & FL_SHOOTABLE)) || (target->flags & FL_DYING))
+ { NewState(ob,&s_gunlower1);
+ ob->target = NULL;
+ return;
+ }
+
+ dx = target->x-ob->x;
+ dy = ob->y-target->y;
+ dz = ob->z-target->z;
+
+
+ tnear = ((abs(dy)<0x40000) && (abs(dx)<0x40000) && (abs(dz) < 20));
+ infrontof = 0;
+
+ switch (ob->dir)
+ {
+ case north:
+ if ((dy > 0) && (abs(dx)<0x8000))
+ infrontof = 1;
+ break;
+
+ case east:
+ if ((dx < 0) && (abs(dy)<0x8000))
+ infrontof = 1;
+ break;
+
+ case south:
+ if ((dy < 0) && (abs(dx)<0x8000))
+ infrontof = 1;
+ break;
+
+ case west:
+ if ((dx > 0) && (abs(dy)<0x8000))
+ infrontof = 1;
+ break;
+
+ default:
+ break;
+ }
+
+ if ((!infrontof) || (!CheckLine(ob,target,SHOOT)) ||
+ (!tnear))
+ { NewState(ob,&s_gunlower1);
+ ob->target = NULL;
+ return;
+ }
+
+ //SD_PlaySoundRTP(SD_FIRE,PLAYER[0]->x,PLAYER[0]->y,ob->x,ob->y);
+ //hitchance = 128;
+
+// if (!target)
+ // Error("object called shoot without a target\n");
+
+
+ damage = DMG_AHGUN;
+
+
+ if (target->obclass == playerobj)
+ { target->target = ob;
+ if (target->flags & FL_BPV)
+ damage >>= 1;
+
+ }
+ savedangle = ob->angle;
+ ob->angle = atan2_appx(dx,dy);
+ RayShoot(ob,damage,GameRandomNumber("A_GunShoot Accuracy",0) % 20);
+ ob->angle = savedangle;
+ SD_PlaySoundRTP(SD_BIGEMPLACEFIRESND,ob->x,ob->y);
+ }
+
+}
+
+
+void A_4WayGunShoot(objtype*ob)
+{
+ int dx,dy,dz,damage,savedangle;
+ objtype * target;
+
+ if (ob->ticcount == (ob->state->tictime >> 1))
+ {
+ target = (objtype*)(ob->target);
+ if (!target)
+ Error("an instance of %s called 4waygunshoot without a target\n",debugstr[ob->obclass]);
+ dx = abs(target->x-ob->x);
+ dy = abs(ob->y-target->y);
+ dz = abs(ob->z-target->z);
+ if ((dx > 0x40000) || (dy > 0x40000) || (dz > 20) ||
+ (!CheckLine(ob,target,SHOOT)) ||
+ (!(target->flags & FL_SHOOTABLE)) ||
+ (target->flags & FL_DYING)
+ )
+ {
+ ob->target = NULL;
+ NewState(ob,&s_4waygun);
+ return;
+ }
+
+
+ //SD_PlaySoundRTP(SD_FIRE,PLAYER[0]->x,PLAYER[0]->y,ob->x,ob->y);
+ //hitchance = 128;
+
+ // if (!target)
+ // Error("object called shoot without a target\n");
+
+
+ damage = DMG_AHGUN;
+ SD_PlaySoundRTP(BAS[ob->obclass].fire,ob->x,ob->y);
+
+ if (target->obclass == playerobj)
+ {
+ target->target = ob;
+ if (target->flags & FL_BPV)
+ damage >>= 1;
+ }
+
+ savedangle = ob->angle;
+ ob->angle = 0;
+ RayShoot(ob,damage,GameRandomNumber("A_4WayGunShoot Accuracy",0) % 20);
+ ob->angle = ANG90;
+ RayShoot(ob,damage,GameRandomNumber("A_4WayGunShoot Accuracy",0) % 20);
+ ob->angle = ANG180;
+ RayShoot(ob,damage,GameRandomNumber("A_4WayGunShoot Accuracy",0) % 20);
+ ob->angle = ANG270;
+ RayShoot(ob,damage,GameRandomNumber("A_4WayGunShoot Accuracy",0) % 20);
+ ob->angle = savedangle;
+ }
+}
+
+
+void A_Drain (objtype *ob)
+{
+ int dx,dy,dz,damage;
+
+ dx = abs(PLAYER[0]->x - ob->x);
+ dy = abs(PLAYER[0]->y - ob->y);
+ dz = abs(PLAYER[0]->z - ob->z);
+
+ if ((dx > TOUCHDIST) || (dy > TOUCHDIST) || (dz > (TOUCHDIST>>10)))
+ {
+ NewState(ob,&s_dmonkshoot5);
+ return;
+ }
+
+ if (ob->ticcount)
+ return;
+
+ else
+ {
+ damage = (GameRandomNumber("A_Drain",ob->obclass) >> 3);
+ DamageThing (PLAYER[0],damage);
+ ob->hitpoints += damage;
+ if (ob->hitpoints > starthitpoints[gamestate.difficulty][ob->obclass])
+ ob->hitpoints = starthitpoints[gamestate.difficulty][ob->obclass];
+
+ Collision(PLAYER[0],ob,0,0);
+ if (PLAYER[0]->flags & FL_DYING)
+ PLAYER[0]->target = ob;
+ M_CheckPlayerKilled(PLAYER[0]);
+ SD_PlaySoundRTP(SD_MONKGRABSND,ob->x,ob->y);
+ }
+}
+
+
+
+
+
+
+void A_DmonkAttack(objtype*ob)
+{ int angle,nobclass,nspeed,altangle1=0,altangle2=0,zoff=0,sound;
+ statetype *nstate;
+
+
+ if (!ob->ticcount)
+ {
+ ob->hitpoints -= 120;//120;
+ if (ob->hitpoints <= 0)
+ {
+ objtype*column = (objtype*)(ob->whatever);
+
+ EnableObject((long)column);
+ ob->whatever = NULL;
+
+ KillActor(ob);
+ NewState(ob,&s_darkmonkfastspawn);
+ return;
+ }
+ }
+
+
+ if (ob->dirchoosetime)
+ ob->dirchoosetime --;
+
+ else
+ { sound = BAS[ob->obclass].fire;
+ angle = AngleBetween(ob,PLAYER[0]);
+ nspeed = 0x6000;
+
+ if (ob->state == &s_darkmonksphere8)
+ { nstate = &s_kessphere1;
+ nobclass = p_kesobj;
+ ob->dirchoosetime = 70;
+ }
+
+ else if (ob->state == &s_darkmonkhball7)
+ { nstate = &s_handball1;
+ nobclass = dm_heatseekobj;
+ nspeed = 0x3000;
+ ob->dirchoosetime = 5;
+ }
+
+ else if (ob->state == &s_darkmonkbball7)
+ { nstate = &s_faceball1;
+ nobclass = dm_weaponobj;
+ nspeed = 0x3000;
+ ob->dirchoosetime = 5;
+ }
+
+ else if (ob->state == &s_darkmonklightning9)
+ { nstate = &s_lightning;
+ nobclass = dm_weaponobj;
+ ob->dirchoosetime = 3;
+ sound++;
+ }
+
+ else if (ob->state == &s_dmgreenthing8)
+ { nstate = &s_energysphere1;
+ nobclass = dm_weaponobj;
+ sound +=2;
+ ob->dirchoosetime = 70;
+ }
+
+ else if (ob->state == &s_darkmonkfspark5)
+ { nstate = &s_floorspark1;
+
+ altangle1 = angle + ANGLES/24;
+ altangle2 = angle - ANGLES/24;
+ Fix(altangle1);
+ Fix(altangle2);
+ nobclass = dm_weaponobj;
+ ob->dirchoosetime = 3;
+ sound += 3;
+ }
+
+ else if (ob->state == &s_darkmonkbreathe6)
+ { nstate = &s_crossfire1;
+ ob->dirchoosetime = 3;
+ nobclass = dm_weaponobj;
+ zoff = -15;
+ sound += 3;
+ }
+
+ SpawnMissile(ob,nobclass,nspeed,angle,nstate,0xb000);
+ SD_PlaySoundRTP(sound,ob->x,ob->y);
+
+ new->z = ob->z+zoff;
+ if (altangle1)
+ {
+ SpawnMissile(ob,nobclass,nspeed,altangle1,nstate,0xb000);
+ SpawnMissile(ob,nobclass,nspeed,altangle2,nstate,0xb000);
+ }
+ }
+
+
+
+}
+
+
+
+#endif // SHAREWARE endif
+
+
+
+
+//=====================================================================//
+
+
+
+
+/*
+===============
+=
+= T_Stand
+=
+===============
+*/
+
+void T_Stand (objtype *ob)
+{
+ if (!ob->ticcount)
+ SightPlayer (ob);
+ else
+ SoftError("\n ob type %s ticcount of %d in T_Stand",debugstr[ob->obclass],
+ ob->ticcount);
+}
+
+
+
+
+
+void DamagePlayerActor(objtype *ob, int damage)
+
+{
+ playertype *pstate;
+
+ switch (gamestate.difficulty)
+ {
+ case 0:
+ damage >>= 1;
+ break;
+ case 1:
+ damage -= (damage >> 2);
+ break;
+ case 2:
+ break;
+ case 3: //damage += (damage>>2);
+ break;
+ //default: Error("Um, Gamestate.Difficulty, uh, has problems.\n");
+ }
+
+ if (!damage) damage++;
+
+ M_LINKSTATE(ob,pstate);
+
+
+ pstate->health -= damage;
+ ob->hitpoints = pstate->health;
+
+ SD_PlaySoundRTP(SD_PLAYERTCHURTSND+(pstate->player),ob->x,ob->y);
+ if (ob==player)
+ {
+ damagecount += damage;
+ if (cybermanenabled)
+ SWIFT_TactileFeedback (10*damage, 15, 15);
+ if ( SHOW_BOTTOM_STATUS_BAR() )
+ DrawBarHealth (false);
+ }
+
+ if (pstate->health<=0)
+ {
+ pstate->health = 0;
+ ob->hitpoints = 0;
+ }
+}
+
+
+
+
+void DamageNonPlayerActor(objtype *ob,int damage)
+{
+ //if ((ob->obclass == b_darksnakeobj) && (!ob->temp3))
+ // return;
+
+ if (!(ob->flags & FL_ATTACKMODE))
+ damage <<= 1;
+
+ ob->hitpoints -= damage;
+ if (ob->hitpoints <= 0)
+ {
+ int sound;
+
+ sound = BAS[ob->obclass].die;
+ if (ob->obclass == lowguardobj)
+ {
+ if (ob->shapeoffset)
+ sound ++;
+ }
+ SD_PlaySoundRTP(sound,ob->x,ob->y);
+ }
+ else
+ SD_PlaySoundRTP(BAS[ob->obclass].hit,ob->x,ob->y);
+
+#if (SHAREWARE == 0)
+ if ((ob->obclass == b_robobossobj) && (ob->temp2 <= 2))
+ {
+ if (ob->hitpoints <
+ ((3-ob->temp2)*starthitpoints[gamestate.difficulty][ob->obclass]>>2)
+ )
+ {
+ SD_PlaySoundRTP(SD_NMEAPARTSND,ob->x,ob->y);
+ ob->temp2++;
+ ob->shapeoffset += 16;
+ ob->speed += 0x500;
+ SpawnNewObj(ob->tilex,ob->tiley,&s_megaexplosions,inertobj);
+ new->temp1 = 3;
+ new->flags |= FL_ABP;
+ MakeActive(new);
+ }
+ if (ob->temp2 == 1)
+ NewState((objtype*)(ob->whatever),&s_NMEhead2);
+ }
+#endif
+ MISCVARS->madenoise = true;
+}
+
+
+
+void DamageStaticObject(statobj_t*tempstat,int damage)
+{
+
+
+ tempstat->hitpoints -= damage;
+ if (tempstat->hitpoints <= 0)
+ {
+ sprites[tempstat->tilex][tempstat->tiley]=NULL;
+ tempstat->flags |= FL_NONMARK;
+ if (tempstat->flags&FL_LIGHT)
+ {
+
+ if (MAPSPOT(tempstat->tilex,tempstat->tiley,2))
+ { touchplatetype *tplate;
+
+ for(tplate=touchplate[tempstat->linked_to]; tplate; tplate = tplate->nextaction)
+ if (tplate->whichobj == (long)(tempstat))
+ RemoveTouchplateAction(tplate,tempstat->linked_to);
+ }
+
+ if (tempstat->flags & FL_LIGHTON)
+ TurnOffLight(tempstat->tilex,tempstat->tiley);
+
+
+ if (tempstat->itemnumber<=stat_chandelier)
+ //SpawnFallingDebris(tempstat->x,tempstat->y,tempstat->z-32);
+ {
+ objtype *prevlast = LASTACTOR;
+
+ SpawnSlowParticles(gt_sparks,4,tempstat->x,tempstat->y,tempstat->z-32);
+ for(prevlast = prevlast->next; prevlast; prevlast= prevlast->next)
+ {
+ prevlast->momentumz = 1; // any positive value will do
+ prevlast->momentumx >>= 1;
+ prevlast->momentumy >>= 1;
+ }
+ }
+ else
+ {
+
+ SpawnStatic(tempstat->tilex,tempstat->tiley,stat_metalshards,-1);
+ LASTSTAT->flags |= (FL_ABP|FL_NONMARK);
+ sprites[tempstat->tilex][tempstat->tiley] = NULL;
+ MakeStatActive(LASTSTAT);
+ switch (tempstat->itemnumber)
+ {
+ case stat_lamp:
+ case stat_altbrazier1:
+ case stat_altbrazier2:
+ case stat_torch:
+ SpawnSlowParticles(gt_sparks,5,tempstat->x,tempstat->y,tempstat->z-32);
+ break;
+ case stat_floorfire:
+ SpawnSlowParticles(gt_sparks,5,tempstat->x,tempstat->y,tempstat->z);
+ break;
+ default:
+ ;
+ }
+ }
+ SpawnSolidStatic(tempstat);
+ SD_PlaySoundRTP(SD_ITEMBLOWSND,tempstat->x,tempstat->y);
+ }
+ else
+ {
+ switch (tempstat->itemnumber)
+ {
+ case stat_dariantouch:
+ MISCVARS->ETOUCH[tempstat->linked_to].x = MISCVARS->ETOUCH[tempstat->linked_to].y = 0;
+ case stat_tntcrate:
+ case stat_bonusbarrel:
+ SpawnNewObj(tempstat->tilex,tempstat->tiley,&s_staticexplosion1,inertobj);
+ MakeActive(new);
+ new->flags |= FL_ABP;
+ new->whatever = tempstat;
+ new->temp2 = damage;
+
+ if (tempstat->itemnumber == stat_bonusbarrel)
+ {
+ int rand = GameRandomNumber("DamageThing",0);
+
+ if (rand < 80)
+ {
+ if (rand & 1)
+ SpawnStatic(tempstat->tilex,tempstat->tiley,stat_monkmeal,-1);
+ else
+ SpawnStatic(tempstat->tilex,tempstat->tiley,stat_priestporridge,-1);
+ gamestate.healthtotal ++;
+ }
+ else if (rand < 160)
+ {
+ if (rand & 1)
+ SpawnStatic(tempstat->tilex,tempstat->tiley,stat_lifeitem1,-1);
+ else
+ SpawnStatic(tempstat->tilex,tempstat->tiley,stat_lifeitem3,-1);
+ }
+ else
+ {
+ if (rand & 1)
+ SpawnStatic(tempstat->tilex,tempstat->tiley,stat_mp40,-1);
+ else
+ {
+ SpawnStatic(tempstat->tilex,tempstat->tiley,stat_heatseeker,-1);
+ gamestate.missiletotal ++;
+ }
+ LASTSTAT->flags &= ~FL_RESPAWN;
+ }
+ //LASTSTAT->flags &= ~FL_SHOOTABLE;
+ LASTSTAT->flags |= FL_ABP;
+ MakeStatActive(LASTSTAT);
+ SD_PlaySoundRTP(SD_BONUSBARRELSND,tempstat->x,tempstat->y);
+ }
+ else
+ {
+ ExplodeStatic(tempstat);
+ if (tempstat == touchsprite)
+ touchsprite = NULL;
+ }
+ SpawnSolidStatic(tempstat);
+ //SD_Play(SD_EXPL);
+ break;
+#if (SHAREWARE == 0)
+ case stat_mine:
+ SpawnNewObj(tempstat->tilex,tempstat->tiley,&s_grexplosion1,inertobj);
+ MakeActive(new);
+ new->flags |= FL_ABP;
+ new->whatever = tempstat;
+ new->temp2 = damage;
+ RemoveStatic(tempstat);
+ break;
+
+ case stat_tomlarva:
+ SD_PlaySoundRTP(SD_ACTORSQUISHSND,tempstat->x,tempstat->y);
+ SpawnGroundExplosion(tempstat->x,tempstat->y,tempstat->z);
+ //MISCVARS->gibgravity = GRAVITY/2;
+ MISCVARS->fulllightgibs = true;
+ SetGibSpeed(0x4000);
+ SpawnSlowParticles(GUTS,30,tempstat->x, tempstat->y,tempstat->z);
+ ResetGibSpeed();
+ MISCVARS->fulllightgibs = false;
+ //MISCVARS->gibgravity = -1;
+ RemoveStatic(tempstat);
+ break;
+#endif
+
+ case stat_lifeitem1:
+ case stat_lifeitem2:
+ case stat_lifeitem3:
+ case stat_lifeitem4:
+ SD_PlaySoundRTP(SD_ITEMBLOWSND,tempstat->x,tempstat->y);
+ gamestate.treasurecount ++;
+ SpawnSlowParticles(gt_sparks,10,tempstat->x,tempstat->y,tempstat->z);
+ SpawnSolidStatic(tempstat);
+ break;
+
+ default:
+
+ if ((tempstat->itemnumber == stat_plant) ||
+ (tempstat->itemnumber == stat_tree))
+ gamestate.plantcount++;
+
+ //tempstat->shapenum = -1;
+ //tempstat->flags &= ~FL_SHOOTABLE;
+ ExplodeStatic(tempstat);
+ SpawnSolidStatic(tempstat);
+ break;
+ }
+ }
+ }
+}
+
+
+void DamageThing (void *thing, int damage)
+{
+ objtype* tempactor;
+ statobj_t* tempstat;
+
+
+ tempactor = (objtype*)thing;
+ if (!tempactor)
+ return;
+
+ if ((tempactor->which == ACTOR) && (!(tempactor->flags & FL_SHOOTABLE)))
+ return;
+
+ if ((tempactor->which == ACTOR) || (tempactor->which == SPRITE))
+ {
+ if (tempactor->which == ACTOR)
+ {
+ if (tempactor->obclass == playerobj)
+ {
+ if ((tempactor->flags & FL_GODMODE) ||
+ (tempactor->flags & FL_DOGMODE) ||
+ godmode ||
+ (gamestate.battlemode == battle_Eluder)
+ )
+ return;
+ DamagePlayerActor(tempactor,damage);
+ }
+
+ else
+ {
+ if ((tempactor->obclass == collectorobj) && (gamestate.SpawnEluder))
+ return;
+ if (tempactor->hitpoints <= 0)
+ return;
+ DamageNonPlayerActor(tempactor,damage);
+ }
+ }
+ else
+ {
+ tempstat = (statobj_t*)thing;
+
+ MISCVARS->madenoise = true;
+ if (!(tempstat->flags & FL_SHOOTABLE))
+ return;
+ DamageStaticObject(tempstat,damage);
+ }
+ }
+}
+
+
+void ExplodeStatic(statobj_t*tempstat)
+{
+//SpawnSolidStatic(tempstat);
+
+ if (tempstat->flags & FL_WOODEN)
+ {
+ SpawnStatic(tempstat->tilex,tempstat->tiley,stat_woodfrag,-1);
+ if ((gamestate.BattleOptions.RespawnItems) &&
+ (tempstat->itemnumber == stat_tntcrate)
+ )
+ {
+ tempstat->linked_to = (long)(LASTSTAT);
+ tempstat->flags |= FL_RESPAWN;
+ }
+
+ }
+ else if (tempstat->flags & FL_METALLIC)
+ SpawnStatic(tempstat->tilex,tempstat->tiley,stat_metalfrag,-1);
+ else
+ SpawnStatic(tempstat->tilex,tempstat->tiley,stat_rubble,-1);
+ LASTSTAT->flags |= (FL_ABP|FL_NONMARK);
+ sprites[tempstat->tilex][tempstat->tiley] = NULL;
+ MakeStatActive(LASTSTAT);
+ SD_PlaySoundRTP(SD_ITEMBLOWSND,tempstat->x,tempstat->y);
+
+
+}
+
+
+
+
+
+void EnableObject(long object)
+{
+ objtype* ob;
+ int i,gasicon;
+ doorobj_t*tdoor;
+
+ ob = (objtype*)object;
+
+#if (BNACRASHPREVENT == 1)//
+ if (ob == 0) {
+ return;
+ }
+#endif
+
+ ob->flags |= FL_ACTIVE;
+ if (ob->obclass == bladeobj)
+ {
+ ParseMomentum(ob,dirangle8[ob->dir]);
+ if (ob->whatever)
+ {
+ objtype *passenger=(objtype*)(ob->whatever);
+
+ passenger->momentumx += ob->momentumx;
+ passenger->momentumy += ob->momentumy;
+ }
+ }
+
+ if (ob->obclass == gasgrateobj)
+ {
+ NewState(ob,&s_gas2);
+ SD_PlaySoundRTP(SD_GASSTARTSND,ob->x,ob->y);
+ ob->dirchoosetime = GASTICS;
+ for(i=0; i<doornum; i++)
+ {
+
+ tdoor = doorobjlist[i];
+ gasicon = MAPSPOT(tdoor->tilex,tdoor->tiley,1);
+ if (gasicon == GASVALUE)
+ LinkedCloseDoor(i);
+ }
+
+ MU_StoreSongPosition();
+ MU_StartSong(song_gason);
+ MISCVARS->GASON = 1;
+ ob->temp3 = 105;
+ }
+ else if (ob->obclass == pillarobj)
+ {
+ ob->flags |= FL_FLIPPED;
+ gamestate.secretcount++;
+ }
+ if (!(ob->flags & FL_ABP))
+ {
+ ob->flags |= FL_ABP;
+ MakeActive(ob);
+ }
+}
+
+void DisableObject(long object)
+{ objtype*ob;
+
+ ob = (objtype*)object;
+ ob->flags &= ~FL_ACTIVE;
+}
+
+
+void T_MoveColumn(objtype* ob)
+{ int spot,index;
+
+
+ if (!(ob->flags & FL_ACTIVE))
+ return;
+ /*
+ switch (ob->dir)
+ {case north:
+ ob->momentumy = -PILLARMOM;
+ break;
+ case south:
+ ob->momentumy = PILLARMOM;
+ break;
+ case east:
+ ob->momentumx = PILLARMOM;
+ break;
+ case west:
+ ob->momentumx = -PILLARMOM;
+ break;
+ }
+
+ */
+ ActorMovement(ob);
+ index = touchindices[ob->tilex][ob->tiley];
+ if (index)
+ TRIGGER[index-1] = 1;
+ ob->temp1 -= PILLARMOM;
+
+ if ((ob->temp1 <= 0) || NOMOM)
+ { ZEROMOM;
+ ob->temp1 = 0x20000;
+ ob->flags &= ~FL_ACTIVE;
+ spot = MAPSPOT(ob->tilex,ob->tiley,1)-ICONARROWS;
+ if ((spot >= 0) && (spot <= 7))
+ { ob->dir = spot;
+ if (!ob->temp2)
+ {
+ gamestate.secrettotal++;
+ }
+ else
+ {
+ ob->flags |= FL_ACTIVE;
+ }
+ ParseMomentum(ob,dirangle8[ob->dir]);
+ }
+ else
+ ob->flags |= FL_DONE;
+
+ }
+}
+
+
+
+boolean NextToDoor(objtype*ob)
+{
+ int tilex,tiley,centerx,centery,dx,dy;
+
+ tilex = ob->tilex;
+ tiley = ob->tiley;
+
+
+ if (M_ISDOOR(tilex+1,tiley) || M_ISDOOR(tilex-1,tiley))
+ { centery = (tiley << TILESHIFT) + HALFGLOBAL1;
+ dy = abs(ob->y - centery);
+ if (dy < 0x2000)
+ return true;
+ }
+
+ if (M_ISDOOR(tilex,tiley+1) || M_ISDOOR(tilex,tiley-1))
+ { centerx = (tilex << TILESHIFT) + HALFGLOBAL1;
+ dx = abs(ob->x - centerx);
+ if (dx < 0x2000)
+ return true;
+ }
+
+ return false;
+}
+
+
+/*
+=================
+=
+= T_Use
+=
+=================
+*/
+
+
+void T_Use(objtype*ob)
+{ if (ob->ticcount)
+ return;
+
+ switch (ob->obclass)
+ {
+#if (SHAREWARE == 0)
+ case b_darianobj:
+ if (touchsprite && !DoPanicMapping())
+ touchsprite->flags |= FL_ACTIVE;
+ if ((!sprites[PLAYER[0]->tilex][PLAYER[0]->tiley]) && (ob->areanumber == PLAYER[0]->areanumber))
+ { SpawnNewObj(PLAYER[0]->tilex,PLAYER[0]->tiley,&s_dspear1,spearobj);
+ new->flags |= (FL_ABP);//|FL_INVULNERABLE);
+ new->z = 0;
+ MakeActive(new);
+ }
+ ZEROMOM;
+ ob->flags |= FL_STUCK;
+ SD_PlaySoundRTP(SD_DARIANUSESND,ob->x,ob->y);
+ //NewState(ob,&s_darianspears);
+ break;
+#endif
+ default:
+ ;
+ }
+
+
+}
+
+
+
+
+
+#define RollStart(ob,state,angle) \
+ { \
+ int oldspeed = ob->speed; \
+ \
+ ob->speed = ROLLMOMENTUM+0x200; \
+ NewState(ob,state); \
+ ParseMomentum(ob,angle); \
+ ob->speed = oldspeed; \
+ } \
+
+
+
+
+
+void AvoidPlayerMissile(objtype*ob)
+{
+ objtype *temp;
+ int dx,dy,dz;
+ int magangle,angle1,rollangle1,rollangle2,dangle1,dangle2;
+
+ if (PLAYER0MISSILE == NULL)
+ return;
+
+ if (GameRandomNumber("scott missile avoid",0) > 160)
+ return;
+
+ if (ob->momentumz)
+ return;
+
+ if ((ob->state->think == T_Roll) || (ob->state->think == T_Reset))
+ return;
+
+ temp = PLAYER0MISSILE;
+
+ dx = abs(temp->x - ob->x);
+ dy = abs(ob->y - temp->y);
+ dz = abs(ob->z - temp->z);
+ angle1 = AngleBetween(temp,ob);
+ magangle = abs(temp->angle - angle1);
+
+ if (magangle > VANG180)
+ magangle = ANGLES - magangle;
+
+
+ if ((magangle > ANGLES/48) || (dx > 0x50000) || (dy > 0x50000) ||
+ (dz > 32))
+ return;
+
+ rollangle1 = angle1 + ANGLES/4;
+ Fix(rollangle1);
+ dangle1 = abs(temp->angle - rollangle1);
+ if (dangle1 > VANG180)
+ dangle1 = ANGLES - dangle1;
+
+ rollangle2 = angle1 - ANGLES/4;
+ Fix(rollangle2);
+ dangle2 = abs(temp->angle - rollangle2);
+ if (dangle2 > VANG180)
+ dangle2 = ANGLES - dangle2;
+
+ ob->momentumx = ob->momentumy = 0;
+
+ if (dangle1 > dangle2)
+ {
+ RollStart(ob,&s_strikerollleft1,rollangle1);
+ }
+ else
+ {
+ RollStart(ob,&s_strikerollright1,rollangle2);
+ }
+ ob->flags |= FL_NOFRICTION;
+
+ ob->target = PLAYER[0];
+ //SelectRollDir(ob);
+
+
+}
+
+
+
+
+/*
+=================
+=
+= T_Chase
+=
+=================
+*/
+
+void T_Chase (objtype *ob)
+{
+ int dx,dy,dz,dist,chance;
+ classtype ocl;
+ statetype *temp;
+ boolean doorok;
+
+ ocl = ob->obclass;
+
+
+ if ((ocl == deathmonkobj) || (ocl == blitzguardobj))
+ { dx = abs(PLAYER[0]->x - ob->x);
+ dy = abs(ob->y - PLAYER[0]->y);
+ dz = abs(ob->z - PLAYER[0]->z);
+
+ if ((dx < TOUCHDIST) && (dy < TOUCHDIST) && (dz < (TOUCHDIST >> 10)))
+ {
+#if (SHAREWARE == 0)
+ if (ocl == deathmonkobj)
+ { NewState(ob,&s_dmonkshoot1);
+ STOPACTOR(ob);
+ return;
+
+ }
+ else
+#endif
+ if ((!ob->temp3) && (PLAYERSTATE[0].missileweapon != -1) &&
+ (PLAYERSTATE[0].missileweapon < wp_godhand))
+ { NewState(ob,&s_blitzsteal1);
+ STOPACTOR(ob);
+ return;
+ }
+ }
+ }
+
+ ob->flags &= ~FL_DODGE;
+
+ //if (CheckLine(ob,PLAYER[0],DIRCHECK) && (ocl != roboguardobj))
+
+ if (!ob->ticcount)
+ { if (CheckLine(ob,PLAYER[0],SIGHT)) // got a shot at player?
+ { if (ocl != roboguardobj)
+ { ob->targettilex = PLAYER[0]->x;
+ ob->targettiley = PLAYER[0]->y;
+ }
+ }
+
+ if (CheckLine(ob,PLAYER[0],SHOOT) && (!(player->flags&FL_DYING))) // got a shot at player?
+ {
+ dx = abs(ob->tilex - PLAYER[0]->tilex);
+ dy = abs(ob->tiley - PLAYER[0]->tiley);
+ dist = (dx>dy)?(dx):(dy);
+ if ((!dist) || (dist==1))
+ chance = 300;
+ else if (ocl >= b_darianobj)
+ chance = 400/dist;
+ else
+ chance = 300/dist;
+
+ if (GameRandomNumber("T_Chase",ocl) <chance)
+ { if ((ocl == b_heinrichobj) && (Near(ob,PLAYER[0],4)))
+ goto cdoor;
+
+ ob->dir = angletodir[AngleBetween(ob,PLAYER[0])];
+ STOPACTOR(ob);
+#if (SHAREWARE == 0)
+ if ((ocl == overpatrolobj) && (!Near(ob,PLAYER[0],3)) &&
+ (!PLAYERSTATE[0].NETCAPTURED) && (!MISCVARS->NET_IN_FLIGHT))
+ { NewState(ob,&s_opbolo1);
+ MISCVARS->NET_IN_FLIGHT = true;
+ return;
+ }
+#endif
+ if ((ocl == triadenforcerobj) && (!Near(ob,PLAYER[0],3)))
+ { NewState(ob,&s_enforcerthrow1);
+ return;
+ }
+
+ if ((temp=M_S(AIM)) != NULL)
+ { if ((ob->flags & FL_HASAUTO) && (!ob->temp3))
+ ob->temp3 = (GameRandomNumber("T_Chase FL_HASAUTO",ocl) % 5) + 3;
+ ob->target = PLAYER[0];
+ NewState(ob,temp);
+ return;
+ }
+
+ }
+ //if ((CheckSight(ob,PLAYER[0])) && (!ob->angle))// &&
+ //(ocl != b_heinrichobj))
+ //ob->flags |= FL_DODGE;
+ }
+
+ }
+cdoor:
+ doorok = NextToDoor(ob);
+
+
+ if (ob->dirchoosetime)
+ ob->dirchoosetime--;
+
+ if ((ob->flags & FL_STUCK) || (!ob->dirchoosetime) || doorok)
+ { //if (ob->flags & FL_DODGE)
+ // SelectDodgeDir(ob);
+ //else
+ SelectChaseDir(ob);
+ ob->dirchoosetime = M_CHOOSETIME(ob);
+ }
+
+ else
+ { if (NOMOM)
+ ParseMomentum(ob,dirangle8[ob->dir]);
+ ActorMovement(ob);
+ }
+}
+
+
+
+void SpawnMissile(objtype* shooter,classtype nobclass,int nspeed,int nangle,statetype*nstate,int offset)
+{
+ GetNewActor();
+ MakeActive(new);
+ new->which = ACTOR;
+ new->obclass = nobclass;
+ new->angle = nangle;
+ new->speed = nspeed;
+ if (shooter->obclass == playerobj)
+ offset += FindDistance(shooter->momentumx,shooter->momentumy);
+
+ SetFinePosition(new,shooter->x + FixedMul(offset,costable[nangle]),
+ shooter->y - FixedMul(offset,sintable[nangle]));
+ SetVisiblePosition(new,new->x,new->y);
+ //SoftError("\n missx:%d, missy:%d, speed:%d, offset:%d, angle%d, drawx:%d, drawy:%d",
+ // new->x,new->y,nspeed,offset,nangle,new->drawx,new->drawy);
+
+ new->z = shooter->z;
+ new->areanumber = shooter->areanumber;
+ new->soundhandle = -1;
+ if (nobclass != inertobj)
+ {
+ MakeLastInArea(new);
+ if (MissileSound == true)
+ new->soundhandle = SD_PlaySoundRTP(BAS[new->obclass].operate,new->x,new->y);
+ }
+
+ if ((shooter->obclass == playerobj) || (shooter->obclass == wallopobj) ||
+ (shooter->obclass == b_robobossobj))
+ {
+ Set_3D_Momenta(new,new->speed,new->angle,shooter->yzangle);
+
+ if (nobclass == p_drunkmissileobj)
+ new->temp1 = new->momentumz;
+
+ new->z -= FixedMulShift(offset,sintable[shooter->yzangle],26);
+ if ((shooter->obclass == playerobj) && (shooter->flags & FL_GODMODE))
+ new->z -= 10;
+ }
+ else
+ ParseMomentum(new,new->angle);
+
+ if (nobclass == p_drunkmissileobj)
+ new->temp3 = VBLCOUNTER/3;
+
+
+ new->flags |= (FL_NEVERMARK|FL_ABP|FL_NOFRICTION|FL_FULLLIGHT);
+ new->whatever = shooter; // keep track of missile possession
+ NewState(new,nstate);
+}
+
+
+
+/*
+=================
+=
+= T_Roll
+=
+=================
+*/
+
+
+void T_Roll (objtype *ob)
+{
+ ActorMovement(ob);
+
+}
+
+
+
+
+/*
+===============
+=
+= T_Path
+=
+===============
+*/
+
+void T_Path (objtype *ob)
+{ int dx,dy,dz,ocl,damage=1;
+ objtype*temp,*ttarg,*twhat;
+
+
+ ocl = ob->obclass;
+
+ if (((ocl == firejetobj) || (ocl == bladeobj)) && (!ob->ticcount))
+ {
+ if (ocl == bladeobj)
+ {
+ if (ob->state->condition & SF_DOWN )
+ ob->flags &= ~FL_BLOCK;
+ else if (ob->state->condition & SF_UP)
+ {
+ ob->flags |= FL_BLOCK;
+ damage = 0;
+ }
+ }
+
+ if ((ob->state->condition & SF_SOUND) && areabyplayer[ob->areanumber])
+ SD_PlaySoundRTP(BAS[ob->obclass].operate,ob->x,ob->y);
+
+ if (damage)
+ {
+ for(temp=firstareaactor[ob->areanumber]; temp; temp=temp->nextinarea)
+ {
+ if (temp == ob)
+ continue;
+
+ if (temp->obclass >= roboguardobj)
+ continue;
+
+ //WAS
+ ttarg = (objtype*)(temp->target);
+ twhat = (objtype*)(temp->whatever);
+
+ if ((M_ISACTOR(ttarg) && (ttarg->obclass == b_robobossobj)) ||
+ (M_ISACTOR(twhat) && (twhat->obclass == b_robobossobj))
+ )
+ continue;
+
+ if ((!(temp->flags & FL_SHOOTABLE)) || (temp->flags & FL_DYING))
+ continue;
+
+ if (temp->obclass == playerobj)
+ {
+ if ((temp->flags & FL_GODMODE) || (temp->flags & FL_DOGMODE))
+ continue;
+ if ((temp->flags & FL_AV) && (ocl == firejetobj))
+ continue;
+ }
+ dx = temp->x - ob->x;
+ if (abs(dx) > 0xa000)
+ continue;
+ dy = temp->y - ob->y;
+ if (abs(dy) > 0xa000)
+ continue;
+
+ //if (temp->obclass == playerobj)
+ //Collision(temp,-temp->momentumx+ob->momentumx,-temp->momentumy + ob->momentumy);
+ dz = temp->z - ob->z;
+ if (abs(dz) > 32)
+ continue;
+
+ DamageThing(temp,EnvironmentDamage(ob));
+ if ((ocl == firejetobj) && (temp->obclass < roboguardobj))
+ SD_PlaySoundRTP(SD_PLAYERBURNEDSND,temp->x,temp->y);
+
+ if ((gamestate.violence == vl_excessive) && (temp->obclass < roboguardobj))
+ {
+ if (ocl == bladeobj)
+ {
+ SpawnParticles(temp,GUTS,1);
+ if (temp->hitpoints <= 0)
+ temp->flags |= FL_HBM;
+ }
+ else if (ocl == firejetobj)
+ {
+ if ((temp->hitpoints <= 0) && (temp->z == nominalheight))
+ {
+
+ temp->hitpoints = 0;
+ temp->flags |= FL_SKELETON;
+ if (temp->obclass == playerobj)
+ {
+ playertype *pstate;
+
+ temp->flags &= ~FL_COLORED;
+ M_LINKSTATE(temp,pstate);
+ pstate->health = 0;
+ pstate->weapon = -1;
+ }
+
+ Collision(temp,ob,-temp->momentumx,-temp->momentumy);
+ M_CheckPlayerKilled(temp);
+
+ continue;
+ }
+ }
+ }
+ //SD_PlaySoundRTP(SD_ACTORBURNEDSND,temp->x,temp->y);
+
+ // if ((ocl == bladeobj) || (ob->state->condition == SF_CRUSH))
+ Collision(temp,ob,-temp->momentumx,-temp->momentumy);
+ M_CheckPlayerKilled(temp);
+
+ }
+ }
+ }
+
+
+ if (ob->dir == nodir)
+ return;
+
+ if ((ocl != firejetobj) && (ocl != bladeobj) && (ocl != diskobj))
+ {
+ if (!ob->ticcount)
+ {
+ if (SightPlayer (ob))
+ return;
+ }
+ else
+ SoftError("\n ob type %s with ticcount %d in T_Path",
+ debugstr[ob->obclass],ob->ticcount);
+ }
+
+ SelectPathDir (ob);
+ if (NOMOM)
+ ParseMomentum(ob,dirangle8[ob->dir]);
+}
+
+
+
+int EnvironmentDamage(objtype *ob)
+{
+ if (BATTLEMODE && (gamestate.BattleOptions.DangerDamage != bo_danger_normal))
+ {
+ return(gamestate.BattleOptions.DangerDamage);
+ }
+ else
+ {
+ int damage = 1;
+
+ switch(ob->obclass)
+ {
+ case firejetobj:
+ case bladeobj:
+ damage = 6;
+ break;
+
+ case boulderobj:
+ damage = 50;
+ break;
+
+ case spearobj:
+ damage = 7;
+ break;
+
+ case gasgrateobj:
+ damage = 20;
+ break;
+
+ case wallfireobj:
+ damage = ((GameRandomNumber("wallfire damage",0) >>3) + 10);
+ break;
+
+ case crushcolobj:
+ damage = 10;
+ break;
+ default:
+ ;
+ }
+
+ if (gamestate.difficulty < gd_hard)
+ damage >>= 1;
+
+ return damage;
+ }
+ //SoftError("unknown environment danger");
+
+}
+
+
+
+
+void T_AutoShootAlign(objtype*ob)
+{
+ if (ob->dir != (dirtype)ob->temp1)
+ ob->dir = dirorder16[ob->dir][NEXT];
+ else
+ NewState(ob,M_S(AIM));
+
+}
+
+
+void T_AutoRealign(objtype*ob)
+{
+ if (ob->dir != (dirtype)ob->targettilex)
+ ob->dir = dirorder16[ob->dir][NEXT];
+ else
+ { objtype *temp;
+
+ NewState(ob,M_S(PATH));
+ for(temp=firstareaactor[ob->areanumber]; temp; temp=temp->nextinarea)
+ { if (temp == ob)
+ continue;
+ if (temp->obclass != ob->obclass)
+ continue;
+ if (!temp->state->think)
+ NewState(temp,UPDATE_STATES[PATH][temp->obclass-lowguardobj]);
+ }
+ }
+}
+
+
+/*
+===============
+=
+= T_AutoPath
+=
+===============
+*/
+
+void T_AutoPath (objtype *ob)
+{ objtype *temp;
+
+ // ob->temp3 holds random number of shots before resuming path
+
+ if (CheckLine(ob,PLAYER[0],SIGHT) && (Near(ob,PLAYER[0],4) || MISCVARS->madenoise))
+
+ { int dx,dy,destdir,ocl;
+ statetype *align,*wait;
+
+ ocl = ob->obclass;
+ dx = player->x - ob->x;
+ dy = ob->y - player->y;
+ destdir = (angletodir[atan2_appx(dx,dy)] << 1);
+ ob->temp1 = destdir;
+ ob->targettilex = ob->dir; //save old dir
+#if (SHAREWARE == 0)
+ if (ocl == wallopobj)
+ { //if (ob->temp3)
+ // Error("may be writing over temp3");
+ ob->temp3 = (GameRandomNumber("T_WallPath",0)%4) + 1;
+ align = &s_wallalign;
+ wait = &s_wallwait;
+ }
+ else
+#endif
+ { align = &s_roboalign;
+ wait = &s_robowait;
+ }
+
+ NewState(ob,align);
+ for(temp=firstareaactor[ob->areanumber]; temp; temp=temp->nextinarea)
+ { if (temp == ob)
+ continue;
+
+ if (temp->obclass != ob->obclass)
+ continue;
+
+ if (temp->flags & FL_DYING)
+ continue;
+
+ if (CheckLine(temp,PLAYER[0],SIGHT) && (Near(temp,PLAYER[0],4) || MISCVARS->madenoise))
+ { dx = PLAYER[0]->x - temp->x;
+ dy = temp->y - PLAYER[0]->y;
+ destdir = (angletodir[atan2_appx(dx,dy)] << 1);
+
+ temp->temp1 = destdir;
+ temp->targettilex = temp->dir;
+ NewState(temp,align);
+ temp->temp3 = ob->temp3;
+ }
+ else
+ NewState(temp,wait);
+ }
+ return;
+ }
+
+ SD_PlaySoundRTP(SD_ROBOTMOVESND,ob->x,ob->y);
+
+ SelectPathDir(ob);
+
+}
+
+
+
+
+/*
+===============
+=
+= A_Shoot
+=
+= Try to damage the player, based on skill level and player's speed
+=
+===============
+*/
+
+void A_Shoot (objtype *ob)
+{
+ int dx,dy,dz,dist;
+ int accuracy,damage,sound;
+ objtype * target;
+ int num;
+ int savedangle;
+
+ ActorMovement(ob);
+
+ ob->flags |= FL_FULLLIGHT;
+//if (!(ob->flags & FL_SHOOTABLE))
+ //Error("\na dead instance of %s is shooting at you",debugstr[ob->obclass]);
+
+ if (!ob->ticcount)
+ { if (ob->obclass == strikeguardobj)
+ ob->flags &= ~FL_NOFRICTION;
+
+ target = (objtype*)(ob->target);
+ if (!target)
+ Error("an instance of %s called shoot without a target\n",debugstr[ob->obclass]);
+
+
+ ob->flags &= ~FL_FULLLIGHT;
+
+
+ dx = (target->x - ob->x);
+ dy = (ob->y - target->y);
+ dz = target->z-ob->z;
+
+
+ if ((ob->obclass == blitzguardobj) && (ob->temp3) &&
+ (ob->temp3 != stat_gasmask) && (ob->temp3 != stat_asbesto) &&
+ (ob->temp3 != stat_bulletproof) &&
+ (gamestate.difficulty >= gd_medium) &&
+ ((abs(dx) > 0xc000) || (abs(dy) > 0xc000))
+ )
+ {
+ int i;
+ missile_stats* newmissiledata;
+
+ newmissiledata = &PlayerMissileData[GetWeaponForItem(ob->temp3)];
+
+ // ready to annihilate this poor bastard
+
+ SpawnMissile(ob,newmissiledata->obclass,newmissiledata->speed,
+ AngleBetween(ob,player), newmissiledata->state,
+ newmissiledata->offset);
+
+ if (newmissiledata->obclass == p_drunkmissileobj)
+ {
+ for(i=0; i<4; i++)
+ {
+ SpawnMissile(ob,newmissiledata->obclass,newmissiledata->speed,
+ AngleBetween(ob,player), newmissiledata->state,
+ newmissiledata->offset);
+ }
+ }
+ ob->target = NULL;
+ ob->temp2 --;
+ if (ob->temp2 == 0)
+ ob->temp3 = 0;
+ return;
+ }
+
+
+ if ((!areabyplayer[ob->areanumber]) && (target->obclass == playerobj))
+ return;
+
+ //if (!CheckLine(ob,target,SHOOT)) // player is behind a wall
+ //return;
+
+
+ savedangle=ob->angle;
+ ob->angle = atan2_appx (dx,dy);
+ dist = FindDistance(dx,dy);
+ ob->yzangle = FINEANGLES-atan2_appx(dist, dz<<10);
+
+ if ((ob->yzangle>MAXYZANGLE) && (ob->yzangle<FINEANGLES-MAXYZANGLE))
+ ob->yzangle=MAXYZANGLE;
+
+ dist>>=16;
+
+ accuracy=(WHICHACTOR<<4)+((gamestate.difficulty) << 6);
+
+ num = GameRandomNumber("A_Shoot3",ob->obclass);
+
+ if (num<128) num=128; // Don't let accuracy fall below 50% original
+
+ accuracy=FixedMulShift(num,accuracy,8); // scale accuracy based off randomness
+
+ // check for maximum accuracy;
+
+ if (accuracy>255) accuracy=255;
+
+ if (ob->obclass==highguardobj)
+ damage=DMG_MP40;
+ else if (ob->obclass == triadenforcerobj)
+ damage=DMG_MP40;
+ else
+ damage=DMG_ENEMYBULLETWEAPON;
+
+
+ RayShoot (ob, damage, 255-accuracy);
+
+ ob->angle=savedangle;
+ sound = BAS[ob->obclass].fire;
+ SD_PlaySoundRTP(sound,ob->x,ob->y);
+ MISCVARS->madenoise = true;
+ if ((!(ob->flags& FL_HASAUTO)) || (!ob->temp3))
+ ob->target = NULL;
+ }
+}
+
+
+
+
+void A_Repeat(objtype*ob)
+{
+ ActorMovement(ob);
+
+ if (!ob->ticcount)
+ { ob->temp3 --;
+ if (ob->temp3 <= 0)
+ NewState(ob,M_S(CHASE));
+ }
+
+}
+
+
+void A_MissileWeapon(objtype *ob)
+{
+ int sound,nspeed,noffset,zoffset;
+
+#if (SHAREWARE == 0)
+ int oldyzangle;
+#endif
+ classtype nobclass;
+ statetype*nstate;
+
+
+ if ((ob->obclass == wallopobj) || (ob->obclass == roboguardobj));
+ //SelectPathDir(ob);
+ else
+ ActorMovement(ob);
+
+ if (!ob->ticcount)
+ {
+#if (SHAREWARE == 0)
+ if ((ob->obclass == wallopobj) && (!ob->temp3))
+ {
+ NewState(ob,&s_wallrestore);
+ return;
+ }
+#endif
+ if ((ob->obclass == b_darianobj) && (!CheckLine(ob,PLAYER[0],SHOOT)))
+ { NewState(ob,M_S(CHASE));
+ return;
+ }
+// Move sounds, flags into switch cases
+
+ sound = BAS[ob->obclass].fire;
+ nspeed = 0x4000;
+ noffset = 0x8000;
+ zoffset = 0;
+ switch (ob->obclass)
+ {
+
+ case triadenforcerobj:
+ nobclass = grenadeobj;
+ nstate= &s_grenade1;
+ sound++;
+ break;
+
+
+ case roboguardobj:
+ nobclass = shurikenobj;
+ nspeed = 0x2000;
+ noffset = 0x10000;
+ nstate = &s_robogrdshuriken1;
+ break;
+
+ /*
+ case b_darkmonkobj:
+ nobclass = dmfballobj;
+ nstate = &s_dmfball1;
+ break;
+ */
+ /*
+ case b_robobossobj:
+ nobclass = bigshurikenobj;
+ nstate = &s_oshuriken1;
+ break;
+ */
+#if (SHAREWARE == 0)
+ case b_darianobj:
+ nobclass = missileobj;
+ //nspeed = 0x100;
+ //noffset = 0x18000;
+ nstate = &s_missile1;
+ zoffset = -20;
+ break;
+
+
+ case dfiremonkobj:
+ nobclass = fireballobj;
+ nstate = &s_monkfire1;
+ break;
+
+
+ case overpatrolobj:
+ nobclass = netobj;
+ nstate = &s_bolocast1;
+ sound ++;
+ break;
+
+
+ case wallopobj:
+ { int dx,dy,dz,xydist;
+
+ ob->temp2 ^= 1; // increment numfired
+ ob->temp3 --; // decrement random fire no.
+
+
+ dx = PLAYER[0]->x-ob->x;
+ dy = ob->y-PLAYER[0]->y;
+ if (GameRandomNumber("bcraft shoot up/down",0) < 128)
+ dz = 10;
+ else
+ dz = -10;
+ xydist = FindDistance(dx,dy);
+ oldyzangle = ob->yzangle;
+ ob->yzangle = atan2_appx(xydist,dz<<10);
+ if (ob->temp2)
+ { nobclass = missileobj;
+ nstate = &s_missile1;
+ }
+ else
+ { nobclass = bigshurikenobj;
+ nstate = &s_bstar1;
+ }
+ }
+ break;
+#endif
+ default:
+ ;
+ }
+
+ SpawnMissile(ob,nobclass,nspeed,AngleBetween(ob,PLAYER[0]),nstate,noffset);
+ new->z += zoffset;
+ SD_PlaySoundRTP(sound,ob->x,ob->y);
+ MISCVARS->madenoise = true;
+ if (ob->obclass == triadenforcerobj)
+ { //new->flags |= (FL_SHOOTABLE);
+ new->temp1 = 0x50000;
+ }
+#if (SHAREWARE == 0)
+ else if (ob->obclass == wallopobj)
+ ob->yzangle = oldyzangle;
+#endif
+
+
+ }
+}
+
+
+void A_Wallfire(objtype *ob)
+{
+ if (!(ob->flags & FL_ACTIVE))
+ return;
+
+ if (!ob->ticcount)
+ { SpawnMissile(ob,wallfireobj,0x4000,ob->angle,&s_crossfire1,0xa000);
+ if (areabyplayer[ob->areanumber])
+ SD_PlaySoundRTP(SD_FIRECHUTESND,ob->x,ob->y);
+ new->dir = angletodir[new->angle];
+ new->z = nominalheight;
+ }
+
+}
+
+
+void T_Reset(objtype *ob)
+{
+ ActorMovement(ob);
+
+ if (ob->ticcount)
+ return;
+
+ ob->momentumx = ob->momentumy = ob->dirchoosetime = 0;
+ ob->flags &= ~FL_NOFRICTION;
+
+
+
+}
+
+void SelectRollDir(objtype *ob)
+{ int angle,tryx,tryy;
+
+
+ if (ob->state == &s_strikerollright1)
+ angle = AngleBetween(ob,PLAYER[0]) + ANGLES/4;
+ else
+ angle = AngleBetween(ob,PLAYER[0]) - ANGLES/4;
+
+ Fix(angle);
+ tryx = ob->x + FixedMul(0x20000l,costable[angle]);
+ tryy = ob->y - FixedMul(0x20000l,sintable[angle]);
+ ZEROMOM;
+ if (QuickSpaceCheck(ob,tryx,tryy))
+ { int oldspeed;
+
+ oldspeed = ob->speed;
+ ob->speed = ROLLMOMENTUM;
+ ParseMomentum(ob,angle);
+ ob->speed = oldspeed;
+ ob->dirchoosetime = 5;
+ ob->flags |= FL_NOFRICTION;
+ }
+ else
+ ob->dirchoosetime = 0;
+
+
+}
+
+
+void SelectDodgeDir (objtype *ob)
+{
+ int dx,dy,i,tx,ty;
+ unsigned absdx,absdy;
+ dirtype dirtry[5];
+ dirtype turnaround,tdir,olddir;
+
+
+ olddir = ob->dir;
+ if (ob->flags & FL_FIRSTATTACK)
+ {
+ //
+ // turning around is only ok the very first time after noticing the
+ // player
+ //
+ turnaround = nodir;
+ ob->flags &= ~FL_FIRSTATTACK;
+ }
+ else
+ turnaround=opposite[ob->dir];
+
+
+ if (ob->targettilex || ob->targettiley)
+ { tx = ob->targettilex;
+ ty = ob->targettiley;
+ dx= tx - ob->x;
+ dy= ty - ob->y;
+ if ( ((dx < MINACTORDIST) && (dx > -MINACTORDIST)) &&
+ ((dy < MINACTORDIST) && (dy > -MINACTORDIST)))
+ { dx= PLAYER[0]->x-ob->x;
+ dy= PLAYER[0]->y-ob->y;
+ }
+ }
+ else
+ { dx= PLAYER[0]->x-ob->x;
+ dy= PLAYER[0]->y-ob->y;
+ }
+
+
+
+//
+// arange 5 direction choices in order of preference
+// the four cardinal directions plus the diagonal straight towards
+// the player
+//
+ if (dx>ACTORSIZE)
+ {
+ dirtry[1]= east;
+ dirtry[3]= west;
+ }
+ else if (dx < -ACTORSIZE)
+ {
+ dirtry[1]= west;
+ dirtry[3]= east;
+ }
+
+ if (dy>ACTORSIZE)
+ {
+ dirtry[2]= south; // south
+ dirtry[4]= north; // north
+ }
+ else if (dy <-ACTORSIZE)
+ {
+ dirtry[2]= north; // north
+ dirtry[4]= south; // south
+ }
+
+//
+// randomize a bit for dodging
+//
+ absdx = abs(dx);
+ absdy = abs(dy);
+
+ if (absdx > absdy)
+ {
+ tdir = dirtry[1];
+ dirtry[1] = dirtry[2];
+ dirtry[2] = tdir;
+ tdir = dirtry[3];
+ dirtry[3] = dirtry[4];
+ dirtry[4] = tdir;
+ }
+
+ if (GameRandomNumber("SelectDogeDir",ob->obclass) < 128)
+ {
+ tdir = dirtry[1];
+ dirtry[1] = dirtry[2];
+ dirtry[2] = tdir;
+ tdir = dirtry[3];
+ dirtry[3] = dirtry[4];
+ dirtry[4] = tdir;
+ }
+
+ dirtry[0] = diagonal [dirtry[1]] [dirtry[2]];
+
+ ZEROMOM;
+
+ for (i=0; i<5; i++)
+ { if ((dirtry[i] == nodir) || (dirdiff[dirtry[i]][olddir] > 1))
+ continue;
+
+ M_CHECKDIR(ob,dirtry[i]);
+ }
+
+//
+// turn around only as a last resort
+//
+// for(tdir = east;tdir<=southeast;tdir++)
+ //if (tdir != turnaround)
+// M_CHECKDIR(ob,tdir);
+
+ if (turnaround != nodir)
+ M_CHECKDIR(ob,turnaround);
+
+}
+
+
+
+
+#define TryAbruptProximalDirections(trydir) \
+ { \
+ next = dirorder[trydir][NEXT]; \
+ prev = dirorder[trydir][PREV]; \
+ if (GameRandomNumber("actor choose dir",0) < 128) \
+ { \
+ dirtype temp = next; \
+ \
+ next = prev; \
+ prev = temp; \
+ } \
+ \
+ if (!dirtried[next]) \
+ { \
+ M_CHECKDIR(ob,next); \
+ dirtried[next]=1; \
+ } \
+ \
+ if (!dirtried[prev]) \
+ { \
+ M_CHECKDIR(ob,prev); \
+ dirtried[prev]=1; \
+ } \
+ \
+ }
+
+
+#define TrySmoothProximalDirections(trydir) \
+ { \
+ \
+ if (((trydir == olddir) || (dirdiff[trydir][olddir] < 2)) && \
+ (!dirtried[trydir])) \
+ { \
+ M_CHECKDIR(ob,trydir); \
+ dirtried[trydir] = 1; \
+ } \
+ next = dirorder[olddir][NEXT]; \
+ prev = dirorder[olddir][PREV]; \
+ \
+ if (dirdiff[trydir][next] <= dirdiff[trydir][prev]) \
+ { \
+ start = next; \
+ whichway = NEXT; \
+ } \
+ else \
+ { \
+ start = prev; \
+ whichway = PREV; \
+ } \
+ \
+ for (tdir= start; tdir != dirorder[trydir][whichway]; \
+ tdir = dirorder[tdir][whichway] \
+ ) \
+ { \
+ if (dirtried[tdir]) \
+ continue; \
+ M_CHECKDIR(ob,tdir); \
+ dirtried[tdir]=1; \
+ } \
+ \
+ }
+
+
+
+#define ChasePlayer(ob) \
+ { \
+ dx= player->x-ob->x; \
+ dy= ob->y-player->y; \
+ if ((abs(dx) < 0xb000) && (abs(dy) < 0xb000)) \
+ return; \
+ dummy.x = player->x; \
+ dummy.y = player->y; \
+ }
+
+
+void SelectChaseDir (objtype *ob)
+{
+ int dx,dy,whichway,tx,ty,actrad,visible,
+ realdiff;
+ dirtype dtry1,dtry2,tdir,olddir,next,prev,start,straight;
+ tpoint dummy;
+ byte dirtried[9] = {0};
+
+ olddir=ob->dir;
+ visible = CheckLine(ob,PLAYER[0],SIGHT);
+
+ /*
+ if (ob->flags & FL_FIRSTATTACK)
+ {
+ //
+ // turning around is only ok the very first time after noticing the
+ // player
+ //
+ turnaround = opposite[ob->dir];
+ ob->flags &= ~FL_FIRSTATTACK;
+ }
+ else
+ turnaround=nodir;
+ */
+ dummy.which = ACTOR;
+ dummy.z = ob->z;
+ if (ob->targettilex || ob->targettiley)
+ {
+ tx = ob->targettilex;
+ ty = ob->targettiley;
+ dx= tx - ob->x;
+ dy= ob->y - ty;
+ dummy.x = tx;
+ dummy.y = ty;
+ if ((abs(dx) < 0x2000) && (abs(dy) < 0x2000))
+ ChasePlayer(ob);
+ }
+ else
+ ChasePlayer(ob);
+
+ //if ((abs(dx) < 0x10000) && (abs(dy) < 0x10000))
+ //return;
+ straight = angletodir[atan2_appx(dx,dy)];
+ realdiff = dirdiff[straight][ob->dir];
+ ZEROMOM;
+
+ //insertion 20
+
+ actrad = ACTORSIZE;
+ dtry1=nodir;
+ dtry2=nodir;
+
+ if (dx> actrad)
+ dtry1= east;
+ else if (dx< -actrad)
+ dtry1= west;
+ if (dy> actrad)
+ dtry2=north;
+ else if (dy < -actrad)
+ dtry2= south;
+
+
+ if (abs(dy)>abs(dx))
+ {
+ tdir=dtry1;
+ dtry1=dtry2;
+ dtry2=tdir;
+ }
+
+ if (GameRandomNumber("chase minor",0) < 80)
+ {
+ tdir=dtry1;
+ dtry1=dtry2;
+ dtry2=tdir;
+ }
+
+ ZEROMOM;
+
+ if ((!visible) || (realdiff > 2)) // don't worry about abrupt or unrealistic turns if player
+ // can't see guards
+ {
+ M_CHECKDIR(ob,straight);
+ dirtried[straight]=1;
+ next = dirorder[straight][NEXT];
+ prev = dirorder[straight][PREV];
+
+ if ((dtry1 != nodir) && (dtry1 != straight))
+ {
+ M_CHECKDIR(ob,dtry1);
+ dirtried[dtry1]=1;
+ }
+
+
+ if ((dtry2 != nodir) && (!dirtried[dtry2]))
+ {
+ M_CHECKDIR(ob,dtry2);
+ dirtried[dtry2]=1;
+ }
+
+ if (dtry1 != nodir)
+ TryAbruptProximalDirections(dtry1);
+
+ if (dtry2 != nodir)
+ TryAbruptProximalDirections(dtry2);
+ }
+
+ else
+ {
+ if (realdiff < 2)
+ {
+ M_CHECKDIR(ob,straight);
+ dirtried[straight]=1;
+ }
+
+ if (dtry1 != nodir)
+ TrySmoothProximalDirections(dtry1);
+
+ if (dtry2 != nodir)
+ TrySmoothProximalDirections(dtry2);
+
+ }
+
+ if ((dtry1!=nodir) || (dtry2!=nodir))
+ {
+ if (GameRandomNumber("actor choose dir",0) < 128)
+ whichway = NEXT;
+ else
+ whichway = PREV;
+
+ for(tdir = dirorder[olddir][whichway]; tdir != olddir; tdir = dirorder[tdir][whichway])
+ {
+ if (dirtried[tdir])
+ continue;
+ M_CHECKDIR(ob,tdir);
+ }
+ }
+
+ ob->dir = olddir;
+}
+
+
+
+int Near(objtype *ob,void* what,int distance)
+
+{
+ objtype *aw;
+
+ aw = (objtype*) what;
+
+ if (FindDistance((aw->x - ob->x),(aw->y - ob->y)) <= (distance<<16))
+ return 1;
+ return 0;
+
+}
+
+
+
+/*
+===============
+=
+= SelectPathDir
+=
+===============
+*/
+
+void SelectPathDir (objtype *ob)
+{
+ int spot,centerx,centery,dx,dy,set,done,radius,ocl;
+
+ ocl = ob->obclass;
+
+
+ if ((ocl == bladeobj) && (!(ob->flags & FL_ACTIVE)))
+ return;
+
+ spot = MAPSPOT(ob->tilex,ob->tiley,1)-ICONARROWS;
+ set = ((ocl == wallopobj) || (ocl == roboguardobj));
+ done = (((!set) && (ob->dir == (dirtype)spot)) ||
+ (set && (ob->dir == (dirtype)(spot<<1))));
+
+ if ((spot >= 0) && (spot<= 7) && (!done))
+ {
+ centerx= (ob->tilex << 16) + HALFGLOBAL1;
+ centery= (ob->tiley << 16) + HALFGLOBAL1;
+ dx = abs(centerx - ob->x);
+ dy = abs(centery - ob->y);
+ //radius = (ob->speed > 0x4800)?(0xb000):(0x4000);
+ radius = 0x4000;
+
+ if ((dx < radius) && (dy < radius))
+ // new direction
+ {
+ ZEROMOM;
+ if ((ocl == wallopobj) || (ocl == roboguardobj))
+ {
+ ob->dir = spot<<1;
+ ParseMomentum(ob,dirangle16[ob->dir]);
+ }
+ else
+ {
+ ob->dir = spot;
+ ParseMomentum(ob,dirangle8[ob->dir]);
+ }
+ dx = centerx - ob->x;
+ dy = centery - ob->y;
+ SetFinePosition(ob,centerx,centery);
+ SetVisiblePosition(ob,centerx,centery);
+ /*
+ if (((ocl == bladeobj) || (ocl == diskobj)) && ob->whatever)
+ {objtype*passenger = (objtype*)(ob->whatever);
+
+ passenger->x += dx;
+ passenger->y += dy;
+ passenger->drawx = passenger->x;
+ passenger->drawy = passenger->y;
+ passenger->tilex = passenger->x >> 16;
+ passenger->tiley = passenger->y >> 16;
+ }*/
+// if (ob==SNAKEHEAD)
+// Debug("\n path changed at %d, %d",
+// ob->tilex,ob->tiley);
+ }
+ }
+ if (NOMOM)
+ {
+ if ((ocl == wallopobj) || (ocl == roboguardobj))
+ ParseMomentum(ob,dirangle16[ob->dir]);
+ else
+ ParseMomentum(ob,dirangle8[ob->dir]);
+ }
+
+ //if ((ob->obclass == firejetobj) || (ob->obclass == bladeobj))
+ //MoveActor(ob);
+ //else
+ ActorMovement(ob);
+
+}
+
+
+
+/*
+================
+=
+= CheckSight
+=
+= Checks a straight line between player and current object
+=
+= If the sight is ok, check alertness and angle to see if they notice
+=
+= returns true if the player has been spoted
+=
+================
+*/
+
+
+boolean CheckSight (objtype *ob,void *atwhat)
+{
+ long deltax,deltay;
+ objtype * what;
+//
+// don't bother tracing a line if the area isn't connected to the player's
+//
+ if (!areabyplayer[ob->areanumber])
+ return false;
+
+//
+// if the player is real close, sight is automatic
+//
+ what = (objtype*)atwhat;
+ deltax = what->x - ob->x;
+ deltay = what->y - ob->y;
+
+ if ((deltax > -MINSIGHT) && (deltax < MINSIGHT) &&
+ (deltay > -MINSIGHT) && (deltay < MINSIGHT))
+ return true;
+
+//
+// see if they are looking in the right direction
+//
+ switch (ob->dir)
+ {
+ case north:
+ if (deltay > 0)
+ return false;
+ break;
+
+ case east:
+ if (deltax < 0)
+ return false;
+ break;
+
+ case south:
+ if (deltay < 0)
+ return false;
+ break;
+
+ case west:
+ if (deltax > 0)
+ return false;
+ break;
+ default:
+ ;
+ }
+
+//
+// trace a line to check for blocking tiles (corners)
+//
+ return CheckLine (ob,atwhat,SIGHT);
+
+}
+
+
+
+void ActivateEnemy(objtype*ob)
+{ statetype *temp;
+
+
+ ob->flags |= (FL_ATTACKMODE|FL_FIRSTATTACK);
+ if (ob->obclass == roboguardobj)
+ return;
+
+ if (ob->temp3 == SNEAKY)
+ { NewState(ob,&s_sneakyrise1);
+ ob->temp3=0;
+ }
+ else if ((temp = M_S(CHASE)) != NULL)
+ NewState(ob,temp);
+ /*
+ ob->speed = ENEMYRUNSPEED;
+ */
+ if (ob->obclass == b_heinrichobj)
+ ob->speed = 7*ob->speed/2;
+ else if (ob->obclass == b_darianobj)
+ ob->speed = 3*SPDPATROL;
+ if (ob->door_to_open != -1)
+ ob->door_to_open = -1; // ignore the door opening command
+ ob->dirchoosetime = 0;
+
+
+}
+
+
+/*
+===============
+=
+= FirstSighting
+=
+= Puts an actor into attack mode and possibly reverses the direction
+= if the player is behind it
+=
+===============
+*/
+
+void FirstSighting (objtype *ob)
+{
+ statetype *temp;
+ int sound;
+
+ if (ob->temp3 == SNEAKY)
+ {
+ NewState(ob,&s_sneakyrise1);
+ ob->temp3=0;
+ if (ob->shapeoffset==0)
+ SD_PlaySoundRTP(SD_SNEAKYSPRINGMSND,ob->x,ob->y);
+ else
+ SD_PlaySoundRTP(SD_SNEAKYSPRINGFSND,ob->x,ob->y);
+ }
+ else if ((temp = M_S(CHASE)) != NULL)
+ {
+ int rand;
+
+ NewState(ob,temp);
+ sound = BAS[ob->obclass].see;
+ rand = GameRandomNumber("FirstSighting low",0);
+ if ((ob->obclass > lowguardobj) && (ob->obclass <= blitzguardobj) && (rand < 128)) //hack for alternate
+ sound++;
+ //if ((ob->obclass == lowguardobj) && (rand < 80))
+ //sound ++;
+ else if (ob->obclass == lowguardobj)
+ { if (rand < 128)
+ { if ((PLAYERSTATE[0].player == 1) || (PLAYERSTATE[0].player == 3))
+ sound++;
+ }
+ else
+ sound += 2;
+
+ if (ob->shapeoffset)
+ sound += 4;
+
+ }
+ SD_PlaySoundRTP(sound,ob->x,ob->y);
+ if ((ob->obclass>=b_darianobj) && (ob->obclass<=b_darksnakeobj))
+ {
+ MU_StartSong(song_bosssee);
+ }
+ }
+
+ /*
+ ob->speed = ENEMYRUNSPEED;*/
+ if (ob->obclass == b_heinrichobj)
+ ob->speed = 7*ob->speed/2;
+ else if (ob->obclass == b_darianobj)
+ ob->speed = 3*SPDPATROL;
+ if (ob->door_to_open != -1)
+ ob->door_to_open = -1; // ignore the door opening command
+ ob->dirchoosetime = 0;
+ ob->flags |= (FL_ATTACKMODE|FL_FIRSTATTACK);
+
+}
+
+
+/*
+===============
+=
+= SightPlayer
+=
+= Called by actors that ARE NOT chasing the player. If the player
+= is detected (by sight, noise, or proximity), the actor is put into
+= it's combat frame and true is returned.
+=
+= Incorporates a random reaction delay
+=
+===============
+*/
+
+boolean SightPlayer (objtype *ob)
+{
+ //if (ob->flags & FL_ATTACKMODE)
+ //Error ("An instance of %s in ATTACKMODE called SightPlayer!",debugstr[ob->obclass]);
+
+ if (!areabyplayer[ob->areanumber])
+ return false;
+
+ if (ob->obclass == b_robobossobj)
+ {
+ if (!(CheckSight(ob,player) || Near(ob,player,6)))
+ return false;
+
+ }
+
+
+ else if (ob->flags & FL_AMBUSH)
+ {
+ if (!CheckSight (ob,PLAYER[0]))
+ {
+ //SoftError("\n failed from ambush in SightPlayer");
+ return false;
+ }
+ ob->flags &= ~FL_AMBUSH;
+ }
+ else
+ {
+ if (ob->temp3 == SNEAKY)
+ {
+ if (!Near(ob,PLAYER[0],2))
+ return false;
+ }
+ else if (!((MISCVARS->madenoise) ||
+ (CheckSight (ob,player)) ||
+ (Near(ob,player,4))
+ )
+ )
+ {
+ //SoftError("\n failed from SightPlayer");
+ return false;
+ }
+ }
+
+ FirstSighting (ob);
+
+ return true;
+}
+
+
+/*
+=====================
+=
+= CheckLine
+=
+= Returns true if a straight line between two obs is unobstructed
+=
+=====================
+*/
+
+
+
+boolean CheckLine (void *from, void *to, int condition)
+{
+ objtype *tempactor,*ob,*orig;
+ statobj_t *checksprite;
+ int destx,desty,destz;
+ int desttilex,desttiley;
+ int snx,sny;
+ int incr[2];
+ int thedir[2];
+ int cnt;
+ int grid[2];
+ int index;
+ int vx,vy;
+ int yzangle;
+ int value;
+ int dx,dy,dz;
+ int xydist;
+ int otx,oty,count=0;
+
+
+
+ ob = (objtype*)to;
+ orig = (objtype*)from;
+ if (ob->which == SPRITE)
+ {
+ destx = ((statobj_t*)to)->x;
+ desty = ((statobj_t*)to)->y;
+ destz = ((statobj_t*)to)->z;
+ }
+ else
+ {
+ destx = ob->x;
+ desty = ob->y;
+ destz = ob->z;
+ }
+
+ desttilex=destx>>16;
+ desttiley=desty>>16;
+
+ if ((desttilex == orig->tilex) && (desttiley == orig->tiley))
+ return true;
+
+
+ dx=destx-orig->x;
+ dy=orig->y-desty;
+ dz=orig->z-destz;
+ xydist = FindDistance(dx,dy);
+ yzangle = atan2_appx(xydist,dz<<10);
+
+ if ((yzangle>MAXYZANGLE) && (yzangle<FINEANGLES-MAXYZANGLE))
+ {
+#if (0)
+ Debug("\nfailed from yzangle");
+#endif
+ return false;
+ }
+
+ //angle = atan2_appx(dx,dy);
+ otx = orig->x >> TILESHIFT;
+ oty = orig->y >> TILESHIFT;
+
+ if (xydist==0)
+ {
+ /*
+ SoftError("\nCheckLine:xydist=0");
+ if (orig->which == ACTOR)
+ SoftError("shooter: %s",debugstr[orig->obclass]);
+ if (ob->which == ACTOR)
+ SoftError("target: %s",debugstr[ob->obclass]);*/
+ vy=-dy;
+ vx=dx;
+ }
+ else
+ {
+ vy = -FixedDiv2(dy,xydist);
+ vx = FixedDiv2(dx,xydist);
+ }
+ snx=orig->x&0xffff;
+ sny=orig->y&0xffff;
+
+ grid[0]=otx;
+ grid[1]=oty;
+
+ if (vx>0)
+ {
+ thedir[0]=1;
+ snx^=0xffff;
+ incr[1]=-vx;
+ }
+ else
+ {
+ thedir[0]=-1;
+ incr[1]=vx;
+ }
+ if (vy>0)
+ {
+ thedir[1]=1;
+ sny^=0xffff;
+ incr[0]=vy;
+ }
+ else
+ {
+ thedir[1]=-1;
+ incr[0]=-vy;
+ }
+ cnt=FixedMul(snx,incr[0])+FixedMul(sny,incr[1]);
+
+
+ do
+ { count ++;
+ /*
+ if (count > 1000)
+ Error("possible infinite loop in CheckLine");
+ if ((grid[0] < 0) || (grid[0] > (MAPSIZE-1)) ||
+ (grid[1] < 0) || (grid[1] > (MAPSIZE-1)))
+ Error("out of bounds in check line, grid[0] = %d, grid[1] = %d",grid[0],grid[1]);
+ */
+ if ((grid[0]==desttilex) && (grid[1]==desttiley))
+ return true;
+ tempactor = (objtype*)actorat[grid[0]][grid[1]];
+ value = tilemap[grid[0]][grid[1]];
+ checksprite = sprites[grid[0]][grid[1]];
+ if (value)
+ {
+ if (value&0x8000)
+ {
+ if (!(value&0x4000))
+ {
+ doorobj_t*dptr = doorobjlist[value&0x3ff];
+
+ if (dptr->position < 0x8000)
+ {
+
+ int x = (grid[0] << 16) + 0x8000;
+ int y = (grid[1] << 16) + 0x8000;
+
+ if (dptr->vertical)
+ {
+ if (abs(dx) > abs(x-orig->x))
+ return false;
+ }
+ else
+ {
+ if (abs(dy) > abs(orig->y-y))
+ return false;
+ }
+ }
+ }
+ else
+ {
+ if (condition == SHOOT)
+ {
+ if ( maskobjlist[value&0x3ff]->flags & MW_SHOOTABLE )
+ {
+#if (0)
+ SoftError("\nfailed from shootable mask");
+#endif
+ return false;
+ }
+ else if ( maskobjlist[value&0x3ff]->flags & MW_WEAPONBLOCKING )
+ {
+#if (0)
+ SoftError("\nfailed from block mask");
+#endif
+ return false;
+ }
+ }
+ else if ((condition == MISSILE) &&
+ ( maskobjlist[value&0x3ff]->flags & MW_BLOCKING )
+ )
+ return false;
+ }
+ }
+ else
+ {
+#if (0)
+ SoftError("\n obx %d, oby %d, origx %d, origy %d"
+ "\n xydist %d, vx %d, vy %d",ob->x,ob->y,orig->x,
+ orig->y,xydist,vx,vy);
+
+ SoftError("\nfailed from normal wall");
+#endif
+ return false;
+ }
+ }
+ if (condition == SHOOT)
+ {
+ if (tempactor && (tempactor->which == ACTOR) &&
+ (tempactor->flags & FL_BLOCK) && (tempactor != orig) &&
+ (tempactor != ob)) //&&
+// (InRange(orig,tempactor,
+// FindDistance(orig->x-tempactor->x,orig->y-tempactor->y) )
+// ==true) )
+ {
+#if (0)
+ SoftError("\nfailed from actor");
+#endif
+ return false;
+ }
+ }
+
+ if (checksprite && (checksprite->flags & FL_BLOCK) && (condition == SHOOT) &&
+ ((void *)checksprite != to) &&
+ (checksprite->itemnumber!=stat_disk) &&
+ (InRange(orig,(objtype *)checksprite,
+ FindDistance(orig->x-checksprite->x,orig->y-checksprite->y) )
+ ==true) )
+
+ {
+#if (0)
+ SoftError("\nfailed from sprite");
+#endif
+ return false;
+ }
+
+ if (tempactor && (tempactor->which == PWALL))
+ {
+#if (0)
+ SoftError("\nfailed from pushwall");
+#endif
+ return false;
+ }
+ index=(cnt>=0);
+ cnt+=incr[index];
+ grid[index]+=thedir[index];
+ }
+ while (1);
+}
+
+
+
+
+
+
+
+/*
+=====================
+=
+= ShootActor
+=
+= Shoot an actor.
+=
+=====================
+*/
+void ShootActor(objtype * shooter, objtype * target, int damage, int accuracy, int angle)
+{
+ int dx,dy,dist;
+ int newmomx, newmomy;
+ int tcl;
+
+
+ if (target->flags & FL_DYING)
+ return;
+
+ dx = abs(shooter->x - target->x);
+ dy = abs(shooter->y - target->y);
+ dist = FindDistance(dx,dy)>>16;
+
+ tcl=target->obclass;
+
+ if (tcl==playerobj)
+ {
+ target->target=shooter;
+ if (target->flags&FL_BPV)
+ {
+ playertype *pstate;
+
+ M_LINKSTATE(target,pstate);
+ pstate->protectiontime -= (damage<<1);
+ if (pstate->protectiontime < 1)
+ pstate->protectiontime = 1;
+ if (target==player)
+ GM_UpdateBonus (pstate->protectiontime, false);
+ return;
+ }
+ else if ((target->flags&FL_GODMODE) || (target->flags&FL_DOGMODE) || godmode)
+ return;
+ //damage=FixedMulShift((gamestate.difficulty+1),damage,2); // player object difficulty
+ }
+
+ else if (tcl == NMEsaucerobj)
+ {
+ target->momentumx = target->momentumy = 0;
+ NewState(target,&s_explosion1);
+ target->flags &= ~FL_SHOOTABLE;
+ return;
+ }
+ else if (tcl == b_darianobj)
+ MISCVARS->ESAU_SHOOTING = false;
+ else if ((tcl == strikeguardobj) || (tcl == b_heinrichobj))
+ target->target = shooter;
+
+ if (( (!(target->flags & FL_SHOOTABLE)) ||
+ (tcl == roboguardobj) || (tcl == wallopobj) ||
+ (tcl == patrolgunobj) ) &&
+ (tcl!=playerobj) )
+ SpawnMetalSparks(target,angle);
+
+ else if ((tcl < b_darianobj) || (tcl > b_darksnakeobj))
+ {
+
+ //target->flags &= ~FL_USE;
+
+ damage=FixedMulShift(511-accuracy,damage,9); // Min half damage
+ if (dist<64)
+ {
+ if (dist>2)
+ damage=FixedMulShift(63-dist,damage,6);
+ if (damage<1)
+ damage=1;
+ }
+ else
+ damage=1;
+
+ if (damage>MAXDAMAGE) damage=MAXDAMAGE; // absolutely clip it
+
+ DamageThing(target,damage);
+ if ((tcl == collectorobj) && gamestate.SpawnDeluder)
+ {
+ Collision(target,shooter,0,0);
+ if (target->hitpoints <= 0)
+ BATTLE_CheckGameStatus(battle_shot_deluder,shooter->dirchoosetime);
+ }
+
+ else
+ { newmomx = FixedMul(damage<<7,costable[angle]);
+ newmomy = -FixedMul(damage<<7,sintable[angle]);
+ Collision(target,shooter,-(target->momentumx)+newmomx,-(target->momentumy)+newmomy);
+ if (tcl == playerobj)
+ {
+ playertype * pstate;
+
+ M_LINKSTATE(target,pstate);
+ if (pstate->health <= 0)
+ {
+
+ if (shooter->obclass == playerobj) {
+ if (!target->momentumz)
+ BATTLE_PlayerKilledPlayer(battle_kill_with_bullet,shooter->dirchoosetime,target->dirchoosetime);
+ else
+ BATTLE_PlayerKilledPlayer(battle_kill_with_bullet_in_air,shooter->dirchoosetime,target->dirchoosetime);
+ }
+ }
+ }
+// SoftError("ShootActor: damage=%ld dist=%ld\n",damage,dist);
+
+ if ((GameRandomNumber("disembowel",0)<64) && (gamestate.violence == vl_excessive))
+ {
+ int temp;
+ temp=target->temp1;
+ target->temp1=angle;
+
+ SpawnParticles(target,DISEMBOWEL,damage>>3);
+ target->temp1=temp;
+ }
+ else if (gamestate.violence > 0)
+ SpawnBlood(target,angle);
+ }
+ }
+}
+
+
+/*
+=====================
+=
+= ShootSprite
+=
+= Shoot a sprite.
+=
+=====================
+*/
+void ShootSprite(objtype * shooter, statobj_t * target, int damage, int accuracy, int angle)
+{
+ int dx,dy,dist;
+
+
+ if (!(target->flags & FL_SHOOTABLE))
+// Watchout for sprite being passed in as actor WARNING
+ SpawnMetalSparks((objtype *)target,angle);
+
+ else
+ {
+ dx = abs(shooter->x - target->x);
+ dy = abs(shooter->y - target->y);
+ dist = FindDistance(dx,dy)>>16;
+
+ damage=FixedMulShift(511-accuracy,damage,9); // Min half damage
+ if (dist<64)
+ {
+ if (dist>2)
+ damage=FixedMulShift(63-dist,damage,6);
+ if (damage<1)
+ damage=1;
+ }
+ else
+ damage=1;
+
+ if (damage>MAXDAMAGE) damage=MAXDAMAGE; // absolutely clip it
+
+ // SoftError("ShootSprite: damage=%ld dist=%ld\n",damage,dist);
+
+ DamageThing((objtype *)target,damage);
+ if (FirstExplosionState(new->state))
+ new->whatever = shooter;
+
+ SpawnStaticDamage(target, angle);
+ }
+}
+
+
+/*
+=====================
+=
+= RayShoot
+=
+= Cast a ray out at the shooter's angle and yzangle, return
+=
+=====================
+*/
+
+
+
+void RayShoot (objtype * shooter, int damage, int accuracy)
+{
+ objtype *tempactor;
+ statobj_t *checksprite;
+ int snx,sny;
+ int incr[2];
+ int zincr[2];
+ int thedir[2];
+ int cnt;
+ int grid[2];
+ int index;
+ int vx,vy;
+ int angle;
+ int yzangle;
+ int value;
+ int offset;
+ int z;
+ int lastcnt;
+ int bullethole=0;
+ enum {gs_door, gs_wall, gs_floor, gs_ceiling, gs_pushwall};
+ int smokecondition=0;
+
+
+ if ((shooter->areanumber==player->areanumber) && (Near(shooter,player,3)))
+ SetIllumination(2);
+
+ offset = ((GameRandomNumber("RayShoot",0)-128)>>MAXSHOOTSHIFT);
+ offset = FixedMulShift(accuracy,offset,8);
+
+ if (offset>MAXSHOOTOFFSET)
+ offset=MAXSHOOTOFFSET;
+
+ else if (offset<-MAXSHOOTOFFSET)
+ offset=-MAXSHOOTOFFSET;
+
+ angle=(shooter->angle+offset)&(FINEANGLES-1);
+
+ offset = ((GameRandomNumber("RayShoot",1)-128)>>MAXSHOOTSHIFT);
+ offset = FixedMulShift(accuracy,offset,8);
+
+ if (offset>MAXSHOOTOFFSET)
+ offset=MAXSHOOTOFFSET;
+
+ else if (offset<-MAXSHOOTOFFSET)
+ offset=-MAXSHOOTOFFSET;
+
+ yzangle=(shooter->yzangle+offset)&(FINEANGLES-1);
+
+ vy = -sintable[angle];
+ vx = costable[angle];
+ snx=shooter->x&0xffff;
+ sny=shooter->y&0xffff;
+ grid[0]=shooter->tilex;
+ grid[1]=shooter->tiley;
+ if (shooter->obclass==playerobj)
+ {
+ playertype * pstate;
+
+ M_LINKSTATE(shooter,pstate);
+ z=shooter->z+pstate->playerheight-32;
+ }
+ else
+ z=shooter->z-7;
+ if (vx>0)
+ {
+ thedir[0]=1;
+ snx^=0xffff;
+ incr[1]=-vx;
+ }
+ else
+ {
+ thedir[0]=-1;
+ incr[1]=vx;
+ }
+ if (vy>0)
+ {
+ thedir[1]=1;
+ sny^=0xffff;
+ incr[0]=vy;
+ }
+ else
+ {
+ thedir[1]=-1;
+ incr[0]=-vy;
+ }
+ zincr[0]=-FixedMulShift(sintable[yzangle],abs(vx),26);
+ zincr[1]=-FixedMulShift(sintable[yzangle],abs(vy),26);
+
+ cnt=FixedMul(snx,incr[0])+FixedMul(sny,incr[1]);
+ index= (cnt >= 0);
+ do
+ {
+ tempactor = (objtype*)actorat[grid[0]][grid[1]];
+ value = tilemap[grid[0]][grid[1]];
+ checksprite = sprites[grid[0]][grid[1]];
+ if (value)
+ {
+ if (value&0x8000)
+ {
+ if (!(value&0x4000))
+ {
+ if ((doorobjlist[value&0x3ff]->action==dr_closed) || (z<maxheight-64))
+ {
+ smokecondition=gs_door;
+ break;
+ }
+ else if (doorobjlist[value&0x3ff]->position<=0x8000)
+ {
+ smokecondition=gs_door;
+ break;
+ }
+ }
+ else
+ {
+ if ( maskobjlist[value&0x3ff]->flags & MW_SHOOTABLE )
+ {
+ if (z>maxheight-64) // Are we shooting above the glass
+ {
+ UpdateMaskedWall(value&0x3ff);
+ return;
+ }
+ }
+ else if ( maskobjlist[value&0x3ff]->flags & MW_WEAPONBLOCKING )
+ {
+ smokecondition=gs_door;
+ break;
+ }
+ }
+ }
+ else
+ {
+ smokecondition=gs_wall;
+ break;
+ }
+ }
+
+ if (checksprite &&
+ ((checksprite->flags & FL_BLOCK)||(checksprite->flags & FL_SHOOTABLE)) &&
+ (abs(checksprite->z-z)<32) &&
+ (InRange(shooter,(objtype *)checksprite,
+ FindDistance(shooter->x-checksprite->x,shooter->y-checksprite->y) )
+ ==true
+ )
+ )
+ {
+ ShootSprite(shooter, checksprite, damage, accuracy, angle);
+ return;
+ }
+
+
+ if (tempactor)
+ { if (tempactor->which == ACTOR)
+ { if ((abs(tempactor->z-z)<32 ) && (!(tempactor->flags & FL_DYING)) &&
+ (tempactor->flags & FL_BLOCK) && (tempactor != shooter) &&
+ (tempactor->obclass!=diskobj) &&
+ (InRange(shooter,tempactor,
+ FindDistance(shooter->x-tempactor->x,shooter->y-tempactor->y) )
+ ==true
+ )
+ )
+ { ShootActor(shooter, tempactor, damage, accuracy, angle);
+ return;
+ }
+ }
+ else if (tempactor->which == PWALL)
+ return;
+ }
+
+ if (z<-32)
+ {
+ smokecondition=gs_ceiling;
+ break;
+ }
+ else if (z>maxheight)
+ {
+ smokecondition=gs_floor;
+ break;
+ }
+ index= (cnt >= 0);
+ cnt+=incr[index];
+ z +=zincr[index];
+ grid[index]+=thedir[index];
+ }
+ while (1);
+
+ if (IsWindow(grid[0],grid[1]))
+ return;
+
+ lastcnt=cnt-incr[index];
+
+ if (smokecondition==gs_floor)
+ {
+ int dist;
+ int tangentangle;
+
+ tangentangle=tantable[yzangle];
+ if (tangentangle!=0)
+ {
+ dist=FixedDiv2(((shooter->z-maxheight)<<10),(tangentangle<<1));
+ xintercept=shooter->x+FixedMul(dist,costable[angle]);
+ yintercept=shooter->y-FixedMul(dist,sintable[angle]);
+ }
+ z=maxheight;
+// bullethole=5;
+ }
+ else if (smokecondition==gs_ceiling)
+ {
+ int dist;
+ int tangentangle;
+
+ if (sky!=0)
+ return;
+ tangentangle=tantable[yzangle];
+ if (tangentangle!=0)
+ {
+ dist=FixedDiv2(((shooter->z+32)<<10),(tangentangle<<1));
+ xintercept=shooter->x+FixedMul(dist,costable[angle]);
+ yintercept=shooter->y-FixedMul(dist,sintable[angle]);
+ }
+ z=-32;
+// bullethole=5;
+ }
+ else
+ {
+ int dx,dy,xydist;
+
+
+#define CORNERVALUE 0x500
+
+
+ if (IsWindow(grid[0],grid[1]))
+ return;
+ if (lastcnt<0)
+ {
+ xintercept=grid[0]<<16;
+ if (smokecondition==gs_door)
+ {
+ if (thedir[0]<0)
+ xintercept+=0x9fff;
+ else
+ xintercept+=0x5fff;
+ yintercept=FixedScale(xintercept-shooter->x,vy,vx)+shooter->y;
+ if ((yintercept>>16)!=grid[1])
+ {
+ if ((yintercept>>16)>grid[1])
+ yintercept=(grid[1]<<16)+0xffff;
+ else
+ yintercept=(grid[1]<<16);
+ }
+ }
+ else if (smokecondition==gs_wall)
+ {
+ if (thedir[0]<0)
+ {
+ objtype * ta;
+
+ xintercept += 0x10000;
+ yintercept=FixedScale(xintercept-shooter->x,vy,vx)+shooter->y;
+
+ xintercept += SMOKEWALLOFFSET;
+ bullethole=1;
+ if (yintercept < ((grid[1] << 16) + CORNERVALUE))
+ bullethole = 0;
+ else if (yintercept > ((grid[1] << 16) + 0x10000 - CORNERVALUE))
+ bullethole = 0;
+
+ ta = (objtype*)actorat[grid[0]][grid[1]];
+ if ((ta) && (ta->which==PWALL))
+ bullethole=0;
+ }
+ else
+ {
+ objtype * ta;
+
+ yintercept=FixedScale(xintercept-shooter->x,vy,vx)+shooter->y;
+ xintercept-=SMOKEWALLOFFSET;
+ bullethole=2;
+ if (yintercept < ((grid[1] << 16) + CORNERVALUE))
+ bullethole = 0;
+ else if (yintercept > ((grid[1] << 16) + 0x10000 - CORNERVALUE))
+ bullethole = 0;
+
+ ta = (objtype*)actorat[grid[0]][grid[1]];
+ if ((ta) && (ta->which==PWALL))
+ bullethole=0;
+ }
+ }
+ }
+ else
+ {
+ yintercept=grid[1]<<16;
+ if (smokecondition==gs_door)
+ {
+ if (thedir[1]<0)
+ yintercept+=0x9fff;
+ else
+ yintercept+=0x5fff;
+ xintercept=FixedScale(yintercept-shooter->y,vx,vy)+shooter->x;
+ if ((xintercept>>16)!=grid[0])
+ {
+ if ((xintercept>>16)>grid[0])
+ xintercept=(grid[0]<<16)+0xffff;
+ else
+ xintercept=(grid[0]<<16);
+ }
+ }
+ else if (smokecondition==gs_wall)
+ {
+ if (thedir[1]<0)
+ {
+ objtype * ta;
+
+
+ yintercept += 0x10000;
+ xintercept=FixedScale(yintercept-shooter->y,vx,vy)+shooter->x;
+
+ yintercept += SMOKEWALLOFFSET;
+ bullethole=3;
+ if (xintercept < ((grid[0] << 16) + CORNERVALUE))
+ bullethole = 0;
+ else if (xintercept > ((grid[0] << 16) + 0x10000 - CORNERVALUE))
+ bullethole = 0;
+
+ ta = (objtype*)actorat[grid[0]][grid[1]];
+ if ((ta) && (ta->which==PWALL))
+ bullethole=0;
+ }
+ else
+ {
+ objtype * ta;
+
+ xintercept=FixedScale(yintercept-shooter->y,vx,vy)+shooter->x;
+ yintercept-=SMOKEWALLOFFSET;
+ bullethole=4;
+ if (xintercept < ((grid[0] << 16) + CORNERVALUE))
+ bullethole = 0;
+ else if (xintercept > ((grid[0] << 16) + 0x10000 - CORNERVALUE))
+ bullethole = 0;
+
+ ta = (objtype*)actorat[grid[0]][grid[1]];
+ if ((ta) && (ta->which==PWALL))
+ bullethole=0;
+ }
+ }
+ }
+ dx = xintercept - shooter->x;
+ dy = shooter->y - yintercept;
+ xydist = FindDistance(dx,dy);
+ if (shooter->obclass==playerobj)
+ {
+ playertype * pstate;
+
+ M_LINKSTATE(shooter,pstate);
+ z=shooter->z-FixedMulShift(xydist,tantable[yzangle],25)+pstate->playerheight-32;
+ }
+ else
+ z=shooter->z-FixedMulShift(xydist,tantable[yzangle],25);
+ if (smokecondition==gs_wall)
+ {
+ if (z<-32)
+ z=-32;
+ }
+ }
+ SpawnGunSmoke(xintercept,yintercept,z,angle,bullethole);
+}
+
+
+/*
+=====================
+=
+= T_BossDied ()
+=
+=====================
+*/
+
+void T_BossDied (objtype *ob)
+{
+
+ if (ob->ticcount)
+ return;
+
+ switch (ob->obclass)
+ {
+ case b_darianobj:
+ case b_heinrichobj:
+ case b_darkmonkobj:
+ case b_robobossobj:
+ case b_darksnakeobj:
+ playstate = ex_bossdied;
+ break;
+ default:
+ ;
+ }
+}
+
+
+/*
+=====================
+=
+= T_Wind ()
+=
+=====================
+*/
+
+static int WindDistance = 1000;
+static int WindCurrentDistance = 1000;
+static int WindHandle = -1;
+static int WindLastTic = -1;
+static int WindPlaying = false;
+static int WindPitch = 0;
+static int WindDestPitch = 0;
+static int WindPitchRate = 0;
+
+void T_Wind
+(
+ objtype *ob
+)
+
+{
+ int distance;
+ int dx;
+ int dy;
+
+ if ( ( GetTicCount() - WindLastTic ) > 0 )
+ {
+ WindDistance = 1000;
+
+ WindPitch += WindPitchRate;
+ if ( WindPitch == WindDestPitch )
+ {
+ WindDestPitch = ( RandomNumber( "Wind Pitch", 0 ) - 128 ) << 3;
+ WindPitchRate = 1;
+ if ( WindDestPitch < WindPitch )
+ {
+ WindPitchRate = -WindPitchRate;
+ }
+ }
+ }
+ WindLastTic = GetTicCount();
+
+ dx = ( ob->x - PLAYER[0]->x );
+ dy = ( PLAYER[0]->y - ob->y );
+
+ distance = 1000;
+ if ( areabyplayer[ ob->areanumber ] )
+ {
+ distance = ( FindDistance( dx, dy ) ) >> 13;
+ }
+
+ if ( distance < WindDistance )
+ {
+ WindDistance = distance;
+ }
+
+ if ( WindDistance < 255 )
+ {
+ WindPlaying = true;
+ WindCurrentDistance = WindDistance;
+ }
+ else
+ {
+ if ( WindPlaying )
+ {
+ WindCurrentDistance += 3;
+ }
+ }
+
+ if ( WindPlaying )
+ {
+ if ( WindCurrentDistance < 255 )
+ {
+ if ( !SD_SoundActive( WindHandle ) )
+ {
+ WindHandle = SD_PlayPitchedSound( SD_WINDSND,
+ 255 - WindCurrentDistance, WindPitch );
+ }
+ else
+ {
+ SD_SetSoundPitch( WindHandle, WindPitch );
+ SD_SetPan( WindHandle, 255 - WindCurrentDistance, 255 - WindCurrentDistance,
+ 255 - WindCurrentDistance );
+ }
+ }
+ else
+ {
+ SD_StopSound( WindHandle );
+ WindPlaying = false;
+ }
+ }
+}
+
+/*
+=====================
+=
+= StopWind ()
+=
+=====================
+*/
+
+void StopWind
+(
+ void
+)
+
+{
+ objtype *temp;
+
+ FX_SetReverb( 0 );
+
+ SD_StopSound( WindHandle );
+ WindDistance = 1000;
+ WindCurrentDistance = 1000;
+ WindHandle = -1;
+ WindLastTic = -1;
+ WindPlaying = false;
+ WindPitch = 0;
+ WindDestPitch = 0;
+ WindPitchRate = 0;
+
+
+ for(temp=FIRSTACTOR; temp; temp=temp->next)
+ {
+ if (temp->soundhandle != -1)
+ SD_StopSound(temp->soundhandle);
+ }
+}
+
--- /dev/null
+++ b/rott/rt_actor.h
@@ -1,0 +1,438 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_actor_public
+#define _rt_actor_public
+
+//***************************************************************************
+//
+// RT_ACTOR.C (actor functions)
+//
+//***************************************************************************
+
+#include "states.h"
+
+
+#define FL_SYNCED 0x400
+#define FL_MASTER 0x800
+#define FL_SKELETON 0x02
+#define GASTICS 1050
+
+
+#define M_ISACTOR(x) ((x!=NULL) && (x->which == ACTOR))
+
+#define SF_GUTS 0x20
+
+#define NUMENEMIES 16
+#define NUMCLASSES 51
+#define MAXTOUCH 10
+#define MAXPOP 32
+#define MAXDELETE 512
+
+#define InMapBounds(x,y) (((x) >= 0) && ((x) < MAPSIZE) && ((y) >= 0) && ((y) < MAPSIZE))
+
+
+#define ACTIVE(ob) ((ob == firstactive) || (ob->prevactive) || (ob->nextactive))
+
+enum {SHOOT,SIGHT,DIRCHECK,EXPLOSION,MISSILE};
+
+
+typedef enum
+{
+ gt_sparks,
+ gt_organ,
+ gt_rib,
+ gt_pinkorgan,
+ gt_head,
+ gt_arm,
+ gt_leg,
+ gt_humerus,
+ gt_pelvis,
+ gt_limb,
+ gt_bsoul,
+ gt_lsoul,
+ gt_spit,
+ NumGibTypes
+} gib_t;
+
+#define GUTS (NumGibTypes)
+#define RANDOM (NumGibTypes + 1)
+#define DISEMBOWEL (NumGibTypes + 2)
+
+
+#define GASVALUE 192
+
+#define PAINOFFSET 2
+#define PMFOFFSET 50
+#define REMOTEOFFSET 86
+
+#define ACTORSIZE 0x5800
+#define PWALLRAD 0xa000
+
+#ifdef __WATCOMC__
+int M_ABS(int value);
+#pragma aux M_ABS = \
+ "test eax,eax", \
+ "jge done", \
+ "neg eax",\
+ "done: " \
+ parm [eax] \
+ value [eax] \
+ modify exact [eax]
+#else
+#define M_ABS abs
+#endif
+
+#define M_CheckPlayerKilled(ob) \
+{ if ((ob->obclass == playerobj) && (ob->flags & FL_DYING)) \
+ BATTLE_CheckGameStatus(battle_player_killed,ob->dirchoosetime);\
+}
+
+
+
+#define SetTilePosition(ob, newtilex, newtiley) \
+ { \
+ ob->tilex = newtilex; \
+ ob->tiley = newtiley; \
+ ob->x = (ob->tilex << TILESHIFT) + TILEGLOBAL/2; \
+ ob->y = (ob->tiley << TILESHIFT) + TILEGLOBAL/2; \
+ }
+
+
+#define SetFinePosition(ob, newx, newy) \
+ { \
+ ob->x = newx; \
+ ob->y = newy; \
+ ob->tilex = (ob->x >> TILESHIFT); \
+ ob->tiley = (ob->y >> TILESHIFT); \
+ }
+
+#define SetVisiblePosition(ob, x, y) \
+ { \
+ ob->drawx = x; \
+ ob->drawy = y; \
+ }
+
+
+//***************************************************************************
+//
+// WeaponDamages
+//
+//***************************************************************************
+#define DMG_PISTOL 13
+#define DMG_MP40 10
+#define DMG_AHGUN 10
+#define DMG_ENEMYBULLETWEAPON 10
+
+
+
+
+typedef struct bas
+{
+ short operate,
+ see,
+ fire,
+ hit,
+ die;
+} basic_actor_sounds;
+
+extern basic_actor_sounds BAS[NUMCLASSES+3];
+
+
+typedef struct
+{ int x,y;
+} _2Dpoint;
+
+typedef enum {
+ inertobj,
+ playerobj,
+ lowguardobj,
+ highguardobj,
+ overpatrolobj,
+ strikeguardobj,
+ blitzguardobj,
+ triadenforcerobj,
+ deathmonkobj,
+ dfiremonkobj,
+ roboguardobj,
+
+ b_darianobj,
+ b_heinrichobj,
+ b_robobossobj,
+ b_darkmonkobj,
+ b_darksnakeobj,
+ patrolgunobj,
+ wallopobj,
+
+
+ //specials
+
+ pillarobj,
+ firejetobj,
+ bladeobj,
+ crushcolobj,
+ boulderobj,
+ spearobj,
+ gasgrateobj,
+ springobj,
+
+ // Missile weapon types
+
+ shurikenobj,
+ wallfireobj,
+ netobj,
+ h_mineobj,
+ grenadeobj,
+ fireballobj,
+ dmfballobj,
+ bigshurikenobj,
+ missileobj,
+ NMEsaucerobj,
+ dm_weaponobj,
+ dm_heatseekobj,
+ dm_spitobj,
+ p_bazookaobj,
+ p_firebombobj,
+ p_heatseekobj,
+ p_drunkmissileobj,
+ p_firewallobj,
+ p_splitmissileobj,
+ p_kesobj,
+ p_godballobj,
+ collectorobj,
+ diskobj,
+ rainobj
+
+
+} classtype;
+
+
+typedef struct objstruct
+{
+ thingtype which;
+ byte tilex,tiley;
+ fixed x,y,z;
+ int shapenum;
+ unsigned flags;
+ short ticcount;
+ signed short hitpoints;
+ word whichactor;
+
+ signed short dirchoosetime;
+ fixed drawx,drawy;
+ classtype obclass;
+ statetype * state;
+ signed char door_to_open;
+ byte areanumber;
+ signed short shapeoffset;
+ int targettilex,targettiley;
+
+
+ dirtype dir;
+ short int angle;
+ short int yzangle;
+
+ int soundhandle;
+ int speed;
+ int momentumx, momentumy, momentumz;
+ int temp1,temp2,temp3;
+ void *whatever,*target;
+ struct objstruct *next, *prev;
+ struct objstruct *nextactive, *prevactive;
+ struct objstruct *nextinarea, *previnarea;
+
+} objtype;
+
+
+
+
+typedef struct b_struct
+{ int NMErotate;
+ int NMEdirstried;
+ int NMEqueuesize;
+ int ESAU_HIDING,ESAU_SHOOTING;
+ int HRAMMING, HMINING;
+ int SOUNDTIME;
+ int redindex,REDTIME;
+ int monkz;
+ int monkup;
+ int firespawned;
+ int notouch,noholes;
+ int nexttouch,nextpop;
+ int popsleft;
+ int DSTATE;
+ int doorcount;
+ int KEYACTORSLEFT;
+ int GASON;
+ int gasindex;
+ boolean NET_IN_FLIGHT;
+ boolean madenoise;
+ _2Dpoint ETOUCH[MAXTOUCH],EPOP[MAXPOP],TOMLOC;
+ int NUMWEAPONS;
+ int BulletHoleNum;
+ int NUMBEGGINGKEVINS;
+ boolean fulllightgibs;
+ boolean directgibs;
+ int gibgravity;
+ int gibspeed;
+ boolean supergibflag;
+ boolean randgibspeed;
+ int numgibs;
+ boolean elevatormusicon;
+} misc_stuff;
+
+
+extern boolean ludicrousgibs;
+extern objtype* PLAYER0MISSILE;
+extern byte deathshapeoffset[8];
+extern byte RANDOMACTORTYPE[10];
+extern objtype* FIRSTACTOR,*LASTACTOR;
+extern objtype *FIRSTRAIN,*LASTRAIN;
+extern objtype* SCREENEYE;
+extern objtype *firstareaactor[NUMAREAS+1],*lastareaactor[NUMAREAS+1];
+extern misc_stuff mstruct,*MISCVARS;
+extern int actorstart,actorstop;
+extern exit_t playstate;
+extern objtype *lastactive,*firstactive;
+extern objtype *new,**objlist,
+ *killerobj;
+extern void *actorat[MAPSIZE][MAPSIZE];
+extern int angletodir[ANGLES];
+extern _2Dpoint SNAKEPATH[512];
+/* extern int STOPSPEED; */
+extern int FRICTION;
+
+extern int objcount;
+
+void SpawnInertActor(int,int,int);
+objtype* DiskAt(int tilex,int tiley);
+void GetRainActors(void);
+void DoRain(void);
+void SpawnDisk(int,int,int,boolean);
+void T_ElevDisk(objtype*);
+void Add_To_Delete_Array(void*);
+void Remove_Delete_Array_Entries(void);
+void MakeInactive(objtype*ob);
+void RespawnEluder(void);
+void SpawnCollector(int,int);
+void MakeLastInArea(objtype*);
+void RemoveFromArea(objtype*);
+void GetMomenta(objtype*,objtype*,int*,int*,int*,int);
+int AngleBetween(objtype*,objtype*);
+void TurnActorIntoSprite(objtype*);
+void ResolveDoorSpace(int,int);
+void RemoveObj(objtype*);
+void SpawnParticles(objtype*,int,int);
+void MakeActive(objtype*);
+void SpawnSpear(int,int,int);
+void SpawnBoulder(int,int,int);
+void SpawnCrushingColumn(int,int,int);
+void SpawnFirejet(int,int,int,int);
+void T_Firethink(objtype*);
+void SpawnBlade(int,int,int,int,int);
+void T_OrobotChase(objtype*);
+void SpawnMultiSpriteActor(classtype,int,int,int);
+boolean ActorTryMove(objtype*,int,int,int);
+void A_Repeat(objtype*);
+void T_Heinrich_Defend(objtype*);
+void T_Heinrich_Out_of_Control(objtype*);
+void A_HeinrichShoot(objtype*);
+void T_EsauWait(objtype*);
+void T_EsauRise(objtype*);
+void A_Drain(objtype*ob);
+void T_Explosion(objtype*ob);
+void T_MoveColumn(objtype*);
+void EnableObject(long object);
+void DisableObject(long object);
+
+void T_Collide(objtype*);
+void Collision(objtype*ob,objtype *attacker,int hitmomentumx,int hitmomentumy);
+void ActorMovement (objtype *);
+void MoveActor(objtype*);
+
+void InitActorList(void);
+void NewState(objtype*,statetype*);
+void DoActor(objtype*);
+
+void SpawnPushColumn(int tilex,int tiley,int which,int dir, int linked);
+void SpawnGunThingy(classtype which, int tilex, int tiley, int dir);
+void SpawnStand (classtype which, int tilex, int tiley, int dir, int ambush);
+void SpawnPatrol (classtype which, int tilex, int tiley, int dir);
+void SpawnDeadGuard (int tilex, int tiley);
+void SpawnWallfire(int tilex, int tiley, int dir);
+void SpawnMissile(objtype*,classtype,int,int,statetype*,int);
+
+void InitHitRect (objtype *ob, unsigned radius);
+void NewState (objtype *ob, statetype *state);
+void SelectPathDir(objtype*);
+void SelectChaseDir (objtype *ob);
+boolean SightPlayer (objtype *ob);
+boolean CheckLine (void*,void *,int);
+boolean CheckSight (objtype *ob,void*);
+void KillActor (objtype *ob);
+void DamageThing (void *, int);
+void MissileHit (objtype *,void*);
+void GetNewActor(void);
+
+void T_WallPath(objtype*);
+void T_Path (objtype *ob); //done
+void T_RoboChase(objtype*ob);
+void T_RoboPath(objtype*ob);
+void T_Chase (objtype *ob); //done
+void T_EsauChase(objtype*ob); //done
+void T_Spears(objtype*);
+void T_Projectile (objtype *ob); //done
+void T_Stand (objtype *ob); //done
+void T_GunStand(objtype *ob); //done
+void T_Use(objtype *ob); // done
+void A_Shoot (objtype *ob); // done
+void A_MissileWeapon(objtype*); // done
+void A_Wallfire(objtype*);
+
+void A_Steal(objtype*);
+
+void T_Roll(objtype*);
+void T_BossDied (objtype *ob);
+boolean QuickSpaceCheck(objtype*,int,int);
+void PushWallMove(int num);
+void SpawnNewObj(unsigned,unsigned,statetype*,classtype);
+void SpawnSpring(int,int);
+void SpawnFourWayGun(int,int);
+void SpawnSnake(int tilex,int tiley);
+void SpawnSneaky(int,int);
+boolean MissileTryMove(objtype*ob,int,int,int);
+
+void SaveActors(byte ** buf, int * size);
+void LoadActors(byte * buf, int size);
+
+boolean TurnOffLight0 (int tilex, int tiley);
+boolean TurnOffLight1 (int tilex, int tiley, int i, int j);
+boolean TurnOffLight2 (int tilex, int tiley, int j);
+boolean TurnOffLight3 (int tilex, int tiley, int i);
+
+void ParseMomentum(objtype *ob,int angle);
+void SpawnGroundExplosion(int x, int y, int z);
+void RayShoot (objtype * shooter, int damage, int accuracy);
+void FindEmptyTile(int *stilex, int *stiley);
+void T_Wind( objtype *ob );
+void StopWind( void );
+
+void ResurrectEnemies();
+
+#endif
--- /dev/null
+++ b/rott/rt_battl.c
@@ -1,0 +1,1129 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: RT_BATTL.C
+
+ author: James R. Dose
+ phone: (214)-271-1365 Ext #221
+ date: September 8, 1994
+
+ Battle mode support routines for Rise of the Triad.
+
+ (c) Copyright 1994 Apogee Software. All Rights Reserved.
+**********************************************************************/
+
+#include <string.h>
+#include "rt_def.h"
+#include "rottnet.h"
+#include "isr.h"
+#include "rt_battl.h"
+#include "rt_actor.h"
+#include "rt_rand.h"
+#include "rt_playr.h"
+#include "rt_game.h"
+#include "rt_sound.h"
+#include "rt_com.h"
+#include "rt_msg.h"
+#include "rt_view.h"
+
+#include "rt_util.h"
+#include "rt_main.h"
+//MED
+#include "memcheck.h"
+
+#define INFINITE -1
+
+static battle_status BATTLE_StartRound( void );
+
+static int Timer;
+static int TimeLimit;
+static int NumberOfPlayers;
+static int BattleRound;
+static int BattleMode;
+
+static boolean RoundOver;
+static boolean KillsEndGame;
+static boolean KeepTrackOfKills;
+boolean UpdateKills;
+
+static boolean SwapFlag;
+
+static battle_type BattleOptions;
+
+specials BattleSpecialsTimes =
+{
+ 60, // god
+ 60, // dog
+ 20, // shrooms
+ 20, // elasto
+ 60, // asbestos vest
+ 60, // bullet proof vest
+ GASTICS / VBLCOUNTER, // gas mask
+ 60, // mercury mode
+
+ 300, // god respawn
+ 60, // dog respawn
+ 60, // shrooms respawn
+ 60, // elasto respawn
+ 60, // asbestos vest respawn
+ 60, // bullet proof vest respawn
+ 60, // gas mask respawn
+ 60 // mercury mode respawn
+};
+
+short WhoKilledWho[ MAXPLAYERS ][ MAXPLAYERS ];
+short BATTLE_Points[ MAXPLAYERS ];
+short BATTLE_PlayerOrder[ MAXPLAYERS ];
+short BATTLE_Team[ MAXPLAYERS ];
+short BATTLE_TeamLeader[ MAXPLAYERS ];
+int BATTLE_NumberOfTeams;
+int BATTLE_NumCollectorItems;
+int PointGoal;
+int DisplayPoints;
+int BATTLE_It;
+
+boolean BATTLE_ShowKillCount;
+
+boolean BATTLEMODE = false;
+
+/*---------------------------------------------------------------------
+ Function Prototypes:
+---------------------------------------------------------------------*/
+
+static int BATTLE_CheckKills
+(
+ battle_event reason,
+ int player
+);
+
+/*---------------------------------------------------------------------
+ Function: BATTLE_Init
+
+ Initializes the battle information.
+---------------------------------------------------------------------*/
+
+void BATTLE_Init
+(
+ int battlemode,
+ int numplayers
+)
+
+{
+ int index;
+ int index2;
+ int team;
+ int TeamNumber[ MAXPLAYERCOLORS ];
+
+#if (BATTLECHECK == 1)
+ if ( ( gamestate.teamplay ) && ( BattleMode == battle_Tag ) )
+ {
+ Error( "BATTLE_Init : Cannot play Tag in team mode.\n" );
+ }
+
+ if ( ( gamestate.teamplay ) && ( BattleMode == battle_CaptureTheTriad ) )
+ {
+ Error( "BATTLE_Init : Can only play Capture the Triad in team mode.\n" );
+ }
+#endif
+
+ Timer = 0;
+ RoundOver = false;
+
+ BattleRound = -1;
+ BATTLE_It = 0;
+
+ BattleMode = battlemode;
+
+ BATTLEMODE = false;
+
+ UpdateKills = true;
+
+ gamestate.BattleOptions.Gravity = NORMAL_GRAVITY;
+ gamestate.BattleOptions.Speed = bo_normal_speed;
+ gamestate.BattleOptions.Ammo = bo_normal_shots;
+ gamestate.BattleOptions.HitPoints = bo_character_hitpoints;
+ gamestate.BattleOptions.LightLevel = bo_light_normal;
+ gamestate.BattleOptions.Kills = bo_kills_default;
+ gamestate.BattleOptions.DangerDamage = bo_danger_normal;
+ gamestate.BattleOptions.TimeLimit = bo_time_infinite;
+ gamestate.BattleOptions.RespawnTime = bo_normal_respawn_time;
+ gamestate.BattleOptions.RandomWeapons = false;
+ gamestate.BattleOptions.FriendlyFire = true;
+ gamestate.BattleOptions.WeaponPersistence = false;
+ gamestate.BattleOptions.SpawnMines = false;
+
+ if ( BattleMode != battle_StandAloneGame )
+ {
+ BATTLEMODE = true;
+
+ if ( gamestate.Product == ROTT_SHAREWARE )
+ {
+ switch( battlemode )
+ {
+ case battle_Normal :
+ case battle_Collector :
+ case battle_Hunter :
+ break;
+
+ default :
+ Error( "Shareware version can only play Normal, Collector, "
+ "or Hunter in Comm-bat game." );
+ }
+ }
+
+ gamestate.BattleOptions.Gravity = BattleOptions.Gravity;
+ gamestate.BattleOptions.Speed = BattleOptions.Speed;
+ gamestate.BattleOptions.Ammo = BattleOptions.Ammo;
+ gamestate.BattleOptions.HitPoints = BattleOptions.HitPoints;
+ gamestate.BattleOptions.LightLevel = BattleOptions.LightLevel;
+ gamestate.BattleOptions.Kills = BattleOptions.Kills;
+ gamestate.BattleOptions.DangerDamage = BattleOptions.DangerDamage;
+ gamestate.BattleOptions.TimeLimit = BattleOptions.TimeLimit;
+ gamestate.BattleOptions.RespawnTime = BattleOptions.RespawnTime;
+ gamestate.BattleOptions.RandomWeapons = BattleOptions.RandomWeapons;
+ gamestate.BattleOptions.FriendlyFire = BattleOptions.FriendlyFire;
+ gamestate.BattleOptions.SpawnMines = BattleOptions.SpawnMines;
+ gamestate.BattleOptions.WeaponPersistence = BattleOptions.WeaponPersistence;
+ }
+
+ gamestate.ShowScores = true;
+ gamestate.BattleOptions.SpawnHealth = true;
+ gamestate.BattleOptions.SpawnWeapons = true;
+ gamestate.BattleOptions.SpawnDangers = true;
+ gamestate.SpawnCollectItems = false;
+ gamestate.SpawnEluder = false;
+ gamestate.SpawnDeluder = false;
+ gamestate.BattleOptions.RespawnItems = false;
+
+ NumberOfPlayers = numplayers;
+
+
+ BATTLE_NumberOfTeams = numplayers;
+ for( index = 0; index < MAXPLAYERS; index++ )
+ {
+ BATTLE_PlayerOrder[ index ] = index;
+ BATTLE_Points[ index ] = 0;
+ for( index2 = 0; index2 < MAXPLAYERS; index2++ )
+ {
+ WhoKilledWho[ index ][ index2 ] = 0;
+ }
+
+ BATTLE_Team[ index ] = index;
+ BATTLE_TeamLeader[ index ] = index;
+ }
+
+
+ if ( gamestate.teamplay )
+ {
+ for( index = 0; index < MAXPLAYERCOLORS; index++ )
+ {
+ TeamNumber[ index ] = -1;
+ }
+
+ BATTLE_NumberOfTeams = 0;
+
+ for( index = 0; index < numplayers; index++ )
+ {
+ team = PLAYERSTATE[ index ].uniformcolor;
+ if ( TeamNumber[ team ] == -1 )
+ {
+ TeamNumber[ team ] = BATTLE_NumberOfTeams;
+ BATTLE_TeamLeader[ BATTLE_NumberOfTeams ] = index;
+ BATTLE_NumberOfTeams++;
+ }
+ BATTLE_Team[ index ] = TeamNumber[ team ];
+ }
+ }
+
+ PointGoal = gamestate.BattleOptions.Kills;
+ if ( ( gamestate.BattleOptions.Kills == bo_kills_random ) ||
+ ( gamestate.BattleOptions.Kills == bo_kills_blind ) )
+ {
+ // Possibility of playing from 5 to 50 kills
+ PointGoal = ( GameRandomNumber( "BATTLE_Init", 0 ) % 46 ) + 5;
+ }
+
+ DisplayPoints = PointGoal;
+
+ for( index = 0; index < MAXPLAYERS; index++ )
+ {
+ gamestate.PlayerHasGun[ index ] = true;
+ }
+
+ KillsEndGame = true;
+ KeepTrackOfKills = true;
+
+ switch( BattleMode )
+ {
+ case battle_StandAloneGame :
+ KillsEndGame = false;
+ KeepTrackOfKills = false;
+ break;
+
+ case battle_Normal :
+ break;
+
+ case battle_ScoreMore :
+ break;
+
+ case battle_Collector :
+ for( index = 0; index < MAXPLAYERS; index++ )
+ {
+ gamestate.PlayerHasGun[ index ] = false;
+ }
+ KillsEndGame = false;
+ KeepTrackOfKills = false;
+ gamestate.BattleOptions.SpawnHealth = false;
+ gamestate.BattleOptions.SpawnWeapons = false;
+ gamestate.SpawnCollectItems = true;
+ break;
+
+ case battle_Scavenger :
+ KillsEndGame = false;
+ KeepTrackOfKills = false;
+ gamestate.BattleOptions.SpawnWeapons = true;
+ gamestate.BattleOptions.SpawnHealth = true;
+ gamestate.SpawnCollectItems = true;
+ break;
+
+ case battle_Hunter :
+ PointGoal *= BATTLE_NumberOfTeams;
+ KillsEndGame = false;
+ KeepTrackOfKills = true;
+ BATTLE_It = 0;
+ for( index = 0; index < NumberOfPlayers; index++ )
+ {
+ if ( BATTLE_Team[ index ] == 0 )
+ {
+ gamestate.PlayerHasGun[ index ] = false;
+ }
+ }
+ break;
+
+ case battle_Tag :
+ for( index = 0; index < MAXPLAYERS; index++ )
+ {
+ gamestate.PlayerHasGun[ index ] = false;
+ }
+
+ gamestate.BattleOptions.SpawnHealth = false;
+ gamestate.BattleOptions.SpawnWeapons = false;
+ gamestate.BattleOptions.SpawnDangers = true;
+ KeepTrackOfKills = true;
+ KillsEndGame = true;
+ break;
+
+ case battle_Eluder :
+ KeepTrackOfKills = false;
+ KillsEndGame = false;
+
+ for( index = 0; index < MAXPLAYERS; index++ )
+ {
+ gamestate.PlayerHasGun[ index ] = false;
+ }
+
+ gamestate.BattleOptions.SpawnWeapons = false;
+ gamestate.SpawnEluder = true;
+ break;
+
+ case battle_Deluder :
+ KeepTrackOfKills = false;
+ KillsEndGame = false;
+ gamestate.SpawnDeluder = true;
+ break;
+
+ case battle_CaptureTheTriad :
+ KillsEndGame = false;
+ KeepTrackOfKills = false;
+ break;
+ }
+
+ if ( BattleMode != battle_StandAloneGame )
+ {
+ if ( BattleOptions.RespawnItems )
+ {
+ gamestate.BattleOptions.RespawnItems = true;
+ }
+
+ if ( !BattleOptions.SpawnDangers )
+ {
+ gamestate.BattleOptions.SpawnDangers = false;
+ }
+
+ if ( !BattleOptions.SpawnHealth )
+ {
+ gamestate.BattleOptions.SpawnHealth = false;
+ }
+
+ if ( !BattleOptions.SpawnWeapons )
+ {
+ gamestate.BattleOptions.SpawnWeapons = false;
+ }
+
+ if ( gamestate.BattleOptions.Kills == bo_kills_blind )
+ {
+ gamestate.ShowScores = false;
+ }
+
+ GRAVITY = gamestate.BattleOptions.Gravity;
+
+ if ( gamestate.BattleOptions.Kills == bo_kills_infinite )
+ {
+ KillsEndGame = false;
+ }
+ }
+
+ BATTLE_StartRound();
+
+#if (BATTLEINFO == 1)
+ SoftError( "GRAVITY = %d\n", GRAVITY );
+ SoftError( "BO_Gravity = %d\n", BattleOptions.Gravity );
+ SoftError( "BO_Speed = %d\n", BattleOptions.Speed );
+ SoftError( "BO_Ammo = %d\n", BattleOptions.Ammo );
+ SoftError( "BO_HitPoints = %d\n", BattleOptions.HitPoints );
+ SoftError( "BO_Dangers = %d\n", BattleOptions.SpawnDangers );
+ SoftError( "BO_Health = %d\n", BattleOptions.SpawnHealth );
+ SoftError( "BO_Weapons = %d\n", BattleOptions.SpawnWeapons );
+ SoftError( "BO_Respawn = %d\n", BattleOptions.RespawnItems );
+ SoftError( "BO_Light = %d\n", BattleOptions.LightLevel );
+ SoftError( "BO_Kills = %d\n", BattleOptions.Kills );
+ SoftError( "BO_DangerDam = %d\n", BattleOptions.DangerDamage );
+ SoftError( "BO_TimeLimit = %d\n", BattleOptions.TimeLimit );
+#endif
+}
+
+
+/*---------------------------------------------------------------------
+ Function: BATTLE_GetSpecials
+
+ Set the battle special times.
+---------------------------------------------------------------------*/
+
+void BATTLE_GetSpecials
+(
+ void
+)
+
+{
+ int *src;
+ int *dest;
+
+ src = ( int * )&BattleSpecialsTimes;
+ dest = ( int * )&gamestate.SpecialsTimes;
+
+ while( src < ( int * )( &BattleSpecialsTimes + 1 ) )
+ {
+ *dest = *src * VBLCOUNTER;
+ dest++;
+ src++;
+ }
+}
+
+
+/*---------------------------------------------------------------------
+ Function: BATTLE_SetOptions
+
+ Set the battle options.
+---------------------------------------------------------------------*/
+
+void BATTLE_SetOptions
+(
+ battle_type *options
+)
+
+{
+ memcpy( &BattleOptions, options, sizeof( battle_type ) );
+}
+
+
+/*---------------------------------------------------------------------
+ Function: BATTLE_GetOptions
+
+ Returns the battle options.
+---------------------------------------------------------------------*/
+
+void BATTLE_GetOptions
+(
+ battle_type *options
+)
+
+{
+ memcpy( options, &BattleOptions, sizeof( battle_type ) );
+}
+
+
+/*---------------------------------------------------------------------
+ Function: BATTLE_Shutdown
+
+ Shutsdown the battle information.
+---------------------------------------------------------------------*/
+
+void BATTLE_Shutdown
+(
+ void
+)
+
+{
+ int index;
+ int index2;
+
+ Timer = 0;
+ RoundOver = false;
+ BattleRound = 0;
+ BattleMode = battle_StandAloneGame;
+ BATTLEMODE = false;
+ NumberOfPlayers = 1;
+ BATTLE_NumberOfTeams = 1;
+ PointGoal = 0;
+ KillsEndGame = false;
+ KeepTrackOfKills = false;
+
+ for( index = 0; index < MAXPLAYERS; index++ )
+ {
+ BATTLE_Points[ index ] = 0;
+ for( index2 = 0; index2 < MAXPLAYERS; index2++ )
+ {
+ WhoKilledWho[ index ][ index2 ] = 0;
+ }
+ gamestate.PlayerHasGun[ index ] = true;
+ }
+ gamestate.BattleOptions.SpawnHealth = true;
+ gamestate.BattleOptions.SpawnWeapons = true;
+ gamestate.BattleOptions.SpawnDangers = true;
+ gamestate.BattleOptions.RandomWeapons = false;
+ gamestate.BattleOptions.FriendlyFire = true;
+ gamestate.BattleOptions.WeaponPersistence = false;
+ gamestate.BattleOptions.SpawnMines = false;
+
+ gamestate.ShowScores = true;
+ gamestate.SpawnCollectItems = false;
+ gamestate.SpawnEluder = false;
+ gamestate.SpawnDeluder = false;
+}
+
+
+
+/*---------------------------------------------------------------------
+ Function: BATTLE_StartRound
+
+ Begins a round of battle.
+---------------------------------------------------------------------*/
+
+static battle_status BATTLE_StartRound
+(
+ void
+)
+
+{
+ int index;
+
+ Timer = 0;
+ TimeLimit = INFINITE;
+ RoundOver = false;
+
+ if ( !BATTLEMODE )
+ {
+ return( battle_no_event );
+ }
+
+ BattleRound++;
+
+ if ( gamestate.BattleOptions.TimeLimit == bo_time_infinite )
+ {
+ if ( BattleMode == battle_Hunter )
+ {
+ TimeLimit = MINUTES_TO_GAMECOUNT( 99 );
+ }
+ else
+ {
+ TimeLimit = INFINITE;
+ }
+ }
+ else
+ {
+ TimeLimit = MINUTES_TO_GAMECOUNT( gamestate.BattleOptions.TimeLimit );
+ }
+
+ if ( BattleMode == battle_Hunter )
+ {
+ for( index = 0; index < MAXPLAYERS; index++ )
+ {
+ gamestate.PlayerHasGun[ index ] = true;
+ }
+
+ if ( ( gamestate.BattleOptions.Kills != bo_kills_infinite ) &&
+ ( BattleRound >= PointGoal ) )
+ {
+ return( battle_end_game );
+ }
+
+ BATTLE_It = BattleRound % BATTLE_NumberOfTeams;
+ for( index = 0; index < NumberOfPlayers; index++ )
+ {
+ if ( BATTLE_Team[ index ] == BATTLE_It )
+ {
+ gamestate.PlayerHasGun[ index ] = false;
+ }
+ }
+ }
+
+ return( battle_no_event );
+}
+
+/*---------------------------------------------------------------------
+ Function: BATTLE_CheckGameStatus
+
+ Checks if certain battle mode conditions have been met and
+ determines the appropriate response.
+---------------------------------------------------------------------*/
+
+battle_status BATTLE_CheckGameStatus
+(
+ battle_event reason,
+ int player
+)
+
+{
+ battle_status status;
+ int team;
+
+ if ( ( player < 0 ) || ( player >= MAXPLAYERS ) )
+ {
+#if (BATTLECHECK == 1)
+ Error( "BATTLE_CheckGameStatus - reason %d : Player out of range!\n",
+ reason );
+#else
+ return( battle_no_event );
+#endif
+ }
+
+ if ( !BATTLEMODE )
+ {
+ return( battle_no_event );
+ }
+
+ team = BATTLE_Team[ player ];
+
+ status = battle_no_event;
+
+ switch( reason )
+ {
+ case battle_refresh :
+ Timer++;
+ if ( ( TimeLimit != INFINITE ) &&
+ ( Timer > TimeLimit ) )
+ {
+ RoundOver = true;
+
+ if ( BattleMode == battle_Hunter )
+ {
+ status = BATTLE_StartRound();
+ if ( status == battle_no_event )
+ {
+ status = battle_end_round;
+ }
+ }
+ else
+ {
+ status = battle_out_of_time;
+ }
+
+ UpdateKills = true;
+ }
+
+ if ( UpdateKills )
+ {
+ BATTLE_SortPlayerRanks();
+ if ( gamestate.ShowScores )
+ {
+ DrawKills (false);
+ }
+ UpdateKills = false;
+ }
+
+ if ( RoundOver )
+ {
+ return( battle_end_game );
+ }
+ break;
+
+ case battle_player_killed :
+#if (BATTLEINFO == 1)
+ SoftError( "BATTLE_CheckGameStatus: Player %d Died", player );
+ SoftError( "---ticks = %d\n", Timer );
+#endif
+
+ switch( BattleMode )
+ {
+ case battle_Normal :
+ case battle_ScoreMore :
+ case battle_Hunter :
+ if ( BattleOptions.FriendlyFire )
+ {
+ BATTLE_Points[ team ]--;
+ UpdateKills = true;
+ }
+ break;
+
+ case battle_Tag :
+ // Same as being tagged
+ if ( BattleOptions.FriendlyFire )
+ {
+ BATTLE_Points[ team ]++;
+ UpdateKills = true;
+ }
+ break;
+ }
+
+ WhoKilledWho[ player ][ player ]++;
+ break;
+
+ case battle_get_collector_item :
+
+ if ( ( BattleMode != battle_Collector ) &&
+ ( BattleMode != battle_Scavenger ) )
+ {
+#if (BATTLECHECK == 1)
+ Error( "BATTLE_CheckGameStatus : Got collector item on wrong battle mode!" );
+#else
+ return( battle_no_event );
+#endif
+ }
+ BATTLE_Points[ team ]++;
+ UpdateKills = true;
+
+ BATTLE_NumCollectorItems--;
+ if ( BATTLE_NumCollectorItems <= 0 )
+ {
+ RoundOver = true;
+ return( battle_end_game );
+ }
+ break;
+
+ case battle_caught_eluder :
+ if ( BattleMode == battle_Deluder )
+ {
+ return( battle_no_event );
+ }
+
+ if ( BattleMode != battle_Eluder )
+ {
+#if (BATTLECHECK == 1)
+ Error( "BATTLE_CheckGameStatus : Caught Eluder on non-Eluder battle mode!" );
+#else
+ return( battle_no_event );
+#endif
+ }
+
+ BATTLE_Points[ team ]++;
+ UpdateKills = true;
+
+ if ( ( gamestate.BattleOptions.Kills != bo_kills_infinite ) &&
+ ( BATTLE_Points[ team ] >= PointGoal ) )
+ {
+ RoundOver = true;
+ return( battle_end_game );
+ }
+ RespawnEluder();
+ break;
+
+ case battle_shot_deluder :
+ if ( BattleMode == battle_Eluder )
+ {
+ return( battle_no_event );
+ }
+
+ if ( BattleMode != battle_Deluder )
+ {
+#if (BATTLECHECK == 1)
+ Error( "BATTLE_CheckGameStatus : Shot Eluder on non-Eluder battle mode!" );
+#else
+ return( battle_no_event );
+#endif
+ }
+
+ BATTLE_Points[ team ]++;
+ UpdateKills = true;
+
+ if ( ( gamestate.BattleOptions.Kills != bo_kills_infinite ) &&
+ ( BATTLE_Points[ team ] >= PointGoal ) )
+ {
+ RoundOver = true;
+ return( battle_end_game );
+ }
+ RespawnEluder();
+ break;
+
+ case battle_captured_triad :
+ if ( BattleMode != battle_CaptureTheTriad )
+ {
+#if (BATTLECHECK == 1)
+ Error( "BATTLE_CheckGameStatus : Triad Captured on invalid battle mode!" );
+#else
+ return( battle_no_event );
+#endif
+ }
+
+ if ( consoleplayer == player )
+ {
+ AddMessage( "You captured a triad! You rule!", MSG_GAME );
+ }
+
+ BATTLE_Points[ team ]++;
+ UpdateKills = true;
+
+ if ( ( gamestate.BattleOptions.Kills != bo_kills_infinite ) &&
+ ( BATTLE_Points[ team ] >= PointGoal ) )
+ {
+ RoundOver = true;
+ return( battle_end_game );
+ }
+ break;
+
+ default :
+#if (BATTLECHECK == 1)
+ Error( "BATTLE_CheckGameStatus called with a reason of %d.",
+ reason );
+#else
+ return( battle_no_event );
+#endif
+ break;
+ }
+
+ return( status );
+}
+
+/*---------------------------------------------------------------------
+ Function: BATTLE_SortPlayerRanks
+
+ Sorts the players in order of score.
+---------------------------------------------------------------------*/
+
+void BATTLE_SortPlayerRanks
+(
+ void
+)
+
+{
+ int i;
+ int j;
+ int temp;
+
+ SwapFlag = false;
+
+ if ( BattleMode == battle_Tag )
+ {
+ for( i = 0; i < BATTLE_NumberOfTeams - 1; i++ )
+ {
+ for( j = i + 1; j < BATTLE_NumberOfTeams; j++ )
+ {
+ if ( BATTLE_Points[ BATTLE_PlayerOrder[ i ] ] >
+ BATTLE_Points[ BATTLE_PlayerOrder[ j ] ] )
+ {
+ SwapFlag = true;
+ temp = BATTLE_PlayerOrder[ i ];
+ BATTLE_PlayerOrder[ i ] = BATTLE_PlayerOrder[ j ];
+ BATTLE_PlayerOrder[ j ] = temp;
+ }
+ }
+ }
+ }
+ else
+ {
+ for( i = 0; i < BATTLE_NumberOfTeams - 1; i++ )
+ {
+ for( j = i + 1; j < BATTLE_NumberOfTeams; j++ )
+ {
+ if ( BATTLE_Points[ BATTLE_PlayerOrder[ i ] ] <
+ BATTLE_Points[ BATTLE_PlayerOrder[ j ] ] )
+ {
+ SwapFlag = true;
+ temp = BATTLE_PlayerOrder[ i ];
+ BATTLE_PlayerOrder[ i ] = BATTLE_PlayerOrder[ j ];
+ BATTLE_PlayerOrder[ j ] = temp;
+ }
+ }
+
+ if ( BattleMode != battle_Hunter )
+ {
+ BATTLE_It = BATTLE_PlayerOrder[ 0 ];
+ }
+ }
+ }
+
+#if (BATTLEINFO == 1)
+ for( i = 0; i < BATTLE_NumberOfTeams; i++ )
+ {
+ SoftError( "Sorted rank %d = player %d : Score = %d\n", i,
+ BATTLE_PlayerOrder[ i ], BATTLE_Points[ BATTLE_PlayerOrder[ i ] ] );
+ }
+#endif
+
+ if ( ( SwapFlag == true ) && ( gamestate.ShowScores ) &&
+ ( SHOW_TOP_STATUS_BAR() || SHOW_KILLS() ) )
+ {
+ SD_Play ( SD_ENDBONUS1SND );
+ }
+}
+
+
+/*---------------------------------------------------------------------
+ Function: BATTLE_PlayerKilledPlayer
+
+ Increases the number of kills a player has.
+---------------------------------------------------------------------*/
+
+battle_status BATTLE_PlayerKilledPlayer
+(
+ battle_event reason,
+ int killer,
+ int victim
+)
+
+{
+ int points;
+ int status;
+ int killerteam;
+ int victimteam;
+
+#if (BATTLEINFO == 1)
+ SoftError( "PlayerKilledPlayer:\nMode = %d\n", BattleMode );
+ SoftError( "Reason = %d\n", reason );
+ SoftError( "killer = %d, team = %d\n", killer, killerteam );
+ SoftError( "victim = %d, team = %d\n", victim, victimteam );
+ SoftError( "---ticks = %d\n", Timer );
+#endif
+
+ if ( ( killer < 0 ) || ( killer >= MAXPLAYERS ) )
+ {
+#if (BATTLECHECK == 1)
+ Error( "BATTLE_PlayerKilledPlayer - reason %d : Killer out of range!\n",
+ reason );
+#else
+ return( battle_no_event );
+#endif
+ }
+ if ( ( victim < 0 ) || ( victim >= MAXPLAYERS ) )
+ {
+#if (BATTLECHECK == 1)
+ Error( "BATTLE_PlayerKilledPlayer - reason %d : Victim out of range!\n",
+ reason );
+#else
+ return( battle_no_event );
+#endif
+ }
+
+ if ( ( killer == victim ) && ( reason != battle_kill_with_missile ) &&
+ ( reason != battle_kill_with_missile_in_air ) )
+ {
+#if (BATTLECHECK == 1)
+ Error( "BATTLE_PlayerKilledPlayer : Player "
+ "killed self with illegal reason of %d.", reason );
+#else
+ return( battle_no_event );
+#endif
+ }
+
+ killerteam = BATTLE_Team[ killer ];
+ victimteam = BATTLE_Team[ victim ];
+
+ if ( ( killerteam < 0 ) || ( killerteam >= BATTLE_NumberOfTeams ) ||
+ ( victimteam < 0 ) || ( victimteam >= BATTLE_NumberOfTeams ) )
+ {
+#if (BATTLECHECK == 1)
+ Error( "BATTLE_PlayerKilledPlayer - reason %d : Team out of range!\n",
+ reason );
+#else
+ return( battle_no_event );
+#endif
+ }
+
+ if ( !BATTLEMODE )
+ {
+ return( battle_no_event );
+ }
+
+ if ( ( consoleplayer == victim ) &&
+ ( reason == battle_kill_by_crushing ) )
+ {
+ AddMessage( "Oh yeah. You've been crushed.", MSG_GAME );
+ }
+
+ status = battle_no_event;
+ if ( BattleMode == battle_ScoreMore )
+ {
+ points = 0;
+ switch( reason )
+ {
+ case battle_kill_with_missile :
+ points = 1;
+ break;
+
+ case battle_kill_with_bullet :
+ points = 2;
+ break;
+
+ case battle_kill_with_missile_in_air :
+ points = 2;
+ break;
+
+ case battle_kill_with_bullet_in_air :
+ points = 3;
+ break;
+
+ case battle_kill_by_crushing :
+ points = 4;
+ break;
+
+ default :
+#if (BATTLECHECK == 1)
+ Error( "BATTLE_PlayerKilledPlayer called with a reason of %d.",
+ reason );
+#else
+ return( battle_no_event );
+#endif
+ }
+
+ if ( killerteam == victimteam )
+ {
+ if ( BattleOptions.FriendlyFire )
+ {
+ BATTLE_Points[ killerteam ]--;
+ WhoKilledWho[ killer ][ victim ]++;
+ }
+ }
+ else
+ {
+ BATTLE_Points[ killerteam ] += points;
+ WhoKilledWho[ killer ][ victim ] += points;
+ }
+ UpdateKills = true;
+ }
+ else if ( BattleMode == battle_Tag )
+ {
+ if ( reason == battle_player_tagged )
+ {
+ WhoKilledWho[ killer ][ victim ]++;
+ BATTLE_Points[ victimteam ]++;
+ UpdateKills = true;
+ BATTLE_It = victimteam;
+
+ if ( ( gamestate.BattleOptions.Kills != bo_kills_infinite ) &&
+ ( BATTLE_Points[ victimteam ] >= PointGoal ) )
+ {
+ RoundOver = true;
+ status = battle_end_game;
+ }
+ }
+#if (BATTLECHECK == 1)
+ else if ( reason != battle_kill_by_crushing )
+ {
+ Error( "BATTLE_PlayerKilledPlayer - reason %d : "
+ "Illegal reason in Tag!\n", reason );
+ }
+#endif
+
+ return( status );
+ }
+ else if ( BattleMode == battle_Hunter )
+ {
+ switch( reason )
+ {
+ case battle_kill_with_missile :
+ case battle_kill_with_bullet :
+ case battle_kill_with_missile_in_air :
+ case battle_kill_with_bullet_in_air :
+ case battle_kill_by_crushing :
+ if ( victimteam == BATTLE_It )
+ {
+ WhoKilledWho[ killer ][ victim ]++;
+ if ( killerteam == victimteam )
+ {
+ if ( BattleOptions.FriendlyFire )
+ {
+ BATTLE_Points[ killerteam ]--;
+ UpdateKills = true;
+ }
+ }
+ else
+ {
+ BATTLE_Points[ killerteam ]++;
+ UpdateKills = true;
+ }
+ }
+ break;
+ default :
+#if (BATTLECHECK == 1)
+ Error( "BATTLE_PlayerKilledPlayer called with a "
+ "reason of %d in Hunter.", reason );
+#else
+ ;
+#endif
+ }
+ }
+ else
+ {
+ switch( reason )
+ {
+ case battle_kill_with_missile :
+ case battle_kill_with_bullet :
+ case battle_kill_with_missile_in_air :
+ case battle_kill_with_bullet_in_air :
+ case battle_kill_by_crushing :
+ WhoKilledWho[ killer ][ victim ]++;
+ if ( KeepTrackOfKills )
+ {
+ if ( killerteam == victimteam )
+ {
+ if ( BattleMode == battle_Normal )
+ {
+ if ( BattleOptions.FriendlyFire )
+ {
+ BATTLE_Points[ killerteam ]--;
+ UpdateKills = true;
+ }
+ }
+ }
+ else
+ {
+ BATTLE_Points[ killerteam ]++;
+ UpdateKills = true;
+ }
+ }
+ break;
+
+ default :
+#if (BATTLECHECK == 1)
+ Error( "BATTLE_PlayerKilledPlayer called with a reason of %d.",
+ reason );
+#else
+ return( battle_no_event );
+#endif
+ }
+ }
+
+ if ( ( KillsEndGame ) && ( BATTLE_Points[ killerteam ] >= PointGoal ) )
+ {
+ RoundOver = true;
+ status = battle_end_game;
+ }
+
+ return( status );
+}
--- /dev/null
+++ b/rott/rt_battl.h
@@ -1,0 +1,224 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: RT_BATTL.H
+
+ author: James R. Dose
+ phone: (214)-271-1365 Ext #221
+ date: September 8, 1994
+
+ Public header for RT_BATTL.C
+
+ (c) Copyright 1994 Apogee Software. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __RT_BATTLE_public
+#define __RT_BATTLE_public
+
+
+#define BIT_MASK( bit_number ) ( 1 << ( bit_number ) )
+#define MINUTES_TO_GAMECOUNT( minutes ) \
+ ( ( minutes ) * 60 * VBLCOUNTER )
+
+//
+// Return codes
+//
+
+typedef enum
+{
+ battle_no_event,
+ battle_end_game,
+ battle_end_round,
+ battle_out_of_time
+} battle_status;
+
+//
+// Types of battle events
+//
+
+typedef enum
+{
+ battle_refresh,
+ battle_player_killed,
+ battle_player_tagged,
+ battle_kill_with_missile,
+ battle_kill_with_bullet,
+ battle_kill_with_missile_in_air,
+ battle_kill_with_bullet_in_air,
+ battle_kill_by_crushing,
+ battle_get_collector_item,
+ battle_caught_eluder,
+ battle_shot_deluder,
+ battle_captured_triad
+} battle_event;
+
+//
+// Battle modes
+//
+
+enum
+{
+ battle_StandAloneGame,
+ battle_Normal,
+ battle_ScoreMore,
+ battle_Collector,
+ battle_Scavenger,
+ battle_Hunter,
+ battle_Tag,
+ battle_Eluder,
+ battle_Deluder,
+ battle_CaptureTheTriad,
+ battle_NumBattleModes
+};
+
+//
+// Battle mode option : Gravity
+//
+
+//enum
+// {
+// bo_low_gravity,
+// bo_normal_gravity,
+// bo_high_gravity
+// };
+
+//
+// Battle mode option : Speed
+//
+
+enum
+{
+ bo_normal_speed,
+ bo_fast_speed
+};
+
+//
+// Battle mode option : Ammo
+//
+
+enum
+{
+ bo_one_shot,
+ bo_normal_shots,
+ bo_infinite_shots
+};
+
+//
+// Battle mode option : Hit points
+//
+
+#define bo_character_hitpoints 0
+#define bo_default_hitpoints 250
+
+//
+// Battle mode option : Light levels
+//
+
+enum
+{
+ bo_light_dark,
+ bo_light_normal,
+ bo_light_bright,
+ bo_light_fog,
+ bo_light_periodic,
+ bo_light_lightning
+};
+
+//
+// Battle mode option : Number of kills
+//
+
+enum
+{
+ bo_kills_random = -2,
+ bo_kills_blind = -1,
+ bo_kills_infinite = 0,
+ bo_kills_default = 21
+};
+
+//
+// Battle mode option : Environment danger damage
+//
+
+enum
+{
+ bo_danger_normal = -1,
+ bo_danger_low = 1,
+ bo_danger_kill = 30000
+};
+
+//
+// Battle mode option : Time limit
+//
+#define bo_time_infinite 0
+
+//
+// Battle mode configuration
+//
+typedef struct
+{
+ unsigned Gravity;
+ unsigned Speed;
+ unsigned Ammo;
+ unsigned HitPoints;
+ unsigned SpawnDangers;
+ unsigned SpawnHealth;
+ unsigned SpawnWeapons;
+ unsigned SpawnMines;
+ unsigned RespawnItems;
+ unsigned WeaponPersistence;
+ unsigned RandomWeapons;
+ unsigned FriendlyFire;
+ unsigned LightLevel;
+ int Kills;
+ int DangerDamage;
+ unsigned TimeLimit;
+ unsigned RespawnTime;
+} battle_type;
+
+#define bo_normal_respawn_time 30
+
+extern boolean BATTLEMODE;
+extern short WhoKilledWho[ MAXPLAYERS ][ MAXPLAYERS ];
+extern short BATTLE_Points[ MAXPLAYERS ];
+extern short BATTLE_PlayerOrder[ MAXPLAYERS ];
+extern int BATTLE_NumCollectorItems;
+extern int PointGoal;
+extern int DisplayPoints;
+extern int BATTLE_It;
+extern boolean BATTLE_ShowKillCount;
+extern short BATTLE_Team[ MAXPLAYERS ];
+extern short BATTLE_TeamLeader[ MAXPLAYERS ];
+extern int BATTLE_NumberOfTeams;
+extern boolean UpdateKills;
+
+// Located in RT_MENU.C
+extern battle_type BATTLE_Options[ battle_NumBattleModes ];
+
+void BATTLE_Init( int battlemode, int numplayers );
+void BATTLE_GetSpecials( void );
+void BATTLE_SetOptions( battle_type *options );
+void BATTLE_GetOptions( battle_type *options );
+battle_status BATTLE_CheckGameStatus( battle_event reason, int player );
+void BATTLE_SortPlayerRanks( void );
+battle_status BATTLE_PlayerKilledPlayer( battle_event reason, int killer, int victim );
+void BATTLE_Shutdown( void );
+
+#endif
--- /dev/null
+++ b/rott/rt_build.c
@@ -1,0 +1,1572 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// RT_BUILD.C
+
+#include "rt_def.h"
+#include <string.h>
+#include "watcom.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef DOS
+#include <dos.h>
+#include <conio.h>
+#endif
+
+#include "rt_build.h"
+#include "_rt_buil.h"
+#include "rt_dr_a.h"
+#include "rt_draw.h"
+#include "rt_scale.h"
+#include "rt_menu.h"
+#include "rt_main.h"
+#include "isr.h"
+#include "rt_util.h"
+#include "engine.h"
+#include "lumpy.h"
+#include "rt_fc_a.h"
+#include "z_zone.h"
+#include "w_wad.h"
+#include "rt_view.h"
+#include "rt_cfg.h"
+#include "rt_vid.h"
+
+#include "rt_sound.h"
+#include "modexlib.h"
+#include "rt_str.h"
+//MED
+#include "memcheck.h"
+
+byte * intensitytable;
+
+
+// LOCAL VARIABLES
+
+static byte * menubuf;
+static byte * menubuffers[2];
+static char menutitles[2][40];
+static int alternatemenubuf=0;
+static int titleshade=16;
+static int titleshadedir=1;
+static int titleyoffset=0;
+static char titlestring[40]="\0";
+static int readytoflip;
+static boolean MenuBufStarted=false;
+static int mindist=0x2700;
+static boolean BackgroundDrawn=false;
+
+static plane_t planelist[MAXPLANES],*planeptr;
+
+static int StringShade=16;
+
+extern void (*USL_MeasureString)(const char *, int *, int *, font_t *);
+
+static char strbuf[MaxString];
+
+//******************************************************************************
+//
+// DrawRotPost
+//
+//******************************************************************************
+
+void DrawRotPost ( int height, byte * src, byte * buf, int origheight)
+{
+ int y1;
+ int y2;
+
+ hp_srcstep=(origheight<<18)/height;
+ y1 = (((centery<<8)-(height<<5)+(MENUOFFY<<8)));
+ y2 = (((height<<6)+y1)>>8);
+
+ if (((y1>>8)>=200) || (y2<0))
+ return;
+ if (y1<0)
+ {
+ hp_startfrac=FixedMulShift(-y1,hp_srcstep,8);
+ y2 = (((height<<6)+y1)>>8);
+ y1=0;
+ }
+ else
+ {
+ hp_startfrac=FixedMulShift(255-(y1&0xff),hp_srcstep,8);
+ y1>>=8;
+ }
+ if (y2>200)
+ {
+ DrawMenuPost(200-y1, src, buf+ylookup[y1]);
+ }
+ else
+ {
+ DrawMenuPost(y2-y1, src, buf+ylookup[y1]);
+ }
+}
+
+
+
+/*
+========================
+=
+= GetPoint
+=
+========================
+*/
+
+void GetPoint (int x1, int y1, int px, int py, int * screenx, int * height, int angle)
+{
+
+ fixed gxt,gyt,nx,ny;
+ fixed gxtt,gytt;
+ int gx,gy;
+
+
+//
+// translate point to view centered coordinates
+//
+ gx = x1-px;
+ gy = y1-py;
+
+//
+// calculate newx
+//
+ gxt = FixedMul(gx,costable[angle]);
+ gyt = FixedMul(gy,sintable[angle]);
+ nx =gxt-gyt;
+
+ if (nx<mindist)
+ nx=mindist;
+
+
+//
+// calculate newy
+//
+ gxtt = FixedMul(gx,sintable[angle]);
+ gytt = FixedMul(gy,costable[angle]);
+ ny = gytt+gxtt;
+
+// too close, don't overflow the divid'
+
+
+ *screenx = 160 + ((ny*NORMALWIDTHMULTIPLIER)/nx); // DEBUG: use assembly divide
+
+ *height = NORMALHEIGHTDIVISOR/nx;
+
+ if (*screenx<0) *screenx=0;
+
+}
+
+
+/*
+========================
+=
+= InterpolatePlane
+=
+========================
+*/
+
+void InterpolatePlane (visobj_t * plane)
+{
+ int d1,d2;
+ int top;
+ int topinc;
+ int bot;
+ int botinc;
+ int i;
+ int texture;
+ int dh;
+ int dx;
+ int height;
+
+
+ dx=(plane->x2-plane->x1+1);
+ if (plane->h1<=0 || plane->h2<=0 || (dx==0))
+ return;
+ d1=65536/plane->h1;
+ d2=65536/plane->h2;
+ dh=((plane->h2-plane->h1)<<8)/dx;
+ top=0;
+ topinc=(d1)*((plane->textureend-plane->texturestart)>>4);
+ bot=d2*dx;
+ botinc=d1-d2;
+ height=(plane->h1<<8);
+ if (plane->x1>=viewwidth)
+ return;
+ for (i=plane->x1; i<=plane->x2; i++)
+ {
+ if ((i>=0 && i<viewwidth)&&(posts[i].wallheight<(height>>8)))
+ {
+ if (bot)
+ {
+ texture=((top/bot)+(plane->texturestart>>4))>>6;
+ posts[i].texture=texture*plane->viewx;
+ posts[i].lump=plane->shapenum;
+ posts[i].wallheight=(height>>8);
+ posts[i].offset=plane->viewx;
+ }
+ }
+ top+=topinc;
+ bot+=botinc;
+ height+=dh;
+ }
+}
+
+//******************************************************************************
+//
+// DrawPlanePosts
+//
+//******************************************************************************
+
+void DrawPlanePosts (void)
+{
+ int height;
+ char * buf;
+ byte * shape;
+ int lastwall=-2;
+ int plane;
+ int i;
+
+ shadingtable=colormap+(16<<8);
+
+#ifdef DOS
+ for (plane=0; plane<4; plane++)
+#endif
+
+ {
+ VGAWRITEMAP(plane);
+ buf=(byte *)(bufferofs);
+
+#ifdef DOS
+ for (i=plane; i<viewwidth; i+=4,buf++)
+#else
+ for (i=0; i<viewwidth; i++,buf++)
+#endif
+ {
+ height=(posts[i].wallheight);
+ if (height<=4)
+ continue;
+ if (lastwall!=posts[i].lump)
+ {
+ lastwall=posts[i].lump;
+ if (lastwall==-1)
+ shape=menubuf;
+ else
+ shape=W_CacheLumpNum(lastwall,PU_CACHE, Cvt_patch_t, 1);
+ }
+ DrawRotPost (height,shape+posts[i].texture,buf,posts[i].offset);
+ }
+ }
+}
+
+//******************************************************************************
+//
+// NextPlaneptr
+//
+//******************************************************************************
+
+void NextPlaneptr ( void )
+{
+ if (planeptr < &planelist[MAXPLANES-1]) // don't let it overflo'
+ planeptr++;
+}
+
+//******************************************************************************
+//
+// RestPlaneptr
+//
+//******************************************************************************
+
+void ResetPlaneptr ( void )
+{
+ planeptr = &planelist[0];
+}
+
+//******************************************************************************
+//
+// NextVisptr
+//
+//******************************************************************************
+
+void NextVisptr ( void )
+{
+ if (visptr < &vislist[MAXVISIBLE-1]) // don't let it overflo'
+ visptr++;
+}
+
+//******************************************************************************
+//
+// ResetVisptr
+//
+//******************************************************************************
+
+void ResetVisptr ( void )
+{
+ visptr = &vislist[0];
+}
+
+//******************************************************************************
+//
+// SetupPlanes
+//
+//******************************************************************************
+
+void SetupPlanes ( void )
+{
+ int i;
+
+ for (i=0; i<320; i++)
+ posts[i].wallheight=-1;
+}
+
+
+
+//******************************************************************************
+//
+// CalcPlanes
+//
+//******************************************************************************
+
+void CalcPlanes ( int px, int py, int angle )
+{
+ plane_t * pptr;
+
+ ResetVisptr();
+ for (pptr = &planelist[0]; pptr<planeptr; pptr++)
+ {
+ if (SideOfLine(pptr->x1,pptr->y1,pptr->x2,pptr->y2,px,py)<0)
+ {
+ GetPoint (pptr->x1,pptr->y1,px,py,&visptr->x1,&visptr->h1,angle);
+ GetPoint (pptr->x2,pptr->y2,px,py,&visptr->x2,&visptr->h2,angle);
+ visptr->textureend=0x0;
+ visptr->texturestart=pptr->texturewidth;
+ }
+ else
+ {
+ GetPoint (pptr->x2,pptr->y2,px,py,&visptr->x1,&visptr->h1,angle);
+ GetPoint (pptr->x1,pptr->y1,px,py,&visptr->x2,&visptr->h2,angle);
+ visptr->texturestart=0x0;
+ visptr->textureend=pptr->texturewidth;
+ }
+ visptr->shapenum=pptr->texture;
+ visptr->viewx=pptr->origheight;
+ visptr->viewheight=MAX(visptr->h1,visptr->h2);
+ NextVisptr();
+ }
+}
+
+
+//******************************************************************************
+//
+// DrawTransformedPlanes
+//
+//******************************************************************************
+
+void DrawTransformedPlanes ( void )
+{
+ int numvisible;
+ int greatest;
+ int height;
+ int i;
+ visobj_t * closest;
+
+ numvisible = visptr-&vislist[0];
+ if (!numvisible)
+ return; // no visible objects
+ for (i = 0; i<numvisible; i++)
+ {
+ greatest = 0;
+ for (visstep=&vislist[0] ; visstep<visptr ; visstep++)
+ {
+ height = visstep->viewheight;
+ if (height > greatest)
+ {
+ greatest = height;
+ closest = visstep;
+ }
+ }
+ InterpolatePlane(closest);
+ closest->viewheight = 0;
+ }
+}
+
+
+//******************************************************************************
+//
+// ClearMenuBuf
+//
+//******************************************************************************
+
+void ClearMenuBuf ( void )
+{
+ byte * shape;
+
+ if (MenuBufStarted==false)
+ Error("Called ClearMenuBuf without menubuf started\n");
+
+ shape=W_CacheLumpName(MENUBACKNAME,PU_CACHE, Cvt_patch_t, 1);
+ shape+=8;
+ memcpy (menubuf,shape,TEXTUREW*TEXTUREHEIGHT);
+}
+
+//******************************************************************************
+//
+// ShutdownMenuBuf
+//
+//******************************************************************************
+
+void ShutdownMenuBuf ( void )
+{
+ if (MenuBufStarted==false)
+ return;
+ MenuBufStarted=false;
+ SafeFree(menubuffers[0]);
+ SafeFree(menubuffers[1]);
+ if (loadedgame==false)
+ SetViewSize(viewsize);
+}
+
+//******************************************************************************
+//
+// SetupMenuBuf
+//
+//******************************************************************************
+
+void SetupMenuBuf ( void )
+{
+#define SRCH 148
+#define SRCW 258
+#define PLANEX1 (-0x24000)
+#define PLANEX2 (0x23fff)
+#define PLANEW (16<<10)
+#define PLANEY (0x40000)
+#define PLANEW2 (0x5a827)
+
+ if (MenuBufStarted==true)
+ return;
+ MenuBufStarted=true;
+
+ // No top offsets like in game
+
+ centery=100;
+ centeryfrac=centery<<16;
+
+ strcpy(titlestring,menutitles[0]);
+
+ screenofs=0;
+ viewwidth=320;
+ viewheight=200;
+
+ alternatemenubuf=0;
+
+ ResetPlaneptr();
+ planeptr->texture=-1;
+ planeptr->y1=PLANEX1;
+ planeptr->x1=PLANEW;
+ planeptr->y2=PLANEX2;
+ planeptr->x2=PLANEW;
+ planeptr->origheight=TEXTUREHEIGHT;
+ planeptr->texturewidth=TEXTUREWIDTH;
+ NextPlaneptr();
+ planeptr->texture=-1;
+ planeptr->y1=PLANEX1;
+ planeptr->x1=-PLANEW;
+ planeptr->y2=PLANEX2;
+ planeptr->x2=-PLANEW;
+ planeptr->origheight=TEXTUREHEIGHT;
+ planeptr->texturewidth=TEXTUREWIDTH;
+ NextPlaneptr();
+ planeptr->texture=W_GetNumForName(MENUBACKNAME);
+ planeptr->y1=PLANEX1;
+ planeptr->x1=PLANEW;
+ planeptr->y2=PLANEX1;
+ planeptr->x2=-PLANEW;
+ planeptr->origheight=TEXTUREHEIGHT;
+ planeptr->texturewidth=TEXTUREWIDTH;
+ NextPlaneptr();
+ planeptr->texture=W_GetNumForName(MENUBACKNAME);
+ planeptr->y1=PLANEX2;
+ planeptr->x1=PLANEW;
+ planeptr->y2=PLANEX2;
+ planeptr->x2=-PLANEW;
+ planeptr->origheight=TEXTUREHEIGHT;
+ planeptr->texturewidth=TEXTUREWIDTH;
+ NextPlaneptr();
+
+ menubuffers[0]=SafeMalloc(TEXTUREW*TEXTUREHEIGHT);
+ menubuffers[1]=SafeMalloc(TEXTUREW*TEXTUREHEIGHT);
+ menubuf=menubuffers[0];
+ ClearMenuBuf();
+ BackgroundDrawn=false;
+}
+
+
+//******************************************************************************
+//
+// PositionMenuBuf
+//
+//******************************************************************************
+
+void PositionMenuBuf( int angle, int distance, boolean drawbackground )
+{
+ int px,py;
+ font_t * oldfont;
+ int width,height;
+
+
+ if (MenuBufStarted==false)
+ Error("Called PositionMenuBuf without menubuf started\n");
+ CalcTics();
+ SetupPlanes();
+ if ((drawbackground==true) || (BackgroundDrawn==false))
+ {
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ }
+ px=FixedMulShift(distance,costable[angle&(FINEANGLES-1)],16);
+ py=FixedMulShift(-distance,sintable[angle&(FINEANGLES-1)],16);
+ CalcPlanes(px,py,(angle+ANG180)&(FINEANGLES-1));
+ DrawTransformedPlanes();
+ DrawPlanePosts();
+ oldfont=CurrentFont;
+ CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_CACHE, Cvt_font_t, 1);
+ US_MeasureStr (&width, &height, "%s", titlestring);
+ US_ClippedPrint ((320-width)>>1, MENUTITLEY-titleyoffset, titlestring);
+ CurrentFont=oldfont;
+ FlipPage();
+ titleshade+=titleshadedir;
+ if (abs(titleshade-16)>6)
+ titleshadedir=-titleshadedir;
+ if (BackgroundDrawn==false)
+ {
+ VL_CopyDisplayToHidden();
+ BackgroundDrawn=true;
+ }
+}
+
+//******************************************************************************
+//
+// RefreshMenuBuf
+//
+//******************************************************************************
+
+void RefreshMenuBuf( int time )
+{
+ int i;
+
+ if (MenuBufStarted==false)
+ Error("Called RefreshMenuBuf without menubuf started\n");
+
+ if (readytoflip)
+ return;
+
+ for (i=0; i<=time; i+=tics)
+ {
+ //PositionMenuBuf (0,NORMALVIEW,false);
+ PositionMenuBuf (0,NORMALVIEW,true);//bna++ in not true bg in menu is no redrawn
+ }
+}
+
+//******************************************************************************
+//
+// ScaleMenuBufPost
+//
+//******************************************************************************
+
+void ScaleMenuBufPost (byte * src, int topoffset, byte * buf)
+{
+ int d;
+ int offset;
+ int length;
+ int s;
+
+
+ while (1)
+ {
+ offset=*(src++);
+ if (offset==0xff)
+ return;
+ else
+ {
+ d=offset-topoffset;
+ length=*(src++);
+ for (s=0; s<length; s++,d++)
+ *(buf+d)=*(src+s);
+ src+=length;
+ }
+ }
+}
+
+//******************************************************************************
+//
+// SetAlternateMenuBuf
+//
+//******************************************************************************
+
+void SetAlternateMenuBuf ( void )
+{
+ if (MenuBufStarted==false)
+ Error("Called SetAlternateMenuBuf without menubuf started\n");
+
+ alternatemenubuf^=1;
+ readytoflip=1;
+ menubuf=menubuffers[alternatemenubuf];
+}
+
+//******************************************************************************
+//
+// SetMenuTitle
+//
+//******************************************************************************
+
+void SetMenuTitle ( const char * menutitle )
+{
+ if (MenuBufStarted==false)
+ Error("Called SetMenuTitle without menubuf started\n");
+ strcpy(menutitles[alternatemenubuf],menutitle);
+ if (readytoflip==0)
+ strcpy(titlestring,menutitle);
+}
+
+//******************************************************************************
+//
+// DrawMenuBufPicture
+//
+//******************************************************************************
+
+void DrawMenuBufPicture (int x, int y, const byte * pic, int w, int h)
+{
+ byte *buffer;
+ int i;
+
+ if (MenuBufStarted==false)
+ Error("Called DrawMenuBufPictoure without menubuf started\n");
+
+ if ((x<0) || (x+w>=TEXTUREW))
+ Error ("DrawMenuBufPicture: x is out of range\n");
+ if ((y<0) || (y+h>=TEXTUREHEIGHT))
+ Error ("DrawMenuBufPicture: y is out of range\n");
+
+ for (i=0; i<w; i++)
+ {
+ buffer = (byte*)menubuf+y+((x+i)*TEXTUREHEIGHT);
+ memcpy(buffer,pic,h);
+ pic+=h;
+ }
+}
+
+//******************************************************************************
+//
+// DrawMenuBufItem
+//
+//******************************************************************************
+
+void DrawMenuBufItem (int x, int y, int shapenum)
+{
+ byte *buffer;
+ int cnt;
+ byte *shape;
+ patch_t *p;
+
+ if (MenuBufStarted==false)
+ Error("Called DrawMenuBufItem without menubuf started\n");
+
+ shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_patch_t, 1);
+ p = (patch_t *)shape;
+
+ if (((x-p->leftoffset)<0) || ((x-p->leftoffset+p->width)>=TEXTUREW))
+ Error ("DrawMenuBufItem: x is out of range\n");
+ if (((y-p->topoffset)<0) || ((y-p->topoffset+p->height)>=TEXTUREHEIGHT))
+ Error ("DrawMenuBufItem: y is out of range\n");
+
+ buffer = (byte*)menubuf+y+((x-p->leftoffset)*TEXTUREHEIGHT);
+
+ for (cnt = 0; cnt < p->width; cnt++,buffer+=TEXTUREHEIGHT)
+ ScaleMenuBufPost ((byte *)(p->collumnofs[cnt]+shape),
+ p->topoffset, buffer);
+}
+
+//******************************************************************************
+//
+// IScaleMenuBufPost
+//
+//******************************************************************************
+
+void IScaleMenuBufPost (byte * src, int topoffset, byte * buf, int color)
+{
+ int d;
+ int offset;
+ int length;
+ int s;
+
+
+ while (1)
+ {
+ offset=*(src++);
+ if (offset==0xff)
+ return;
+ else
+ {
+ d=offset-topoffset;
+ length=*(src++);
+ for (s=0; s<length; s++,d++)
+ *(buf+d)=*(intensitytable+((*(src+s))<<8)+color);
+ src+=length;
+ }
+ }
+}
+
+
+//******************************************************************************
+//
+// DrawIMenuBufItem
+//
+//******************************************************************************
+
+void DrawIMenuBufItem (int x, int y, int shapenum, int color)
+{
+ byte *buffer;
+ int cnt;
+ byte *shape;
+ patch_t *p;
+
+
+ if (MenuBufStarted==false)
+ Error("Called DrawIMenuBufItem without menubuf started\n");
+
+ shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_patch_t, 1);
+ p = (patch_t *)shape;
+
+ if (((x-p->leftoffset)<0) || ((x-p->leftoffset+p->width)>=TEXTUREW))
+ Error ("DrawIMenuBufItem: x is out of range\n");
+ if (((y-p->topoffset)<0) || ((y-p->topoffset+p->height)>=TEXTUREHEIGHT))
+ Error ("DrawIMenuBufItem: y is out of range\n");
+
+ buffer = (byte*)menubuf+y+((x-p->leftoffset)*TEXTUREHEIGHT);
+
+ for (cnt = 0; cnt < p->width; cnt++,buffer+=TEXTUREHEIGHT)
+ IScaleMenuBufPost ((byte *)(p->collumnofs[cnt]+shape),
+ p->topoffset, buffer, color);
+}
+
+
+//******************************************************************************
+//
+// TScaleMenuBufPost
+//
+//******************************************************************************
+void TScaleMenuBufPost (byte * src, int topoffset, byte * buf)
+{
+ int d;
+ int offset;
+ int length;
+ byte pixel;
+ int s;
+
+
+ while (1)
+ {
+ offset=*(src++);
+ if (offset==0xff)
+ return;
+ else
+ {
+ d=offset-topoffset;
+ length=*(src++);
+ for (s=0; s<length; s++,d++)
+ {
+ pixel = *(buf+d);
+ pixel = *(shadingtable+pixel);
+ *(buf+d) = pixel;
+ }
+ src+=length;
+ }
+ }
+}
+
+
+//******************************************************************************
+//
+// CScaleMenuBufPost
+//
+//******************************************************************************
+void CScaleMenuBufPost (byte * src, int topoffset, byte * buf)
+{
+ int d;
+ int offset;
+ int length;
+ byte pixel;
+ int s;
+
+
+ while (1)
+ {
+ offset=*(src++);
+ if (offset==0xff)
+ return;
+ else
+ {
+ d=offset-topoffset;
+ length=*(src++);
+ for (s=0; s<length; s++,d++)
+ {
+ pixel = *(src+s);
+ pixel = *(shadingtable+pixel);
+ *(buf+d) = pixel;
+ }
+ src+=length;
+ }
+ }
+}
+
+
+//******************************************************************************
+//
+// EraseMenuBufRegion
+//
+//******************************************************************************
+
+void EraseMenuBufRegion (int x, int y, int width, int height)
+{
+ byte *buffer;
+ int xx,yy;
+ byte * shape;
+
+ if (MenuBufStarted==false)
+ Error("Called EraseMenuBufRegion without menubuf started\n");
+
+ if ((x<0) || (x+width>=TEXTUREW))
+ Error ("EraseMenuBufRegion: x is out of range\n");
+ if ((y<0) || (y+height>=TEXTUREHEIGHT))
+ Error ("EraseMenuBufRegion: y is out of range\n");
+
+ shape=W_CacheLumpName(MENUBACKNAME,PU_CACHE, Cvt_patch_t, 1);
+ shape+=8;
+ shape+=(x*TEXTUREHEIGHT)+y;
+ buffer = (byte*)menubuf+(x*TEXTUREHEIGHT)+y;
+
+ for (xx = 0; xx < width; xx++)
+ {
+ for (yy = 0; yy < height; yy++)
+ *(buffer+yy)=*(shape+yy);
+ buffer+=TEXTUREHEIGHT;
+ shape+=TEXTUREHEIGHT;
+ }
+}
+
+
+//******************************************************************************
+//
+// DrawTMenuBufPic
+//
+//******************************************************************************
+
+void DrawTMenuBufPic (int x, int y, int shapenum)
+{
+ byte *buffer;
+ byte *buf;
+ int xx,yy;
+ int plane;
+ int pixel;
+ byte *shape;
+ byte *src;
+ pic_t *p;
+
+ if (MenuBufStarted==false)
+ Error("Called DrawTMenuBufPic without menubuf started\n");
+
+ shadingtable=colormap+(25<<8);
+
+ shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_pic_t, 1);
+ p = (pic_t *)shape;
+
+ if ((x<0) || ((x+(p->width<<2))>=TEXTUREW))
+ Error ("DrawTMenuBufPic: x is out of range\n");
+ if ((y<0) || ((y+p->height)>=TEXTUREHEIGHT))
+ Error ("DrawTMenuBufPic: y is out of range\n");
+
+ buffer = (byte*)menubuf+(x*TEXTUREHEIGHT)+y;
+
+ src=(byte *)&p->data;
+ for (plane=0; plane<4; plane++,buffer+=TEXTUREHEIGHT)
+ {
+ for (yy = 0; yy < p->height; yy++)
+ {
+ buf=buffer+yy;
+ for (xx = 0; xx < p->width; xx++,buf+=TEXTUREHEIGHT<<2)
+ {
+ pixel = *(buf);
+ pixel = *(shadingtable+pixel);
+ *(buf) = pixel;
+ }
+ }
+ }
+}
+
+
+//******************************************************************************
+//
+// DrawTMenuBufItem
+//
+//******************************************************************************
+
+void DrawTMenuBufItem (int x, int y, int shapenum)
+{
+ byte *buffer;
+ int cnt;
+ byte *shape;
+ patch_t *p;
+
+
+ if (MenuBufStarted==false)
+ Error("Called DrawTMenuBufItem without menubuf started\n");
+
+ shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_patch_t, 1);
+ p = (patch_t *)shape;
+
+ shadingtable=colormap+(25<<8);
+
+ if (((x-p->leftoffset)<0) || ((x-p->leftoffset+p->width)>=TEXTUREW))
+ Error ("DrawTMenuBufItem: x is out of range\n");
+ if (((y-p->topoffset)<0) || ((y-p->topoffset+p->height)>=TEXTUREHEIGHT))
+ Error ("DrawTMenuBufItem: y is out of range\n");
+
+ buffer = (byte*)menubuf+y+((x-p->leftoffset)*TEXTUREHEIGHT);
+
+ for (cnt = 0; cnt < p->width; cnt++,buffer+=TEXTUREHEIGHT)
+ TScaleMenuBufPost ((byte *)(p->collumnofs[cnt]+shape),
+ p->topoffset, buffer);
+}
+
+//******************************************************************************
+//
+// DrawColoredMenuBufItem
+//
+//******************************************************************************
+
+void DrawColoredMenuBufItem (int x, int y, int shapenum, int color)
+{
+ byte *buffer;
+ int cnt;
+ byte *shape;
+ patch_t *p;
+
+
+ if (MenuBufStarted==false)
+ Error("Called DrawColoredMenuBufItem without menubuf started\n");
+
+ shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_patch_t, 1);
+ p = (patch_t *)shape;
+
+ shadingtable=playermaps[color]+(16<<8);
+
+ if (((x-p->leftoffset)<0) || ((x-p->leftoffset+p->width)>=TEXTUREW))
+ Error ("DrawColoredMenuBufItem: x is out of range\n");
+ if (((y-p->topoffset)<0) || ((y-p->topoffset+p->height)>=TEXTUREHEIGHT))
+ Error ("DrawColoredMenuBufItem: y is out of range\n");
+
+ buffer = (byte*)menubuf+y+((x-p->leftoffset)*TEXTUREHEIGHT);
+
+ for (cnt = 0; cnt < p->width; cnt++,buffer+=TEXTUREHEIGHT)
+ CScaleMenuBufPost ((byte *)(p->collumnofs[cnt]+shape),
+ p->topoffset, buffer);
+}
+
+//******************************************************************************
+//
+// DrawMenuBufPic
+//
+//******************************************************************************
+
+void DrawMenuBufPic (int x, int y, int shapenum)
+{
+ byte *buffer;
+ byte *buf;
+ int xx,yy;
+ int plane;
+ byte *shape;
+ byte *src;
+ pic_t *p;
+
+ if (MenuBufStarted==false)
+ Error("Called DrawMenuBufPic without menubuf started\n");
+
+ shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_pic_t, 1);
+ p = (pic_t *)shape;
+
+ if ((x<0) || ((x+(p->width<<2))>=TEXTUREW))
+ Error ("DrawTMenuBufPic: x is out of range\n");
+ if ((y<0) || ((y+p->height)>=TEXTUREHEIGHT))
+ Error ("DrawTMenuBufPic: y is out of range\n");
+
+
+ buffer = (byte*)menubuf+(x*TEXTUREHEIGHT)+y;
+
+ src=(byte *)&p->data;
+ for (plane=0; plane<4; plane++,buffer+=TEXTUREHEIGHT)
+ {
+ for (yy = 0; yy < p->height; yy++)
+ {
+ buf=buffer+yy;
+ for (xx = 0; xx < p->width; xx++,buf+=TEXTUREHEIGHT<<2)
+ *(buf)=*(src++);
+ }
+ }
+}
+
+
+
+
+//******************************************************************************
+//
+// DrawTMenuBufBox
+//
+//******************************************************************************
+
+
+void DrawTMenuBufBox ( int x, int y, int width, int height )
+{
+ byte *buffer;
+ int xx;
+ int yy;
+ int pixel;
+
+ if (MenuBufStarted==false)
+ Error("Called DrawTMenuBufBox without menubuf started\n");
+
+ shadingtable = colormap + ( 25 << 8 );
+
+ if ( ( x < 0 ) || ( ( x + width ) >= TEXTUREW ) )
+ Error ("DrawTMenuBar : x is out of range\n");
+ if ( ( y < 0 ) || ( y + height ) >= TEXTUREHEIGHT )
+ Error ("DrawTMenuBar : y is out of range\n");
+
+ buffer = ( byte * )menubuf + ( x * TEXTUREHEIGHT ) + y;
+
+ for ( xx = 0; xx < width; xx++ )
+ {
+ for ( yy = 0; yy < height; yy++ )
+ {
+ pixel = *( buffer + yy );
+ pixel = *( shadingtable + pixel );
+ *( buffer + yy ) = pixel;
+ }
+
+ buffer += TEXTUREHEIGHT;
+ }
+}
+
+
+//******************************************************************************
+//
+// DrawTMenuBufHLine
+//
+//******************************************************************************
+
+void DrawTMenuBufHLine (int x, int y, int width, boolean up)
+{
+ byte *buffer;
+ byte *buf;
+ int xx;
+ int plane;
+ int pixel;
+ int w = width>>2;
+ int ww = w;
+
+ if ((x<0) || ((x+(width))>=TEXTUREW))
+ Error ("DrawTMenuBufBox: x is out of range\n");
+ if (y<0)
+ Error ("DrawTMenuBufBox: y is out of range\n");
+
+ buffer = (byte*)menubuf+(x*TEXTUREHEIGHT)+y;
+
+ if (up)
+ shadingtable=colormap+(13<<8);
+ else
+ shadingtable=colormap+(25<<8);
+
+ for (plane = 0; plane < 4; plane++, buffer += TEXTUREHEIGHT)
+ {
+ w = ww;
+ switch (plane)
+ {
+ case 0:
+ if (width % 4)
+ w++;
+ break;
+ case 1:
+ if ((width % 4) > 1)
+ w++;
+ break;
+ case 2:
+ if ((width % 4) > 2)
+ w++;
+ break;
+ }
+
+
+ buf = buffer;
+ for (xx = 0; xx < w; xx++, buf += (TEXTUREHEIGHT<<2))
+ {
+ pixel = *(buf);
+ pixel = *(shadingtable+pixel);
+ *(buf) = pixel;
+ }
+ }
+}
+
+//******************************************************************************
+//
+// DrawTMenuBufVLine
+//
+//******************************************************************************
+
+void DrawTMenuBufVLine (int x, int y, int height, boolean up)
+{
+ byte *buffer;
+ byte *buf;
+ int yy;
+ int pixel;
+
+ if (x<0)
+ Error ("DrawTMenuBufBox: x is out of range\n");
+ if ((y<0) || ((y+height)>=TEXTUREHEIGHT))
+ Error ("DrawTMenuBufBox: y is out of range\n");
+
+ buffer = (byte*)menubuf+(x*TEXTUREHEIGHT)+y;
+
+ if (up)
+ shadingtable=colormap+(13<<8);
+ else
+ shadingtable=colormap+(25<<8);
+
+ for (yy = 0; yy < height; yy++)
+ {
+ buf = buffer+yy;
+ pixel = *(buf);
+ pixel = *(shadingtable+pixel);
+ *(buf) = pixel;
+ }
+}
+
+//******************************************************************************
+//******************************************************************************
+//
+// STRING ROUTINES
+//
+//******************************************************************************
+//******************************************************************************
+
+
+//******************************************************************************
+//
+// DrawMenuBufPropString ()
+//
+//******************************************************************************
+
+void DrawMenuBufPropString (int px, int py, const char *string)
+{
+ byte pix;
+ int width,height,ht;
+ byte *source, *dest, *origdest;
+ int ch;
+
+
+ if (MenuBufStarted==false)
+ Error("Called DrawMenuBufPropString without menubuf started\n");
+
+ ht = CurrentFont->height;
+ dest = origdest = (byte*)menubuf+(px*TEXTUREHEIGHT)+py;
+
+ while ((ch = (unsigned char)*string++)!=0)
+ {
+ ch -= 31;
+ width = CurrentFont->width[ch];
+ source = ((byte *)CurrentFont)+CurrentFont->charofs[ch];
+ while (width--)
+ {
+ height = ht;
+ while (height--)
+ {
+ pix = *source;
+ if (pix)
+ *dest = pix;
+
+ source++;
+ dest ++;
+ }
+
+ PrintX++;
+ origdest+=TEXTUREHEIGHT;
+ dest = origdest;
+ }
+ }
+
+}
+
+
+//******************************************************************************
+//
+// DrawMenuBufIString ()
+//
+//******************************************************************************
+
+void DrawMenuBufIString (int px, int py, const char *string, int color)
+{
+ byte pix;
+ int width,height,ht;
+ byte *source, *dest, *origdest;
+ int ch;
+
+ if (MenuBufStarted==false)
+ Error("Called DrawMenuBufPropString without menubuf started\n");
+
+ if ( ( color < 0 ) || ( color > 255 ) )
+ {
+ Error( "Intensity Color out of range\n" );
+ }
+
+ ht = IFont->height;
+ dest = origdest = (byte*)menubuf+(px*TEXTUREHEIGHT)+py;
+
+ PrintX = px;
+ PrintY = py;
+
+ while ((ch = (unsigned char)*string++)!=0)
+ {
+ // Tab
+ if ( ch == '\x9' )
+ {
+ int offset;
+
+ PrintX -= px;
+ offset = 4 * 5 - PrintX % ( 4 * 5 );
+ PrintX += offset + px;
+ origdest += offset * TEXTUREHEIGHT;
+ dest = origdest;
+ continue;
+ }
+
+ ch -= 31;
+ width = IFont->width[ ch ];
+
+ source = ( ( byte * )IFont ) + IFont->charofs[ ch ];
+
+ while (width--)
+ {
+ height = ht;
+ while (height--)
+ {
+ pix = *source;
+ if ( pix != 0xFE )
+ {
+ *dest = ( ( byte )intensitytable[ ( pix << 8 ) + color ] );
+ GetIntensityColor( pix );
+ }
+
+ source++;
+ dest ++;
+ }
+
+ PrintX++;
+ origdest+=TEXTUREHEIGHT;
+ dest = origdest;
+ }
+ }
+
+}
+
+
+//******************************************************************************
+//
+// DrawTMenuBufPropString ()
+//
+// Draws a string at px, py to bufferofs
+//
+//******************************************************************************
+
+void DrawTMenuBufPropString (int px, int py, const char *string)
+{
+ byte pix;
+ int width,height,ht;
+ byte *source, *dest, *origdest;
+ int ch;
+
+
+ if (MenuBufStarted==false)
+ Error("Called DrawTMenuBufPropString without menubuf started\n");
+
+ ht = CurrentFont->height;
+ dest = origdest = (byte*)menubuf+(px*TEXTUREHEIGHT)+py;
+
+ shadingtable=colormap+(StringShade<<8);
+ while ((ch = (unsigned char)*string++)!=0)
+ {
+ ch -= 31;
+ width = CurrentFont->width[ch];
+ source = ((byte *)CurrentFont)+CurrentFont->charofs[ch];
+ while (width--)
+ {
+ height = ht;
+ while (height--)
+ {
+ pix = *source;
+ if (pix)
+ {
+ pix = *dest;
+ pix = *(shadingtable+pix);
+ *dest = pix;
+ }
+ source++;
+ dest ++;
+ }
+
+ PrintX++;
+ origdest+=TEXTUREHEIGHT;
+ dest = origdest;
+ }
+ }
+}
+
+
+//******************************************************************************
+//
+// MenuBufCPrintLine() - Prints a string centered on the current line and
+// advances to the next line. Newlines are not supported.
+//
+//******************************************************************************
+
+void MenuBufCPrintLine (const char *s)
+{
+ int w, h;
+
+ USL_MeasureString (s, &w, &h, CurrentFont);
+
+ if (w > WindowW)
+ Error("MenuBufCPrintLine() - String exceeds width");
+
+ PrintX = WindowX + ((WindowW - w) / 2);
+ DrawMenuBufPropString (PrintX, PrintY, s);
+ PrintY += h;
+}
+
+//******************************************************************************
+//
+// MenuBufCPrint() - Prints a string in the current window. Newlines are
+// supported.
+//
+//******************************************************************************
+
+void MenuBufCPrint (const char *string)
+{
+ char c,
+ *se,
+ *s;
+
+ /* !!! FIXME: this is lame. */
+ if (strlen(string) >= sizeof (strbuf))
+ {
+ fprintf(stderr, "buffer overflow!\n");
+ return;
+ }
+
+ /* prevent writing to literal strings... ( MenubufCPrint("feh"); ) */
+ strcpy(strbuf, string);
+ s = strbuf;
+
+ while (*s)
+ {
+ se = s;
+ while ((c = *se) && (c != '\n'))
+ se++;
+ *se = '\0';
+
+ MenuBufCPrintLine(s);
+
+ s = se;
+ if (c)
+ {
+ *se = c;
+ s++;
+ }
+ }
+}
+
+//******************************************************************************
+//
+// MenuBufPrintLine() - Prints a string on the current line and
+// advances to the next line. Newlines are not supported.
+//
+//******************************************************************************
+
+void MenuBufPrintLine (const char *s)
+{
+ int w, h;
+
+ USL_MeasureString (s, &w, &h, CurrentFont);
+
+ if (w > WindowW)
+ Error("MenuBufCPrintLine() - String exceeds width");
+
+ PrintX = WindowX;
+ DrawMenuBufPropString (PrintX, PrintY, s);
+ PrintY += h;
+}
+
+//******************************************************************************
+//
+// MenuBufPrint() - Prints a string in the current window. Newlines are
+// supported.
+//
+//******************************************************************************
+
+void MenuBufPrint (const char *string)
+{
+ char c,
+ *se,
+ *s;
+
+ strcpy(strbuf, string);
+ s = strbuf;
+
+ while (*s)
+ {
+ se = s;
+ while ((c = *se) && (c != '\n'))
+ se++;
+ *se = '\0';
+
+ MenuBufPrintLine(s);
+
+ s = se;
+ if (c)
+ {
+ *se = c;
+ s++;
+ }
+ }
+}
+
+//******************************************************************************
+//
+// MenuTBufPrintLine() - Prints a string on the current line and
+// advances to the next line. Newlines are not supported.
+//
+//******************************************************************************
+
+void MenuTBufPrintLine (const char *s, int shade)
+{
+ int w, h;
+
+ USL_MeasureString (s, &w, &h, CurrentFont);
+
+ if (w > WindowW)
+ Error("MenuBufCPrintLine() - String exceeds width");
+
+ PrintX = WindowX;
+ StringShade=shade;
+ DrawTMenuBufPropString (PrintX, PrintY, s);
+ PrintY += h;
+}
+
+//******************************************************************************
+//
+// FlipMenuBuf
+//
+//******************************************************************************
+
+void FlipMenuBuf ( void )
+{
+ int i;
+ int dh;
+ int h;
+ int y;
+ int dy;
+ int time;
+ int flip;
+
+ if (MenuBufStarted==false)
+ Error("Called FlipMenuBuf without menubuf started\n");
+
+ if (!readytoflip)
+ Error("FlipMenuBuf called without SetAlternateMenuBuf beforehand");
+ readytoflip=0;
+ if (Menuflipspeed<=5)
+ {
+ menubuf=menubuffers[alternatemenubuf];
+ strcpy(titlestring,menutitles[alternatemenubuf]);
+ RefreshMenuBuf(0);
+ }
+ else
+ {
+ menubuf=menubuffers[alternatemenubuf^1];
+ strcpy(titlestring,menutitles[alternatemenubuf^1]);
+ time=Menuflipspeed-5;
+ dh=(1024<<8)/time;
+ h=0;
+ dy=((MENUTITLEY*6)<<8)/time;
+ y=0;
+ flip=0;
+ titleyoffset=0;
+ for (i=0; i<time; i+=tics)
+ {
+ PositionMenuBuf(h>>8,NORMALVIEW,true);
+ h+=dh*tics;
+ y+=dy*tics;
+ titleyoffset=y>>8;
+ if ((h>=512<<8) && (flip==0))
+ {
+ MN_PlayMenuSnd (SD_MENUFLIP);
+ h=1536<<8;
+ dy=-dy;
+ menubuf=menubuffers[alternatemenubuf];
+ strcpy(titlestring,menutitles[alternatemenubuf]);
+ flip=1;
+ }
+ }
+ }
+ titleyoffset=0;
+ BackgroundDrawn=false;
+}
+
+
+
+//******************************************************************************
+//
+// RotatePlane
+//
+//******************************************************************************
+
+void RotatePlane ( void )
+{
+ SetupMenuBuf();
+
+ while (!(Keyboard[0x01]))
+ {
+ RefreshMenuBuf(100);
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ DrawMenuBufPic (0,0,W_GetNumForName("newg11"));
+ DrawMenuBufItem (0,0,W_GetNumForName("apogee"));
+ FlipMenuBuf();
+ EraseMenuBufRegion(30,30,30,30);
+ RefreshMenuBuf(100);
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ FlipMenuBuf();
+ }
+ ShutdownMenuBuf();
+}
--- /dev/null
+++ b/rott/rt_build.h
@@ -1,0 +1,65 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_build_public
+#define _rt_build_public
+
+//***************************************************************************
+//
+// RT_BUILD.C
+//
+//***************************************************************************
+
+extern int Menuflipspeed;
+extern byte * intensitytable;
+
+void SetupMenuBuf ( void );
+void ShutdownMenuBuf ( void );
+
+void ClearMenuBuf ( void );
+void SetAlternateMenuBuf ( void );
+void SetMenuTitle ( const char * menutitle );
+
+void PositionMenuBuf( int angle, int distance, boolean drawbackground );
+void RefreshMenuBuf( int time );
+void FlipMenuBuf ( void );
+
+void DrawMenuBufItem (int x, int y, int shapenum);
+void DrawMenuBufIString (int px, int py, const char *string, int color);
+void DrawTMenuBufItem (int x, int y, int shapenum);
+void DrawIMenuBufItem (int x, int y, int shapenum, int color);
+void DrawColoredMenuBufItem (int x, int y, int shapenum, int color);
+void DrawMenuBufPic (int x, int y, int shapenum);
+void DrawTMenuBufPic (int x, int y, int shapenum);
+void EraseMenuBufRegion (int x, int y, int width, int height);
+
+void DrawMenuBufPropString (int px, int py, const char *string);
+void DrawTMenuBufPropString (int px, int py, const char *string);
+
+void DrawTMenuBufBox (int x, int y, int width, int height);
+void DrawTMenuBufHLine (int x, int y, int width, boolean up);
+void DrawTMenuBufVLine (int x, int y, int height, boolean up);
+void MenuBufCPrintLine (const char *s);
+void MenuBufCPrint (const char *s);
+void MenuBufPrint (const char *s);
+void MenuTBufPrintLine (const char *s, int shade);
+
+void DrawMenuBufPicture (int x, int y, const byte * pic, int w, int h);
+
+#endif
--- /dev/null
+++ b/rott/rt_cfg.c
@@ -1,0 +1,2239 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//****************************************************************************
+//
+// RT_CFG.C
+//
+//****************************************************************************
+
+#define _ROTT_
+
+#ifdef DOS
+#include <io.h>
+#include <bios.h>
+#include <conio.h>
+#include <process.h>
+#else
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#endif
+
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef _ROTT_
+#include "rt_def.h"
+#else
+#include "st_def.h"
+#endif
+
+#include "rt_cfg.h"
+#include "version.h"
+
+#ifdef _ROTT_
+
+#include "scriplib.h"
+#include "rt_playr.h"
+#include "rt_menu.h"
+#include "rt_game.h"
+#include "rt_in.h"
+#include "z_zone.h"
+#include "w_wad.h"
+#include "rt_crc.h"
+#include "rt_sound.h"
+#include "rt_util.h"
+#include "rt_main.h"
+#include "rt_view.h"
+#include "rt_msg.h"
+#include "rt_battl.h"
+#include "rt_net.h"
+#include "isr.h"
+#include "fx_man.h"
+#include "develop.h"
+
+#else
+
+#include "st_def.h"
+#include "rt_cfg.h"
+#include "scriplib.h"
+#include "rt_sound.h"
+#include "st_util.h"
+
+#endif
+//MED
+#include "memcheck.h"
+
+
+//******************************************************************************
+//
+// GLOBALS
+//
+//******************************************************************************
+
+extern int G_weaponscale;
+extern boolean iG_aimCross;
+
+boolean WriteSoundFile = true;
+
+int FXMode = 0;
+int MusicMode = 0;
+
+int MUvolume = 196;
+int FXvolume = 196;
+
+#ifdef DOS
+fx_blaster_config SBSettings =
+{
+ 0x220, fx_SB, 7, 1, 5, 0x330, 0x620
+};
+#endif
+
+boolean mouseenabled = 1;
+boolean usemouselook = 0;
+int inverse_mouse = 1; //set to -1 to invert mouse
+boolean usejump = 0;
+boolean sdl_fullscreen = 1;
+
+boolean allowBlitzMoreMissileWeps = 0;
+boolean enableAmmoPickups = 0;
+boolean autoAimMissileWeps = 0;
+boolean autoAim = 1;
+
+boolean joystickenabled = 0;
+boolean joypadenabled = 0;
+int joystickport = 0;
+int mouseadjustment = 5;
+int threshold = 1;
+int NumVoices = 4;
+int NumChannels = 1;
+int NumBits = 8;
+#ifdef DOS
+int MidiAddress = 0x330;
+#endif
+boolean cybermanenabled = false;
+boolean assassinenabled = false;
+boolean spaceballenabled = false;
+boolean AutoDetailOn = true;
+int DoubleClickSpeed = 20;
+boolean BobbinOn = true;
+int Menuflipspeed = 15;
+int DetailLevel = 2; //HI DETAIL
+int fandc = 1;
+int blanktime = (2*60*VBLCOUNTER);
+boolean ConfigLoaded = false;
+boolean stereoreversed = false;
+
+int DefaultDifficulty = 2;
+int DefaultPlayerCharacter = 0;
+int DefaultPlayerColor = 0;
+byte passwordstring[20];
+
+#ifndef _ROTT_
+
+int fulllight = 0;
+int viewsize = 7;
+
+#endif
+MacroList CommbatMacros[MAXMACROS];
+
+#ifdef DOS
+char *ApogeePath = "APOGEECD";
+#else
+char ApogeePath[256];
+#endif
+
+//******************************************************************************
+//
+// LOCALS
+//
+//******************************************************************************
+
+static char SoundName[13] = "sound.rot";
+
+#ifdef _ROTT_
+
+static char *ConfigName = "config.rot";
+static char *ScoresName = "scores.rot";
+static char *ROTT = "rott.rot";
+static char *CONFIG = "setup.rot";
+static char *BattleName = "battle.rot";
+
+AlternateInformation RemoteSounds;
+//AlternateInformation PlayerGraphics;
+AlternateInformation GameLevels;
+AlternateInformation BattleLevels;
+char CodeName[MAXCODENAMELENGTH];
+
+#endif
+
+
+#ifdef _ROTT_
+
+//******************************************************************************
+//
+// ReadScores ()
+//
+//******************************************************************************
+
+void ReadScores (void)
+{
+ int file;
+ char filename[ 128 ];
+
+ GetPathFromEnvironment( filename, ApogeePath, ScoresName );
+ if (access (filename, F_OK) == 0)
+ {
+ file = SafeOpenRead (filename);
+ SafeRead (file, &Scores, sizeof (Scores));
+ close(file);
+ }
+ else
+ gamestate.violence = 0;
+}
+
+#endif
+
+//******************************************************************************
+//
+// ReadInt
+//
+//******************************************************************************
+
+void ReadInt (const char * s1, int * val)
+{
+ GetToken (true);
+ if (!strcmpi (token,s1))
+ {
+ if (TokenAvailable()==true)
+ {
+ GetToken(false);
+ *val=ParseNum(token);
+ }
+ }
+}
+
+//******************************************************************************
+//
+// ReadBoolean
+//
+//******************************************************************************
+
+void ReadBoolean (const char * s1, boolean * val)
+{
+ int temp;
+
+ temp = (int)(*val);
+ ReadInt (s1,&temp);
+ *val = (boolean) temp;
+}
+
+//******************************************************************************
+//
+// ReadUnsigned
+//
+//******************************************************************************
+
+void ReadUnsigned (const char * s1, unsigned long * val)
+{
+ int temp;
+
+ temp = (int)(*val);
+ ReadInt (s1,&temp);
+ *val = (unsigned) temp;
+}
+
+//******************************************************************************
+//
+// ParseSoundFile ()
+//
+//******************************************************************************
+
+boolean ParseSoundFile (void)
+{
+ boolean retval = true;
+ int version = 0;
+
+ ReadInt("Version",&version);
+
+ if (version == ROTTVERSION)
+ {
+ // Read in Music Mode
+
+ ReadInt ("MusicMode",&MusicMode);
+
+ // Read in FX Mode
+
+ ReadInt ("FXMode",&FXMode);
+
+ // Read in Music Volume
+
+ ReadInt ("MusicVolume", &MUvolume);
+
+ // Read in FX Volume
+
+ ReadInt ("FXVolume", &FXvolume);
+
+ // Read in numvoices
+
+ ReadInt ("NumVoices",&NumVoices);
+
+ // Read in numchannels
+
+ ReadInt ("NumChannels",&NumChannels);
+
+ // Read in numbits
+
+ ReadInt ("NumBits",&NumBits);
+
+#ifdef DOS
+ // Read in Midi Address
+
+ ReadInt ("MidiAddress",&MidiAddress);
+#endif
+
+ // Read in stereo reversal
+
+ ReadBoolean ("StereoReverse",&stereoreversed);
+
+#ifdef DOS
+ // Read in Sound Blaster info
+ ReadUnsigned ("SBType", &SBSettings.Type );
+ ReadUnsigned ("SBPort", &SBSettings.Address );
+ ReadUnsigned ("SBIrq", &SBSettings.Interrupt );
+ ReadUnsigned ("SBDma8", &SBSettings.Dma8 );
+ ReadUnsigned ("SBDma16", &SBSettings.Dma16 );
+ ReadUnsigned ("SBMidi", &SBSettings.Midi );
+ ReadUnsigned ("SBEmu", &SBSettings.Emu );
+#endif
+ }
+ else
+ retval = false;
+
+ return (retval);
+}
+
+
+
+//******************************************************************************
+//
+// SetSoundDefaultValues ()
+//
+//******************************************************************************
+void SetSoundDefaultValues
+(
+ void
+)
+
+{
+#ifdef DOS
+ fx_blaster_config blaster;
+#endif
+ int status;
+
+ //
+ // no config file, so select default values
+ //
+#if !defined(PLATFORM_DOS)
+ // icculus' SDL_mixer driver looks like a soundscape to us
+ MusicMode = 6;
+ FXMode = 6;
+ NumVoices = 8;
+ NumChannels = 2;
+ NumBits = 16;
+ stereoreversed = false;
+#else
+ MusicMode = 0;
+ FXMode = 0;
+ NumVoices = 4;
+ NumChannels = 1;
+ NumBits = 8;
+ MidiAddress = 0x330;
+ stereoreversed = false;
+
+ status = FX_GetBlasterSettings( &blaster );
+ if ( status == FX_Ok )
+ {
+ SBSettings.Type = blaster.Type;
+ SBSettings.Address = blaster.Address;
+ SBSettings.Interrupt = blaster.Interrupt;
+ SBSettings.Dma8 = blaster.Dma8;
+ SBSettings.Dma16 = blaster.Dma16;
+ SBSettings.Midi = blaster.Midi;
+ SBSettings.Emu = blaster.Emu;
+ }
+#endif
+}
+
+
+#ifdef _ROTT_
+
+extern char pword[ 13 ];
+//******************************************************************************
+//
+// ConvertStringToPasswordString ()
+//
+//******************************************************************************
+
+#define PASSWORDENCRYPTER "7d7e4a2d3b6a0319554654231f6d2a"
+
+void ConvertStringToPasswordString ( char * string )
+{
+ int i;
+ unsigned int j;
+ char temp[3];
+
+ memset(temp,0,sizeof(temp));
+
+ for (i=0; i<13; i++)
+ {
+ memcpy(&temp[0],&string[i<<1],2);
+ sscanf(&temp[0],"%x",&j);
+ passwordstring[i+0] = j & 0xff;
+ j >>= 8;
+ passwordstring[i+1] = j & 0xff;
+ j >>= 8;
+ passwordstring[i+2] = j & 0xff;
+ j >>= 8;
+ passwordstring[i+3] = j & 0xff;
+ }
+}
+
+//******************************************************************************
+//
+// ConvertPasswordStringToPassword ()
+//
+//******************************************************************************
+
+void ConvertPasswordStringToPassword ( void )
+{
+ int i;
+ int x;
+ char temp[3];
+ char key[40];
+
+ memset(temp,0,sizeof(temp));
+ strcpy(&key[0],PASSWORDENCRYPTER);
+
+ for (i=0; i<12; i++)
+ {
+ memcpy(&temp[0],&key[i<<1],2);
+ sscanf(&temp[0],"%x",&x);
+ pword[i]=passwordstring[i]^x;
+ }
+ memcpy(&temp[0],&key[i<<1],2);
+ sscanf(&temp[0],"%x",&x);
+ gamestate.violence=passwordstring[i]^x;
+ if (
+ (gamestate.violence<0) ||
+ (gamestate.violence>3)
+ )
+ gamestate.violence=0;
+}
+
+//******************************************************************************
+//
+// ConvertPasswordStringToString ()
+//
+//******************************************************************************
+
+void ConvertPasswordStringToString ( char * string )
+{
+ int i;
+ char temp[8];
+
+ memset(temp,0,sizeof(temp));
+
+ for (i=0; i<13; i++)
+ {
+ itoa((passwordstring[i]>>4),&temp[0],16);
+ string[(i<<1)+0]=temp[0];
+ itoa((passwordstring[i]&0xf),&temp[0],16);
+ string[(i<<1)+1]=temp[0];
+ }
+}
+
+//******************************************************************************
+//
+// ConvertPasswordToPasswordString ()
+//
+//******************************************************************************
+
+void ConvertPasswordToPasswordString ( void )
+{
+ int i;
+ int x;
+ char temp[3];
+ char key[40];
+
+ memset(temp,0,sizeof(temp));
+ strcpy(&key[0],PASSWORDENCRYPTER);
+
+ for (i=0; i<12; i++)
+ {
+ memcpy(&temp[0],&key[i<<1],2);
+ sscanf(&temp[0],"%x",&x);
+ passwordstring[i]=pword[i]^x;
+ }
+ memcpy(&temp[0],&key[i<<1],2);
+ sscanf(&temp[0],"%x",&x);
+ passwordstring[i]=gamestate.violence^x;
+}
+
+//******************************************************************************
+//
+// ParseConfigFile ()
+//
+//******************************************************************************
+
+boolean ParseConfigFile (void)
+{
+// int temp;
+ boolean retval = true;
+ int version = 0;
+
+ ReadInt("Version",&version);
+
+ if (version == ROTTVERSION)
+ {
+ //Read in allowBlitzguardMoreMissileWeps
+
+ ReadBoolean("AllowBlitzguardMoreMissileWeps", &allowBlitzMoreMissileWeps);
+
+ //Read in enableAmmoPickups
+
+ ReadBoolean("EnableAmmoPickups", &enableAmmoPickups);
+
+ //Read in AutoAim
+
+ ReadBoolean("AutoAim", &autoAim);
+
+ //Read in AutoAimMissileWeps
+
+ ReadBoolean("AutoAimMissileWeps", &autoAimMissileWeps);
+
+ // Read in MouseEnabled
+ ReadBoolean("MouseEnabled",&mouseenabled);
+
+ // Read in UseMouseLook
+ ReadBoolean("UseMouseLook",&usemouselook);
+
+ ReadInt("InverseMouse",&inverse_mouse);
+
+ // Read in UseJump
+ ReadBoolean("UseJump",&usejump);
+
+ // Read in CrossHair
+ ReadBoolean("CrossHair",&iG_aimCross);
+
+ // Read in JoystickEnabled
+ ReadBoolean("JoystickEnabled",&joystickenabled);
+
+ // Read in JoypadEnabled
+ ReadBoolean("JoypadEnabled",&joypadenabled);
+
+ // Read in JoystickPort
+
+ ReadInt("JoystickPort",&joystickport);
+
+ // Read in fullscreen
+ ReadBoolean("FullScreen", &sdl_fullscreen);
+
+ // Read in resolution
+ ReadInt("ScreenWidth", &iGLOBAL_SCREENWIDTH);
+ ReadInt("ScreenHeight", &iGLOBAL_SCREENHEIGHT);
+
+ // Read in ViewSize
+
+ ReadInt("ViewSize",&viewsize);
+
+ // Read in Weaponscale
+
+ ReadInt("Weaponscale",&G_weaponscale);//bna added
+ if ((G_weaponscale <150)||(G_weaponscale>600)) {
+ if (iGLOBAL_SCREENWIDTH == 320) {
+ G_weaponscale=168;
+ } else if (iGLOBAL_SCREENWIDTH == 640) {
+ G_weaponscale=299;
+ } else if (iGLOBAL_SCREENWIDTH == 800) {
+ G_weaponscale=376;
+ }
+ }
+
+ // Read in MouseAdjustment
+
+ ReadInt("MouseAdjustment",&mouseadjustment);
+
+ // Read in threshold
+
+ ReadInt("Threshold",&threshold);
+
+ // Read in Auto Detail
+
+ ReadBoolean ("AutoDetail", &AutoDetailOn);
+
+ // Read in Light Dim
+
+ ReadInt ("LightDim", &fulllight);
+
+ // Read in Bobbin' On
+
+ ReadBoolean ("BobbingOn", &BobbinOn);
+
+ // Read in Double Click Speed
+
+ ReadInt ("DoubleClickSpeed", &DoubleClickSpeed);
+
+ // Read in Menu Flip Speed
+
+ ReadInt ("MenuFlipSpeed", &Menuflipspeed);
+
+ // Read in Detail Level
+
+ ReadInt ("DetailLevel", &DetailLevel);
+
+ // Read in Floor and Ceiling
+
+ ReadInt ("FloorCeiling", &fandc);
+
+ // Read in MessagesEnabled
+
+ ReadBoolean ("Messages", &MessagesEnabled );
+
+ // Read in Autorun
+
+ ReadInt ("AutoRun", &gamestate.autorun );
+
+ // Read in GammaIndex
+
+ ReadInt ("GammaIndex", &gammaindex);
+
+ // Read screen blanking time
+
+ ReadInt ("BlankTime", &blanktime);
+
+ blanktime=blanktime*60*VBLCOUNTER;
+
+ // Read keys
+
+ ReadInt ("Fire", &buttonscan[0]);
+ ReadInt ("Strafe", &buttonscan[1]);
+ ReadInt ("Run", &buttonscan[2]);
+ ReadInt ("Use", &buttonscan[3]);
+ ReadInt ("LookUp", &buttonscan[4]);
+ ReadInt ("LookDn", &buttonscan[5]);
+ ReadInt ("Swap", &buttonscan[6]);
+ ReadInt ("Drop", &buttonscan[7]);
+ ReadInt ("TargetUp", &buttonscan[8]);
+ ReadInt ("TargetDn", &buttonscan[9]);
+ ReadInt ("SelPistol", &buttonscan[10]);
+ ReadInt ("SelDualPistol",&buttonscan[11]);
+ ReadInt ("SelMP40", &buttonscan[12]);
+ ReadInt ("SelMissile", &buttonscan[13]);
+ ReadInt ("AutoRun", &buttonscan[14]);
+ ReadInt ("LiveRemRid", &buttonscan[15]);
+ ReadInt ("StrafeLeft", &buttonscan[16]);
+ ReadInt ("StrafeRight", &buttonscan[17]);
+ ReadInt ("VolteFace", &buttonscan[18]);
+ ReadInt ("Aim", &buttonscan[19]);
+ ReadInt ("Forward", &buttonscan[20]);
+ ReadInt ("Right", &buttonscan[21]);
+ ReadInt ("Backward", &buttonscan[22]);
+ ReadInt ("Left", &buttonscan[23]);
+ ReadInt ("Map", &buttonscan[24]);
+ ReadInt ("SendMessage", &buttonscan[25]);
+ ReadInt ("DirectMessage",&buttonscan[26]);
+
+ ReadInt ("MouseButton0",&buttonmouse[0]);
+ ReadInt ("MouseButton1",&buttonmouse[1]);
+ ReadInt ("MouseButton2",&buttonmouse[2]);
+ ReadInt ("DblClickB0", &buttonmouse[3]);
+ ReadInt ("DblClickB1", &buttonmouse[4]);
+ ReadInt ("DblClickB2", &buttonmouse[5]);
+
+ ReadInt ("JoyButton0", &buttonjoy[0]);
+ ReadInt ("JoyButton1", &buttonjoy[1]);
+ ReadInt ("JoyButton2", &buttonjoy[2]);
+ ReadInt ("JoyButton3", &buttonjoy[3]);
+ ReadInt ("DblClickJB0", &buttonjoy[4]);
+ ReadInt ("DblClickJB1", &buttonjoy[5]);
+ ReadInt ("DblClickJB2", &buttonjoy[6]);
+ ReadInt ("DblClickJB3", &buttonjoy[7]);
+
+ ReadInt ("JoyMaxX", &joyxmax);
+ ReadInt ("JoyMaxY", &joyymax);
+ ReadInt ("JoyMinX", &joyxmin);
+ ReadInt ("JoyMinY", &joyymin);
+
+ ReadInt( "DefaultDifficulty", &DefaultDifficulty );
+ ReadInt( "DefaultPlayerCharacter", &DefaultPlayerCharacter );
+ ReadInt( "DefaultPlayerColor", &DefaultPlayerColor );
+
+ // Get Password string
+ GetToken (true);
+ if (!stricmp (token, "SecretPassword"))
+ {
+ GetTokenEOL (false);
+ ConvertStringToPasswordString ( &name[0] );
+ }
+
+ if (!CybermanPresent)
+ cybermanenabled = false;
+
+ if (!AssassinPresent)
+ assassinenabled = false;
+
+ if (!SpaceBallPresent)
+ spaceballenabled = false;
+
+ if (!MousePresent)
+ mouseenabled = false;
+
+ if (!JoysPresent[joystickport])
+ joystickenabled = false;
+
+ // precaution
+
+ if (!joyxmin || !joyxmax || !joyymin || !joyymax)
+ joystickenabled = false;
+
+ if (joystickenabled)
+ IN_SetupJoy (joystickport, joyxmin, joyxmax, joyymin, joyymax);
+ }
+ else
+ retval = false;
+
+ return (retval);
+}
+
+
+//******************************************************************************
+//
+// ParseBattleFile ()
+//
+//******************************************************************************
+boolean ParseBattleFile (void)
+{
+ boolean retval = true;
+ int version = 0;
+ int index;
+ int temp;
+ extern specials BattleSpecialsTimes;
+
+ ReadInt("Version",&version);
+ if (version != ROTTVERSION)
+ retval = false;
+ else
+ {
+ ReadBoolean( "ShowKillCount", &BATTLE_ShowKillCount );
+
+ ReadInt( "GodModeTime", &BattleSpecialsTimes.GodModeTime );
+ ReadInt( "DogModeTime", &BattleSpecialsTimes.DogModeTime );
+ ReadInt( "ShroomsModeTime", &BattleSpecialsTimes.ShroomsModeTime );
+ ReadInt( "ElastoModeTime", &BattleSpecialsTimes.ElastoModeTime );
+ ReadInt( "AsbestosVestTime", &BattleSpecialsTimes.AsbestosVestTime );
+ ReadInt( "BulletProofVestTime", &BattleSpecialsTimes.BulletProofVestTime );
+ ReadInt( "GasMaskTime", &BattleSpecialsTimes.GasMaskTime );
+ ReadInt( "MercuryModeTime", &BattleSpecialsTimes.MercuryModeTime );
+ ReadInt( "GodModeRespawnTime", &BattleSpecialsTimes.GodModeRespawnTime );
+ ReadInt( "DogModeRespawnTime", &BattleSpecialsTimes.DogModeRespawnTime );
+ ReadInt( "ShroomsModeRespawnTime", &BattleSpecialsTimes.ShroomsModeRespawnTime );
+ ReadInt( "ElastoModeRespawnTime", &BattleSpecialsTimes.ElastoModeRespawnTime );
+ ReadInt( "AsbestosVestRespawnTime", &BattleSpecialsTimes.AsbestosVestRespawnTime );
+ ReadInt( "BulletProofVestRespawnTime", &BattleSpecialsTimes.BulletProofVestRespawnTime );
+ ReadInt( "GasMaskRespawnTime", &BattleSpecialsTimes.GasMaskRespawnTime );
+ ReadInt( "MercuryModeRespawnTime", &BattleSpecialsTimes.MercuryModeRespawnTime );
+
+ ReadBoolean( "EKG", &battlegibs );
+
+ for( index = battle_Normal; index < battle_NumBattleModes; index++ )
+ {
+ // Read Gravity
+ temp = BATTLE_Options[ index ].Gravity;
+ ReadInt( "Gravity", &temp );
+ BATTLE_Options[ index ].Gravity = temp;
+
+ // Read Speed
+ temp = bo_normal_speed;
+ ReadInt( "Speed", &temp );
+ if ( ( temp >= bo_normal_speed ) &&
+ ( temp <= bo_fast_speed ) )
+ {
+ BATTLE_Options[ index ].Speed = temp;
+ }
+
+ if ( ( index != battle_Collector ) && ( index != battle_Tag ) &&
+ ( index != battle_Eluder ) )
+ {
+ // Read Ammo
+ temp = bo_normal_shots;
+ BATTLE_Options[ index ].Ammo = bo_normal_shots;
+ ReadInt( "Ammo", &temp );
+ if ( ( temp >= bo_one_shot ) &&
+ ( temp <= bo_infinite_shots ) )
+ {
+ BATTLE_Options[ index ].Ammo = temp;
+ }
+ }
+
+ if ( index != battle_Eluder )
+ {
+ // Read Hitpoints
+ temp = BATTLE_Options[ index ].HitPoints;
+ ReadInt( "Hitpoints", &temp );
+ BATTLE_Options[ index ].HitPoints = temp;
+ }
+
+ // Read Spawn Dangers
+ temp = 1;
+ ReadInt( "SpawnDangers", &temp );
+ BATTLE_Options[ index ].SpawnDangers = temp;
+
+ if ( index != battle_Eluder )
+ {
+ // Read Spawn Health
+ temp = 1;
+ ReadInt( "SpawnHealth", &temp );
+ BATTLE_Options[ index ].SpawnHealth = temp;
+
+ // Read Spawn Mines
+ temp = 0;
+ ReadInt( "SpawnMines", &temp );
+ BATTLE_Options[ index ].SpawnMines = temp;
+ }
+
+ if ( ( index != battle_Collector ) && ( index != battle_Tag ) &&
+ ( index != battle_Eluder ) )
+ {
+ // Read Spawn Weapons
+ temp = 1;
+ ReadInt( "SpawnWeapons", &temp );
+ BATTLE_Options[ index ].SpawnWeapons = temp;
+
+ // Read Random Weapons
+ temp = 0;
+ ReadInt( "RandomWeapons", &temp );
+ BATTLE_Options[ index ].RandomWeapons = temp;
+
+ // Read Weapon Persistence
+ temp = 0;
+ ReadInt( "WeaponPersistence", &temp );
+ BATTLE_Options[ index ].WeaponPersistence = temp;
+ }
+
+ if ( ( index == battle_Normal ) || ( index == battle_ScoreMore ) ||
+ ( index == battle_Hunter ) || ( index == battle_Tag ) )
+ {
+ // Read Friendly Fire
+ temp = 1;
+ ReadInt( "FriendlyFire", &temp );
+ BATTLE_Options[ index ].FriendlyFire = temp;
+ }
+
+ if ( index != battle_Eluder )
+ {
+ // Read Respawn Items
+ temp = 1;
+ ReadInt( "RespawnItems", &temp );
+ BATTLE_Options[ index ].RespawnItems = temp;
+ }
+
+ // Read Light Level
+ temp = bo_light_normal;
+ ReadInt( "LightLevel", &temp );
+ if ( ( temp >= bo_light_dark ) &&
+ ( temp <= bo_light_lightning ) )
+ {
+ BATTLE_Options[ index ].LightLevel = temp;
+ }
+
+ if ( ( index != battle_Collector ) && ( index != battle_Scavenger ) )
+ {
+ // Read Point Goal
+ temp = bo_kills_default;
+ ReadInt( "PointGoal", &temp );
+ BATTLE_Options[ index ].Kills = temp;
+ if ( temp < bo_kills_random )
+ {
+ BATTLE_Options[ index ].Kills = bo_kills_default;
+ }
+ }
+
+ if ( index != battle_Eluder )
+ {
+ // Read Danger Damage
+ temp = bo_danger_normal;
+ ReadInt( "DangerDamage", &temp );
+ BATTLE_Options[ index ].DangerDamage = temp;
+ }
+
+ // Read Time Limit
+ temp = bo_time_infinite;
+ ReadInt( "TimeLimit", &temp );
+ if ( ( index == battle_Hunter ) && ( temp == bo_time_infinite ) )
+ {
+ temp = 99;
+ }
+ BATTLE_Options[ index ].TimeLimit = temp;
+
+ // Read Respawn time
+ temp = bo_normal_respawn_time;
+ ReadInt( "RespawnTime", &temp );
+ BATTLE_Options[ index ].RespawnTime = temp;
+ }
+ }
+
+ return (retval);
+}
+
+//******************************************************************************
+//
+// SetBattleDefaultValues ()
+//
+//******************************************************************************
+
+void SetBattleDefaultValues (void)
+{
+ int index;
+
+ //
+ // no config file, so select default values
+ //
+ for( index = battle_StandAloneGame; index < battle_NumBattleModes;
+ index++ )
+ {
+ BATTLE_Options[ index ].Gravity = NORMAL_GRAVITY;
+ BATTLE_Options[ index ].Speed = bo_normal_speed;
+ BATTLE_Options[ index ].Ammo = bo_normal_shots;
+ BATTLE_Options[ index ].HitPoints = bo_default_hitpoints;
+ BATTLE_Options[ index ].SpawnDangers = 1;
+ BATTLE_Options[ index ].SpawnHealth = 1;
+ BATTLE_Options[ index ].SpawnMines = 0;
+ BATTLE_Options[ index ].SpawnWeapons = 1;
+ BATTLE_Options[ index ].RespawnItems = 1;
+ BATTLE_Options[ index ].RandomWeapons = 0;
+ BATTLE_Options[ index ].WeaponPersistence = 0;
+ BATTLE_Options[ index ].FriendlyFire = 1;
+ BATTLE_Options[ index ].LightLevel = bo_light_normal;
+ BATTLE_Options[ index ].Kills = bo_kills_default;
+ BATTLE_Options[ index ].DangerDamage = bo_danger_normal;
+ BATTLE_Options[ index ].TimeLimit = bo_time_infinite;
+ BATTLE_Options[ index ].RespawnTime = bo_normal_respawn_time;
+ }
+
+ BATTLE_Options[ battle_CaptureTheTriad ].Kills = 1;
+ BATTLE_Options[ battle_Hunter ].TimeLimit = 1;
+ BATTLE_Options[ battle_Eluder ].SpawnHealth = 0;
+ BATTLE_Options[ battle_Eluder ].RespawnItems = 0;
+ BATTLE_Options[ battle_Eluder ].SpawnWeapons = 0;
+ BATTLE_Options[ battle_Eluder ].FriendlyFire = 0;
+ BATTLE_Options[ battle_Collector ].SpawnWeapons = 0;
+ BATTLE_Options[ battle_Collector ].FriendlyFire = 0;
+ BATTLE_Options[ battle_Tag ].SpawnWeapons = 0;
+ battlegibs=false;
+ BATTLE_ShowKillCount = true;
+}
+
+//******************************************************************************
+//
+// SetConfigDefaultValues ()
+//
+//******************************************************************************
+
+void SetConfigDefaultValues (void)
+{
+ //
+ // no config file, so select default values
+ //
+ if (MousePresent)
+ mouseenabled = true;
+
+ joystickenabled = false;
+ joypadenabled = false;
+ joystickport = 0;
+ viewsize = 7;
+ mouseadjustment = 5;
+ gammaindex = 0;
+ gamestate.violence = 3;
+ passwordstring[0]=0x7d;
+ passwordstring[1]=0x7e;
+ passwordstring[2]=0x4a;
+ passwordstring[3]=0x2d;
+ passwordstring[4]=0x3b;
+ passwordstring[5]=0x6a;
+ passwordstring[6]=0x03;
+ passwordstring[7]=0x19;
+ passwordstring[8]=0x55;
+ passwordstring[9]=0x46;
+ passwordstring[10]=0x54;
+ passwordstring[11]=0x23;
+ passwordstring[12]=0x1c;
+}
+#endif
+
+//******************************************************************************
+//
+// DeleteSoundFile ()
+//
+//******************************************************************************
+void DeleteSoundFile ( void )
+{
+ char filename[ 128 ];
+
+ GetPathFromEnvironment( filename, ApogeePath, SoundName );
+ unlink (filename); // Delete SOUND.ROT
+}
+
+//******************************************************************************
+//
+// ReadConfig ()
+//
+//******************************************************************************
+
+
+void ReadConfig (void)
+{
+ char filename[ 128 ];
+
+ GetPathFromEnvironment( filename, ApogeePath, SoundName );
+ SetSoundDefaultValues ();
+
+ if (access (filename, F_OK) == 0)
+ {
+ LoadScriptFile (filename);
+
+ if (ParseSoundFile () == false)
+ {
+ DeleteSoundFile();
+ }
+
+ Z_Free (scriptbuffer);
+ }
+#ifdef DOS
+ else if ( !SOUNDSETUP )
+ {
+ Error( "Could not find SOUND.ROT. Please run SNDSETUP to configure "
+ "your sound hardware." );
+ }
+#endif
+
+
+#ifdef _ROTT_
+ ReadScores();
+
+ GetPathFromEnvironment( filename, ApogeePath, ConfigName );
+ SetConfigDefaultValues ();
+ if (access(filename,F_OK)==0)
+ {
+ LoadScriptFile(filename);
+
+ if (ParseConfigFile () == false)
+ {
+ unlink (filename); // Delete CONFIG.ROT
+ }
+
+ Z_Free(scriptbuffer);
+ }
+
+ GetPathFromEnvironment( filename, ApogeePath, BattleName );
+ SetBattleDefaultValues ();
+ if (access(filename,F_OK)==0)
+ {
+ LoadScriptFile(filename);
+
+ if (ParseBattleFile() == false)
+ {
+ unlink (filename); // Delete BATTLE.ROT
+ }
+
+ Z_Free(scriptbuffer);
+ }
+#endif
+ ConfigLoaded = true;
+}
+
+//******************************************************************************
+//
+// CheckVendor ()
+//
+//******************************************************************************
+
+#if (SHAREWARE==1)
+#define VENDORDOC ("VENDOR.DOC")
+#define VENDORLUMP ("VENDOR")
+#else
+#define VENDORDOC ("LICENSE.DOC")
+#define VENDORLUMP ("LICENSE")
+#endif
+
+void CheckVendor (void)
+{
+ boolean saveout=false;
+ int wadcrc;
+ int filecrc;
+ int size;
+ int lump;
+ byte * vendor;
+ char filename[ 128 ];
+
+ GetPathFromEnvironment( filename, ApogeePath, VENDORDOC );
+ if (access (filename, F_OK) == 0)
+ {
+ size = LoadFile(filename,(void **)&vendor);
+ filecrc = CalculateCRC (vendor, size);
+ SafeFree(vendor);
+ lump=W_GetNumForName(VENDORLUMP);
+ vendor = W_CacheLumpNum(lump,PU_CACHE, CvtNull, 1);
+ size=W_LumpLength(lump);
+ wadcrc = CalculateCRC (vendor, size);
+ if (wadcrc != filecrc)
+ saveout=true;
+ }
+ else
+ saveout=true;
+
+ if (saveout==true)
+ {
+ lump=W_GetNumForName(VENDORLUMP);
+ vendor = W_CacheLumpNum(lump,PU_CACHE, CvtNull, 1);
+ size = W_LumpLength(lump);
+ SaveFile (filename,vendor,size);
+ }
+}
+
+//******************************************************************************
+//
+// WriteParameter
+//
+//******************************************************************************
+
+void WriteParameter (int file, const char * s1, int val)
+{
+ char s[50];
+
+ // Write out Header
+ SafeWriteString (file, (char *)s1);
+
+ // Write out space character
+ strcpy (&s[0],(const char *)" ");
+ SafeWriteString (file, &s[0]);
+
+ // Write out value
+ itoa(val,&s[0],10);
+ SafeWriteString (file, &s[0]);
+
+ // Write out EOL character
+ strcpy (&s[0],(const char *)"\n");
+ SafeWriteString (file, &s[0]);
+}
+
+
+//******************************************************************************
+//
+// WriteParameterHex
+//
+//******************************************************************************
+
+void WriteParameterHex (int file, const char * s1, int val)
+{
+ char s[50];
+
+ // Write out Header
+ SafeWriteString (file, (char *)s1);
+
+ // Write out space character
+ strcpy (&s[0],(const char *)" $");
+ SafeWriteString (file, &s[0]);
+
+ // Write out value
+ itoa(val,&s[0],16);
+ SafeWriteString (file, &s[0]);
+
+ // Write out EOL character
+ strcpy (&s[0],(const char *)"\n");
+ SafeWriteString (file, &s[0]);
+}
+
+
+
+#ifdef _ROTT_
+
+//******************************************************************************
+//
+// WriteScores ()
+//
+//******************************************************************************
+
+void WriteScores (void)
+{
+ int file;
+ char filename[ 128 ];
+
+ GetPathFromEnvironment( filename, ApogeePath, ScoresName );
+ file=SafeOpenWrite( filename );
+ SafeWrite (file, &Scores, sizeof (Scores));
+ close(file);
+}
+
+
+//******************************************************************************
+//
+// WriteBattleConfig ()
+//
+//******************************************************************************
+
+void WriteBattleConfig
+(
+ void
+)
+
+{
+ int file;
+ int index;
+ char filename[ 128 ];
+ extern specials BattleSpecialsTimes;
+
+ // Write Battle File
+ GetPathFromEnvironment( filename, ApogeePath, BattleName );
+ file = open( filename, O_RDWR | O_TEXT | O_CREAT | O_TRUNC,
+ S_IREAD | S_IWRITE );
+
+ if ( file == -1 )
+ {
+ Error( "Error opening %s: %s", filename, strerror( errno ) );
+ }
+
+ // Write out BATTLECONFIG header
+ SafeWriteString( file,
+ ";Rise of the Triad Battle Configuration File\n"
+ "; (c) 1995\n"
+ ";\n"
+ ";You may change these options at you own risk. Using any values\n"
+ ";other than the ones documented may make the game unplayable.\n"
+ ";If this happens, you may delete this file (BATTLE.ROT) and ROTT\n"
+ ";will recreate it with the default values selected.\n"
+ ";\n"
+ ";With that in mind, have fun!\n"
+ ";\n"
+ "\n" );
+
+ // Write out Version
+ WriteParameter( file, "Version ", ROTTVERSION );
+
+ // Write out BATTLE_ShowKillPics
+ SafeWriteString(file, "\n;\n");
+ WriteParameter( file, "; Yes - ", 1 );
+ WriteParameter( file, "; No - ", 0 );
+ WriteParameter( file, "ShowKillCount ", BATTLE_ShowKillCount );
+
+ // Write out specials' times
+ SafeWriteString(file, "\n;\n"
+ "; These are the time in seconds of the various powerups.\n"
+ "; You could modify these to give you infinite Mercury mode,\n"
+ "; stronger vests, or to make them persistent.\n;\n" );
+
+ WriteParameter( file, "GodModeTime ", BattleSpecialsTimes.GodModeTime );
+ WriteParameter( file, "DogModeTime ", BattleSpecialsTimes.DogModeTime );
+ WriteParameter( file, "ShroomsModeTime ", BattleSpecialsTimes.ShroomsModeTime );
+ WriteParameter( file, "ElastoModeTime ", BattleSpecialsTimes.ElastoModeTime );
+ WriteParameter( file, "AsbestosVestTime ", BattleSpecialsTimes.AsbestosVestTime );
+ WriteParameter( file, "BulletProofVestTime ", BattleSpecialsTimes.BulletProofVestTime );
+ WriteParameter( file, "GasMaskTime ", BattleSpecialsTimes.GasMaskTime );
+ WriteParameter( file, "MercuryModeTime ", BattleSpecialsTimes.MercuryModeTime );
+ WriteParameter( file, "GodModeRespawnTime ", BattleSpecialsTimes.GodModeRespawnTime );
+ WriteParameter( file, "DogModeRespawnTime ", BattleSpecialsTimes.DogModeRespawnTime );
+ WriteParameter( file, "ShroomsModeRespawnTime ", BattleSpecialsTimes.ShroomsModeRespawnTime );
+ WriteParameter( file, "ElastoModeRespawnTime ", BattleSpecialsTimes.ElastoModeRespawnTime );
+ WriteParameter( file, "AsbestosVestRespawnTime ", BattleSpecialsTimes.AsbestosVestRespawnTime );
+ WriteParameter( file, "BulletProofVestRespawnTime ", BattleSpecialsTimes.BulletProofVestRespawnTime );
+ WriteParameter( file, "GasMaskRespawnTime ", BattleSpecialsTimes.GasMaskRespawnTime );
+ WriteParameter( file, "MercuryModeRespawnTime ", BattleSpecialsTimes.MercuryModeRespawnTime );
+
+ // Write out battlegibs
+ SafeWriteString(file, "\n;\n");
+ WriteParameter( file, "; Yes - ", 1 );
+ WriteParameter( file, "; No - ", 0 );
+ WriteParameter( file, "EKG ", battlegibs );
+
+ // Describe options
+
+ // Write out Gravity
+ SafeWriteString(file, "\n"
+ ";\n"
+ "; Here is a description of the possible values for"
+ " each option:\n"
+ ";\n"
+ "; Gravity options:\n" );
+ WriteParameter( file, "; Low Gravity - ", LOW_GRAVITY );
+ WriteParameter( file, "; Normal Gravity - ", NORMAL_GRAVITY );
+ WriteParameter( file, "; High Gravity - ", HIGH_GRAVITY );
+
+ // Write out Speed
+ SafeWriteString(file, ";\n"
+ "; Speed options:\n" );
+ WriteParameter( file, "; Normal Speed - ", bo_normal_speed );
+ WriteParameter( file, "; Fast Speed - ", bo_fast_speed );
+
+ // Write out Ammo
+ SafeWriteString(file, ";\n"
+ "; Ammo options:\n" );
+ WriteParameter( file, "; One Shot - ", bo_one_shot );
+ WriteParameter( file, "; Normal Shots - ", bo_normal_shots );
+ WriteParameter( file, "; Infinite Shots - ", bo_infinite_shots );
+
+ // Write out Hit Points
+ SafeWriteString(file, ";\n"
+ "; Hitpoint options:\n" );
+ WriteParameter( file, "; Character Hitpoints - ", bo_character_hitpoints );
+ WriteParameter( file, "; 1 Hitpoint - ", 1 );
+ WriteParameter( file, "; 25 Hitpoints - ", 25 );
+ WriteParameter( file, "; 100 Hitpoints - ", 100 );
+ WriteParameter( file, "; 500 Hitpoints - ", 500 );
+ WriteParameter( file, "; 250 Hitpoints - ", 250 );
+ WriteParameter( file, "; 4000 Hitpoints - ", 4000 );
+
+ // Write out Danger Spawning
+ SafeWriteString(file, ";\n"
+ "; SpawnDangers options:\n"
+ "; Spawn Dangers - 1\n"
+ "; Don't Spawn Dangers - 0\n" );
+
+ // Write out Health Spawning
+ SafeWriteString(file, ";\n"
+ "; SpawnHealth options:\n"
+ "; Spawn Health - 1\n"
+ "; Don't Spawn Health - 0\n" );
+
+ // Write out Mine Spawning
+ SafeWriteString(file, ";\n"
+ "; SpawnMines options:\n"
+ "; Spawn Mines - 1\n"
+ "; Don't Spawn Mines - 0\n" );
+
+ // Write out Weapon Spawning
+ SafeWriteString(file, ";\n"
+ "; SpawnWeapons options:\n"
+ "; Spawn Weapons - 1\n"
+ "; Don't Spawn Weapons - 0\n" );
+
+ // Write out Random Weapons
+ SafeWriteString(file, ";\n"
+ "; RandomWeapons options:\n"
+ "; Randomize Weapons - 1\n"
+ "; Don't Randomize Weapons - 0\n" );
+
+ // Write out Weapon Persistence
+ SafeWriteString(file, ";\n"
+ "; WeaponPersistence options:\n"
+ "; Weapons Persist - 1\n"
+ "; Weapons don't Persist - 0\n" );
+
+ // Write out Friendly Fire
+ SafeWriteString(file, ";\n"
+ "; FriendlyFire options:\n"
+ "; Penalize Friendly Fire - 1\n"
+ "; No penalty - 0\n" );
+
+ // Write out Respawn Items
+ SafeWriteString(file, ";\n"
+ "; RespawnItems options:\n"
+ "; Respawn Items - 1\n"
+ "; Don't Respawn Items - 0\n" );
+
+ // Write out Light Level
+ SafeWriteString(file, ";\n"
+ "; LightLevel options:\n" );
+ WriteParameter( file, "; Dark - ", bo_light_dark );
+ WriteParameter( file, "; Normal Light Levels - ", bo_light_normal );
+ WriteParameter( file, "; Bright - ", bo_light_bright );
+ WriteParameter( file, "; Fog - ", bo_light_fog );
+ WriteParameter( file, "; Periodic light - ", bo_light_periodic );
+ WriteParameter( file, "; Lightning - ", bo_light_lightning );
+
+ // Write out Point Goal
+ SafeWriteString(file, ";\n"
+ "; PointGoal options:\n" );
+ WriteParameter( file, "; 1 Point - ", 1 );
+ WriteParameter( file, "; 5 Points - ", 5 );
+ WriteParameter( file, "; 11 Points - ", 11 );
+ WriteParameter( file, "; 21 Points - ", 21 );
+ WriteParameter( file, "; 50 Points - ", 50 );
+ WriteParameter( file, "; 100 Points - ", 100 );
+ WriteParameter( file, "; Random Points - ", bo_kills_random );
+ WriteParameter( file, "; Blind Points - ", bo_kills_blind );
+ WriteParameter( file, "; Infinite Points - ", bo_kills_infinite );
+
+ // Write out Danger Damage
+ SafeWriteString(file, ";\n"
+ "; DangerDamage options:\n" );
+ WriteParameter( file, "; Normal Damage - ", bo_danger_normal );
+ WriteParameter( file, "; Low Damage - ", bo_danger_low );
+ WriteParameter( file, "; Kill - ", bo_danger_kill );
+
+ // Write out TimeLimit
+ SafeWriteString(file, ";\n"
+ "; TimeLimit options:\n" );
+ WriteParameter( file, "; 1 minute - ", 1 );
+ WriteParameter( file, "; 2 minute - ", 2 );
+ WriteParameter( file, "; 5 minutes - ", 5 );
+ WriteParameter( file, "; 10 minutes - ", 10 );
+ WriteParameter( file, "; 21 minutes - ", 21 );
+ WriteParameter( file, "; 30 minutes - ", 30 );
+ WriteParameter( file, "; 99 minutes - ", 99 );
+ WriteParameter( file, "; No limit - ", bo_time_infinite );
+
+ // Write out RespawnTime
+ SafeWriteString(file, ";\n"
+ "; RespawnTime options:\n" );
+ WriteParameter( file, "; 1 second - ", 1 );
+ WriteParameter( file, "; 1 minute - ", 60 );
+ WriteParameter( file, "; 2 minutes - ", 120 );
+ WriteParameter( file, "; normal - ", bo_normal_respawn_time );
+
+ for( index = battle_Normal; index < battle_NumBattleModes; index++ )
+ {
+ SafeWriteString(file, "\n;\n");
+ switch( index )
+ {
+ case battle_Normal :
+ SafeWriteString( file, "; Standard battle options\n;\n" );
+ break;
+
+ case battle_ScoreMore :
+ SafeWriteString( file, "; Score More battle options\n;\n" );
+ break;
+
+ case battle_Collector :
+ SafeWriteString( file, "; Collector battle options\n;\n" );
+ break;
+
+ case battle_Scavenger :
+ SafeWriteString( file, "; Scavenger battle options\n;\n" );
+ break;
+
+ case battle_Hunter :
+ SafeWriteString( file, "; Hunter battle options\n;\n" );
+ break;
+
+ case battle_Tag :
+ SafeWriteString( file, "; Tag battle options\n;\n" );
+ break;
+
+ case battle_Eluder :
+ SafeWriteString( file, "; Eluder battle options\n;\n" );
+ break;
+
+ case battle_Deluder :
+ SafeWriteString( file, "; Deluder battle options\n;\n" );
+ break;
+
+ case battle_CaptureTheTriad :
+ SafeWriteString( file, "; Capture the Triad battle options\n;\n" );
+ break;
+ }
+
+ // Write out Gravity
+ WriteParameter( file, "Gravity ",
+ BATTLE_Options[ index ].Gravity );
+
+ // Write out Speed
+ WriteParameter( file, "Speed ",
+ BATTLE_Options[ index ].Speed );
+
+ if ( ( index != battle_Collector ) && ( index != battle_Tag ) &&
+ ( index != battle_Eluder ) )
+ {
+ // Write out Ammo
+ WriteParameter( file, "Ammo ",
+ BATTLE_Options[ index ].Ammo );
+ }
+
+ if ( index != battle_Eluder )
+ {
+ // Write out Hit Points
+ WriteParameter( file, "Hitpoints ",
+ BATTLE_Options[ index ].HitPoints );
+ }
+
+ // Write out Danger Spawning
+ WriteParameter( file, "SpawnDangers ",
+ BATTLE_Options[ index ].SpawnDangers );
+
+ if ( index != battle_Eluder )
+ {
+ // Write out Health Spawning
+ WriteParameter( file, "SpawnHealth ",
+ BATTLE_Options[ index ].SpawnHealth );
+
+ // Write out Mine Spawning
+ WriteParameter( file, "SpawnMines ",
+ BATTLE_Options[ index ].SpawnMines );
+ }
+
+ if ( ( index != battle_Collector ) && ( index != battle_Tag ) &&
+ ( index != battle_Eluder ) )
+ {
+ // Write out Weapon Spawning
+ WriteParameter( file, "SpawnWeapons ",
+ BATTLE_Options[ index ].SpawnWeapons );
+
+ // Write out Random Weapons
+ WriteParameter( file, "RandomWeapons ",
+ BATTLE_Options[ index ].RandomWeapons );
+
+ // Write out Weapon Persistence
+ WriteParameter( file, "WeaponPersistence",
+ BATTLE_Options[ index ].WeaponPersistence );
+ }
+
+ if ( ( index == battle_Normal ) || ( index == battle_ScoreMore ) ||
+ ( index == battle_Hunter ) || ( index == battle_Tag ) )
+ {
+ // Write out Friendly Fire
+ WriteParameter( file, "FriendlyFire ",
+ BATTLE_Options[ index ].FriendlyFire );
+ }
+
+ if ( index != battle_Eluder )
+ {
+ // Write out Respawn Items
+ WriteParameter( file, "RespawnItems ",
+ BATTLE_Options[ index ].RespawnItems );
+ }
+
+ // Write out Light Level
+ WriteParameter( file, "LightLevel ",
+ BATTLE_Options[ index ].LightLevel );
+
+ if ( ( index != battle_Collector ) && ( index != battle_Scavenger ) )
+ {
+ // Write out Point Goal
+ WriteParameter( file, "PointGoal ",
+ BATTLE_Options[ index ].Kills );
+ }
+
+ if ( index != battle_Eluder )
+ {
+ // Write out Danger Damage
+ WriteParameter( file, "DangerDamage ",
+ BATTLE_Options[ index ].DangerDamage );
+ }
+
+ // Write out TimeLimit
+ WriteParameter( file, "TimeLimit ",
+ BATTLE_Options[ index ].TimeLimit );
+
+ // Write out RespawnTime
+ WriteParameter( file, "RespawnTime ",
+ BATTLE_Options[ index ].RespawnTime );
+ }
+
+ close( file );
+}
+
+#endif
+
+//******************************************************************************
+//
+// WriteSoundConfig ()
+//
+//******************************************************************************
+
+void WriteSoundConfig
+(
+ void
+)
+
+{
+ int file;
+ char filename[ 128 ];
+
+ if ( !WriteSoundFile )
+ {
+ return;
+ }
+
+ GetPathFromEnvironment( filename, ApogeePath, SoundName );
+ file = open ( filename, O_RDWR | O_TEXT | O_CREAT | O_TRUNC,
+ S_IREAD | S_IWRITE);
+
+ if (file == -1)
+ Error ("Error opening %s: %s", filename, strerror(errno));
+
+ // Write out ROTTSOUND header
+
+ SafeWriteString (file, ";Rise of the Triad Sound File\n");
+ SafeWriteString (file, "; (c) 1995\n\n");
+
+ // Write out Version
+
+ WriteParameter(file,"Version ",ROTTVERSION);
+
+ // Write out Music Mode
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; Music Modes\n");
+ SafeWriteString(file,"; 0 - Off\n");
+#ifdef DOS
+ SafeWriteString(file,"; 1 - UltraSound\n");
+ SafeWriteString(file,"; 2 - Sound Blaster\n");
+ SafeWriteString(file,"; 3 - Sound Man 16\n");
+ SafeWriteString(file,"; 4 - Pro Audio Spectrum\n");
+ SafeWriteString(file,"; 5 - Awe32\n");
+ SafeWriteString(file,"; 6 - SoundScape\n");
+ SafeWriteString(file,"; 7 - Wave Blaster\n");
+ SafeWriteString(file,"; 8 - General Midi\n");
+ SafeWriteString(file,"; 9 - Sound Canvas\n");
+ SafeWriteString(file,"; 10 - Adlib\n");
+#else
+ SafeWriteString(file,"; 6 - On\n");
+#endif
+ WriteParameter(file,"MusicMode ",MusicMode);
+
+ // Write out FX Mode
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; FX Modes\n");
+ SafeWriteString(file,"; 0 - Off\n");
+#ifdef DOS
+ SafeWriteString(file,"; 1 - UltraSound\n");
+ SafeWriteString(file,"; 2 - Sound Blaster\n");
+ SafeWriteString(file,"; 3 - Sound Man 16\n");
+ SafeWriteString(file,"; 4 - Pro Audio Spectrum\n");
+ SafeWriteString(file,"; 5 - Awe32\n");
+ SafeWriteString(file,"; 6 - SoundScape\n");
+ SafeWriteString(file,"; 7 - Adlib\n");
+ SafeWriteString(file,"; 8 - Disney Sound Source\n");
+ SafeWriteString(file,"; 9 - Tandy Sound Source\n");
+ SafeWriteString(file,"; 10 - PC Speaker\n");
+#else
+ SafeWriteString(file,"; 6 - On\n");
+#endif
+ WriteParameter(file,"FXMode ",FXMode);
+
+ // Write in Music Volume
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; Music Volume\n");
+ SafeWriteString(file,"; (low) 0 - 255 (high)\n");
+ WriteParameter (file, "MusicVolume ", MUvolume);
+
+ // Write in FX Volume
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; FX Volume\n");
+ SafeWriteString(file,"; (low) 0 - 255 (high)\n");
+ WriteParameter (file, "FXVolume ", FXvolume);
+
+ // Write out numvoices
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; Number of Voices\n");
+ SafeWriteString(file,"; 1 - 8\n");
+ WriteParameter(file,"NumVoices ",NumVoices);
+
+ // Write out numchannels
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; Stereo or Mono\n");
+ SafeWriteString(file,"; 1 - Mono\n");
+ SafeWriteString(file,"; 2 - Stereo\n");
+ WriteParameter(file,"NumChannels ",NumChannels);
+
+ // Write out numbits
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; Resolution\n");
+ SafeWriteString(file,"; 8 bit\n");
+ SafeWriteString(file,"; 16 bit\n");
+ WriteParameter(file,"NumBits ",NumBits);
+
+#ifdef DOS
+ // Write out Midi Address
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; Midi Addresses\n");
+ SafeWriteString(file,"; $300\n");
+ SafeWriteString(file,"; $310\n");
+ SafeWriteString(file,"; $320\n");
+ SafeWriteString(file,"; $330\n");
+ SafeWriteString(file,"; $340\n");
+ SafeWriteString(file,"; $350\n");
+ SafeWriteString(file,"; $360\n");
+ SafeWriteString(file,"; $370\n");
+ SafeWriteString(file,"; $380\n");
+ WriteParameterHex(file,"MidiAddress ",MidiAddress);
+#endif
+
+ // Write out stereo reversal
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; ReverseStereo\n");
+ SafeWriteString(file,"; 0 no reversal\n");
+ SafeWriteString(file,"; 1 reverse stereo\n");
+ WriteParameter (file,"StereoReverse ",stereoreversed);
+
+#ifdef DOS
+ // Write out Sound Blaster info
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; Sound Blaster Settings\n");
+ WriteParameter(file, "SBType ", SBSettings.Type );
+ WriteParameterHex(file, "SBPort ", SBSettings.Address );
+ WriteParameter(file, "SBIrq ", SBSettings.Interrupt );
+ WriteParameter(file, "SBDma8 ", SBSettings.Dma8 );
+ WriteParameter(file, "SBDma16 ", SBSettings.Dma16 );
+ WriteParameterHex(file, "SBMidi ", SBSettings.Midi );
+ WriteParameterHex(file, "SBEmu ", SBSettings.Emu );
+#endif
+
+ close (file);
+}
+
+
+//******************************************************************************
+//
+// WriteConfig ()
+//
+//******************************************************************************
+
+void WriteConfig (void)
+{
+ int file;
+ char filename[ 128 ];
+ char passwordtemp[50];
+ static int inconfig = 0;
+
+ if (inconfig > 0)
+ return;
+
+ inconfig++ ;
+
+ if ( !ConfigLoaded )
+ {
+ return;
+ }
+
+ // Write Sound File
+ WriteSoundConfig();
+
+ // Write Config, Battle and Score files
+#ifdef _ROTT_
+ WriteScores();
+ WriteBattleConfig();
+
+ GetPathFromEnvironment( filename, ApogeePath, ConfigName );
+ file = open( filename,O_RDWR | O_TEXT | O_CREAT | O_TRUNC
+ , S_IREAD | S_IWRITE);
+
+ if (file == -1)
+ Error ("Error opening %s: %s",filename,strerror(errno));
+
+ // Write out ROTTCONFIG header
+
+ SafeWriteString (file, ";Rise of the Triad Configuration File\n");
+ SafeWriteString (file, "; (c) 1995\n\n");
+
+ // Write out Version
+
+ WriteParameter(file,"Version ",ROTTVERSION);
+
+ //Write out AllowBlitzguardMoreMissileWeps
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file, "; 1 - Allows Blitzguards to have Random Missile weapons\n");
+ SafeWriteString(file, "; 0 - Disallows the above (ROTT Default)\n");
+ WriteParameter(file, "AllowBlitzguardMoreMissileWeps ", allowBlitzMoreMissileWeps);
+
+ //Write out enableAmmoPickups
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file, "; 1 - Allows players to refill their missile weapons by running over one a matching one on the ground\n");
+ SafeWriteString(file, "; 0 - Disables the above (ROTT default)\n");
+ WriteParameter(file, "EnableAmmoPickups ", enableAmmoPickups);
+
+ //Write out autoAim
+
+ SafeWriteString(file, "\n;\n");
+ SafeWriteString(file, "; 1 - Bullet weapons will automatically target enemies. (ROTT default)\n");
+ SafeWriteString(file, "; 0 - Disables the above.\n");
+ WriteParameter(file, "AutoAim ", autoAim);
+
+ //Write out autoAimMissileWeps
+
+ SafeWriteString(file, "\n;\n");
+ SafeWriteString(file, "; 1 - Missile weapons will be automatically aimed at targets like bullet weapons.\n");
+ SafeWriteString(file, "; 0 - Missile weapons are not automatically aimed at targets. (ROTT default)\n");
+ WriteParameter(file, "AutoAimMissileWeps ", autoAimMissileWeps);
+
+ // Write out MouseEnabled
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; 1 - Mouse Enabled\n");
+ SafeWriteString(file,"; 0 - Mouse Disabled\n");
+ WriteParameter(file,"MouseEnabled ",mouseenabled);
+
+ // Write out UseMouseLook
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; 1 - UseMouseLook Enabled\n");
+ SafeWriteString(file,"; 0 - UseMouseLook Disabled\n");
+ WriteParameter(file,"UseMouseLook ",usemouselook);
+
+ // Write out InverseMouse
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; 1 - Normal Mouse Enabled\n");
+ SafeWriteString(file,"; -1 - Inverse Mouse Enabled\n");
+ WriteParameter(file,"InverseMouse ",inverse_mouse);
+
+ // Write out UseJump
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; 1 - usejump Enabled\n");
+ SafeWriteString(file,"; 0 - usejump Disabled\n");
+ WriteParameter(file,"UseJump ",usejump);
+
+ // Write out CrossHair
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; 1 - CrossHair Enabled\n");
+ SafeWriteString(file,"; 0 - CrossHair Disabled\n");
+ WriteParameter(file,"CrossHair ", iG_aimCross);
+
+ // Write out JoystickEnabled
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; 1 - Joystick Enabled\n");
+ SafeWriteString(file,"; 0 - Joystick Disabled\n");
+ WriteParameter(file,"JoystickEnabled ",joystickenabled);
+
+ // Write out JoypadEnabled
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; 1 - Joypad Enabled\n");
+ SafeWriteString(file,"; 0 - Joypad Disabled\n");
+ WriteParameter(file,"JoypadEnabled ",joypadenabled);
+
+ // Write out JoystickPort
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; 0 - Use Joystick Port 1\n");
+ SafeWriteString(file,"; 1 - Use Joystick Port 2\n");
+ WriteParameter(file,"JoystickPort ",joystickport);
+
+ // Write out fullscreen
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; 0 - Start in windowed mode\n");
+ SafeWriteString(file,"; 1 - Start in fullscreen mode\n");
+ WriteParameter(file,"FullScreen ",sdl_fullscreen);
+
+ // Write out resolution
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; Screen Resolution, supported resolutions: \n");
+ SafeWriteString(file,"; 320x200, 640x480 and 800x600\n");
+ WriteParameter(file,"ScreenWidth ",iGLOBAL_SCREENWIDTH);
+ WriteParameter(file,"ScreenHeight ",iGLOBAL_SCREENHEIGHT);
+
+ // Write out ViewSize
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; Size of View port.\n");
+ SafeWriteString(file,"; (smallest) 0 - 10 (largest)\n");
+ WriteParameter(file,"ViewSize ",viewsize);
+
+ // Write out WEAPONSCALE bna added
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; Size of Weaponscale.\n");
+ SafeWriteString(file,"; (smallest) 150 - 600 (largest)\n");
+ G_weaponscale = (weaponscale * 168 )/65536;
+
+ if ((G_weaponscale <150)||(G_weaponscale>600)) {
+ if (iGLOBAL_SCREENWIDTH == 320) {
+ G_weaponscale=168;
+ } else if (iGLOBAL_SCREENWIDTH == 640) {
+ G_weaponscale=299;
+ } else if (iGLOBAL_SCREENWIDTH == 800) {
+ G_weaponscale=376;
+ }
+ }
+ WriteParameter(file,"Weaponscale ",G_weaponscale);
+
+
+ // Write out MouseAdjustment
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; Sensitivity of Mouse\n");
+ SafeWriteString(file,"; (lowest) 0 - 11 (highest)\n");
+ WriteParameter(file,"MouseAdjustment ",mouseadjustment);
+
+ // Write out threshold
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; Threshold of Mouse and Joystick\n");
+ SafeWriteString(file,"; (smallest) 1 - 15 (largest)\n");
+ WriteParameter(file,"Threshold ",threshold);
+
+ // Write in Cyberman Enabled
+
+// SafeWriteString(file,"\n;\n");
+// SafeWriteString(file,"; 1 - Cyberman Enabled\n");
+// SafeWriteString(file,"; 0 - Cyberman Disabled\n");
+// WriteParameter(file,"CybermanEnabled ",cybermanenabled);
+
+ // Write in Spaceball Enabled
+
+// SafeWriteString(file,"\n;\n");
+// SafeWriteString(file,"; 1 - Spaceball Enabled\n");
+// SafeWriteString(file,"; 0 - Spaceball Disabled\n");
+// WriteParameter(file,"SpaceballEnabled ",spaceballenabled);
+
+ // Write in Auto Detail
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; 1 - Auto Detail on\n");
+ SafeWriteString(file,"; 0 - Auto Detail off\n");
+ WriteParameter (file,"AutoDetail ", AutoDetailOn);
+
+ // Write in Light Dim
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; 1 - Light Diminishing on\n");
+ SafeWriteString(file,"; 0 - Light Diminishing off\n");
+ WriteParameter (file,"LightDim ", fulllight);
+
+ // Write in Bobbin' On
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; 1 - Bobbing on\n");
+ SafeWriteString(file,"; 0 - Bobbing off\n");
+ WriteParameter (file,"BobbingOn ", BobbinOn);
+
+ // Write in Double Click Speed
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; (slowest) 50 - 5 (fastest)\n");
+ WriteParameter (file,"DoubleClickSpeed ", DoubleClickSpeed);
+
+ // Write in Menu Flip Speed
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; Menu Flip Speed\n");
+ SafeWriteString(file,"; (slowest) 100 - 5 (fastest)\n");
+ WriteParameter (file,"MenuFlipSpeed ", Menuflipspeed);
+
+ // Write in Detail Level
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; 0 - Detail Level Low\n");
+ SafeWriteString(file,"; 1 - Detail Level Medium\n");
+ SafeWriteString(file,"; 2 - Detail Level High\n");
+ WriteParameter (file,"DetailLevel ", DetailLevel);
+
+ // Write in Floor and Ceiling
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; 1 - Floor and Ceiling on\n");
+ SafeWriteString(file,"; 0 - Floor and Ceiling off\n");
+ WriteParameter (file,"FloorCeiling ", fandc);
+
+ // Write in DisableMessages
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; 1 - Messages on\n");
+ SafeWriteString(file,"; 0 - Messages off\n");
+ WriteParameter (file,"Messages ", MessagesEnabled );
+
+ // Write in AutoRun
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; 1 - AutoRun on\n");
+ SafeWriteString(file,"; 0 - AutoRun off\n");
+ WriteParameter (file,"AutoRun ", gamestate.autorun );
+
+ // Write in GammaIndex
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; 0 - Gamma Correction level 1\n");
+ SafeWriteString(file,"; 1 - Gamma Correction level 2\n");
+ SafeWriteString(file,"; 2 - Gamma Correction level 3\n");
+ SafeWriteString(file,"; 3 - Gamma Correction level 4\n");
+ SafeWriteString(file,"; 4 - Gamma Correction level 5\n");
+ WriteParameter (file,"GammaIndex ", gammaindex);
+
+ // Write out screen saver time
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; Minutes before screen blanking\n");
+ WriteParameter (file,"BlankTime ", blanktime/(VBLCOUNTER*60));
+
+
+ // Write out keys
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; Scan codes for keyboard buttons\n");
+ WriteParameter (file,"Fire ", buttonscan[0]);
+ WriteParameter (file,"Strafe ", buttonscan[1]);
+ WriteParameter (file,"Run ", buttonscan[2]);
+ WriteParameter (file,"Use ", buttonscan[3]);
+ WriteParameter (file,"LookUp ", buttonscan[4]);
+ WriteParameter (file,"LookDn ", buttonscan[5]);
+ WriteParameter (file,"Swap ", buttonscan[6]);
+ WriteParameter (file,"Drop ", buttonscan[7]);
+ WriteParameter (file,"TargetUp ", buttonscan[8]);
+ WriteParameter (file,"TargetDn ", buttonscan[9]);
+ WriteParameter (file,"SelPistol ", buttonscan[10]);
+ WriteParameter (file,"SelDualPistol ", buttonscan[11]);
+ WriteParameter (file,"SelMP40 ", buttonscan[12]);
+ WriteParameter (file,"SelMissile ", buttonscan[13]);
+ WriteParameter (file,"AutoRun ", buttonscan[14]);
+ WriteParameter (file,"LiveRemRid ", buttonscan[15]);
+ WriteParameter (file,"StrafeLeft ", buttonscan[16]);
+ WriteParameter (file,"StrafeRight ", buttonscan[17]);
+ WriteParameter (file,"VolteFace ", buttonscan[18]);
+ WriteParameter (file,"Aim ", buttonscan[19]);
+ WriteParameter (file,"Forward ", buttonscan[20]);
+ WriteParameter (file,"Right ", buttonscan[21]);
+ WriteParameter (file,"Backward ", buttonscan[22]);
+ WriteParameter (file,"Left ", buttonscan[23]);
+ WriteParameter (file,"Map ", buttonscan[24]);
+ WriteParameter (file,"SendMessage ", buttonscan[25]);
+ WriteParameter (file,"DirectMessage ", buttonscan[26]);
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; Mouse buttons\n");
+
+ WriteParameter (file,"MouseButton0 ", buttonmouse[0]);
+ WriteParameter (file,"MouseButton1 ", buttonmouse[1]);
+ WriteParameter (file,"MouseButton2 ", buttonmouse[2]);
+ WriteParameter (file,"DblClickB0 ", buttonmouse[3]);
+ WriteParameter (file,"DblClickB1 ", buttonmouse[4]);
+ WriteParameter (file,"DblClickB2 ", buttonmouse[5]);
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; Joystick buttons\n");
+
+ WriteParameter (file,"JoyButton0 ", buttonjoy[0]);
+ WriteParameter (file,"JoyButton1 ", buttonjoy[1]);
+ WriteParameter (file,"JoyButton2 ", buttonjoy[2]);
+ WriteParameter (file,"JoyButton3 ", buttonjoy[3]);
+ WriteParameter (file,"DblClickJB0 ", buttonjoy[4]);
+ WriteParameter (file,"DblClickJB1 ", buttonjoy[5]);
+ WriteParameter (file,"DblClickJB2 ", buttonjoy[6]);
+ WriteParameter (file,"DblClickJB3 ", buttonjoy[7]);
+
+ SafeWriteString(file,"\n;\n");
+ SafeWriteString(file,"; Joystick calibration coordinates\n");
+
+ WriteParameter (file,"JoyMaxX ", joyxmax);
+ WriteParameter (file,"JoyMaxY ", joyymax);
+ WriteParameter (file,"JoyMinX ", joyxmin);
+ WriteParameter (file,"JoyMinY ", joyymin);
+
+ // Write out DefaultDifficulty
+ SafeWriteString(file,"\n;\n");
+ WriteParameter(file,"; Easy - ", gd_baby );
+ WriteParameter(file,"; Medium - ", gd_easy );
+ WriteParameter(file,"; Hard - ", gd_medium );
+ WriteParameter(file,"; Crezzy - ", gd_hard );
+ WriteParameter(file,"DefaultDifficulty ", DefaultDifficulty );
+
+ // Write out DefaultPlayerCharacter
+ SafeWriteString(file,"\n;\n");
+ WriteParameter(file,"; Taradino Cassatt - ", 0 );
+ WriteParameter(file,"; Thi Barrett - ", 1 );
+ WriteParameter(file,"; Doug Wendt - ", 2 );
+ WriteParameter(file,"; Lorelei Ni - ", 3 );
+ WriteParameter(file,"; Ian Paul Freeley - ", 4 );
+ WriteParameter(file,"DefaultPlayerCharacter ", DefaultPlayerCharacter );
+
+ // Write out DefaultPlayerColor
+ SafeWriteString(file,"\n;\n");
+ WriteParameter(file,"; Gray - ", 0 );
+ WriteParameter(file,"; Brown - ", 1 );
+ WriteParameter(file,"; Black - ", 2 );
+ WriteParameter(file,"; Tan - ", 3 );
+ WriteParameter(file,"; Red - ", 4 );
+ WriteParameter(file,"; Olive - ", 5 );
+ WriteParameter(file,"; Blue - ", 6 );
+ WriteParameter(file,"; White - ", 7 );
+ WriteParameter(file,"; Green - ", 8 );
+ WriteParameter(file,"; Purple - ", 9 );
+ WriteParameter(file,"; Orange - ", 10 );
+ WriteParameter(file,"DefaultPlayerColor ", DefaultPlayerColor );
+
+ // Writeout password Password string
+ SafeWriteString(file,"\n;\nSecretPassword ");
+ memset(passwordtemp,0,sizeof(passwordtemp));
+ ConvertPasswordStringToString ( &passwordtemp[0] );
+ SafeWriteString(file,&passwordtemp[0]);
+
+ close (file);
+#endif
+ inconfig--;
+}
+
+#ifdef _ROTT_
+
+
+//****************************************************************************
+//
+// GetAlternatePath ()
+//
+//****************************************************************************
+
+void GetAlternatePath (char * tokenstr, AlternateInformation *info)
+{
+ strcpy (&info->path[0], ".\0");
+ GetToken (true);
+ if (!stricmp (token, tokenstr))
+ {
+ GetTokenEOL (false);
+ memset (&info->path[0], 0, sizeof (info->path));
+ strcpy (&info->path[0], &name[0]);
+ }
+}
+
+
+//****************************************************************************
+//
+// GetAlternateFile ()
+//
+//****************************************************************************
+
+void GetAlternateFile (char * tokenstr, AlternateInformation *info)
+{
+ // Read in remote sound file
+ //
+ strcpy (&info->file[0], "foo.foo\0");
+ GetToken (true);
+ if (!stricmp (token, tokenstr))
+ {
+ if (TokenAvailable()==true)
+ {
+ GetToken (false);
+ if (stricmp (token, "~"))
+ {
+#if (SHAREWARE == 0)
+ info->avail = true;
+ memset (&info->file[0], 0, sizeof (info->file));
+ strcpy (&info->file[0], &token[0]);
+#else
+ printf("Alternate file %s ignored.\n",token);
+ memset (&info->file[0], 0, sizeof (info->file));
+#endif
+ }
+ }
+ }
+}
+
+
+//****************************************************************************
+//
+// ReadSETUPFiles ()
+//
+//****************************************************************************
+
+void ReadSETUPFiles (void)
+{
+ char filename[ 128 ];
+ int i;
+
+ RemoteSounds.avail = false;
+// PlayerGraphics.avail = false;
+ GameLevels.avail = false;
+ BattleLevels.avail = false;
+
+ GetPathFromEnvironment( filename, ApogeePath, CONFIG );
+ if (access (filename, F_OK) == 0)
+ {
+ LoadScriptFile (filename);
+
+ GetTokenEOL (true); //MODEMNAME
+ GetTokenEOL (true); //MODEMINITSTR
+ GetTokenEOL (true); //MODEMHANGUP
+ GetTokenEOL (true); //RATE
+ GetTokenEOL (true); //COMPORT
+ GetTokenEOL (true); //IRQ
+ GetTokenEOL (true); //UART
+ GetTokenEOL (true); //PULSE
+ GetTokenEOL (true); //AUTOMATICDIALOUT
+
+ GetAlternatePath ("REMOTESOUNDPATH", &RemoteSounds);
+// GetAlternatePath ("PLAYERGRAPHICSPATH", &PlayerGraphics);
+ GetAlternatePath ("GAMELEVELPATH", &GameLevels);
+ GetAlternatePath ("BATTLELEVELPATH", &BattleLevels);
+
+ // Get CodeName
+ GetToken (true);
+ if (stricmp (token, "CODENAME"))
+ Error ("Can't find %s token.\n", "CODENAME");
+
+ GetTokenEOL (false);
+ memset (&CodeName[0], 0, sizeof (CodeName));
+ if (stricmp (name, "~"))
+ {
+
+ // Get First (MAXCODENAMELENGTH-1) characters
+ for (i=0; i<MAXCODENAMELENGTH-1; i++)
+ CodeName[i]=name[i];
+ }
+ GetTokenEOL (true); //NUMPLAYERS
+ GetTokenEOL (true); //NETWORKSOCKET
+ GetTokenEOL (true); //DEFAULT
+ for (i=0; i<14; i++)
+ GetTokenEOL (true); //NUMBERLIST
+
+ memset (CommbatMacros, 0, sizeof(CommbatMacros) );
+
+ for (i=0; i<MAXMACROS; i++)
+ {
+ GetToken (true);
+
+ GetTokenEOL (true);
+
+ if (name[0] != '~')
+ {
+ memcpy (&CommbatMacros[i].macro[0], &name[0], strlen (name));
+ CommbatMacros[i].avail = 1;
+ }
+ }
+
+ Z_Free (scriptbuffer);
+ }
+
+ GetPathFromEnvironment( filename, ApogeePath, ROTT );
+ if (access (filename, F_OK) == 0)
+ {
+ LoadScriptFile (filename);
+
+ GetTokenEOL (true); //PHONENUMBER
+
+ GetAlternateFile ("REMOTESOUNDFILE", &RemoteSounds);
+// GetAlternateFile ("PLAYERGRAPHICSFILE", &PlayerGraphics);
+ GetAlternateFile ("GAMELEVELFILE", &GameLevels);
+ GetAlternateFile ("COMMBATLEVELFILE", &BattleLevels);
+
+ Z_Free (scriptbuffer);
+
+ unlink (filename); // Delete ROTT.ROT
+ }
+}
+
+#endif
+
--- /dev/null
+++ b/rott/rt_cfg.h
@@ -1,0 +1,125 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_cfg_public
+#define _rt_cfg_public
+
+//****************************************************************************
+//
+// Public header for RT_CFG.C
+//
+//****************************************************************************
+
+
+//****************************************************************************
+//
+// GLOBALS
+//
+//****************************************************************************
+
+extern int FXMode;
+extern int MusicMode;
+extern int MUvolume;
+extern int FXvolume;
+extern boolean mouseenabled;
+extern boolean joystickenabled;
+extern boolean joypadenabled;
+extern boolean allowBlitzMoreMissileWeps;
+extern boolean enableAmmoPickups;
+extern boolean autoAimMissileWeps;
+extern boolean autoAim;
+
+extern int joystickport;
+extern int mouseadjustment;
+extern int threshold;
+extern int NumVoices;
+extern int NumChannels;
+extern int NumBits;
+#ifdef DOS
+extern int MidiAddress;
+#endif
+extern boolean stereoreversed;
+extern boolean cybermanenabled;
+extern boolean assassinenabled;
+extern boolean spaceballenabled;
+extern boolean AutoDetailOn;
+extern int DoubleClickSpeed;
+extern int fulllight;
+extern boolean BobbinOn;
+extern int Menuflipspeed;
+extern int DetailLevel;
+extern int fandc;
+extern int blanktime;
+extern char CodeName[9];
+#ifdef DOS
+extern char *ApogeePath;
+#else
+extern char ApogeePath[256];
+#endif
+
+extern int DefaultDifficulty;
+extern int DefaultPlayerCharacter;
+extern int DefaultPlayerColor;
+extern byte passwordstring[20];
+
+typedef struct
+{
+ char * path;
+ boolean avail;
+ char * file;
+} AlternateInformation;
+
+extern AlternateInformation RemoteSounds;
+extern AlternateInformation PlayerGraphics;
+extern AlternateInformation GameLevels;
+extern AlternateInformation BattleLevels;
+
+#define MAXMACROLENGTH 32
+#define MAXMACROS 10
+
+typedef struct {
+ byte avail;
+ char macro[MAXMACROLENGTH+1];
+} MacroList;
+
+extern MacroList CommbatMacros[MAXMACROS];
+
+//****************************************************************************
+//
+// PROTOTYPES
+//
+//****************************************************************************
+
+void WriteBattleConfig(void);
+void ReadScores (void);
+void ReadInt (const char * s1, int * val);
+void ReadBoolean (const char * s1, boolean * val);
+void ReadConfig (void);
+void WriteParameter (int file, const char * s1, int val);
+void WriteScores (void);
+void WriteConfig (void);
+void ReadSETUPFiles (void);
+void DeleteSoundFile ( void );
+void CheckVendor (void);
+void ConvertStringToPasswordString ( char * string );
+void ConvertPasswordStringToPassword ( void );
+void ConvertPasswordStringToString ( char * string );
+void ConvertPasswordToPasswordString ( void );
+
+#endif
--- /dev/null
+++ b/rott/rt_com.c
@@ -1,0 +1,799 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#ifdef DOS
+#include <conio.h>
+#include <dos.h>
+#include <process.h>
+#include <bios.h>
+#endif
+
+#include "rt_def.h"
+#include "_rt_com.h"
+#include "rt_com.h"
+#include "rt_util.h"
+#include "rt_in.h"
+#include "rt_crc.h"
+#include "rt_playr.h"
+#include "isr.h"
+#include "rt_msg.h"
+#include "rottnet.h"
+#include "rt_main.h"
+#include "rt_net.h"
+#include "rt_draw.h"
+//#include "rt_ser.h"
+//MED
+#include "memcheck.h"
+
+// GLOBAL VARIABLES
+
+// Same as in real mode
+rottcom_t * rottcom;
+int badpacket;
+int consoleplayer;
+byte ROTTpacket[MAXCOMBUFFERSIZE];
+int controlsynctime;
+
+// LOCAL VARIABLES
+#ifdef DOS
+static union REGS comregs;
+#endif
+
+static int ComStarted=false;
+static int transittimes[MAXPLAYERS];
+
+void SyncTime( int client );
+void SetTransitTime( int client, int time );
+
+#ifdef PLATFORM_UNIX
+
+static int sock = -1;
+
+static void ReadUDPPacket()
+{
+ rottcom->remotenode = -1;
+}
+
+static void WriteUDPPacket()
+{
+}
+
+#endif
+
+/*
+===============
+=
+= InitROTTNET
+=
+===============
+*/
+
+void InitROTTNET (void)
+{
+ int netarg;
+ long netaddress;
+
+ if (ComStarted==true)
+ return;
+ ComStarted=true;
+
+#ifdef DOS
+ netarg=CheckParm ("net");
+ netarg++;
+
+ netaddress=atol(_argv[netarg]);
+ rottcom=(rottcom_t *)netaddress;
+#elif defined(PLATFORM_UNIX)
+ /*
+ server-specific options:
+ -net: enables netplay
+ -server: run as rott server (default port 34858)
+ -port: select a non-default port for server
+ -host: select a non-default ip address to bind to
+ -standalone: run as standalone server
+ -remoteridicule: enable remote ridicule
+ -players: number of players to expect
+
+ client-specific options:
+ -master: request to have control
+ -net: specifies the host to connect to
+ -port: select a non-default port to connect to
+ */
+
+ rottcom = (rottcom_t *) malloc (sizeof(rottcom_t));
+ memset(rottcom, 0, sizeof(rottcom_t));
+
+ rottcom->ticstep = 1;
+ rottcom->gametype = 1;
+ rottcom->remotenode = -1;
+
+ if (CheckParm("server")) {
+ if (CheckParm("standalone")) {
+ rottcom->consoleplayer = 0;
+ } else {
+ rottcom->consoleplayer = 1;
+ }
+
+ if (CheckParm("remoteridicule")) {
+ rottcom->remoteridicule = 1;
+ } else {
+ rottcom->remoteridicule = 0;
+ }
+
+ netarg = CheckParm("players");
+ if (netarg && netarg < _argc-1) {
+ rottcom->numplayers = atoi(_argv[netarg+1]);
+ } else {
+ rottcom->numplayers = 2;
+ }
+
+ rottcom->client = 0;
+ } else {
+ rottcom->client = 1;
+
+ /* consoleplayer will be initialized after connecting */
+ /* numplayers will be initialized after connecting */
+ /* remoteridicule will be initialized after connecting */
+ }
+
+ /* client-server negotiation protocol, as inspired by ipxsetup.c */
+ /*
+ Best case:
+ client sends a HereIAm packet.
+ server replies with a YouAre packet, and broadcasts an Info packet
+ to the rest, indicating that the new player has joined.
+ client replies with an IAm packet
+ until all players have joined, the server broadcasts an Info packet
+ to the rest, indicating that another player is needed.
+ once server has enough players, it broadcasts an AllDone packet.
+
+ In detail:
+ Client state: HereIAm (initial connection)
+ Client sends HereIAm packet, waits for YouAre from server.
+ At timeout, Client resends HereIam
+ When client receives YouAre, client switches to IAm state
+
+ Client state: IAm
+ Client sends IAm packet, waits for IAmAck from server.
+ At timeout, Client resends IAm
+ When client receives IAmAck, client switches to WaitForDone state.
+
+ Client state: WaitForDone
+ Client waits for AllDone packet.
+ When client receives AllDone, it sends an AllDoneAck.
+ */
+
+#endif
+
+ remoteridicule = false;
+ remoteridicule = rottcom->remoteridicule;
+ if (rottcom->ticstep != 1)
+ remoteridicule = false;
+ if (remoteridicule == true)
+ {
+ if (!quiet)
+ printf("ROTTNET: LIVE Remote Ridicule Enabled\n");
+ }
+
+ if (!quiet)
+ {
+#ifdef DOS
+ printf("ROTTNET: Communicating on vector %ld\n",(long int)rottcom->intnum);
+#endif
+ printf("ROTTNET: consoleplayer=%ld\n",(long int)rottcom->consoleplayer);
+ }
+}
+
+/*
+================
+=
+= ReadPacket
+=
+================
+*/
+
+boolean ReadPacket (void)
+{
+ word crc;
+ word sentcrc;
+
+ // Set command (Get Packet)
+ rottcom->command=CMD_GET;
+
+ badpacket = 0;
+
+ // Check to see if a packet is ready
+
+#ifdef DOS
+ int386(rottcom->intnum,&comregs,&comregs);
+#elif PLATFORM_UNIX
+ ReadUDPPacket();
+#endif
+
+ // Is it ready?
+
+ if (rottcom->remotenode!=-1)
+ {
+ // calculate crc on packet
+ crc=CalculateCRC (&rottcom->data[0], rottcom->datalength-sizeof(word));
+
+ // get crc inside packet
+ sentcrc=*((word *)(&rottcom->data[rottcom->datalength-sizeof(word)]));
+
+ // are the crcs the same?
+ if (crc!=sentcrc)
+ {
+ badpacket=1;
+ SoftError("BADPKT at %d\n",GetTicCount());
+ }
+ if (networkgame==false)
+ {
+ rottcom->remotenode=server;
+ }
+ else
+ {
+ if ((IsServer==true) && (rottcom->remotenode>0))
+ rottcom->remotenode--;
+ }
+ memcpy(&ROTTpacket[0], &rottcom->data[0], rottcom->datalength);
+
+// SoftError( "ReadPacket: time=%ld size=%ld src=%ld type=%d\n",GetTicCount(), rottcom->datalength,rottcom->remotenode,rottcom->data[0]);
+
+#if 0
+ rottcom->command=CMD_OUTQUEBUFFERSIZE;
+ int386(rottcom->intnum,&comregs,&comregs);
+ SoftError( "outque size=%ld\n",*((short *)&(rottcom->data[0])));
+ rottcom->command=CMD_INQUEBUFFERSIZE;
+ int386(rottcom->intnum,&comregs,&comregs);
+ SoftError( "inque size=%ld\n",*((short *)&(rottcom->data[0])));
+#endif
+ return true;
+ }
+ else // Not ready yet....
+ return false;
+}
+
+
+/*
+=============
+=
+= WritePacket
+=
+=============
+*/
+
+void WritePacket (void * buffer, int len, int destination)
+{
+ word crc;
+
+ // set send command
+ rottcom->command=CMD_SEND;
+
+ // set destination
+ rottcom->remotenode=destination;
+
+ if (len>(int)(MAXCOMBUFFERSIZE-sizeof(word)))
+ {
+ Error("WritePacket: Overflowed buffer\n");
+ }
+
+ // copy local buffer into realmode buffer
+ memcpy((byte *)&(rottcom->data[0]),(byte *)buffer,len);
+
+ // calculate CRC
+ crc=CalculateCRC (buffer, len);
+
+ // put CRC into realmode buffer packet
+ *((word *)&rottcom->data[len])=crc;
+
+ // set size of realmode packet including crc
+ rottcom->datalength=len+sizeof(word);
+
+ if (*((byte *)buffer)==0)
+ Error("Packet type = 0\n");
+
+ if (networkgame==true)
+ {
+ if (IsServer==true)
+ rottcom->remotenode++; // server fix-up
+ }
+
+// SoftError( "WritePacket: time=%ld size=%ld src=%ld type=%d\n",GetTicCount(),rottcom->datalength,rottcom->remotenode,rottcom->data[0]);
+ // Send It !
+#ifdef DOS
+ int386(rottcom->intnum,&comregs,&comregs);
+#elif PLATFORM_UNIX
+ WriteUDPPacket();
+#endif
+
+#if 0
+ rottcom->command=CMD_OUTQUEBUFFERSIZE;
+ int386(rottcom->intnum,&comregs,&comregs);
+ SoftError( "outque size=%ld\n",*((short *)&(rottcom->data[0])));
+ rottcom->command=CMD_INQUEBUFFERSIZE;
+ int386(rottcom->intnum,&comregs,&comregs);
+ SoftError( "inque size=%ld\n",*((short *)&(rottcom->data[0])));
+#endif
+}
+
+
+
+
+/*
+=============
+=
+= ValidSyncPacket
+=
+=============
+*/
+boolean ValidSyncPacket ( synctype * sync )
+{
+ if (ReadPacket() && (badpacket==0))
+ {
+ if (((syncpackettype *)&(ROTTpacket[0]))->type==COM_SYNC)
+ {
+ memcpy(&(sync->pkt),&(ROTTpacket[0]),sizeof(sync->pkt));
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+=============
+=
+= SendSyncPacket
+=
+=============
+*/
+void SendSyncPacket ( synctype * sync, int dest)
+{
+ sync->pkt.type=COM_SYNC;
+ sync->sendtime=GetTicCount();
+ WritePacket( &(sync->pkt.type), sizeof(syncpackettype), dest );
+}
+
+
+/*
+=============
+=
+= SlavePhaseHandler
+=
+=============
+*/
+
+boolean SlavePhaseHandler( synctype * sync )
+{
+ boolean done;
+
+ done=false;
+
+ switch (sync->pkt.phase)
+ {
+ case SYNC_PHASE1:
+ break;
+ case SYNC_PHASE2:
+ ISR_SetTime(sync->pkt.clocktime);
+ break;
+ case SYNC_PHASE3:
+ sync->pkt.clocktime=GetTicCount();
+ break;
+ case SYNC_PHASE4:
+ ISR_SetTime(GetTicCount()-sync->pkt.delta);
+ sync->pkt.clocktime=GetTicCount();
+ break;
+ case SYNC_PHASE5:
+ ISR_SetTime(GetTicCount()-sync->pkt.delta);
+ sync->sendtime=sync->pkt.clocktime;
+ done=true;
+ break;
+ }
+ return done;
+}
+
+
+
+/*
+=============
+=
+= MasterPhaseHandler
+=
+=============
+*/
+
+boolean MasterPhaseHandler( synctype * sync )
+{
+ boolean done;
+
+ done=false;
+
+ switch (sync->pkt.phase)
+ {
+ case SYNC_PHASE1:
+ sync->pkt.phase=SYNC_PHASE2;
+ sync->pkt.clocktime=GetTicCount()+(sync->deltatime>>1);
+ break;
+ case SYNC_PHASE2:
+ sync->pkt.phase=SYNC_PHASE3;
+ break;
+ case SYNC_PHASE3:
+ sync->pkt.delta=sync->pkt.clocktime-GetTicCount()+(sync->deltatime>>1);
+ sync->pkt.phase=SYNC_PHASE4;
+ break;
+ case SYNC_PHASE4:
+ sync->pkt.phase=SYNC_PHASE5;
+ sync->pkt.delta=sync->pkt.clocktime-GetTicCount()+(sync->deltatime>>1);
+ sync->sendtime=GetTicCount()+SYNCTIME;
+ sync->pkt.clocktime=sync->sendtime;
+ done=true;
+ break;
+ }
+ return done;
+}
+
+
+/*
+=============
+=
+= ComSetTime
+=
+=============
+*/
+
+void ComSetTime ( void )
+{
+ int i;
+ syncpackettype * syncpacket;
+ boolean done=false;
+
+ syncpacket=(syncpackettype *)SafeMalloc(sizeof(syncpackettype));
+
+
+ // Sync clocks
+
+ if (networkgame==true)
+ {
+ if (IsServer==true)
+ {
+ for (i=0; i<numplayers; i++)
+ {
+ if (PlayerInGame(i)==false)
+ continue;
+ if (standalone==true)
+ SyncTime(i);
+ else if (i!=consoleplayer)
+ SyncTime(i);
+ if (standalone==true)
+ printf("ComSetTime: player#%ld\n",(long int)i);
+ }
+ }
+ else
+ {
+ SyncTime(0);
+ }
+ }
+ else // Modem 2-player game
+ {
+ if (consoleplayer==0)
+ SyncTime(server);
+ else
+ SyncTime(server);
+ }
+
+ if ( ( (networkgame==true) && (IsServer==true) ) ||
+ ( (networkgame==false) && (consoleplayer==0) )
+ ) // Master/Server
+ {
+ int nump;
+ int time;
+
+ syncpacket->type=COM_START;
+ syncpacket->clocktime=GetTicCount();
+ controlsynctime=syncpacket->clocktime;
+ if (networkgame==true)
+ nump=numplayers;
+ else
+ nump=1;
+
+ time = GetTicCount();
+
+ for (i=0; i<nump; i++)
+ {
+ WritePacket( &(syncpacket->type), sizeof(syncpackettype), i );
+ }
+
+ while (GetTicCount()<time+(VBLCOUNTER/4)) ;
+
+ for (i=0; i<nump; i++)
+ {
+ WritePacket( &(syncpacket->type), sizeof(syncpackettype), i );
+ }
+
+ if (standalone==true)
+ printf("ComSetTime: Start packets sent\n");
+ }
+ else // Slave/Client
+ {
+ while (done==false)
+ {
+ AbortCheck("ComSetTime aborted as client");
+
+ if (ReadPacket() && (badpacket==0))
+ {
+ memcpy(syncpacket,&(ROTTpacket[0]),sizeof(syncpackettype));
+ if (syncpacket->type==COM_START)
+ {
+ controlsynctime=syncpacket->clocktime;
+ done=true;
+ }
+ }
+ }
+ }
+ if (standalone==false)
+ {
+ AddMessage("All players synched.",MSG_SYSTEM);
+ ThreeDRefresh();
+ }
+ SafeFree(syncpacket);
+
+//
+// flush out any extras
+//
+ while (GetTicCount()<controlsynctime+VBLCOUNTER)
+ {
+ ReadPacket ();
+ }
+}
+
+/*
+=============
+=
+= InitialMasterSync
+=
+=============
+*/
+void InitialMasterSync ( synctype * sync, int client )
+{
+ boolean done=false;
+ int i;
+
+ if (networkgame==true)
+ {
+ for (i=0; i<numplayers; i++)
+ {
+ if (i<=client)
+ continue;
+ sync->pkt.type=COM_SYNC;
+ sync->pkt.phase=SYNC_MEMO;
+ sync->pkt.clocktime=client;
+ SendSyncPacket(sync,i);
+ }
+ }
+
+ // Initialize send time so as soon as we enter the loop, we send
+
+ sync->sendtime=GetTicCount()-SYNCTIME;
+
+ while (done==false)
+ {
+ sync->pkt.phase=SYNC_PHASE0;
+
+ AbortCheck("Initial sync aborted as master");
+ if ((sync->sendtime+SYNCTIME) <= GetTicCount())
+ SendSyncPacket(sync,client);
+ if (ValidSyncPacket(sync)==true)
+ {
+ if (sync->pkt.phase==SYNC_PHASE0)
+ {
+ int time=GetTicCount();
+
+ while (time+SYNCTIME>GetTicCount())
+ {
+ ReadPacket();
+ }
+ time=GetTicCount();
+ while (time+SYNCTIME>GetTicCount()) {}
+ done=true;
+ }
+ }
+ }
+}
+
+/*
+=============
+=
+= InitialSlaveSync
+=
+=============
+*/
+void InitialSlaveSync ( synctype * sync )
+{
+ boolean done=false;
+
+ while (done==false)
+ {
+ AbortCheck("Initial sync aborted as slave");
+ if (ValidSyncPacket(sync)==true)
+ {
+ if (sync->pkt.phase==SYNC_MEMO)
+ {
+ char str[50]="Server is synchronizing player ";
+ char str2[10];
+
+ strcat(str,itoa(sync->pkt.clocktime+1,str2,10));
+ AddMessage(str,MSG_SYSTEM);
+ ThreeDRefresh();
+ }
+ if (sync->pkt.phase==SYNC_PHASE0)
+ {
+ int time=GetTicCount();
+
+ SendSyncPacket(sync,server);
+ while (time+SYNCTIME>GetTicCount())
+ {
+ ReadPacket();
+ }
+ done=true;
+ }
+ }
+ }
+ AddMessage("Server is synchronizing your system",MSG_SYSTEM);
+ ThreeDRefresh();
+}
+
+
+/*
+=============
+=
+= SyncTime
+=
+=============
+*/
+
+void SyncTime( int client )
+{
+ int dtime[NUMSYNCPHASES];
+ boolean done;
+ int i;
+ synctype * sync;
+
+ sync=(synctype *)SafeMalloc(sizeof(synctype));
+
+ if ( ((networkgame==true) && (IsServer==true)) ||
+ ((networkgame==false) && (consoleplayer==0)) )
+ {
+ // Master
+
+ InitialMasterSync ( sync, client );
+
+ done=false;
+
+ // Initial setup for Master
+ // Initialize send time so as soon as we enter the loop, we send
+
+ sync->pkt.phase=SYNC_PHASE1;
+ sync->sendtime=GetTicCount()-SYNCTIME;
+
+ while (done==false)
+ {
+ // Master
+
+ AbortCheck("SyncTime aborted as master");
+
+ if ((sync->sendtime+SYNCTIME) <= GetTicCount())
+ SendSyncPacket(sync,client);
+
+ while (ValidSyncPacket(sync)==true)
+ {
+
+ // find average delta
+
+ sync->deltatime=0;
+
+ // calculate last delta
+
+ dtime[sync->pkt.phase]=GetTicCount()-sync->sendtime;
+
+ for (i=0; i<=sync->pkt.phase; i++)
+ sync->deltatime+=dtime[i];
+ if (i!=0)
+ sync->deltatime/=i;
+ else
+ Error("SyncTime: this should not happen\n");
+
+ done = MasterPhaseHandler( sync );
+
+ SendSyncPacket(sync,client);
+
+ }
+ }
+ }
+ else
+ {
+ // Slave
+
+ InitialSlaveSync ( sync );
+
+ done=false;
+
+ while (done==false)
+ {
+ // Slave
+
+ AbortCheck("SyncTime aborted as slave");
+
+ while (ValidSyncPacket(sync)==true)
+ {
+ done = SlavePhaseHandler( sync );
+
+ if (done==false)
+ SendSyncPacket(sync,server);
+
+ }
+ }
+ }
+
+ while (sync->sendtime > GetTicCount())
+ {
+ while (ReadPacket()) {}
+ }
+ while ((sync->sendtime+SYNCTIME) > GetTicCount())
+ {
+ }
+
+ if ( ((networkgame==true) && (IsServer==true)) ||
+ ((networkgame==false) && (consoleplayer==0)) )
+ SetTransitTime( client, (sync->deltatime>>1));
+
+ SafeFree(sync);
+}
+
+/*
+=============
+=
+= SetTransitTime
+=
+=============
+*/
+
+void SetTransitTime( int client, int time )
+{
+ transittimes[client]=time;
+}
+
+/*
+=============
+=
+= GetTransitTime
+=
+=============
+*/
+
+int GetTransitTime( int client )
+{
+ return transittimes[client];
+}
+
--- /dev/null
+++ b/rott/rt_com.h
@@ -1,0 +1,48 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_com_public
+#define _rt_com_public
+
+//***************************************************************************
+//
+// RT_COM.C
+//
+//***************************************************************************
+
+#define MAXPACKET 512
+
+#include "rottnet.h"
+
+extern int badpacket;
+extern int consoleplayer;
+extern byte ROTTpacket[MAXCOMBUFFERSIZE];
+
+extern int controlsynctime;
+
+
+//#define consoleplayer (rottcom->consoleplayer)
+
+void InitROTTNET (void);
+boolean ReadPacket (void);
+void WritePacket (void * buffer, int len, int destination);
+void ComSetTime (void);
+int GetTransitTime( int client );
+
+#endif
--- /dev/null
+++ b/rott/rt_crc.c
@@ -1,0 +1,134 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// CRC lib
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "rt_crc.h"
+//MED
+#include "memcheck.h"
+
+/* variables */
+static const unsigned short int crc16tab[256] =
+{
+ 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
+ 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
+ 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
+ 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
+ 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
+ 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
+ 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
+ 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
+ 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
+ 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
+ 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
+ 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
+ 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
+ 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
+ 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
+ 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
+ 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
+ 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
+ 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
+ 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
+ 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
+ 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
+ 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
+ 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
+ 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
+ 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
+ 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
+ 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
+ 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
+ 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
+ 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
+ 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
+};
+
+/* driver */
+#if 0
+main(argc,argv)
+int argc;
+char **argv;
+{
+ if(argc>2) perr("Usage: crcfast [filename]");
+ if(argc==2) strcpy(filename,argv[1]);
+ else
+ {
+ printf("\nEnter filename: ");
+ gets(filename);
+ }
+ if((fp=fopen(filename,"rb"))==NULL) perr("Can't open file");
+ num=0L;
+ crc16=crctt=0;
+ while((ch=fgetc(fp))!=EOF)
+ {
+ num++;
+ crc16=updatecrc(crc16,ch);
+// crctt=updcrc(crctt,ch);
+ }
+ fclose(fp);
+ printf("\nNumber of bytes = %lu\nCRC16 = %04X\nCRCTT = %04X",
+ num,crc16,crctt);
+}
+
+#endif
+
+/* update crc reverse */
+int updatecrc(int crc, int c)
+{
+ int tmp;
+ tmp=crc^c;
+ crc=(crc>>8)^crc16tab[tmp & 0xff];
+ return crc;
+}
+
+//******************************************************************************
+//
+// CalculateCRC ()
+//
+//******************************************************************************
+
+word CalculateCRC (byte *source, unsigned size)
+{
+ unsigned i;
+ int checksum;
+ int tmp;
+
+ checksum=0;
+
+ for (i = 0; i < size; i++)
+ {
+ tmp=checksum^(*(source++));
+ checksum=(checksum>>8)^crc16tab[tmp & 0xff];
+ }
+
+ return ((word)checksum);
+
+}
+
+
+
+
+
+
+
+
--- /dev/null
+++ b/rott/rt_crc.h
@@ -1,0 +1,24 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "rt_def.h"
+
+int updatecrc(int,int);
+word CalculateCRC (byte *source, unsigned size);
+
--- /dev/null
+++ b/rott/rt_debug.c
@@ -1,0 +1,1695 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "rt_def.h"
+#include "rt_debug.h"
+#include "isr.h"
+#include "rt_game.h"
+#include "rt_menu.h"
+#include "rt_build.h"
+#include "rt_str.h"
+#include "rt_vid.h"
+#include "rt_playr.h"
+#include "rt_main.h"
+#include "rt_util.h"
+#include "rt_draw.h"
+#include "rt_in.h"
+#include "z_zone.h"
+#include "rt_ted.h"
+#include "rt_view.h"
+#include "develop.h"
+#include "rt_msg.h"
+#include "rt_net.h"
+#include "rt_sound.h"
+#include "rt_stat.h"
+#include "rt_map.h"
+
+#include <stdlib.h>
+#include <ctype.h>
+//MED
+#include "memcheck.h"
+#include "w_wad.h"
+
+extern int iDemoNames;
+extern boolean iG_aimCross;
+
+
+extern void DisplayMessage (int num,int position);
+
+
+typedef struct {
+ char code[15];
+ byte length;
+} CodeStruct;
+
+enum
+{
+ RICOCHETING, //richocheting rockets
+ RICOCHETINGALT, //richocheting rockets alt
+ ENABLECHEAT, // enable cheats
+ ENABLECHEATALT, // enable cheats
+ SOMEITEMS, // three keys, more health
+ SOMEITEMSALT, // three keys, more health
+ INVULNERABLE, // normal god mode
+ INVULNERABLEALT, // normal god mode
+ WARP, // warp
+ WARPALT, // warp
+ ITEMS, // all keys, armor, 100% health
+ ITEMSALT, // all keys, armor, 100% health
+ GODMODEPWUP, // god mode powerup
+ GODMODEPWUPALT, // god mode powerup
+#if (SHAREWARE == 0)
+ DOGMODEPWUP, // dog mode powerup
+ DOGMODEPWUPALT, // dog mode powerup
+#endif
+ MERCURYPWUP, // mercury mode powerup
+ MERCURYPWUPALT, // mercury mode powerup
+ SHROOMSPWUP, // shrooms mode powerup
+ SHROOMSPWUPALT, // shrooms mode powerup
+ ELASTOPWUP, // elasto mode powerup
+ ELASTOPWUPALT, // elasto mode powerup
+ RESTARTGAME, // warp to level 1, start with pistol
+ RESTARTGAMEALT, // warp to level 1, start with pistol
+ HURTPLAYER, // hurt player 10%
+ HURTPLAYERALT, // hurt player 10%
+ TOMHALLMODE, // run fast all the time
+ TOMHALLMODEALT, // run fast all the time
+ NORMAL, // back to normal
+ NORMALALT, // back to normal
+ LIGHTDIMON, // light diminishing on
+ LIGHTDIMONALT, // light diminishing on
+ LIGHTDIMOFF, // light diminishing off
+ LIGHTDIMOFFALT, // light diminishing off
+ FOGON, // fog on (0x00 - 0x80 minmax)
+ FOGONALT, // fog on (0x00 - 0x80 minmax)
+ FOGOFF, // fog off (0x80 - 0xFF minmax)
+ FOGOFFALT, // fog off (0x80 - 0xFF minmax)
+ QUITGAME, // blow out of game
+ QUITGAMEALT, // blow out of game
+ ENDLEVEL, // end the current level
+ ENDLEVELALT, // end the current level
+ FANDCOFF, // floor and ceiling off
+ FANDCOFFALT, // floor and ceiling off
+ FANDCON, // floor and ceiling on
+ FANDCONALT, // floor and ceiling on
+ BULLETARMOR, // bullet proof armor
+ BULLETARMORALT, // bullet proof armor
+ FIREARMOR, // fire proof armor
+ FIREARMORALT, // fire proof armor
+ GASMASK, // gas mask
+ GASMASKALT, // gas mask
+ OUTFIT, // all keys, armor, 100% health, MP40, heatseek
+ OUTFITALT, // all keys, armor, 100% health, MP40, heatseek
+ KILLPLAYER, // kill player
+ KILLPLAYERALT, // kill player
+ RESTARTLEVEL, // re-enter level
+ RESTARTLEVELALT, // re-enter level
+ WEAPONTWOPISTOL, // give double pistol
+ WEAPONTWOPISTOLALT, // give double pistol
+ WEAPONMP40, // give mp40
+ WEAPONMP40ALT, // give mp40
+ WEAPONBAZOOKA, // give bazooka
+ WEAPONBAZOOKAALT, // give bazooka
+ WEAPONHEAT, // give heatseeker
+ WEAPONHEATALT, // give heatseeker
+ WEAPONDRUNK, // give drunk missile
+ WEAPONDRUNKALT, // give drunk missile
+ WEAPONFIREBOMB, // give firebomb
+ WEAPONFIREBOMBALT, // give firebomb
+ WEAPONFIREWALL, // give firewall
+ WEAPONFIREWALLALT, // give firewall
+ WEAPONGOD, // give godhand
+ WEAPONGODALT, // give godhand
+ AIMCROSS, // bna++
+ AIMCROSSALT, // give bna++
+
+#if (SHAREWARE == 0)
+
+ WEAPONSPLIT, // give split missile
+ WEAPONSPLITALT, // give split missile
+ WEAPONKES, // give kes
+ WEAPONKESALT, // give kes
+ WEAPONBAT, // give bat
+ WEAPONBATALT, // give bat
+ WEAPONDOG, // give dogmode
+ WEAPONDOGALT, // give dogmode
+#endif
+
+ MISSILECAMTOGGLE, // Turn missile cam on/off
+ MISSILECAMTOGGLEALT, // Turn missile cam on/off
+ HUDTOGGLE, // Turn HUD on/off
+ HUDTOGGLEALT, // Turn HUD on/off
+ ROTATIONFUN, // Rotation fun
+ DEMORECORD, // Start recording demo
+ DEMOEND, // End recording demo
+ DEMOPLAYBACK, // Playback demo
+ CRAZYGIBS, // Engine Killing Gibs
+ JUKEBOX, // JukeBox
+ JUKEBOXALT, // JukeBox
+ MAPCHEAT, // Map Cheat
+ MAPCHEATALT, // Map Cheat Alt,
+ MAXCODES
+};
+
+CodeStruct Codes[MAXCODES + 6] =
+{
+ {"TIHSHO", 6}, //richocheting rockets LT++
+ {"SIHTTNAWTNOD", 12}, //ricocheting rockets LT++
+ {"KCITSPID", 8}, // enable cheats
+ {"CCE\\", 4}, // enable cheats
+ {"REKCALS", 7}, // three keys, more health
+ {"MUB\\", 4}, // three keys, more health
+ {"NIJOHC", 6}, // normal god mode
+ {"WWW\\", 4}, // normal god mode
+ {"OTOG", 4}, // warp
+ {"LTG\\", 4}, // warp
+ {"SYOTXIS", 7}, // all keys, armor, 100% health
+ {"IAG\\", 4}, // all keys, armor, 100% health
+ {"DASOOT", 6}, // god mode powerup
+ {"DOG\\", 4}, // god mode powerup
+#if (SHAREWARE == 0)
+ {"FOOW", 4}, // dog mode powerup
+ {"GOD\\", 4}, // dog mode powerup
+#endif
+ {"YOBYLF", 6}, // mercury mode powerup
+ {"REM\\", 4}, // mercury mode powerup
+ {"PIRTDAB", 7}, // shrooms mode powerup
+ {"RHS\\", 4}, // shrooms mode powerup
+ {"GNIOB", 5}, // elasto mode powerup
+ {"ALE\\", 4}, // elasto mode powerup
+ {"SREBOOG", 7}, // warp to level 1, start with pistol
+ {"OOG\\", 4}, // warp to level 1, start with pistol
+ {"KCAHW", 5}, // hurt player 10%
+ {"FOO\\", 4}, // hurt player 10%
+ {"DEEPS", 5}, // run fast all the time
+ {"AFR\\", 4}, // run fast all the time
+ {"CINAP", 5}, // back to normal
+ {"NAP\\", 4}, // back to normal
+ {"NOMID", 5}, // light diminishing on
+ {"NOD\\", 4}, // light diminishing on
+ {"FFOMID", 6}, // light diminishing off
+ {"FOD\\", 4}, // light diminishing off
+ {"NODNOL", 6}, // fog on (0x00 - 0x80 minmax)
+ {"NOF\\", 4}, // fog on (0x00 - 0x80 minmax)
+ {"LONDON", 6}, // fog off (0x80 - 0xFF minmax)
+ {"FOF\\", 4}, // fog off (0x80 - 0xFF minmax)
+ {"SETAGOG", 7}, // blow out of game
+ {"R8L\\", 4}, // blow out of game
+ {"HCRAOG", 6}, // end the current level
+ {"LCE\\", 4}, // end the current level
+ {"683ATOG", 7}, // floor and ceiling off
+ {"NOC\\", 4}, // floor and ceiling off
+ {"684ATOG", 7}, // floor and ceiling on
+ {"FOC\\", 4}, // floor and ceiling on
+ {"EMTOOHS", 7}, // bullet proof armor
+ {"RAB\\", 4}, // bullet proof armor
+ {"EMNRUB", 6}, // fire proof armor
+ {"RAF\\", 4}, // fire proof armor
+ {"GNUDGNUL", 8}, // gas mask
+ {"RAG\\", 4}, // gas mask
+ {"KCAPTNUH", 8}, // all keys, armor, 100% health, MP40, heatseek
+ {"PFO\\", 4}, // all keys, armor, 100% health, MP40, heatseek
+ {"EM68", 4}, // kill player
+ {"EID\\", 4}, // kill player
+ {"REEN", 4}, // re-enter level
+ {"LER\\", 4}, // re-enter level
+ {"OOWNHOJ", 7}, // give double pistol
+ {"2WG\\", 4}, // give double pistol
+ {"EMGULP", 6}, // give mp40
+ {"3WG\\", 4}, // give mp40
+ {"ALLINAV", 7}, // give bazooka
+ {"4WG\\", 4}, // give bazooka
+ {"SEMITTOH", 8}, // give heatseeker
+ {"5WG\\", 4}, // give heatseeker
+ {"EZOOB", 5}, // give drunk missile
+ {"6WG\\", 4}, // give drunk missile
+ {"BMOBERIF", 8}, // give firebomb
+ {"7WG\\", 4}, // give firebomb
+ {"SENOB", 5}, // give firewall
+ {"8WG\\", 4}, // give firewall
+ {"AYEES", 5}, // give god hand
+ {"9WG\\", 4}, // give god hand
+ {"MIA", 3}, // give aim bna++
+ {"MIA\\", 4}, // give aim bna++
+
+
+
+#if (SHAREWARE == 0)
+
+ {"TILPS", 5}, // give split missile
+ {"AWG\\", 4}, // give split missile
+ {"HTAEDFOSEK", 10}, // give kes
+ {"BWG\\", 4}, // give kes
+ {"NUREMOH", 8}, // give bat
+ {"CWG\\", 4}, // give bat
+ {"OJUC", 4}, // give dog weapon
+ {"DWG\\", 4}, // give dog weapon
+#endif
+ {"EDIR", 4}, // give MISSILE CAM
+ {"MAC\\", 4}, // give Missile Cam
+ {"EREHW", 5}, // turn where am i on/off
+ {"DUH\\", 4}, // give hud
+ {"NUF\\", 4}, // Rotation fun
+ {"DROCER", 6}, // Demo RECORD
+ {"POTS", 4}, // Demo stop recording
+ {"YALP", 4}, // Demo Playback
+ {"GKE\\", 4}, // Engine Killing Gibs
+ {"ORTSEAM", 7}, // JukeBox
+ {"EEL\\", 4}, // JukeBox
+ {"REITRAC", 7}, // Map Cheat
+ {"PAM\\", 4}, // Map Cheat
+ {"UOY\\", 4}, // Secret Message
+ {"EVAH", 4}, // Secret Message
+ {"ON\\", 3}, // Secret Message
+ {"EFIL", 4} // Secret Message
+
+};
+
+
+
+
+/*
+================
+=
+= CheatSpawnItem
+=
+================
+*/
+
+void CheatSpawnItem (int item)
+{
+ SpawnStatic(player->tilex, player->tiley, item,-1);
+ LASTSTAT->z = player->z;
+ MakeStatActive(LASTSTAT);
+ LASTSTAT->flags|=FL_ABP;
+}
+
+
+/*
+================
+=
+= FixupPowerupsY
+=
+================
+*/
+
+void FixupPowerupsY (void)
+{
+ player->z = nominalheight;
+}
+
+
+/*
+================
+=
+= EnableCheatCodes
+=
+================
+*/
+
+void EnableCheatCodes (void)
+{
+ DebugOk ^= 1;
+
+ if (DebugOk)
+ AddMessage ("Cheat Codes \\cENABLED!", MSG_CHEAT);
+ else
+ AddMessage ("Cheat Codes \\cDISABLED!", MSG_CHEAT);
+}
+
+
+/*
+================
+=
+= ResetCheatCodes
+=
+================
+*/
+
+void ResetCheatCodes (void)
+{
+// godmode = false;
+}
+
+/*
+================
+=
+= DoMapCheat
+=
+================
+*/
+
+void DoMapCheat (void)
+{
+ AddMessage ("Entire Map Revealed!", MSG_CHEAT);
+ CheatMap ();
+}
+
+/*
+================
+=
+= DoGodMode
+=
+================
+*/
+
+void DoGodMode (void)
+{
+ if (godmode)
+ AddMessage ("Woundless With Weapons \\cOFF", MSG_CHEAT);
+ else
+ AddMessage ("Woundless With Weapons \\cON", MSG_CHEAT);
+
+ godmode ^= 1;
+}
+
+
+/*
+================
+=
+= DoWarp
+=
+================
+*/
+#include "byteordr.h"//bna++
+void DoWarp (void)
+{
+ /*
+ char str[10];
+ boolean esc;
+ int level;
+
+ CurrentFont = smallfont;
+
+ US_CenterWindow(26,3);
+ PrintY+=6;
+
+ US_Print(" Warp to level(1-99):");
+
+ VW_UpdateScreen();
+
+ ShutdownClientControls();
+
+ esc = !US_LineInput (px, py, str, NULL, true, 2, 25, 13);
+
+ if (!esc)
+ {
+ level = ParseNum (str);
+ if (level>0 && level<=99)
+ {
+ gamestate.mapon = level-1;
+ playstate = ex_warped;
+ gamestate.episode = GetEpisode (gamestate.mapon);
+ }
+ }
+
+ while (Keyboard[sc_Escape])
+ IN_UpdateKeyboard ();
+ IN_ClearKeyboardQueue ();
+
+ */
+
+ int level;
+
+
+ EnableScreenStretch();//bna++ shut on streech mode
+
+
+ MU_StoreSongPosition();
+ MU_StartSong( song_secretmenu);
+ StopWind();
+ ShutdownClientControls();
+
+ SetupMenuBuf();
+ SetUpControlPanel ();
+
+ level = CP_LevelSelectionMenu();
+
+ CleanUpControlPanel();
+ ShutdownMenuBuf();
+
+ //bna++ section
+ if (( playstate == ex_stillplaying )&&(iGLOBAL_SCREENWIDTH > 320)) {
+ pic_t *shape;
+ shape = ( pic_t * )W_CacheLumpName( "backtile", PU_CACHE, Cvt_pic_t, 1 );
+ DrawTiledRegion( 0, 16, iGLOBAL_SCREENWIDTH, iGLOBAL_SCREENHEIGHT - 32, 0, 16, shape );
+ DisableScreenStretch();//dont strech when we go BACK TO GAME
+ DrawPlayScreen(true);//repaint ammo and life stat
+ VW_UpdateScreen ();//update screen
+ }
+ //bna section end
+
+ EnableScreenStretch();//bna++ shut on streech mode
+ while( Keyboard[ sc_Escape ] )
+ {
+ IN_UpdateKeyboard();
+ }
+ IN_ClearKeyboardQueue();
+
+ if ((level == -1) || (level == gamestate.mapon))
+ {
+ MU_StartSong(song_level);
+ MU_RestoreSongPosition();
+ }
+
+ if ( level >= 0 )
+ {
+ playstate = ex_warped;
+ gamestate.mapon = level;
+
+ GetEpisode( gamestate.mapon );
+
+ VL_FadeOut (0, 255, 0, 0, 0, 20);
+ }
+ else
+ {
+ DisableScreenStretch();//dont strech when we go BACK TO GAME
+ SetupScreen(true);
+ }
+
+ StartupClientControls();
+}
+
+/*
+================
+=
+= DoJukeBox
+=
+================
+*/
+
+void DoJukeBox (void)
+
+{
+ if (iGLOBAL_SCREENWIDTH > 320) {
+ EnableScreenStretch();//bna++ shut on streech mode
+ }
+ StopWind();
+ ShutdownClientControls();
+
+ SetupMenuBuf();
+ SetUpControlPanel ();
+
+ MU_JukeBoxMenu();
+
+ CleanUpControlPanel();
+ ShutdownMenuBuf();
+
+ //bna++ section
+ if (( playstate == ex_stillplaying )&&(iGLOBAL_SCREENWIDTH > 320)) {
+ pic_t *shape;
+ shape = ( pic_t * )W_CacheLumpName( "backtile", PU_CACHE, Cvt_pic_t, 1 );
+ DrawTiledRegion( 0, 16, iGLOBAL_SCREENWIDTH, iGLOBAL_SCREENHEIGHT - 32, 0, 16, shape );
+ DisableScreenStretch();//dont strech when we go BACK TO GAME
+ DrawPlayScreen(true);//repaint ammo and life stat
+ VW_UpdateScreen ();//update screen
+ }
+ //bna section end
+
+ SetupScreen(true);
+
+ while( Keyboard[ sc_Escape ] )
+ {
+ IN_UpdateKeyboard();
+ }
+ IN_ClearKeyboardQueue();
+
+ StartupClientControls();
+}
+
+
+
+/*
+================
+=
+= DoNormalThing
+=
+================
+*/
+
+void DoNormalThing (void)
+{
+ AddMessage ("BACK TO NORMAL. AH.", MSG_CHEAT);
+
+ player->flags &= ~(FL_BPV|FL_AV|FL_GASMASK);
+ locplayerstate->protectiontime = 0;
+
+ if (player->flags & FL_ELASTO)
+ player->flags &= ~FL_NOFRICTION;
+ player->flags &= ~(FL_SHROOMS|FL_ELASTO|FL_FLEET);
+ locplayerstate->poweruptime = 0;
+
+ InitializeWeapons(locplayerstate);
+ locplayerstate->keys = 0;
+
+ DrawPlayScreen (false);
+}
+
+
+
+/*
+================
+=
+= DoItemCheat
+=
+================
+*/
+
+void DoItemCheat (void)
+{
+ AddMessage ("Items Aplenty!", MSG_CHEAT);
+
+ GivePoints (100000);
+ HealPlayer (99, player);
+
+ locplayerstate->keys = 0xF;
+ DrawKeys (false);
+
+ player->flags &= ~(FL_GASMASK|FL_BPV|FL_AV);
+ CheatSpawnItem(stat_bulletproof);
+
+ /*
+ player->flags |= FL_BPV;
+ player->flags &= ~(FL_GASMASK|FL_AV);
+ locplayerstate->protectiontime = POWERUPTICS;
+ GM_DrawBonus (stat_bulletproof);
+ */
+}
+
+/*
+================
+=
+= DoSomeItemCheat
+=
+================
+*/
+
+void DoSomeItemCheat (void)
+{
+ AddMessage ("Slacker pack!", MSG_CHEAT);
+
+ HealPlayer (40, player);
+
+ locplayerstate->keys = 0x7;
+ DrawKeys (false);
+}
+
+
+/*
+================
+=
+= DoGodModePowerup
+=
+================
+*/
+
+void DoGodModePowerup (void)
+{
+
+ if (PLAYER[0]->flags & FL_GODMODE)
+ return;
+
+ CheatSpawnItem(stat_godmode);
+}
+
+
+/*
+================
+=
+= DoDogModePowerup
+=
+================
+*/
+
+void DoDogModePowerup (void)
+{
+
+ if (PLAYER[0]->flags & FL_DOGMODE)
+ return;
+
+ CheatSpawnItem(stat_dogmode);
+}
+
+
+/*
+================
+=
+= DoMercuryModePowerup
+=
+================
+*/
+
+void DoMercuryModePowerup (void)
+{
+
+ if (PLAYER[0]->flags & FL_FLEET)
+ return;
+
+ CheatSpawnItem(stat_fleetfeet);
+}
+
+
+/*
+================
+=
+= DoElastoModePowerup
+=
+================
+*/
+
+void DoElastoModePowerup (void)
+{
+ if (PLAYER[0]->flags & FL_ELASTO)
+ return;
+
+ CheatSpawnItem(stat_elastic);
+}
+
+
+/*
+================
+=
+= DoShroomsModePowerup
+=
+================
+*/
+
+void DoShroomsModePowerup (void)
+{
+ if (PLAYER[0]->flags & FL_SHROOMS)
+ return;
+
+ AddMessage ("SHROOMS MODE POWERDOWN!", MSG_CHEAT);
+
+ CheatSpawnItem(stat_mushroom);
+}
+
+
+/*
+================
+=
+= RestartNormal
+=
+================
+*/
+
+void RestartNormal (void)
+{
+ EnableScreenStretch();//bna
+ DoNormalThing ();
+
+ AddMessage ("Restart to level 1", MSG_CHEAT);
+ gamestate.mapon = 0;
+ playstate = ex_warped;
+
+ GetEpisode (gamestate.mapon);
+}
+
+
+/*
+================
+=
+= HurtPlayer
+=
+================
+*/
+
+void HurtPlayer (void)
+{
+ int oldhitpoints;
+
+ oldhitpoints = player->hitpoints;
+ DamageThing (player, MaxHitpointsForCharacter(locplayerstate) / 10);
+ if (player->hitpoints < oldhitpoints)
+ AddMessage ("OUCH!!!!", MSG_CHEAT);
+
+ Collision(player,player,0,0);
+}
+
+
+/*
+================
+=
+= SetLightDiminish
+=
+================
+*/
+
+void SetLightDiminish (boolean off)
+{
+ if (off)
+ {
+ AddMessage ("Light Diminishing \\cOff", MSG_CHEAT);
+ fulllight = 1;
+ }
+ else
+ {
+ AddMessage ("Light Diminishing \\cOn", MSG_CHEAT);
+ fulllight = 0;
+ }
+}
+
+
+/*
+================
+=
+= SetFog
+=
+================
+*/
+
+void SetFog (boolean on)
+{
+ if (on)
+ {
+ AddMessage ("Fog \\cOn", MSG_CHEAT);
+ MAPSPOT(2,0,1)=105;
+ MAPSPOT(3,0,1)=0;
+ SetupLightLevels ();
+
+ }
+ else
+ {
+ AddMessage ("Fog \\cOff", MSG_CHEAT);
+ MAPSPOT(2,0,1)=104;
+ SetupLightLevels ();
+ }
+}
+
+
+
+/*
+================
+=
+= ToggleMissileCam
+=
+================
+*/
+
+void ToggleMissileCam (void)
+{
+ if (missilecam==false)
+ {
+ missilecam=true;
+ AddMessage ("Missile Cam \\cOn", MSG_CHEAT);
+ }
+ else
+ {
+ missilecam=false;
+ AddMessage ("Missile Cam \\cOff", MSG_CHEAT);
+ }
+}
+
+/*
+================
+=
+= ToggleHUD
+=
+================
+*/
+
+void ToggleHUD (void)
+{
+ if (HUD==false)
+ {
+ HUD=true;
+ AddMessage ("HUD \\cOn", MSG_CHEAT);
+ }
+ else
+ {
+ HUD=false;
+ AddMessage ("HUD \\cOff", MSG_CHEAT);
+ }
+}
+
+
+
+/*
+================
+=
+= EndLevel
+=
+================
+*/
+
+void EndLevel (void)
+{
+ AddMessage ("End Level", MSG_CHEAT);
+ playstate = ex_skiplevel;
+}
+
+
+/*
+================
+=
+= FloorandCeiling
+=
+================
+*/
+
+void FloorandCeiling (boolean off)
+{
+ if (off)
+ {
+ AddMessage ("Floor and Ceiling \\cON", MSG_CHEAT);
+ fandc = 1;
+ }
+ else
+ {
+ AddMessage ("Floor and Ceiling \\cOFF", MSG_CHEAT);
+ fandc = 0;
+ }
+}
+
+
+/*
+================
+=
+= GiveGasMask
+=
+================
+*/
+
+void GiveGasMask ()
+{
+
+ if (PLAYER[0]->flags & FL_GASMASK)
+ return;
+
+ CheatSpawnItem(stat_gasmask);
+}
+
+/*
+================
+=
+= GiveBulletProofArmor
+=
+================
+*/
+
+void GiveBulletProofArmor ()
+{
+ if (PLAYER[0]->flags & FL_BPV)
+ return;
+
+
+ CheatSpawnItem(stat_bulletproof);
+}
+
+/*
+================
+=
+= GiveAsbestoArmor
+=
+================
+*/
+
+void GiveAsbestoArmor ()
+{
+ if (PLAYER[0]->flags & FL_AV)
+ return;
+
+ CheatSpawnItem(stat_asbesto);
+}
+
+
+/*
+================
+=
+= OutfitPlayer
+=
+================
+*/
+void OutfitPlayer ()
+{
+ AddMessage ("Outfit Player!", MSG_CHEAT);
+
+ locplayerstate->keys = 0xF;
+ DrawKeys (false);
+ HealPlayer (99, player);
+
+ /*
+ player->flags |= FL_BPV;
+ player->flags &= ~(FL_GASMASK|FL_AV);
+ locplayerstate->protectiontime = POWERUPTICS;
+ GM_DrawBonus (stat_bulletproof);
+
+ GiveWeapon (player,wp_mp40);
+ */
+
+#if (SHAREWARE == 0)
+ CheatSpawnItem(stat_splitmissile);
+#else
+ CheatSpawnItem(stat_heatseeker);
+#endif
+
+
+}
+
+/*
+================
+=
+= KillPlayer
+=
+================
+*/
+
+void KillPlayer ()
+{
+ AddMessage ("Say Goodnight.", MSG_CHEAT);
+ playstate = ex_died;
+}
+
+
+
+/*
+================
+=
+= RestartCurrentLevel
+=
+================
+*/
+
+void RestartCurrentLevel (void)
+{
+ playstate = ex_warped;
+
+ GetEpisode (gamestate.mapon);
+}
+
+/*
+================
+=
+= EndDemo
+=
+================
+*/
+void EndDemo ( void )
+{
+ char str[10];
+ boolean esc;
+ int demonumber;
+
+ if (demorecord==false)
+ return;
+
+ ShutdownClientControls();
+
+ CurrentFont = smallfont;
+
+ demorecord = false;
+ US_CenterWindow (26, 4);
+ US_CPrint ("Save demo as:");
+ US_Print ("\n");
+ US_CPrint ("Demo Number (1-4):");
+
+ VW_UpdateScreen();
+
+ esc = !US_LineInput (px, py, str, NULL, true, 1, 25, 13);
+
+ if (!esc)
+ {
+ demonumber = ParseNum (str);
+ if ((demonumber > 0) && (demonumber < 5))
+ {
+ SaveDemo (demonumber);
+ }
+ }
+
+ IN_ClearKeysDown ();
+
+ while (Keyboard[sc_Enter])
+ IN_UpdateKeyboard ();
+ while (Keyboard[sc_Escape])
+ IN_UpdateKeyboard ();
+ IN_ClearKeyboardQueue ();
+
+ StartupClientControls();
+ DisableScreenStretch();
+}
+
+
+/*
+================
+=
+= RecordDemoQuery
+=
+================
+*/
+void RecordDemoQuery ( void )
+{
+ char str[10];
+ boolean esc;
+ int level;
+
+ ShutdownClientControls();
+
+ CurrentFont = smallfont;
+
+ US_CenterWindow (26, 5);
+ PrintY += 6;
+
+ US_CPrint ("Record Demo");
+ US_Print ("\n");
+#if (SHAREWARE==0)
+ US_CPrint ("Which level (1-36):");
+#else
+ US_CPrint ("Which level (1-8):");
+#endif
+
+ VW_UpdateScreen();
+
+ esc = !US_LineInput (px, py, str, NULL, true, 2, 25, 13);
+
+ if (!esc)
+ {
+ level = ParseNum (str);
+#if (SHAREWARE==0)
+ if ((level > 0) && (level < 37))
+#else
+ if ((level > 0) && (level < 9))
+#endif
+ {
+ EnableScreenStretch();//bna
+ gamestate.mapon = level-1;
+ playstate = ex_demorecord;
+ }
+ }
+
+ while (Keyboard[sc_Enter])
+ IN_UpdateKeyboard ();
+ while (Keyboard[sc_Escape])
+ IN_UpdateKeyboard ();
+ IN_ClearKeyboardQueue ();
+
+ StartupClientControls();
+}
+
+/*
+================
+=
+= PlaybackDemoQuery
+=
+================
+*/
+void PlaybackDemoQuery ( void )
+{
+ char str[10];
+ boolean esc;
+ int level;
+
+ ShutdownClientControls();
+
+ CurrentFont = smallfont;
+ US_CenterWindow (33, 4);
+ US_CPrint ("Playback demo");
+ US_Print ("\n");
+ US_CPrint ("Enter demo number (1-4):");
+
+ VW_UpdateScreen ();
+
+ esc = !US_LineInput (px, py, str, NULL, true, 1, 25, 13);
+
+ if (!esc)
+ {
+ level = ParseNum (str);
+ if ((level > 0) && (level < 5))
+ {
+ if (DemoExists (level) == true)
+ LoadDemo (level);
+ }
+ }
+
+ while (Keyboard[sc_Enter])
+ IN_UpdateKeyboard ();
+ while (Keyboard[sc_Escape])
+ IN_UpdateKeyboard ();
+ IN_ClearKeyboardQueue ();
+
+ StartupClientControls();
+
+ EnableScreenStretch();
+}
+
+/*
+================
+=
+= DebugKeys
+=
+================
+*/
+
+int DebugKeys (void)
+{
+#if (DEVELOPMENT == 1)
+ char str[10];
+ boolean esc;
+ int level;
+ int i,f,temp;
+ static int whichpowerup = 0;
+ static int whichprotection = 0;
+
+ if (Keyboard[sc_G]) // G = god mode
+ {
+ DoGodMode ();
+ while (Keyboard[sc_G])
+ IN_UpdateKeyboard ();
+ return 1;
+ }
+ else if (Keyboard[sc_Q]) // Q = fast quit
+ QuitGame ();
+ else if (Keyboard[sc_W]) // W = warp to level
+ {
+ DoWarp ();
+ return 1;
+ }
+ else if (Keyboard[sc_F]) // F = FPS
+ {
+ f=0;
+ for (i=0; i<VBLCOUNTER*10; i+=tics)
+ {
+ ThreeDRefresh();
+ DoSprites();
+ CalcTics ();
+ f++;
+ }
+
+ CurrentFont = smallfont;
+
+ US_CenterWindow (12,2);
+ temp=f*10;
+ SoftError("fps = %2ld.%2ld\n",temp/100,temp%100);
+
+ US_Print ("FPS=");
+ US_PrintUnsigned (temp/100);
+ US_Print (".");
+ US_PrintUnsigned (temp%100);
+
+ VW_UpdateScreen();
+ IN_Ack();
+
+ return 1;
+ }
+ else if (Keyboard[sc_H]) // H = hurt self
+ {
+ IN_ClearKeysDown ();
+ HurtPlayer ();
+ }
+ else if (Keyboard[sc_Z]) // Z = end level
+ {
+ EndLevel ();
+ }
+ else if (Keyboard[sc_P]) // P = step through powerups
+ {
+ whichpowerup++;
+ if (whichpowerup == 6)
+ whichpowerup = 0;
+
+ switch (whichpowerup)
+ {
+ case 0: // nothing
+ if (player->flags & FL_ELASTO)
+ player->flags &= ~FL_NOFRICTION;
+ player->flags &= ~(FL_SHROOMS|FL_ELASTO|FL_FLEET|FL_GODMODE|FL_DOGMODE);
+ locplayerstate->poweruptime = 0;
+ GM_UpdateBonus (0, true);
+ break;
+
+ case 1: // god mode
+ DoGodModePowerup ();
+ break;
+
+ case 2: // dog mode
+ DoDogModePowerup ();
+ break;
+
+ case 3: // fleet feet
+ DoMercuryModePowerup ();
+ break;
+
+ case 4: // elasto
+ DoElastoModePowerup ();
+ break;
+
+ case 5: // shrooms
+ DoShroomsModePowerup ();
+ break;
+ }
+
+ while (Keyboard[sc_P])
+ IN_UpdateKeyboard ();
+ }
+ else if (Keyboard[sc_A]) // step through armor
+ {
+ whichprotection++;
+ if (whichprotection == 4)
+ whichprotection = 0;
+
+ switch (whichprotection)
+ {
+ case 0: // nothing
+ player->flags &= ~(FL_BPV|FL_AV|FL_GASMASK);
+ locplayerstate->protectiontime = 0;
+ GM_UpdateBonus (0, false);
+ break;
+
+ case 1: // gas mask
+ GiveGasMask ();
+ break;
+
+ case 2: // armor
+ GiveBulletProofArmor ();
+ break;
+
+ case 3: // fire vest
+ GiveAsbestoArmor ();
+ break;
+ }
+
+ while (Keyboard[sc_A])
+ IN_UpdateKeyboard ();
+ }
+ else if (Keyboard[sc_O]) // O = outfit player
+ {
+ OutfitPlayer ();
+
+ IN_ClearKeysDown ();
+ IN_Ack ();
+ return 1;
+ }
+ else if (Keyboard[sc_K]) // K = kill self
+ {
+ IN_ClearKeysDown ();
+ locplayerstate->lives = -1;
+ KillPlayer ();
+ }
+ else if (Keyboard[sc_I]) // I = item cheat
+ {
+ DoItemCheat ();
+ return 1;
+ }
+ else if (Keyboard[53]) // \ = back to normal
+ {
+ DoNormalThing ();
+ return 1;
+ }
+ else if (Keyboard[sc_R])
+ {
+ RecordDemoQuery();
+ }
+ else if (Keyboard[sc_E])
+ {
+ EndDemo();
+ }
+ else if (Keyboard[sc_D])
+ {
+ PlaybackDemoQuery();
+ }
+#endif
+ return (0);
+}
+
+
+/*
+================
+=
+= WeaponCheat
+=
+================
+*/
+
+void WeaponCheat (int weapon)
+{
+ if ((player->flags & FL_GODMODE) || (player->flags & FL_DOGMODE))
+ return;
+
+ if ((weapon <= wp_mp40) && (PLAYERSTATE[0].HASBULLETWEAPON[weapon]))
+ return;
+
+ CheatSpawnItem(GetItemForWeapon(weapon));
+
+}
+
+
+
+/*
+================
+=
+= CheckCode ()
+=
+================
+*/
+
+extern boolean ricochetingRocketsEnabled;
+
+void CheckCode (int which)
+{
+ int pos = (LastLetter-1)&(MAXLETTERS-1);
+ int num = 0;
+ int start;
+
+ start = pos;
+
+ while ((toupper(LetterQueue[pos]) == Codes[which].code[num]) &&
+ (num < Codes[which].length))
+ {
+ pos = (pos-1)&(MAXLETTERS-1);
+ num++;
+ }
+
+ if (num == Codes[which].length)
+ {
+ // Kill last letter so the debug rtn will not keep triggering
+ LetterQueue[start] = 0;
+
+ switch (which)
+ {
+ case ENABLECHEAT:
+ case ENABLECHEATALT:
+ EnableCheatCodes ();
+ break;
+
+ case INVULNERABLE:
+ case INVULNERABLEALT:
+ DoGodMode ();
+ break;
+
+ case WARP:
+ case WARPALT:
+ DoWarp ();
+ break;
+
+ case ITEMS:
+ case ITEMSALT:
+ DoItemCheat ();
+ break;
+
+ case SOMEITEMS:
+ case SOMEITEMSALT:
+ DoSomeItemCheat ();
+ break;
+
+ case GODMODEPWUP:
+ case GODMODEPWUPALT:
+ DoGodModePowerup ();
+ break;
+
+#if (SHAREWARE == 0)
+ case DOGMODEPWUP:
+ case DOGMODEPWUPALT:
+ DoDogModePowerup ();
+ break;
+#endif
+
+ case MERCURYPWUP:
+ case MERCURYPWUPALT:
+ DoMercuryModePowerup ();
+ break;
+
+ case SHROOMSPWUP:
+ case SHROOMSPWUPALT:
+ DoShroomsModePowerup ();
+ break;
+
+ case ELASTOPWUP:
+ case ELASTOPWUPALT:
+ DoElastoModePowerup ();
+ break;
+
+ case RESTARTGAME:
+ case RESTARTGAMEALT:
+ RestartNormal ();
+ break;
+
+ case HURTPLAYER:
+ case HURTPLAYERALT:
+ HurtPlayer ();
+ break;
+
+ case TOMHALLMODE:
+ case TOMHALLMODEALT:
+ gamestate.autorun = true;
+ AddMessage("Autorun enabled!",MSG_CHEAT);
+ break;
+
+ case NORMAL:
+ case NORMALALT:
+ DoNormalThing ();
+ break;
+
+ case LIGHTDIMON:
+ case LIGHTDIMONALT:
+ SetLightDiminish (false);
+ break;
+
+ case LIGHTDIMOFF:
+ case LIGHTDIMOFFALT:
+ SetLightDiminish (true);
+ break;
+
+ case FOGON:
+ case FOGONALT:
+ SetFog (true);
+ break;
+
+ case FOGOFF:
+ case FOGOFFALT:
+ SetFog (false);
+ break;
+
+ case QUITGAME:
+ case QUITGAMEALT:
+ QuitGame ();
+ break;
+
+ case ENDLEVEL:
+ case ENDLEVELALT:
+ EndLevel ();
+ break;
+
+ case FANDCOFF:
+ case FANDCOFFALT:
+ FloorandCeiling (false);
+ break;
+
+ case FANDCON:
+ case FANDCONALT:
+ FloorandCeiling (true);
+ break;
+
+
+ case AIMCROSS:
+ case AIMCROSSALT:
+ if (iG_aimCross == 0) {
+ iG_aimCross = 1;
+ AddMessage("Crosshair on",MSG_GAME);
+ } else {
+ iG_aimCross = 0;
+ AddMessage("Crosshair off",MSG_GAME);
+ }
+ break;
+
+
+ case BULLETARMOR:
+ case BULLETARMORALT:
+ GiveBulletProofArmor ();
+ break;
+
+ case FIREARMOR:
+ case FIREARMORALT:
+ GiveAsbestoArmor ();
+ break;
+
+ case GASMASK:
+ case GASMASKALT:
+ GiveGasMask ();
+ break;
+
+ case OUTFIT:
+ case OUTFITALT:
+ OutfitPlayer ();
+ break;
+
+ case KILLPLAYER:
+ case KILLPLAYERALT:
+ KillPlayer ();
+ break;
+
+ case RESTARTLEVEL:
+ case RESTARTLEVELALT:
+ RestartCurrentLevel ();
+ break;
+
+
+ case WEAPONTWOPISTOL:
+ case WEAPONTWOPISTOLALT:
+ WeaponCheat(wp_twopistol);
+ break;
+
+ case WEAPONMP40:
+ case WEAPONMP40ALT:
+ WeaponCheat(wp_mp40);
+ break;
+
+ case WEAPONBAZOOKA:
+ case WEAPONBAZOOKAALT:
+ WeaponCheat(wp_bazooka);
+ break;
+ case WEAPONFIREBOMB:
+ case WEAPONFIREBOMBALT:
+ WeaponCheat(wp_firebomb);
+ break;
+
+ case WEAPONHEAT:
+ case WEAPONHEATALT:
+ WeaponCheat(wp_heatseeker);
+ break;
+
+ case WEAPONDRUNK:
+ case WEAPONDRUNKALT:
+ WeaponCheat(wp_drunk);
+ break;
+
+ case WEAPONFIREWALL:
+ case WEAPONFIREWALLALT:
+ WeaponCheat(wp_firewall);
+ break;
+
+ case WEAPONGOD:
+ case WEAPONGODALT:
+ WeaponCheat(wp_godhand);
+ break;
+
+
+#if (SHAREWARE == 0)
+
+ case WEAPONSPLIT:
+ case WEAPONSPLITALT:
+ WeaponCheat(wp_split);
+ break;
+
+ case WEAPONKES:
+ case WEAPONKESALT:
+ WeaponCheat(wp_kes);
+ break;
+
+ case WEAPONBAT:
+ case WEAPONBATALT:
+ WeaponCheat(wp_bat);
+ break;
+
+ case WEAPONDOG:
+ case WEAPONDOGALT:
+ WeaponCheat(wp_dog);
+ break;
+#endif
+
+ case MISSILECAMTOGGLE:
+ case MISSILECAMTOGGLEALT:
+ ToggleMissileCam();
+ break;
+
+ case HUDTOGGLE:
+ case HUDTOGGLEALT:
+ ToggleHUD();
+ break;
+
+ case ROTATIONFUN:
+ ShutdownClientControls();
+ RotationFun();
+ StartupClientControls();
+ SetupScreen( true );
+ break;
+ case DEMORECORD:
+ RecordDemoQuery();
+ break;
+ case DEMOEND:
+ EndDemo();
+ break;
+ case DEMOPLAYBACK:
+ PlaybackDemoQuery();
+ break;
+ case CRAZYGIBS:
+ if (gamestate.violence == vl_excessive)
+ {
+
+ ludicrousgibs ^= 1;
+ if (ludicrousgibs == true)
+ AddMessage("EKG mode on!",MSG_GAME);
+ else
+ AddMessage("EKG mode off!",MSG_GAME);
+ }
+ break;
+
+ case JUKEBOX:
+ case JUKEBOXALT:
+ DoJukeBox();
+ break;
+ case MAPCHEAT:
+ case MAPCHEATALT:
+ DoMapCheat();
+ break;
+ case RICOCHETING:
+ case RICOCHETINGALT:
+ ricochetingRocketsEnabled ^= 1;
+ if (ricochetingRocketsEnabled)
+ AddMessage("Ricocheting Rockets \\cEnabled!", MSG_CHEAT);
+ else
+ AddMessage("Ricocheting Rockets \\cDisabled!", MSG_CHEAT);
+ }
+ }
+}
+
+
+/*
+================
+=
+= CheckDebug ()
+=
+================
+*/
+
+void CheckDebug (void)
+{
+ int which;
+ if (DebugOk == false)
+ {
+ CheckCode (0); // Check for Debug switch only
+ CheckCode (1); // Check for Debug switch only
+ CheckCode (2); // Check for Slacker pack
+ CheckCode (3); // Check for Slacker pack
+ }
+ else
+ {
+ if (demoplayback==true)
+ {
+ return;
+ }
+ else if (demorecord==true)
+ {
+ CheckCode (DEMORECORD);
+ CheckCode (DEMOEND);
+ }
+ else
+ {
+ for (which = 0; which < MAXCODES; which++) // Check all debug codes
+ CheckCode (which);
+ }
+ }
+}
--- /dev/null
+++ b/rott/rt_debug.h
@@ -1,0 +1,34 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_debug_public
+#define _rt_debug_public
+
+//***************************************************************************
+//
+// RT_DEBUG.C
+//
+//***************************************************************************
+
+void ResetCheatCodes (void);
+int DebugKeys (void);
+void CheckDebug (void);
+void EndDemo ( void );
+
+#endif
--- /dev/null
+++ b/rott/rt_def.h
@@ -1,0 +1,544 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_def_public
+#define _rt_def_public
+
+
+// RT_DEF.H Zee big one
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "develop.h"
+#define SAVE_SCREEN 1
+
+#if PLATFORM_UNIX
+#include <unistd.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <dirent.h>
+#include <ctype.h>
+#endif
+
+#if (defined _MSC_VER)
+/* __int64 is built in. */
+#include <malloc.h>
+#include <fcntl.h>
+#include <io.h>
+//#define alloca(x) _alloca(x)
+#define access(x, y) _access(x, y)
+#define F_OK 0
+#elif (defined __GNUC__)
+#define __int64 long long
+#else
+#error please define your platform.
+#endif
+
+#if PLATFORM_DOS || PLATFORM_WIN32
+#define PATH_SEP_CHAR '\\'
+#define PATH_SEP_STR "\\"
+#elif PLATFORM_UNIX
+#define PATH_SEP_CHAR '/'
+#define PATH_SEP_STR "/"
+#define ROOTDIR "/"
+#define CURDIR "./"
+#elif PLATFORM_MACCLASSIC
+#define PATH_SEP_CHAR ':'
+#define PATH_SEP_STR ":"
+#else
+#error please define your platform.
+#endif
+
+#if (!defined MAX_PATH)
+#if (defined MAXPATHLEN)
+#define MAX_PATH MAXPATHLEN
+#elif (defined PATH_MAX)
+#define MAX_PATH PATH_MAX
+#else
+#define MAX_PATH 256
+#endif
+#endif
+
+//
+//
+//
+//***************************************************************************
+//
+// Global Constants
+//
+//***************************************************************************
+
+#ifndef DATADIR
+#define DATADIR ""
+#endif
+
+#undef PI
+#undef M_PI
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define PI 3.141592657
+#define LONG(a) ((int)a)
+#define M_PI 3.14159
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#ifndef O_TEXT
+#define O_TEXT 0
+#endif
+
+#ifndef min
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef max
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#if !PLATFORM_DOS
+#if PLATFORM_WIN32
+#define strcmpi(x, y) stricmp(x, y)
+#define _fstricmp(x, y) stricmp(x, y)
+#elif PLATFORM_UNIX
+#ifndef strcmpi
+#define strcmpi(x, y) strcasecmp(x, y)
+#endif
+
+#ifndef stricmp
+#define stricmp(x, y) strcasecmp(x, y)
+#endif
+
+#ifndef _fstricmp
+#define _fstricmp(x, y) strcasecmp(x, y)
+#endif
+
+char *strupr(char *);
+char *itoa(int, char *, int);
+char *ltoa(long, char *, int);
+char *ultoa(unsigned long, char *, int);
+char getch(void);
+long filelength(int handle);
+#else
+#error please define for your platform.
+#endif
+
+#if !defined(ANSIESC)
+#define STUB_FUNCTION fprintf(stderr,"STUB: %s at " __FILE__ ", line %d, thread %d\n",__FUNCTION__,__LINE__,getpid())
+#else
+#define STUB_FUNCTION
+#endif
+
+#define far
+#define cdecl
+#endif
+
+//***************************************************************************
+//
+// Screen Constants
+//
+//***************************************************************************
+#define VIEWGLOBAL 0x10000 // globals visable flush to wall
+/*
+#define VIEWWIDTH MAXSCREENWIDTH//320*2 // size of view window
+#define VIEWHEIGHT MAXSCREENHEIGHT//200*2
+#define MAXSCANLINES MAXSCREENHEIGHT//200*2 // size of ylookup table
+*/
+#define CHARWIDTH 2
+#define TILEWIDTH 4
+#define STATUSLINES 16
+
+
+
+//***************************************************************************
+//
+// Engine Constants
+//
+//***************************************************************************
+
+#define ANGLES 2048 // must be divisible by 4
+#define ANGLEQUAD (ANGLES/4)
+#define FINEANGLES 2048
+#define FINEANGLEQUAD (FINEANGLES/4)
+#define ANG90 (FINEANGLES/4)
+#define ANG180 (ANG90*2)
+#define ANG270 (ANG90*3)
+#define ANG360 (ANG90*4)
+#define VANG90 (ANGLES/4)
+#define VANG180 (VANG90*2)
+#define VANG270 (VANG90*3)
+#define VANG360 (VANG90*4)
+#define ANGLESDIV8 (ANGLES/8)
+#define MINDIST (0x5800l)
+#define PIXRADIUS 512
+#define FOCALLENGTH (0x5700l) // in global coordinates
+#define MAXTICS 10
+
+//***************************************************************************
+//
+// Map Constants/ macros
+//
+//***************************************************************************
+
+
+#define GLOBAL1 (1l<<16)
+#define TILEGLOBAL GLOBAL1
+#define PIXGLOBAL (GLOBAL1/64)
+#define TILESHIFT 16l
+#define UNSIGNEDSHIFT 8
+#define PLAYERSIZE 0x5700l // player radius
+#define MAPSIZE 128 // maps are 64*64 max
+#define NUMAREAS 47
+#define MAPSPOT(x,y,plane) (mapplanes[plane][MAPSIZE*(y)+(x)])
+#define AREATILE 107
+#define ICONARROWS 72
+#define PUSHABLETILE 80
+#define ELEVATORTILE 72
+#define ALTELEVATORTILE 106
+#define LASTLEVELVALUE 459
+
+#define AREANUMBER(x,y) (MAPSPOT((x),(y),0)-AREATILE)
+
+//***************************************************************************
+//
+// Scale Constants
+//
+//***************************************************************************
+
+#define SFRACBITS 16
+#define SFRACUNIT (0x10000)
+#define FRACUNIT (0x100)
+
+//***************************************************************************
+//
+// Actor Constants
+//
+//***************************************************************************
+
+#define RUNSPEED 6000
+#define MINACTORDIST 0x9000l
+#define MAXSTATS 400 // max number of lamps, bonus, etc
+
+#define MAXWALLTILES 105 // max number of wall tiles
+#define MAXACTORS 600
+#define NORTH 0
+#define EAST 1
+#define SOUTH 2
+#define WEST 3
+
+//***************************************************************************
+//
+// Input Defines - joystick, keyboard and mouse
+//
+//***************************************************************************
+
+#define MaxJoys 2
+#define MaxKbds 2
+#define MaxJoys 2
+#define NumCodes 128
+
+// Key definitions
+
+#define key_None 0
+#define key_Return 0x0d
+#define key_Enter key_Return
+#define key_Escape 0x1b
+#define key_Space 0x20
+#define key_BackSpace 0x08
+#define key_Tab 0x09
+#define key_Delete 0x7f
+
+#define ANGLEBITS 16
+#define ANGLEFRACMAX (FINEANGLES<<ANGLEBITS)
+
+
+//***************************************************************************
+//
+// SWIFT Constants
+//
+//***************************************************************************
+
+//
+// device type codes, returned in deviceType field (SWIFT_StaticData)
+//
+#define SWIFT_DEV_NONE 0
+#define SWIFT_DEV_CYBERMAN 1
+
+//
+// Dynamic device data
+//
+#define SDD_EXTERNAL_POWER_CONNECTED 1
+#define SDD_EXTERNAL_POWER_TOO_HIGH 2
+
+#define AX(r) ((r).x.eax)
+#define BX(r) ((r).x.ebx)
+#define CX(r) ((r).x.ecx)
+#define DX(r) ((r).x.edx)
+#define SI(r) ((r).x.esi)
+#define DI(r) ((r).x.edi)
+
+//***************************************************************************
+//
+// Global Types
+//
+//***************************************************************************
+
+/////////////////// GLOBAL DATA TYPES ///////////////////////////////
+
+
+typedef unsigned char byte;
+typedef unsigned short int word;
+typedef unsigned int longword;
+typedef int fixed;
+
+
+//////////////////////////////////////////////////////////////////////////
+
+
+////////////////// GLOBAL ENUMERATED TYPES ///////////////////////
+
+#ifdef __WATCOMC__
+typedef enum
+{ false,
+ true
+}
+boolean;
+#else
+/* boolean is serialized at the moment, and watcomc made it a byte. */
+
+typedef unsigned char boolean;
+enum {
+ false, true
+};
+#endif
+
+
+
+
+typedef enum {
+ east,
+ northeast,
+ north,
+ northwest,
+ west,
+ southwest,
+ south,
+ southeast,
+ nodir
+} dirtype;
+
+typedef enum
+{ SPRITE,
+ WALL,
+ ACTOR,
+ DOOR,
+ PWALL,
+ MWALL
+}
+thingtype;
+
+#define NUMTXBUTTONS 16
+enum {
+ bt_nobutton=-1,
+ bt_attack=0,
+ bt_strafe=1,
+ bt_run=2,
+ bt_use=3,
+ bt_lookup=4,
+ bt_lookdown=5,
+ bt_swapweapon=6,
+ bt_dropweapon=7,
+ bt_horizonup=8,
+ bt_horizondown=9,
+ bt_pistol=10,
+ bt_dualpistol=11,
+ bt_mp40=12,
+ bt_missileweapon=13,
+ bt_autorun=14,
+ bt_recordsound=15,
+ bt_strafeleft=16,
+ bt_straferight=17,
+ bt_turnaround=18,
+ bt_aimbutton=19,
+ di_north=20,
+ di_east=21,
+ di_south=22,
+ di_west=23,
+ bt_map=24,
+ bt_message=25,
+ bt_directmsg=26,
+ NUMBUTTONS
+};
+
+
+#if (SHAREWARE == 0)
+#define MAXWEAPONS 13
+#else
+#define MAXWEAPONS 9
+#endif
+
+
+typedef enum { wp_pistol,
+ wp_twopistol,
+ wp_mp40,
+ wp_bazooka,
+ wp_heatseeker,
+ wp_drunk,
+ wp_firebomb,
+ wp_firewall,
+ wp_godhand,
+
+#if (SHAREWARE == 0)
+ wp_split,
+ wp_kes,
+ wp_bat,
+ wp_dog
+#endif
+
+ } weapontype;
+
+
+
+enum {
+ gd_baby,
+ gd_easy,
+ gd_medium,
+ gd_hard
+};
+
+
+typedef enum {
+ ex_stillplaying,
+ ex_completed,
+ ex_died,
+ ex_warped,
+ ex_resetgame,
+ ex_loadedgame,
+ ex_victorious,
+ ex_abort,
+ ex_demodone,
+ ex_skiplevel,
+ ex_secretlevel,
+ ex_secretdone,
+ ex_titles,
+ ex_demorecord,
+ ex_demoplayback,
+
+ ex_bossdied,
+ ex_gameover,
+ ex_battledone
+} exit_t;
+
+// Types for cache lumps (for endian converters)
+enum {
+ cache_other,
+ cache_pic_t,
+ cache_lpic_t,
+ cache_font_t,
+ cache_lbm_t,
+ cache_patch_t,
+ cache_transpatch_t,
+ cache_cfont_t
+};
+
+////////////////////////////////////////////////////////////////////////////
+
+///////////////// GLOBAL STRUCTURE TYPES //////////////////////////
+
+
+//=================== SHARED FLAGS =====================================//
+
+#define FL_SHOOTABLE 0x01
+#define FL_ACTIVE 0x02
+#define FL_VISIBLE 0x08
+#define FL_NOFRICTION 0x100 //
+#define FL_DYING 0x1000
+#define FL_ALTERNATE 0x20000
+#define FL_GODSTRUCK 0x80000
+#define FL_ABP 0x400000
+#define FL_BLOCK 0x800000
+#define FL_HBM 0x1000000
+#define FL_RIDING 0x2000000
+#define FL_SOLIDCOLOR 0x4000000
+#define FL_SEEN 0x8000000
+#define FL_COLORED 0x10000000
+#define FL_FULLLIGHT 0x80000000
+
+//=================== ACTOR FLAGS =====================================//
+
+#define FL_NEVERMARK 4
+#define FL_ATTACKMODE 0x10
+#define FL_FIRSTATTACK 0x20
+#define FL_ISFIRE 0x20
+#define FL_AMBUSH 0x40
+#define FL_NONMARK 0x80
+#define FL_DONE 0x200 // used by push column
+#define FL_DODGE 0x400 // "
+#define FL_STUCK 0x800 //
+#define FL_HASAUTO 0x2000
+#define FL_FALLINGOBJECT 0x4000
+#define FL_KEYACTOR 0x8000
+#define FL_HEAD 0x40000
+#define FL_TARGET 0x200000
+#define FL_FLIPPED 0x40000000
+#define FL_CRAZY 0x40000000
+
+
+//================== PLAYER FLAGS ======================================//
+
+#define FL_BPV 0x10
+#define FL_SHROOMS 0x20
+#define FL_AV 0x40
+#define FL_ELASTO 0x200
+#define FL_FLEET 0x400
+#define FL_PUSHED 0x2000
+#define FL_PAIN 0x4000
+#define FL_GODMODE 0x8000
+#define FL_DOGMODE 0x10000
+#define FL_GASMASK 0x100000
+#define FL_DESIGNATED 0x20000000
+#define FL_DIDTAG 0x40000000
+
+//================== SPRITE FLAGS ======================================//
+
+#define NOTHING -1
+#define FL_BONUS 0x04
+#define FL_LIGHT 0x20
+#define FL_CHANGES 0x40
+#define FL_BACKWARDS 0x100
+#define FL_BANDF 0x200
+#define FL_HEAT 0x400
+#define FL_LIGHTOFF 0x800
+#define FL_ACTOR 0x1000
+#define FL_ROTATING 0x2000
+#define FL_RESPAWN 0x4000
+#define FL_WOODEN 0x8000
+#define FL_METALLIC 0x10000
+#define FL_EARTHEN 0x20000
+#define FL_LIGHTON 0x40000
+#define FL_FADING 0x80000
+#define FL_DEADBODY 0x100000
+#define FL_WEAPON 0x200000
+#define FL_TRANSLUCENT 0x2000000
+#define FL_HEIGHTFLIPPABLE 0x40000000
+
+#endif
--- /dev/null
+++ b/rott/rt_dmand.c
@@ -1,0 +1,400 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#ifdef DOS
+#include <mem.h>
+#endif
+
+#include "rt_def.h"
+#include "rt_util.h"
+#include "rt_sound.h"
+#include "rt_net.h"
+#include "rt_dmand.h"
+#include "_rt_dman.h"
+#include "fx_man.h"
+#include "develop.h"
+//MED
+#include "memcheck.h"
+
+static boolean Recording=false;
+static boolean Feeder=false;
+static byte * RecordingBuffer;
+static int Playingvoice;
+static int RecordingPointer;
+static int FeederPointer;
+static boolean Playback=false;
+static boolean Playing=false;
+static byte * PlaybackBuffer;
+static int PlaybackPointer;
+static int PlayingPointer;
+static boolean RecordingSemaphore=false;
+
+//#define FX_StartDemandFeedPlayback MV_StartDemandFeedPlayback
+//#define FX_StartRecording MV_StartRecording
+//#define FX_StopRecord MV_StopRecord
+//#include "multivoc.h"
+
+//***************************************************************************
+//
+// SD_UpdatePlaybackSound - Update playback of a sound in chunks
+//
+//***************************************************************************
+void SD_UpdatePlaybackSound ( char ** ptr, unsigned long * length )
+{
+ if ( Playing==false )
+ {
+ *ptr = NULL;
+ *length = 0;
+ return;
+ }
+ if (PlayingPointer==PlaybackPointer)
+ {
+ *ptr = NULL;
+ *length = 0;
+ if (Playback==false)
+ {
+ FX_StopSound( Playingvoice );
+ SafeFree ( PlaybackBuffer );
+ Playing=false;
+ }
+ return;
+ }
+
+ *length=PLAYBACKDELTASIZE;
+
+ if (PlayingPointer==-1)
+ {
+ *ptr = NULL;
+ *length = 0;
+ return;
+ }
+
+ *ptr=&PlaybackBuffer[PlayingPointer];
+
+ PlayingPointer = (PlayingPointer + *length) &
+ (PLAYBACKBUFFERSIZE - 1);
+}
+
+//***************************************************************************
+//
+// SD_StartIncomingSound - Setup to receive an incoming sound in chunks
+//
+//***************************************************************************
+
+void SD_StartIncomingSound ( void )
+{
+ if (SD_Started==false)
+ return;
+ if ( ( Recording==true ) || ( Playback==true ) )
+ {
+ return;
+ }
+
+ Playback=true;
+ PlaybackBuffer = SafeMalloc (PLAYBACKBUFFERSIZE);
+ Playing = false;
+ PlayingPointer = -1;
+ PlaybackPointer = 0;
+
+ Playingvoice = FX_StartDemandFeedPlayback ( SD_UpdatePlaybackSound,
+ RECORDINGSAMPLERATE,
+ 0, 255, 255, 255, 255, -1);
+ if (Playingvoice==0)
+ {
+ SafeFree(PlaybackBuffer);
+ Playback=false;
+ }
+}
+
+//***************************************************************************
+//
+// SD_StopIncomingSound - Stop receiving an incoming sound and playback
+//
+//***************************************************************************
+
+void SD_StopIncomingSound ( void )
+{
+ if (SD_Started==false)
+ return;
+ Playback=false;
+}
+
+
+//***************************************************************************
+//
+// SD_UpdateIncomingSound - Update an incoming sound
+//
+//***************************************************************************
+
+void SD_UpdateIncomingSound ( byte * ptr, word length )
+{
+ int amount;
+
+ if (SD_Started==false)
+ return;
+
+ if ( Playback==false )
+ {
+ return;
+ }
+ amount=length;
+ if (PlaybackPointer+length > PLAYBACKBUFFERSIZE)
+ amount=PLAYBACKBUFFERSIZE-PlaybackPointer;
+ memcpy ( &PlaybackBuffer[PlaybackPointer],
+ ptr, amount);
+ PlaybackPointer = (PlaybackPointer + amount) &
+ (PLAYBACKBUFFERSIZE - 1);
+
+ ptr+=amount;
+
+ if (length!=amount)
+ {
+ amount=length-amount;
+ memcpy ( &PlaybackBuffer[PlaybackPointer],
+ ptr, amount);
+ PlaybackPointer = (PlaybackPointer + amount) &
+ (PLAYBACKBUFFERSIZE - 1);
+ }
+
+ if (PlayingPointer==-1)
+ {
+ Playing=true;
+ PlayingPointer=0;
+ }
+ if (PlaybackPointer==PlayingPointer)
+ {
+ Playback=false;
+ }
+}
+
+//***************************************************************************
+//
+// SD_UpdateRecordingSound - Update recording a sound in chunks
+//
+//***************************************************************************
+extern int whereami;
+void SD_UpdateRecordingSound ( char * ptr, int length )
+{
+ int amount;
+
+ whereami = 69;
+ if ( Recording==false )
+ {
+ return;
+ }
+ whereami = 70;
+ amount=length;
+ if (RecordingPointer+length > RECORDINGBUFFERSIZE)
+ amount=RECORDINGBUFFERSIZE-RecordingPointer;
+ memcpy ( &RecordingBuffer[RecordingPointer],
+ ptr, amount);
+ whereami = 71;
+ RecordingPointer = (RecordingPointer + amount) &
+ (RECORDINGBUFFERSIZE - 1);
+
+ if (length!=amount)
+ {
+ ptr += amount;
+ amount=length-amount;
+ memcpy ( &RecordingBuffer[RecordingPointer],
+ ptr, amount);
+ RecordingPointer = (RecordingPointer + amount) &
+ (RECORDINGBUFFERSIZE - 1);
+ }
+ whereami = 72;
+ if (Feeder == false)
+ {
+ Feeder = true;
+ }
+
+ whereami = 73;
+ if (RecordingPointer==FeederPointer)
+ {
+ Recording=false;
+ }
+ whereami = 74;
+}
+
+//***************************************************************************
+//
+// SD_StartRecordingSound - Start recording a sound in chunks
+//
+//***************************************************************************
+
+boolean SD_StartRecordingSound ( void )
+{
+ int status;
+
+ if (SD_Started==false)
+ return false;
+ if (remoteridicule == false)
+ return false;
+ if ( ( Recording==true ) || ( Playback==true ) || (Feeder==true))
+ {
+ return false;
+ }
+ Recording=true;
+ RecordingBuffer = SafeMalloc (RECORDINGBUFFERSIZE);
+ Feeder = false;
+ FeederPointer = -1;
+ RecordingPointer = 0;
+
+ status=FX_StartRecording( RECORDINGSAMPLERATE, SD_UpdateRecordingSound);
+
+ if (status!=FX_Ok)
+ {
+ Recording=false;
+ SafeFree(RecordingBuffer);
+ return false;
+ }
+
+ return true;
+}
+
+//***************************************************************************
+//
+// SD_StopRecordingSound - Stop recording a sound
+//
+//***************************************************************************
+
+void SD_StopRecordingSound ( void )
+{
+ if (SD_Started==false)
+ return;
+ if (Recording == true)
+ {
+ FX_StopRecord();
+ Recording=false;
+ }
+}
+
+//***************************************************************************
+//
+// SD_SetRecordingActive - Set the recording active flag
+//
+//***************************************************************************
+
+void SD_SetRecordingActive ( void )
+{
+ RecordingSemaphore=true;
+}
+
+//***************************************************************************
+//
+// SD_ClearRecordingActive - Clear the recording active flag
+//
+//***************************************************************************
+
+void SD_ClearRecordingActive ( void )
+{
+ RecordingSemaphore=false;
+}
+
+//***************************************************************************
+//
+// SD_RecordingActive - Check if recording is active on some system
+//
+//***************************************************************************
+
+boolean SD_RecordingActive ( void )
+{
+ return RecordingSemaphore;
+}
+
+//***************************************************************************
+//
+// SD_GetSoundData - Returns next piece of sound data, returns:
+//
+// nodata if no sound data is ready
+// newsound if it is the start of a new sound
+// data is also returned;
+// endsound if the sound is finished
+// data if data is ready
+//
+//***************************************************************************
+
+recordstate SD_GetSoundData ( byte * data, word length )
+{
+ recordstate status=rs_data;
+ int amount;
+
+ if (SD_Started==false)
+ return rs_nodata;
+
+ if (Feeder==false)
+ return rs_nodata;
+
+ if (FeederPointer==RecordingPointer)
+ {
+ if (Recording==false)
+ {
+ SafeFree(RecordingBuffer);
+ Feeder=false;
+ return rs_endsound;
+ }
+ else
+ {
+ return rs_nodata;
+ }
+ }
+
+ if (FeederPointer==-1)
+ {
+ status=rs_newsound;
+ FeederPointer=0;
+ }
+
+ amount=length;
+
+ if (FeederPointer+length > RECORDINGBUFFERSIZE)
+ amount=RECORDINGBUFFERSIZE-FeederPointer;
+ memcpy ( data, &RecordingBuffer[FeederPointer], amount);
+
+ FeederPointer = (FeederPointer + amount) &
+ (RECORDINGBUFFERSIZE - 1);
+
+ data += amount;
+
+ if (length!=amount)
+ {
+ amount=length-amount;
+ memcpy ( data, &RecordingBuffer[FeederPointer], amount);
+ FeederPointer = (FeederPointer + amount) &
+ (RECORDINGBUFFERSIZE - 1);
+ }
+
+ return status;
+}
+
+//***************************************************************************
+//
+// SD_SoundDataReady - Returns true if data is ready
+//
+//***************************************************************************
+
+boolean SD_SoundDataReady ( void )
+{
+ if (SD_Started==false)
+ return false;
+ return Feeder;
+}
+
+
+
--- /dev/null
+++ b/rott/rt_dmand.h
@@ -1,0 +1,114 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_dmand_public
+#define _rt_dmand_public
+
+typedef enum {
+ rs_nodata,
+ rs_newsound,
+ rs_endsound,
+ rs_data
+} recordstate;
+
+//***************************************************************************
+//
+// SD_StartIncomingSound - Setup to receive an incoming sound in chunks
+//
+//***************************************************************************
+
+void SD_StartIncomingSound ( void );
+
+//***************************************************************************
+//
+// SD_StopIncomingSound - Stop receiving an incoming sound and playback
+//
+//***************************************************************************
+
+void SD_StopIncomingSound ( void );
+
+//***************************************************************************
+//
+// SD_UpdateIncomingSound - Update an incoming sound
+//
+//***************************************************************************
+
+void SD_UpdateIncomingSound ( byte * data, word length );
+
+//***************************************************************************
+//
+// SD_GetSoundData - Returns next piece of sound data, returns:
+//
+// nodata if no sound data is ready
+// newsound if it is the start of a new sound
+// data is also returned;
+// data if data is ready
+//
+//***************************************************************************
+
+recordstate SD_GetSoundData ( byte * data, word length );
+
+//***************************************************************************
+//
+// SD_SoundDataReady - Returns true if data is ready
+//
+//***************************************************************************
+
+boolean SD_SoundDataReady ( void );
+
+//***************************************************************************
+//
+// SD_SetRecordingActive - Set the recording active flag
+//
+//***************************************************************************
+
+void SD_SetRecordingActive ( void );
+
+//***************************************************************************
+//
+// SD_ClearRecordingActive - Clear the recording active flag
+//
+//***************************************************************************
+
+void SD_ClearRecordingActive ( void );
+
+//***************************************************************************
+//
+// SD_RecordingActive - Check if recording is active on some system
+//
+//***************************************************************************
+
+boolean SD_RecordingActive ( void );
+
+//***************************************************************************
+//
+// SD_StartRecordingSound - Start recording a sound in chunks
+//
+//***************************************************************************
+
+boolean SD_StartRecordingSound ( void );
+
+//***************************************************************************
+//
+// SD_StopRecordingSound - Stop recording a sound
+//
+//***************************************************************************
+void SD_StopRecordingSound ( void );
+
+#endif
--- /dev/null
+++ b/rott/rt_door.c
@@ -1,0 +1,4421 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "rt_def.h"
+#include "rt_sound.h"
+#include "rt_door.h"
+#include "rt_actor.h"
+#include "rt_stat.h"
+#include "_rt_door.h"
+#include "z_zone.h"
+#include "w_wad.h"
+#include "rt_ted.h"
+#include "rt_draw.h"
+#include "rt_main.h"
+#include "rt_playr.h"
+#include "rt_util.h"
+#include "rt_menu.h"
+#include "rt_ted.h"
+#include "rt_msg.h"
+#include "rt_game.h"
+#include "rt_vid.h"
+#include "rt_net.h"
+#include "isr.h"
+#include "develop.h"
+#include "rt_rand.h"
+#include "engine.h"
+#include <stdlib.h>
+#include <string.h>
+//MED
+#include "memcheck.h"
+
+/*=============================================================================
+
+ DOORS
+
+doorobjlist[] holds most of the information for the doors
+
+Open doors conect two areas, so sounds will travel between them and sight
+ will be checked when the player is in a connected area.
+
+Areaconnect is incremented/decremented by each door. If >0 they connect
+
+Every time a door opens or closes the areabyplayer matrix gets recalculated.
+ An area is true if it connects with the player's current spor.
+
+=============================================================================
+*/
+
+
+// Global Variables
+
+
+#define ELEVATORMUSICTIME 560
+
+elevator_t ELEVATOR[MAXELEVATORS];
+int _numelevators;
+animmaskedwallobj_t* FIRSTANIMMASKEDWALL,*LASTANIMMASKEDWALL;
+maskedwallobj_t* FIRSTMASKEDWALL,*LASTMASKEDWALL;
+byte touchindices[MAPSIZE][MAPSIZE],lasttouch;
+touchplatetype *touchplate[MAXTOUCHPLATES],*lastaction[MAXTOUCHPLATES];
+
+byte numactions[MAXTOUCHPLATES];
+int totalactions;
+
+byte TRIGGER[MAXTOUCHPLATES];
+doorobj_t *doorobjlist[MAXDOORS];
+int doornum;
+maskedwallobj_t *maskobjlist[MAXMASKED];
+int maskednum;
+
+pwallobj_t *pwallobjlist[MAXPWALLS];
+int pwallnum;
+
+byte areaconnect[NUMAREAS][NUMAREAS];
+
+boolean areabyplayer[NUMAREAS];
+
+
+// Local Variables
+
+static void (*touchactions[NUMTOUCHPLATEACTIONS])(long) =
+{ ActivatePushWall,
+ ActivateMoveWall,
+ LinkedOpenDoor,
+ LinkedCloseDoor,
+ EnableObject,
+ DisableObject,
+ ActivateLight,
+ DeactivateLight
+};
+
+#if ((DEVELOPMENT == 1))
+#if ((LOADSAVETEST == 1))
+static char*touchstrings[NUMTOUCHPLATEACTIONS] =
+{ "ActivatePushWall",
+ "ActivateMoveWall",
+ "LinkedOpenDoor",
+ "LinkedCloseDoor",
+ "EnableObject",
+ "DisableObject",
+ "ActivateLight",
+ "DeactivateLight"
+};
+#endif
+#endif
+#if ((DEVELOPMENT == 1))
+#if ((ELEVATORTEST == 1))
+
+static char*elevstring[NUMELEVATORACTIONS] =
+{ "ready at source",
+ "ready at destination",
+ "moving to source",
+ "moving to destination",
+ "doorclosing"
+};
+#endif
+#endif
+
+void UtilizeDoor (int door,void (*action)(int));
+void UseDoor (int door);
+void Teleport(elevator_t*eptr,int destination);
+void ConnectPushWall (int pwall);
+void SetupPushWall (int pwall);
+void WallMoving (int pwall);
+int SetNextAction(elevator_t*eptr,int action);
+
+/*
+===============
+=
+= MakeMaskedWallActive
+=
+===============
+*/
+
+void MakeMaskedWallActive(maskedwallobj_t* tmwall)
+{ if (!FIRSTMASKEDWALL)
+ FIRSTMASKEDWALL = tmwall;
+ else
+ { tmwall->prev = LASTMASKEDWALL;
+ LASTMASKEDWALL->next = tmwall;
+ }
+ LASTMASKEDWALL = tmwall;
+}
+
+/*
+===============
+=
+= MakeMaskedWallInactive
+=
+===============
+*/
+
+
+void MakeMaskedWallInactive(maskedwallobj_t* tmwall)
+{
+ if (tmwall == LASTMASKEDWALL)
+ LASTMASKEDWALL = tmwall->prev;
+ else
+ tmwall->next->prev = tmwall->prev;
+
+ if (tmwall == FIRSTMASKEDWALL)
+ FIRSTMASKEDWALL = tmwall->next;
+ else
+ tmwall->prev->next = tmwall->next;
+
+ tmwall->prev = NULL;
+ tmwall->next = NULL;
+
+}
+
+
+/*
+===============
+=
+= ActivateAnimMaskedWall
+=
+===============
+*/
+
+void ActivateAnimMaskedWall(animmaskedwallobj_t* amwall)
+{
+ if (!FIRSTANIMMASKEDWALL)
+ FIRSTANIMMASKEDWALL = amwall;
+ else
+ {
+ amwall->prev = LASTANIMMASKEDWALL;
+ LASTANIMMASKEDWALL->next = amwall;
+ }
+ LASTANIMMASKEDWALL = amwall;
+}
+
+/*
+===============
+=
+= DeactivateAnimMaskedWall
+=
+===============
+*/
+
+
+void DeactivateAnimMaskedWall(animmaskedwallobj_t* amwall)
+{
+ if (amwall == LASTANIMMASKEDWALL)
+ LASTANIMMASKEDWALL = amwall->prev;
+ else
+ amwall->next->prev = amwall->prev;
+
+ if (amwall == FIRSTANIMMASKEDWALL)
+ FIRSTANIMMASKEDWALL = amwall->next;
+ else
+ amwall->prev->next = amwall->next;
+
+ amwall->prev = NULL;
+ amwall->next = NULL;
+
+}
+
+
+int PlatformHeight(int tilex,int tiley)
+{
+ int platform;
+
+ if (!IsPlatform(tilex,tiley))
+ return nominalheight;
+
+ platform = MAPSPOT(tilex,tiley,2);
+
+ switch(platform)
+ {
+ case 1:
+ return -10;
+ case 4:
+ return nominalheight;
+ case 5:
+ case 6:
+ return nominalheight - 64;
+ case 7:
+ return nominalheight;
+ case 8:
+ case 9:
+ return -10;
+ }
+
+ return -1000;
+}
+
+void SpawnAnimatedMaskedWall ( int num )
+{
+ animmaskedwallobj_t * temp;
+
+ temp = (animmaskedwallobj_t *)Z_LevelMalloc(sizeof(animmaskedwallobj_t),PU_LEVELSTRUCT,NULL);
+ if (!temp)
+ Error("SpawnAnimatedMaskedWall: Failed on allocation of animated masked wall");
+ temp->num=num;
+ temp->count=AMW_NUMFRAMES;
+ temp->ticcount=AMW_TICCOUNT;
+ temp->next=NULL;
+ temp->prev=NULL;
+ ActivateAnimMaskedWall(temp);
+}
+
+void KillAnimatedMaskedWall ( animmaskedwallobj_t * temp )
+{
+ DeactivateAnimMaskedWall(temp);
+ Z_Free(temp);
+}
+
+
+void DoAnimatedMaskedWalls ( void )
+{
+ boolean done;
+ animmaskedwallobj_t * temp;
+
+ for(temp=FIRSTANIMMASKEDWALL; temp;)
+ {
+ done=false;
+ temp->ticcount-=tics;
+ while (temp->ticcount<0)
+ {
+ temp->ticcount+=AMW_TICCOUNT;
+ temp->count--;
+ maskobjlist[temp->num]->bottomtexture++;
+ if (temp->count==0)
+ {
+ done=true;
+ break;
+ }
+ }
+ if (done==true)
+ {
+ animmaskedwallobj_t * temp2;
+
+ temp2=temp->next;
+ KillAnimatedMaskedWall(temp);
+ temp=temp2;
+ }
+ else
+ temp=temp->next;
+ }
+}
+
+
+int GetIndexForAction(void (*action)(long))
+{ int i;
+
+ for(i=0; i<NUMTOUCHPLATEACTIONS; i++)
+ if (action == touchactions[i])
+ return i;
+
+ Error("Touchplate Action Not Matched");
+ return -1;
+}
+
+
+void SaveTouchPlates(byte ** buffer,int *size)
+{ int i,k;
+ byte * tptr;
+ touchplatetype *temp;
+ saved_touch_type dummy;
+
+ *size = sizeof(TRIGGER);
+ *size += sizeof(numactions);
+ *size += sizeof(saved_touch_type)*totalactions;
+
+ *buffer = (byte *)SafeMalloc(*size);
+ tptr = *buffer;
+ memcpy(tptr,&TRIGGER[0],sizeof(TRIGGER));
+ tptr+=sizeof(TRIGGER);
+
+ memcpy(tptr,&numactions[0],sizeof(numactions));
+ tptr+=sizeof(numactions);
+
+#if ((DEVELOPMENT == 1))
+#if (LOADSAVETEST == 1)
+ Debug("\n\nSAVE INFO\n");
+ Debug("---------");
+
+ Debug("\n\nTOUCHINDICES\n");
+ Debug("------------\n\n");
+ for(i=0; i<MAPSIZE; i++)
+ for(j=0; j< MAPSIZE; j++)
+ if (touchindices[i][j])
+ Debug("\ntouchindices[%3d][%3d]: %d",i,j,touchindices[i][j]);
+
+ Debug("\n\nTRIGGER: ");
+ for(i=0; i<(sizeof(TRIGGER)/sizeof(TRIGGER[0])); i++)
+ if (TRIGGER[i])
+ Debug("%1d",TRIGGER[i]);
+ Debug("\n\nNUMACTIONS PER TOUCHPLATE\n");
+ Debug("-------------------------\n\n");
+ for(i=0; i<(sizeof(numactions)/sizeof(numactions[0])); i++)
+ if (numactions[i])
+ Debug("\n %2d: %2d",i,numactions[i]);
+#endif
+#endif
+
+ for(i=0; i<lasttouch; i++)
+ {
+#if ((DEVELOPMENT == 1))
+#if (LOADSAVETEST == 1)
+ Debug("\n\nTOUCHPLATE[%2d]\n",i);
+ Debug("--------------\n\n");
+#endif
+#endif
+
+ for(k=0,temp=touchplate[i]; temp; k++,temp = temp->nextaction)
+ {
+ dummy.tictime = temp->tictime;
+ dummy.ticcount = temp->ticcount;
+ dummy.triggered = temp->triggered;
+ dummy.done = temp->done;
+ dummy.complete = temp->complete;
+
+ if (temp->action)
+ dummy.actionindex = GetIndexForAction(temp->action);
+ else
+ dummy.actionindex = -1;
+
+ if (temp->swapaction)
+ dummy.swapactionindex = GetIndexForAction(temp->swapaction);
+ else
+ dummy.swapactionindex = -1;
+ if ((dummy.actionindex > 5) || (dummy.swapactionindex > 5)) // means whichobj holds pointer to actor
+ {
+ statobj_t *tstat;
+
+ tstat = (statobj_t*)(temp->whichobj);
+ dummy.whichobj = (tstat->whichstat|FL_TSTAT);
+ }
+
+ else if ((dummy.actionindex > 3) || (dummy.swapactionindex > 3))
+
+ {
+ objtype *tactor;
+
+ tactor = (objtype*)(temp->whichobj);
+ dummy.whichobj = (tactor->whichactor|FL_TACT);
+ }
+
+ else
+ dummy.whichobj = temp->whichobj;
+
+#if ((DEVELOPMENT == 1))
+#if (LOADSAVETEST == 1)
+ Debug("action node %d: tictime: %d, ticcount: %d ",k,dummy.tictime,dummy.ticcount);
+ if (dummy.actionindex == -1)
+ Debug("action: -1,");
+ else
+ Debug("action: %13s,",touchstrings[dummy.actionindex]);
+
+ if (dummy.swapactionindex == -1)
+ Debug("swapaction: -1,");
+ else
+ Debug("swapaction: %13s,",touchstrings[dummy.swapactionindex]);
+
+ if (dummy.whichobj & FL_TACT)
+ Debug("whichobj (actor): %4x\n",(dummy.whichobj & ~FL_TACT));
+ else
+ Debug("whichobj (nonactor): %4x\n",dummy.whichobj);
+#endif
+#endif
+
+
+ memcpy(tptr,&dummy,sizeof(saved_touch_type));
+ tptr+=sizeof(saved_touch_type);
+ }
+ }
+}
+
+statobj_t* GetStatForIndex(int index)
+{ statobj_t *temp;
+
+ for(temp = FIRSTSTAT; temp; temp=temp->statnext)
+ if (temp->whichstat == index)
+ return temp;
+
+ SoftError("\nstat not found in GetStatForIndex");
+ return NULL;
+
+}
+
+
+void LoadTouchPlates(byte * buffer, int size)
+{ touchplatetype *temp;
+ int i,savedactions,loadedactions,index=0;
+ saved_touch_type dummy;
+
+ savedactions = (size-sizeof(TRIGGER)-sizeof(numactions))/sizeof(saved_touch_type);
+ memset(touchplate,0,sizeof(touchplate));
+ memset(lastaction,0,sizeof(lastaction));
+ memset(numactions,0,sizeof(numactions));
+ totalactions = 0;
+
+ memcpy(&TRIGGER[0],buffer,sizeof(TRIGGER));
+ buffer += sizeof(TRIGGER);
+
+ memcpy(&numactions[0],buffer,sizeof(numactions));
+ buffer += sizeof(numactions);
+
+ for(loadedactions=0,index=0,i=0; i<savedactions; i++)
+ { memcpy(&dummy,buffer,sizeof(saved_touch_type));
+ temp = (touchplatetype*)Z_LevelMalloc(sizeof(touchplatetype),PU_LEVELSTRUCT,NULL);
+ if (!temp)
+ Error("LoadTouchplates: Failed on allocation of touchplates %d of %d",i,savedactions);
+ memset(temp,0,sizeof(*temp));
+
+ temp->tictime = dummy.tictime;
+ temp->ticcount = dummy.ticcount;
+ temp->triggered = dummy.triggered;
+ temp->done = dummy.done;
+ temp->complete = dummy.complete;
+
+ if (dummy.whichobj & FL_TACT)
+ temp->whichobj = (long)(objlist[dummy.whichobj & ~FL_TACT]);
+
+ else if (dummy.whichobj & FL_TSTAT)
+ temp->whichobj = (long)(GetStatForIndex(dummy.whichobj & ~FL_TSTAT));
+ else
+ temp->whichobj = dummy.whichobj;
+ if (dummy.actionindex != -1)
+ temp->action = touchactions[dummy.actionindex];
+ else
+ temp->action = NULL;
+
+ if (dummy.swapactionindex != -1)
+ temp->swapaction = touchactions[dummy.swapactionindex];
+ else
+ temp->swapaction = NULL;
+
+ buffer+=sizeof(saved_touch_type);
+
+ while (!numactions[index])
+ index ++;
+
+ AddTouchplateAction(temp,index);
+
+ /*if (touchplate[index])
+ lastaction[index]->nextaction = temp;
+ else
+ touchplate[index] = temp;
+ lastaction[index] = temp;*/
+
+ totalactions ++;
+
+ loadedactions++;
+ if (loadedactions == numactions[index]) // found end of a touchplate's actions, goto next touch.
+ { loadedactions = 0;
+ index++;
+ }
+ }
+
+
+#if ((DEVELOPMENT == 1))
+#if (LOADSAVETEST == 1)
+ Debug("\n\nLOAD INFO\n");
+ Debug("---------");
+
+ Debug("\n\nTOUCHINDICES\n");
+ Debug("------------\n\n");
+ for(i=0; i<MAPSIZE; i++)
+ for(j=0; j< MAPSIZE; j++)
+ if (touchindices[i][j])
+ Debug("\ntouchindices[%3d][%3d]: %d",i,j,touchindices[i][j]);
+
+ Debug("\n\nTRIGGER: ");
+ for(i=0; i<(sizeof(TRIGGER)/sizeof(TRIGGER[0])); i++)
+ if (TRIGGER[i])
+ Debug("%1d",TRIGGER[i]);
+ Debug("\n\nNUMACTIONS PER TOUCHPLATE\n");
+ Debug("-------------------------\n\n");
+ for(i=0; i<(sizeof(numactions)/sizeof(numactions[0])); i++)
+ if (numactions[i])
+ Debug("\n %2d: %2d",i,numactions[i]);
+
+ for(i=0; i<lasttouch; i++)
+ {
+ Debug("\n\nTOUCHPLATE[%2d]\n",i);
+ Debug("--------------\n\n");
+
+ for(k=0,temp=touchplate[i]; temp; k++,temp = temp->nextaction)
+ {
+ Debug("action node %d: tictime: %d, ticcount: %d ",k,temp->tictime,temp->ticcount);
+ if (!temp->action)
+ Debug("action: NULL,");
+ else
+ Debug("action: %13s,",touchstrings[GetIndexForAction(temp->action)]);
+
+ if (!temp->swapaction)
+ Debug("swapaction: NULL,");
+ else
+ Debug("swapaction: %13s,",touchstrings[GetIndexForAction(temp->swapaction)]);
+
+ Debug("whichobj: %4x\n",(int)temp->whichobj);
+ }
+ }
+#endif
+#endif
+
+ SafeFree(objlist);
+
+}
+
+
+
+
+void AddTouchplateAction(touchplatetype *tplate,int index)
+{
+ if (touchplate[index])
+ { tplate->prevaction = lastaction[index];
+ lastaction[index]->nextaction = tplate;
+ }
+ else
+ touchplate[index] = tplate;
+ lastaction[index] = tplate;
+
+}
+
+
+
+
+void RemoveTouchplateAction(touchplatetype *tplate,int index)
+{
+ if (tplate == lastaction[index]) // remove from master list
+ lastaction[index] = tplate->prevaction;
+ else
+ tplate->nextaction->prevaction = tplate->prevaction;
+
+ if (tplate == touchplate[index])
+ touchplate[index] = tplate->nextaction;
+ else
+ tplate->prevaction->nextaction = tplate->nextaction;
+
+ Z_Free(tplate);
+ numactions[index]--;
+ totalactions--;
+
+}
+
+
+
+void Link_To_Touchplate(word touchlocx, word touchlocy, void (*maction)(long), void (*swapaction)(long), long wobj, int delaytime)
+{ touchplatetype *temp;
+ int index;
+
+ index = touchindices[touchlocx][touchlocy]-1;
+
+ temp = (touchplatetype*)Z_LevelMalloc(sizeof(touchplatetype),PU_LEVELSTRUCT,NULL);
+ if (!temp)
+ Error("Link_To_Touchplate: Failed on allocation of touchplate\n");
+ memset(temp,0,sizeof(*temp));
+ temp->action = maction;
+ temp->swapaction = swapaction;
+ temp->whichobj = wobj;
+ temp->tictime = temp->ticcount = delaytime;
+
+ AddTouchplateAction(temp,index);
+ /*if(touchplate[index])
+ lastaction[index]->nextaction=temp;
+ else
+ touchplate[index] = temp;
+ lastaction[index] = temp;*/
+ numactions[index]++;
+ totalactions++;
+}
+
+
+
+void ClockLink (void (*saction)(long), void (*eaction)(long), long wobj,int whichclock)
+{ touchplatetype*temp;
+
+
+// adding two actions per clock
+ temp = (touchplatetype*)Z_LevelMalloc(sizeof(touchplatetype),PU_LEVELSTRUCT,NULL);
+ if (!temp)
+ Error("ClockLink: Failed on allocation of clock");
+ memset(temp,0,sizeof(*temp));
+ temp->action = saction;
+ temp->swapaction = eaction;
+ temp->whichobj = wobj;
+ temp->clocktype = 1;
+
+ AddTouchplateAction(temp,whichclock);
+ /* if(touchplate[whichclock])
+ lastaction[whichclock]->nextaction = temp;
+ else
+ touchplate[whichclock] = temp;
+ lastaction[whichclock]=temp;*/
+
+ numactions[whichclock]++;
+ totalactions ++;
+}
+
+
+void DisplayMessageForAction(touchplatetype *temp, boolean *wallmessage,
+ boolean *doormessage, boolean*columnmessage)
+{
+
+ if ((temp->action == ActivatePushWall) ||
+ (temp->action == ActivateMoveWall)
+ )
+ {
+ if (*wallmessage == false)
+ {
+ if (temp->clocktype)
+ AddMessage("Time-delay wall moves.",MSG_GAME);
+ else
+ AddMessage("A wall moves.",MSG_GAME);
+ *wallmessage = true;
+ }
+ }
+
+ else if (temp->action == LinkedCloseDoor)
+ {
+ if (*doormessage == false)
+ {
+ if (temp->clocktype)
+ AddMessage("Time-delay door closes.",MSG_GAME);
+ else
+ AddMessage("A door closes.",MSG_GAME);
+ *doormessage = true;
+ }
+ }
+
+ else if (temp->action == LinkedOpenDoor)
+ {
+ if (*doormessage == false)
+ {
+ if (temp->clocktype)
+ AddMessage("Time-delay door opens.",MSG_GAME);
+ else
+ AddMessage("A door opens.",MSG_GAME);
+ *doormessage = true;
+ }
+ }
+
+ else if (temp->action == EnableObject)
+ {
+ objtype *tempactor = (objtype*)(temp->whichobj);
+
+ if (M_ISACTOR(tempactor) && (tempactor->obclass == pillarobj))
+ {
+ if (*columnmessage == false)
+ {
+ if (temp->clocktype)
+ AddMessage("Time-delay column moves.",MSG_GAME);
+ else
+ AddMessage("A column moves.",MSG_GAME);
+ *columnmessage = true;
+ }
+ }
+ }
+}
+
+void TriggerStuff(void)
+{
+ touchplatetype *temp;
+ int i,touchcomplete,j;
+ int playeron;
+ void (*tempact)(long);
+ boolean wallmessage,doormessage,columnmessage;
+
+ for(i=0; i<lasttouch; i++)
+ {
+ playeron = false;
+ for( j = 0; j < numplayers; j++ )
+ {
+ if ( i == touchindices[ PLAYER[ j ]->tilex ][ PLAYER[ j ]->tiley ] - 1 )
+ {
+ playeron = true;
+ break;
+ }
+ }
+#if (BNACRASHPREVENT == 1)
+ //SetTextMode ( ); qwert
+ // CRASH IN SHAREWARE 'ride em cowboy' BNA FIX
+ // DONT ALLOW BAD touchplate ( == 0 ) see rt_playr.c
+ if (touchplate[i] == 0) {
+ continue;
+ }
+#endif
+
+ if (!TRIGGER[i])
+ continue;
+
+ else if (touchplate[i]->complete)
+ {
+ if (!playeron)
+ TRIGGER[i] = 0;
+ continue;
+ }
+
+ if (touchplate[i]->done)
+ {
+ if (!playeron)
+ {
+ for(temp = touchplate[i]; temp; temp = temp->nextaction)
+ temp->triggered=false;
+ TRIGGER[i] = 0;
+ touchplate[i]->done = false;
+ }
+ }
+
+ else
+ {
+ wallmessage = false;
+ doormessage = false;
+ columnmessage = false;
+
+ for(temp = touchplate[i]; temp; temp = temp->nextaction)
+ {
+ if (temp->action && (!temp->triggered))
+ {
+ if (!temp->ticcount)
+ {
+ temp->action(temp->whichobj);
+ if (temp->action == ActivateMoveWall)
+ {
+ int tilex,tiley;
+
+ tilex = pwallobjlist[temp->whichobj]->tilex;
+ tiley = pwallobjlist[temp->whichobj]->tiley;
+ tilemap[tilex][tiley] = 0;
+
+ }
+ if (gamestate.difficulty == gd_baby)
+ {
+ DisplayMessageForAction(temp,&wallmessage,&doormessage,&columnmessage);
+ }
+
+ tempact = temp->action;
+ temp->action = temp->swapaction;
+ temp->swapaction = tempact;
+ temp->ticcount = temp->tictime;
+ temp->triggered = true;
+ }
+
+ else
+ temp->ticcount --;
+ }
+ }
+ //done:
+
+ // check to see if any actions will ever be triggered by this
+ // touchplate again; if not, null touchplate out; else,
+ // check status of other actions
+
+ touchcomplete = 1;
+ for(temp = touchplate[i]; temp; temp = temp->nextaction)
+ {
+ if (temp->action)
+ {
+ touchcomplete = 0;
+ break;
+ }
+ }
+
+ if (touchcomplete)
+ touchplate[i]->complete = 1; // this touchplate is out of commission
+ else
+ {
+ touchplate[i]->done = true;
+ for(temp = touchplate[i]; temp; temp = temp->nextaction)
+ {
+ if (temp->action && (!temp->triggered))
+ {
+ touchplate[i]->done = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+//==================== Tile stuff ====================================
+
+boolean CheckTile(int x, int y)
+{
+
+ if ((x < 2) || (x > (MAPSIZE-1)) || (y < 2) || (y > (MAPSIZE - 1)))
+ return false;
+
+ if (actorat[x][y])
+ { objtype *check = (objtype*)(actorat[x][y]);
+ if (insetupgame)
+ return false;
+ if (!(M_ISACTOR(check) && (check->obclass == playerobj)))
+ return false;
+ }
+ if (DiskAt(x,y))
+ return false;
+ if (sprites[x][y])
+ return false;
+ if ((tilemap[x][y]) && (IsPlatform(x,y)==false))
+ return false;
+ if ((AREANUMBER(x,y)<=0) || (AREANUMBER(x,y)>NUMAREAS))
+ return false;
+ if (IsWindow(x,y))
+ return false;
+ return true;
+}
+
+
+#define CountTile(x,y) \
+{ \
+ if (oldarea == AREANUMBER(x,y))\
+ {if (CheckTile(x,y)) \
+ numemptytiles ++; \
+ \
+ areanumbercount++; \
+ if (areanumbercount == numareatiles[oldarea])\
+ return numemptytiles; \
+ } \
+ \
+} \
+
+
+int Number_of_Empty_Tiles_In_Area_Around(int x, int y)
+{ int roverx,rovery,areanumbercount=0,
+ numemptytiles=0,oldarea,i,limit,j;
+
+ oldarea = AREANUMBER(x,y);
+
+ for (i=1;; i++)
+ { roverx = x-i;
+ rovery = y-i;
+
+ CountTile(roverx,rovery);
+ limit = i<<1;
+
+ for(j=0; j<limit; j++)
+ { roverx++;
+ CountTile(roverx,rovery);
+ }
+
+ for(j=0; j<limit; j++)
+ { rovery++;
+ CountTile(roverx,rovery);
+ }
+
+ for(j=0; j<limit; j++)
+ { roverx--;
+ CountTile(roverx,rovery);
+ }
+
+ for(j=0; j<limit-1; j++)
+ { rovery--;
+ CountTile(roverx,rovery);
+ }
+ }
+}
+
+
+
+#define CheckSet(x,y) \
+{if (CheckTile(x,y) && (oldarea == AREANUMBER(x,y))) \
+ {*stilex = x; \
+ *stiley = y; \
+ return; \
+ } \
+} \
+
+
+
+void FindEmptyTile(int *stilex, int *stiley)
+{
+ int i,j,x,y,oldarea,roverx,rovery,limit;
+
+ oldarea = AREANUMBER(*stilex,*stiley);
+
+ x = *stilex;
+ y = *stiley;
+
+ if (CheckTile(x,y) && (oldarea == AREANUMBER(x,y)))
+ return;
+
+ for (i=1;; i++)
+ { roverx = x-i;
+ rovery = y-i;
+
+ CheckSet(roverx,rovery);
+ limit = i<<1;
+
+ for(j=0; j<limit; j++)
+ { roverx++;
+ CheckSet(roverx,rovery);
+ }
+
+ for(j=0; j<limit; j++)
+ { rovery++;
+ CheckSet(roverx,rovery);
+ }
+
+ for(j=0; j<limit; j++)
+ { roverx--;
+ CheckSet(roverx,rovery);
+ }
+
+ for(j=0; j<limit-1; j++)
+ { rovery--;
+ CheckSet(roverx,rovery);
+ }
+ }
+}
+
+//================================================================
+
+
+
+
+void RecursiveConnect (int areanumber)
+{
+ int i;
+
+ for (i=0; i<NUMAREAS; i++)
+ {
+ if (areaconnect[areanumber][i] && !areabyplayer[i])
+ {
+ areabyplayer[i] = true;
+ RecursiveConnect (i);
+ }
+ }
+}
+
+
+/*
+==============
+=
+= ConnectAreas
+=
+= Scans outward from playerarea, marking all connected areas
+=
+==============
+*/
+
+void ConnectAreas (void)
+{ objtype*temp;
+ statobj_t*tstat;
+ int i;
+#define MASTER_DISK(ob) ((ob->obclass == diskobj) && (ob->flags & FL_MASTER))
+
+ memset (areabyplayer,0,sizeof(areabyplayer));
+ for (i=0; i<numplayers; i++)
+ {
+ areabyplayer[PLAYER[i]->areanumber] = true;
+ RecursiveConnect (PLAYER[i]->areanumber);
+ }
+ for(temp=FIRSTACTOR; temp; temp=temp->next)
+ {
+ if (MASTER_DISK(temp))
+ continue;
+ if (!areabyplayer[temp->areanumber])
+ continue;
+ if (!(temp->flags & FL_ABP))
+ { temp->flags |= FL_ABP;
+ MakeActive(temp);
+ }
+ }
+
+ for(tstat=FIRSTSTAT; tstat; tstat=tstat->statnext)
+ { if (areabyplayer[tstat->areanumber])
+ { if (!(tstat->flags & FL_ABP))
+ { tstat->flags |= FL_ABP;
+ MakeStatActive(tstat);
+ }
+ }
+ else if (tstat->flags & FL_ABP)
+ { MakeStatInactive(tstat);
+ tstat->flags &= ~FL_ABP;
+ }
+ }
+
+ for(i=0; i<maskednum; i++)
+ { if (areabyplayer[maskobjlist[i]->areanumber])
+ { if (!(maskobjlist[i]->flags & MW_ABP))
+ { maskobjlist[i]->flags |= MW_ABP;
+ MakeMaskedWallActive(maskobjlist[i]);
+ }
+ }
+ else if (maskobjlist[i]->flags & MW_ABP)
+ { MakeMaskedWallInactive(maskobjlist[i]);
+ maskobjlist[i]->flags &= ~MW_ABP;
+ }
+ }
+}
+
+
+void InitAreas (void)
+{
+ memset (areabyplayer,0,sizeof(areabyplayer));
+ memset (areaconnect,0,sizeof(areaconnect));
+}
+
+
+/*
+===============
+=
+= InitDoorList
+=
+===============
+*/
+
+void InitDoorList (void)
+{
+ doornum=0;
+ pwallnum=0;
+ maskednum=0;
+ lasttouch = 0;
+ numclocks=0;
+
+ memset(touchindices,0,sizeof(touchindices));
+ memset(touchplate,0,sizeof(touchplate));
+ memset(lastaction,0,sizeof(lastaction));
+ memset(numactions,0,sizeof(numactions));
+ totalactions = 0;
+ memset(TRIGGER,0,sizeof(TRIGGER));
+ memset(Clocks,0,sizeof(Clocks));
+ FIRSTMASKEDWALL=NULL;
+ LASTMASKEDWALL=NULL;
+ FIRSTANIMMASKEDWALL=NULL;
+ LASTANIMMASKEDWALL=NULL;
+}
+
+/*
+===============
+=
+= IsWall
+=
+===============
+*/
+
+int IsWall (int tilex, int tiley)
+{
+ int map;
+
+ map=MAPSPOT(tilex,tiley,0);
+
+ if ((map>=1) && (map<=89))
+ return 1;
+
+ else if ((map>=106) && (map<=107))
+ return 1;
+
+ else if ((map>=224) && (map<=233))
+ return 1;
+
+ else if ((map>=242) && (map<=244))
+ return 1;
+
+ return 0;
+}
+
+
+
+/*
+===============
+=
+= InitElevators
+=
+===============
+*/
+
+void InitElevators(void)
+{ _numelevators = 0;
+ memset(ELEVATOR,0,sizeof(ELEVATOR));
+
+}
+
+
+
+/*
+===============
+=
+= IsDoor
+=
+===============
+*/
+
+int IsDoor (int tilex, int tiley)
+{
+ int map;
+
+ map=MAPSPOT(tilex,tiley,0);
+
+ if ((map>=33) && (map<=35))
+ return 1;
+
+ if ((map>=90) && (map<=104))
+ return 1;
+
+ if ((map>=154) && (map<=156))
+ return 1;
+
+ if (M_ISDOOR(tilex,tiley))
+ return 1;
+
+ return 0;
+}
+
+
+/*
+===============
+=
+= SpawnDoor
+=
+===============
+*/
+
+void SpawnDoor (int tilex, int tiley, int lock, int texture)
+{
+ int i;
+ doorobj_t * lastdoorobj;
+ int up,dn,lt,rt;
+ int abovewallstart;
+ int swallstart;
+ int basetexture;
+
+ abovewallstart=W_GetNumForName("ABVWSTRT")+1;
+ swallstart=W_GetNumForName("SIDESTRT")+1;
+
+ doorobjlist[doornum]=(doorobj_t*)Z_LevelMalloc(sizeof(doorobj_t),PU_LEVELSTRUCT,NULL);
+ if (!doorobjlist[doornum])
+ Error("SpawnDoor: Failed on allocation of door %d ",doornum);
+ memset(doorobjlist[doornum],0,sizeof(doorobj_t));
+ lastdoorobj=doorobjlist[doornum];
+
+ if (
+ ( MAPSPOT(tilex,tiley,1) >= 29 ) &&
+ ( MAPSPOT(tilex,tiley,1) <= 32 )
+ )
+ {
+ lock = MAPSPOT(tilex,tiley,1) - 28;
+ }
+
+ lastdoorobj->position = 0;
+ lastdoorobj->tilex = tilex;
+ lastdoorobj->tiley = tiley;
+ lastdoorobj->lock = lock;
+ lastdoorobj->action = dr_closed;
+ lastdoorobj->which = DOOR;
+ lastdoorobj->flags = 0;
+ lastdoorobj->eindex = -1;
+
+ //
+ // make the door space solid
+ //
+
+ if (loadedgame==false)
+ actorat[tilex][tiley] = lastdoorobj;
+
+ if (IsDoor(tilex,tiley-1)) up=2;
+ else if (IsWall(tilex,tiley-1)) up=1;
+ else up=0;
+
+ if (IsDoor(tilex,tiley+1)) dn=2;
+ else if (IsWall(tilex,tiley+1)) dn=1;
+ else dn=0;
+
+ if (IsDoor(tilex-1,tiley)) lt=2;
+ else if (IsWall(tilex-1,tiley)) lt=1;
+ else lt=0;
+
+ if (IsDoor(tilex+1,tiley)) rt=2;
+ else if (IsWall(tilex+1,tiley)) rt=1;
+ else rt=0;
+
+ if ((up==1) && (dn==1))
+ lastdoorobj->vertical = true;
+ else if ((lt==1) && (rt==1))
+ lastdoorobj->vertical = false;
+ else if ((up>0) && (dn>0))
+ lastdoorobj->vertical = true;
+ else if ((lt>0) && (rt>0))
+ lastdoorobj->vertical = false;
+ else if (up>0)
+ lastdoorobj->vertical = true;
+ else if (dn>0)
+ lastdoorobj->vertical = true;
+ else if (lt>0)
+ lastdoorobj->vertical = false;
+ else if (rt>0)
+ lastdoorobj->vertical = false;
+
+ switch (texture)
+ {
+
+ case 0:
+ case 8:
+ basetexture = W_GetNumForName("RAMDOOR1\0");
+ break;
+
+ case 1:
+ case 9:
+ basetexture = W_GetNumForName("DOOR2\0");
+ break;
+
+
+ case 2:
+ case 3:
+ case 13:
+ basetexture = W_GetNumForName("TRIDOOR1\0");
+ break;
+
+ case 10:
+ case 11:
+ case 14:
+ basetexture = W_GetNumForName("SDOOR4\0");
+ break;
+
+
+
+ case 12:
+ basetexture = W_GetNumForName("EDOOR\0");
+ break;
+ case 15:
+ basetexture = W_GetNumForName("SNDOOR\0");
+ break;
+ case 16:
+ basetexture = W_GetNumForName("SNADOOR\0");
+ break;
+ case 17:
+ basetexture = W_GetNumForName("SNKDOOR\0");
+ break;
+
+ case 18:
+ basetexture = W_GetNumForName("TNDOOR\0");
+ break;
+ case 19:
+ basetexture = W_GetNumForName("TNADOOR\0");
+ break;
+ case 20:
+ basetexture = W_GetNumForName("TNKDOOR\0");
+ break;
+ default:
+ Error("Illegal door value encountered\n");
+ break;
+ }
+ lastdoorobj->basetexture = basetexture;
+ lastdoorobj->texture = lastdoorobj->basetexture;
+
+ SD_PreCacheSoundGroup(SD_OPENDOORSND,SD_CLOSEDOORSND);
+
+//
+// make the door tile a special tile, and mark the adjacent tiles
+// for door sides
+//
+ tilemap[tilex][tiley] = doornum | 0x8000;
+
+ switch (texture)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ lastdoorobj->sidepic = W_GetNumForName("SIDE8");
+ lastdoorobj->alttexture = W_GetNumForName("ABOVEW3");
+ break;
+
+ case 15:
+ case 16:
+ case 17:
+#if (SHAREWARE == 1)
+ lastdoorobj->sidepic = W_GetNumForName("SIDE8");
+
+#else
+ lastdoorobj->sidepic = W_GetNumForName("SIDE16");
+#endif
+
+ lastdoorobj->alttexture = W_GetNumForName("ABOVEW16");
+ break;
+
+ case 18:
+ case 19:
+ case 20:
+#if (SHAREWARE == 1)
+ lastdoorobj->sidepic = W_GetNumForName("SIDE8");
+ lastdoorobj->alttexture = W_GetNumForName("ABOVEW3");
+
+#else
+ lastdoorobj->sidepic = W_GetNumForName("SIDE17");
+ lastdoorobj->alttexture = W_GetNumForName("ABOVEW17");
+
+#endif
+
+ break;
+ default:
+ Error("Illegal door value encountered\n");
+ break;
+ }
+
+
+
+ if ((lock>0) && (lock<5))
+ lastdoorobj->sidepic = W_GetNumForName("lock1")+lock-1;
+
+ PreCacheLump(lastdoorobj->sidepic,PU_CACHEWALLS,cache_pic_t);
+ PreCacheLump(lastdoorobj->alttexture,PU_CACHEWALLS,cache_pic_t);
+
+ if (lastdoorobj->vertical==true)
+ {
+ if (up==1)
+ tilemap[tilex][tiley-1] |= 0x4000;
+ else if (up==2)
+ lastdoorobj->flags|=DF_MULTI;
+ if (dn==1)
+ tilemap[tilex][tiley+1] |= 0x4000;
+ else if (dn==2)
+ lastdoorobj->flags|=DF_MULTI;
+ }
+ else
+ {
+ if (lt==1)
+ tilemap[tilex-1][tiley] |= 0x4000;
+ else if (lt==2)
+ lastdoorobj->flags|=DF_MULTI;
+ if (rt==1)
+ tilemap[tilex+1][tiley] |= 0x4000;
+ else if (rt==2)
+ lastdoorobj->flags|=DF_MULTI;
+ }
+
+ PreCacheLump(lastdoorobj->texture,PU_CACHEWALLS,cache_pic_t);
+ for (i=1; i<9; i++) // only first texture is pic_t!
+ PreCacheLump(lastdoorobj->texture+i,PU_CACHEWALLS,cache_patch_t);
+ doornum++;
+ lastdoorobj++;
+ if (doornum==MAXDOORS)
+ Error ("Too many doors on level!");
+
+}
+
+/*
+===============
+=
+= MakeWideDoorVisible
+=
+===============
+*/
+void MakeWideDoorVisible ( int doornum )
+{
+ int dx,dy;
+ doorobj_t * dr2;
+ doorobj_t * dr;
+ int tx,ty;
+
+ dr=doorobjlist[doornum];
+
+ dx=0;
+ dy=0;
+ if (dr->vertical==true)
+ dy=1;
+ else
+ dx=1;
+ spotvis[dr->tilex][dr->tiley]=1;
+ tx=dr->tilex+dx;
+ ty=dr->tiley+dy;
+ while (M_ISDOOR(tx,ty))
+ {
+ int num;
+
+ num=tilemap[tx][ty]&0x3ff;
+ dr2=doorobjlist[num];
+ if (!(dr2->flags&DF_MULTI))
+ break;
+ spotvis[tx][ty]=1;
+
+ tx+=dx;
+ ty+=dy;
+ }
+ tx=dr->tilex-dx;
+ ty=dr->tiley-dy;
+ while (M_ISDOOR(tx,ty))
+ {
+ int num;
+
+ num=tilemap[tx][ty]&0x3ff;
+ dr2=doorobjlist[num];
+ if (!(dr2->flags&DF_MULTI))
+ break;
+ spotvis[tx][ty]=1;
+
+ tx-=dx;
+ ty-=dy;
+ }
+}
+
+/*
+=====================
+=
+= LockLinkedDoor
+=
+=====================
+*/
+
+void LockLinkedDoor (int door)
+{
+ doorobj_t*dptr;
+
+ dptr = doorobjlist[door];
+ if (!dptr->lock)
+ dptr->lock=5;
+}
+
+/*
+=====================
+=
+= IsDoorLinked
+=
+=====================
+*/
+
+boolean IsDoorLinked (int door)
+{
+ doorobj_t*dptr;
+
+ dptr = doorobjlist[door];
+ if (dptr->lock==5)
+ return true;
+ return false;
+}
+
+
+/*
+===============
+=
+= FixDoorAreaNumbers
+=
+===============
+*/
+void FixDoorAreaNumbers ( void )
+{
+ int i;
+ int up,dn,lt,rt;
+ int tilex,tiley;
+
+ for (i=0; i<doornum; i++)
+ {
+ tilex=doorobjlist[i]->tilex;
+ tiley=doorobjlist[i]->tiley;
+ up=MAPSPOT(tilex,tiley-1,0)-AREATILE;
+ dn=MAPSPOT(tilex,tiley+1,0)-AREATILE;
+ lt=MAPSPOT(tilex-1,tiley,0)-AREATILE;
+ rt=MAPSPOT(tilex+1,tiley,0)-AREATILE;
+
+ up = ((up>0) && (up<=NUMAREAS));
+ dn = ((dn>0) && (dn<=NUMAREAS));
+ lt = ((lt>0) && (lt<=NUMAREAS));
+ rt = ((rt>0) && (rt<=NUMAREAS));
+
+
+ if (doorobjlist[i]->vertical==true)
+ {
+ if (rt)
+ MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex+1,tiley,0);
+ else if (lt)
+ MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex-1,tiley,0);
+ else
+ Error("FixDoors: Couldn't fix up area at x=%d y=%d\n",tilex,tiley);
+ }
+ else
+ {
+ if (dn)
+ MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley+1,0);
+ else if (up)
+ MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley-1,0);
+ else
+ Error("FixDoors: Couldn't fix up area at x=%d y=%d\n",tilex,tiley);
+ }
+ if (IsDoorLinked(i))
+ UtilizeDoor(i,LockLinkedDoor);
+ }
+}
+
+
+//===========================================================================
+
+/*
+=====================
+=
+= OpenDoor
+=
+=====================
+*/
+
+void OpenDoor (int door)
+{
+ if (doorobjlist[door]->action == dr_open)
+ doorobjlist[door]->ticcount = 0; // reset open time
+ else
+ {
+ doorobjlist[door]->action = dr_opening; // start it opening
+ }
+}
+
+/*
+=====================
+=
+= DoorUnBlocked
+=
+=====================
+*/
+
+boolean DoorUnBlocked (int door)
+{
+ int tilex,tiley;
+ objtype *check;
+ doorobj_t*dptr;
+
+ dptr = doorobjlist[door];
+
+//
+// don't close on anything solid
+//
+
+ tilex = dptr->tilex;
+ tiley = dptr->tiley;
+ check = (objtype*)actorat[tilex][tiley];
+
+ if (check && (check->which == ACTOR))
+ return false;
+
+ if (dptr->vertical==true)
+ {
+ check = (objtype*)actorat[tilex-1][tiley];
+ if (check && (check->which==ACTOR) && ((check->x+MINDIST) >> TILESHIFT) == tilex )
+ return false;
+ check = (objtype*)actorat[tilex+1][tiley];
+ if (check && (check->which==ACTOR) && ((check->x-MINDIST) >> TILESHIFT) == tilex )
+ return false;
+ }
+ else if (dptr->vertical==false)
+ {
+ check = (objtype*)actorat[tilex][tiley-1];
+ if (check && (check->which==ACTOR) && ((check->y+MINDIST) >> TILESHIFT) == tiley )
+ return false;
+ check = (objtype*)actorat[tilex][tiley+1];
+ if (check && (check->which==ACTOR) && ((check->y-MINDIST) >> TILESHIFT) == tiley )
+ return false;
+ }
+ return true;
+}
+
+
+/*
+=====================
+=
+= DoorReadyToClose
+=
+= Alter the door's state
+=
+=====================
+*/
+
+boolean DoorReadyToClose(int door)
+{
+ doorobj_t*dptr;
+ int dx,dy;
+ doorobj_t * dr2;
+ int tx,ty;
+
+
+ dptr = doorobjlist[door];
+
+ if (dptr->action==dr_closed)
+ return true;
+
+ if (DoorUnBlocked(door)==false)
+ return false;
+
+ dx=0;
+ dy=0;
+ if (dptr->vertical==true)
+ dy=1;
+ else
+ dx=1;
+ tx=dptr->tilex+dx;
+ ty=dptr->tiley+dy;
+ while (M_ISDOOR(tx,ty))
+ {
+ int num;
+
+ num=tilemap[tx][ty]&0x3ff;
+ dr2=doorobjlist[num];
+ if (!(dr2->flags&DF_MULTI))
+ break;
+ if (DoorUnBlocked(num)==false)
+ return false;
+ tx+=dx;
+ ty+=dy;
+ }
+ tx=dptr->tilex-dx;
+ ty=dptr->tiley-dy;
+ while (M_ISDOOR(tx,ty))
+ {
+ int num;
+
+ num=tilemap[tx][ty]&0x3ff;
+ dr2=doorobjlist[num];
+ if (!(dr2->flags&DF_MULTI))
+ break;
+ if (DoorUnBlocked(num)==false)
+ return false;
+ tx-=dx;
+ ty-=dy;
+ }
+ return true;
+}
+
+
+/*
+=====================
+=
+= CloseDoor
+=
+=====================
+*/
+
+void CloseDoor (int door)
+{
+ int tilex,tiley,area;
+ doorobj_t*dptr;
+
+ dptr = doorobjlist[door];
+ if (dptr->action == dr_closed)
+ return;
+ tilex = dptr->tilex;
+ tiley = dptr->tiley;
+
+//
+// play door sound
+//
+ area = MAPSPOT(tilex,tiley,0)-AREATILE;
+ if (areabyplayer[area])
+ {
+ dptr->soundhandle=SD_PlaySoundRTP ( SD_CLOSEDOORSND, dptr->tilex<<16, dptr->tiley<<16 );
+ }
+
+ dptr->action = dr_closing;
+//
+// make the door space solid
+//
+ actorat[tilex][tiley] = dptr;
+}
+
+
+
+/*
+=====================
+=
+= OperateDoor
+=
+= The player wants to change the door's direction
+=
+=====================
+*/
+
+void OperateDoor (int keys, int door, boolean localplayer )
+{
+ int lock;
+ doorobj_t*dptr;
+
+ dptr = doorobjlist[door];
+ if ( ( dptr->flags & DF_ELEVLOCKED ) ||
+ ( MISCVARS->GASON && ( MAPSPOT( dptr->tilex,
+ dptr->tiley, 1 ) == GASVALUE ) ) )
+ {
+ if ( localplayer )
+ {
+ // locked
+ SD_Play ( SD_NOITEMSND );
+ }
+ return;
+ }
+
+ lock = dptr->lock;
+ if ( lock && !( keys & ( 1 << ( lock - 1 ) ) ) )
+ {
+ if ( localplayer )
+ {
+ // locked
+ switch (lock)
+ {
+ case 1:
+ AddMessage("You need the \\EGOLD key",MSG_DOOR);
+ break;
+
+ case 2:
+ AddMessage("You need the \\FSILVER key",MSG_DOOR);
+ break;
+
+ case 3:
+ AddMessage("You need the \\8IRON key",MSG_DOOR);
+ break;
+
+ case 4:
+ AddMessage("You need the \\AOSCURO key",MSG_DOOR);
+ break;
+
+ default:
+ AddMessage("This door appears to be locked",MSG_DOOR);
+ break;
+ }
+
+ SD_Play( SD_NOITEMSND );
+ }
+ return;
+ }
+ UseDoor(door);
+}
+
+/*
+=====================
+=
+= LinkedOpenDoor
+=
+=====================
+*/
+
+void LinkedOpenDoor (long door)
+{
+ UtilizeDoor(door,OpenDoor);
+}
+
+/*
+=====================
+=
+= LinkedCloseDoor
+=
+=====================
+*/
+
+void LinkedCloseDoor (long door)
+{
+ if (DoorReadyToClose(door)==true)
+ UtilizeDoor(door,CloseDoor);
+}
+
+/*
+=====================
+=
+= UtilizeDoor
+=
+= Alter the door's state
+=
+=====================
+*/
+
+void UtilizeDoor (int door,void (*action)(int))
+{
+ doorobj_t*dptr;
+ int dx,dy;
+ doorobj_t * dr2;
+ int tx,ty;
+
+ dptr = doorobjlist[door];
+
+ action(door);
+
+ dx=0;
+ dy=0;
+ if (dptr->vertical==true)
+ dy=1;
+ else
+ dx=1;
+ tx=dptr->tilex+dx;
+ ty=dptr->tiley+dy;
+ while (M_ISDOOR(tx,ty))
+ {
+ int num;
+
+ num=tilemap[tx][ty]&0x3ff;
+ dr2=doorobjlist[num];
+ if (!(dr2->flags&DF_MULTI))
+ break;
+ action(num);
+ tx+=dx;
+ ty+=dy;
+ }
+ tx=dptr->tilex-dx;
+ ty=dptr->tiley-dy;
+ while (M_ISDOOR(tx,ty))
+ {
+ int num;
+
+ num=tilemap[tx][ty]&0x3ff;
+ dr2=doorobjlist[num];
+ if (!(dr2->flags&DF_MULTI))
+ break;
+ action(num);
+ tx-=dx;
+ ty-=dy;
+ }
+}
+
+/*
+=====================
+=
+= UseDoor
+=
+= Alter the door's state
+=
+=====================
+*/
+
+void UseDoor (int door)
+{
+ switch (doorobjlist[door]->action)
+ {
+ case dr_closing:
+ SD_StopSound(doorobjlist[door]->soundhandle);
+ case dr_closed:
+ UtilizeDoor(door,OpenDoor);
+ break;
+ case dr_opening:
+ SD_StopSound(doorobjlist[door]->soundhandle);
+ case dr_open:
+ if (DoorReadyToClose(door)==true)
+ UtilizeDoor(door,CloseDoor);
+ break;
+ }
+}
+
+//===========================================================================
+
+/*
+===============
+=
+= DoorOpen
+=
+= Close the door after three seconds
+=
+===============
+*/
+
+void DoorOpen (int door)
+{ doorobj_t* dptr;
+
+ dptr = doorobjlist[door];
+ dptr->ticcount += 1;
+ if ((dptr->ticcount >= OPENTICS) &&
+ (!(dptr->flags & DF_TIMED)) &&
+ (DoorReadyToClose(door)==true))
+ UtilizeDoor(door,CloseDoor);
+}
+
+
+
+/*
+===============
+=
+= DoorOpening
+=
+===============
+*/
+
+void DoorOpening (int door)
+{
+ int area1,area2;
+ word *map;
+ long position;
+ int tilex,tiley;
+
+ position = doorobjlist[door]->position;
+ tilex = doorobjlist[door]->tilex;
+ tiley = doorobjlist[door]->tiley;
+ if (!position)
+ {
+ //
+ // door is just starting to open, so connect the areas
+ //
+ map = &MAPSPOT(tilex,tiley,0);
+
+ if (doorobjlist[door]->vertical==true)
+ {
+ area1 = *(map+1);
+ area2 = *(map-1);
+ }
+ else
+ {
+ area1 = *(map-mapwidth);
+ area2 = *(map+mapwidth);
+ }
+ area1 -= AREATILE;
+ area2 -= AREATILE;
+ areaconnect[area1][area2]++;
+ areaconnect[area2][area1]++;
+ if ((insetupgame==false) && (loadedgame==false))
+ ConnectAreas ();
+ if (areabyplayer[area1])
+ {
+ doorobjlist[door]->soundhandle=SD_PlaySoundRTP ( SD_OPENDOORSND, doorobjlist[door]->tilex<<16, doorobjlist[door]->tiley<<16 );
+ }
+ }
+
+//
+// slide the door by an adaptive amount
+//
+ position += 1<<12;
+ if (position >= 0xffff)
+ {
+ //
+ // door is all the way open
+ //
+ position = 0xffff;
+ doorobjlist[door]->ticcount = 0;
+ doorobjlist[door]->action = dr_open;
+ if (doorobjlist[door] == actorat[tilex][tiley])
+ actorat[tilex][tiley] = 0;
+ }
+
+ doorobjlist[door]->position = position;
+ doorobjlist[door]->texture=doorobjlist[door]->basetexture+((position+1)>>13);
+}
+
+
+/*
+===============
+=
+= DoorClosing
+=
+===============
+*/
+
+void DoorClosing (int door)
+{
+ int area1,area2;
+ word *map;
+ long position;
+ int tilex,tiley;
+ doorobj_t *dptr;
+
+ dptr = doorobjlist[door];
+
+ tilex = dptr->tilex;
+ tiley = dptr->tiley;
+
+ position = dptr->position;
+
+//
+// slide the door by an adaptive amount
+//
+ position -= 1<<12;
+ if (position < (0xffff >> 1))
+ ResolveDoorSpace(tilex,tiley);
+
+
+ if (position <= 0)
+ {
+ //
+ // door is closed all the way, so disconnect the areas
+ //
+ position = 0;
+
+ dptr->action = dr_closed;
+
+
+
+ map = &MAPSPOT(tilex,tiley,0);
+
+ if (areabyplayer[(*map-AREATILE)])
+ {
+ dptr->soundhandle=SD_PlaySoundRTP ( SD_DOORHITSND, dptr->tilex<<16, dptr->tiley<<16 );
+ }
+
+ if (dptr->vertical==true)
+ {
+ area1 = *(map+1);
+ area2 = *(map-1);
+ }
+ else
+ {
+ area1 = *(map-mapwidth);
+ area2 = *(map+mapwidth);
+ }
+ area1 -= AREATILE;
+ area2 -= AREATILE;
+ areaconnect[area1][area2]--;
+ areaconnect[area2][area1]--;
+
+ ConnectAreas ();
+ }
+
+ dptr->position = position;
+ dptr->texture=dptr->basetexture+((position+1)>>13);
+}
+
+/*
+===============
+=
+= IsMaskedWall
+=
+===============
+*/
+
+int IsMaskedWall (int tilex, int tiley)
+{
+ int map;
+
+ if (IsPlatform(tilex,tiley))
+ return 1;
+
+ map=MAPSPOT(tilex,tiley,0);
+
+ if ((map>=157) && (map<=160))
+ return 1;
+
+ if ((map>=162) && (map<=179))
+ return 1;
+
+ if (M_ISMWALL(tilex,tiley))
+ return 1;
+
+ return 0;
+}
+
+/*
+===============
+=
+= SpawnMaskedWall
+=
+===============
+*/
+
+
+void SpawnMaskedWall (int tilex, int tiley, int which, int flags)
+{ word *map;
+ int area1, area2;
+ int up,dn,lt,rt;
+ int himask;
+ boolean sidepic;
+ int side, middle, above, bottom;
+ maskedwallobj_t * lastmaskobj;
+ boolean metal;
+ int maskedstart;
+ int abovemaskedwallstart;
+ int swallstart;
+
+ himask=W_GetNumForName("HMSKSTRT")+1;
+ maskedstart=W_GetNumForName("MASKSTRT");
+ abovemaskedwallstart=W_GetNumForName("ABVMSTRT");
+ swallstart=W_GetNumForName("SIDESTRT");
+
+ maskobjlist[maskednum]=(maskedwallobj_t*)Z_LevelMalloc(sizeof(maskedwallobj_t),PU_LEVELSTRUCT,NULL);
+ memset(maskobjlist[maskednum],0,sizeof(maskedwallobj_t));
+ lastmaskobj=maskobjlist[maskednum];
+
+ sidepic=true;
+
+ lastmaskobj->tilex = tilex;
+ lastmaskobj->tiley = tiley;
+ lastmaskobj->which = MWALL;
+ up=MAPSPOT(tilex,tiley-1,0)-AREATILE;
+ dn=MAPSPOT(tilex,tiley+1,0)-AREATILE;
+ lt=MAPSPOT(tilex-1,tiley,0)-AREATILE;
+ rt=MAPSPOT(tilex+1,tiley,0)-AREATILE;
+
+ if (IsMaskedWall(tilex,tiley-1)) up=2;
+ else if (IsWall(tilex,tiley-1)) up=1;
+ else up=0;
+
+ if (IsMaskedWall(tilex,tiley+1)) dn=2;
+ else if (IsWall(tilex,tiley+1)) dn=1;
+ else dn=0;
+
+ if (IsMaskedWall(tilex-1,tiley)) lt=2;
+ else if (IsWall(tilex-1,tiley)) lt=1;
+ else lt=0;
+
+ if (IsMaskedWall(tilex+1,tiley)) rt=2;
+ else if (IsWall(tilex+1,tiley)) rt=1;
+ else rt=0;
+
+ if ((up==1) && (dn==1))
+ lastmaskobj->vertical = true;
+ else if ((lt==1) && (rt==1))
+ lastmaskobj->vertical = false;
+ else if ((up>0) && (dn>0))
+ lastmaskobj->vertical = true;
+ else if ((lt>0) && (rt>0))
+ lastmaskobj->vertical = false;
+ else if (up>0)
+ lastmaskobj->vertical = true;
+ else if (dn>0)
+ lastmaskobj->vertical = true;
+ else if (lt>0)
+ lastmaskobj->vertical = false;
+ else if (rt>0)
+ lastmaskobj->vertical = false;
+
+ tilemap[tilex][tiley] = maskednum | 0xc000;
+ map = &MAPSPOT(tilex,tiley,0);
+
+ if (lastmaskobj->vertical==true)
+ {
+ area1 = *(map+1);
+ area2 = *(map-1);
+ area1 -= AREATILE;
+ area2 -= AREATILE;
+ if (lt==0 && rt==0)
+ {
+ areaconnect[area1][area2]++;
+ areaconnect[area2][area1]++;
+ }
+ }
+ else
+ {
+ area1 = *(map-mapwidth);
+ area2 = *(map+mapwidth);
+ area1 -= AREATILE;
+ area2 -= AREATILE;
+ if (up==0 && dn==0)
+ {
+ areaconnect[area1][area2]++;
+ areaconnect[area2][area1]++;
+ }
+ }
+ lastmaskobj->flags=flags;
+
+ if (IsPlatform(tilex,tiley))
+ {
+ if (MAPSPOT(tilex,tiley,0)==21)
+ {
+ metal=true;
+ actorat[tilex][tiley]=0;
+ }
+ else
+ metal=false;
+ }
+
+
+
+ switch (which)
+ {
+ case mw_peephole:
+
+ //#if (SHAREWARE == 1)
+ side = W_GetNumForName("SIDE21");
+ middle = W_GetNumForName("ABOVEM4A") ;
+ above = W_GetNumForName("ABOVEM4") ;
+ /*
+ #else
+ side = W_GetNumForName("SIDE16");
+ middle = W_GetNumForName("ABOVEM3A") ;
+ above = W_GetNumForName("ABOVEM2A") ;
+
+ #endif
+ */
+ bottom = W_GetNumForName("PEEPMASK");
+ break;
+
+
+ case mw_dogwall:
+
+ side = W_GetNumForName("SIDE21");
+ above = W_GetNumForName("ABOVEM4") ;
+
+#if (SHAREWARE == 1)
+ middle = W_GetNumForName("ABOVEM4A") ;
+#else
+ middle = W_GetNumForName("ABOVEM9") ;
+
+#endif
+ bottom = W_GetNumForName("DOGMASK");
+ break;
+
+ case mw_multi1:
+
+ /*
+ #if (SHAREWARE == 1)
+ side = W_GetNumForName("SIDE21");
+ middle = W_GetNumForName("ABOVEM4A") ;
+ above = W_GetNumForName("ABOVEM4") ;
+
+ #else
+ */
+ //side = W_GetNumForName("SIDE23") ;
+ side = W_GetNumForName("SIDE21") ;
+ middle = W_GetNumForName("ABOVEM5A") ;
+ above = W_GetNumForName("ABOVEM5") ;
+
+ // #endif
+
+ bottom = W_GetNumForName("MULTI1");
+ break;
+
+ case mw_multi2:
+ /*
+ #if (SHAREWARE == 1)
+ side = W_GetNumForName("SIDE21");
+ middle = W_GetNumForName("ABOVEM4A");
+ above = W_GetNumForName("ABOVEM4") ;
+
+ #else
+ */
+ //side = W_GetNumForName("SIDE23") ;
+ side = W_GetNumForName("SIDE21") ;
+ middle = W_GetNumForName("ABOVEM5B");
+ above = W_GetNumForName("ABOVEM5") ;
+
+
+ //#endif
+
+ bottom = W_GetNumForName("MULTI2");
+ break;
+
+ case mw_multi3:
+
+ /*
+ #if (SHAREWARE == 1)
+ side = W_GetNumForName("SIDE21");
+ middle = W_GetNumForName("ABOVEM4A") ;
+ above = W_GetNumForName("ABOVEM4") ;
+
+ #else
+ */
+ //side = W_GetNumForName("SIDE23") ;
+ side = W_GetNumForName("SIDE21") ;
+ middle = W_GetNumForName("ABOVEM5C") ;
+ above = W_GetNumForName("ABOVEM5") ;
+
+
+ //#endif
+
+ bottom = W_GetNumForName("MULTI3");
+ break;
+
+ case mw_singlepane:
+
+ // #if (SHAREWARE == 1)
+ side = W_GetNumForName("SIDE21");
+
+ // #else
+ // side = W_GetNumForName("SIDE22") ;
+ // #endif
+
+ middle = W_GetNumForName("ABOVEM4A") ;
+ above = W_GetNumForName("ABOVEM4") ;
+ bottom = W_GetNumForName("MASKED4");
+ break;
+
+ case mw_normal1:
+ side = W_GetNumForName("SIDE21");
+
+
+ // #if (SHAREWARE == 1)
+ middle = W_GetNumForName("ABOVEM4A") ;
+ above = W_GetNumForName("ABOVEM4") ;
+
+ //#else
+ // middle = W_GetNumForName("ABOVEM1A") ;
+ // above = W_GetNumForName("ABOVEM1") ;
+
+
+ //#endif
+
+ bottom = W_GetNumForName("MASKED1");
+ break;
+
+ case mw_normal2:
+ side = W_GetNumForName("SIDE21");
+
+ //#if (SHAREWARE == 1)
+ middle = W_GetNumForName("ABOVEM4A") ;
+ above = W_GetNumForName("ABOVEM4") ;
+
+ //#else
+ // middle = W_GetNumForName("ABOVEM2A") ;
+ // above = W_GetNumForName("ABOVEM2") ;
+
+ //#endif
+
+ bottom = W_GetNumForName("MASKED2");
+ break;
+
+ case mw_normal3:
+ side = W_GetNumForName("SIDE21");
+
+ //#if (SHAREWARE == 1)
+ middle = W_GetNumForName("ABOVEM4A") ;
+ above = W_GetNumForName("ABOVEM4") ;
+
+ //#else
+ // middle = W_GetNumForName("ABOVEM3A") ;
+ // above = W_GetNumForName("ABOVEM3") ;
+
+ //#endif
+
+ bottom = W_GetNumForName("MASKED3");
+ break;
+
+ case mw_exitarch:
+
+ side = W_GetNumForName("SIDE21");
+
+ //#if (SHAREWARE == 1)
+ middle = W_GetNumForName("ABOVEM4A") ;
+ above = W_GetNumForName("ABOVEM4") ;
+
+ //#else
+ // middle = W_GetNumForName("ABOVEM6A") ;
+ // above = W_GetNumForName("ABOVEM6") ;
+
+ //#endif
+
+ bottom = W_GetNumForName("EXITARCH");
+ break;
+
+ case mw_secretexitarch:
+
+ side = W_GetNumForName("SIDE21");
+
+ //#if (SHAREWARE == 1)
+ middle = W_GetNumForName("ABOVEM4A") ;
+ above = W_GetNumForName("ABOVEM4") ;
+
+ //#else
+ // middle = W_GetNumForName("ABOVEM8A") ;
+ // above = W_GetNumForName("ABOVEM8") ;
+
+ //#endif
+
+ bottom = W_GetNumForName("EXITARCA");
+ break;
+
+ case mw_railing:
+ sidepic = false;
+ middle = -1;
+ above = -1;
+ bottom = W_GetNumForName("RAILING");
+ break;
+
+ case mw_hiswitchon:
+ sidepic = false;
+ middle = himask+1;
+ above = himask+3;
+ bottom = himask;
+ break;
+
+ case mw_hiswitchoff:
+ sidepic = false;
+ middle = himask+1;
+ above = himask+2;
+ bottom = himask;
+ break;
+
+ case mw_entrygate:
+ side = W_GetNumForName("SIDE21");
+
+ //#if (SHAREWARE == 1)
+ //side = W_GetNumForName("SIDE21");
+ middle = W_GetNumForName("ABOVEM4A") ;
+ above = W_GetNumForName("ABOVEM4") ;
+
+ //#else
+ //side = W_GetNumForName("SIDE20") ;
+ // middle = W_GetNumForName("ABOVEM7A") ;
+ // above = W_GetNumForName("ABOVEM7") ;
+
+
+ //#endif
+
+ bottom = W_GetNumForName("ENTRARCH");
+ break;
+
+ case mw_platform1:
+ sidepic = false;
+ bottom = -1;
+ middle = -1;
+ above = himask+10;
+ if (metal==true)
+ {
+ bottom = -1;
+ middle = -1;
+ above = himask+15;
+ }
+ break;
+ case mw_platform2:
+ sidepic = false;
+ bottom = himask+8;
+ middle = -1;
+ above = -1;
+ if (metal==true)
+ {
+ bottom = himask+14;
+ middle = -1;
+ above = -1;
+ }
+ else
+ lastmaskobj->flags|=MW_BOTTOMFLIPPING;
+ break;
+ case mw_platform3:
+ sidepic = false;
+ bottom = himask+8;
+ middle = -1;
+ above = himask+10;
+ if (metal==true)
+ {
+ bottom = himask+14;
+ middle = -1;
+ above = himask+15;
+ }
+ else
+ lastmaskobj->flags|=MW_BOTTOMFLIPPING;
+ break;
+ case mw_platform4:
+ sidepic = false;
+ bottom = himask+12;
+ middle = himask+7;
+ above = himask+7;
+ if (metal==true)
+ {
+ bottom = -1;
+ middle = himask+15;
+ above = himask+15;
+ }
+ break;
+ case mw_platform5:
+ sidepic = false;
+ bottom = himask+12;
+ middle = himask+7;
+ above = himask+5;
+ if (metal==true)
+ {
+ bottom = -1;
+ middle = himask+15;
+ above = -1;
+ }
+ else
+ lastmaskobj->flags|=MW_TOPFLIPPING;
+ break;
+ case mw_platform6:
+ sidepic = false;
+ bottom = himask+4;
+ middle = himask+7;
+ above = himask+5;
+ if (metal==true)
+ {
+ bottom = himask+14;
+ middle = himask+15;
+ above = -1;
+ }
+ else
+ lastmaskobj->flags|=MW_TOPFLIPPING;
+ break;
+ case mw_platform7:
+ sidepic = false;
+ bottom = himask+4;
+ middle = himask+7;
+ above = himask+5;
+ if ((up==1) || (dn==1))
+ lastmaskobj->vertical=true;
+ else if ((lt==1) || (rt==1))
+ lastmaskobj->vertical=false;
+ else
+ Error("Perpendicular platform used with no wall near it\n");
+ if (metal==true)
+ {
+ bottom = himask+14;
+ middle = himask+15;
+ above = -1;
+ }
+ else
+ lastmaskobj->flags|=MW_TOPFLIPPING;
+ break;
+ }
+
+ switch (which)
+ {
+ case mw_multi1:
+ case mw_multi2:
+ case mw_multi3:
+ case mw_singlepane:
+ case mw_normal1:
+ case mw_normal2:
+ case mw_normal3:
+ if (!(flags & MW_SHOOTABLE))
+ bottom+=9;
+ break;
+ }
+ lastmaskobj->midtexture=middle;
+ lastmaskobj->toptexture=above;
+ lastmaskobj->bottomtexture=bottom;
+
+ if (sidepic == true)
+ {
+ lastmaskobj->sidepic=side;
+ if (lastmaskobj->vertical==true)
+ {
+ if (up==1)
+ tilemap[tilex][tiley-1] |= 0x4000;
+ if (dn==1)
+ tilemap[tilex][tiley+1] |= 0x4000;
+ }
+ else
+ {
+ if (lt==1)
+ tilemap[tilex-1][tiley] |= 0x4000;
+ if (rt==1)
+ tilemap[tilex+1][tiley] |= 0x4000;
+ }
+ }
+
+ // Cache in the broken version
+
+ if (lastmaskobj->flags & MW_SHOOTABLE)
+ {
+ int i;
+
+ for (i=1; i<AMW_NUMFRAMES; i++)
+ {
+ PreCacheLump(lastmaskobj->bottomtexture+i,PU_CACHEWALLS,cache_transpatch_t);
+ }
+ SD_PreCacheSound(SD_GLASSBREAKSND);
+ }
+ if (sidepic==true)
+ {
+ PreCacheLump(lastmaskobj->sidepic,PU_CACHEWALLS,cache_pic_t);
+ }
+ if (lastmaskobj->bottomtexture>=0)
+ PreCacheLump(lastmaskobj->bottomtexture,PU_CACHEWALLS,cache_transpatch_t);
+ if (lastmaskobj->toptexture>=0)
+ PreCacheLump(lastmaskobj->toptexture,PU_CACHEWALLS,cache_patch_t);
+ if (lastmaskobj->midtexture>=0)
+ PreCacheLump(lastmaskobj->midtexture,PU_CACHEWALLS,cache_patch_t);
+ maskednum++;
+ lastmaskobj++;
+ if (maskednum==MAXMASKED)
+ Error ("Too many masked walls\n");
+}
+
+/*
+===============
+=
+= FixMaskedWallAreaNumbers
+=
+===============
+*/
+void FixMaskedWallAreaNumbers ( void )
+{
+ int i;
+ int up,dn,lt,rt;
+ int tilex,tiley;
+
+ for (i=0; i<maskednum; i++)
+ {
+ int tile;
+ tilex=maskobjlist[i]->tilex;
+ tiley=maskobjlist[i]->tiley;
+ tile=MAPSPOT(tilex,tiley,0)-AREATILE;
+ if ((tile<=NUMAREAS) && (tile>0))
+ {
+ maskobjlist[i]->areanumber = tile;
+ continue;
+ }
+ up=MAPSPOT(tilex,tiley-1,0)-AREATILE;
+ dn=MAPSPOT(tilex,tiley+1,0)-AREATILE;
+ lt=MAPSPOT(tilex-1,tiley,0)-AREATILE;
+ rt=MAPSPOT(tilex+1,tiley,0)-AREATILE;
+
+
+
+ up = ((up>0) && (up<=NUMAREAS));
+ dn = ((dn>0) && (dn<=NUMAREAS));
+ lt = ((lt>0) && (lt<=NUMAREAS));
+ rt = ((rt>0) && (rt<=NUMAREAS));
+
+ if (maskobjlist[i]->vertical==true)
+ {
+ if (rt)
+ MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex+1,tiley,0);
+ else if (lt)
+ MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex-1,tiley,0);
+ else if (up)
+ MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley-1,0);
+ else if (dn)
+ MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley+1,0);
+ else
+ Error("FixMaskedWalls: Couldn't fix up area at x=%d y=%d\n",tilex,tiley);
+ }
+ else
+ {
+ if (dn)
+ MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley+1,0);
+ else if (up)
+ MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex,tiley-1,0);
+ else if (rt)
+ MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex+1,tiley,0);
+ else if (lt)
+ MAPSPOT(tilex,tiley,0) = MAPSPOT(tilex-1,tiley,0);
+ else
+ Error("FixMaskedWalls: Couldn't fix up area at x=%d y=%d\n",tilex,tiley);
+ }
+ maskobjlist[i]->areanumber = MAPSPOT(tilex,tiley,0)-AREATILE;
+ if ((maskobjlist[i]->areanumber <0) || (maskobjlist[i]->areanumber > NUMAREAS))
+ Error("Bad masked wall areanumber of %d",maskobjlist[i]->areanumber);
+ }
+}
+
+
+/*
+===============
+=
+= CheckMaskedWall
+=
+===============
+*/
+
+int CheckMaskedWall( maskedwallobj_t * mw )
+{
+ int result;
+
+ result=0;
+ if (mw->flags & MW_SHOOTABLE)
+ {
+ if (mw->flags & MW_BLOCKINGCHANGES)
+ {
+ mw->flags&=~MW_BLOCKINGCHANGES;
+ mw->flags&=~MW_BLOCKING;
+ mw->flags|=MW_BOTTOMPASSABLE;
+ }
+ mw->flags&=~MW_SHOOTABLE;
+// mw->bottomtexture++;
+ result=1;
+ }
+ return result;
+}
+
+
+/*
+===============
+=
+= UpdateMaskedWall
+=
+===============
+*/
+
+int UpdateMaskedWall (int num)
+{
+ maskedwallobj_t * mw;
+ int result;
+
+
+ mw=maskobjlist[num];
+ result=CheckMaskedWall(mw);
+ if (result==1)
+ {
+ SpawnAnimatedMaskedWall(num);
+ if (loadedgame==false)
+ SD_PlaySoundRTP(SD_GLASSBREAKSND,mw->tilex<<16,mw->tiley<<16);
+ if (mw->flags&MW_MULTI)
+ {
+ int i;
+ int dx,dy;
+ int r;
+ maskedwallobj_t * mw2;
+
+ dx=0;
+ dy=0;
+ if (mw->vertical==true)
+ dy=1;
+ else
+ dx=1;
+ i=1;
+ while (M_ISMWALL(mw->tilex+(dx*i),mw->tiley+(dy*i)))
+ {
+ int num;
+
+ num=tilemap[mw->tilex+(dx*i)][mw->tiley+(dy*i)]&0x3ff;
+ mw2=maskobjlist[num];
+ if (!(mw2->flags&MW_MULTI))
+ break;
+ r=CheckMaskedWall(mw2);
+ if (r==1)
+ {
+ SpawnAnimatedMaskedWall(num);
+ if (loadedgame==false)
+ SD_PlaySoundRTP(SD_GLASSBREAKSND,mw2->tilex<<16,mw2->tiley<<16);
+ }
+ i++;
+ }
+ i=1;
+ while (M_ISMWALL(mw->tilex-(dx*i),mw->tiley-(dy*i)))
+ {
+ int num;
+
+ num=tilemap[mw->tilex-(dx*i)][mw->tiley-(dy*i)]&0x3ff;
+ mw2=maskobjlist[num];
+ if (!(mw2->flags&MW_MULTI))
+ break;
+ r=CheckMaskedWall(mw2);
+ if (r==1)
+ {
+ SpawnAnimatedMaskedWall(num);
+ if (loadedgame==false)
+ SD_PlaySoundRTP(SD_GLASSBREAKSND,mw2->tilex<<16,mw2->tiley<<16);
+ }
+ i++;
+ }
+ }
+ }
+ return result;
+}
+
+
+
+/*
+============================
+=
+= ExecuteElevatorStopActions
+=
+============================
+*/
+
+
+void ExecuteElevatorStopActions(elevator_t *eptr, int teleport_location,
+ int desttilex,int desttiley)
+{
+ eptr->state = ev_doorclosing;
+ eptr->doorclosing = eptr->doortoopen;
+ doorobjlist[eptr->doortoopen]->flags &= ~DF_ELEVLOCKED;
+ OpenDoor(eptr->doortoopen);
+ SD_PlaySoundRTP(SD_ELEVATORENDSND,desttilex,desttiley);
+ Teleport(eptr,teleport_location);
+ eptr->ticcount = OPENTICS;
+ eptr->doortoopen = -1;
+ if (MISCVARS->elevatormusicon == true)
+ {
+ MU_StartSong(song_level);
+ MU_RestoreSongPosition();
+ MISCVARS->elevatormusicon = false;
+
+ }
+}
+
+
+boolean PlayerInElevator(elevator_t *eptr)
+{
+ if (eptr->state == ev_mts)
+ {
+ if ((eptr->dx == player->tilex) && (eptr->dy == player->tiley))
+ return true;
+ }
+ else if (eptr->state == ev_mtd)
+ {
+ if ((eptr->sx == player->tilex) && (eptr->sy == player->tiley))
+ return true;
+ }
+
+ return false;
+
+}
+
+#define SHOULD_START_ELEVATOR_MUSIC(eptr) \
+ ((demoplayback == false) && (demorecord == false) && \
+ (MusicStarted() == true) && \
+ (!BATTLEMODE) && \
+ (!(player->flags & FL_GODMODE)) &&\
+ (GameRandomNumber("elevator music",0) < 25) && \
+ (PlayerInElevator(eptr)) \
+ ) \
+
+
+/*
+==========================
+=
+= SetElevatorOperationTime
+=
+==========================
+*/
+
+
+void SetElevatorOperationTime(elevator_t*eptr)
+{
+ if (SHOULD_START_ELEVATOR_MUSIC(eptr))
+ {
+ MU_StoreSongPosition();
+ MU_StartSong(song_elevator);
+ MISCVARS->elevatormusicon = true;
+ eptr->ticcount = ELEVATORMUSICTIME;
+ }
+
+ else if (AREANUMBER(eptr->sx,eptr->sy) == AREANUMBER(eptr->dx,eptr->dy))
+ eptr->ticcount = 70;
+ else
+ eptr->ticcount = 170;
+
+}
+
+
+/*
+=====================
+=
+= CheckElevatorStart
+=
+=====================
+*/
+
+void CheckElevatorStart (elevator_t*eptr)
+{
+ doorobj_t *dptr = doorobjlist[eptr->doorclosing];
+
+ if (dptr->action == dr_closed)
+ {
+
+ if (eptr->nextaction!=-1)
+ {
+ eptr->state = eptr->nextaction;
+ eptr->nextaction = -1;
+ switch (eptr->state)
+ {
+ case ev_mtd:
+ eptr->doortoopen = eptr->door2;
+ SD_PlaySoundRTP(SD_ELEVATORONSND,eptr->sx<<16,eptr->sy<<16);
+ //eptr->doorclosing = eptr->door1;
+
+ SetElevatorOperationTime(eptr);
+ break;
+
+ case ev_mts:
+ eptr->doortoopen = eptr->door1;
+
+ SD_PlaySoundRTP(SD_ELEVATORONSND,eptr->dx<<16,eptr->dy<<16);
+
+ SetElevatorOperationTime(eptr);
+ break;
+ }
+ }
+
+ else if (eptr->doorclosing == eptr->door1)
+ eptr->state = ev_ras;
+
+
+ else if (eptr->doorclosing == eptr->door2)
+ eptr->state = ev_rad;
+
+
+ eptr->doorclosing = -1;
+ }
+}
+
+
+/*
+=====================
+=
+= ProcessElevators
+=
+= Called from PlayLoop
+=
+=====================
+*/
+
+void ProcessElevators (void)
+{
+ int ectr;
+ elevator_t *eptr;
+
+ for (ectr = 0 ; ectr < _numelevators ; ectr++)
+ {
+ eptr = &ELEVATOR[ectr];
+ if (eptr->ticcount)
+ eptr->ticcount --;
+ else
+ {
+ switch (eptr->state)
+ {
+ /*
+ case ev_ras:
+ break;
+
+ case ev_rad:
+ break;
+ */
+ case ev_mts:
+ ExecuteElevatorStopActions(eptr,0,(eptr->sx << 16),(eptr->sy << 16));
+ break;
+
+ case ev_mtd:
+ ExecuteElevatorStopActions(eptr,1,(eptr->dx << 16),(eptr->dy << 16));
+ break;
+
+ case ev_doorclosing:
+ CheckElevatorStart(eptr);
+ break;
+ }
+ }
+ }
+}
+
+
+
+void Teleport(elevator_t*eptr,int destination)
+{ statobj_t*tstat;
+ objtype*temp;
+ int startx,starty,destx,desty;
+
+ if (destination) // move to dest
+ { startx = eptr->sx;
+ starty = eptr->sy;
+ destx = eptr->dx;
+ desty = eptr->dy;
+ tilemap[eptr->esx][eptr->esy] = (elevatorstart + 5) | 0x2000;
+
+ }
+ else
+ { startx = eptr->dx;
+ starty = eptr->dy;
+ destx = eptr->sx;
+ desty = eptr->sy;
+ tilemap[eptr->edx][eptr->edy] = (elevatorstart + 5) | 0x2000;
+ }
+
+ for(tstat=firstactivestat; tstat; tstat=tstat->nextactive)
+ { if ((tstat->tilex == startx) && (tstat->tiley == starty))
+ {
+ tstat->x += ((destx - tstat->tilex) << TILESHIFT);
+ tstat->y += ((desty - tstat->tiley) << TILESHIFT);
+ tstat->tilex = tstat->x >> TILESHIFT;
+ tstat->tiley = tstat->y >> TILESHIFT;
+ tstat->visspot = &spotvis[tstat->tilex][tstat->tiley];
+ if (sprites[startx][starty] == tstat)
+ { sprites[startx][starty] = NULL;
+ sprites[destx][desty] = tstat;
+
+ }
+
+ }
+ }
+
+ for(temp=firstactive; temp; temp=temp->nextactive)
+ { if ((temp->tilex == startx) && (temp->tiley == starty))
+ { temp->x += ((destx - temp->tilex) << TILESHIFT);
+ temp->y += ((desty - temp->tiley) << TILESHIFT);
+ temp->tilex = temp->x >> TILESHIFT;
+ temp->tiley = temp->y >> TILESHIFT;
+ if (temp->obclass!=inertobj)
+ {
+ RemoveFromArea (temp);
+ temp->areanumber = AREANUMBER(temp->tilex,temp->tiley);
+ MakeLastInArea (temp);
+ }
+ if (temp == player)
+ SHAKETICS = 10;
+ }
+ }
+
+
+
+}
+
+
+
+void OperateElevatorDoor(int dnum)
+{
+ elevator_t*eptr;
+ doorobj_t *dptr,*door1,*door2;
+
+ dptr = doorobjlist[dnum];
+ eptr = &ELEVATOR[dptr->eindex];
+ door1 = doorobjlist[eptr->door1];
+ door2 = doorobjlist[eptr->door2];
+
+ switch(eptr->state)
+ { /*
+ case ev_mtd: // if already on the way to request,
+ // ignore; else, put request in
+ if (dnum == eptr->door1)
+ {eptr->nextaction = ev_mts;
+ //eptr->doortoopen = eptr->door1;
+ #if (DEVELOPMENT == 1)
+ #if (ELEVATORTEST == 1)
+ Debug("\nplayer at source requesting elev %d mtd",dptr->eindex);
+ #endif
+ #endif
+ }
+ break;
+
+ case ev_mts:
+ if (dnum == eptr->door2)
+ {eptr->nextaction = ev_mtd;
+ //eptr->doortoopen = eptr->door2;
+ #if (DEVELOPMENT == 1)
+ #if (ELEVATORTEST == 1)
+ Debug("\nplayer at dest requesting elev %d mts",dptr->eindex);
+ #endif
+ #endif
+ }
+ break;
+ */
+ case ev_rad: // if ready at other place,
+ if ((dnum == eptr->door1) && (eptr->nextaction != ev_mts)) // process request, lock doors,
+
+ {
+#if (DEVELOPMENT == 1)
+#if (ELEVATORTEST == 1)
+ Debug("\nplayer at source requesting elev %d rad",dptr->eindex);
+#endif
+#endif
+ // start moving to current loc;
+ SetNextAction(eptr,0); // if already there, do nothing
+
+ }
+ break;
+
+ case ev_ras:
+ if ((dnum == eptr->door2) && (eptr->nextaction != ev_mtd))
+ {
+#if (DEVELOPMENT == 1)
+#if (ELEVATORTEST == 1)
+ Debug("\nplayer at dest requesting elev %d ras",dptr->eindex);
+#endif
+#endif
+ SetNextAction(eptr,1);
+
+ }
+ break;
+
+ case ev_doorclosing:
+ if (eptr->doorclosing == dnum) // if opening door at current loc,
+ // reset elev state to ready
+ { //if (eptr->door1 == dnum)
+ // eptr->nextaction = ev_ras;
+ //else
+ //eptr->nextaction = ev_rad;
+ }
+ else //else prepare for movement
+ { if ((eptr->door1 == dnum) && (eptr->nextaction != ev_mts))
+ {
+#if ((DEVELOPMENT == 1))
+#if ((ELEVATORTEST == 1))
+ Debug("\nplayer at source requesting elev %d dc",dptr->eindex);
+#endif
+#endif
+ SetNextAction(eptr,0);
+
+ }
+ else if ((eptr->door2 == dnum) && (eptr->nextaction != ev_mtd))
+ {
+#if ((DEVELOPMENT == 1))
+#if ((ELEVATORTEST == 1))
+ Debug("\nplayer at dest requesting elev %d dc",dptr->eindex);
+#endif
+#endif
+ SetNextAction(eptr,1);
+
+ }
+ }
+ break;
+
+
+ }
+
+}
+
+
+int SetNextAction(elevator_t*eptr,int action)
+{ int dn;
+
+ if (action)
+ { if (!DoorReadyToClose(eptr->door1))
+ return false;
+
+ eptr->nextaction = ev_mtd;
+ dn = eptr->door1;
+ }
+ else
+ { if (!DoorReadyToClose(eptr->door2))
+ return false;
+
+ eptr->nextaction = ev_mts;
+ dn = eptr->door2;
+ }
+ eptr->state = ev_doorclosing;
+
+ eptr->doorclosing = dn;
+#if (DEVELOPMENT == 1)
+#if (ELEVATORTEST == 1)
+ Debug("\nCloseDoor %d",dn);
+#endif
+#endif
+ if (doorobjlist[dn]->action != dr_closed)
+ CloseDoor(dn);
+ doorobjlist[dn]->flags |= DF_ELEVLOCKED;
+
+ return true;
+}
+
+
+void OperateElevatorSwitch(objtype*ob,int elevnum,int checkx,int checky)
+{ elevator_t*eptr;
+ doorobj_t *door1,*door2;
+
+ eptr = &ELEVATOR[elevnum];
+
+ if ((eptr->state == ev_mts) ||
+ (eptr->state == ev_mtd))
+ {
+#if (DEVELOPMENT == 1)
+#if (ELEVATORTEST == 1)
+ Debug("\nobj %d tried to use elevator %d switch while in use",ob->obclass,elevnum);
+#endif
+#endif
+ return;
+ }
+
+ door1 = doorobjlist[eptr->door1];
+ door2 = doorobjlist[eptr->door2];
+
+ if ((abs(ob->tilex-door1->tilex)<=1) && //switch at source
+ (abs(ob->tiley-door1->tiley)<=1))
+ { if (!SetNextAction(eptr,1)) // set next to dest
+ return;
+#if (DEVELOPMENT == 1)
+#if (ELEVATORTEST == 1)
+ Debug("\nswitch at src %d flipped",elevnum);
+#endif
+#endif
+ eptr->ticcount = 0;
+ }
+ else //switch at dest
+ { if (!SetNextAction(eptr,0)) // set next to src
+ return;
+#if (DEVELOPMENT == 1)
+#if (ELEVATORTEST == 1)
+ Debug("\nswitch at dest %d flipped",elevnum);
+#endif
+#endif
+ eptr->ticcount = 0;
+ }
+
+ tilemap[checkx][checky] = (elevatorstart + 6) | 0x2000;
+ SD_PlaySoundRTP(SD_TOUCHPLATESND,ob->x,ob->y);
+
+}
+
+
+
+
+/*
+=====================
+=
+= MoveDoors
+=
+= Called from PlayLoop
+=
+=====================
+*/
+
+void MoveDoors (void)
+{
+ int door;
+
+ for (door = 0 ; door < doornum ; door++)
+ switch (doorobjlist[door]->action)
+ {
+ case dr_open:
+ DoorOpen (door);
+ break;
+
+ case dr_opening:
+ DoorOpening(door);
+ SD_PanRTP ( doorobjlist[door]->soundhandle, doorobjlist[door]->tilex<<16, doorobjlist[door]->tiley<<16 );
+ break;
+
+ case dr_closing:
+ DoorClosing(door);
+ SD_PanRTP ( doorobjlist[door]->soundhandle, doorobjlist[door]->tilex<<16, doorobjlist[door]->tiley<<16 );
+ break;
+ default:
+ ;
+ }
+}
+
+
+//===========================================================
+//
+// PUSHWALLS
+//
+//===========================================================
+
+
+/*
+===============
+=
+= GetAreaNumber
+=
+===============
+*/
+int GetAreaNumber ( int tilex, int tiley, int dir )
+{
+ int up,dn,lt,rt;
+
+ up=MAPSPOT(tilex,tiley-1,0)-AREATILE;
+ dn=MAPSPOT(tilex,tiley+1,0)-AREATILE;
+ lt=MAPSPOT(tilex-1,tiley,0)-AREATILE;
+ rt=MAPSPOT(tilex+1,tiley,0)-AREATILE;
+ if ((up<=0) || (up>NUMAREAS)) up=0;
+ if ((dn<=0) || (dn>NUMAREAS)) dn=0;
+ if ((lt<=0) || (lt>NUMAREAS)) lt=0;
+ if ((rt<=0) || (rt>NUMAREAS)) rt=0;
+ switch (dir)
+ {
+ case north:
+ if (up)
+ return up;
+ else if (dn)
+ return dn;
+ break;
+ case south:
+ if (dn)
+ return dn;
+ else if (up)
+ return up;
+ break;
+ case east:
+ if (rt)
+ return rt;
+ else if (lt)
+ return lt;
+ break;
+ case west:
+ if (lt)
+ return lt;
+ else if (rt)
+ return rt;
+ break;
+ }
+ if (up)
+ return up;
+ else if (dn)
+ return dn;
+ else if (lt)
+ return lt;
+ else if (rt)
+ return rt;
+ else
+ Error("Cannot find an area number for tile at x=%d y=%d\n",tilex,tiley);
+ return -1;
+}
+
+/*
+===============
+=
+= SpawnPushWall
+=
+===============
+*/
+
+void SpawnPushWall (int tilex, int tiley, int lock, int texture, int dir, int type)
+{
+ pwallobj_t * lastpwallobj;
+
+ if (pwallnum==MAXPWALLS)
+ Error ("MAXPWALLS on level!");
+
+ pwallobjlist[pwallnum]=(pwallobj_t*)Z_LevelMalloc(sizeof(pwallobj_t),PU_LEVELSTRUCT,NULL);
+ memset(pwallobjlist[pwallnum],0,sizeof(pwallobj_t));
+ lastpwallobj=pwallobjlist[pwallnum];
+
+ lastpwallobj->x = (tilex<<16)+0x8000;
+ lastpwallobj->y = (tiley<<16)+0x8000;
+ lastpwallobj->momentumx=0;
+ lastpwallobj->momentumy=0;
+ lastpwallobj->tilex = tilex;
+ lastpwallobj->tiley = tiley;
+ lastpwallobj->lock = lock;
+ lastpwallobj->action = pw_npushed;
+ lastpwallobj->which = PWALL;
+ lastpwallobj->dir = dir;
+ lastpwallobj->num = pwallnum;
+ actorat[tilex][tiley] = (pwallobj_t*)(lastpwallobj); // consider it a solid wall
+
+ if ( (MAPSPOT(tilex,tiley,0)==44) ||
+ (MAPSPOT(tilex,tiley,0)==233)
+ )
+ lastpwallobj->flags=PW_DAMAGE;
+
+ lastpwallobj->texture = texture;
+ if (!texture&0x1000)
+ PreCacheLump(texture,PU_CACHEWALLS,cache_pic_t);
+ lastpwallobj->areanumber = GetAreaNumber(tilex,tiley,lastpwallobj->dir);
+
+ MAPSPOT (tilex, tiley, 0)=(word)(lastpwallobj->areanumber+AREATILE);
+
+ switch(type)
+ {
+ case 0:
+ case 1:
+ case 3:
+ lastpwallobj->speed = 2;
+ break;
+ case 2:
+ case 4:
+ lastpwallobj->speed = 4;
+ break;
+ default:
+ Error("Illegal PushWall type passed into SpawnPushWall\n");
+ break;
+ }
+ if (type>2)
+ {
+ tilemap[tilex][tiley] = 0;
+ ActivateMoveWall(pwallnum);
+ }
+ else
+ {
+ tilemap[tilex][tiley] = texture|0x800;
+ if ((loadedgame==false) && (type==0))
+ gamestate.secrettotal++;
+ }
+
+ pwallnum++;
+ lastpwallobj++;
+
+ SD_PreCacheSoundGroup(SD_PUSHWALLSND,SD_TURBOWALLSND);
+}
+
+
+
+/*
+=====================
+=
+= OperatePushWall
+=
+= The player wants to change the pushwall's direction
+=
+=====================
+*/
+void OperatePushWall (int pwall, int dir, boolean localplayer )
+{
+ pwallobj_t * pw;
+
+ pw=pwallobjlist[pwall];
+
+ if (pw->lock)
+ {
+ if ( localplayer )
+ {
+ // Can't push
+ AddMessage("This push wall appears to be locked...",MSG_DOOR);
+ PlayNoWaySound();
+ }
+ return;
+ }
+ switch (pw->action)
+ {
+ case pw_npushed:
+ if ((dir!=pw->dir) && (pw->dir!=nodir))
+ {
+ // Can't push
+ if ( localplayer )
+ {
+ PlayNoWaySound();
+ }
+ return;
+ }
+ else if (localplayer && (gamestate.difficulty == gd_baby))
+ AddMessage("Push Wall Activated.",MSG_GAME);
+
+ pw->action=pw_pushing;
+ pw->dir=dir;
+ SD_PlaySoundRTP ( SD_TOUCHPLATESND, pw->x, pw->y );
+ ConnectPushWall(pwall);
+ SetupPushWall(pwall);
+ gamestate.secretcount++;
+ break;
+ default:
+ // Can't push
+ if ( localplayer )
+ {
+ PlayNoWaySound();
+ }
+ break;
+ }
+}
+
+/*
+=====================
+=
+= ActivateAllPushWalls
+=
+= A Push wall has beeen activated by a touch plate
+=
+=====================
+*/
+
+void ActivateAllPushWalls(void)
+{
+ int i;
+
+ for(i=0; i<pwallnum; i++)
+ {
+ if (pwallobjlist[i]->dir != nodir)
+ {
+ ActivatePushWall(i);
+ }
+ }
+}
+
+/*
+=====================
+=
+= ActivatePushWall
+=
+= A Push wall has beeen activated by a touch plate
+=
+=====================
+*/
+
+void ActivatePushWall (long pwall)
+{
+ pwallobj_t * pw;
+
+ pw=pwallobjlist[pwall];
+
+ switch (pw->action)
+ {
+ case pw_npushed:
+ pw->action=pw_pushing;
+ ConnectPushWall(pwall);
+ SetupPushWall(pwall);
+ gamestate.secretcount++;
+ break;
+ default:
+ // Can't push
+ SD_Play( SD_BADTOUCHSND );
+ break;
+ }
+}
+
+/*
+=====================
+=
+= ActivateMoveWall
+=
+= A Push wall has beeen activated by a touch plate
+=
+=====================
+*/
+
+void ActivateMoveWall (long pwall)
+{
+ pwallobj_t * pw;
+
+ pw=pwallobjlist[pwall];
+
+ switch (pw->action)
+ {
+ case pw_npushed:
+ pw->action=pw_moving;
+ SetupPushWall(pwall);
+ break;
+ default:
+ SD_Play( SD_BADTOUCHSND );
+ break;
+ }
+}
+
+
+
+/*
+===============
+=
+= ConnectPushWall
+=
+===============
+*/
+
+void ConnectPushWall (int pwall)
+{
+ int checkx;
+ int checky;
+ int area1,area2;
+ int area3,area4;
+ word *map;
+ pwallobj_t * pw;
+
+ pw=pwallobjlist[pwall];
+
+ checkx=pw->tilex;
+ checky=pw->tiley;
+ tilemap[checkx][checky] = 0;
+ map = &MAPSPOT (checkx, checky, 0);
+
+ area1 = *(map-mapwidth);
+ area2 = *(map+mapwidth);
+ area3 = *(map+1);
+ area4 = *(map-1);
+
+ area1 -= AREATILE;
+ area2 -= AREATILE;
+ area3 -= AREATILE;
+ area4 -= AREATILE;
+ if (((area1>0) && (area1<NUMAREAS)) &&
+ ((area2>0) && (area2<NUMAREAS)))
+ {
+ areaconnect[area1][area2]++;
+ areaconnect[area2][area1]++;
+
+ if ((insetupgame==false) && (loadedgame==false))
+ ConnectAreas ();
+ }
+ if (((area3>0) && (area3<NUMAREAS)) &&
+ ((area4>0) && (area4<NUMAREAS)))
+ {
+ areaconnect[area3][area4]++;
+ areaconnect[area4][area3]++;
+
+ if ((insetupgame==false) && (loadedgame==false))
+ ConnectAreas ();
+ }
+}
+
+/*
+===============
+=
+= SetupPushWall
+=
+===============
+*/
+
+void SetupPushWall (int pwall)
+{
+ pwallobj_t * pw;
+ int speed;
+
+ pw=pwallobjlist[pwall];
+ speed=pw->speed<<PUSHWALLSPEED;
+ switch (pw->dir)
+ {
+ case north:
+ pw->momentumx=0;
+ pw->momentumy=-speed;
+ break;
+
+ case east:
+ pw->momentumx=speed;
+ pw->momentumy=0;
+ break;
+
+ case northeast:
+ pw->momentumx=speed;
+ pw->momentumy=-speed;
+ break;
+
+ case southeast:
+ pw->momentumx=speed;
+ pw->momentumy=speed;
+ break;
+
+ case south:
+ pw->momentumx=0;
+ pw->momentumy=speed;
+ break;
+
+ case west:
+ pw->momentumx=-speed;
+ pw->momentumy=0;
+ break;
+
+ case northwest:
+ pw->momentumx=-speed;
+ pw->momentumy=-speed;
+ break;
+
+ case southwest:
+ pw->momentumx=-speed;
+ pw->momentumy=speed;
+ break;
+ }
+ if (pw->action==pw_pushing)
+ {
+ if (loadedgame==false)
+ pw->soundhandle=SD_PlaySoundRTP ( SD_PUSHWALLSND, pw->x, pw->y );
+ pw->state=(0x20000L/speed);
+ }
+ if (pw->action==pw_moving)
+ pw->state=(0x10000L/speed);
+}
+
+
+/*
+=====================
+=
+= MovePWalls
+=
+= Called from PlayLoop
+=
+=====================
+*/
+
+void MovePWalls (void)
+{
+ int pwall;
+
+ for (pwall = 0 ; pwall < pwallnum ; pwall++)
+ {
+ if (pwallobjlist[pwall]->action==pw_pushing)
+ {
+ WallPushing (pwall);
+ SD_PanRTP (pwallobjlist[pwall]->soundhandle, pwallobjlist[pwall]->x, pwallobjlist[pwall]->y );
+ }
+ if (pwallobjlist[pwall]->action==pw_moving)
+ {
+ WallMoving (pwall);
+ SD_PanRTP (pwallobjlist[pwall]->soundhandle, pwallobjlist[pwall]->x, pwallobjlist[pwall]->y );
+ }
+ }
+}
+
+
+void ClearActorat(pwallobj_t*pw)
+{ int txhigh,txlow,tyhigh,tylow;
+ int tryx,tryy,x,y;
+ int pwrad = 0x6fff;
+
+
+ tryx = pw->x;
+ tryy = pw->y;
+ txlow = (tryx - pwrad) >> 16;
+ txhigh = (tryx + pwrad) >> 16;
+ tylow = (tryy - pwrad) >> 16;
+ tyhigh = (tryy + pwrad) >> 16;
+ for(y=tylow; y<=tyhigh; y++)
+ for(x=txlow; x<=txhigh; x++)
+ { if (actorat[x][y] == pw)
+ actorat[x][y] = NULL;
+ }
+}
+
+void SetActorat(pwallobj_t*pw)
+{ int txhigh,txlow,tyhigh,tylow;
+ int tryx,tryy,x,y;
+ int pwrad = 0x6fff;
+
+ tryx = pw->x;
+ tryy = pw->y;
+ txlow = (tryx - pwrad) >> 16;
+ txhigh = (tryx + pwrad) >> 16;
+ tylow = (tryy - pwrad) >> 16;
+ tyhigh = (tryy + pwrad) >> 16;
+
+ for(y=tylow; y<=tyhigh; y++)
+ for(x=txlow; x<=txhigh; x++)
+ actorat[x][y] = pw;
+}
+
+/*
+=================
+=
+= FinishPushWall
+=
+=================
+*/
+void FinishPushWall (pwallobj_t * pw)
+{
+ pw->action = pw_pushed;
+ actorat[pw->tilex][pw->tiley] = (wall_t*)&walls[GetWallIndex(pw->texture)];
+ tilemap[pw->tilex][pw->tiley] = pw->texture;
+}
+
+/*
+=================
+=
+= ResetPushWall
+=
+=================
+*/
+void ResetPushWall (pwallobj_t * pw)
+{
+ SetActorat(pw);
+ tilemap[pw->tilex][pw->tiley] = pw->texture|0x800;
+}
+
+/*
+=================
+=
+= WallPushing
+=
+=================
+*/
+void WallPushing (int pwall)
+{
+ int checkx,checky;
+ int spot;
+ pwallobj_t * pw;
+
+ pw=pwallobjlist[pwall];
+
+ ClearActorat(pw);
+
+ PushWallMove(pwall);
+ pw->x+=pw->momentumx;
+ pw->y+=pw->momentumy;
+
+ pw->state--;
+
+ checkx=pw->tilex;
+ checky=pw->tiley;
+
+ pw->tilex=pw->x>>16;
+ pw->tiley=pw->y>>16;
+
+ if ((pw->tilex!=checkx) || (pw->tiley!=checky))
+ {
+ int x,y;
+ int area = MAPSPOT(pw->tilex,pw->tiley,0)-AREATILE;
+
+ if ((area<=0) || (area>NUMAREAS))
+ {
+ area=pw->areanumber;
+ MAPSPOT (pw->tilex, pw->tiley, 0)=(word)(pw->areanumber+AREATILE);
+ }
+ // block crossed into a new block
+ //
+ // the tile can now be walked into
+ //
+ mapseen[checkx][checky] = 0;
+ pw->areanumber = area;
+ if (pw->momentumx>0)
+ x=1;
+ else if (pw->momentumx<0)
+ x=-1;
+ else
+ x=0;
+ if (pw->momentumy>0)
+ y=1;
+ else if (pw->momentumy<0)
+ y=-1;
+ else
+ y=0;
+ if (tilemap[pw->tilex+x][pw->tiley+y])
+ {
+ pw->state=(0x8000L/(pw->speed<<PUSHWALLSPEED));
+ }
+ if (actorat[pw->tilex+x][pw->tiley+y])
+ ResolveDoorSpace(pw->tilex+x,pw->tiley+y);
+ }
+
+
+ if (pw->state==0)
+ {
+ pw->x=(pw->tilex<<16)+0x8000;
+ pw->y=(pw->tiley<<16)+0x8000;
+ spot = MAPSPOT(pw->tilex,pw->tiley,1)-ICONARROWS;
+ if ((spot >= 0) && (spot <= 7))
+ {
+ pw->action = pw_npushed;
+ pw->dir = spot;
+ ResetPushWall (pw);
+ if (pw->lock)
+ {
+ pw->action=pw_pushing;
+ ConnectPushWall(pwall);
+ SetupPushWall(pwall);
+ }
+ else
+ {
+ gamestate.secrettotal++;
+ }
+ }
+ else
+ {
+ FinishPushWall (pw);
+ }
+ }
+ else
+ SetActorat(pw);
+}
+
+
+/*
+=================
+=
+= WallMoving
+=
+=================
+*/
+void WallMoving (int pwall)
+{
+ int checkx,checky;
+ int spot;
+ pwallobj_t * pw;
+
+ pw=pwallobjlist[pwall];
+
+ ClearActorat(pw);
+
+ PushWallMove(pwall);
+ pw->x+=pw->momentumx;
+ pw->y+=pw->momentumy;
+
+ pw->state--;
+
+ checkx=pw->tilex;
+ checky=pw->tiley;
+
+ pw->tilex=pw->x>>16;
+ pw->tiley=pw->y>>16;
+
+ if ((pw->tilex!=checkx) || (pw->tiley!=checky))
+ {
+ int area = MAPSPOT(pw->tilex,pw->tiley,0)-AREATILE;
+
+ if ((area<=0) || (area>NUMAREAS))
+ {
+ area=pw->areanumber;
+ MAPSPOT (pw->tilex, pw->tiley, 0)=(word)(pw->areanumber+AREATILE);
+ }
+ // block crossed into a new block
+ //
+ // the tile can now be walked into
+ //
+ if (areabyplayer[area])
+ {
+ if (pw->speed==2)
+ pw->soundhandle=SD_PlaySoundRTP ( SD_GOWALLSND, pw->x, pw->y );
+ else
+ pw->soundhandle=SD_PlaySoundRTP ( SD_TURBOWALLSND, pw->x, pw->y );
+ }
+
+ if (actorat[pw->tilex][pw->tilex])
+ ResolveDoorSpace(pw->tilex,pw->tiley);
+ mapseen[checkx][checky] = 0;
+ pw->areanumber = MAPSPOT (pw->tilex, pw->tiley, 0)-AREATILE;
+ //actorat[pw->tilex][pw->tiley]=pw;
+ if ( (pw->tilex==0) || (pw->tilex==127) ||
+ (pw->tiley==0) || (pw->tiley==127) )
+ {
+ if (W_CheckNumForName("imfree")>=0)
+ {
+ lbm_t *LBM;
+
+ LBM = (lbm_t *) W_CacheLumpNum (W_GetNumForName ("imfree"), PU_CACHE, Cvt_lbm_t, 1);
+ VL_DecompressLBM (LBM,true);
+ VW_UpdateScreen ();
+ I_Delay (2000);
+ }
+ Error ("PushWall Attempting to escape off the edge of the map\nIt is located at x=%d y=%d\nI'm Free!!!!\n",
+ pw->tilex, pw->tiley);
+ }
+ }
+ if (pw->state==0)
+ {
+ pw->x=(pw->tilex<<16)+0x8000;
+ pw->y=(pw->tiley<<16)+0x8000;
+ spot = MAPSPOT(pw->tilex,pw->tiley,1)-ICONARROWS;
+ if ((spot >= 0) && (spot <= 7))
+ {
+ int area = MAPSPOT(pw->tilex,pw->tiley,0)-AREATILE;
+
+ if ((area<=0) || (area>NUMAREAS))
+ {
+ area=pw->areanumber;
+ MAPSPOT (pw->tilex, pw->tiley, 0)=(word)(pw->areanumber+AREATILE);
+ }
+
+ if (areabyplayer[area] && (abs(spot-pw->dir)==4))
+ SD_PlaySoundRTP ( SD_PUSHWALLHITSND, pw->x, pw->y );
+ pw->dir = spot;
+ }
+ SetupPushWall(pwall);
+ }
+ else
+ SetActorat(pw);
+}
+
+
+
+/*
+=================
+=
+= SavePushWalls
+=
+=================
+*/
+void SavePushWalls(byte ** buf, int * sz)
+{
+ int unitsize;
+ pwallobj_t * pw;
+ byte * bufptr;
+ int i;
+ int size;
+
+ if (pwallnum==0)
+ {
+ *sz=0;
+ *buf=SafeMalloc(16);
+ return;
+ }
+ pw=pwallobjlist[0];
+ unitsize=0;
+ unitsize+=sizeof(pw->state);
+ unitsize+=sizeof(pw->x);
+ unitsize+=sizeof(pw->y);
+ unitsize+=sizeof(pw->dir);
+ unitsize+=sizeof(pw->speed);
+ unitsize+=sizeof(pw->action);
+
+ *sz=pwallnum*unitsize;
+
+ *buf=SafeMalloc(*sz);
+ bufptr=*buf;
+
+ for (i=0; i<pwallnum; i++)
+ {
+ pw=pwallobjlist[i];
+ size=sizeof(pw->state);
+ memcpy(bufptr,&(pw->state),size);
+ bufptr+=size;
+
+ size=sizeof(pw->x);
+ memcpy(bufptr,&(pw->x),size);
+ bufptr+=size;
+
+ size=sizeof(pw->y);
+ memcpy(bufptr,&(pw->y),size);
+ bufptr+=size;
+
+ size=sizeof(pw->dir);
+ memcpy(bufptr,&(pw->dir),size);
+ bufptr+=size;
+
+ size=sizeof(pw->speed);
+ memcpy(bufptr,&(pw->speed),size);
+ bufptr+=size;
+
+ size=sizeof(pw->action);
+ memcpy(bufptr,&(pw->action),size);
+ bufptr+=size;
+ }
+}
+
+/*
+=================
+=
+= LoadPushWalls
+=
+=================
+*/
+void LoadPushWalls(byte * bufptr, int sz)
+{
+ int unitsize;
+ pwallobj_t * pw;
+ pwallobj_t new;
+ int i;
+ int num;
+ int size;
+ int area;
+
+ if (sz==0)
+ return;
+ SetupPushWalls();
+ pw=pwallobjlist[0];
+ unitsize=0;
+ unitsize+=sizeof(pw->state);
+ unitsize+=sizeof(pw->x);
+ unitsize+=sizeof(pw->y);
+ unitsize+=sizeof(pw->dir);
+ unitsize+=sizeof(pw->speed);
+ unitsize+=sizeof(pw->action);
+
+ num=sz/unitsize;
+ if (pwallnum!=num)
+ Error("Different number of Push Walls when trying to load a game\npwallnum=%d num=%d",pwallnum,num);
+
+ for (i=0; i<pwallnum; i++)
+ {
+ pw=pwallobjlist[i];
+
+ size=sizeof(new.state);
+ memcpy(&(new.state),bufptr,size);
+ bufptr+=size;
+
+ size=sizeof(new.x);
+ memcpy(&(new.x),bufptr,size);
+ bufptr+=size;
+
+ size=sizeof(new.y);
+ memcpy(&(new.y),bufptr,size);
+ bufptr+=size;
+
+ size=sizeof(new.dir);
+ memcpy(&(new.dir),bufptr,size);
+ bufptr+=size;
+
+ size=sizeof(new.speed);
+ memcpy(&(new.speed),bufptr,size);
+ bufptr+=size;
+
+ size=sizeof(new.action);
+ memcpy(&(new.action),bufptr,size);
+ bufptr+=size;
+
+ actorat[pw->tilex][pw->tiley] = 0;
+ mapseen[pw->tilex][pw->tiley] = 0;
+
+ new.tilex=new.x>>16;
+ new.tiley=new.y>>16;
+
+ if ((new.tilex!=pw->tilex) || (new.tiley!=pw->tiley))
+ {
+ ClearActorat(pw);
+ tilemap[pw->tilex][pw->tiley] = 0;
+ if (pw->state!=pw_moving)
+ {
+#if 0
+ if (pw->dir==nodir)
+ {
+ if (tilemap[pw->tilex+1][pw->tiley]==0)
+ pw->dir=east;
+ else if (tilemap[pw->tilex-1][pw->tiley]==0)
+ pw->dir=west;
+ else if (tilemap[pw->tilex][pw->tiley+1]==0)
+ pw->dir=south;
+ else
+ pw->dir=north;
+ }
+#endif
+ ConnectPushWall(i);
+ }
+ }
+
+// fixup area if needed
+
+ area = MAPSPOT(new.tilex,new.tiley,0)-AREATILE;
+ if ((area<=0) || (area>NUMAREAS))
+ {
+ MAPSPOT (new.tilex, new.tiley, 0)=(word)(pw->areanumber+AREATILE);
+ }
+
+ pw->tilex=new.tilex;
+ pw->tiley=new.tiley;
+ pw->x=new.x;
+ pw->y=new.y;
+ pw->action=new.action;
+ pw->dir=new.dir;
+ pw->speed=new.speed;
+ SetupPushWall(i);
+ pw->state=new.state;
+
+ pw->areanumber = MAPSPOT (pw->tilex, pw->tiley, 0)-AREATILE;
+
+ if (pw->action==pw_pushed)
+ {
+ FinishPushWall (pw);
+ }
+ else if (pw->action==pw_npushed)
+ {
+ ResetPushWall (pw);
+ }
+ else
+ {
+ SetActorat(pw);
+ }
+ }
+}
+
+
+
+
+
+/*
+=================
+=
+= SaveMaskedWalls
+=
+=================
+*/
+void SaveMaskedWalls(byte ** buf, int * size)
+{
+ int unitsize;
+ maskedwallobj_t * mw;
+ byte * bufptr;
+ int i;
+ int sz;
+
+ if (maskednum==0)
+ {
+ *size=0;
+ *buf=SafeMalloc(16);
+ return;
+ }
+ mw=maskobjlist[0];
+ unitsize=0;
+ unitsize+=sizeof(mw->flags);
+
+ *size=maskednum*unitsize;
+
+ *buf=SafeMalloc(*size);
+ bufptr=*buf;
+
+ for (i=0; i<maskednum; i++)
+ {
+ mw=maskobjlist[i];
+ sz=sizeof(mw->flags);
+ memcpy(bufptr,&(mw->flags),sz);
+ bufptr+=sz;
+ }
+}
+
+/*
+=================
+=
+= LoadMaskedWalls
+=
+=================
+*/
+void LoadMaskedWalls(byte * bufptr, int sz)
+{
+ int unitsize;
+ maskedwallobj_t * mw;
+ int i;
+ int size;
+ int num;
+
+ if (sz==0)
+ return;
+
+ SetupMaskedWalls();
+ FixMaskedWallAreaNumbers();
+
+ mw=maskobjlist[0];
+ unitsize=0;
+ unitsize+=sizeof(mw->flags);
+
+ num=sz/unitsize;
+ if (maskednum!=num)
+ Error("Different number of Masked Walls when trying to load a game\nmaskednum=%d num=%d",maskednum,num);
+
+ for (i=0; i<maskednum; i++)
+ {
+ word flags; // Endianness fix thanks to DrLex - DDOI
+
+ mw=maskobjlist[i];
+ size=sizeof(mw->flags);
+ memcpy(&flags,bufptr,size);
+ bufptr+=size;
+ if ((flags&0xff)!=mw->flags) // Preserves original behavior
+ UpdateMaskedWall(i);
+ if (mw->flags&MW_SWITCHON)
+ mw->toptexture--;
+ }
+}
+
+
+/*
+=================
+=
+= SaveDoors
+=
+=================
+*/
+
+void SaveDoors (byte ** buf, int * size)
+{
+ int door;
+ int doorsave;
+ byte doorflag;
+ byte doorlocked;
+ signed char dooreindex;
+ short int doortime;
+ int unitsize;
+ byte *ptr;
+
+ if (doornum==0)
+ {
+ *size=0;
+ *buf=SafeMalloc(16);
+ return;
+ }
+
+ //
+ // Size = (int + byte + byte) * numdoors
+ //
+
+ unitsize=0;
+ unitsize+=sizeof(doorsave);
+ unitsize+=sizeof(doorflag);
+ unitsize+=sizeof(doorlocked);
+ unitsize+=sizeof(doortime);
+ unitsize+=sizeof(dooreindex);
+
+ *size = unitsize*doornum;
+ *buf = (byte *) SafeMalloc (*size);
+
+ ptr = *buf;
+
+ for (door = 0; door < doornum ; door++)
+ {
+ doorsave = doorobjlist[door]->position & ~3;
+ doorsave |= doorobjlist[door]->action;
+ doorflag = doorobjlist[door]->flags;
+ doorlocked = doorobjlist[door]->lock;
+ doortime = doorobjlist[door]->ticcount;
+ dooreindex = doorobjlist[door]->eindex;
+
+ memcpy (ptr, &doorsave, sizeof (doorsave));
+ ptr += sizeof (doorsave);
+ memcpy (ptr, &doorflag, sizeof (doorflag));
+ ptr += sizeof (doorflag);
+ memcpy (ptr, &doorlocked, sizeof (doorlocked));
+ ptr += sizeof (doorlocked);
+ memcpy (ptr, &doortime, sizeof (doortime));
+ ptr += sizeof (doortime);
+ memcpy (ptr, &dooreindex, sizeof (dooreindex));
+ ptr += sizeof (dooreindex);
+ }
+}
+
+
+/*
+=================
+=
+= LoadDoors
+=
+=================
+*/
+
+void LoadDoors (byte * buf, int size)
+{
+ int door;
+ int doorsave;
+ byte doorflag;
+ byte doorlocked;
+ signed char dooreindex;
+ short int doortime;
+ byte *ptr;
+ int unitsize;
+ int num;
+
+ SetupDoors ();
+ FixDoorAreaNumbers();
+ ptr = buf;
+
+ unitsize=0;
+ unitsize+=sizeof(doorsave);
+ unitsize+=sizeof(doorflag);
+ unitsize+=sizeof(doorlocked);
+ unitsize+=sizeof(doortime);
+ unitsize+=sizeof(dooreindex);
+
+ num=size/unitsize;
+ if (doornum!=num)
+ Error("Different number of Doors when trying to load a game\ndoornum=%d num=%d",doornum,num);
+
+ for (door = 0; door < doornum; door++)
+ {
+ memcpy (&doorsave, ptr, sizeof (doorsave));
+ ptr += sizeof (doorsave);
+ memcpy (&doorflag, ptr, sizeof (doorflag));
+ ptr += sizeof (doorflag);
+ memcpy (&doorlocked, ptr, sizeof (doorlocked));
+ ptr += sizeof (doorlocked);
+ memcpy (&doortime, ptr, sizeof (doortime));
+ ptr += sizeof (doortime);
+ memcpy (&dooreindex, ptr, sizeof (dooreindex));
+ ptr += sizeof (dooreindex);
+
+ doorobjlist[door]->action = doorsave & 3;
+
+ // Update Areas
+
+ if (doorobjlist[door]->action != dr_closed)
+ DoorOpening(door);
+
+ doorobjlist[door]->action = doorsave & 3;
+ doorobjlist[door]->position = doorsave;
+ doorobjlist[door]->flags = doorflag;
+ doorobjlist[door]->lock = doorlocked;
+ doorobjlist[door]->ticcount = doortime;
+ doorobjlist[door]->eindex = dooreindex;
+
+ if (doorobjlist[door]->action == dr_open)
+ doorobjlist[door]->position = 0xFFFF;
+
+ else if (doorobjlist[door]->action == dr_closed)
+ doorobjlist[door]->position = 0;
+
+ if (
+ (doorobjlist[door]->action == dr_closing) ||
+ (doorobjlist[door]->action == dr_closed)
+ )
+ {
+ actorat[doorobjlist[door]->tilex][doorobjlist[door]->tiley] = doorobjlist[door];
+ }
+ doorobjlist[door]->texture = doorobjlist[door]->basetexture +
+ ((doorobjlist[door]->position+1)>>13);
+ }
+}
+
+
+/*
+=====================
+=
+= SaveElevators
+=
+=
+=====================
+*/
+
+void SaveElevators(byte ** buffer,int *size)
+{ int i;
+ byte * tptr;
+
+ *size = _numelevators*sizeof(elevator_t);
+
+ *buffer = (byte *)SafeMalloc(*size);
+ tptr = *buffer;
+
+ for(i=0; i<_numelevators; i++)
+ { memcpy(tptr,&ELEVATOR[i],sizeof(elevator_t));
+ tptr += sizeof(elevator_t);
+ }
+}
+
+
+/*
+=====================
+=
+= LoadElevators
+=
+=
+=====================
+*/
+
+void LoadElevators(byte * buffer,int size)
+{ int i;
+
+ _numelevators = size/sizeof(elevator_t);
+
+
+ for(i=0; i<_numelevators; i++)
+ { memcpy(&ELEVATOR[i],buffer,sizeof(elevator_t));
+ buffer += sizeof(elevator_t);
+ }
+}
+
--- /dev/null
+++ b/rott/rt_door.h
@@ -1,0 +1,270 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_door_public
+#define _rt_door_public
+
+//***************************************************************************
+//
+// RT_DOOR.C - doors
+//
+//***************************************************************************
+
+#define MAXTOUCHPLATES 64
+#define MAXMASKED 300 // max masked walls
+#define MAXDOORS 150 // max number of sliding doors
+#define MAXPWALLS 150 // max number of pushwalls
+#define DF_TIMED 0x01
+#define DF_ELEVLOCKED 0x02
+#define DF_MULTI 0x04
+#define MAXELEVATORS 16
+
+#define PW_DAMAGE 0x01
+
+#define NUMELEVATORACTIONS 5
+
+typedef enum
+{ ev_ras, //ready at source
+ ev_rad, //ready at destination
+ ev_mts, //moving to source
+ ev_mtd, //moving to destination
+ //door at elevator location open
+ ev_doorclosing //door at elevator location closed
+} estate;
+
+typedef enum
+{
+ mw_peephole,
+ mw_dogwall,
+ mw_multi1,
+ mw_multi2,
+ mw_multi3,
+ mw_singlepane,
+ mw_normal1,
+ mw_normal2,
+ mw_normal3,
+ mw_exitarch,
+ mw_secretexitarch,
+ mw_railing,
+ mw_hiswitchon,
+ mw_hiswitchoff,
+ mw_platform1,
+ mw_platform2,
+ mw_platform3,
+ mw_platform4,
+ mw_platform5,
+ mw_platform6,
+ mw_platform7,
+ mw_entrygate
+} masked_walls;
+
+typedef struct elevator
+{ short sx,sy;
+ short dx,dy;
+ short esx,esy,edx,edy;
+ short door1,door2;
+ signed char state;
+ short doortoopen;
+ short doorclosing;
+ short ticcount;
+ short nextaction;
+} elevator_t;
+
+
+typedef struct doorstruct
+{
+ thingtype which;
+ byte tilex,tiley;
+ word texture;
+ word alttexture;
+ word sidepic;
+ word basetexture;
+ byte lock;
+ byte flags;
+ short int ticcount;
+ signed char eindex;
+ boolean vertical;
+ int soundhandle;
+ int position;
+ enum {dr_open,dr_closed,dr_opening,dr_closing} action;
+} doorobj_t;
+
+typedef struct pwallstruct
+{
+ thingtype which;
+ int x,y;
+ int momentumx,momentumy;
+ byte areanumber;
+ byte lock;
+ byte dir;
+ byte tilex,tiley;
+ byte num;
+ byte speed;
+ word texture;
+ int soundhandle;
+ enum {pw_npushed,pw_pushing,pw_pushed,pw_moving} action;
+ int state;
+ byte flags;
+} pwallobj_t;
+
+typedef struct tplate
+{ void (*action)(long);
+ void (*swapaction)(long);
+ struct tplate * nextaction;
+ struct tplate * prevaction;
+ long whichobj;
+ byte tictime;
+ byte ticcount;
+ byte triggered;
+ byte done;
+ byte complete;
+ byte clocktype;
+} touchplatetype;
+
+#define MW_SHOOTABLE 0x01
+#define MW_BLOCKING 0x02
+#define MW_MULTI 0x04
+#define MW_BLOCKINGCHANGES 0x08
+#define MW_ABOVEPASSABLE 0x10
+#define MW_NONDOGBLOCKING 0x20
+#define MW_WEAPONBLOCKING 0x40
+#define MW_BOTTOMPASSABLE 0x80
+#define MW_MIDDLEPASSABLE 0x100
+#define MW_ABP 0x200
+#define MW_SWITCHON 0x400
+#define MW_BOTTOMFLIPPING 0x800
+#define MW_TOPFLIPPING 0x1000
+#define M_ISDOOR(x,y) ((tilemap[x][y] & 0x8000) && (!(tilemap[x][y] & 0x4000)))
+#define M_ISMWALL(x,y) ((tilemap[x][y] & 0x8000) && (tilemap[x][y] & 0x4000))
+
+
+typedef struct mwall
+{
+ thingtype which;
+ byte tilex,tiley;
+ signed char areanumber;
+ signed short toptexture;
+ signed short midtexture;
+ signed short bottomtexture;
+ word flags;
+ boolean vertical;
+ int sidepic;
+
+ struct mwall *next;
+ struct mwall *prev;
+
+} maskedwallobj_t;
+
+typedef struct animmwall
+{
+ word num;
+ byte count;
+ signed char ticcount;
+ struct animmwall *next;
+ struct animmwall *prev;
+
+} animmaskedwallobj_t;
+
+extern elevator_t ELEVATOR[MAXELEVATORS];
+extern int _numelevators;
+extern animmaskedwallobj_t *FIRSTANIMMASKEDWALL,*LASTANIMMASKEDWALL;
+extern maskedwallobj_t *FIRSTMASKEDWALL,*LASTMASKEDWALL;
+extern byte touchindices[MAPSIZE][MAPSIZE],lasttouch;
+extern touchplatetype *touchplate[MAXTOUCHPLATES],*lastaction[MAXTOUCHPLATES];
+extern byte TRIGGER[MAXTOUCHPLATES];
+
+extern doorobj_t *doorobjlist[MAXDOORS];
+extern int doornum;
+extern maskedwallobj_t *maskobjlist[MAXMASKED];
+extern int maskednum;
+extern pwallobj_t *pwallobjlist[MAXPWALLS];
+extern int pwallnum;
+// 0xffff = fully open
+extern byte areaconnect[NUMAREAS][NUMAREAS];
+extern boolean areabyplayer[NUMAREAS];
+
+
+void ActivateAllPushWalls(void);
+boolean CheckTile(int,int);
+void FindEmptyTile(int*,int*);
+int Number_of_Empty_Tiles_In_Area_Around(int,int);
+void AddTouchplateAction(touchplatetype*,int);
+void RemoveTouchplateAction(touchplatetype*,int);
+
+void InitElevators(void);
+void ProcessElevators(void);
+void OperateElevatorDoor(int);
+
+
+int PlatformHeight(int,int);
+void Link_To_Touchplate(word, word, void (*)(long), void (*)(long), long, int);
+void TriggerStuff(void);
+void ClockLink(void (*)(long),void(*)(long),long,int);
+void RecursiveConnect(int);
+void ConnectAreas(void);
+void InitAreas(void);
+void InitDoorList(void);
+void SpawnDoor(int,int,int,int);
+void SpawnMaskedWall (int tilex, int tiley, int which, int flags);
+void OpenDoor(int);
+void CloseDoor(int);
+void OperateDoor (int keys, int door, boolean localplayer );
+void DoorOpen(int);
+void DoorOpening(int);
+void DoorClosing(int door);
+void MoveDoors(void);
+void SpawnPushWall (int tilex, int tiley, int lock, int texture, int dir, int type);
+void MovePWalls(void);
+void WallPushing (int pwall);
+void PushWall (int pwall, int dir);
+void OperatePushWall (int pwall, int dir, boolean localplayer );
+void ActivatePushWall (long pwall);
+void ActivateMoveWall (long pwall);
+int UpdateMaskedWall (int num);
+
+void FixDoorAreaNumbers ( void );
+void FixMaskedWallAreaNumbers ( void );
+void SaveMaskedWalls(byte ** buf, int * size);
+void LoadMaskedWalls(byte * buf, int size);
+void SaveDoors(byte ** buf, int * size);
+void SaveTouchPlates(byte ** buf, int * size);
+void LoadDoors(byte * buf, int size);
+void LoadTouchPlates(byte * buf, int size);
+void SavePushWalls(byte ** buf, int * sz);
+void LoadPushWalls(byte * bufptr, int sz);
+
+void DeactivateAnimMaskedWall(animmaskedwallobj_t* amwall);
+void ActivateAnimMaskedWall(animmaskedwallobj_t* amwall);
+
+void SpawnAnimatedMaskedWall ( int num );
+void KillAnimatedMaskedWall ( animmaskedwallobj_t * temp );
+
+void DoAnimatedMaskedWalls ( void );
+
+void SaveElevators(byte ** buffer,int *size);
+
+void LoadElevators(byte * buffer,int size);
+
+void MakeWideDoorVisible ( int doornum );
+void LinkedCloseDoor (long door);
+void LinkedOpenDoor (long door);
+int IsWall (int tilex, int tiley);
+int IsDoor (int tilex, int tiley);
+int IsMaskedWall (int tilex, int tiley);
+#endif
--- /dev/null
+++ b/rott/rt_dr_a.h
@@ -1,0 +1,45 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_dr_a_public
+#define _rt_dr_a_public
+
+//***************************************************************************
+//
+// RT_DR_A.ASM - Low level draw stuff, DrawPost
+//
+//***************************************************************************
+
+void SetMode240(void);
+void RefreshClear(void);
+void DrawPost (int height, char * column, char * buf);
+void DrawHeightPost (int height, byte * src, byte * buf); // IN rt_dr_a.asm
+void R_DrawWallColumn (byte * buf);
+void DrawMenuPost (int height, byte * src, byte * buf); // IN rt_dr_a.asm
+void DrawMapPost (int height, byte * src, byte * buf); // IN rt_dr_a.asm
+
+#if defined(__WATCOMC__)
+#pragma aux DrawPost parm [ECX] [ESI] [EDI] modify exact [eax ebx ecx edx esi edi]
+#pragma aux DrawHeightPost parm [ECX] [ESI] [EDI] modify exact [eax ebx ecx edx edi]
+#pragma aux R_DrawWallColumn parm [EDI] modify exact [eax ebx ecx edx esi edi]
+#pragma aux DrawMenuPost parm [ECX] [ESI] [EDI] modify exact [eax ebx ecx edx edi]
+#pragma aux DrawMapPost parm [ECX] [ESI] [EDI] modify exact [eax ebx ecx edx edi]
+#endif
+
+#endif
--- /dev/null
+++ b/rott/rt_draw.c
@@ -1,0 +1,6520 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// RT_DRAW.C
+
+#include "profile.h"
+#include "rt_def.h"
+#include <string.h>
+
+#ifdef DOS
+#include <dos.h>
+#include <conio.h>
+#endif
+
+#include "watcom.h"
+#include "sprites.h"
+#include "rt_actor.h"
+#include "rt_stat.h"
+#include "rt_draw.h"
+#include "_rt_draw.h"
+#include "rt_dr_a.h"
+#include "rt_fc_a.h"
+#include "rt_scale.h"
+#include "rt_floor.h"
+#include "rt_main.h"
+#include "rt_playr.h"
+#include "rt_door.h"
+#include "rt_ted.h"
+#include "isr.h"
+#include "rt_util.h"
+#include "engine.h"
+#include "z_zone.h"
+#include "w_wad.h"
+#include "lumpy.h"
+#include "rt_menu.h"
+#include "rt_game.h"
+#include "rt_vid.h"
+#include "rt_view.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "rt_cfg.h"
+#include "rt_str.h"
+#include "develop.h"
+#include "rt_sound.h"
+#include "rt_msg.h"
+#include "modexlib.h"
+#include "rt_rand.h"
+#include "rt_net.h"
+#include "rt_sc_a.h"
+//MED
+#include "memcheck.h"
+
+
+extern void VH_UpdateScreen (void);
+
+
+
+//int testval;
+/*
+=============================================================================
+
+Global Variables GLOBAL VARIABLES
+
+=============================================================================
+*/
+
+int iG_masked;
+
+int whereami=-1;
+
+byte * shadingtable;
+
+word tilemap[MAPSIZE][MAPSIZE]; // wall values only
+byte spotvis[MAPSIZE][MAPSIZE];
+byte mapseen[MAPSIZE][MAPSIZE];
+unsigned long * lights;
+
+int wstart;
+
+
+const int dirangle8[9] = {0,FINEANGLES/8,2*FINEANGLES/8,3*FINEANGLES/8,4*FINEANGLES/8,
+ 5*FINEANGLES/8,6*FINEANGLES/8,7*FINEANGLES/8,8*FINEANGLES/8
+ };
+
+const int dirangle16[16] = {0,FINEANGLES/16,2*FINEANGLES/16,3*FINEANGLES/16,
+ 4*FINEANGLES/16,5*FINEANGLES/16,6*FINEANGLES/16,
+ 7*FINEANGLES/16,8*FINEANGLES/16,9*FINEANGLES/16,
+ 10*FINEANGLES/16,11*FINEANGLES/16,12*FINEANGLES/16,
+ 13*FINEANGLES/16,14*FINEANGLES/16,15*FINEANGLES/16
+ };
+
+//
+// math tables
+//
+
+short tantable[FINEANGLES];
+int sintable[FINEANGLES+FINEANGLEQUAD+1],
+ *costable = sintable+(FINEANGLES/4);
+
+//
+// refresh variables
+//
+
+fixed viewx,viewy; // the focal point
+int viewangle;
+int c_startx, c_starty;
+fixed viewsin,viewcos;
+int tics;
+
+//
+// ray tracing variables
+//
+
+long xintercept,yintercept;
+
+int doublestep=0;
+int hp_startfrac;
+int hp_srcstep;
+
+int levelheight;
+
+int actortime=0;
+int drawtime=0;
+
+visobj_t vislist[MAXVISIBLE],*visptr,*visstep,*farthest;
+
+int firstcoloffset=0;
+
+/*
+==================
+=
+= Local Variables
+=
+==================
+*/
+static int nonbobpheight;
+
+static visobj_t * sortedvislist[MAXVISIBLE];
+
+static const fixed mindist = 0x1000;
+
+static int walltime=0;
+
+static int weaponbobx, weaponboby;
+
+static int pretics[3];
+static int preindex;
+static int netlump;
+static int gmasklump;
+
+int G_gmasklump;
+
+static const int weaponshape[NUMWEAPGRAPHICS] =
+{
+#if (SHAREWARE == 0)
+
+ W_KNIFE,
+#endif
+
+ W_MALEPISTOL1,
+ W_MRIGHTPISTOL1,
+ W_MP40,
+ W_BAZOOKA,
+ W_HEATSEEKER,
+ W_DRUNK,
+ W_FIREBOMB,
+ W_FIREWALL,
+ W_GODHAND,
+
+
+#if (SHAREWARE == 0)
+ W_SPLIT,
+ W_KES,
+ W_BAT,
+ W_DOG,
+ W_FEMALEPISTOL1,
+ W_BMALEPISTOL1
+#endif
+};
+
+void SetColorLightLevel (int x, int y, visobj_t * sprite, int dir, int color, int fullbright);
+void DrawRotatedScreen(int cx, int cy, byte *destscreen, int angle, int scale, int masked);
+void InterpolateMaskedWall (visobj_t * plane);
+void InterpolateDoor (visobj_t * plane);
+void InterpolateWall (visobj_t * plane);
+
+/*
+==================
+=
+= BuildTables
+=
+==================
+*/
+
+void BuildTables (void)
+{
+ byte * table;
+ byte * ptr;
+ int length;
+ int i;
+
+//
+// load in tables file
+//
+
+ table=W_CacheLumpName("tables",PU_STATIC, CvtNull, 1);
+ ptr=table;
+
+//
+// get size of first table
+//
+
+ memcpy(&length,ptr,sizeof(int));
+ SwapIntelLong(&length);
+
+//
+// skip first table
+//
+
+ ptr+=(length+1)*sizeof(int);
+
+//
+// get size of sin/cos table
+//
+
+ memcpy(&length,ptr,sizeof(int));
+ SwapIntelLong(&length);
+ ptr+=sizeof(int);
+
+//
+// get sin/cos table
+//
+ memcpy(&sintable[0],ptr,length*sizeof(int));
+ SwapIntelLongArray(&sintable[0], length);
+ ptr+=(length)*sizeof(int);
+
+//
+// get size of tangent table
+//
+
+ memcpy(&length,ptr,sizeof(int));
+ SwapIntelLong(&length);
+ ptr+=sizeof(int);
+
+//
+// get tangent table
+//
+ memcpy(tantable,ptr,length*sizeof(short));
+ SwapIntelShortArray(tantable, length);
+ ptr+=(length)*sizeof(short);
+
+//
+// get size of gamma table
+//
+
+ memcpy(&length,ptr,sizeof(int));
+ SwapIntelLong(&length);
+ ptr+=sizeof(int);
+
+//
+// get gamma table
+//
+ memcpy(&gammatable[0],ptr,length*sizeof(byte));
+ table=W_CacheLumpName("tables",PU_CACHE, CvtNull, 1);
+
+ costable = (fixed *)&(sintable[FINEANGLES/4]);
+
+ wstart=W_GetNumForName("WALLSTRT");
+#if (SHAREWARE==0)
+ netlump=W_GetNumForName("net1");
+#endif
+ gmasklump=W_GetNumForName("p_gmask");
+ G_gmasklump = gmasklump;
+
+ preindex=0;
+ pretics[0]=0x10000;
+ pretics[2]=0x10000;
+ pretics[1]=0x10000;
+
+ for(i=0; i<ANGLES; i++)
+ { angletodir[i] = (i + (ANGLES/16))/(ANGLES/8);
+ if (angletodir[i] == 8)
+ angletodir[i] = 0;
+ }
+
+ // Check out VENDOR.DOC file
+ CheckVendor();
+
+ if (!quiet)
+ printf("RT_DRAW: Tables Initialized\n");
+}
+
+
+/*
+========================
+=
+= TransformObject
+=
+========================
+*/
+
+boolean TransformObject (int x, int y, int *dispx, int *dispheight)
+{
+
+ fixed gx,gy,gxt,gyt,nx,ny;
+
+
+//
+// translate point to view centered coordinates
+//
+ gx = x-viewx;
+ gy = y-viewy;
+
+//
+// calculate newx
+//
+ gxt = FixedMul(gx,viewcos);
+ gyt = FixedMul(gy,viewsin);
+ nx = gxt-gyt;
+
+ if (nx<MINZ)
+ return false;
+
+ // the midpoint could put parts of the shape
+ // into an adjacent wall
+ //
+ // calculate newy
+ //
+ gxt = FixedMul(gx,viewsin);
+ gyt = FixedMul(gy,viewcos);
+ ny = gyt+gxt;
+
+
+//
+// calculate perspective ratio
+//
+
+ *dispx = centerx + ny*scale/nx; // DEBUG: use assembly divide
+
+ *dispheight = heightnumerator/nx;
+
+ return true;
+}
+
+
+/*
+========================
+=
+= TransformPoint
+=
+========================
+*/
+
+void TransformPoint (int x, int y, int * screenx, int * height, int * texture, int vertical)
+{
+
+ fixed gxt,gyt,nx,ny;
+ fixed gxtt,gytt;
+ int gx,gy;
+ int vx,vy;
+ int svs,svc;
+
+
+//
+// translate point to view centered coordinates
+//
+ gx = x-viewx;
+ gy = y-viewy;
+
+//
+// calculate newx
+//
+ gxt = FixedMul(gx,viewcos);
+ gyt = FixedMul(gy,viewsin);
+ nx =gxt-gyt;
+
+ if (nx<10)
+ nx=10;
+
+
+//
+// calculate newy
+//
+ gxtt = FixedMul(gx,viewsin);
+ gytt = FixedMul(gy,viewcos);
+ ny = gytt+gxtt;
+
+// too close, don't overflow the divid'
+
+
+ *screenx = centerx + ((ny*scale)/nx); // DEBUG: use assembly divide
+
+ *height = heightnumerator/nx;
+
+
+ if (*screenx<0)
+ {
+ svc=(-centerx)*viewcos;
+ svs=(-centerx)*viewsin;
+ vx=(scale*viewcos)+svs;
+ vy=(-scale*viewsin)+svc;
+ if (vertical)
+ {
+ if ((viewcos-viewsin)==0)
+ {
+ *height=20000<<HEIGHTFRACTION;
+ return;
+ }
+ gy=FixedScale(gx,vy,vx);
+ y=gy+viewy;
+ gyt = FixedMul(gy,viewsin);
+ nx =gxt-gyt;
+ if (nx<10)
+ nx=10;
+ *screenx = 0;
+ *height = heightnumerator/nx;
+ }
+ else
+ {
+ if ((-viewsin-viewcos)==0)
+ {
+ *height=20000<<HEIGHTFRACTION;
+ return;
+ }
+ gx=FixedScale(gy,vx,vy);
+ x=gx+viewx;
+ gxt = FixedMul(gx,viewcos);
+ nx =gxt-gyt;
+ if (nx<10)
+ nx=10;
+ *screenx = 0;
+ *height = heightnumerator/nx;
+ }
+ }
+ else if (*screenx>=viewwidth)
+ {
+ svc=(centerx)*viewcos;
+ svs=(centerx)*viewsin;
+ vx=(scale*viewcos)+svs;
+ vy=(-scale*viewsin)+svc;
+ if (vertical)
+ {
+ if ((viewcos+viewsin)==0)
+ {
+ *height=20000<<HEIGHTFRACTION;
+ return;
+ }
+ gy=FixedScale(gx,vy,vx);
+ y=gy+viewy;
+ gyt = FixedMul(gy,viewsin);
+ nx =gxt-gyt;
+ if (nx<10)
+ nx=10;
+ *screenx = viewwidth-1;
+ *height = heightnumerator/nx;
+ }
+ else
+ {
+ if ((-viewsin+viewcos)==0)
+ {
+ *height=20000<<HEIGHTFRACTION;
+ return;
+ }
+ gx=FixedScale(gy,vx,vy);
+ x=gx+viewx;
+ gxt = FixedMul(gx,viewcos);
+ nx =gxt-gyt;
+ if (nx<10)
+ nx=10;
+ *screenx = viewwidth-1;
+ *height = heightnumerator/nx;
+ }
+ }
+ if (vertical)
+ *texture=(y-*texture)&0xffff;
+ else
+ *texture=(x-*texture)&0xffff;
+}
+
+/*
+========================
+=
+= TransformSimplePoint
+=
+========================
+*/
+
+boolean TransformSimplePoint (int x, int y, int * screenx, int * height, int * texture, int vertical)
+{
+
+ fixed gxt,gyt,nx,ny;
+ fixed gxtt,gytt;
+ int gx,gy;
+
+
+//
+// translate point to view centered coordinates
+//
+ gx = x-viewx;
+ gy = y-viewy;
+
+//
+// calculate newx
+//
+ gxt = FixedMul(gx,viewcos);
+ gyt = FixedMul(gy,viewsin);
+ nx =gxt-gyt;
+
+ if (nx<MINZ)
+ return false;
+
+
+//
+// calculate newy
+//
+ gxtt = FixedMul(gx,viewsin);
+ gytt = FixedMul(gy,viewcos);
+ ny = gytt+gxtt;
+
+// too close, don't overflow the divid'
+
+
+ *screenx = centerx + ((ny*scale)/nx); // DEBUG: use assembly divide
+
+ *height = heightnumerator/nx;
+
+ if (vertical)
+ *texture=(y-*texture)&0xffff;
+ else
+ *texture=(x-*texture)&0xffff;
+
+ return true;
+}
+
+
+/*
+========================
+=
+= TransformPlane
+=
+========================
+*/
+
+boolean TransformPlane (int x1, int y1, int x2, int y2, visobj_t * plane)
+{
+ boolean result2;
+ boolean result1;
+ boolean vertical;
+ int txstart,txend;
+
+ vertical=((x2-x1)==0);
+ plane->viewx=vertical;
+ txstart=plane->texturestart;
+ txend=plane->textureend;
+ result1=TransformSimplePoint(x1,y1,&(plane->x1),&(plane->h1),&(plane->texturestart),vertical);
+ result2=TransformSimplePoint(x2,y2,&(plane->x2),&(plane->h2),&(plane->textureend),vertical);
+ if (result1==true)
+ {
+ if (plane->x1>=viewwidth)
+ return false;
+ if (result2==false)
+ {
+ plane->textureend=txend;
+ TransformPoint(x2,y2,&(plane->x2),&(plane->h2),&(plane->textureend),vertical);
+ }
+ }
+ else
+ {
+ if (result2==false)
+ return false;
+ else
+ {
+ if (plane->x2<0)
+ return false;
+ plane->texturestart=txstart;
+ TransformPoint(x1,y1,&(plane->x1),&(plane->h1),&(plane->texturestart),vertical);
+ }
+ }
+ if (plane->x1<0)
+ {
+ plane->texturestart=txstart;
+ TransformPoint(x1,y1,&(plane->x1),&(plane->h1),&(plane->texturestart),vertical);
+ }
+ if (plane->x2>=viewwidth)
+ {
+ plane->textureend=txend;
+ TransformPoint(x2,y2,&(plane->x2),&(plane->h2),&(plane->textureend),vertical);
+ }
+
+ plane->viewheight=(plane->h1+plane->h2)>>1;
+
+ if ((plane->viewheight>=(2000<<HEIGHTFRACTION)) || (plane->x1>=viewwidth-1) || (plane->x2<=0))
+ return false;
+
+ return true;
+}
+
+//==========================================================================
+
+/*
+====================
+=
+= CalcHeight
+=
+= Calculates the height of xintercept,yintercept from viewx,viewy
+=
+====================
+*/
+
+int CalcHeight (void)
+{
+ fixed gxt,gyt,nx;
+ long gx,gy;
+
+ whereami=0;
+
+ gx = xintercept-viewx;
+ gxt = FixedMul(gx,viewcos);
+
+ gy = yintercept-viewy;
+ gyt = FixedMul(gy,viewsin);
+
+ nx = gxt-gyt;
+
+ if (nx<mindist)
+ nx=mindist; // don't let divide overflo'
+
+ return (heightnumerator/nx);
+}
+
+
+
+#if 0
+//==========================================================================
+
+//******************************************************************************
+//
+// NextPlaneptr
+//
+//******************************************************************************
+
+void NextPlaneptr ( void )
+{
+ if (planeptr < &planelist[MAXPLANES-1]) // don't let it overflo'
+ planeptr++;
+}
+
+//******************************************************************************
+//
+// RestPlaneptr
+//
+//******************************************************************************
+
+void ResetPlaneptr ( void )
+{
+ planeptr = &planelist[0];
+}
+
+//******************************************************************************
+//
+// NextVisptr
+//
+//******************************************************************************
+
+void NextVisptr ( void )
+{
+ if (visptr < &vislist[MAXVISIBLE-1]) // don't let it overflo'
+ visptr++;
+}
+
+//******************************************************************************
+//
+// ResetVisptr
+//
+//******************************************************************************
+
+void ResetVisptr ( void )
+{
+ visptr = &vislist[0];
+}
+
+#endif
+
+//==========================================================================
+
+
+
+/*
+=====================
+=
+= StatRotate
+=
+=====================
+*/
+
+int StatRotate (statobj_t *temp)
+{
+ int angle;
+ int dx,dy;
+
+ whereami=2;
+
+ dx = temp->x - player->x;
+ dy = player->y - temp->y;
+ angle = atan2_appx(dx,dy);
+
+ angle = angle-VANG180-dirangle8[temp->count];
+ angle+=ANGLES/16;
+ while (angle>=ANGLES)
+ angle-=ANGLES;
+ while (angle<0)
+ angle+=ANGLES;
+
+ return angle/(ANGLES/8);
+
+}
+
+
+
+
+/*
+=====================
+=
+= CalcRotate
+=
+=====================
+*/
+
+int CalcRotate (objtype *ob)
+{
+ int angle,viewangle;
+ int dx,dy;
+ int rotation;
+
+ whereami=1;
+
+ // this isn't exactly correct, as it should vary by a trig value'
+ // but it is close enough with only eight rotations
+ /*
+ if (ob->obclass == b_robobossobj)
+ viewangle = player->angle;
+ else
+ viewangle = player->angle + (centerx - ob->viewx)/8;*/
+ dx = ob->x - player->x;
+ dy = player->y - ob->y;
+ viewangle = atan2_appx(dx,dy);
+
+ if ((ob->obclass >= p_bazookaobj) || (ob->obclass == missileobj))
+ { angle = viewangle - ob->angle;
+#if (0)
+ Debug("\nviewangle: %d, angle: %d",viewangle,angle);
+#endif
+ }
+ else if ((ob->obclass > wallopobj) && (ob->obclass != b_darksnakeobj))
+ angle = (viewangle-ANG180)- ob->angle;
+ else if (ob->state->rotate == 16)
+ angle = (viewangle-ANG180)- dirangle16[ob->dir];
+ else
+ angle = (viewangle-ANG180)- dirangle8[ob->dir];
+
+ if (ob->state->rotate == true)
+ angle += ANGLES/16;
+ else if (ob->state->rotate == 16)
+ angle += ANGLES/32;
+
+ while (angle>=ANGLES)
+ angle-=ANGLES;
+ while (angle<0)
+ angle+=ANGLES;
+
+ if (ob->state->rotate == 2) // 2 rotation pain frame
+ { rotation = 4*(angle/(ANG180));
+ return rotation;
+ }
+
+ if (ob->state->rotate == 16)
+ { rotation = angle/(ANGLES/16);
+#if (0)
+ Debug("\nrotation: %d", rotation);
+#endif
+ return rotation;
+ }
+ rotation = angle/(ANGLES/8);
+ return rotation;
+
+}
+
+
+
+#if 0
+/*
+=====================
+=
+= DrawMaskedWalls
+=
+=====================
+*/
+
+void DrawMaskedWalls (void)
+{
+
+
+ int i,numvisible;
+ int gx,gy;
+ unsigned short int *tilespot;
+ byte *visspot;
+ boolean result;
+ statobj_t *statptr;
+ objtype *obj;
+ maskedwallobj_t* tmwall;
+
+ whereami=6;
+
+//
+// place maskwall objects
+//
+ for(tmwall=FIRSTMASKEDWALL; tmwall; tmwall=tmwall->next)
+ {
+ if (spotvis[tmwall->tilex][tmwall->tiley])
+ {
+ mapseen[tmwall->tilex][tmwall->tiley]=1;
+ if (tmwall->vertical)
+ {
+ gx=(tmwall->tilex<<16)+0x8000;
+ gy=(tmwall->tiley<<16);
+ visptr->texturestart=0;
+ visptr->textureend=0;
+ if (viewx<gx)
+ result=TransformPlane(gx,gy,gx,gy+0xffff,visptr);
+ else
+ result=TransformPlane(gx,gy+0xffff,gx,gy,visptr);
+ visptr->shapenum=tmwall->bottomtexture;
+ visptr->altshapenum=tmwall->midtexture;
+ visptr->viewx=tmwall->toptexture;
+ visptr->shapesize=2;
+ }
+ else
+ {
+ gx=(tmwall->tilex<<16);
+ gy=(tmwall->tiley<<16)+0x8000;
+ visptr->texturestart=0;
+ visptr->textureend=0;
+ if (viewy<gy)
+ result=TransformPlane(gx+0xffff,gy,gx,gy,visptr);
+ else
+ result=TransformPlane(gx,gy,gx+0xffff,gy,visptr);
+ visptr->shapenum=tmwall->bottomtexture;
+ visptr->altshapenum=tmwall->midtexture;
+ visptr->viewx=tmwall->toptexture;
+ visptr->shapesize=2;
+ }
+ if ((tmwall->flags&MW_TOPFLIPPING) &&
+ (nonbobpheight>64)
+ )
+ {
+ visptr->viewx++;
+ }
+ else if ((tmwall->flags&MW_BOTTOMFLIPPING) &&
+ (nonbobpheight>maxheight-32)
+ )
+ {
+ visptr->shapenum++;
+ }
+ if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
+ visptr++;
+ }
+ }
+}
+#endif
+
+/*
+======================
+=
+= SortScaleds
+= Sort the scaleds using a HEAPSORT
+=
+======================
+*/
+
+#define SGN(x) ((x>0) ? (1) : ((x==0) ? (0) : (-1)))
+
+/*--------------------------------------------------------------------------*/
+int CompareHeights(s1p,s2p) visobj_t **s1p,**s2p;
+{
+ whereami=3;
+ return SGN((*s1p)->viewheight-(*s2p)->viewheight);
+}
+
+void SwitchPointers(s1p,s2p) visobj_t **s1p,**s2p;
+{
+ visobj_t * temp;
+
+ whereami=4;
+ temp=*s1p;
+ *s1p=*s2p;
+ *s2p=temp;
+}
+
+
+void SortVisibleList( int numvisible, visobj_t * vlist )
+{
+ int i;
+
+ whereami=5;
+ for (i=0; i<numvisible; i++)
+ sortedvislist[i]=&(vlist[i]);
+ hsort((char *)&(sortedvislist[0]),numvisible,sizeof(visobj_t *),&CompareHeights,&SwitchPointers);
+}
+
+/*
+=====================
+=
+= DrawScaleds
+=
+= Draws all objects that are visible
+=
+=====================
+*/
+
+#define HF_1 (24)
+#define HF_2 (72)
+
+void DrawScaleds (void)
+{
+
+
+ int i,numvisible;
+ int gx,gy;
+ unsigned short int *tilespot;
+ byte *visspot;
+ boolean result;
+ statobj_t *statptr;
+ objtype *obj;
+ maskedwallobj_t* tmwall;
+
+ whereami=6;
+
+//
+// place maskwall objects
+//
+ for(tmwall=FIRSTMASKEDWALL; tmwall; tmwall=tmwall->next)
+ {
+ if (spotvis[tmwall->tilex][tmwall->tiley])
+ {
+ mapseen[tmwall->tilex][tmwall->tiley]=1;
+ if (tmwall->vertical)
+ {
+ gx=(tmwall->tilex<<16)+0x8000;
+ gy=(tmwall->tiley<<16);
+ visptr->texturestart=0;
+ visptr->textureend=0;
+ if (viewx<gx)
+ result=TransformPlane(gx,gy,gx,gy+0xffff,visptr);
+ else
+ result=TransformPlane(gx,gy+0xffff,gx,gy,visptr);
+ visptr->shapenum=tmwall->bottomtexture;
+ visptr->altshapenum=tmwall->midtexture;
+ visptr->viewx=tmwall->toptexture;
+ visptr->shapesize=2;
+ }
+ else
+ {
+ gx=(tmwall->tilex<<16);
+ gy=(tmwall->tiley<<16)+0x8000;
+ visptr->texturestart=0;
+ visptr->textureend=0;
+ if (viewy<gy)
+ result=TransformPlane(gx+0xffff,gy,gx,gy,visptr);
+ else
+ result=TransformPlane(gx,gy,gx+0xffff,gy,visptr);
+ visptr->shapenum=tmwall->bottomtexture;
+ visptr->altshapenum=tmwall->midtexture;
+ visptr->viewx=tmwall->toptexture;
+ visptr->shapesize=2;
+ }
+ if ((tmwall->flags&MW_TOPFLIPPING) &&
+ (nonbobpheight>64)
+ )
+ {
+ visptr->viewx++;
+ }
+ else if ((tmwall->flags&MW_BOTTOMFLIPPING) &&
+ (nonbobpheight>maxheight-32)
+ )
+ {
+ visptr->shapenum++;
+ }
+ if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
+ visptr++;
+ }
+ }
+//
+// place static objects
+//
+ UpdateClientControls();
+ for (statptr = firstactivestat ; statptr; statptr=statptr->nextactive)
+ { //redraw:
+ if((visptr->shapenum = statptr->shapenum) == NOTHING)
+ continue;
+
+ visptr->shapenum += shapestart;
+ if ((visptr->shapenum <= shapestart) ||
+ (visptr->shapenum >= shapestop))
+ Error("actor shapenum %d out of range (%d-%d)",visptr->shapenum,shapestart,shapestop);
+
+ visspot = statptr->visspot;
+ if (!((*(visspot-0)) ||
+ (*(visspot-1)) ||
+ (*(visspot+1)) ||
+ (*(visspot-129)) ||
+ (*(visspot-128)) ||
+ (*(visspot-127)) ||
+ (*(visspot+129)) ||
+ (*(visspot+128)) ||
+ (*(visspot+127))))
+ { statptr->flags &= ~FL_VISIBLE;
+ continue; // not visible
+ }
+
+ result = TransformObject (statptr->x,statptr->y,&(visptr->viewx),&(visptr->viewheight));
+
+ if ((result==false) || (visptr->viewheight< (1<<(HEIGHTFRACTION+2))))
+ continue; // to close to the object
+ statptr->flags |= FL_SEEN;
+
+ statptr->flags |= FL_VISIBLE;
+
+ if (statptr->flags & FL_ROTATING)
+ visptr->shapenum += StatRotate(statptr);
+
+ if (statptr->flags&FL_TRANSLUCENT)
+ {
+ visptr->shapesize=1;
+ if (statptr->flags&FL_FADING)
+ visptr->h2=transparentlevel;
+ else
+ visptr->h2=FIXEDTRANSLEVEL;
+ SetSpriteLightLevel(statptr->x,statptr->y,visptr,0,(statptr->flags&FL_FULLLIGHT));
+ }
+ else if (statptr->flags&FL_SOLIDCOLOR)
+ {
+ visptr->shapesize=4;
+ visptr->h2=statptr->hitpoints;
+ }
+ else if (statptr->flags&FL_COLORED)
+ {
+ visptr->shapesize=0;
+#if (DEVELOPMENT == 1)
+ if ((statptr->hitpoints>=0) &&
+ (statptr->hitpoints<MAXPLAYERCOLORS))
+ {
+#endif
+ SetColorLightLevel(statptr->x,statptr->y,visptr,
+ 0,statptr->hitpoints,
+ (statptr->flags&FL_FULLLIGHT));
+#if (DEVELOPMENT == 1)
+ }
+ else
+ {
+ Error("Illegal color map for sprite type %d\n",statptr->itemnumber);
+ }
+#endif
+ }
+ else
+ {
+ visptr->shapesize=0;
+ SetSpriteLightLevel(statptr->x,statptr->y,visptr,0,(statptr->flags&FL_FULLLIGHT));
+ }
+
+ visptr->h1=pheight-statptr->z;
+
+ if ((statptr->itemnumber != (unsigned int)-1) &&
+ (statptr->flags&FL_HEIGHTFLIPPABLE)
+ )
+ {
+ if (statptr->itemnumber==stat_disk)
+ {
+ int value;
+ value=nonbobpheight-statptr->z-32;
+ if ((value<=HF_2) && (value>HF_1))
+ {
+ visptr->shapenum++;
+ }
+ else if ((value<=HF_1) && (value>=-HF_1))
+ {
+ visptr->shapenum+=2;
+ }
+ else if ((value<-HF_1) && (value>=-HF_2))
+ {
+ visptr->shapenum+=3;
+ }
+ else if (value<-HF_2)
+ {
+ visptr->shapenum+=4;
+ }
+ }
+ else if ((nonbobpheight-statptr->z)<-16)
+ {
+ visptr->shapenum++;
+ }
+ }
+
+ if (visptr < &vislist[MAXVISIBLE-1]) // don't let it overflo'
+ visptr++;
+
+
+ }
+//
+// place active objects
+//
+ UpdateClientControls();
+ for (obj = firstactive; obj; obj=obj->nextactive)
+ {
+ if (obj==player)
+ continue;
+
+ if ((visptr->shapenum = obj->shapenum) == NOTHING)
+ continue; // no shape
+
+ visptr->shapenum += shapestart;
+ if ((visptr->shapenum <= shapestart) ||
+ (visptr->shapenum >= shapestop))
+ Error("actor shapenum %d out of range (%d-%d)",visptr->shapenum,shapestart,shapestop);
+ visspot = &spotvis[obj->tilex][obj->tiley];
+ tilespot = &tilemap[obj->tilex][obj->tiley];
+
+ //
+ // could be in any of the nine surrounding tiles
+ //
+ if (*visspot
+ || ( *(visspot-1))
+ || ( *(visspot+1))
+ || ( *(visspot-129))
+ || ( *(visspot-128))
+ || ( *(visspot-127))
+ || ( *(visspot+129))
+ || ( *(visspot+128))
+ || ( *(visspot+127)) )
+ {
+
+// result = TransformObject (obj->drawx, obj->drawy,&(visptr->viewx),&(visptr->viewheight));
+ result = TransformObject (obj->x, obj->y,&(visptr->viewx),&(visptr->viewheight));
+ if ((result==false) || (visptr->viewheight< (1<<(HEIGHTFRACTION+2))))
+ continue; // to close to the object
+ if (obj->state->rotate)
+ visptr->shapenum += CalcRotate (obj);
+
+ visptr->shapesize=0;
+
+ if (player->flags&FL_SHROOMS)
+ {
+ visptr->shapesize=4;
+ visptr->h2=(GetTicCount()&0xff);
+ }
+ if (obj->obclass==playerobj)
+ {
+ if (obj->flags&FL_GODMODE)
+ {
+ visptr->shapesize=4;
+ visptr->h2=240+(GetTicCount()&0x7);
+ }
+ else if (obj->flags & FL_COLORED)
+ {
+ playertype *pstate;
+
+ M_LINKSTATE(obj,pstate);
+#if (DEVELOPMENT == 1)
+ if ((pstate->uniformcolor>=0) &&
+ (pstate->uniformcolor<MAXPLAYERCOLORS))
+ {
+#endif
+ SetColorLightLevel(obj->x,obj->y,visptr,
+ obj->dir,pstate->uniformcolor,
+ (obj->flags&FL_FULLLIGHT) );
+#if (DEVELOPMENT == 1)
+ }
+ else
+ {
+ Error("Illegal color map for players\n");
+ }
+#endif
+ }
+ else
+ SetSpriteLightLevel(obj->x,obj->y,visptr,obj->dir,(obj->flags&FL_FULLLIGHT));
+
+ }
+ else
+ {
+ if ((obj->obclass >= b_darianobj) && (obj->obclass <= b_robobossobj) &&
+ MISCVARS->redindex)
+ {
+ visptr->colormap=redmap+((MISCVARS->redindex-1)<<8);
+ }
+ else
+ {
+ SetSpriteLightLevel(obj->x,obj->y,visptr,obj->dir,(obj->flags&FL_FULLLIGHT));
+ }
+ }
+
+ visptr->h1= pheight - obj->z;
+
+ if (obj->obclass==diskobj)
+ {
+ int value;
+ value=nonbobpheight-obj->z-32;
+ if ((value<=HF_2) && (value>HF_1))
+ {
+ visptr->shapenum++;
+ }
+ else if ((value<=HF_1) && (value>=-HF_1))
+ {
+ visptr->shapenum+=2;
+ }
+ else if ((value<-HF_1) && (value>=-HF_2))
+ {
+ visptr->shapenum+=3;
+ }
+ else if (value<-HF_2)
+ {
+ visptr->shapenum+=4;
+ }
+ }
+ else if ( (obj->obclass==pillarobj) &&
+ ((nonbobpheight-obj->z)<-16)
+ )
+ {
+ visptr->shapenum++;
+ }
+
+ if (visptr < &vislist[MAXVISIBLE-1]) // don't let it overflo'
+ visptr++;
+ obj->flags |= FL_SEEN;
+ obj->flags |= FL_VISIBLE;
+ }
+ else
+ obj->flags &= ~FL_VISIBLE;
+ }
+//
+// draw from back to front
+//
+ numvisible = visptr-&vislist[0];
+ if (!numvisible)
+ return; // no visible objects
+ SortVisibleList( numvisible, &vislist[0] );
+ UpdateClientControls();
+ for (i = 0; i<numvisible; i++)
+ {
+ //
+ // draw farthest
+ //
+
+ if (sortedvislist[i]->shapesize==4) {
+
+ ScaleSolidShape(sortedvislist[i]);
+
+ } else if (sortedvislist[i]->shapesize==3) {
+
+ InterpolateDoor (sortedvislist[i]);
+
+ } else if (sortedvislist[i]->shapesize==2) {
+
+ InterpolateMaskedWall (sortedvislist[i]);
+
+ } else if (sortedvislist[i]->shapesize==1) {
+
+ ScaleTransparentShape(sortedvislist[i]);
+
+ } else {
+
+ ScaleShape(sortedvislist[i]);
+
+ }
+
+ }
+}
+
+//==========================================================================
+
+
+
+
+
+/*
+==============
+=
+= DrawPlayerWeapon
+=
+= Draw the player's hand'
+=
+==============
+*/
+
+void DrawPlayerWeapon (void)
+{
+ int shapenum,index;
+ int xdisp=0;
+ int ydisp=0;
+ int female,black;
+ int altshape=0;
+
+ whereami=7;
+
+ SoftError("\n attackframe: %d, weaponframe: %d, weapondowntics: %d"
+ " weaponuptics: %d",locplayerstate->attackframe,
+ locplayerstate->weaponframe,locplayerstate->weapondowntics,
+ locplayerstate->weaponuptics);
+
+ if ((locplayerstate->NETCAPTURED == 1) && (!locplayerstate->HASKNIFE))
+ return;
+
+ if (locplayerstate->weapon != -1)
+ { female = ((locplayerstate->player == 1) || (locplayerstate->player == 3));
+ black = (locplayerstate->player == 2);
+
+ if (((locplayerstate->NETCAPTURED >= 1) || (locplayerstate->NETCAPTURED == -2)) && (locplayerstate->HASKNIFE == 1)) // if raising or lowering
+ { index = 0;
+ shapenum = gunsstart + weaponshape[index] + locplayerstate->weaponframe;
+ }
+ else if (locplayerstate->weapon != wp_twopistol)
+ { if (locplayerstate->weapon==wp_pistol)
+ { if (female)
+ index = NUMWEAPGRAPHICS-2;
+ else if (black)
+ index = NUMWEAPGRAPHICS-1;
+ else
+#if (SHAREWARE == 0)
+ index = 1;
+#else
+ index = 0;
+#endif
+ }
+ else
+#if (SHAREWARE == 0)
+
+ index = locplayerstate->weapon + 1;
+#else
+ index = locplayerstate->weapon;
+#endif
+
+ if ((index<0) || (index>=NUMWEAPGRAPHICS))
+ Error ("Weapon shapenum out of range\n");
+ shapenum = gunsstart + weaponshape[index] + locplayerstate->weaponframe;
+
+#if (SHAREWARE == 0)
+ if ((shapenum < W_GetNumForName("KNIFE1")) ||
+ (shapenum > W_GetNumForName("DOGPAW4"))
+ )
+#else
+ if ((shapenum < W_GetNumForName("MPIST11")) ||
+ (shapenum > W_GetNumForName("GODHAND8"))
+ )
+#endif
+ Error("\n illegal weapon shapenum %d, index %d, weaponframe %d",
+ shapenum,index,locplayerstate->weaponframe);
+ }
+
+ else
+ {
+#if (SHAREWARE == 0)
+ if (female)
+ { altshape = W_FLEFTPISTOL1;
+ shapenum = W_FRIGHTPISTOL1;
+ }
+ else if (black)
+ { altshape = W_BMLEFTPISTOL1;
+ shapenum = W_BMRIGHTPISTOL1;
+ }
+ else
+#endif
+ { altshape = W_MLEFTPISTOL1;
+ shapenum = W_MRIGHTPISTOL1;
+ }
+
+ altshape += gunsstart;
+ shapenum += gunsstart;
+ if (locplayerstate->weaponframe > 2)
+ altshape += (locplayerstate->weaponframe - 3);
+ else
+ shapenum += locplayerstate->weaponframe;
+ }
+
+ if (!(locplayerstate->NETCAPTURED) ||
+ (locplayerstate->NETCAPTURED == -1) ||
+ (locplayerstate->HASKNIFE == 0))
+ { switch (locplayerstate->weapon)
+ {
+
+ case wp_godhand:
+ break;
+
+ case wp_mp40:
+ break;
+
+ case wp_firewall:
+ ydisp = 10;
+ break;
+
+ case wp_bazooka:
+ break;
+
+ case wp_heatseeker:
+ ydisp = 20;
+ break;
+
+ case wp_pistol:
+ break;
+
+ case wp_twopistol:
+ xdisp = 80;
+ break;
+
+ case wp_drunk:
+ ydisp = 10;
+ break;
+
+ case wp_firebomb:
+ break;
+
+
+
+#if (SHAREWARE == 0)
+
+ case wp_kes:
+ break;
+
+ case wp_bat:
+ xdisp = 20;
+ break;
+
+ case wp_split:
+ ydisp = 20;
+ break;
+
+
+ case wp_dog:
+ break;
+
+
+#endif
+
+ default:
+ Error("Illegal weapon value = %d\n",locplayerstate->weapon);
+ break;
+ }
+ }
+ else
+ xdisp = 60;
+
+
+
+
+ if (altshape)
+ {
+ int temp;
+ int delta;
+
+ temp = weaponscale;
+ delta = FixedMul((weaponbobx<<9),weaponscale);
+ weaponscale += delta;
+ ScaleWeapon(xdisp - weaponbobx,ydisp + weaponboby + locplayerstate->weaponheight,shapenum);
+ weaponscale -= delta;
+ ScaleWeapon(weaponbobx - 80,ydisp + weaponboby + locplayerstate->weaponheight,altshape);
+ weaponscale = temp;
+ }
+ else
+ {
+ int temp;
+ int delta;
+
+ temp = weaponscale;
+ delta = FixedMul((weaponbobx<<9),weaponscale);
+ weaponscale -= delta;
+ ScaleWeapon(xdisp + weaponbobx,ydisp + weaponboby + locplayerstate->weaponheight,shapenum);
+ weaponscale = temp;
+ }
+ }
+}
+
+void AdaptDetail ( void )
+{
+#if PROFILE
+ return;
+#else
+
+ whereami=8;
+ if ((preindex<0) || (preindex>2))
+ Error("preindex out of range\n");
+ pretics[preindex]=(pretics[0]+pretics[1]+pretics[2]+(tics<<16)+0x8000)>>2;
+ if (pretics[preindex]>GOLOWER)
+ {
+ pretics[0]=GOHIGHER;
+ pretics[1]=GOHIGHER;
+ pretics[2]=GOHIGHER;
+ doublestep++;
+ if (doublestep>2) doublestep=2;
+ }
+ else if (pretics[preindex]<GOHIGHER)
+ {
+ if (doublestep>0)
+ doublestep--;
+ }
+ preindex++;
+ if (preindex>2)
+ preindex=0;
+#endif
+}
+
+
+
+/*
+=====================
+=
+= CalcTics
+=
+=====================
+*/
+
+void CalcTics (void)
+{
+
+#if PROFILE
+ tics=PROFILETICS;
+ GetTicCount()+=PROFILETICS;
+ oldtime=GetTicCount();
+ return;
+#else
+#if (DEVELOPMENT == 1)
+ int i;
+#endif
+ volatile int tc;
+
+ whereami=9;
+// SoftError("InCalcTics\n");
+// SoftError("CT GetTicCount()=%ld\n",GetTicCount());
+// SoftError("CT oldtime=%ld\n",oldtime);
+
+//
+// calculate tics since last refresh for adaptive timing
+//
+
+ tc=GetTicCount();
+ while (tc==oldtime) {
+ tc=GetTicCount(); /* endwhile */
+ }
+ tics=tc-oldtime;
+
+// SoftError("CT GetTicCount()=%ld\n",GetTicCount());
+// if (tics>MAXTICS)
+// {
+// tc-=(tics-MAXTICS);
+// GetTicCount() = tc;
+// tics = MAXTICS;
+// }
+
+ if (demoplayback || demorecord)
+ {
+ if (tics>MAXTICS)
+ {
+ tc=oldtime+MAXTICS;
+ tics=MAXTICS;
+ ISR_SetTime(tc);
+ }
+ }
+ oldtime=tc;
+#if (DEVELOPMENT == 1)
+ if (graphicsmode==true)
+ {
+ int drawntics;
+
+ VGAWRITEMAP(1);
+ drawntics=tics;
+ if (drawntics>MAXDRAWNTICS)
+ drawntics=MAXDRAWNTICS;
+ for (i=0; i<drawntics; i++)
+ *((byte *)displayofs+screenofs+(SCREENBWIDE*3)+i)=egacolor[15];
+ }
+ /*
+ if (drawtime>MAXDRAWNTICS)
+ drawtime=MAXDRAWNTICS;
+ for (i=0;i<drawtime;i++)
+ *((byte *)displayofs+screenofs+(SCREENBWIDE*5)+i)=egacolor[2];
+ if (walltime>MAXDRAWNTICS)
+ walltime=MAXDRAWNTICS;
+ for (i=0;i<walltime;i++)
+ *((byte *)displayofs+screenofs+(SCREENBWIDE*7)+i)=egacolor[14];
+ if (actortime>MAXDRAWNTICS)
+ actortime=MAXDRAWNTICS;
+ for (i=0;i<actortime;i++)
+ *((byte *)displayofs+screenofs+(SCREENBWIDE*9)+i)=egacolor[4];
+ }
+ */
+#endif
+#endif
+
+}
+
+/*
+==========================
+=
+= SetSpriteLightLevel
+=
+==========================
+*/
+
+void SetSpriteLightLevel (int x, int y, visobj_t * sprite, int dir, int fullbright)
+{
+ int i;
+ int lv;
+ int intercept;
+
+ whereami=10;
+
+ if (MISCVARS->GASON==1)
+ {
+ sprite->colormap=greenmap+(MISCVARS->gasindex<<8);
+ return;
+ }
+
+ if (fulllight || fullbright)
+ {
+ sprite->colormap=colormap+(1<<12);
+ return;
+ }
+
+ if (fog)
+ {
+ i=((sprite->viewheight*200/iGLOBAL_SCREENHEIGHT)>>normalshade)+minshade;
+ if (i>maxshade) i=maxshade;
+ sprite->colormap=colormap+(i<<8);
+ }
+ else
+ {
+ if (lightsource)
+ {
+ if (dir==east || dir==west)
+ intercept=(x>>11)&0x1c;
+ else
+ intercept=(y>>11)&0x1c;
+
+ lv=(((LightSourceAt(x>>16,y>>16)>>intercept)&0xf)>>1);
+ i=maxshade-(sprite->viewheight>>normalshade)-lv;
+ if (i<minshade) i=minshade;
+ sprite->colormap=colormap+(i<<8);
+ }
+ else
+ {
+ i=maxshade-(sprite->viewheight>>normalshade);
+ if (i<minshade) i=minshade;
+ sprite->colormap=colormap+(i<<8);
+ }
+ }
+}
+
+/*
+==========================
+=
+= SetColorLightLevel
+=
+==========================
+*/
+
+void SetColorLightLevel (int x, int y, visobj_t * sprite, int dir, int color, int fullbright)
+{
+ int i;
+ int lv;
+ int intercept;
+ int height;
+ byte * map;
+
+
+ whereami=11;
+ height=sprite->viewheight<<1;
+ map=playermaps[color];
+ if (MISCVARS->GASON==1)
+ {
+ sprite->colormap=greenmap+(MISCVARS->gasindex<<8);
+ return;
+ }
+
+ if ((fulllight) || (fullbright))
+ {
+ sprite->colormap=map+(1<<12);
+ return;
+ }
+
+ if (fog)
+ {
+ i=((height*200/iGLOBAL_SCREENHEIGHT)>>normalshade)+minshade;
+ if (i>maxshade) i=maxshade;
+ sprite->colormap=map+(i<<8);
+ }
+ else
+ {
+ if (lightsource)
+ {
+ if (dir==east || dir==west)
+ intercept=(x>>11)&0x1c;
+ else
+ intercept=(y>>11)&0x1c;
+
+ lv=(((LightSourceAt(x>>16,y>>16)>>intercept)&0xf)>>1);
+ i=maxshade-(height>>normalshade)-lv;
+ if (i<minshade) i=minshade;
+ sprite->colormap=map+(i<<8);
+ }
+ else
+ {
+ i=maxshade-(height>>normalshade);
+ if (i<minshade) i=minshade;
+ sprite->colormap=map+(i<<8);
+ }
+ }
+}
+
+/*
+==========================
+=
+= SetWallLightLevel
+=
+==========================
+*/
+
+void SetWallLightLevel (wallcast_t * post)
+{
+ int la;
+ int lv;
+ int i;
+
+ whereami=12;
+ if (MISCVARS->GASON==1)
+ {
+ shadingtable=greenmap+(MISCVARS->gasindex<<8);
+ return;
+ }
+
+ switch (post->posttype)
+ {
+ case 0:
+ la=0;
+ break;
+ case 1:
+ la=4;
+ break;
+ case 2:
+ la=(4-gamestate.difficulty);
+ break;
+ case 3:
+ la=3+(4-gamestate.difficulty);
+ break;
+ }
+
+ if (lightsource)
+ {
+ int x,y;
+ int intercept;
+
+ x=post->offset>>7;
+ y=post->offset&0x7f;
+ intercept=(post->texture>>11)&0x1c;
+ lv=(((LightSourceAt(x,y)>>intercept)&0xf)>>1);
+ }
+ else
+ lv=0;
+ if (fulllight)
+ {
+ if (fog)
+ {
+ i =16+minshade-lv+la;
+ if (i>maxshade+la) i=maxshade+la;
+ shadingtable=colormap+(i<<8);
+ }
+ else
+ {
+ i =maxshade-16-lv+la;
+ if (i>=maxshade) i=maxshade;
+ if (i<minshade+la) i=minshade+la;
+ shadingtable=colormap+(i<<8);
+ }
+ return;
+ }
+ if (fog)
+ {
+ i =((post->wallheight*200/iGLOBAL_SCREENHEIGHT)>>normalshade)+minshade-lv+la;
+ if (i>maxshade+la) i=maxshade+la;
+ shadingtable=colormap+(i<<8);
+ }
+ else
+ {
+ i =maxshade-(post->wallheight>>normalshade)-lv+la;
+ if (i>=maxshade) i=maxshade;
+ if (i<minshade+la) i=minshade+la;
+ shadingtable=colormap+(i<<8);
+ }
+}
+
+
+
+/*
+====================
+=
+= DrawWallPost
+=
+====================
+*/
+
+void DrawWallPost ( wallcast_t * post, byte * buf)
+{
+ int ht;
+ int topscreen;
+ int bottomscreen;
+ byte * src;
+ byte * src2;
+
+ whereami=42;
+ if (post->lump)
+ src=W_CacheLumpNum(post->lump,PU_CACHE, CvtNull, 1);
+ if (post->alttile!=0)
+ {
+ if (post->alttile==-1)
+ {
+ ht=maxheight+32;
+ dc_invscale = post->wallheight<<(10-HEIGHTFRACTION);
+ dc_texturemid = (pheight<<SFRACBITS)+(SFRACUNIT>>1);
+ topscreen = centeryfrac - FixedMul(dc_texturemid,dc_invscale);
+ bottomscreen = topscreen + (dc_invscale*ht);
+ dc_yh = ((bottomscreen-1)>>SFRACBITS)+1;
+ if (dc_yh < 0)
+ {
+ post->floorclip=-1;
+ post->ceilingclip=0;
+ }
+ else if (dc_yh >= viewheight)
+ {
+ post->floorclip=viewheight-1;
+ post->ceilingclip=viewheight;
+ }
+ else
+ {
+ post->floorclip=dc_yh-1;
+ post->ceilingclip=dc_yh;
+ }
+ return;
+ }
+ else
+ {
+ ht=nominalheight;
+ src2=W_CacheLumpNum(post->alttile,PU_CACHE, CvtNull, 1);
+ }
+ }
+ else
+ {
+ ht=maxheight+32;
+ src2=src;
+ }
+
+ dc_invscale = post->wallheight<<(10-HEIGHTFRACTION);
+ dc_texturemid = (pheight<<SFRACBITS)+(SFRACUNIT>>1);
+ topscreen = centeryfrac - FixedMul(dc_texturemid,dc_invscale);
+ bottomscreen = topscreen + (dc_invscale*ht);
+ dc_yl = (topscreen+SFRACUNIT-1)>>SFRACBITS;
+ dc_yh = ((bottomscreen-1)>>SFRACBITS)+1;
+
+ if (dc_yl >= viewheight)
+ {
+ post->ceilingclip=viewheight;
+ post->floorclip=viewheight-1;
+ return;
+ }
+ else if (dc_yl < 0)
+ dc_yl = 0;
+
+ dc_iscale = (64<<(16+HEIGHTFRACTION))/post->wallheight;
+
+ if (dc_yh < 0)
+ {
+ post->floorclip=-1;
+ post->ceilingclip=0;
+ goto bottomcheck;
+ }
+ else if (dc_yh > viewheight)
+ dc_yh = viewheight;
+
+ post->ceilingclip=dc_yl;
+ post->floorclip=dc_yh-1;
+ dc_source=src2+((post->texture>>4)&0xfc0);
+ R_DrawWallColumn (buf);
+
+bottomcheck:
+
+ if (ht!=nominalheight)
+ return;
+
+ dc_texturemid-=(nominalheight<<SFRACBITS);
+ topscreen = centeryfrac - FixedMul(dc_texturemid,dc_invscale);
+ bottomscreen = topscreen + (dc_invscale<<6);
+ dc_yl = (topscreen+SFRACUNIT-1)>>SFRACBITS;
+ dc_yh = ((bottomscreen-1)>>SFRACBITS);
+
+ if (dc_yl >= viewheight)
+ return;
+ else if (dc_yl < 0)
+ dc_yl = 0;
+ if (dc_yh < 0)
+ return;
+ else if (dc_yh > viewheight)
+ dc_yh = viewheight;
+ post->floorclip=dc_yh-1;
+ dc_source=src+((post->texture>>4)&0xfc0);
+ R_DrawWallColumn (buf);
+}
+
+/*
+====================
+=
+= DrawWalls
+=
+====================
+*/
+
+void DrawWalls (void)
+{
+ char * buf;
+ int plane;
+ wallcast_t * post;
+
+ whereami=13;
+
+ plane = 0;
+
+ if (doublestep>1)
+ {
+#ifdef DOS
+ for (plane=0; plane<4; plane+=2)
+#endif
+ {
+ VGAMAPMASK((1<<plane)+(1<<(plane+1)));
+ buf=(byte *)(bufferofs);
+#ifdef DOS
+ for (post=&posts[plane]; post<&posts[viewwidth]; post+=4,buf++)
+#else
+ for (post=&posts[plane]; post<&posts[viewwidth]; post+=2,buf+=2)
+#endif
+ {
+ SetWallLightLevel(post);
+ DrawWallPost(post,buf);
+#ifndef DOS
+ DrawWallPost(post,buf+1);
+#endif
+ (post+1)->ceilingclip=post->ceilingclip;
+ (post+1)->floorclip=post->floorclip;
+ }
+ }
+ }
+ else
+ {
+#ifdef DOS
+ for (plane=0; plane<4; plane++)
+#endif
+ {
+ VGAWRITEMAP(plane);
+ buf=(byte *)(bufferofs);
+#ifdef DOS
+ for (post=&posts[plane]; post<&posts[viewwidth]; post+=4,buf++)
+#else
+ for (post=&posts[plane]; post<&posts[viewwidth]; post++,buf++)
+#endif
+ {
+ SetWallLightLevel(post);
+ DrawWallPost(post,buf);
+ }
+ }
+ }
+}
+
+
+/*
+====================
+=
+= TransformDoors
+=
+====================
+*/
+
+void TransformDoors( void )
+{
+ int i;
+ int numvisible;
+ boolean result;
+ int gx,gy;
+ visobj_t visdoorlist[MAXVISIBLEDOORS],*doorptr;
+
+ whereami=14;
+ doorptr=&visdoorlist[0];
+//
+// place door objects
+//
+
+ for (i = 0; i<doornum; i++)
+ {
+ if (spotvis[doorobjlist[i]->tilex][doorobjlist[i]->tiley])
+ {
+ mapseen[doorobjlist[i]->tilex][doorobjlist[i]->tiley]=1;
+ doorptr->texturestart=0;
+ doorptr->textureend=0;
+ if (doorobjlist[i]->vertical)
+ {
+ gx=(doorobjlist[i]->tilex<<16)+0x8000;
+ gy=(doorobjlist[i]->tiley<<16);
+ if (viewx<gx)
+ result=TransformPlane(gx,gy,gx,gy+0xffff,doorptr);
+ else
+ result=TransformPlane(gx,gy+0xffff,gx,gy,doorptr);
+ }
+ else
+ {
+ gx=(doorobjlist[i]->tilex<<16);
+ gy=(doorobjlist[i]->tiley<<16)+0x8000;
+ if (viewy<gy)
+ result=TransformPlane(gx+0xffff,gy,gx,gy,doorptr);
+ else
+ result=TransformPlane(gx,gy,gx+0xffff,gy,doorptr);
+ }
+ if (result==true)
+ {
+ doorptr->viewx=0;
+ doorptr->shapenum=doorobjlist[i]->texture;
+ doorptr->altshapenum=doorobjlist[i]->alttexture;
+ if (doorobjlist[i]->texture==doorobjlist[i]->basetexture)
+ {
+ doorptr->shapesize=(doorobjlist[i]->tilex<<7)+doorobjlist[i]->tiley;
+ if (doorptr < &visdoorlist[MAXVISIBLEDOORS-1]) // don't let it overflo'
+ doorptr++;
+ }
+ else
+ {
+ doorptr->shapesize=3;
+ memcpy(visptr,doorptr,sizeof(visobj_t));
+ if (visptr < &vislist[MAXVISIBLE-1])
+ visptr++;
+ }
+ }
+ }
+ }
+//
+// draw from back to front
+//
+ numvisible = doorptr-&visdoorlist[0];
+ if (!numvisible)
+ return;
+ SortVisibleList( numvisible, &visdoorlist[0] );
+ for (i = 0; i<numvisible; i++)
+ {
+ //
+ // draw farthest
+ //
+ InterpolateWall (sortedvislist[i]);
+ }
+}
+
+
+/*
+====================
+=
+= TransformPushWalls
+=
+====================
+*/
+
+void TransformPushWalls( void )
+{
+ int i;
+ int gx,gy;
+ byte *visspot;
+ visobj_t *savedptr;
+ int numvisible;
+ boolean result;
+
+ whereami=15;
+ savedptr=visptr;
+ //
+ // place pwall objects
+ //
+ for (i = 0; i<pwallnum; i++)
+ {
+ if ((pwallobjlist[i]->action==pw_pushed) || (pwallobjlist[i]->action==pw_npushed))
+ continue;
+ visspot = &spotvis[pwallobjlist[i]->x>>16][pwallobjlist[i]->y>>16];
+ if (*visspot
+ || ( *(visspot-1))
+ || ( *(visspot+1))
+ || ( *(visspot-128))
+ || ( *(visspot+128)))
+ {
+ gx=pwallobjlist[i]->x;
+ gy=pwallobjlist[i]->y;
+ mapseen[gx>>16][gy>>16]=1;
+ if (viewx<gx)
+ {
+ if (viewy<gy)
+ {
+ visptr->texturestart=(gx-0x8000)&0xffff;
+ visptr->textureend=visptr->texturestart;
+ result=TransformPlane(gx+0x7fff,gy-0x8000,gx-0x8000,gy-0x8000,visptr);
+ visptr->texturestart^=0xffff;
+ visptr->textureend^=0xffff;
+ visptr->shapenum=pwallobjlist[i]->texture;
+ visptr->shapesize=((pwallobjlist[i]->x>>16)<<7)+(pwallobjlist[i]->y>>16);
+ visptr->viewx+=2;
+ if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
+ visptr++;
+ visptr->texturestart=(gy-0x8000)&0xffff;
+ visptr->textureend=visptr->texturestart;//-0xffff;
+ result=TransformPlane(gx-0x8000,gy-0x8000,gx-0x8000,gy+0x7fff,visptr);
+ }
+ else
+ {
+ visptr->texturestart=(gy-0x8000)&0xffff;
+ visptr->textureend=visptr->texturestart;//-0xffff;
+ result=TransformPlane(gx-0x8000,gy-0x8000,gx-0x8000,gy+0x7fff,visptr);
+ visptr->shapenum=pwallobjlist[i]->texture;
+ visptr->shapesize=((pwallobjlist[i]->x>>16)<<7)+(pwallobjlist[i]->y>>16);
+ visptr->viewx+=2;
+ if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
+ visptr++;
+ visptr->texturestart=(gx-0x8000)&0xffff;
+ visptr->textureend=visptr->texturestart;//-0xffff;
+ result=TransformPlane(gx-0x8000,gy+0x7fff,gx+0x7fff,gy+0x7fff,visptr);
+ }
+ }
+ else
+ {
+ if (viewy<gy)
+ {
+ visptr->texturestart=(gy-0x8000)&0xffff;
+ visptr->textureend=visptr->texturestart;
+ result=TransformPlane(gx+0x7fff,gy+0x7fff,gx+0x7fff,gy-0x8000,visptr);
+ visptr->texturestart^=0xffff;
+ visptr->textureend^=0xffff;
+ visptr->shapenum=pwallobjlist[i]->texture;
+ visptr->shapesize=((pwallobjlist[i]->x>>16)<<7)+(pwallobjlist[i]->y>>16);
+ visptr->viewx+=2;
+ if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
+ visptr++;
+ visptr->texturestart=(gx-0x8000)&0xffff;
+ visptr->textureend=visptr->texturestart;
+ result=TransformPlane(gx+0x7fff,gy-0x8000,gx-0x8000,gy-0x8000,visptr);
+ visptr->texturestart^=0xffff;
+ visptr->textureend^=0xffff;
+ }
+ else
+ {
+ visptr->texturestart=(gx-0x8000)&0xffff;
+ visptr->textureend=visptr->texturestart;//-0xffff;
+ result=TransformPlane(gx-0x8000,gy+0x7fff,gx+0x7fff,gy+0x7fff,visptr);
+ visptr->shapenum=pwallobjlist[i]->texture;
+ visptr->shapesize=((pwallobjlist[i]->x>>16)<<7)+(pwallobjlist[i]->y>>16);
+ visptr->viewx+=2;
+ if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
+ visptr++;
+ visptr->texturestart=(gy-0x8000)&0xffff;
+ visptr->textureend=visptr->texturestart;
+ result=TransformPlane(gx+0x7fff,gy+0x7fff,gx+0x7fff,gy-0x8000,visptr);
+ visptr->texturestart^=0xffff;
+ visptr->textureend^=0xffff;
+ }
+ }
+ visptr->viewx+=2;
+ visptr->shapenum=pwallobjlist[i]->texture;
+ visptr->shapesize=((pwallobjlist[i]->x>>16)<<7)+(pwallobjlist[i]->y>>16);
+ if ((visptr < &vislist[MAXVISIBLE-1]) && (result==true)) // don't let it overflo'
+ visptr++;
+ }
+ }
+
+
+//
+// draw from back to front
+//
+ numvisible = visptr-savedptr;
+ if (!numvisible)
+ return;
+ SortVisibleList( numvisible, savedptr );
+ for (i = 0; i<numvisible; i++)
+ {
+ //
+ // draw farthest
+ //
+ if (sortedvislist[i]->shapenum & 0x1000)
+ sortedvislist[i]->shapenum=animwalls[sortedvislist[i]->shapenum&0x3ff].texture;
+ sortedvislist[i]->altshapenum=0;
+ InterpolateWall (sortedvislist[i]);
+ }
+ visptr=savedptr;
+}
+
+/*
+====================
+=
+= WallRefresh
+=
+====================
+*/
+
+void WallRefresh (void)
+{
+ volatile int dtime;
+ int mag;
+ int yzangle;
+
+ whereami=16;
+ firstcoloffset=(firstcoloffset+(tics<<8))&65535;
+
+ dtime=GetFastTics();
+ if (missobj)
+ {
+ viewangle=missobj->angle;
+ viewx=missobj->x-costable[viewangle];
+ viewy=missobj->y+sintable[viewangle];
+ pheight = missobj->z + 32;
+ nonbobpheight=pheight;
+ spotvis[missobj->tilex][missobj->tiley]=1;
+ yzangle=missobj->yzangle;
+ }
+ else
+ {
+ if (player->flags&FL_SHROOMS)
+ {
+ viewangle = (player->angle + FixedMulShift(FINEANGLES,sintable[(GetTicCount()<<5)&(FINEANGLES-1)],(16+4)))&(FINEANGLES-1);
+ ChangeFocalWidth(FixedMulShift(40,sintable[(GetTicCount()<<5)&(FINEANGLES-1)],16));
+ }
+ else
+ viewangle = player->angle;
+ if ((viewangle<0) && (viewangle>=FINEANGLES))
+ Error ("View angle out of range = %d\n",viewangle);
+ viewx = player->x;
+ viewy = player->y;
+ pheight = player->z + locplayerstate->playerheight + locplayerstate->heightoffset;
+ nonbobpheight=pheight;
+ if (
+ (
+ (player->z == nominalheight) ||
+ (IsPlatform(player->tilex,player->tiley)) ||
+ (DiskAt(player->tilex,player->tiley))
+ ) &&
+ (!(player->flags & FL_DOGMODE)) &&
+ (BobbinOn==true) &&
+ (GamePaused==false)
+ )
+ {
+ int mag;
+
+ mag=(player->speed>MAXBOB ? MAXBOB : player->speed);
+
+ pheight+=FixedMulShift(mag,sintable[(GetTicCount()<<7)&2047],28);
+
+ weaponbobx=FixedMulShift(mag,costable[((GetTicCount()<<5))&(FINEANGLES-1)],27);
+ weaponboby=FixedMulShift(mag,sintable[((GetTicCount()<<5))&((FINEANGLES/2)-1)],26);
+ }
+ else
+ {
+ weaponbobx=0;
+ weaponboby=0;
+ }
+ yzangle=player->yzangle;
+ spotvis[player->tilex][player->tiley]=1;
+ }
+
+ if (yzangle > ANG180)
+ pheight -= (sintable[yzangle&2047] >> 14);
+ else
+ pheight += (sintable[yzangle&2047] >> 14);
+
+ viewx -= (FixedMul(sintable[yzangle&2047],costable[viewangle&2047])>>1);
+ viewy += (FixedMul(sintable[yzangle&2047],sintable[viewangle&2047])>>1);
+
+// Set YZ angle
+
+ centery=viewheight>>1;
+
+ if (yzangle>ANG180)
+ centery-=FixedMul(FINEANGLES-yzangle,yzangleconverter);
+ else
+ centery+=FixedMul(yzangle,yzangleconverter);
+
+ centeryfrac=(centery<<16);
+
+ if (pheight < 1)
+ pheight = 1;
+ else if (pheight > maxheight+30)
+ pheight = maxheight+30;
+
+ if (nonbobpheight < 1)
+ nonbobpheight = 1;
+ else if (nonbobpheight > maxheight+30)
+ nonbobpheight = maxheight+30;
+
+ // Set light level of touchplates etc.
+
+ mag=7+((3-gamestate.difficulty)<<2);
+
+ transparentlevel=FixedMul(mag,sintable[(GetTicCount()<<5)&(FINEANGLES-1)])+mag;
+
+ viewsin = sintable[viewangle];
+ viewcos = costable[viewangle];
+ c_startx=(scale*viewcos)-(centerx*viewsin);
+ c_starty=(-scale*viewsin)-(centerx*viewcos);
+ Refresh ();
+ UpdateClientControls();
+ TransformPushWalls();
+ TransformDoors();
+ UpdateClientControls();
+ DrawWalls();
+ UpdateClientControls();
+ walltime=GetFastTics()-dtime;
+
+}
+
+
+/*
+====================
+=
+= GetRainBoundingBox
+=
+====================
+*/
+
+void GetRainBoundingBox (int * xmin, int * xmax, int * ymin, int * ymax)
+{
+ wallcast_t * post;
+ int x,y;
+
+ // zero out all boundaries by default
+
+ *xmax=0;
+ *ymax=0;
+ *xmin=127<<16;
+ *ymin=127<<16;
+
+ // check player's x and y
+
+ if (viewx<(*xmin))
+ (*xmin)=viewx;
+ else if (viewx>(*xmax))
+ (*xmax)=viewx;
+
+ if (viewy<(*ymin))
+ (*ymin)=viewy;
+ else if (viewy>(*ymax))
+ (*ymax)=viewy;
+
+ for (post=&posts[0]; post<&posts[viewwidth]; post+=(viewwidth>>2))
+ {
+ x=(post->offset>>7)<<16;
+ y=(post->offset&0x7f)<<16;
+
+ if (x<(*xmin))
+ (*xmin)=x;
+ else if (x>(*xmax))
+ (*xmax)=x;
+
+ if (y<(*ymin))
+ (*ymin)=y;
+ else if (y>(*ymax))
+ (*ymax)=y;
+ }
+}
+
+/*
+========================
+=
+= InterpolateWall
+=
+========================
+*/
+
+void InterpolateWall (visobj_t * plane)
+{
+ int d1,d2;
+ int top;
+ int topinc;
+ int bot;
+ int botinc;
+ int i;
+ int texture;
+ int dh;
+ int dx;
+ int height;
+ byte * buf;
+
+ whereami=17;
+ dx=(plane->x2-plane->x1+1);
+ if (plane->h1<=0 || plane->h2<=0 || dx==0)
+ return;
+ d1=(1<<(16+HEIGHTFRACTION)) / plane->h1;
+ d2=(1<<(16+HEIGHTFRACTION)) / plane->h2;
+ dh=(((plane->h2-plane->h1)<<DHEIGHTFRACTION)+(1<<(DHEIGHTFRACTION-1)))/dx;
+ top=0;
+ topinc=FixedMulShift(d1,plane->textureend-plane->texturestart,4);
+ bot=d2*dx;
+ botinc=d1-d2;
+ height=plane->h1<<DHEIGHTFRACTION;
+ buf=(byte *)bufferofs;
+ if (plane->x1>=viewwidth)
+ return;
+ for (i=plane->x1; i<=plane->x2; i++)
+ {
+ if ((i>=0 && i<viewwidth)&&(posts[i].wallheight<=(height>>DHEIGHTFRACTION)))
+ {
+ if (bot)
+ {
+ texture=((top/bot)+(plane->texturestart>>4))&0xfc0;
+ posts[i].texture=texture<<4;
+ posts[i].lump=plane->shapenum;
+ posts[i].alttile=plane->altshapenum;
+ posts[i].posttype=plane->viewx;
+ posts[i].offset=plane->shapesize;
+ posts[i].wallheight=height>>DHEIGHTFRACTION;
+ }
+ }
+ top+=topinc;
+ bot+=botinc;
+ height+=dh;
+ }
+}
+
+
+/*
+========================
+=
+= InterpolateDoor
+=
+========================
+*/
+
+void InterpolateDoor (visobj_t * plane)
+{
+ int d1,d2;
+ int top;
+ int topinc;
+ int bot;
+ int botinc;
+ int i;
+ int texture;
+ int dh;
+ int dx;
+ int height;
+ int bottomscreen;
+ byte * shape;
+ byte * shape2;
+ byte * buf;
+ patch_t *p;
+ int pl;
+
+ whereami=18;
+ dx=(plane->x2-plane->x1+1);
+ if (plane->h1<=0 || plane->h2<=0 || dx==0)
+ return;
+ shape=W_CacheLumpNum(plane->shapenum,PU_CACHE, Cvt_patch_t, 1);
+ shape2=W_CacheLumpNum(plane->altshapenum,PU_CACHE, Cvt_patch_t, 1);
+ p=(patch_t *)shape;
+ d1=(1<<(16+HEIGHTFRACTION)) / plane->h1;
+ d2=(1<<(16+HEIGHTFRACTION)) / plane->h2;
+ dh=(((plane->h2-plane->h1)<<DHEIGHTFRACTION)+(1<<(DHEIGHTFRACTION-1)))/dx;
+ topinc=FixedMulShift(d1,plane->textureend-plane->texturestart,4);
+ botinc=d1-d2;
+ if (plane->x1>=viewwidth)
+ return;
+#ifdef DOS
+ for (pl=0; pl<4; pl++)
+#endif
+ {
+#ifdef DOS
+ top=topinc*pl;
+ bot=(d2*dx)+(pl*botinc);
+ height=(plane->h1<<DHEIGHTFRACTION)+(dh*pl);
+ buf=(byte *)bufferofs+((pl+plane->x1)>>2);
+ VGAWRITEMAP((plane->x1+pl)&3);
+
+ for (i=plane->x1+pl; i<=plane->x2; i+=4,buf++)
+#else
+ top=0;
+ bot=(d2*dx);
+ height=(plane->h1<<DHEIGHTFRACTION);
+ buf=(byte *)bufferofs+(plane->x1);
+
+ for (i=plane->x1; i<=plane->x2; i++,buf++)
+#endif
+ {
+ if ((i>=0 && i<viewwidth) && (bot!=0) && (posts[i].wallheight<=(height>>DHEIGHTFRACTION)) )
+ {
+ dc_invscale=height>>(HEIGHTFRACTION+DHEIGHTFRACTION-10);
+ dc_iscale = 0xffffffffu/(unsigned)dc_invscale;
+ dc_texturemid=((pheight-nominalheight+p->topoffset)<<SFRACBITS)+(SFRACUNIT>>1);
+ sprtopoffset=centeryfrac - FixedMul(dc_texturemid,dc_invscale);
+
+ texture=((top/bot)+(plane->texturestart>>4))>>6;
+ SetLightLevel(height>>DHEIGHTFRACTION);
+ ScaleMaskedPost (p->collumnofs[texture]+shape,buf);
+
+ if (levelheight>1)
+ {
+ sprtopoffset-=(dc_invscale<<6)*(levelheight-1);
+ bottomscreen =sprtopoffset + (dc_invscale*nominalheight);
+ dc_yl = (sprtopoffset+SFRACUNIT-1)>>SFRACBITS;
+ dc_yh = ((bottomscreen-1)>>SFRACBITS)+1;
+ if (dc_yl >= viewheight)
+ continue;
+ else if (dc_yl < 0)
+ dc_yl = 0;
+ if (dc_yh > viewheight)
+ dc_yh = viewheight;
+
+ dc_source=shape2+((texture<<6)&0xfc0);
+ R_DrawWallColumn (buf);
+ }
+ }
+
+#ifdef DOS
+ top+=topinc<<2;
+ bot+=botinc<<2;
+ height+=dh<<2;
+#else
+ top+=topinc;
+ bot+=botinc;
+ height+=dh;
+#endif
+ }
+ }
+}
+
+
+/*
+========================
+=
+= InterpolateMaskedWall
+=
+========================
+*/
+
+void InterpolateMaskedWall (visobj_t * plane)
+{
+ int d1,d2;
+ int top;
+ int topinc;
+ int bot;
+ int botinc;
+ int i;
+ int j;
+ int texture;
+ int dh;
+ int dx;
+ int height;
+ byte * shape;
+ byte * shape2;
+ byte * shape3;
+ byte * buf;
+ transpatch_t *p;
+ patch_t *p2;
+ patch_t *p3;
+ int pl;
+ boolean drawbottom,drawmiddle,drawtop;
+ int topoffset;
+
+ whereami=19;
+ dx=(plane->x2-plane->x1+1);
+ if (plane->h1<=0 || plane->h2<=0 || dx==0)
+ return;
+ if (plane->altshapenum>=0)
+ {
+ drawmiddle=true;
+ shape2=W_CacheLumpNum(plane->altshapenum,PU_CACHE, Cvt_patch_t, 1);
+ p2=(patch_t *)shape2;
+ topoffset=p2->topoffset;
+ }
+ else
+ {
+ drawmiddle=false;
+ }
+ if (plane->viewx>=0)
+ {
+ drawtop=true;
+ shape3=W_CacheLumpNum(plane->viewx,PU_CACHE, Cvt_patch_t, 1);
+ p3=(patch_t *)shape3;
+ topoffset=p3->topoffset;
+ }
+ else
+ {
+ drawtop=false;
+ }
+ if (plane->shapenum>=0)
+ {
+ drawbottom=true;
+ shape=W_CacheLumpNum(plane->shapenum,PU_CACHE, Cvt_transpatch_t, 1);
+ p = (transpatch_t *)shape;
+ topoffset=p->topoffset;
+ }
+ else
+ {
+ drawbottom=false;
+ }
+
+ d1=(1<<(16+HEIGHTFRACTION)) / plane->h1;
+ d2=(1<<(16+HEIGHTFRACTION)) / plane->h2;
+ dh=(((plane->h2-plane->h1)<<DHEIGHTFRACTION)+(1<<(DHEIGHTFRACTION-1)))/dx;
+ topinc=FixedMulShift(d1,plane->textureend-plane->texturestart,4);
+ botinc=d1-d2;
+ if (plane->x1>=viewwidth)
+ return;
+#ifdef DOS
+ for (pl=0; pl<4; pl++)
+#endif
+ {
+#ifdef DOS
+ int planenum;
+
+ top=topinc*pl;
+ bot=(d2*dx)+(pl*botinc);
+ height=(plane->h1<<DHEIGHTFRACTION)+(dh*pl);
+ buf=(byte *)bufferofs+((pl+plane->x1)>>2);
+ planenum=((plane->x1+pl)&3);
+ VGAWRITEMAP(planenum);
+ VGAREADMAP(planenum);
+ for (i=plane->x1+pl; i<=plane->x2; i+=4,buf++)
+#else
+ top=0;
+ bot=(d2*dx);
+ height=(plane->h1<<DHEIGHTFRACTION);
+ buf=(byte *)bufferofs+(plane->x1);
+ for (i=plane->x1; i<=plane->x2; i++,buf++)
+#endif
+ {
+ if ((i>=0 && i<viewwidth) && (bot!=0) && (posts[i].wallheight<=(height>>DHEIGHTFRACTION)) )
+ {
+ dc_invscale=height>>(HEIGHTFRACTION+DHEIGHTFRACTION-10);
+ dc_iscale = 0xffffffffu/(unsigned)dc_invscale;
+ dc_texturemid=((pheight-nominalheight+topoffset)<<SFRACBITS)+(SFRACUNIT>>1);
+ sprtopoffset=centeryfrac - FixedMul(dc_texturemid,dc_invscale);
+
+ texture=((top/bot)+(plane->texturestart>>4))>>6;
+ SetLightLevel(height>>DHEIGHTFRACTION);
+ if (drawbottom==true)
+ ScaleTransparentPost (p->collumnofs[texture]+shape,buf,(p->translevel+8));
+ for (j=0; j<levelheight-2; j++)
+ {
+ sprtopoffset-=(dc_invscale<<6);
+ dc_texturemid+=(1<<22);
+ if (drawmiddle==true)
+ ScaleMaskedPost (p2->collumnofs[texture]+shape2,buf);
+ }
+ if (levelheight>1)
+ {
+ sprtopoffset-=(dc_invscale<<6);
+ dc_texturemid+=(1<<22);
+ if (drawtop==true)
+ ScaleMaskedPost (p3->collumnofs[texture]+shape3,buf);
+ }
+ }
+#ifdef DOS
+ top+=topinc<<2;
+ bot+=botinc<<2;
+ height+=dh<<2;
+#else
+ top+=topinc;
+ bot+=botinc;
+ height+=dh;
+#endif
+ }
+ }
+}
+
+/*
+========================
+=
+= DrawPlayerLocation
+=
+========================
+*/
+#define PLX (320-24)
+#define PLY 16
+void DrawPlayerLocation ( void )
+{
+ int i;
+ char buf[30];
+
+ CurrentFont=tinyfont;
+
+ whereami=20;
+ VGAMAPMASK(15);
+ for (i=0; i<18; i++)
+#ifdef DOS
+ memset((byte *)bufferofs+(ylookup[i+PLY])+(PLX>>2),0,6);
+#else
+ memset((byte *)bufferofs+(ylookup[i+PLY])+PLX,0,6);
+#endif
+ px=PLX;
+ py=PLY;
+ VW_DrawPropString(strupr(itoa(player->x,&buf[0],16)));
+ px=PLX;
+ py=PLY+6;
+ VW_DrawPropString(strupr(itoa(player->y,&buf[0],16)));
+ px=PLX;
+ py=PLY+12;
+ VW_DrawPropString(strupr(itoa(player->angle,&buf[0],16)));
+}
+
+
+
+/*
+========================
+=
+= ThreeDRefresh
+=
+========================
+*/
+
+
+int playerview=0;
+void ThreeDRefresh (void)
+{
+ objtype * tempptr;
+
+ whereami=21;
+ tempptr=player;
+#if (DEVELOPMENT == 1)
+ if (Keyboard[sc_9])
+ {
+ while (Keyboard[sc_9])
+ {
+ IN_UpdateKeyboard();
+ }
+ playerview++;
+ if (playerview>numplayers)
+ playerview=1;
+ }
+ if (playerview!=0)
+ {
+ player=PLAYER[playerview-1];
+ }
+#endif
+
+//
+// Erase old messages
+//
+
+ RestoreMessageBackground();
+
+ bufferofs += screenofs;
+
+ RefreshClear();
+
+ UpdateClientControls ();
+
+//
+// follow the walls from there to the right, drawwing as we go
+//
+
+ visptr = &vislist[0];
+ WallRefresh ();
+
+ UpdateClientControls ();
+
+ if (fandc)
+ DrawPlanes();
+
+ UpdateClientControls ();
+
+//
+// draw all the scaled images
+//
+ DrawScaleds(); // draw scaled stuff
+
+ UpdateClientControls ();
+
+ if (!missobj)
+ {
+ if (locplayerstate->NETCAPTURED && (locplayerstate->NETCAPTURED != -2))
+ {
+ int value;
+
+ if (locplayerstate->NETCAPTURED < 0)
+ value = -locplayerstate->NETCAPTURED;
+ else
+ value = locplayerstate->NETCAPTURED;
+ DrawScreenSizedSprite(netlump+value-1);
+ }
+ DrawPlayerWeapon (); // draw player's hand'
+
+ if (SCREENEYE)
+ DrawScreenSprite(SCREENEYE->targettilex,SCREENEYE->targettiley,SCREENEYE->state->condition + GIBEYE1 + shapestart);
+ UpdateClientControls ();
+
+ if (player->flags&FL_GASMASK)
+ DrawScreenSizedSprite(gmasklump);
+
+
+ if ( SHOW_PLAYER_STATS() )
+ {
+ DrawStats ();
+ }
+
+ DoBorderShifts ();
+
+ UpdateClientControls ();
+ }
+
+ bufferofs -= screenofs;
+ DrawMessages();
+ bufferofs += screenofs;
+
+ if ( ((GamePaused==true) && (!Keyboard[sc_LShift])) ||
+ (controlupdatestarted==0)
+ )
+ DrawPause ();
+
+//
+// show screen and time last cycle
+//
+ if ((fizzlein==true) && (modemgame==false))
+ {
+ if (newlevel==true)
+ ShutdownClientControls();
+ bufferofs-=screenofs;
+ DrawPlayScreen (true);
+ RotateBuffer(0,FINEANGLES,FINEANGLES*8,FINEANGLES,(VBLCOUNTER*3)/4);
+ bufferofs+=screenofs;
+ fizzlein = false;
+ StartupClientControls();
+ }
+
+ bufferofs -= screenofs;
+
+ UpdateClientControls ();
+
+ if (HUD == true)
+ DrawPlayerLocation();
+
+ FlipPage();
+ gamestate.frame++;
+
+ player=tempptr;
+}
+
+
+//******************************************************************************
+//
+// FlipPage
+//
+//******************************************************************************
+
+void FlipPage ( void )
+{
+#ifdef DOS
+ unsigned displaytemp;
+
+ whereami=22;
+ displayofs = bufferofs;
+
+ displaytemp = displayofs;
+ if ( ( SHAKETICS != 0xFFFF ) && ( !inmenu ) && ( !GamePaused ) &&
+ ( !fizzlein ) )
+ {
+ ScreenShake ();
+ }
+
+
+// _disable();
+ OUTP(CRTC_INDEX,CRTC_STARTHIGH);
+ OUTP(CRTC_DATA,((displayofs&0x0000ffff)>>8));
+
+
+ if (SHAKETICS != 0xFFFF)
+ {
+ if (SHAKETICS > 0)
+ {
+ OUTP (CRTC_INDEX, CRTC_STARTLOW);
+ OUTP (CRTC_DATA, (displayofs&0x000000FF));
+ displayofs = displaytemp;
+ }
+ else
+ {
+ displayofs = displaytemp;
+ OUTP(CRTC_INDEX,CRTC_STARTHIGH);
+ OUTP(CRTC_DATA,((displayofs&0x0000ffff)>>8));
+ OUTP (CRTC_INDEX, CRTC_STARTLOW);
+ OUTP (CRTC_DATA, (displayofs&0x000000FF));
+ SHAKETICS = 0xFFFF;
+ }
+ }
+// _enable();
+
+ bufferofs += screensize;
+ if (bufferofs > page3start)
+ bufferofs = page1start;
+#else
+
+ whereami=22;
+
+ if ( ( SHAKETICS != 0xFFFF ) && ( !inmenu ) && ( !GamePaused ) &&
+ ( !fizzlein ) )
+ {
+ ScreenShake ();
+ }
+
+ /* TODO some shake thing */
+
+ /* just call the one in modexlib.c */
+ XFlipPage();
+
+#endif
+}
+
+
+//******************************************************************************
+//
+// TurnShakeOff
+//
+//******************************************************************************
+void TurnShakeOff
+(
+ void
+)
+
+{
+// _disable();
+ OUTP (CRTC_INDEX, CRTC_STARTHIGH );
+ OUTP (CRTC_DATA, ( ( displayofs & 0x0000ffff ) >> 8 ) );
+ OUTP (CRTC_INDEX, CRTC_STARTLOW);
+ OUTP (CRTC_DATA, (displayofs&0x000000FF));
+// _enable();
+ SHAKETICS = 0xFFFF;
+}
+
+//******************************************************************************
+//
+// DrawScaledScreen
+// draw sreen after reentering fro restore game
+//******************************************************************************
+
+void DrawScaledScreen(int x, int y, int step, byte * src)
+{
+ int xfrac;
+ int yfrac;
+// int plane;
+ int i,j;
+ byte * p;
+ byte * buf;
+ int xsize;
+ int ysize;
+
+ xsize=(iGLOBAL_SCREENWIDTH<<16)/step;
+ if (xsize>iGLOBAL_SCREENWIDTH) xsize=iGLOBAL_SCREENWIDTH;
+ ysize=(iGLOBAL_SCREENHEIGHT<<16)/step;
+ if (ysize>iGLOBAL_SCREENHEIGHT) ysize=iGLOBAL_SCREENHEIGHT;
+
+#ifdef DOS
+ for (plane=x; plane<x+4; plane++)
+#endif
+ {
+ yfrac=0;
+#ifdef DOS
+ VGAWRITEMAP(plane&3);
+#endif
+ for (j=y; j<y+ysize; j++)
+ {
+ p=src+(iGLOBAL_SCREENWIDTH*(yfrac>>16));
+#ifdef DOS
+ buf=(byte *)bufferofs+ylookup[j]+(plane>>2);
+#else
+ buf=(byte *)bufferofs+ylookup[j]+x;
+#endif
+#ifdef DOS
+ xfrac=(plane-x)*step;
+#else
+ xfrac=0;
+#endif
+ yfrac+=step;
+#ifdef DOS
+ for (i=plane; i<x+xsize; i+=4)
+#else
+ for (i=x; i<x+xsize; i++)
+#endif
+ {
+ *buf=*(p+(xfrac>>16));
+ buf++;
+#ifdef DOS
+ xfrac+=(step<<2);
+#else
+ xfrac+=step;
+#endif
+ }
+ }
+ }
+}
+
+
+//******************************************************************************
+//
+// DoLoadGameSequence
+//
+//******************************************************************************
+
+void DoLoadGameSequence ( void )
+{
+ int x;
+ int y;
+ int dx;
+ int dy;
+ int s;
+ int ds;
+ int time;
+ int i;
+ byte * destscreen;
+ pic_t *shape;//bna++
+
+
+
+
+
+ fizzlein=false;
+ x=(18+SaveGamePicX)<<16;
+ y=(30+SaveGamePicY)<<16;
+ time=VBLCOUNTER;
+ s=0x2000000;
+ dx=(-x)/time;
+ dy=(-y)/time;
+ ds=-((s-0x1000000)/time);
+
+ destscreen=SafeMalloc(64000*8);//bna fixme
+
+ SetupScreen(false);
+ ThreeDRefresh();
+
+ FlipPage();
+ FlipPage();
+
+ VL_CopyPlanarPageToMemory ( (byte *)bufferofs, destscreen );
+ VL_CopyDisplayToHidden ();
+
+ CalcTics();
+ for (i=0; i<time; i+=tics)
+ {
+ CalcTics();
+ DrawScaledScreen((x>>16),(y>>16),(s>>8),destscreen);
+ FlipPage();
+ x+=(dx*tics);
+ if (x<0) x=0;
+ y+=(dy*tics);
+ if (y<0) y=0;
+ s+=(ds*tics);
+ }
+
+ DrawScaledScreen(0,0,0x10000,destscreen);
+ FlipPage();
+ VL_CopyDisplayToHidden ();
+ SafeFree(destscreen);
+ CalcTics();
+ CalcTics();
+ //bna++ section
+ shape = ( pic_t * )W_CacheLumpName( "backtile", PU_CACHE, Cvt_pic_t, 1 );
+ DrawTiledRegion( 0, 16, iGLOBAL_SCREENWIDTH, iGLOBAL_SCREENHEIGHT - 32, 0, 16, shape );//bna++
+ DrawPlayScreen(false);
+ DisableScreenStretch();
+ SHAKETICS = 0xFFFF;
+ //bna section end
+}
+
+//******************************************************************************
+//
+// StartupRotateBuffer
+//
+//******************************************************************************
+byte * RotatedImage;
+boolean RotateBufferStarted = false;
+void StartupRotateBuffer ( int masked)
+{
+ int k;////zxcv
+ int a,b;
+
+// int Xres = 320;//org
+// int Yres = 200;//org
+ int Xres = iGLOBAL_SCREENWIDTH;//bna val 800
+ int Yres = iGLOBAL_SCREENHEIGHT;//bna val 600
+
+
+ iG_masked = masked;
+
+ if (RotateBufferStarted == true)
+ return;
+
+ RotateBufferStarted = true;
+
+ // RotatedImage=SafeMalloc(131072);org
+ //RotatedImage=SafeMalloc(131072*8);
+ if (iGLOBAL_SCREENWIDTH == 320) {
+ RotatedImage=SafeMalloc(131072);
+ } else if (iGLOBAL_SCREENWIDTH == 640) {
+ RotatedImage=SafeMalloc(131072*4);
+ } else if (iGLOBAL_SCREENWIDTH == 800) {
+ RotatedImage=SafeMalloc(131072*8);
+ }
+//SetupScreen(false);//used these 2 to test screen size
+//VW_UpdateScreen ();
+ if (masked==0) {
+ if (iGLOBAL_SCREENWIDTH == 320) {
+ memset(RotatedImage,0,131072);
+ } else if (iGLOBAL_SCREENWIDTH == 640) {
+ memset(RotatedImage,0,131072*4);
+ } else if (iGLOBAL_SCREENWIDTH == 800) {
+ //memset(RotatedImage,0,131072);//org
+ memset(RotatedImage,0,131072*8);
+ }
+ } else {
+ if (iGLOBAL_SCREENWIDTH == 320) {
+ memset(RotatedImage,0xff,131072);
+ } else if (iGLOBAL_SCREENWIDTH == 640) {
+ memset(RotatedImage,0xff,131072*4);
+ } else if (iGLOBAL_SCREENWIDTH == 800) {
+ memset(RotatedImage,0xff,131072*8);
+ }
+ }
+ //memset(RotatedImage,0xff,131072);//org
+ //memset(RotatedImage,0xff,131072*8);
+
+ if ((masked == false)&&(iGLOBAL_SCREENWIDTH == 800)) {
+ DisableScreenStretch();
+ // SetTextMode ( );
+
+ k=(28*512);//14336;
+ //k=((0+28)<<10);//28672
+ for (a=0; a<iGLOBAL_SCREENHEIGHT; a++) {
+ for (b=0; b<iGLOBAL_SCREENWIDTH; b++) {
+ //*(RotatedImage+99+((a+28)<<9)+b) = *((byte *)bufferofs+(a*linewidth)+b);
+ // 99 is some offset value
+ k = ((a+28)<<10);
+ *(RotatedImage+(k)+b) = *((byte *)bufferofs+(a*linewidth)+b);
+ //*(RotatedImage+b) = *((byte *)bufferofs+(a*linewidth)+b);
+ }
+ //k+=512*2;
+ }
+ } else if ((masked == false)&&(iGLOBAL_SCREENWIDTH == 640)) {
+ DisableScreenStretch();
+ k=(28*512);//14336;
+ for (a=0; a<iGLOBAL_SCREENHEIGHT; a++) {
+ for (b=0; b<iGLOBAL_SCREENWIDTH; b++) {
+ k = ((a+28)<<10);
+ *(RotatedImage+(k)+b) = *((byte *)bufferofs+(a*linewidth)+b);
+ }
+ }
+
+ } else if ((masked == true)||(iGLOBAL_SCREENWIDTH == 320)) {
+ for (a=0; a<200; a++) {
+ for (b=0; b<320; b++)
+ *(RotatedImage+99+((a+28)<<9)+b)=*((byte *)bufferofs+(a*linewidth)+b);
+ }
+ }
+
+}
+/* copier liner af 1024 bredde
+a=0=14436 a=1=14848 a=2=15360 a=3=15872 -> 512 i difference
+*(RotatedImage+(512)+0) = bufferofs+(0*800)+0);
+*(RotatedImage+(512)+100) = bufferofs+(100*800)+0);
+*/
+
+//******************************************************************************
+//
+// ShutdownRotateBuffer
+//
+//******************************************************************************
+
+void ShutdownRotateBuffer ( void )
+{
+ if (RotateBufferStarted == false)
+ return;
+
+ RotateBufferStarted = false;
+ SafeFree(RotatedImage);
+}
+
+//******************************************************************************
+//
+// ScaleAndRotateBuffer
+//
+//******************************************************************************
+
+void ScaleAndRotateBuffer (int startangle, int endangle, int startscale, int endscale, int time)
+{
+ int anglestep;
+ int scalestep;
+ int angle;
+ int scale;
+ int i;
+
+
+//bna section
+// int Xh = 160;//org
+// int Yh = 100;//org
+
+ int Xh = iGLOBAL_SCREENWIDTH/2;
+ int Yh = iGLOBAL_SCREENHEIGHT/2;
+// Xh = 259;
+// Yh = 109;
+
+ time = time;
+////zxcv
+ DisableScreenStretch();//bna++
+
+
+ anglestep=((endangle-startangle)<<16)/time;
+ scalestep=((endscale-startscale)<<6)/time;
+
+ angle=(startangle<<16);
+
+ scale=(startscale<<6);
+
+ CalcTics();
+ CalcTics();
+ for (i=0; i<time; i+=tics)
+ { //zxcv
+ DrawRotatedScreen(Xh,Yh, (byte *)bufferofs,(angle>>16)&(FINEANGLES-1),scale>>6,0);
+ FlipPage();
+ scale+=(scalestep*tics);
+ angle+=(anglestep*tics);
+ CalcTics();
+ }
+
+ DrawRotatedScreen(Xh,Yh, (byte *)bufferofs,endangle&(FINEANGLES-1),endscale,0);
+ FlipPage();
+ DrawRotatedScreen(Xh,Yh, (byte *)bufferofs,endangle&(FINEANGLES-1),endscale,0);
+ FlipPage();
+ DrawRotatedScreen(Xh,Yh, (byte *)bufferofs,endangle&(FINEANGLES-1),endscale,0);
+ CalcTics();
+ CalcTics();
+ //I_Delay (240);//bna++
+ //bna++ section
+ if ( playstate == ex_stillplaying ) {//bna++
+ pic_t *shape;
+ shape = ( pic_t * )W_CacheLumpName( "backtile", PU_CACHE, Cvt_pic_t, 1 );
+ DrawTiledRegion( 0, 16, iGLOBAL_SCREENWIDTH, iGLOBAL_SCREENHEIGHT - 32, 0, 16, shape );//bna++
+ DisableScreenStretch();//dont strech when we go BACK TO GAME
+ DrawPlayScreen(true);//repaint ammo and life stat
+ }
+}
+//bna section end
+
+
+
+//******************************************************************************
+//
+// RotateBuffer
+//
+//******************************************************************************
+
+void RotateBuffer (int startangle, int endangle, int startscale, int endscale, int time)
+{
+ int savetics;
+
+ //save off fastcounter
+
+ savetics=GetFastTics();
+
+ StartupRotateBuffer (0);
+
+ ScaleAndRotateBuffer (startangle, endangle, startscale, endscale, time);
+
+ ShutdownRotateBuffer ();
+
+ // restore fast counter
+ SetFastTics(savetics);
+}
+
+
+//******************************************************************************
+//
+// DrawRotatedScreen
+//
+//******************************************************************************
+
+void DrawRotatedScreen(int cx, int cy, byte *destscreen, int angle, int scale, int masked)
+{ //ZXCV
+ int c, s;
+ int xst, xct;
+ int y;
+
+ byte * screen;
+ //int Xres = 320;//old value
+ //int Yres = 200;//old val
+
+ int Xr = iGLOBAL_SCREENWIDTH;//640;
+ int Yr = (iGLOBAL_SCREENHEIGHT);//400; //bna aaaa fix
+
+// SetTextMode ( );
+ c = FixedMulShift(scale,costable[angle],11);
+ s = FixedMulShift(scale,sintable[angle],11);
+
+// c = c/2; //these values are to rotate degres or?
+// s = s/2;
+// xst & xct= start center values ;
+ if ((iGLOBAL_SCREENWIDTH == 320 )||(masked == true)) {
+ xst = (((-cx)*s)+(128<<16))-(cy*c);
+ xct = (((-cx)*c)+(256<<16)+(1<<18)-(1<<16))+(cy*s);
+ }
+ else if ((iGLOBAL_SCREENWIDTH == 640 )&&(masked == false)) {
+ xst = (((-cx)*s)+((268)<<16))-(cy*c);
+ xct = (((-cx)*c)+((317)<<16)+(1<<18)-(1<<16))+(cy*s);
+ }//y=268;x=317
+ else if ((iGLOBAL_SCREENWIDTH == 800 )&&(masked == false)) {
+ xst = (((-cx)*s)+((328)<<16))-(cy*c);
+ xct = (((-cx)*c)+((397)<<16)+(1<<18)-(1<<16))+(cy*s);
+ }//328 397
+
+ mr_xstep=s;
+ mr_ystep=c;
+
+
+ if ((iGLOBAL_SCREENWIDTH == 800)&&(masked==0)) {
+ screen=destscreen+iGLOBAL_SCREENWIDTH;//bna aaaa fix
+ } else {
+ screen=destscreen;
+ }
+
+ if (masked==0)
+ {
+ // paint hole 800x600 screen
+ {
+ mr_yfrac=xct;
+ mr_xfrac=xst;
+ VGAWRITEMAP(plane);
+ for (y=0; y<Yr; y++,mr_xfrac+=c,mr_yfrac-=s)
+ DrawRotRow(Xr,screen+ylookup[y],RotatedImage);
+ }
+ }
+ else
+ {
+ {
+ mr_yfrac=xct;
+ mr_xfrac=xst;
+ VGAWRITEMAP(plane);
+ for (y=0; y<Yr; y++,mr_xfrac+=c,mr_yfrac-=s)
+ DrawMaskedRotRow(Xr,screen+ylookup[y],RotatedImage);
+ }
+ }
+
+}
+
+
+//******************************************************************************
+//
+// DrawScaledPost
+//
+//******************************************************************************
+
+void DrawScaledPost ( int height, byte * src, int offset, int x)
+{
+ patch_t *p;
+
+ p=(patch_t *)src;
+ dc_invscale=(height<<16)/p->origsize;
+ dc_iscale=(p->origsize<<16)/height;
+ dc_texturemid=(((p->origsize>>1)+p->topoffset)<<SFRACBITS)+(SFRACUNIT>>1);
+ sprtopoffset=centeryfrac - FixedMul(dc_texturemid,dc_invscale);
+ shadingtable=colormap+(1<<12);
+ VGAWRITEMAP(x&3);
+#ifdef DOS
+ ScaleMaskedPost(((p->collumnofs[offset])+src), (byte *)bufferofs+(x>>2));
+#else
+ ScaleMaskedPost(((p->collumnofs[offset])+src), (byte *)bufferofs+x);
+#endif
+}
+
+
+
+void ApogeeTitle (void)
+{
+ byte pal[768];
+ int angle;
+ int scale;
+ int x,y;
+ int danglex;
+ int anglex;
+ int dy,dangle,dscale;
+ int time;
+
+ CalcTics();
+ CalcTics();
+ IN_ClearKeysDown();
+ viewwidth=320;
+ viewheight=200;
+ memcpy(&pal[0],W_CacheLumpName("ap_pal",PU_CACHE, CvtNull, 1),768);
+ shadingtable=colormap+(1<<12);
+ VL_NormalizePalette(&pal[0]);
+ SwitchPalette(&pal[0],35);
+// DrawWorld();
+// RotateBuffer(0,FINEANGLES*6,FINEANGLES*48,FINEANGLES,(VBLCOUNTER*2));
+// DoLaserShoot("apogee");
+// DoZIntro();
+
+ VL_ClearBuffer (bufferofs, 255);
+ DrawNormalSprite (0, 0, W_GetNumForName("ap_titl"));
+
+ StartupRotateBuffer (1);
+
+ //save off fastcounter
+
+#define APOGEEXANGLE 913
+#define APOGEEXMAG 180
+#define APOGEESTARTY 0
+#define APOGEEENDY 100
+
+#define APOGEESCALESTART (FINEANGLES<<4)
+#define APOGEESCALEEND (FINEANGLES)
+#define APOGEESONGTIME (124-1)
+
+ time = APOGEESONGTIME;
+
+ anglex=0;
+ danglex=(APOGEEXANGLE<<16)/time;
+
+ y=APOGEESTARTY<<16;
+ dy=((APOGEEENDY-APOGEESTARTY)<<16)/time;
+
+ dscale=((APOGEESCALEEND-APOGEESCALESTART)<<16)/time;
+ scale=APOGEESCALESTART<<16;
+
+ angle=0;
+ dangle=(FINEANGLES<<17)/time;
+
+ MU_StartSong(song_apogee);
+
+ CalcTics();
+
+ while (time>=0)
+ {
+ VL_DrawPostPic (W_GetNumForName("ap_wrld"));
+ IN_PumpEvents();
+
+ x=100+FixedMul(APOGEEXMAG,sintable[anglex>>16]);
+
+ DrawRotatedScreen(x,y>>16,(byte *)bufferofs,(angle>>16)&(FINEANGLES-1),scale>>16,1);
+ FlipPage();
+ CalcTics();
+ angle+=dangle*tics;
+ scale+=dscale*tics;
+ y+=dy*tics;
+ anglex+=danglex*tics;
+ time-=tics;
+ if ((LastScan) || IN_GetMouseButtons())
+ goto apogeeexit;
+ }
+ CalcTics();
+ CalcTics();
+ VL_DrawPostPic (W_GetNumForName("ap_wrld"));
+ DrawRotatedScreen(x,y>>16,(byte *)bufferofs,0,APOGEESCALEEND,1);
+ FlipPage();
+
+ while (MU_SongPlaying())
+ {
+ IN_PumpEvents();
+ if ((LastScan) || IN_GetMouseButtons())
+ goto apogeeexit;
+ }
+
+// I_Delay(65); //bna added
+apogeeexit:
+
+ VL_ClearBuffer (bufferofs, 0); //bna added
+ MenuFadeOut(); //bna added
+ VH_UpdateScreen (); //bna added
+ ShutdownRotateBuffer ();
+
+}
+
+#if (SHAREWARE==0)
+
+void DopefishTitle (void)
+{
+ int shapenum;
+ int height;
+
+ shapenum=W_GetNumForName("scthead1");
+ CalcTics();
+ CalcTics();
+ IN_ClearKeysDown();
+ MU_StartSong( song_secretmenu);
+ viewwidth=320;
+ viewheight=200;
+ SwitchPalette(origpal,35);
+ oldtime=GetTicCount();
+ FlipPage();
+ for (height=1; height<200; height+=(tics<<2))
+ {
+ DrawPositionedScaledSprite (160, 100, shapenum, height, 0);
+ FlipPage();
+ CalcTics();
+ if ((LastScan) || IN_GetMouseButtons())
+ break;
+ }
+ SD_Play ( SD_DOPEFISHSND );
+ oldtime=GetTicCount();
+ for (height=0; height<FINEANGLES<<1; height+=(tics<<5))
+ {
+ DrawPositionedScaledSprite (160+FixedMul(60,costable[height&(FINEANGLES-1)]), 100+FixedMul(60,sintable[height&(FINEANGLES-1)]), shapenum, 200, 0);
+ FlipPage();
+ VL_CopyPlanarPage ( (byte *) displayofs, (byte *) bufferofs );
+ CalcTics();
+ if ((LastScan) || IN_GetMouseButtons())
+ break;
+ }
+ SD_Play ( SD_DOPEFISHSND );
+ FlipPage();
+}
+
+#endif
+
+//******************************************************************************
+//
+// RotationFun
+//
+//******************************************************************************
+
+void RotationFun ( void )
+{
+ int angle;
+ int scale;
+ int x,y;
+ word buttons;
+
+ //save off fastcounter
+
+
+ angle=0;
+ scale=FINEANGLES;
+
+ StartupRotateBuffer (0);
+
+ CalcTics();
+ CalcTics();
+ while (!Keyboard[sc_Escape])
+ {
+ IN_UpdateKeyboard ();
+ DrawRotatedScreen(160,100,(byte *)bufferofs,angle,scale,0);
+ FlipPage();
+ CalcTics();
+ INL_GetMouseDelta(&x, &y);
+ buttons=IN_GetMouseButtons ();
+ angle=(angle-x)&(FINEANGLES-1);
+ if (buttons & (1 << 0))
+ {
+ if (scale>0)
+ scale-=30;
+ }
+ else if (buttons & (1 << 1))
+ {
+ scale+=30;
+ }
+ }
+ CalcTics();
+ CalcTics();
+ Keyboard[sc_Escape]=0;
+
+ ShutdownRotateBuffer ();
+}
+
+boolean ScreenSaverStarted=false;
+screensaver_t * ScreenSaver;
+#define PAUSETIME (70)
+
+//******************************************************************************
+//
+// SetupScreenSaverPhase
+//
+//******************************************************************************
+void SetupScreenSaverPhase ( void )
+{
+ if (ScreenSaverStarted==false)
+ return;
+
+ if (ScreenSaver->phase==0)
+ {
+ ScreenSaver->x=160;
+ ScreenSaver->y=100;
+ ScreenSaver->angle=0;
+ ScreenSaver->scale=FINEANGLES;
+ ScreenSaver->dangle=FINEANGLES/VBLCOUNTER;
+ ScreenSaver->dx=0;
+ ScreenSaver->dy=0;
+ ScreenSaver->dscale=((FINEANGLES<<2)-(FINEANGLES))/VBLCOUNTER;
+ ScreenSaver->time=VBLCOUNTER;
+ }
+ else if (ScreenSaver->phase==1)
+ {
+ ScreenSaver->x=160;
+ ScreenSaver->y=100;
+ ScreenSaver->angle=0;
+ ScreenSaver->scale=FINEANGLES<<2;
+ ScreenSaver->dangle=FINEANGLES/VBLCOUNTER;
+ ScreenSaver->dx=RandomNumber("StartupScreen",0)>>5;
+ ScreenSaver->dy=RandomNumber("StartupScreen",0)>>5;
+ ScreenSaver->dscale=0;
+ ScreenSaver->time=-1;
+ }
+}
+
+//******************************************************************************
+//
+// StartupScreenSaver
+//
+//******************************************************************************
+void StartupScreenSaver ( void )
+{
+ if (ScreenSaverStarted==true)
+ return;
+
+ ScreenSaverStarted=true;
+
+ StartupRotateBuffer (0);
+
+ ScreenSaver=(screensaver_t *)SafeMalloc(sizeof(screensaver_t));
+ ScreenSaver->phase=0;
+ ScreenSaver->pausetime=PAUSETIME;
+ if (iGLOBAL_SCREENWIDTH == 320) {
+ ScreenSaver->pausex=120;
+ ScreenSaver->pausey=84;
+ } else if (iGLOBAL_SCREENWIDTH == 640) {
+ ScreenSaver->pausex=240;
+ ScreenSaver->pausey=201;
+ } else if (iGLOBAL_SCREENWIDTH == 800) {
+ ScreenSaver->pausex=300;
+ ScreenSaver->pausey=252;
+ }
+ ScreenSaver->pausex=120;
+ ScreenSaver->pausey=84;
+ SetupScreenSaverPhase();
+}
+
+//******************************************************************************
+//
+// ShutdownScreenSaver
+//
+//******************************************************************************
+void ShutdownScreenSaver ( void )
+{
+ if (ScreenSaverStarted==false)
+ return;
+
+ ScreenSaverStarted=false;
+
+ ShutdownRotateBuffer ();
+ SafeFree(ScreenSaver);
+ //bna section
+ StartupClientControls();
+
+}
+
+//******************************************************************************
+//
+// UpdateScreenSaver
+//
+//******************************************************************************
+
+#define SPINSIZE 40
+#define MAXSPEED 8
+void UpdateScreenSaver ( void )
+{
+ //EnableScreenStretch();
+ if (ScreenSaver->time!=-1)
+ {
+ ScreenSaver->time-=tics;
+ if (ScreenSaver->time<0)
+ {
+ ScreenSaver->phase++;
+ SetupScreenSaverPhase();
+ }
+ }
+ ScreenSaver->x+=ScreenSaver->dx*tics;
+ ScreenSaver->y+=ScreenSaver->dy*tics;
+ ScreenSaver->angle=(ScreenSaver->angle+(ScreenSaver->dangle*tics))&(FINEANGLES-1);
+ ScreenSaver->scale+=ScreenSaver->dscale*tics;
+ if (ScreenSaver->x<SPINSIZE)
+ {
+ ScreenSaver->x=SPINSIZE;
+ ScreenSaver->dx=abs(ScreenSaver->dx);
+ ScreenSaver->dy+=(RandomNumber("Rotate",0)>>6)-2;
+ }
+ else if (ScreenSaver->x>iGLOBAL_SCREENWIDTH-SPINSIZE)
+ {
+ ScreenSaver->x=iGLOBAL_SCREENWIDTH-SPINSIZE;
+ ScreenSaver->dx=-(abs(ScreenSaver->dx));
+ ScreenSaver->dy+=(RandomNumber("Rotate",0)>>6)-2;
+ }
+ if (ScreenSaver->y<SPINSIZE)
+ {
+ ScreenSaver->y=SPINSIZE;
+ ScreenSaver->dy=abs(ScreenSaver->dy);
+ ScreenSaver->dx+=(RandomNumber("Rotate",0)>>6)-2;
+ }
+ else if (ScreenSaver->y>iGLOBAL_SCREENHEIGHT-SPINSIZE)
+ {
+ ScreenSaver->y=iGLOBAL_SCREENHEIGHT-SPINSIZE;
+ ScreenSaver->dy=-(abs(ScreenSaver->dy));
+ ScreenSaver->dx+=(RandomNumber("Rotate",0)>>6)-2;
+ }
+
+ if (abs(ScreenSaver->dx)>MAXSPEED)
+ ScreenSaver->dx=SGN(ScreenSaver->dx)*MAXSPEED;
+
+ if (abs(ScreenSaver->dy)>MAXSPEED)
+ ScreenSaver->dy=SGN(ScreenSaver->dy)*MAXSPEED;
+
+ DrawRotatedScreen(ScreenSaver->x,ScreenSaver->y, (byte *)bufferofs,ScreenSaver->angle,ScreenSaver->scale,0);
+
+ ScreenSaver->pausetime-=tics;
+ if (ScreenSaver->pausetime<=0)
+ {
+ ScreenSaver->pausetime=PAUSETIME;
+ if (iGLOBAL_SCREENWIDTH == 320) {
+ ScreenSaver->pausex=RandomNumber ("pausex",0)%240;
+ ScreenSaver->pausey=RandomNumber ("pausey",0)%168;
+ } else if (iGLOBAL_SCREENWIDTH == 640) {
+ ScreenSaver->pausex=RandomNumber ("pausex",0)%480;
+ ScreenSaver->pausey=RandomNumber ("pausey",0)%403;
+ } else if (iGLOBAL_SCREENWIDTH == 800) {
+ ScreenSaver->pausex=RandomNumber ("pausex",0)%600;
+ ScreenSaver->pausey=RandomNumber ("pausey",0)%504;
+ }
+ }
+ DrawPauseXY (ScreenSaver->pausex, ScreenSaver->pausey);
+
+ FlipPage();
+}
+#if 0
+
+//******************************************************************************
+//
+// DoLaserShoot
+//
+//******************************************************************************
+void DoLaserShoot (char * name)
+{
+
+ int sourcex;
+ int lastx;
+ int sourceheight;
+ int destheight;
+ int sourcestep;
+ int xstep;
+ int hstep;
+ int midx;
+ int startx;
+ int dx;
+ int f;
+ int s;
+ int height;
+ int x;
+ int sx;
+ int size;
+ patch_t *p;
+ byte * shape;
+
+ DrawWorld();
+ midx=160;
+ shape=W_CacheLumpName(name,PU_CACHE);
+ p=(patch_t *)shape;
+ size=p->origsize;
+
+ startx=midx-(size>>1)-(p->leftoffset);
+
+ sourcex=0;
+ lastx=startx+p->width;
+ sourcestep=(320*65536)/p->width;
+ sourceheight=p->origsize<<3;
+ destheight=p->origsize;
+ CalcTics();
+ CalcTics();
+
+
+ for (x=startx; x<lastx; x+=tics,sourcex+=(sourcestep*tics))
+ {
+ for (f=startx; f<=x; f++)
+ DrawScaledPost(destheight,shape,f-startx,f);
+ height=sourceheight<<16;
+ if (x<=midx)
+ {
+ dx=x-(sourcex>>16);
+ xstep=1;
+ }
+ else
+ {
+ dx=(sourcex>>16)-x;
+ xstep=-1;
+ }
+ sx=sourcex>>16;
+ if (dx)
+ hstep=((-destheight+sourceheight)<<16)/dx;
+ else
+ hstep=0;
+ for (s=0; s<dx; s++,height-=hstep,sx+=xstep)
+ DrawScaledPost(height>>16,shape,x-startx,sx);
+ FlipPage();
+ CalcTics();
+ DrawWorld();
+ break;
+ }
+
+ // Write out one more time so that the rest of the screen is clear
+
+ for (f=startx; f<lastx; f++)
+ DrawScaledPost(destheight,shape,f-startx,f);
+ FlipPage();
+}
+
+//******************************************************************************
+//
+// DoIntro
+//
+//******************************************************************************
+
+#define MAXMAG (80)
+#define OSCTIME (5*VBLCOUNTER)
+#define OSCXSHIFT (4)
+#define OSCTSHIFT (4)
+
+void DoIntro (void)
+{
+ byte * shape;
+ byte * origshape;
+ int mag;
+ int currentmag;
+ int magstep;
+ int time;
+ int x;
+ int t;
+
+ shadingtable=colormap+(1<<12);
+
+ origshape=W_CacheLumpName("ap_wrld",PU_CACHE);
+
+ mag=MAXMAG<<16;
+ magstep = (MAXMAG<<16)/OSCTIME;
+ time = OSCTIME;
+ t=0;
+
+ CalcTics();
+
+ while (time>0)
+ {
+ int yoffset;
+ int ylow;
+ int yhigh;
+ int offset;
+ int postheight;
+ byte * src;
+
+ shape=origshape;
+ VL_ClearBuffer (bufferofs, 0);
+ currentmag=mag>>16;
+ for (x=0; x<320; x++,shape+=200)
+ {
+ VGAWRITEMAP(x&3);
+ src=shape;
+ offset=(t+(x<<OSCXSHIFT))&(FINEANGLES-1);
+ yoffset=FixedMul(currentmag,sintable[offset]);
+ ylow=yoffset;
+ if (ylow<0)
+ {
+ src-=ylow;
+ ylow=0;
+ }
+ if (ylow>199)
+ ylow=199;
+ yhigh=yoffset+200;
+ if (yhigh>199)
+ {
+ yhigh=199;
+ }
+ if (yhigh<0)
+ yhigh=0;
+ postheight=yhigh-ylow+1;
+ if (postheight>0)
+#ifdef DOS
+ DrawSkyPost((byte *)bufferofs + (x>>2) + ylookup[ylow],src,postheight);
+#else
+ DrawSkyPost((byte *)bufferofs + x + ylookup[ylow],src,postheight);
+#endif
+ }
+ FlipPage();
+ CalcTics();
+ mag -= (magstep * tics);
+ time -= tics;
+ t += (tics<<OSCTSHIFT);
+ if (mag<0) mag = 0;
+ }
+}
+
+
+//******************************************************************************
+//
+// DoZIntro
+//
+//******************************************************************************
+
+#define ZMAXMAG (199)
+#define ZOSCTIME (3*VBLCOUNTER)
+#define ZOSCXSHIFT (2)
+#define ZOSCXSTEP ( (FINEANGLES<<(ZOSCXSHIFT+16))/320 )
+#define ZOSCTSHIFT (2)
+
+void DoZIntro (void)
+{
+ byte * shape;
+ int mag;
+ int currentmag;
+ int magstep;
+ int time;
+ int x;
+ int t;
+
+ SetViewSize (MAXVIEWSIZES-1);
+
+ shadingtable=colormap+(1<<12);
+
+ shape=W_CacheLumpName("ap_wrld",PU_CACHE);
+
+ mag=ZMAXMAG<<16;
+ magstep = (ZMAXMAG<<16)/ZOSCTIME;
+ time = ZOSCTIME;
+ t=0;
+
+ CalcTics();
+
+
+ while (time>0)
+ {
+ int zoffset;
+ int hoffset;
+ int offset;
+ int srcoffset;
+ int bottomscreen;
+ int src;
+// int i;
+
+
+ VL_ClearBuffer (bufferofs, 0);
+ currentmag=mag>>16;
+
+ srcoffset=0;
+ for (x=0; x<320;)
+ {
+ VGAWRITEMAP(x&3);
+
+ offset=(t+(FixedMul(x,ZOSCXSTEP)))&(FINEANGLES-1);
+ zoffset=FixedMul(currentmag,sintable[offset]);
+// hoffset=FixedMulShift(currentmag,sintable[offset],17);
+ hoffset=0;
+ dc_texturemid=((100+hoffset)<<SFRACBITS)+(SFRACUNIT>>1);
+
+ dc_invscale=((200+zoffset)<<16)/200;
+ dc_iscale=0xffffffffu/(unsigned)dc_invscale;
+
+ srcoffset+=dc_invscale;
+ sprtopoffset=centeryfrac - FixedMul(dc_texturemid,dc_invscale);
+ bottomscreen = sprtopoffset + (dc_invscale*200);
+ dc_yl = (sprtopoffset+SFRACUNIT-1)>>SFRACBITS;
+ dc_yh = ((bottomscreen-1)>>SFRACBITS);
+ if (dc_yh >= viewheight)
+ dc_yh = viewheight-1;
+ if (dc_yl < 0)
+ dc_yl = 0;
+ if (dc_yl <= dc_yh)
+ {
+ src=srcoffset>>16;
+ if (src>319)
+ src=319;
+ if (src<0)
+ src=0;
+ dc_source=shape+(src * 200);
+// if (RandomNumber("hello",0)<128)
+#ifdef DOS
+ R_DrawColumn ((byte *)bufferofs+(x>>2));
+#else
+ R_DrawColumn ((byte *)bufferofs+x);
+#endif
+ }
+// srcoffset+=0x10000;
+ x++;
+ if ((LastScan) || IN_GetMouseButtons())
+ return;
+ }
+ FlipPage();
+ CalcTics();
+ mag -= (magstep * tics);
+// mag += FixedMulShift((magstep * tics),sintable[time&(FINEANGLES-1)],19);
+ time -= tics;
+ t += (tics<<ZOSCTSHIFT);
+ if (mag<0) mag = 0;
+ }
+}
+#endif
+
+
+
+// Old Stuff
+
+/*
+ int y1;
+ int y2;
+
+ if (post->alttile!=0)
+ {
+ ht=nominalheight;
+ src2=W_CacheLumpNum(1+post->alttile,PU_CACHE);
+// src2+=8;
+ }
+ else
+ {
+ ht=maxheight;
+ src2=src;
+ }
+ hp_srcstep=(64<<(16+HEIGHTFRACTION))/post->wallheight;
+ y1 = (((centery<<HFRACTION)-(post->wallheight*pheight)+(1<<(HFRACTION-1))));
+ y2 = (((post->wallheight*ht)+y1)>>HFRACTION);
+
+ if ((y1>>HFRACTION)>=viewheight)
+ {
+ post->ceilingclip=viewheight-1;
+ post->floorclip=viewheight-1;
+ return;
+ }
+ else if (y1<0)
+ {
+ hp_startfrac=FixedMulShift(-y1,hp_srcstep,HFRACTION);
+ y1=0;
+ post->ceilingclip=0;
+ }
+ else
+ {
+ hp_startfrac=FixedMulShift(255-(y1&0xff),hp_srcstep,HFRACTION);
+ y1>>=HFRACTION;
+ post->ceilingclip=y1;
+ }
+ if (y2<0)
+ {
+ post->floorclip=0;
+ post->ceilingclip=0;
+ }
+ else if (y2>viewheight)
+ {
+ DrawHeightPost(viewheight-y1, src2+((post->texture>>4)&0xfc0), buf+ylookup[y1]);
+ post->floorclip=viewheight-1;
+ }
+ else
+ {
+ DrawHeightPost(y2-y1, src2+((post->texture>>4)&0xfc0), buf+ylookup[y1]);
+ post->floorclip=y2-1;
+ }
+
+ if (ht==maxheight)
+ return;
+
+ y1 = (((centery<<HFRACTION)-(post->wallheight*(pheight-ht))+(1<<(HFRACTION-1))));
+ y2 = (((post->wallheight<<6)+y1)>>HFRACTION);
+
+ if ((y1>>HFRACTION)>=viewheight)
+ return;
+ else if (y1<0)
+ {
+ hp_startfrac=FixedMulShift(-y1,hp_srcstep,HFRACTION);
+ y1=0;
+ }
+ else
+ {
+ hp_startfrac=FixedMulShift(255-(y1&0xff),hp_srcstep,HFRACTION);
+ y1>>=HFRACTION;
+ }
+ if (y2<0)
+ return;
+ else if (y2>viewheight)
+ {
+ DrawHeightPost(viewheight-y1, src+((post->texture>>4)&0xfc0), buf+ylookup[y1]);
+ post->floorclip=viewheight-1;
+ }
+ else
+ {
+ DrawHeightPost(y2-y1, src+((post->texture>>4)&0xfc0), buf+ylookup[y1]);
+ post->floorclip=y2-1;
+ }
+}
+*/
+
+
+
+
+
+
+//******************************************************************************
+//
+// DrawBackground
+//
+//******************************************************************************
+
+void DrawBackground ( byte * bkgnd )
+{
+// int plane;
+ int size;
+
+ size=linewidth*200;
+
+#ifdef DOS
+ for (plane=0; plane<4; plane++)
+#endif
+ {
+ VGAWRITEMAP(plane);
+ memcpy((byte *)bufferofs,bkgnd,size);
+ bkgnd+=size;
+ }
+}
+
+
+//******************************************************************************
+//
+// PrepareBackground
+//
+//******************************************************************************
+
+void PrepareBackground ( byte * bkgnd )
+{
+// int plane;
+ int size;
+
+ size=linewidth*200;
+
+#ifdef DOS
+ for (plane=0; plane<4; plane++)
+#endif
+ {
+ VGAREADMAP(plane);
+ memcpy(bkgnd,(byte *)bufferofs,size);
+ bkgnd+=size;
+ }
+}
+
+//******************************************************************************
+//
+// WarpString
+//
+//******************************************************************************
+
+void WarpString (
+ int x, int y, int endx, int endy,
+ int time, byte * back, char * str
+)
+{
+ int dx;
+ int dy;
+ int cx;
+ int cy;
+ int starttime;
+
+
+ LastScan = 0;
+
+
+ dx=((endx-x)<<16)/time;
+ dy=((endy-y)<<16)/time;
+ cx=x<<16;
+ cy=y<<16;
+ starttime=time;
+
+ CalcTics();
+
+ while (time>0)
+ {
+
+ DrawBackground ( back );
+ US_ClippedPrint (cx>>16, cy>>16, str);
+ FlipPage();
+
+ CalcTics();
+ cx+=dx*tics;
+ cy+=dy*tics;
+ time-=tics;
+ if (LastScan != 0)
+ break;
+ }
+
+ // DrawBackground ( back );
+ // US_ClippedPrint (endx, endy, str);
+ // FlipPage();
+
+}
+
+
+#if (SHAREWARE==1)
+//******************************************************************************
+//
+// DoEndCinematic
+//
+//******************************************************************************
+
+//******************************************************************************
+//
+// WarpSprite
+//
+//******************************************************************************
+
+void WarpSprite (
+ int x, int y, int endx, int endy,
+ int time, byte * back, int shape
+)
+{
+ int dx;
+ int dy;
+ int cx;
+ int cy;
+ int starttime;
+
+ LastScan = 0;
+
+ dx=((endx-x)<<16)/time;
+ dy=((endy-y)<<16)/time;
+ cx=x<<16;
+ cy=y<<16;
+ starttime=time;
+
+ CalcTics();
+
+ while (time>0)
+ {
+ DrawBackground ( back );
+ DrawUnScaledSprite (cx>>16, cy>>16, shape, 16);
+ FlipPage();
+ CalcTics();
+ cx+=dx*tics;
+ cy+=dy*tics;
+ time-=tics;
+ if (LastScan != 0)
+ break;
+ }
+}
+
+
+char *EndCinematicPicNames[5] =
+{
+ "lwgshoo2",
+ "hg2shoo2",
+ "ankshoo1",
+ "ligrise4",
+ "tritoss5",
+
+};
+
+#define NUMENDMESSAGES 24
+
+
+char *EndCinematicText[NUMENDMESSAGES] =
+{
+ "You've won the battle, Cassatt.\n"
+ "But when the Oscuridos return,\n"
+ "will you be ready as they wage\n"
+ "their Dark War?",
+
+ "Armed with only a pistol and 30\n"
+ "bucks, you must stop the minions of\n"
+ "El Oscuro before they kill millions\n"
+ "of innocent people.",
+
+ "But for now, hey, enjoy the medal\n"
+ "you received and take a vacation.\n"
+ "You've earned it. Maybe on \n"
+ "San Nicolas Island . . .",
+
+ "Thanks for playing. If you liked\n"
+ "\"The HUNT Begins\", check Ordering\n"
+ "Info for information about \n"
+ "continuing your adventure.",
+
+ "Okay, you can stop reading now.",
+
+ "Press a key. That's all there is.\n"
+ "Thanks.",
+
+ "Are you lazy, or illiterate?\n"
+ "PRESS A KEY.",
+
+ "Look, this is pointless. You\n"
+ "are done. Push off.",
+
+ "Okay, show's over. Nothing\n"
+ "more to see here.",
+
+ "Wow, you must like this fine\n"
+ "background screen.",
+
+ "For waiting this long, you get . . .\n"
+ "nothing! Go away!",
+
+ "I mean, I like you as a friend,\n"
+ "but . . .",
+
+ "\"Bob\"",
+
+ "All right, um . . . you found the\n"
+ "secret message! Congratulations!",
+
+ "Didn't work, huh? Okay, how about\n"
+ "this . . .",
+
+ "THE END",
+
+ "Dang. Thought I had you there.",
+
+ "Stop watching.",
+
+ "You know that if you registered,\n"
+ "there would be a lot more cool\n"
+ "stuff happening right now.",
+
+ "Episode IV: A New Hope\n",
+
+ "Just think of all the new secret\n"
+ "messages you could find hidden\n"
+ "in the registered version!",
+
+ "Someone right now is probably\n"
+ "enjoying the really exciting\n"
+ "ending of the registered version.",
+
+ "ROTT was filmed before\n"
+ "a live audience.",
+
+ "No animals were harmed during the\n"
+ "creation of this video game, although\n"
+ "one dog did get its butt spanked\n"
+ "when it peed on the carpet.\n",
+
+
+};
+char NextGameString1[] = "The Developers of Incredible Power";
+char NextGameString2[] = "shall return";
+
+void DoEndCinematic ( void )
+{
+ int trilogo;
+ int group;
+ int world;
+ int width;
+ int height;
+ int x,y;
+ int shape;
+ int time1,time2;
+ byte * tmp;
+ byte * sky;
+ byte * bkgnd;
+ int i;
+
+ byte pal[768];
+ EnableScreenStretch();
+
+ viewwidth = 320;//MAXSCREENWIDTH;
+ viewheight = 200;//MAXSCREENHEIGHT;
+
+ MU_StartSong(song_youwin);
+
+ bkgnd=SafeMalloc(800*linewidth);
+
+ trilogo=W_GetNumForName("trilogo");
+ world=W_GetNumForName("ap_wrld");
+ group=W_GetNumForName("mmbk");
+ VL_DrawPostPic (trilogo);
+ PrepareBackground ( bkgnd );
+
+ WarpSprite (160, -100, 160, 100, (VBLCOUNTER*3), bkgnd, W_GetNumForName("youwin"));
+ if (LastScan !=0)
+ goto fadelogo;
+
+ I_Delay(30);
+fadelogo:
+ MenuFadeOut();
+ ClearGraphicsScreen();
+ memcpy(&pal[0],W_CacheLumpName("ap_pal",PU_CACHE,CvtNull,1),768);
+ VL_NormalizePalette(&pal[0]);
+ SwitchPalette(&pal[0],35);
+
+ VL_DrawPostPic (world);
+ PrepareBackground ( bkgnd );
+
+ WarpSprite (160, 250, 160, 100, (VBLCOUNTER*3), bkgnd, W_GetNumForName("wrldsafe"));
+ if (LastScan !=0)
+ goto fadeworld;
+
+ I_Delay(10);
+ if (LastScan !=0)
+ goto fadeworld;
+
+ WarpSprite (160, 100, 160, -50, (VBLCOUNTER*3), bkgnd, W_GetNumForName("wrldsafe"));
+ if (LastScan !=0)
+ goto fadeworld;
+
+ I_Delay(20);
+
+fadeworld:
+ MenuFadeOut();
+ ClearGraphicsScreen();
+ MenuFadeIn();
+
+
+ sky=W_CacheLumpNum(W_GetNumForName("SKYSTART")+2,PU_CACHE,CvtNull,1);
+ tmp=sky;
+ for (x=0; x<256; x++)
+ {
+ VGAWRITEMAP(x&3);
+ for (y=0; y<200; y++)
+ {
+#ifdef DOS
+ *((byte *)bufferofs+ylookup[y]+(x>>2))=*tmp++;
+#else
+ *((byte *)bufferofs+ylookup[y]+x)=*tmp++;
+#endif
+ }
+ }
+ tmp=sky;
+ for (x=256; x<320; x++)
+ {
+ VGAWRITEMAP(x&3);
+ for (y=0; y<200; y++)
+ {
+#ifdef DOS
+ *((byte *)bufferofs+ylookup[y]+(x>>2))=*tmp++;
+#else
+ *((byte *)bufferofs+ylookup[y]+x)=*tmp++;
+#endif
+ }
+ }
+
+ for(i=0; i<5; i++)
+ {
+ int tx,ty;
+
+ tx = 32 + (i << 6);
+ ty = 100;
+ shape = W_GetNumForName(EndCinematicPicNames[i]);
+ DrawUnScaledSprite (tx, ty, shape,16);
+ }
+
+ PrepareBackground ( bkgnd );
+
+ //CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_CACHE);
+ CurrentFont = smallfont;
+ LastScan = 0;
+
+ for(i=0; i<NUMENDMESSAGES; i++)
+ {
+ if (i>3)
+ I_Delay(50);
+
+ US_MeasureStr (&width, &height, "%s", &(EndCinematicText[i][0]));
+ if (LastScan !=0)
+ break;
+
+ x=(320-width)>>1;
+ y=(200-height)>>1;
+ time1 = (300 - y)*(VBLCOUNTER*4)/300;
+ time2 = VBLCOUNTER*4-time1;
+
+ WarpString (x, 250, x, y-50,time1, bkgnd, EndCinematicText[i]);
+ if (LastScan !=0)
+ break;
+ I_Delay(40);
+ if (LastScan !=0)
+ break;
+
+ if (i<=3)
+ I_Delay(40);
+ if (LastScan !=0)
+ break;
+
+ WarpString (x, y-50, x, -50, time2, bkgnd, EndCinematicText[i]);
+ if (LastScan !=0)
+ break;
+
+
+ }
+
+ if (LastScan!=0)
+ goto finalfade;
+
+ sky=W_CacheLumpNum(W_GetNumForName("SKYSTART")+2,PU_CACHE,CvtNull,1);
+ tmp=sky;
+ for (x=0; x<256; x++)
+ {
+ VGAWRITEMAP(x&3);
+ for (y=0; y<200; y++)
+ {
+#ifdef DOS
+ *((byte *)bufferofs+ylookup[y]+(x>>2))=*tmp++;
+#else
+ *((byte *)bufferofs+ylookup[y]+x)=*tmp++;
+#endif
+ }
+ }
+ tmp=sky;
+ for (x=256; x<320; x++)
+ {
+ VGAWRITEMAP(x&3);
+ for (y=0; y<200; y++)
+ {
+#ifdef DOS
+ *((byte *)bufferofs+ylookup[y]+(x>>2))=*tmp++;
+#else
+ *((byte *)bufferofs+ylookup[y]+x)=*tmp++;
+#endif
+ }
+ }
+
+ for(i=0; i<5; i++)
+ {
+ int tx,ty;
+
+ tx = 32 + (i << 6);
+ ty = 100;
+ shape = W_GetNumForName(EndCinematicPicNames[i]);
+ DrawUnScaledSprite (tx, ty, shape,16);
+ }
+
+
+ shape = W_GetNumForName("robogrd3");
+ PrepareBackground ( bkgnd );
+ WarpSprite (420,100,300,100,VBLCOUNTER*3,bkgnd,shape);
+ if (LastScan !=0)
+ goto finalfade;
+
+ PrepareBackground ( bkgnd );
+ WarpString (200,80,200,80,VBLCOUNTER*3,bkgnd, "Am I late?");
+ if (LastScan !=0)
+ goto finalfade;
+
+
+ I_Delay(20);
+finalfade:
+
+ MenuFadeOut();
+ VL_ClearVideo (0);
+ I_Delay(10);
+
+ if (LastScan == 0)
+ {
+ US_MeasureStr (&width, &height, "%s", NextGameString1);
+ x=(320-width)>>1;
+ y=(200-height)>>1;
+ US_ClippedPrint (x,y-6, NextGameString1);
+ US_MeasureStr (&width, &height, "%s", NextGameString2);
+ x=(320-width)>>1;
+ y=(200-height)>>1;
+ US_ClippedPrint (x,y+6, NextGameString2);
+ FlipPage();
+ VL_FadeIn(0,255,origpal,150);
+ I_Delay(50);
+ VL_FadeOut(0,255,0,0,0,150);
+ VL_ClearVideo (0);
+ I_Delay(10);
+ }
+
+ SafeFree(bkgnd);
+}
+#else
+
+// REGISTERED VERSION ======================================================
+
+static char burnCastle1Msg []=
+ "The monastery burns.\n"
+ "\n"
+ "El Oscuro is dead.\n"
+ "\n"
+ "The world is safe.\n";
+
+// If all Snake Eggs not destroyed on final level:
+
+
+static char notDoneMsg[] =
+ "Unfortunately not all\n"
+ "of El Oscuro's larvae\n"
+ "were destroyed.\n"
+ "\n"
+ "Thirty years later,\n"
+ "a descendant of\n"
+ "El Oscuro wiped out\n"
+ "the entire world,\n"
+ "but nice job anyway.\n";
+
+static char tryAgainMsg[] =
+ "Try Again.\n"
+ "\n"
+ "The world will not be\n"
+ "safe until all of El\n"
+ "Oscuro's larvae are\n"
+ "destroyed. Find them.\n";
+
+// If all snake eggs destroyed:
+static char doneMsg[] =
+ "You have destroyed\n"
+ "El Oscuro and all his\n"
+ "descendants. Well done!\n";
+
+// On Triad background, in bigger font.
+static char youWin1Msg[] =
+ "So, HUNT Members, how\n"
+ "do you think the\n"
+ "mission went?\n";
+
+// Place menu pix of characters here (maybe modem frame too?)
+static char youWin2Msg[] =
+ "Barrett: Well, I think\n"
+ "I got shin splints from\n"
+ "all those jump pads.\n"
+ "But hey, action-wise,\n"
+ "I've been in tougher\n"
+ "bar fights, for crying\n"
+ "out loud.\n";
+
+static char youWin3Msg[] =
+ "Cassatt: Apart from\n"
+ "the other HUNT members\n"
+ "saying I look like\n"
+ "Richard Mulligan, it\n"
+ "was quite a success.\n"
+ "And some of the\n"
+ "monastery's ironwork\n"
+ "was very nice.\n";
+
+static char youWin4Msg[] =
+ "Ni: it was quite easy,\n"
+ "actually. I just\n"
+ "pictured the enemy\n"
+ "having the face of\n"
+ "my ex-husband, and\n"
+ "man, I was a force\n"
+ "of Nature.\n";
+
+static char youWin5Msg[] =
+ "Wendt: I was kind of\n"
+ "disappointed. I think\n"
+ "I used the missile\n"
+ "weapons way too much.\n"
+ "Next time, bullets\n"
+ "only. Nothing sweeter\n"
+ "than a head shot from\n"
+ "a hundred feet.\n";
+
+static char youWin6Msg[] =
+ "Freeley: I'm still\n"
+ "trying to adjust in\n"
+ "the aftermath. It's\n"
+ "kinda tough. I mean,\n"
+ "I save the damn world,\n"
+ "and all people ask\n"
+ "about is my name.\n"
+ "Sheesh.\n";
+
+// On caching screen
+
+static char youWin7Msg[] =
+ "The HUNT is victorious!\n"
+ "\n"
+ " THE END\n";
+
+
+static char youWin8Msg[] =
+ "Now go and celebrate!\n"
+ "\n"
+ " THE REAL END";
+
+#define NUMEXPLOSIONTYPES 4
+
+typedef struct {
+ char name[11];
+ byte numframes;
+} ExplosionInfoType;
+
+ExplosionInfoType ExplosionInfo[NUMEXPLOSIONTYPES]=
+{
+ {"EXPLOS1\0",20},
+ {"EXP1\0",20},
+ {"GREXP1\0",25},
+ {"PART1\0",12},
+#if 0
+ {"GUTS1\0",12},
+ {"ORGAN1\0",12},
+ {"RIB1\0",12},
+ {"GPINK1\0",12},
+ {"GHEAD1\0",12},
+ {"GARM1\0",12},
+ {"GLEG1\0",12},
+ {"GHUM1\0",12},
+ {"GHIP1\0",12},
+ {"GLIMB1\0",12},
+#endif
+};
+
+
+typedef struct {
+ byte which;
+ byte frame;
+ byte x;
+ byte y;
+} ExplosionType;
+
+#define MAXTRANSMITTEREXPLOSIONS 30
+
+static ExplosionType Explosions[MAXTRANSMITTEREXPLOSIONS];
+
+void ResetTransmitterExplosion ( ExplosionType * Explosion )
+{
+ Explosion->which=RandomNumber("Explosion",0)%NUMEXPLOSIONTYPES;
+ Explosion->frame=0;
+ Explosion->x=(RandomNumber("Explosion",2)>>1)+(160-64);
+ Explosion->y=(RandomNumber("Explosion",3)>>1);
+}
+
+void CacheTransmitterExplosions ( void )
+{
+ int i,j,num;
+
+ for (i=0; i<NUMEXPLOSIONTYPES; i++)
+ {
+ num=W_GetNumForName(ExplosionInfo[i].name);
+ for (j=0; j<ExplosionInfo[i].numframes; j++)
+ {
+ W_CacheLumpNum(num+j, PU_CACHE, Cvt_patch_t, 1);
+ }
+ }
+}
+
+void SetupTransmitterExplosions ( void )
+{
+ int i;
+
+ for (i=0; i<MAXTRANSMITTEREXPLOSIONS; i++)
+ {
+ ResetTransmitterExplosion(&Explosions[i]);
+ }
+}
+void UpdateTransmitterExplosions ( void )
+{
+ int i;
+ for (i=0; i<MAXTRANSMITTEREXPLOSIONS; i++)
+ {
+ Explosions[i].frame+=tics;
+ if (Explosions[i].frame>=(ExplosionInfo[Explosions[i].which].numframes<<1))
+ {
+ ResetTransmitterExplosion(&Explosions[i]);
+ SD_Play(SD_EXPLODEFLOORSND+(RandomNumber("Explosion",4)>>7));
+ }
+ }
+}
+
+void DrawTransmitterExplosions ( void )
+{
+ int i;
+ for (i=0; i<MAXTRANSMITTEREXPLOSIONS; i++)
+ {
+ DrawUnScaledSprite (
+ Explosions[i].x,
+ Explosions[i].y,
+ (W_GetNumForName(ExplosionInfo[Explosions[i].which].name) +
+ (Explosions[i].frame>>1)),
+ 16
+ );
+ }
+}
+
+void DoTransmitterExplosion ( void )
+{
+ byte * back;
+ int i;
+
+ VL_ClearVideo(0);
+ back=SafeMalloc(800*linewidth);
+
+ CalcTics();
+ CalcTics();
+ DrawNormalSprite(0,0,W_GetNumForName("transmit"));
+ PrepareBackground ( back );
+ SetupTransmitterExplosions ();
+ CacheTransmitterExplosions ();
+ DrawBackground ( back );
+ FlipPage();
+ VL_FadeIn (0, 255, origpal, 30);
+ SHAKETICS=VBLCOUNTER*15;
+ for (i=0; i<(VBLCOUNTER*15); i+=tics)
+ {
+ DrawBackground ( back );
+ DrawTransmitterExplosions ();
+ FlipPage();
+ CalcTics();
+ UpdateTransmitterExplosions ();
+ }
+ VL_FadeOut (0, 255, 63, 63, 63, 150);
+ screenfaded=false;
+ SD_Play(SD_PLAYERTCSND);
+ SD_Play(SD_PLAYERTBSND);
+ SD_Play(SD_PLAYERDWSND);
+ SD_Play(SD_PLAYERLNSND);
+ SD_Play(SD_PLAYERIPFSND);
+ VL_FadeOut (0, 255, 0, 0, 0, 30);
+ TurnShakeOff();
+
+ SafeFree(back);
+}
+
+void ShowTransmitter ( void )
+{
+ MenuFadeOut();
+ DrawNormalSprite(0,0,W_GetNumForName("transmit"));
+ FlipPage();
+ VL_FadeIn (0, 255, origpal, 30);
+ I_Delay(30);
+ VL_FadeOut (0, 255, 0, 0, 0, 30);
+}
+
+void ShowFinalDoor ( void )
+{
+ byte pal[768];
+
+ MenuFadeOut();
+
+ VL_ClearBuffer (bufferofs, 0);
+ DrawNormalSprite (0, (200-120)>>1, W_GetNumForName("finldoor"));
+ FlipPage();
+ memcpy(&pal[0],W_CacheLumpName("findrpal",PU_CACHE,CvtNull, 1),768);
+ VL_NormalizePalette(&pal[0]);
+ SD_Play(SD_OPENDOORSND);
+ VL_FadeIn (0, 255, pal, 30);
+ I_Delay(30);
+ VL_FadeOut (0, 255, 0, 0, 0, 30);
+}
+
+void ShowFinalFire ( void )
+{
+ byte pal[768];
+
+ MenuFadeOut();
+
+ VL_ClearBuffer (bufferofs, 0);
+ DrawNormalSprite (0, (200-120)>>1, W_GetNumForName("finlfire"));
+ FlipPage();
+ memcpy(&pal[0],W_CacheLumpName("finfrpal",PU_CACHE,CvtNull, 1),768);
+ VL_NormalizePalette(&pal[0]);
+ SD_Play(SD_BAZOOKAFIRESND);
+ VL_FadeIn (0, 255, pal, 30);
+ SD_Play(SD_FIREBOMBFIRESND);
+ I_Delay(2);
+ SD_Play(SD_HEATSEEKFIRESND);
+ I_Delay(2);
+ SD_Play(SD_DRUNKFIRESND);
+ SD_Play(SD_HEATSEEKFIRESND);
+ I_Delay(2);
+ SD_Play(SD_ATKMP40SND);
+ SD_Play(SD_ATKMP40SND);
+ I_Delay(2);
+ SD_Play(SD_HEATSEEKFIRESND);
+ SD_Play(SD_FIREBOMBFIRESND);
+ I_Delay(2);
+ SD_Play(SD_ATKMP40SND);
+ SD_Play(SD_HEATSEEKFIRESND);
+ I_Delay(2);
+ SD_Play(SD_DRUNKFIRESND);
+ I_Delay(2);
+ SD_Play(SD_FIREBOMBFIRESND);
+ I_Delay(2);
+ SD_Play(SD_HEATSEEKFIRESND);
+ SD_Play(SD_ATKMP40SND);
+ I_Delay(2);
+ SD_Play(SD_DRUNKFIRESND);
+ SD_Play(SD_HEATSEEKFIRESND);
+ I_Delay(2);
+ SD_Play(SD_FIREBOMBFIRESND);
+ SD_Play(SD_ATKMP40SND);
+ I_Delay(2);
+ SD_Play(SD_DRUNKFIRESND);
+ I_Delay(2);
+ SD_Play(SD_HEATSEEKFIRESND);
+ SD_Play(SD_FIREBOMBFIRESND);
+ I_Delay(2);
+ SD_Play(SD_ATKMP40SND);
+ SD_Play(SD_HEATSEEKFIRESND);
+ I_Delay(2);
+ SD_Play(SD_DRUNKFIRESND);
+ SD_Play(SD_FIREBOMBFIRESND);
+ I_Delay(2);
+ SD_Play(SD_HEATSEEKFIRESND);
+ SD_Play(SD_DRUNKFIRESND);
+ SD_Play(SD_BAZOOKAFIRESND);
+ I_Delay(4);
+ VL_FadeOut (0, 255, 0, 0, 0, 30);
+}
+
+void ScrollString ( int cy, char * string, byte * bkgnd, int scrolltime, int pausetime )
+{
+ int x,y;
+ int width,height;
+ int time1,time2;
+
+ LastScan=0;
+ US_MeasureStr (&width, &height, "%s", string);
+
+ x=(320-width)>>1;
+ y=cy-(height>>1);
+ time1 = ((220 - y)*scrolltime)/(220+height);
+ time2 = scrolltime-time1;
+
+ WarpString (x, 210, x, y, time1, bkgnd, string);
+
+ if (LastScan !=0)
+ return;
+
+ I_Delay(pausetime);
+
+ if (LastScan !=0)
+ return;
+
+ WarpString (x, y, x, -10-height, time2, bkgnd, string);
+}
+
+void DoBurningCastle ( void )
+{
+ byte * back;
+
+ LastScan=0;
+ VL_ClearVideo(0);
+ back=SafeMalloc(800*linewidth);
+
+ DrawNormalSprite(0,0,W_GetNumForName("finale"));
+ PrepareBackground ( back );
+ CurrentFont = smallfont;
+ FlipPage();
+ VL_FadeIn (0, 255, origpal, 30);
+ CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1 );
+ ScrollString ( 150, &burnCastle1Msg[0], back, 4*VBLCOUNTER, 80);
+ W_CacheLumpName ("newfnt1", PU_CACHE, Cvt_font_t, 1);
+ VL_FadeOut (0, 255, 0, 0, 0, 80);
+ SafeFree(back);
+}
+
+void DoFailedScreen ( void )
+{
+ byte * back;
+
+ back=SafeMalloc(800*linewidth);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ PrepareBackground ( back );
+ CurrentFont = smallfont;
+ FlipPage();
+ VL_FadeIn (0, 255, origpal, 30);
+ ScrollString ( 100, ¬DoneMsg[0], back, 4*VBLCOUNTER, 100);
+ VL_FadeOut (0, 255, 0, 0, 0, 80);
+ SafeFree(back);
+}
+
+void DoTryAgainScreen ( void )
+{
+ byte * back;
+
+ back=SafeMalloc(800*linewidth);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ PrepareBackground ( back );
+ CurrentFont = smallfont;
+ FlipPage();
+ VL_FadeIn (0, 255, origpal, 30);
+ ScrollString ( 100, tryAgainMsg, back, 4*VBLCOUNTER, 80);
+ VL_FadeOut (0, 255, 0, 0, 0, 80);
+ SafeFree(back);
+}
+
+void ResetWorldExplosion ( ExplosionType * Explosion )
+{
+ Explosion->which=RandomNumber("Explosion",0)%NUMEXPLOSIONTYPES;
+ Explosion->frame=0;
+// RandomNumber("Explosion",1)%ExplosionInfo[Explosions[i].which].numframes;
+ Explosion->x=(RandomNumber("Explosion",2))+64;
+ Explosion->y=(RandomNumber("Explosion",3)%180);
+}
+
+void SetupWorldExplosions ( void )
+{
+ int i;
+
+ for (i=0; i<MAXTRANSMITTEREXPLOSIONS; i++)
+ {
+ ResetWorldExplosion(&Explosions[i]);
+ }
+}
+void UpdateWorldExplosions ( void )
+{
+ int i;
+ for (i=0; i<MAXTRANSMITTEREXPLOSIONS; i++)
+ {
+ Explosions[i].frame+=tics;
+ if (Explosions[i].frame>=(ExplosionInfo[Explosions[i].which].numframes<<1))
+ {
+ ResetWorldExplosion(&Explosions[i]);
+ SD_Play(SD_EXPLODEFLOORSND+(RandomNumber("Explosion",4)>>7));
+ }
+ }
+}
+
+void DestroyEarth ( void )
+{
+ byte * back;
+ int i;
+
+ VL_ClearVideo(0);
+ back=SafeMalloc(800*linewidth);
+
+ CalcTics();
+ CalcTics();
+ DrawNormalSprite(0,0,W_GetNumForName("ourearth"));
+ PrepareBackground ( back );
+ SetupWorldExplosions ();
+ CacheTransmitterExplosions ();
+ DrawBackground ( back );
+ FlipPage();
+ VL_FadeIn (0, 255, origpal, 30);
+ SHAKETICS=VBLCOUNTER*10;
+ for (i=0; i<(VBLCOUNTER*10); i+=tics)
+ {
+ DrawBackground ( back );
+ DrawTransmitterExplosions ();
+ FlipPage();
+ CalcTics();
+ UpdateWorldExplosions ();
+ }
+ VL_FadeOut (0, 255, 63, 63, 63, 150);
+ screenfaded=false;
+ if (gamestate.violence==vl_excessive)
+ SD_Play(SD_YOUSUCKSND);
+ VL_FadeOut (0, 255, 0, 0, 0, 50);
+ TurnShakeOff();
+
+ SafeFree(back);
+}
+
+boolean DestroyedAllEggs ( void )
+{
+ statobj_t * temp;
+
+ for(temp=FIRSTSTAT; temp; temp=temp->statnext)
+ {
+ if (temp->itemnumber==stat_tomlarva)
+ return false;
+ }
+ return true;
+}
+
+void DoSanNicolas ( void )
+{
+ byte pal[768];
+
+ LastScan=0;
+ VL_ClearVideo(0);
+ DrawNormalSprite(0,16,W_GetNumForName("nicolas"));
+ DrawNormalSprite(10,200-58,W_GetNumForName("budgcut"));
+ FlipPage();
+ memcpy(&pal[0],W_CacheLumpName("nicpal",PU_CACHE, CvtNull, 1),768);
+ VL_NormalizePalette(&pal[0]);
+ VL_FadeIn (0, 255, pal, 30);
+ I_Delay(60);
+ VL_FadeOut (0, 255, 0, 0, 0, 80);
+}
+
+void PlayerQuestionScreen ( void )
+{
+ byte * back;
+
+ back=SafeMalloc(800*linewidth);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ PrepareBackground ( back );
+ CurrentFont = smallfont;
+ FlipPage();
+ VL_FadeIn (0, 255, origpal, 30);
+ CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1);
+ ScrollString ( 100, &doneMsg[0], back, 4*VBLCOUNTER, 40);
+ ScrollString ( 100, &youWin1Msg[0], back, 4*VBLCOUNTER, 50);
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawXYPic ( 8, 100-24, W_GetNumForName("player2"));
+ PrepareBackground ( back );
+ CurrentFont = smallfont;
+ SD_Play(SD_PLAYERTBSND);
+ ScrollString ( 100, &youWin2Msg[0], back, 4*VBLCOUNTER, 100);
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawXYPic ( 8, 100-24, W_GetNumForName("player1"));
+ PrepareBackground ( back );
+ SD_Play(SD_PLAYERTCSND);
+ ScrollString ( 100, &youWin3Msg[0], back, 4*VBLCOUNTER, 100);
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawXYPic ( 8, 100-24, W_GetNumForName("player4"));
+ PrepareBackground ( back );
+ SD_Play(SD_PLAYERLNSND);
+ ScrollString ( 100, &youWin4Msg[0], back, 4*VBLCOUNTER, 100);
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawXYPic ( 8, 100-24, W_GetNumForName("player3"));
+ PrepareBackground ( back );
+ SD_Play(SD_PLAYERDWSND);
+ ScrollString ( 100, &youWin5Msg[0], back, 4*VBLCOUNTER, 100);
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawXYPic ( 8, 100-24, W_GetNumForName("player5"));
+ PrepareBackground ( back );
+ SD_Play(SD_PLAYERIPFSND);
+ ScrollString ( 100, &youWin6Msg[0], back, 4*VBLCOUNTER, 100);
+ W_CacheLumpName ("newfnt1", PU_CACHE, Cvt_font_t, 1);
+ VL_FadeOut (0, 255, 0, 0, 0, 80);
+ SafeFree(back);
+}
+
+void DoYouWin ( void )
+{
+ pic_t * pic;
+ byte * back;
+
+ back=SafeMalloc(800*linewidth);
+ LastScan=0;
+ VL_ClearVideo(0);
+ pic = (pic_t *) W_CacheLumpNum (W_GetNumForName ("mmbk"), PU_CACHE, Cvt_pic_t, 1);
+ VWB_DrawPic (0, 0, pic);
+ PrepareBackground ( back );
+ FlipPage();
+ VL_FadeIn (0, 255, origpal, 30);
+ CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1);
+ ScrollString ( 100, &youWin7Msg[0], back, 4*VBLCOUNTER, 300);
+ W_CacheLumpName ("newfnt1", PU_CACHE, Cvt_font_t, 1);
+ VL_FadeOut (0, 255, 0, 0, 0, 80);
+ SafeFree(back);
+}
+
+void DoFinalEnd ( void )
+{
+ pic_t * pic;
+ byte * back;
+
+ back=SafeMalloc(800*linewidth);
+ LastScan=0;
+ VL_ClearVideo(0);
+ pic = (pic_t *) W_CacheLumpNum (W_GetNumForName ("mmbk"), PU_CACHE, Cvt_pic_t, 1);
+ VWB_DrawPic (0, 0, pic);
+ DrawNormalSprite(0,0,W_GetNumForName("sombrero"));
+ DrawNormalSprite(0,0,W_GetNumForName("amflag"));
+ DrawNormalSprite(0,0,W_GetNumForName("witchhat"));
+ DrawNormalSprite(0,0,W_GetNumForName("esterhat"));
+ DrawNormalSprite(0,0,W_GetNumForName("santahat"));
+ PrepareBackground ( back );
+ FlipPage();
+ VL_FadeIn (0, 255, origpal, 30);
+ CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1);
+ ScrollString ( 100, &youWin8Msg[0], back, 4*VBLCOUNTER, 100);
+ W_CacheLumpName ("newfnt1", PU_CACHE, Cvt_font_t, 1);
+ VL_FadeOut (0, 255, 0, 0, 0, 80);
+ SafeFree(back);
+ VL_ClearVideo(0);
+}
+
+static char dipMsg[] =
+ "The Developers of Incredible Power!\n"
+ "\n"
+ "Susan Tom Jim Stephen\n"
+ "Mark William Chuck\n";
+
+static char creditsMsg[] =
+ "Rise of the Triad Credits\n";
+
+static char credits1Msg[] =
+ "Programmers\n"
+ "\n"
+ "Mark Dochtermann\n"
+ "William Scarboro\n"
+ "Jim Dose'\n"
+ "Nolan Martin\n";
+
+static char credits2Msg[] =
+ "Creative Director\n"
+ "\n"
+ "Tom Hall\n";
+
+static char credits3Msg[] =
+ "Artists\n"
+ "\n"
+ "Stephen Hornback\n"
+ "Tim Neveu\n"
+ "Chuck Jones\n"
+ "Susan Singer\n"
+ "James Storey\n"
+ "Cygnus Multimedia\n";
+
+static char credits4Msg[] =
+ "Level Designers\n"
+ "\n"
+ "Tom Hall\n"
+ "Joseph Selinske\n"
+ "Marianna Vayntrub\n"
+ "Joe Siegler\n";
+static char credits5Msg[] =
+ "Music\n"
+ "\n"
+ "Lee Jackson\n"
+ "Bobby Prince\n";
+
+static char credits6Msg[] =
+ "Robot Models\n"
+ "\n"
+ "Gregor Punchatz\n";
+
+static char credits7Msg[] =
+ "Special Thanks\n"
+ "\n"
+ "George Broussard\n"
+ "Scott Miller\n"
+ "Steven Blackburn\n"
+ "Apogee Technical Support\n"
+ "Apogee Support Staff\n"
+ "John Carmack\n"
+ "Ken Silverman\n";
+
+static char credits8Msg[] =
+ "The Hand of God\n"
+ "\n"
+ "Tim Neveu's Hand\n";
+
+static char credits9Msg[] =
+ "Dog Snout and Paw\n"
+ "\n"
+ "Loki\n"
+ "The Carpet Wetting Maestro\n";
+
+static char credits10Msg[] =
+ "Krist's chair\n"
+ "\n"
+ "Stephen Blackburn's Comfy Chair\n"
+ "Marianna's Paper and Glue\n";
+
+static char credits11Msg[] =
+ "Character Voices\n"
+ "\n"
+ "Darian - Mark Dochtermann\n"
+ "Krist - Joe Siegler\n"
+ "NME - Sound CD#4005\n"
+ "Oscuro - Tom Hall\n"
+ "Low Guard - Steve Quarrella\n"
+ "High Guard - Steven Blackburn\n"
+ "Over Patrol - Chuck Jones\n";
+
+static char credits12Msg[] =
+ "Character Voices Continued\n"
+ "\n"
+ "Strike Team - Scott Miller\n"
+ "Lightning Guard - William Scarboro\n"
+ "Triad Enforcer - George Broussard\n"
+ "All Monks - Tom Hall\n"
+ "Taradino - Joe Selinske\n"
+ "Lorelei - Pau Suet Ying\n"
+ "Ian Paul - Jim Dose'\n"
+ "Doug - Lee Jackson\n"
+ "Thi - Susan Singer\n";
+
+static char actorsMsg[] =
+ "The Actors\n";
+
+static char actors1Msg[] =
+ "Low Guard\n"
+ "\n"
+ "Steve Quarrella\n";
+
+static char actors2Msg[] =
+ "High Guard\n"
+ "\n"
+ "Steven Blackburn\n";
+
+static char actors3Msg[] =
+ "Over Patrol\n"
+ "\n"
+ "Nolan Martin\n";
+
+static char actors4Msg[] =
+ "Strike Team\n"
+ "\n"
+ "Scott Miller\n";
+
+static char actors5Msg[] =
+ "Lightning Guard\n"
+ "\n"
+ "Kevin Green\n";
+
+static char actors6Msg[] =
+ "Triad Enforcer\n"
+ "\n"
+ "George Broussard\n";
+
+static char actors7Msg[] =
+ "Death Monk\n"
+ "\n"
+ "Lee Jackson\n";
+
+static char actors8Msg[] =
+ "Deathfire Monk\n"
+ "\n"
+ "Allen Blum III\n";
+
+static char actors9Msg[] =
+ "Robot Guard\n"
+ "\n"
+ "Himself\n";
+
+static char actors10Msg[] =
+ "General Darian\n"
+ "\n"
+ "Steve Maines\n";
+
+static char actors11Msg[] =
+ "Sebastian Krist\n"
+ "\n"
+ "Joe Siegler\n";
+
+static char actors12Msg[] =
+ "The NME\n"
+ "\n"
+ "Himself\n";
+
+static char actors13Msg[] =
+ "El Oscuro\n"
+ "\n"
+ "Tom Hall\n";
+
+
+static char cut1Msg[] =
+ "Deathfire Monk\n"
+ "\n"
+ "Mark Dochtermann\n";
+
+
+static char cut2Msg[] =
+ "Over Patrol\n"
+ "\n"
+ "Pat Miller\n";
+
+
+static char cut3Msg[] =
+ "Low Guard\n"
+ "\n"
+ "Marianna Vayntrub\n";
+
+
+static char cut4Msg[] =
+ "Strike Team\n"
+ "\n"
+ "Ann Grauerholz\n";
+
+static char cut5Msg[] =
+ "Lightning Guard\n"
+ "\n"
+ "William Scarboro\n";
+
+
+static char cut6Msg[] =
+ "High Guard\n"
+ "\n"
+ "Stephen Hornback\n";
+
+
+
+static char playersCutMsg[] =
+ "Actors who were\n"
+ "cut from the game\n";
+
+void DIPCredits ( void )
+{
+ byte * back;
+
+ back=SafeMalloc(800*linewidth);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ PrepareBackground ( back );
+ FlipPage();
+ VL_FadeIn (0, 255, origpal, 30);
+ CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1);
+ ScrollString ( 100, &creditsMsg[0], back, 4*VBLCOUNTER, 30);
+ CurrentFont = smallfont;
+ ScrollString ( 100, &credits1Msg[0], back, 4*VBLCOUNTER, 50);
+ ScrollString ( 100, &credits2Msg[0], back, 4*VBLCOUNTER, 50);
+ ScrollString ( 100, &credits3Msg[0], back, 4*VBLCOUNTER, 50);
+ ScrollString ( 100, &credits4Msg[0], back, 4*VBLCOUNTER, 50);
+ ScrollString ( 100, &credits5Msg[0], back, 4*VBLCOUNTER, 50);
+ ScrollString ( 100, &credits6Msg[0], back, 4*VBLCOUNTER, 50);
+ ScrollString ( 100, &credits7Msg[0], back, 4*VBLCOUNTER, 50);
+ ScrollString ( 100, &credits8Msg[0], back, 4*VBLCOUNTER, 50);
+ ScrollString ( 100, &credits9Msg[0], back, 4*VBLCOUNTER, 50);
+ ScrollString ( 100, &credits10Msg[0], back, 4*VBLCOUNTER, 50);
+ ScrollString ( 100, &credits11Msg[0], back, 4*VBLCOUNTER, 80);
+ ScrollString ( 100, &credits12Msg[0], back, 4*VBLCOUNTER, 80);
+
+ CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1);
+ ScrollString ( 100, &actorsMsg[0], back, 4*VBLCOUNTER, 50);
+
+ CurrentFont = smallfont;
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("lwgshoo2"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &actors1Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("hg2shoo2"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &actors2Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("obpshoo1"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &actors3Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("ankshoo1"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &actors4Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("ligrise4"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &actors5Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("tritoss5"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &actors6Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("monkdr4"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &actors7Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("allksh4"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &actors8Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("robogrd1"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &actors9Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("darshoo1"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &actors10Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("hdope8"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &actors11Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("rbody101"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("rhead101"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("rsw01"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &actors12Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("tomfly21"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &actors13Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ PrepareBackground ( back );
+ CurrentFont = (font_t *)W_CacheLumpName ("newfnt1", PU_STATIC, Cvt_font_t, 1);
+ ScrollString ( 100, &playersCutMsg[0], back, 4*VBLCOUNTER, 40);
+
+ CurrentFont = smallfont;
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("cutmark"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &cut1Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("cutpat"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &cut2Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("cutmari"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &cut3Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("cutann"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &cut4Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("cutwill"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &cut5Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ DrawNormalSprite(0,(200-128)>>1,W_GetNumForName("cutstev"));
+ PrepareBackground ( back );
+ ScrollString ( 100, &cut6Msg[0], back, 4*VBLCOUNTER, 50);
+
+ VL_FadeOut (0, 255, 0, 0, 0, 80);
+
+ DrawNormalSprite(0,0,W_GetNumForName("grouppic"));
+ PrepareBackground ( back );
+ FlipPage();
+ VL_FadeIn (0, 255, origpal, 30);
+ ScrollString ( 175, &dipMsg[0], back, 4*VBLCOUNTER, 140);
+ VL_FadeOut (0, 255, 0, 0, 0, 80);
+
+ W_CacheLumpName ("newfnt1", PU_CACHE, Cvt_font_t, 1);
+ SafeFree(back);
+}
+
+void DoEndCinematic ( void )
+{
+ EnableScreenStretch();
+
+ viewwidth = 320;//MAXSCREENWIDTH;
+ viewheight = 200;//MAXSCREENHEIGHT;
+ MU_FadeOut ( 1000 );
+ MU_StopSong ();
+
+ ShowFinalDoor();
+ ShowTransmitter ();
+ ShowFinalFire();
+ DoTransmitterExplosion();
+ MU_StartSong(song_youwin);
+ DoBurningCastle ();
+ DoSanNicolas();
+ if (DestroyedAllEggs () == true)
+ {
+ PlayerQuestionScreen();
+ DIPCredits();
+ DoYouWin();
+ if (LastScan !=0)
+ {
+ IN_UpdateKeyboard();
+ return;
+ }
+ DoFinalEnd();
+ }
+ else
+ {
+ MU_StartSong(song_gameover);
+ DoFailedScreen();
+ DestroyEarth();
+ DoTryAgainScreen ();
+ playstate=ex_warped;
+ gamestate.mapon=33;
+ }
+ IN_UpdateKeyboard();
+}
+
+void DoInBetweenCinematic (int yoffset, int lump, int delay, char * string )
+{
+ int width,height;
+ int x,y;
+
+ VL_FadeOut (0, 255, 0, 0, 0, 20);
+ VL_ClearBuffer (bufferofs, 0);
+ DrawNormalSprite(0,yoffset,lump);
+
+ CurrentFont=smallfont;
+ US_MeasureStr (&width, &height, "%s", string);
+ x=(320-width)>>1;
+ y=190-height;
+ US_ClippedPrint (x, y, string);
+ FlipPage();
+ VL_FadeIn(0,255,origpal,20);
+ I_Delay (delay);
+ VL_FadeOut (0, 255, 0, 0, 0, 20);
+}
+#endif
+
+
+//******************************************************************************
+//
+// DoCreditScreen
+//
+//******************************************************************************
+
+#define NUMFIRSTCREDITMESSAGES 22
+#define NUMSECONDCREDITMESSAGES 28
+
+typedef struct CreditType {
+ char text[80];
+ byte font;
+ byte endy;
+} CreditType;
+
+CreditType FirstCredits[NUMFIRSTCREDITMESSAGES] =
+{
+ {"Rise of the Triad Credits",0,0},
+ {"COPYRIGHT (c) 1995 Apogee Software Ltd.",1,10},
+ {"Apogee's Developers of Incredible Power",1,20},
+ {"Creative Director",0,30},
+ {"Tom Hall",1,40},
+ {"Programmers",0,50},
+ {"Mark Dochtermann William Scarboro",1,60},
+ {"Jim Dose' Nolan Martin",1,66},
+ {"Artists",0,76},
+ {"Stephen Hornback Chuck Jones",1,86},
+ {"Susan Singer Tim Neveu",1,92},
+ {"James Storey Cygnus Multimedia",1,98},
+ {"Level Designers",0,108},
+ {"Joseph Selinske Tom Hall",1,118},
+ {"Marianna Vayntrub Joe Siegler",1,124},
+ {"Musicians",0,134},
+ {"Lee Jackson Robert Prince",1,144},
+ {"Uniforms",0,154},
+ {"D.J. Goodwin Matt McKinney",1,164},
+ {"Special Thanks",0,174},
+ {"John Carmack Ken Silverman Gregor Punchatz",1,184},
+};
+
+CreditType SecondCredits[NUMSECONDCREDITMESSAGES] =
+{
+ {"Rise of the Triad Credits",0,0},
+ {"COPYRIGHT (c) 1995 Apogee Software Ltd.",1,10},
+ {"Executive Producers",0,20},
+ {"George Broussard Scott Miller",1,30},
+ {"Manual Design",0,40},
+ {"Robert Atkins",1,50},
+ {"Beta Testers",0,60},
+ {"Steven Blackburn",1,70},
+ {"Todd Aubin Mike Bartelt",1,76},
+ {"Wayne Benner Neil Bonner",1,82},
+ {"Glenn Brensinger Douglas Brewer",1,88},
+ {"David Butler Daniel Creeron",1,94},
+ {"Scott Darling Jason Ewasiuk",1,100},
+ {"Craig Hamilton Ken Heckbert",1,106},
+ {"Terry Herrin Greg Hively",1,112},
+ {"John Howard Douglas Howell",1,118},
+ {"Dennis Kurek Hank Leukart",1,124},
+ {"Jim Lietzan Ken Mayer",1,130},
+ {"Wayne Millard Penny Plant",1,136},
+ {"Brian Prinner Jeff Rausch",1,142},
+ {"Kelly Rogers Neil Rubenking",1,148},
+ {"Steven Salter Chris White",1,154},
+ {"Special Thanks",0,162},
+ {"Apogee Technical Support Pau Suet Ying",1,172},
+ {"Anthony, Zach, Rajan, Miki, Loki",1,178},
+ {"Nathan, Petro, Tim, Jake, MacKay",1,184},
+ {"Loyal, Ric, Teller, Amano",1,190},
+};
+
+void DrawPreviousCredits ( int num, CreditType * Credits )
+{
+ int width;
+ int height;
+ int x,y;
+ int i;
+
+ for(i=0; i<num; i++)
+ {
+ if (Credits[i].font==0)
+ CurrentFont=smallfont;
+ else
+ CurrentFont=tinyfont;
+ US_MeasureStr (&width, &height, "%s", &(Credits[i].text[0]));
+ x=(320-width)>>1;
+ y=Credits[i].endy;
+ US_ClippedPrint (x, y+4, &Credits[i].text[0]);
+ }
+}
+
+#define CREDITSTARTY 220
+//******************************************************************************
+//
+// WarpCreditString
+//
+//******************************************************************************
+
+extern boolean dopefish;
+void WarpCreditString ( int time, byte * back, int num, CreditType * Credits)
+{
+ int dy;
+ int cy;
+ int x;
+ int y;
+ int width;
+ int height;
+ boolean soundplayed;
+
+
+ LastScan = 0;
+
+ if (Credits[num].font==0)
+ CurrentFont=smallfont;
+ else
+ CurrentFont=tinyfont;
+ US_MeasureStr (&width, &height, "%s", &(Credits[num].text[0]));
+
+ x=(320-width)>>1;
+ y=Credits[num].endy;
+ dy=((y-CREDITSTARTY)<<16)/time;
+ cy=CREDITSTARTY<<16;
+
+ CalcTics();
+
+ soundplayed=false;
+
+ while (time>0)
+ {
+ DrawBackground ( back );
+ DrawPreviousCredits ( num, Credits );
+ if (Credits[num].font==0)
+ CurrentFont=smallfont;
+ else
+ CurrentFont=tinyfont;
+ US_ClippedPrint (x, (cy>>16)+4, &Credits[num].text[0]);
+ if ( ((cy>>16)<196) && (soundplayed==false))
+ {
+ if ((dopefish==true) && (SD_Started==true))
+ {
+ int snd;
+
+ do
+ {
+ snd=(RandomNumber("DoCredits",0)+RandomNumber("DoCredits",0))%MAXSOUNDS;
+ }
+ while (SD_SoundOkay ( snd ) == false);
+ SD_Play ( snd );
+ }
+ else
+ {
+// SD_Play ( SD_BAZOOKAFIRESND );
+#if (SHAREWARE == 0)
+ SD_Play ( SD_BAZOOKAFIRESND + (RandomNumber("DoCredits",1)%13) );
+#else
+ SD_Play ( SD_BAZOOKAFIRESND + (RandomNumber("DoCredits",1)%6) );
+#endif
+ soundplayed=true;
+ }
+ }
+ FlipPage();
+ CalcTics();
+ cy+=dy*tics;
+ time-=tics;
+ if (LastScan != 0)
+ break;
+ }
+}
+
+void DoCreditScreen ( void )
+{
+ int trilogo;
+ int time;
+ byte * bkgnd;
+ font_t * oldfont;
+ int i;
+ EnableScreenStretch();
+ viewwidth = 320;//MAXSCREENWIDTH;
+ viewheight = 200;//MAXSCREENHEIGHT;
+
+ bkgnd=SafeMalloc(800*linewidth);
+
+ trilogo=W_GetNumForName("trilogo");
+ VL_DrawPostPic (trilogo);
+// SetTextMode ( );
+
+ PrepareBackground ( bkgnd );
+
+ oldfont=CurrentFont;
+
+ for(i=0; i<NUMFIRSTCREDITMESSAGES; i++)
+ {
+ time = (CREDITSTARTY - FirstCredits[i].endy)*(VBLCOUNTER*1)/CREDITSTARTY;
+// time = VBLCOUNTER;
+ WarpCreditString ( time, bkgnd, i, FirstCredits );
+ IN_PumpEvents();
+// SD_Play ( SD_EXPLODESND );
+ if (LastScan !=0)
+ break;
+ }
+ i=NUMFIRSTCREDITMESSAGES;
+ DrawBackground ( bkgnd );
+ DrawPreviousCredits ( i, FirstCredits );
+ FlipPage();
+ IN_PumpEvents();
+
+ I_Delay(40);
+
+ for(i=0; i<NUMSECONDCREDITMESSAGES; i++)
+ {
+ time = (CREDITSTARTY - SecondCredits[i].endy)*(VBLCOUNTER/2)/CREDITSTARTY;
+// time = VBLCOUNTER;
+ WarpCreditString ( time, bkgnd, i, SecondCredits );
+ IN_PumpEvents();
+// SD_Play ( SD_EXPLODESND );
+ if (LastScan !=0)
+ break;
+ }
+ i=NUMSECONDCREDITMESSAGES;
+ DrawBackground ( bkgnd );
+ DrawPreviousCredits ( i, SecondCredits );
+ FlipPage();
+ IN_PumpEvents();
+
+ I_Delay(40);
+ MenuFadeOut();
+ VL_ClearVideo (0);
+
+ SafeFree(bkgnd);
+ CurrentFont=oldfont;
+}
+
+
+#define NUMSTORYLINES 16
+
+char * MicroStory[NUMSTORYLINES] =
+{
+ "You are a member of HUNT, the",
+ "High-Risk United Nations Taskforce.",
+ "Stranded on an island in the",
+ "Pacific, you must battle a master",
+ "of pyrotechnics, hundreds of",
+ "members of a death cult, and their",
+ "leader, El Oscuro.",
+ "\0",
+ "You must reach the transmitter",
+ "that is signalling the systematic",
+ "destruction of Los Angeles.",
+ "\0",
+ "If you fail, millions will die",
+ "and you will be tortured.",
+ "\0",
+ "So, you know, don't fail."
+};
+
+void DoMicroStoryScreen ( void )
+{
+ pic_t * pic;
+ int x,y;
+ int i;
+
+ VL_FadeOut (0, 255, 0, 0, 0, 20);
+
+ pic=(pic_t *)W_CacheLumpName("mmbk",PU_CACHE,Cvt_pic_t,1);
+ VWB_DrawPic (0, 0, pic);
+ CheckHolidays();
+
+ x=15;
+ y=30;
+
+ IFont = ( cfont_t * )W_CacheLumpName( "sifont", PU_CACHE, Cvt_cfont_t, 1);
+ for(i=0; i<NUMSTORYLINES; i++)
+ {
+ DrawIntensityString (x, y, MicroStory[i], 241);
+ y += 9;
+ }
+
+ FlipPage();
+ MenuFadeIn();
+ I_Delay (100);//240
+
+ VL_FadeOut (0, 255, 0, 0, 0, 20);
+}
+
+#ifndef DOS
+
+void DrawMenuPost (int height, byte * src, byte * buf)
+{
+ int frac = hp_startfrac;
+ while (height--) {
+ *buf = src[frac >> 16];
+
+ buf += linewidth;
+ frac += hp_srcstep;
+ }
+}
+
+void DrawMapPost (int height, byte * src, byte * buf)
+{
+ int frac = 0;
+ while (height--) {
+ *buf = src[frac >> 16];
+
+ buf += linewidth;
+ frac += hp_srcstep;
+ }
+}
+
+void DrawRotRow(int count, byte * dest, byte * src)
+{
+ unsigned eax, ecx, edx;
+// unsigned a, b, c,d;
+ byte * srctmp;
+ byte * desttmp;
+
+ ecx = mr_yfrac;
+ edx = mr_xfrac;
+
+ if ((iGLOBAL_SCREENWIDTH == 320)||(iG_masked==true))
+ {
+ while (count--) {
+ eax = edx >> 16;
+ if (eax < 256 && (ecx >> 16) < 512) {
+ eax = (eax << 9) | ((ecx << 7) >> (32-9));
+ } else {
+ eax = 0;
+ }
+
+ *dest++ = src[eax];
+
+ edx += mr_xstep;
+ ecx += mr_ystep;
+ }
+ } else if (iGLOBAL_SCREENWIDTH == 640) {
+ while (count--) {
+ eax = edx >> 16;
+ if (eax < (256*2.0) && (ecx >> 16) < (512*1.8)) {
+ eax = (eax << 10) | ((ecx << 6) >> (32-10));
+ } else {
+ eax = 0;
+ }
+
+ *dest++ = src[eax];
+
+ edx += mr_xstep;
+ ecx += mr_ystep;
+ }
+ } else if (iGLOBAL_SCREENWIDTH == 800) {
+
+
+
+ srctmp = src;
+ desttmp = dest;
+
+ desttmp -= (iGLOBAL_SCREENWIDTH*1);
+
+ ecx = mr_yfrac;
+ edx = mr_xfrac;
+ //count = 800
+//zxcv
+ while (count--) {
+ eax = edx >> 16;//edx=4146069504 eax=63264 edx/eax = 65536->0x10000
+
+ //a=(eax << 9); //=eax*512
+ //a=(eax << 7); //=eax*128
+ //a=512|128; = 640;
+ //SetTextMode ( );
+ //a=(ecx >> 16);//ecx=4102225920 a=62595 ecx/65536 = 62595
+
+ // Y-dir x-dir
+ if (eax < (256*2.5) && (ecx >> 16) < (512*2)) {
+ //eax = (eax << 9) | ((ecx << 7) >> (32-9));
+ eax = (eax << 10) | ((ecx << 6) >> (32-10));
+ /* eax = (eax * 512*2) ;
+ //(23)
+ eax += ((ecx ) >> (32-9));//ecx=196608
+ */
+ } else {
+ eax = 0;
+
+
+ }
+ //desttmp -= centeroffset;
+ *desttmp++ = srctmp[eax];
+ //*desttmp++ = srctmp[eax];
+
+ edx += mr_xstep;
+ ecx += mr_ystep;
+ }
+
+ }
+}
+
+void DrawMaskedRotRow(int count, byte * dest, byte * src)
+{
+ unsigned eax;
+ unsigned xfrac, yfrac;
+
+ xfrac = mr_xfrac;
+ yfrac = mr_yfrac;
+
+ while (count--) {
+ eax = xfrac >> 16;
+ if (eax < 256 && (yfrac >> 16) < 512) {
+ eax = (eax << 9) | ((yfrac << 7) >> (32-9));
+ } else {
+ eax = 0;
+ }
+
+ if (src[eax] != 0xff) *dest = src[eax];
+ dest++;
+
+ xfrac += mr_xstep;
+ yfrac += mr_ystep;
+ }
+}
+
+void DrawSkyPost (byte * buf, byte * src, int height)
+{
+#if 0
+// bna fix for missing sky by high res eg 800x600
+// when sky is >400 (max skyheight) then reverse mouintain to missing spot
+// there should be 200 line of mouintain (400+200) = 600 height lines
+// not the best solution but what it works
+
+ if (iGLOBAL_SCREENWIDTH > 320) {
+ // bna section start
+ //int n = 0;
+ int orgh = 0;//height;
+ if (height > 400) {
+ orgh=height;
+ }
+
+ while (height--) {
+ if ((orgh > 0)&&( height<(orgh-400))) {
+ src-=2;
+ *buf = shadingtable[*src];
+ } else {
+
+ *buf = shadingtable[*src];
+ }
+ buf += linewidth;
+ src++;
+ }
+ // bna section end
+ }
+ else
+#endif
+ {
+ int i = 0;
+ const byte *orig_src = src;
+ // org code
+ while (height--) {
+ *buf = shadingtable[*src];
+
+ buf += linewidth;
+ src = orig_src + (++i*200/iGLOBAL_SCREENHEIGHT);
+ }
+ //
+ }
+
+ /*
+ int lw = linewidth * 2;
+ int h = height;
+
+ while (h--) {
+ *(buf) = shadingtable[*src];
+ buf += lw;
+ *(buf) = shadingtable[*src];
+ buf += lw;
+
+ //buf += lw;
+ src++;
+
+ }*/
+}
+
+#define CEILINGCOLOR 24 //default color when no sky or floor
+#define FLOORCOLOR 32
+
+void RefreshClear (void)
+{
+ int start, base;
+
+ memset(spotvis, 0, sizeof(spotvis));
+
+ if (fandc) {
+ return;
+ }
+
+ start = min(centery, viewheight);
+
+ if (start > 0) {
+ VL_Bar(0, 0, iGLOBAL_SCREENHEIGHT, start, CEILINGCOLOR);
+ } else {
+ start = 0;
+ }
+
+ base = start;
+
+ start = min(viewheight-start, viewheight);
+ if (start > 0) {
+ VL_Bar(0, base, iGLOBAL_SCREENHEIGHT, start, FLOORCOLOR);
+ }
+}
+
+#endif
+
+#if 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef struct {
+ int x;
+ int y;
+ int angle;
+ int speed;
+ int color;
+ int endx;
+ int endy;
+ int plane;
+ int time;
+} ParticleType;
+
+#define NUMPARTICLES 300
+#define PARTICLETHINKTIME 5
+#define Fix(a) (a &= (FINEANGLES-1))
+ParticleType * Particle;
+int numparticles;
+
+//******************************************************************************
+//
+// InitializeParticles
+//
+//******************************************************************************
+
+void InitializeParticles (void)
+{
+ int i;
+ ParticleType * part;
+
+ Particle=(ParticleType *)SafeMalloc ( sizeof(ParticleType) * numparticles );
+ memset ( Particle, 0, sizeof(ParticleType) * numparticles );
+
+ for (i=0; i<numparticles; i++)
+ {
+ part=&Particle[i];
+ part->x=((RandomNumber("hello",0)*RandomNumber("hello",0))%viewwidth)<<16;
+ part->y=((RandomNumber("hello",0)*RandomNumber("hello",0))%viewheight)<<16;
+// part->x=(((RandomNumber("hello",0)*RandomNumber("hello",0))%(viewwidth-40)+20)<<16);
+// part->y=(((RandomNumber("hello",0)*RandomNumber("hello",0))%(viewheight-40)+20)<<16);
+ part->angle=(RandomNumber("hello",0)*RandomNumber("hello",0))%FINEANGLES;
+// part->speed=(RandomNumber("hello",0)%2)<<16;
+ part->speed=(1<<16)-1;
+ part->color=RandomNumber("hello",0);
+ part->endx=-1;
+ part->endy=-1;
+ part->plane=(part->x>>16)&3;
+ part->time=(RandomNumber("",0)%PARTICLETHINKTIME)+1;
+// part->color=255;
+ }
+}
+
+//******************************************************************************
+//
+// ShutdownParticles
+//
+//******************************************************************************
+
+void ShutdownParticles (void)
+{
+ SafeFree(Particle);
+}
+
+
+void AdjustParticleAngle(int maxadjust, int *currangle,int targetangle)
+{
+ int dangle,i,magangle;
+
+ for(i=0; i<maxadjust; i++)
+ {
+ dangle = *currangle - targetangle;
+
+ if (dangle)
+ {
+ magangle = abs(dangle);
+ if (magangle > (ANGLES/2))
+ {
+ if (dangle > 0)
+ (*currangle) ++;
+ else
+ (*currangle) --;
+ }
+ else
+ {
+ if (dangle > 0)
+ (*currangle) --;
+ else
+ (*currangle) ++;
+ }
+ Fix(*currangle);
+ }
+ }
+}
+
+//******************************************************************************
+//
+// UpdateParticles
+//
+//******************************************************************************
+
+//#define MAXADJUST (FINEANGLES/40)
+#define MAXADJUST (FINEANGLES/20)
+void UpdateParticles (int type)
+{
+ int i;
+ int dx,dy;
+ ParticleType * target;
+ ParticleType * part;
+
+ if (type==0)
+ {
+ for (i=0; i<numparticles-1; i++)
+ {
+ int angle;
+
+ part=&Particle[i];
+// target=&Particle[numparticles-1];
+// target=&Particle[i+1];
+ target=&Particle[(RandomNumber("",0)*RandomNumber("",0))%numparticles];
+ part->x+=-FixedMul (part->speed, costable[part->angle]);
+ part->y+= FixedMul (part->speed, sintable[part->angle]);
+ part->plane=(part->x>>16)&3;
+
+ dx = part->x - target->x;
+ dy = target->y - part->y;
+ if (dx && dy)
+ {
+ angle = atan2_appx(dx,dy);
+ AdjustParticleAngle(MAXADJUST,&(part->angle),angle);
+ }
+ }
+ part=&Particle[numparticles-1];
+ part->x+=-FixedMul (part->speed, costable[part->angle]);
+ part->y+= FixedMul (part->speed, sintable[part->angle]);
+ part->plane=(part->x>>16)&3;
+
+ dx=part->x>>16;
+ dy=part->y>>16;
+
+ if ( (dx<20) || (dx>(viewwidth-20)) )
+ {
+ if ( part->angle < (FINEANGLES/2) )
+ {
+ part->angle=FINEANGLES/2-part->angle;
+ Fix(part->angle);
+ }
+ else
+ {
+ part->angle=FINEANGLES-part->angle;
+ Fix(part->angle);
+ }
+ }
+ if ( (dy<20) || (dy>(viewheight-20)) )
+ {
+ part->angle=FINEANGLES-part->angle;
+ Fix(part->angle);
+ }
+ }
+ else
+ {
+ for (i=0; i<numparticles; i++)
+ {
+ int angle;
+
+ part=&Particle[i];
+ if ((part->x>>16)!=part->endx)
+ part->x+=-FixedMul (part->speed, costable[part->angle]);
+ else
+ part->x=part->endx<<16;
+ if ((part->y>>16)!=part->endy)
+ part->y+= FixedMul (part->speed, sintable[part->angle]);
+ else
+ part->y=part->endy<<16;
+ part->plane=(part->x>>16)&3;
+
+ part->time--;
+ if (part->time==0)
+ {
+ part->time=PARTICLETHINKTIME;
+ dx = part->x - (part->endx<<16);
+ dy = (part->endy<<16) - part->y;
+ if (dx && dy)
+ {
+ angle = atan2_appx(dx,dy);
+ AdjustParticleAngle(MAXADJUST,&(part->angle),angle);
+ }
+ }
+ }
+ }
+}
+
+//******************************************************************************
+//
+// DrawParticles
+//
+//******************************************************************************
+
+void DrawParticles (void)
+{
+ int i;
+ int dx,dy;
+ int plane;
+ ParticleType * part;
+
+ VL_ClearBuffer (bufferofs, 0);
+#ifdef DOS
+ for (plane=0; plane<4; plane++)
+#endif
+ {
+ VGAWRITEMAP(plane);
+ for (i=0; i<numparticles; i++)
+ {
+ part=&Particle[i];
+ if (part->plane!=plane)
+ continue;
+ dx=part->x>>16;
+ dy=part->y>>16;
+ if (dx<0) dx=0;
+ if (dx>=viewwidth) dx=viewwidth-1;
+ if (dy<0) dy=0;
+ if (dy>=viewheight) dy=viewheight-1;
+#ifdef DOS
+ *( (byte *) bufferofs + (dx>>2) + ylookup[dy] ) = part->color;
+#else
+ *( (byte *) bufferofs + dx + ylookup[dy] ) = part->color;
+#endif
+ }
+ }
+}
+
+void DrawParticleTemplate (void)
+{
+ byte pal[768];
+
+ viewwidth=320;
+ viewheight=200;
+ memcpy(&pal[0],W_CacheLumpName("ap_pal",PU_CACHE),768);
+ VL_NormalizePalette(&pal[0]);
+ SwitchPalette(&pal[0],35);
+ VL_ClearBuffer (bufferofs, 255);
+ DrawNormalSprite (0, 0, W_GetNumForName("ap_titl"));
+}
+
+void DrawAlternateParticleTemplate (void)
+{
+ viewwidth=320;
+ viewheight=200;
+ VL_ClearBuffer (bufferofs, 255);
+ DrawNormalSprite (0, 0, W_GetNumForName("LIFE_C1"));
+}
+
+int CountParticles (void)
+{
+ int plane,a,b;
+ int count;
+
+ count=0;
+#ifdef DOS
+ for (plane=0; plane<4; plane++)
+#endif
+ {
+ VGAREADMAP(plane);
+ for (a=0; a<200; a++)
+ {
+#ifdef DOS
+ for (b=0; b<80; b++)
+#else
+ for (b=0; b<320; b++)
+#endif
+ {
+ if (*((byte *)bufferofs+(a*linewidth)+b)!=255)
+ count++;
+ }
+ }
+ }
+ return count;
+}
+
+void AssignParticles (void)
+{
+ int plane,a,b;
+ byte pixel;
+ ParticleType * part;
+
+ part=&Particle[0];
+
+#ifdef DOS
+ for (plane=0; plane<4; plane++)
+#endif
+ {
+ VGAREADMAP(plane);
+ for (a=0; a<200; a++)
+ {
+#ifdef DOS
+ for (b=0; b<80; b++)
+#else
+ for (b=0; b<320; b++)
+#endif
+ {
+ pixel = *((byte *)bufferofs+(a*linewidth)+b);
+ if (pixel!=255)
+ {
+#ifdef DOS
+ part->endx=plane+(b<<2);
+#else
+ part->endx=b;
+#endif
+ part->endy=a;
+ part->color=pixel;
+ part++;
+ }
+ }
+ }
+ }
+}
+
+//******************************************************************************
+//
+// ParticleIntro
+//
+//******************************************************************************
+
+void ParticleIntro (void)
+{
+ int i,j;
+
+
+ SetViewSize (MAXVIEWSIZES-1);
+ numparticles=NUMPARTICLES;
+ DrawAlternateParticleTemplate ();
+// DrawParticleTemplate ();
+ numparticles=CountParticles ();
+ InitializeParticles ();
+ AssignParticles();
+// numparticles>>=1;
+
+ CalcTics();
+ CalcTics();
+ LastScan=0;
+ for (i=0; i<VBLCOUNTER*15; i+=tics)
+ {
+ DrawParticles();
+ FlipPage();
+ for (j=0; j<tics; j++)
+ {
+ UpdateParticles(0);
+ }
+ CalcTics();
+ if ((LastScan) || IN_GetMouseButtons())
+ break;;
+ }
+ LastScan=0;
+ for (i=0; i<VBLCOUNTER*15; i+=tics)
+ {
+ DrawParticles();
+ FlipPage();
+ for (j=0; j<tics; j++)
+ {
+ UpdateParticles(1);
+ }
+ CalcTics();
+ if ((LastScan) || IN_GetMouseButtons())
+ break;;
+ }
+ ShutdownParticles ();
+}
+
+#endif
+
--- /dev/null
+++ b/rott/rt_draw.h
@@ -1,0 +1,127 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_draw_public
+#define _rt_draw_public
+
+//***************************************************************************
+//
+// RT_DRAW.C - Draw-o-rama
+//
+//***************************************************************************
+
+
+#define MAXVISIBLE 256
+
+extern int whereami;
+
+extern byte * shadingtable; // Shading table for DrawPost
+
+typedef struct
+{
+ int viewheight;
+ int viewx;
+ int shapenum;
+ int altshapenum;
+ int shapesize;
+ int x1,x2,h1,h2;
+ int texturestart;
+ int textureend;
+ byte * colormap;
+
+} visobj_t;
+
+
+extern word tilemap[MAPSIZE][MAPSIZE]; // wall values only
+extern byte spotvis[MAPSIZE][MAPSIZE];
+
+extern int tics;
+extern int wstart;
+extern int fandc;
+
+//
+// math tables
+//
+extern short tantable[FINEANGLES];
+extern fixed sintable[FINEANGLES+FINEANGLEQUAD+1];
+extern fixed *costable;
+
+//
+// refresh variables
+//
+
+extern fixed viewx,viewy; // the focal point
+extern int viewangle;
+extern fixed viewsin,viewcos;
+
+//
+// ray tracing variables
+//
+
+extern visobj_t vislist[MAXVISIBLE];
+extern visobj_t *visptr,*visstep,*farthest;
+
+extern long xintercept,yintercept;
+extern byte mapseen[MAPSIZE][MAPSIZE];
+extern unsigned long * lights;
+
+extern int hp_startfrac;
+extern int hp_srcstep;
+extern int levelheight;
+extern int maxheight;
+extern int nominalheight;
+
+extern int actortime;
+extern int drawtime;
+extern int c_startx;
+extern int c_starty;
+
+extern const int dirangle8[9];
+extern const int dirangle16[16];
+extern int firstcoloffset;
+
+//=========================== macros =============================
+
+#define LightSourceAt(x,y) (*(lights+((x)<<7)+(y)))
+#define SetLight(x,y,level) (LightSourceAt((x),(y))|=(unsigned long)(level))
+
+//=========================== functions =============================
+
+void BuildTables (void);
+void CalcTics (void);
+void ThreeDRefresh (void);
+void FlipPage ( void );
+void TurnShakeOff( void );
+void AdaptDetail ( void );
+int CalcHeight (void);
+void DoLoadGameSequence( void );
+void RotateBuffer (int startangle, int endangle, int startscale, int endscale, int time);
+void ApogeeTitle (void);
+void DopefishTitle (void);
+void RotationFun (void);
+void GetRainBoundingBox (int * xmin, int * xmax, int * ymin, int * ymax);
+void StartupScreenSaver ( void );
+void ShutdownScreenSaver ( void );
+void UpdateScreenSaver ( void );
+void DoEndCinematic ( void );
+void DoCreditScreen ( void );
+void DoMicroStoryScreen ( void );
+void DoInBetweenCinematic (int yoffset, int lump, int delay, char * string );
+
+#endif
--- /dev/null
+++ b/rott/rt_err.c
@@ -1,0 +1,336 @@
+const unsigned char ROTT_ERR[4000] = {
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC9, 0x1B, 0xCD, 0x1B, 0xB5, 0x1B,
+ 0x1E, 0x9C, 0x52, 0x1E, 0x69, 0x1E, 0x73, 0x1E, 0x65, 0x1E, 0x20, 0x1E,
+ 0x6F, 0x1E, 0x66, 0x1E, 0x20, 0x1E, 0x74, 0x1E, 0x68, 0x1E, 0x65, 0x1E,
+ 0x20, 0x1E, 0x54, 0x1E, 0x72, 0x1E, 0x69, 0x1E, 0x61, 0x1E, 0x64, 0x1E,
+ 0x20, 0x1E, 0x45, 0x1E, 0x72, 0x1E, 0x72, 0x1E, 0x6F, 0x1E, 0x72, 0x1E,
+ 0x21, 0x1E, 0x1E, 0x9C, 0xC6, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xB5, 0x1B, 0x76, 0x19, 0x53, 0x19, 0x31, 0x19, 0x2E, 0x19, 0x30, 0x19,
+ 0xC6, 0x1B, 0xCD, 0x1B, 0xBB, 0x1B, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xBA, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0xBA, 0x1B, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xBA, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0xBA, 0x1B, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xBA, 0x1B, 0x20, 0x1B, 0x50, 0x1B,
+ 0x6C, 0x1B, 0x65, 0x1B, 0x61, 0x1B, 0x73, 0x1B, 0x65, 0x1B, 0x20, 0x1B,
+ 0x72, 0x1B, 0x75, 0x1B, 0x6E, 0x1B, 0x20, 0x1B, 0x52, 0x1B, 0x4F, 0x1B,
+ 0x54, 0x1B, 0x54, 0x1B, 0x48, 0x1B, 0x45, 0x1B, 0x4C, 0x1B, 0x50, 0x1B,
+ 0x2E, 0x1B, 0x45, 0x1B, 0x58, 0x1B, 0x45, 0x1B, 0x20, 0x1B, 0x66, 0x1B,
+ 0x6F, 0x1B, 0x72, 0x1B, 0x20, 0x1B, 0x6D, 0x1B, 0x6F, 0x1B, 0x72, 0x1B,
+ 0x65, 0x1B, 0x2C, 0x1B, 0x20, 0x1B, 0x77, 0x1B, 0x65, 0x1B, 0x6C, 0x1B,
+ 0x6C, 0x1B, 0x2C, 0x1B, 0x20, 0x1B, 0x68, 0x1F, 0x65, 0x1F, 0x6C, 0x1F,
+ 0x70, 0x1F, 0x66, 0x1F, 0x75, 0x1F, 0x6C, 0x1F, 0x20, 0x1B, 0x69, 0x1B,
+ 0x6E, 0x1B, 0x66, 0x1B, 0x6F, 0x1B, 0x72, 0x1B, 0x6D, 0x1B, 0x61, 0x1B,
+ 0x74, 0x1B, 0x69, 0x1B, 0x6F, 0x1B, 0x6E, 0x1B, 0x2E, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0xBA, 0x1B, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC8, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xBC, 0x1B, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC9, 0x1B,
+ 0xCD, 0x1B, 0xB5, 0x1B, 0x1E, 0x9C, 0x55, 0x1E, 0x68, 0x1E, 0x2C, 0x1E,
+ 0x20, 0x1E, 0x6F, 0x1E, 0x68, 0x1E, 0x2E, 0x1E, 0x20, 0x1E, 0x4D, 0x1E,
+ 0x65, 0x1E, 0x6D, 0x1E, 0x6F, 0x1E, 0x72, 0x1E, 0x79, 0x1E, 0x20, 0x1E,
+ 0x70, 0x1E, 0x72, 0x1E, 0x6F, 0x1E, 0x62, 0x1E, 0x6C, 0x1E, 0x65, 0x1E,
+ 0x6D, 0x1E, 0x73, 0x1E, 0x2E, 0x1E, 0x1E, 0x9C, 0xC6, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xB5, 0x1B, 0x76, 0x19, 0x53, 0x19, 0x31, 0x19,
+ 0x2E, 0x19, 0x30, 0x19, 0xC6, 0x1B, 0xCD, 0x1B, 0xBB, 0x1B, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xBA, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0xBA, 0x1B, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xBA, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x59, 0x1B, 0x6F, 0x1B, 0x75, 0x1B, 0x20, 0x1B, 0x64, 0x1B,
+ 0x6F, 0x1B, 0x20, 0x1B, 0x6E, 0x1B, 0x6F, 0x1B, 0x74, 0x1B, 0x20, 0x1B,
+ 0x68, 0x1B, 0x61, 0x1B, 0x76, 0x1B, 0x65, 0x1B, 0x20, 0x1B, 0x65, 0x1B,
+ 0x6E, 0x1B, 0x6F, 0x1B, 0x75, 0x1B, 0x67, 0x1B, 0x68, 0x1B, 0x20, 0x1B,
+ 0x6D, 0x1B, 0x65, 0x1B, 0x6D, 0x1B, 0x6F, 0x1B, 0x72, 0x1B, 0x79, 0x1B,
+ 0x20, 0x1B, 0x74, 0x1B, 0x6F, 0x1B, 0x20, 0x1B, 0x72, 0x1B, 0x75, 0x1B,
+ 0x6E, 0x1B, 0x20, 0x1B, 0x52, 0x1F, 0x69, 0x1F, 0x73, 0x1F, 0x65, 0x1F,
+ 0x20, 0x1F, 0x6F, 0x1F, 0x66, 0x1F, 0x20, 0x1F, 0x74, 0x1F, 0x68, 0x1F,
+ 0x65, 0x1F, 0x20, 0x1F, 0x54, 0x1F, 0x72, 0x1F, 0x69, 0x1F, 0x61, 0x1F,
+ 0x64, 0x1F, 0x2E, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0xBA, 0x1B, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xBA, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x53, 0x1B, 0x6F, 0x1B, 0x6D, 0x1B,
+ 0x65, 0x1B, 0x20, 0x1B, 0x74, 0x1B, 0x68, 0x1B, 0x69, 0x1B, 0x6E, 0x1B,
+ 0x67, 0x1B, 0x73, 0x1B, 0x20, 0x1B, 0x79, 0x1B, 0x6F, 0x1B, 0x75, 0x1B,
+ 0x20, 0x1B, 0x6D, 0x1B, 0x69, 0x1B, 0x67, 0x1B, 0x68, 0x1B, 0x74, 0x1B,
+ 0x20, 0x1B, 0x74, 0x1B, 0x72, 0x1B, 0x79, 0x1B, 0x20, 0x1B, 0x74, 0x1B,
+ 0x6F, 0x1B, 0x20, 0x1B, 0x63, 0x1B, 0x6F, 0x1B, 0x72, 0x1B, 0x72, 0x1B,
+ 0x65, 0x1B, 0x63, 0x1B, 0x74, 0x1B, 0x20, 0x1B, 0x74, 0x1B, 0x68, 0x1B,
+ 0x69, 0x1B, 0x73, 0x1B, 0x20, 0x1B, 0x73, 0x1B, 0x69, 0x1B, 0x74, 0x1B,
+ 0x75, 0x1B, 0x61, 0x1B, 0x74, 0x1B, 0x69, 0x1B, 0x6F, 0x1B, 0x6E, 0x1B,
+ 0x3A, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0xBA, 0x1B, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xBA, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0xBA, 0x1B, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xBA, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x07, 0x1B, 0x20, 0x1B,
+ 0x75, 0x1B, 0x6E, 0x1B, 0x6C, 0x1B, 0x6F, 0x1B, 0x61, 0x1B, 0x64, 0x1B,
+ 0x20, 0x1B, 0x61, 0x1B, 0x6E, 0x1B, 0x79, 0x1B, 0x20, 0x1B, 0x54, 0x1B,
+ 0x53, 0x1B, 0x52, 0x1B, 0x73, 0x1B, 0x20, 0x1B, 0x79, 0x1B, 0x6F, 0x1B,
+ 0x75, 0x1B, 0x20, 0x1B, 0x68, 0x1B, 0x61, 0x1B, 0x76, 0x1B, 0x65, 0x1B,
+ 0x20, 0x1B, 0x69, 0x1B, 0x6E, 0x1B, 0x20, 0x1B, 0x6D, 0x1B, 0x65, 0x1B,
+ 0x6D, 0x1B, 0x6F, 0x1B, 0x72, 0x1B, 0x79, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0xBA, 0x1B, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xBA, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x07, 0x1B, 0x20, 0x1B, 0x64, 0x1B, 0x6F, 0x1B, 0x20, 0x1B, 0x6E, 0x1B,
+ 0x6F, 0x1B, 0x74, 0x1B, 0x20, 0x1B, 0x6C, 0x1B, 0x6F, 0x1B, 0x61, 0x1B,
+ 0x64, 0x1B, 0x20, 0x1B, 0x53, 0x1B, 0x4D, 0x1B, 0x41, 0x1B, 0x52, 0x1B,
+ 0x54, 0x1B, 0x44, 0x1B, 0x52, 0x1B, 0x56, 0x1B, 0x2E, 0x1B, 0x45, 0x1B,
+ 0x58, 0x1B, 0x45, 0x1B, 0x20, 0x1B, 0x69, 0x1B, 0x6E, 0x1B, 0x20, 0x1B,
+ 0x79, 0x1B, 0x6F, 0x1B, 0x75, 0x1B, 0x72, 0x1B, 0x20, 0x1B, 0x41, 0x1B,
+ 0x55, 0x1B, 0x54, 0x1B, 0x4F, 0x1B, 0x45, 0x1B, 0x58, 0x1B, 0x45, 0x1B,
+ 0x43, 0x1B, 0x2E, 0x1B, 0x42, 0x1B, 0x41, 0x1B, 0x54, 0x1B, 0x20, 0x1B,
+ 0x66, 0x1B, 0x69, 0x1B, 0x6C, 0x1B, 0x65, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0xBA, 0x1B, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xBA, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x07, 0x1B, 0x20, 0x1B, 0x64, 0x1B, 0x6F, 0x1B,
+ 0x20, 0x1B, 0x6E, 0x1B, 0x6F, 0x1B, 0x74, 0x1B, 0x20, 0x1B, 0x62, 0x1B,
+ 0x6F, 0x1B, 0x6F, 0x1B, 0x74, 0x1B, 0x20, 0x1B, 0x77, 0x1B, 0x69, 0x1B,
+ 0x74, 0x1B, 0x68, 0x1B, 0x20, 0x1B, 0x61, 0x1B, 0x20, 0x1B, 0x6D, 0x1B,
+ 0x65, 0x1B, 0x6D, 0x1B, 0x6F, 0x1B, 0x72, 0x1B, 0x79, 0x1B, 0x20, 0x1B,
+ 0x6D, 0x1B, 0x61, 0x1B, 0x6E, 0x1B, 0x61, 0x1B, 0x67, 0x1B, 0x65, 0x1B,
+ 0x72, 0x1B, 0x20, 0x1B, 0x28, 0x1B, 0x6C, 0x1B, 0x69, 0x1B, 0x6B, 0x1B,
+ 0x65, 0x1B, 0x20, 0x1B, 0x45, 0x1B, 0x4D, 0x1B, 0x4D, 0x1B, 0x33, 0x1B,
+ 0x38, 0x1B, 0x36, 0x1B, 0x29, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0xBA, 0x1B, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xBA, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x07, 0x1B, 0x20, 0x1B,
+ 0x64, 0x1B, 0x6F, 0x1B, 0x20, 0x1B, 0x6E, 0x1B, 0x6F, 0x1B, 0x74, 0x1B,
+ 0x20, 0x1B, 0x6C, 0x1B, 0x6F, 0x1B, 0x61, 0x1B, 0x64, 0x1B, 0x20, 0x1B,
+ 0x61, 0x1B, 0x6E, 0x1B, 0x79, 0x1B, 0x20, 0x1B, 0x64, 0x1B, 0x69, 0x1B,
+ 0x73, 0x1B, 0x6B, 0x1B, 0x20, 0x1B, 0x63, 0x1B, 0x6F, 0x1B, 0x6D, 0x1B,
+ 0x70, 0x1B, 0x72, 0x1B, 0x65, 0x1B, 0x73, 0x1B, 0x73, 0x1B, 0x69, 0x1B,
+ 0x6F, 0x1B, 0x6E, 0x1B, 0x20, 0x1B, 0x64, 0x1B, 0x72, 0x1B, 0x69, 0x1B,
+ 0x76, 0x1B, 0x65, 0x1B, 0x72, 0x1B, 0x73, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0xBA, 0x1B, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xBA, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x07, 0x1B, 0x20, 0x1B, 0x72, 0x1B, 0x75, 0x1B, 0x6E, 0x1B, 0x20, 0x1B,
+ 0x52, 0x1B, 0x4F, 0x1B, 0x54, 0x1B, 0x54, 0x1B, 0x48, 0x1B, 0x45, 0x1B,
+ 0x4C, 0x1B, 0x50, 0x1B, 0x2E, 0x1B, 0x45, 0x1B, 0x58, 0x1B, 0x45, 0x1B,
+ 0x20, 0x1B, 0x66, 0x1B, 0x6F, 0x1B, 0x72, 0x1B, 0x20, 0x1B, 0x69, 0x1B,
+ 0x6E, 0x1B, 0x66, 0x1B, 0x6F, 0x1B, 0x72, 0x1B, 0x6D, 0x1B, 0x61, 0x1B,
+ 0x74, 0x1B, 0x69, 0x1B, 0x6F, 0x1B, 0x6E, 0x1B, 0x20, 0x1B, 0x6F, 0x1B,
+ 0x6E, 0x1B, 0x20, 0x1B, 0x68, 0x1B, 0x6F, 0x1B, 0x77, 0x1B, 0x20, 0x1B,
+ 0x74, 0x1B, 0x6F, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0xBA, 0x1B, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xBA, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x61, 0x1B, 0x6C, 0x1B,
+ 0x6C, 0x1B, 0x65, 0x1B, 0x76, 0x1B, 0x69, 0x1B, 0x61, 0x1B, 0x74, 0x1B,
+ 0x65, 0x1B, 0x20, 0x1B, 0x74, 0x1B, 0x68, 0x1B, 0x69, 0x1B, 0x73, 0x1B,
+ 0x20, 0x1B, 0x70, 0x1B, 0x72, 0x1B, 0x6F, 0x1B, 0x62, 0x1B, 0x6C, 0x1B,
+ 0x65, 0x1B, 0x6D, 0x1B, 0x20, 0x1B, 0x28, 0x1B, 0x73, 0x1B, 0x65, 0x1B,
+ 0x61, 0x1B, 0x72, 0x1B, 0x63, 0x1B, 0x68, 0x1B, 0x20, 0x1B, 0x66, 0x1B,
+ 0x6F, 0x1B, 0x72, 0x1B, 0x20, 0x1B, 0x22, 0x1B, 0x4D, 0x1B, 0x65, 0x1B,
+ 0x6D, 0x1B, 0x6F, 0x1B, 0x72, 0x1B, 0x79, 0x1B, 0x20, 0x1B, 0x50, 0x1B,
+ 0x72, 0x1B, 0x6F, 0x1B, 0x62, 0x1B, 0x6C, 0x1B, 0x65, 0x1B, 0x6D, 0x1B,
+ 0x73, 0x1B, 0x22, 0x1B, 0x29, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0xBA, 0x1B, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xBA, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0xBA, 0x1B, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xBA, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x54, 0x1B, 0x68, 0x1B, 0x61, 0x1B,
+ 0x74, 0x1B, 0x27, 0x1B, 0x73, 0x1B, 0x20, 0x1B, 0x61, 0x1B, 0x62, 0x1B,
+ 0x6F, 0x1B, 0x75, 0x1B, 0x74, 0x1B, 0x20, 0x1B, 0x61, 0x1B, 0x6C, 0x1B,
+ 0x6C, 0x1B, 0x20, 0x1B, 0x77, 0x1B, 0x65, 0x1B, 0x20, 0x1B, 0x63, 0x1B,
+ 0x61, 0x1B, 0x6E, 0x1B, 0x20, 0x1B, 0x66, 0x1B, 0x69, 0x1B, 0x74, 0x1B,
+ 0x20, 0x1B, 0x69, 0x1B, 0x6E, 0x1B, 0x20, 0x1B, 0x74, 0x1B, 0x68, 0x1B,
+ 0x69, 0x1B, 0x73, 0x1B, 0x20, 0x1B, 0x73, 0x1B, 0x71, 0x1B, 0x75, 0x1B,
+ 0x61, 0x1B, 0x72, 0x1B, 0x65, 0x1B, 0x2E, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x54, 0x1B, 0x72, 0x1B, 0x79, 0x1B, 0x20, 0x1B, 0x52, 0x1B, 0x4F, 0x1B,
+ 0x54, 0x1B, 0x54, 0x1B, 0x48, 0x1B, 0x45, 0x1B, 0x4C, 0x1B, 0x50, 0x1B,
+ 0x21, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0xBA, 0x1B, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xBA, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B, 0x20, 0x1B,
+ 0xBA, 0x1B, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC8, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B, 0xCD, 0x1B,
+ 0xCD, 0x1B, 0xCD, 0x1B, 0xBC, 0x1B, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04, 0xC4, 0x04,
+ 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07,
+ 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07,
+ 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07,
+ 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07,
+ 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07,
+ 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07,
+ 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07,
+ 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07,
+ 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07,
+ 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07,
+ 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07,
+ 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07,
+ 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07, 0x20, 0x07,
+ 0x20, 0x07, 0x20, 0x07
+};
--- /dev/null
+++ b/rott/rt_error.c
@@ -1,0 +1,412 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include <dos.h>
+#include <errno.h>
+#include <io.h>
+#include <stdio.h>
+#include <conio.h>
+#include <stdarg.h>
+#include <mem.h>
+#include <ctype.h>
+#include "rt_def.h"
+#include "rt_str.h"
+#include "rt_error.h"
+#include "rt_menu.h"
+#include "isr.h"
+#include "w_wad.h"
+#include "z_zone.h"
+#include "rt_vid.h"
+#include "rt_util.h"
+#include "modexlib.h"
+//MED
+#include "memcheck.h"
+
+
+//*****************************************************************************
+//
+// HARD ERROR ROUTINES
+//
+//****************************************************************************
+
+#define WINDOWUX 7
+#define WINDOWUY 76
+#define WINDOWLX 138
+#define WINDOWLY 158
+
+#define MESSAGEBOXCOLOR 166
+
+
+#define DISKERROR 0x4000 // bit 15 (of deverr)
+#define IGNOREAVAILABLE 0x1000 // bit 13 (bit 14 isn't used)
+#define RETRYAVAILABLE 0x800 // bit 12
+#define FAILAVAILABLE 0x400 // bit 11
+#define LOCATION 0x300 // bit 10 and 9
+#define READWRITEERROR 0x80 // bit 8
+#define DRIVEOFERROR 0x0F // low-order byte
+
+#define DIVISIONINT 0x00
+
+// Globals
+
+boolean DivisionError = false;
+
+// Statics
+
+
+static char ErrorCodes[13][25] =
+{
+ "Write-protected disk\0",
+ "Unknown unit\0",
+ "Drive not ready\0",
+ "Unknown command\0",
+ "CRC error in data\0",
+ "Bad drive struct length\0",
+ "Seek error\0",
+ "Unknown media type\0",
+ "Sector not found\0",
+ "Printer out of paper\0",
+ "Write fault\0",
+ "Read fault\0",
+ "General failure\0"
+};
+
+static char Drives[7][3] =
+{
+ "A\0",
+ "B\0",
+ "C\0",
+ "D\0",
+ "E\0",
+ "F\0",
+ "G\0"
+};
+
+static char Locations[4][11] =
+{
+ "MS-DOS\0",
+ "FAT\0",
+ "Directory\0",
+ "Data area\0"
+};
+
+static char ReadWrite[2][6] =
+{
+ "Read\0",
+ "Write\0"
+};
+
+static boolean ErrorHandlerStarted=false;
+void (__interrupt __far *olddivisr) () = NULL;
+
+//******************************************************************************
+//
+// UL_UserMessage ()
+//
+//******************************************************************************
+
+void UL_UserMessage (int x, int y, char *str, ...) __attribute__((format(printf,3,4)))
+{
+ va_list strptr;
+ char buf[128];
+ int width, height;
+
+ memset (&buf[0], 0, sizeof (buf));
+ va_start (strptr, str);
+ vsprintf (&buf[0], str, strptr);
+ va_end (strptr);
+
+ if ( *(byte *)0x449 == 0x13)
+ {
+ CurrentFont = tinyfont;
+
+ WindowW=160;
+ WindowH=100;
+ WindowX=80;
+ WindowY=50;
+
+ US_MeasureStr (&width, &height, &buf[0]);
+
+ width += (CurrentFont->width[1] << 1);
+ height += (CurrentFont->height << 1);
+
+ VL_Bar (x, y, WindowW-2, WindowH, MESSAGEBOXCOLOR);
+
+ PrintX = x+CurrentFont->width[1];
+ PrintY = y+CurrentFont->height;
+
+ US_CPrint (&buf[0]);
+
+ displayofs=bufferofs;
+
+ OUTP(CRTC_INDEX, CRTC_STARTHIGH);
+ OUTP(CRTC_DATA,((displayofs&0x0000ffff)>>8));
+
+
+ bufferofs += screensize;
+ if (bufferofs > page3start)
+ bufferofs = page1start;
+ }
+ else
+ printf("%s\n",&buf[0]);
+}
+
+//****************************************************************************
+//
+// UL_GeneralError ()
+//
+//****************************************************************************
+
+int UL_GeneralError (int code)
+{
+ boolean done = false;
+ int retval = 0;
+
+ UL_UserMessage (80, 50, "Device Error!\n%s.\n \n(A)bort (R)etry\n",
+ ErrorCodes[code]);
+
+ if (KeyboardStarted==true)
+ {
+ while (!done)
+ {
+ if (Keyboard[sc_A])
+ {
+ retval = 1;
+ done = true;
+
+ while (Keyboard[sc_A])
+ ;
+ }
+ else if (Keyboard[sc_R])
+ {
+ retval = 0;
+ done = true;
+
+ while (Keyboard[sc_R])
+ ;
+ }
+ }
+ }
+ else
+ {
+ while (!done)
+ {
+ if (kbhit())
+ {
+ char ch;
+
+ ch=toupper(getch());
+ if (ch=='A')
+ {
+ retval = 1;
+ done = true;
+ }
+ else if (ch=='R')
+ {
+ retval = 0;
+ done = true;
+ }
+ }
+ }
+ }
+
+
+ return (retval);
+}
+
+
+//****************************************************************************
+//
+// UL_DriveError ()
+//
+//****************************************************************************
+
+int UL_DriveError (int code, int location, int rwerror, int whichdrive)
+{
+ boolean done = false;
+ int retval = 0;
+
+ UL_UserMessage (80, 50,
+ "Drive Error!\n%s.\nOn drive %s.\nLocation: %s.\n%s error.\n(A)bort (R)etry\n",
+ ErrorCodes[code], Drives[whichdrive],
+ Locations[location], ReadWrite[rwerror]);
+
+ if (KeyboardStarted==true)
+ {
+ while (!done)
+ {
+ if (Keyboard[sc_A])
+ {
+ retval = 1;
+ done = true;
+
+ while (Keyboard[sc_A])
+ ;
+ }
+ else if (Keyboard[sc_R])
+ {
+ retval = 0;
+ done = true;
+
+ while (Keyboard[sc_R])
+ ;
+ }
+ }
+ }
+ else
+ {
+ while (!done)
+ {
+ if (kbhit())
+ {
+ char ch;
+
+ ch=toupper(getch());
+ if (ch=='A')
+ {
+ retval = 1;
+ done = true;
+ }
+ else if (ch=='R')
+ {
+ retval = 0;
+ done = true;
+ }
+ }
+ }
+ }
+
+ return (retval);
+}
+
+
+//****************************************************************************
+//
+// UL_harderr ()
+//
+//****************************************************************************
+
+int __far UL_harderr (unsigned deverr, unsigned errcode, unsigned far *devhdr)
+{
+ int DiskError = 0; // Indicates if it was a disk error
+ int IgnoreAvail = 0; // if "ignore" response is available
+ int RetryAvail = 0; // if "retry" response is available
+ int FailAvail = 0; // if "fail" response is available
+ byte ErrorLocation = 0; // Location of error
+ byte RWerror = 0; // Read/Write error (0 == read, 1 == write)
+ byte whichDrive = 0; // Drive the error is on (0 == A, 1 == B, ...)
+ int action;
+
+ unsigned temp;
+ temp = *devhdr;
+
+ // Check errors
+ DiskError = (deverr & DISKERROR);
+ IgnoreAvail = (deverr & IGNOREAVAILABLE);
+ RetryAvail = (deverr & RETRYAVAILABLE);
+ FailAvail = (deverr & FAILAVAILABLE);
+ ErrorLocation = ((deverr & LOCATION) >> 8);
+ RWerror = (deverr & READWRITEERROR);
+
+ if (DiskError == 0)
+ action = UL_GeneralError (errcode);
+ else
+ action = UL_DriveError (errcode, ErrorLocation, RWerror, whichDrive);
+
+ if (action)
+ Error ("USER BREAK : ROTT aborted.\n");
+ return (_HARDERR_RETRY);
+}
+
+
+//****************************************************************************
+//
+// UL_DivisionISR ()
+//
+//****************************************************************************
+
+extern byte * colormap;
+
+void __interrupt __far UL_DivisionISR ( void )
+{
+// acknowledge the interrupt
+
+ SetBorderColor (*(colormap+(((100-10)>>2)<<8)+160));
+ DivisionError = true;
+ OUTP (0x20, 0x20);
+}
+
+
+//****************************************************************************
+//
+// UL_ErrorStartup ()
+//
+//****************************************************************************
+
+void UL_ErrorStartup ( void )
+{
+ if (ErrorHandlerStarted==true)
+ return;
+ ErrorHandlerStarted=true;
+ _harderr (UL_harderr); // Install hard error handler
+ UL_StartupDivisionByZero();
+}
+
+//****************************************************************************
+//
+// UL_ErrorShutdown ()
+//
+//****************************************************************************
+
+void UL_ErrorShutdown ( void )
+{
+ if (ErrorHandlerStarted==false)
+ return;
+ ErrorHandlerStarted=false;
+ UL_ShutdownDivisionByZero();
+}
+
+
+/*
+===============
+=
+= UL_StartupDivisionByZero
+=
+===============
+*/
+
+void UL_StartupDivisionByZero ( void )
+{
+ olddivisr = _dos_getvect(DIVISIONINT);
+ _dos_setvect (DIVISIONINT, UL_DivisionISR);
+}
+
+/*
+===============
+=
+= UL_ShutdownDivisionByZero
+=
+===============
+*/
+
+void UL_ShutdownDivisionByZero ( void )
+{
+ _dos_setvect (DIVISIONINT, olddivisr);
+}
+
--- /dev/null
+++ b/rott/rt_error.h
@@ -1,0 +1,28 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_error_public
+#define _rt_error_public
+
+extern boolean DivisionError;
+
+void UL_ErrorStartup ( void );
+void UL_ErrorShutdown ( void );
+
+#endif
--- /dev/null
+++ b/rott/rt_fc_a.h
@@ -1,0 +1,42 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_fc_a_public
+#define _rt_fc_a_public
+
+//***************************************************************************
+//
+// RT_FC_A.ASM - Maprow stuff for floor and ceiling
+//
+//***************************************************************************
+
+void DrawSkyPost (byte * buf, byte * src, int height);
+void DrawRow(int count, byte * dest, byte * src);
+void DrawRotRow(int count, byte * dest, byte * src);
+void DrawMaskedRotRow(int count, byte * dest, byte * src);
+
+#if (defined __WATCOMC__)
+#pragma aux DrawSkyPost parm [EDI] [ESI] [ECX] modify exact [eax ecx edx edi esi ebx]
+#pragma aux DrawRow parm [ECX] [EDI] [ESI] modify exact [eax ebx ecx edx esi edi]
+#pragma aux DrawRotRow parm [ECX] [EDI] [ESI] modify exact [eax ebx ecx edx esi edi]
+#pragma aux DrawMaskedRotRow parm [ECX] [EDI] [ESI] modify exact [eax ebx ecx edx esi edi]
+#endif
+
+#endif
+
--- /dev/null
+++ b/rott/rt_floor.c
@@ -1,0 +1,749 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// RT_FLOOR.C
+
+#ifdef DOS
+#include <conio.h>
+#endif
+
+#include "rt_def.h"
+#include "watcom.h"
+#include "rt_floor.h"
+#include "rt_fc_a.h"
+#include "_rt_floo.h"
+#include "rt_draw.h"
+#include "rt_util.h"
+#include "engine.h"
+#include "rt_main.h"
+#include "w_wad.h"
+#include "z_zone.h"
+#include "rt_view.h"
+#include "rt_ted.h"
+#include "rt_cfg.h"
+#include "rt_actor.h"
+#include <string.h>
+#include "isr.h"
+#include "modexlib.h"
+#include "rt_playr.h"
+#include "rt_sound.h"
+#include "rt_rand.h"
+//MED
+#include "memcheck.h"
+
+/*
+=============================================================================
+
+Global Variables GLOBAL VARIABLES
+
+=============================================================================
+*/
+
+int sky;
+int mr_rowofs;
+int mr_count;
+int mr_xstep;
+int mr_ystep;
+int mr_xfrac;
+int mr_yfrac;
+byte * mr_dest;
+byte * mr_src;
+
+/*
+==================
+=
+= Local Variables
+=
+==================
+*/
+
+static byte *floor;
+static byte *ceiling;
+//static int xstarts[MAXVIEWHEIGHT];
+static int xstarts[600];//set to max hight res
+static byte * skysegs[MAXSKYSEGS];
+static byte * skydata[MAXSKYDATA];
+static int horizonheight;
+static int centerskypost;
+static int oldsky=-1;
+
+
+//bna fixit skyerror by 800x600 clouds not big enough
+
+void DrawSky( void )
+{
+
+ byte * src;
+ int dest;
+// int plane;
+ int height;
+// int height2;
+ int ang;
+ int angle;
+ int ofs;
+
+ angle=viewangle;
+
+ if ((fog==0) && (lightning==true))
+ shadingtable=colormap+((basemaxshade-6-lightninglevel)<<8);
+ else
+ shadingtable=colormap+(1<<12);
+
+ ofs=(((maxheight)-(player->z))>>3)+(centery*200/iGLOBAL_SCREENHEIGHT-((viewheight*200/iGLOBAL_SCREENHEIGHT)>>1));
+
+ if (ofs>centerskypost)
+ {
+ ofs=centerskypost;
+ }
+ else if (((centerskypost-ofs)+viewheight*200/iGLOBAL_SCREENHEIGHT)>1799)
+ {
+ ofs=-(1799-(centerskypost+viewheight*200/iGLOBAL_SCREENHEIGHT));
+ }
+//ofs=centerskypost;
+#ifdef DOS
+ if (doublestep>0)
+ {
+#ifdef DOS
+ for (plane=0; plane<4; plane+=2)
+#endif
+ {
+#ifdef DOS
+ VGAMAPMASK((1<<plane)+(1<<(plane+1)));
+ for (dest=plane; dest<viewwidth; dest+=4)
+#else
+ for (dest=0; dest<viewwidth; dest+=2)
+#endif
+ {
+ height=posts[dest].ceilingclip;
+ height2=posts[dest+1].ceilingclip;
+ if (height<height2)
+ height=height2;
+ if (height<=0)
+ continue;
+ ang=(angle+pixelangle[dest])&(FINEANGLES-1);
+ src=skysegs[ang]-ofs;
+#ifdef DOS
+ DrawSkyPost((byte *)bufferofs + (dest>>2),src,height);
+#else
+ /* TODO: this isn't right since it's not really optimized */
+ DrawSkyPost((byte *)bufferofs + dest,src,height);
+ DrawSkyPost((byte *)bufferofs + dest + 1,src,height);
+#endif
+ }
+ }
+ }
+ else
+#endif
+ {
+#ifdef DOS
+ for (plane=0; plane<4; plane++)
+#endif
+ {
+#ifdef DOS
+ VGAWRITEMAP(plane);
+ for (dest=plane; dest<viewwidth; dest+=4)
+#else
+ for (dest=0; dest<viewwidth; dest++)
+#endif
+ {
+ if ((height=posts[dest].ceilingclip)<=0)
+ continue;
+ ang=(angle+pixelangle[dest])&(FINEANGLES-1);
+ src=skysegs[ang]-ofs;
+#ifdef DOS
+ DrawSkyPost((byte *)bufferofs + (dest>>2),src,height);
+#else
+ DrawSkyPost((byte *)bufferofs + dest,src,height);
+#endif
+ }
+ }
+ }
+}
+
+/*
+===================
+=
+= DrawFullSky
+=
+===================
+*/
+void DrawFullSky( void )
+{
+
+ byte * src;
+ int dest;
+ int plane;
+ int ang;
+ int angle;
+ int ofs;
+
+ angle=viewangle;
+
+ if ((fog==0) && (lightning==true))
+ shadingtable=colormap+((basemaxshade-5-lightninglevel)<<8);
+ else
+ shadingtable=colormap+(1<<12);
+
+ ofs=(((maxheight)-(player->z))>>3)+(centery-(viewheight>>1));
+ if (ofs>centerskypost)
+ {
+ ofs=centerskypost;
+ }
+ else if (((centerskypost-ofs)+viewheight)>599)
+ {
+ ofs=-(599-(centerskypost+viewheight));
+ }
+
+ bufferofs+=screenofs;
+
+#ifdef DOS
+ for (plane=0; plane<4; plane++)
+#endif
+ {
+#ifdef DOS
+ VGAWRITEMAP(plane);
+ for (dest=plane; dest<viewwidth; dest+=4)
+#else
+ for (dest=0; dest<viewwidth; dest++)
+#endif
+ {
+ ang=(angle+pixelangle[dest])&(FINEANGLES-1);
+ src=skysegs[ang]-ofs;
+#ifdef DOS
+ DrawSkyPost((byte *)bufferofs + (dest>>2),src,viewheight);
+#else
+ DrawSkyPost((byte *)bufferofs + dest,src,viewheight);
+#endif
+ }
+ }
+
+ bufferofs-=screenofs;
+}
+
+/*
+===================
+=
+= MakeSkyTile
+=
+===================
+*/
+void MakeSkyTile (byte * tile)
+{
+ int i,j;
+ int srcstep;
+ int src;
+
+ srcstep=200<<10;
+ for (i=0; i<64; i++)
+ {
+ src=0;
+ for (j=0; j<64; j++)
+ {
+ *(tile + (i<<6) + j)=*(skysegs[(i<<2)]+(src>>16));
+ src+=srcstep;
+ }
+ }
+}
+
+/*
+===================
+=
+= MakeSkyData
+=
+===================
+*/
+void MakeSkyData ( void )
+{
+ byte * temp;
+ byte * ptr;
+ int c;
+
+ temp=SafeMalloc(256*800);
+
+ ptr=temp;
+
+ for (c=0; c<256; c++)
+ {
+
+ memcpy(ptr,skydata[1]+(c*200),200);
+ ptr+=200;
+
+ memcpy(ptr,skydata[0]+(c*200),200);
+ ptr+=200;
+
+ //memcpy(ptr,skydata[1]+(c*200),200);
+ //ptr+=200;
+ //memcpy(ptr,skydata[0]+(c*200),200);
+ //ptr+=200;
+ }
+ skydata[0]=temp;
+}
+
+/*
+===================
+=
+= GetFloorCeilingLump
+=
+===================
+*/
+
+int GetFloorCeilingLump ( int num )
+{
+ int lump;
+
+ switch (num)
+ {
+ case 1:
+ lump=W_GetNumForName("FLRCL1\0");
+ break;
+ case 2:
+ lump=W_GetNumForName("FLRCL2\0");
+ break;
+ case 3:
+ lump=W_GetNumForName("FLRCL3\0");
+ break;
+ case 4:
+ lump=W_GetNumForName("FLRCL4\0");
+ break;
+ case 5:
+ lump=W_GetNumForName("FLRCL5\0");
+ break;
+ case 6:
+ lump=W_GetNumForName("FLRCL6\0");
+ break;
+ case 7:
+ lump=W_GetNumForName("FLRCL7\0");
+ break;
+ case 8:
+ lump=W_GetNumForName("FLRCL8\0");
+ break;
+ case 9:
+ lump=W_GetNumForName("FLRCL9\0");
+ break;
+ case 10:
+ lump=W_GetNumForName("FLRCL10\0");
+ break;
+ case 11:
+ lump=W_GetNumForName("FLRCL11\0");
+ break;
+ case 12:
+ lump=W_GetNumForName("FLRCL12\0");
+ break;
+ case 13:
+ lump=W_GetNumForName("FLRCL13\0");
+ break;
+ case 14:
+ lump=W_GetNumForName("FLRCL14\0");
+ break;
+ case 15:
+ lump=W_GetNumForName("FLRCL15\0");
+ break;
+ case 16:
+ lump=W_GetNumForName("FLRCL16\0");
+ break;
+ default:
+ Error("Illegal Floor/Ceiling Tile = %d\n",num);
+ break;
+ }
+ return lump;
+}
+
+/*
+===================
+=
+= SkyExists
+=
+===================
+*/
+
+boolean SkyExists (void)
+{
+ if (MAPSPOT(1,0,0) >= 234)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+
+}
+
+/*
+===================
+=
+= SetPlaneViewSize
+=
+===================
+*/
+
+void SetPlaneViewSize (void)
+{
+ int x;
+ int i;
+ int s;
+ int floornum;
+ int ceilingnum;
+ int skytop;
+ int skybottom;
+
+ sky=0;
+
+ if (oldsky>0)
+ {
+ SafeFree(skydata[0]);
+ oldsky=-1;
+ }
+
+ lightning=false;
+
+ if (MAPSPOT(1,0,0) >= 234)
+ {
+ word crud;
+ sky = (MAPSPOT(1,0,0) - 233);
+ if ((sky<1) || (sky>6))
+ Error("Illegal Sky Tile = %d\n",sky);
+ ceilingnum=1;
+ crud=(word)MAPSPOT(1,0,1);
+ if ((crud>=90) && (crud<=97))
+ horizonheight=crud-89;
+ else if ((crud>=450) && (crud<=457))
+ horizonheight=crud-450+9;
+ else
+ Error("You must specify a valid horizon height sprite icon over the sky at (2,0) on map %d\n",gamestate.mapon);
+
+ // Check for lightnign icon
+
+ crud=(word)MAPSPOT(4,0,1);
+ if (crud==377)
+ lightning=true;
+ }
+ else
+ ceilingnum = MAPSPOT(1,0,0)-197;
+
+ floornum = MAPSPOT(0,0,0)-(179);
+
+ floornum = GetFloorCeilingLump ( floornum );
+ //ceilingnum = GetFloorCeilingLump ( ceilingnum );
+
+ floor = W_CacheLumpNum(floornum,PU_LEVELSTRUCT, Cvt_patch_t, 1);
+ floor +=8;
+
+ if (sky==0) // Don't cache in if not used
+ {
+ ceilingnum = GetFloorCeilingLump ( ceilingnum );
+ ceiling = W_CacheLumpNum(ceilingnum,PU_LEVELSTRUCT, Cvt_patch_t, 1);
+ ceiling +=8;
+ } else {
+ ceiling = NULL;
+ }
+
+ s = W_GetNumForName("SKYSTART");
+
+ switch (sky)
+ {
+ case 1:
+ skytop=s+1;
+ skybottom=s+2;
+ break;
+ case 2:
+ skytop=s+3;
+ skybottom=s+4;
+ break;
+ case 3:
+ skytop=s+5;
+ skybottom=s+6;
+ break;
+ case 4:
+ skytop=s+7;
+ skybottom=s+8;
+ break;
+ case 5:
+ skytop=s+9;
+ skybottom=s+10;
+ break;
+ case 6:
+ skytop=s+11;
+ skybottom=s+12;
+ break;
+ }
+ if (sky!=0)
+ {
+ skydata[0]=W_CacheLumpNum(skytop,PU_STATIC, CvtNull, 1);
+ skydata[1]=W_CacheLumpNum(skybottom,PU_STATIC, CvtNull, 1);
+ centerskypost=MINSKYHEIGHT-(horizonheight*6);
+ oldsky=sky;
+ MakeSkyData();
+ W_CacheLumpNum(skytop,PU_CACHE, CvtNull, 1);
+ W_CacheLumpNum(skybottom,PU_CACHE, CvtNull, 1);
+ x=511;
+ for (i=0; i<MAXSKYSEGS; i++)
+ {
+ skysegs[i]=skydata[0]+((x>>1)*400)+centerskypost;
+ x--;
+ if (x==-1)
+ {
+ x=511;
+ }
+ } /* endfor */
+ }
+}
+
+/*
+==========================
+=
+= SetFCLightLevel
+=
+==========================
+*/
+void SetFCLightLevel (int height)
+{
+ int i;
+
+ if (MISCVARS->GASON==1)
+ {
+ shadingtable=greenmap+(MISCVARS->gasindex<<8);
+ return;
+ }
+ if (fulllight)
+ {
+ shadingtable=colormap+(1<<12);
+ return;
+ }
+ if (fog)
+ {
+ i=((height*200/iGLOBAL_SCREENHEIGHT)>>normalshade)+minshade;
+ if (i>maxshade) i=maxshade;
+ shadingtable=colormap+(i<<8);
+ }
+ else
+ {
+ i=maxshade-(height>>normalshade);
+ if (i<minshade) i=minshade;
+ shadingtable=colormap+(i<<8);
+ }
+}
+
+
+
+void DrawHLine (int xleft, int xright, int yp)
+{
+ int plane;
+ byte * buf;
+ byte * dest;
+ int startxfrac;
+ int startyfrac;
+ int height;
+// int length;
+ int ofs;
+
+ if (yp==centery)
+ return;
+ if (yp>centery)
+ {
+ int hd;
+
+ buf=floor;
+ hd=yp-centery;
+ height=(hd<<13)/(maxheight-pheight+32);
+ }
+ else
+ {
+ int hd;
+
+ /* ROTT bug? It'd draw when there was no ceiling. - SBF */
+ if (ceiling == NULL) return;
+
+ buf=ceiling;
+
+ hd=centery-yp;
+ height=(hd<<13)/pheight;
+ }
+ SetFCLightLevel(height>>(8-HEIGHTFRACTION-1));
+ mr_xstep = ((viewsin<<8)/(height));
+ mr_ystep = ((viewcos<<8)/(height));
+
+ startxfrac = ((viewx>>1) + FixedMulShift(mr_ystep,scale,2))-
+ FixedMulShift(mr_xstep,(centerx-xleft),2);
+
+ startyfrac = ((viewy>>1) - FixedMulShift(mr_xstep,scale,2))-
+ FixedMulShift(mr_ystep,(centerx-xleft),2);
+
+ dest=(byte *)bufferofs+ylookup[yp];
+
+ /* TODO: horizontal isn't as easy as vertical in packed */
+#ifdef DOS
+ if (doublestep>0)
+ {
+ if (xleft&1)
+ xleft--;
+
+#ifdef DOS
+ for (plane=xleft; plane<xleft+4; plane+=2)
+#endif
+ {
+
+#ifdef DOS
+ mr_dest=dest+(plane>>2);
+#else
+ mr_dest=dest+xleft;
+#endif
+
+ mr_xfrac = startxfrac;
+ mr_yfrac = startyfrac;
+
+#ifdef DOS
+ startxfrac+=mr_xstep>>1;
+ startyfrac+=mr_ystep>>1;
+
+ mr_count=((xright-plane)>>2)+1;
+#else
+ mr_count = xright - xleft;
+#endif
+
+ if (mr_count)
+ {
+#ifdef DOS
+ int p;
+ ofs=((plane&3)<<3)+(plane&3)+1;
+// VGAMAPMASK(*((byte *)mapmasks1+ofs));
+ p=plane&3;
+ VGAMAPMASK((1<<p) + (1<<(p+1)));
+#endif
+ DrawRow(mr_count,mr_dest,buf);
+
+#if 0
+ ofs=(byte)*((byte *)mapmasks2+ofs);
+ if (ofs!=0)
+ {
+ VGAMAPMASK(ofs);
+ DrawRow(mr_count,mr_dest+1,buf);
+ }
+#endif
+ }
+ }
+ }
+ else
+#endif
+ {
+#ifdef DOS
+ for (plane=xleft; plane<xleft+4; plane++)
+#endif
+ {
+#ifdef DOS
+ mr_dest=dest+(plane>>2);
+ VGAWRITEMAP(plane&3);
+#else
+ mr_dest=dest+xleft;
+#endif
+
+ mr_xfrac = startxfrac;
+ mr_yfrac = startyfrac;
+
+#ifdef DOS
+ startxfrac+=mr_xstep>>2;
+ startyfrac+=mr_ystep>>2;
+
+ mr_count=((xright-plane)>>2)+1;
+#else
+ // back off the pixel increment (orig. is 4x)
+ mr_xstep >>= 2;
+ mr_ystep >>= 2;
+
+ mr_count = xright-xleft+1;
+#endif
+
+ if (mr_count)
+ DrawRow(mr_count,mr_dest,buf);
+ }
+ }
+
+}
+
+void DrawPlanes( void )
+{
+ int x,y;
+ int twall;
+ int bwall;
+
+ if (sky)
+ DrawSky();
+ else
+ {
+ y=0;
+ for (x=0; x<viewwidth; x++)
+ {
+ twall=posts[x].ceilingclip;
+ while (y<twall)
+ {
+ xstarts[y]=x;
+ y++;
+ }
+ while (y>twall)
+ {
+ y--;
+ DrawHLine(xstarts[y],x-1,y);
+ }
+ }
+ while (y>0)
+ {
+ y--;
+ DrawHLine(xstarts[y],viewwidth-1,y);
+ }
+ }
+ y=viewheight-1;
+ for (x=0; x<viewwidth; x++)
+ {
+ bwall=posts[x].floorclip;
+ while (y>bwall)
+ {
+ xstarts[y]=x;
+ y--;
+ }
+ while (y<bwall)
+ {
+ y++;
+ DrawHLine(xstarts[y],x-1,y);
+ }
+ }
+ while (y<viewheight-1)
+ {
+ y++;
+ DrawHLine(xstarts[y],viewwidth-1,y);
+ }
+}
+
+#ifndef DOS
+void DrawRow(int count, byte * dest, byte * src)
+{
+ unsigned frac, fracstep;
+ int coord;
+
+ frac = (mr_yfrac<<16) + (mr_xfrac&0xffff);
+ fracstep = (mr_ystep<<16) + (mr_xstep&0xffff);
+
+ while (count--) {
+ /* extract the x/y coordinates */
+ coord = ((frac >> (32-7)) | ((frac >> (32-23)) << 7)) & 16383;
+
+ *dest++ = shadingtable[src[coord]];
+ frac += fracstep;
+ }
+}
+#endif
--- /dev/null
+++ b/rott/rt_floor.h
@@ -1,0 +1,44 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_floor_public
+#define _rt_floor_public
+
+//***************************************************************************
+//
+// RT_FLOOR.C - Floor and Ceiling stuff
+//
+//***************************************************************************
+
+extern int mr_xstep;
+extern int mr_ystep;
+extern int mr_xfrac;
+extern int mr_yfrac;
+
+extern int sky; //Whether Parallax is on or off
+void DrawPlanes (void);
+void SetPlaneViewSize( void );
+void MakeSkyTile (byte * tile);
+void DrawFullSky( void );
+boolean SkyExists (void);
+
+#endif
+
+
+
--- /dev/null
+++ b/rott/rt_game.c
@@ -1,0 +1,5772 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#ifdef DOS
+#include <dos.h>
+#include <io.h>
+#include <conio.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "rt_def.h"
+#include "rt_main.h"
+#include "rt_game.h"
+#include "_rt_game.h"
+#include "rt_menu.h"
+#include "z_zone.h"
+#include "w_wad.h"
+#include "lumpy.h"
+#include "rt_playr.h"
+#include "rt_util.h"
+#include "rt_ted.h"
+#include "rt_draw.h"
+#include "rt_view.h"
+#include "rt_vid.h"
+#include "rt_door.h"
+#include "rt_in.h"
+#include "rt_str.h"
+#include "isr.h"
+#include "rt_build.h"
+#include "rt_rand.h"
+#include "rt_cfg.h"
+#include "rt_sound.h"
+#include "version.h"
+#include "rt_crc.h"
+#include "modexlib.h"
+#include "engine.h"
+#include "gmove.h"
+#include "rt_com.h"
+#include "rt_net.h"
+#include "watcom.h"
+#include "rt_floor.h"
+#include "rt_msg.h"
+#include "rt_scale.h"
+#include "develop.h"
+//MED
+#include "memcheck.h"
+
+#if (SHAREWARE == 1)
+#define NUMAMMOGRAPHICS 10
+#else
+#define NUMAMMOGRAPHICS 20
+#endif
+
+//******************************************************************************
+//
+// GLOBALS
+//
+//******************************************************************************
+
+int PlayerSnds[5] = {SD_PLAYERTCSND, SD_PLAYERTBSND, SD_PLAYERDWSND,
+ SD_PLAYERLNSND, SD_PLAYERIPFSND
+ };
+
+
+unsigned short SHAKETICS = 0xFFFF;//bna++
+//int SHAKETICS = 0xFFFF;
+int damagecount = 0;
+HighScore Scores[MaxScores] =
+{
+ {"Tom",70000,7,1},
+ {"Chuck",60000,6,1},
+ {"Mark",50000,5,1},
+ {"The Joes",40000,4,1},
+ {"William",30000,3,1},
+ {"Jim",20000,2,1},
+ {"Steve",10000,1,1},
+};
+
+//******************************************************************************
+//
+// LOCALS
+//
+//******************************************************************************
+
+static int KeyX[4] = {KEY1_X, KEY2_X, KEY3_X, KEY4_X};
+
+static const char *Names[ 5 ] =
+{
+ "Taradino", "Thi", "Doug", "Lorelei", "Ian Paul"
+};
+
+static const char *LastNames[ 5 ] =
+{
+ "Cassatt", "Barrett", "Wendt", "Ni", "Freeley"
+};
+
+static STR ScoreStr;
+static STR LivesStr;
+static STR TriadStr;
+static STR KillStr;
+
+static pic_t *lifeptnums[10];
+static pic_t *lifenums[10];
+static pic_t *timenums[10];
+static pic_t *scorenums[10];
+static pic_t *keys[4];
+static pic_t *men[5];
+
+static pic_t *health[6];
+static pic_t *ammo[26];
+static pic_t *erase;
+static pic_t *eraseb;
+static pic_t *fragpic[ 5 ];
+static pic_t *frag100pic[ 5 ];
+static pic_t *negfragpic[ 5 ];
+static pic_t *menneg[ 5 ];
+static pic_t *blankfragpic;
+
+static int powerpics;
+static int poweradjust;
+
+static int poweruptime;
+static int powerupheight;
+static int protectiontime;
+static int protectionheight;
+
+
+static boolean EndLevelStuff = false;
+static boolean borderset = false;
+static int oldsec = -1;
+
+static pic_t *BkPic;
+int SaveTime = 0;
+int oldhealth;
+
+static int oldplayerhealth;
+static int oldpercenthealth;
+
+static int playeruniformcolor;
+
+#define NUMBONUSES 11
+#define BONUSBONUS 100000
+
+
+extern void VL_MemToScreenClipped (byte *source, int width, int height, int x, int y);
+void DrawPPic (int xpos, int ypos, int width, int height, byte *src, int num, boolean up, boolean bufferofsonly);
+extern void MoveScreenUpLeft();
+extern void MoveScreenUpRight();
+extern void MoveScreenDownLeft();
+extern void MoveScreenDownRight();
+//******************************************************************************
+//
+// V_ReDrawBkgnd ()
+//
+//******************************************************************************
+
+void V_ReDrawBkgnd (int x, int y, int width, int height, boolean shade)
+{
+ byte *src;
+ byte *dest;
+ byte *origdest;
+ int j,
+ k,
+ planes,
+ mask,
+ m;
+
+ m = (x&3);
+ mask = (1 << m);
+
+#ifdef DOS
+ origdest = (byte *)(bufferofs+ylookup[y]+(x>>2));
+#else
+ origdest = (byte *)(bufferofs+ylookup[y]+x);
+#endif
+
+ if (VW_MarkUpdateBlock (x, y, x+width-1, y+height-1))
+ {
+ for (planes = 0; planes < 4; planes++)
+ {
+ src = (&(BkPic->data)+((80*200)*m)+(80*y)+(x>>2));
+ dest = origdest;
+
+#ifdef DOS
+ VGAMAPMASK (mask);
+#else
+ dest += planes;
+#endif
+
+ for (j = 0; j < height; j++)
+ {
+ for (k = 0; k < (width/4); k++) {
+ if (shade) {
+ *dest = *(colormap + ((MENUSHADELEVEL>>2)<<8) + *src++);
+ } else {
+ *dest = *src++;
+ }
+#ifdef DOS
+ dest++;
+#else
+ dest += 4;
+#endif
+ }
+
+#ifndef DOS
+ // draw the remainder. did the DOS version even bother? - SBF
+ if ((width & 3) > planes) {
+ if (shade) {
+ *dest = *(colormap + ((MENUSHADELEVEL>>2)<<8) + *src);
+ } else {
+ *dest = *src;
+ }
+ }
+#endif
+
+ src += (80-(width/4));
+#ifdef DOS
+ dest += (linewidth-(width/4));
+#else
+ dest += (linewidth-(width&~3));
+#endif
+ }
+
+ m++;
+
+ mask <<= 1;
+
+ if (mask == 16)
+ {
+ x+=4;
+ mask = 1;
+ m = 0;
+#ifdef DOS
+ origdest++;
+#endif
+ }
+ }
+ }
+}
+
+
+//******************************************************************************
+//
+// CacheLumpGroup ()
+//
+//******************************************************************************
+void CacheLumpGroup
+(
+ char *startlump,
+ pic_t **lumparray,
+ int numberoflumps
+)
+
+{
+ int lumpnum;
+ int i;
+
+ lumpnum = W_GetNumForName( startlump );
+
+ for( i = 0; i < numberoflumps; i++ )
+ {
+ lumparray[ i ] = ( pic_t * )W_CacheLumpNum( lumpnum + i, PU_LEVEL, Cvt_pic_t, 1 );
+ }
+}
+
+//******************************************************************************
+//
+// SetupPlayScreen ()
+//
+//******************************************************************************
+void SetupPlayScreen
+(
+ void
+)
+
+{
+ int i;
+ int j;
+ int num;
+
+ erase = ( pic_t * )W_CacheLumpName( "erase", PU_LEVEL, Cvt_pic_t, 1 );
+ eraseb = ( pic_t * )W_CacheLumpName( "eraseb", PU_LEVEL, Cvt_pic_t, 1 );
+
+ CacheLumpGroup( "tmnum0", timenums, 10 );
+ CacheLumpGroup( "lfnum0", lifeptnums, 10 );
+ CacheLumpGroup( "lvnum0", lifenums, 10 );
+ CacheLumpGroup( "health1b", health, 6 );
+ CacheLumpGroup( "key1", keys, 4 );
+
+ if ( !BATTLEMODE )
+ {
+ CacheLumpGroup( "scnum0", scorenums, 10 );
+
+ num = locplayerstate->player;
+ men[ num ] = ( pic_t * )W_CacheLumpNum( W_GetNumForName( "MAN1" ) +
+ num, PU_LEVEL, Cvt_pic_t, 1 );
+ }
+ else
+ {
+ int man;
+ int num100;
+ int negnum;
+ int negman;
+
+ CacheLumpGroup( "kilnum0", scorenums, 10 );
+
+ negnum = W_GetNumForName( "botnpic1" );
+ num = W_GetNumForName( "botpic0" );
+ num100 = W_GetNumForName( "botopic1" );
+ negman = W_GetNumForName( "negman1" );
+ man = W_GetNumForName( "man1" );
+
+ blankfragpic = ( pic_t * )W_CacheLumpNum( num, PU_LEVEL, Cvt_pic_t, 1 );
+ num++;
+
+ for( i = 0; i < numplayers; i++ )
+ {
+ j = PLAYERSTATE[ i ].player;
+ if ( !gamestate.teamplay )
+ {
+ fragpic[ j ] = ( pic_t * )W_CacheLumpNum( num + j, PU_LEVEL, Cvt_pic_t, 1 );
+ frag100pic[ j ] = ( pic_t * )W_CacheLumpNum( num100 + j, PU_LEVEL, Cvt_pic_t, 1 );
+ negfragpic[ j ] = ( pic_t * )W_CacheLumpNum( negnum + j, PU_LEVEL, Cvt_pic_t, 1 );
+ }
+ else
+ {
+ negfragpic[ j ] = ( pic_t * )W_CacheLumpName( "teamnpic", PU_LEVEL, Cvt_pic_t, 1 );
+ fragpic[ j ] = ( pic_t * )W_CacheLumpName( "teampic", PU_LEVEL, Cvt_pic_t, 1 );
+ frag100pic[ j ] = fragpic[ j ];
+ }
+
+ menneg[ j ] = ( pic_t * )W_CacheLumpNum( negman + j, PU_LEVEL, Cvt_pic_t, 1 );
+ men[ j ] = ( pic_t * )W_CacheLumpNum( man + j, PU_LEVEL, Cvt_pic_t, 1 );
+ }
+ }
+
+ powerpics = W_GetNumForName( "GDMODEP" );
+ poweradjust = POWERUPTICS / 16;
+
+ num = W_GetNumForName( "INF_B" );
+
+ // bullet weapons
+ ammo[0] = ( pic_t * )W_CacheLumpNum( num, PU_LEVEL, Cvt_pic_t, 1 );
+ ammo[1] = ( pic_t * )W_CacheLumpNum( num, PU_LEVEL, Cvt_pic_t, 1 );
+ ammo[2] = ( pic_t * )W_CacheLumpNum( num++, PU_LEVEL, Cvt_pic_t, 1 );
+
+
+ for(i=3; i < 13; i++ )
+ {
+ ammo[ i ] = ( pic_t * )W_CacheLumpNum( num++, PU_LEVEL, Cvt_pic_t, 1 );
+ }
+
+ ammo[13] = ( pic_t * )W_CacheLumpNum( num, PU_LEVEL, Cvt_pic_t, 1 );
+ ammo[14] = ( pic_t * )W_CacheLumpNum( num, PU_LEVEL, Cvt_pic_t, 1 );
+ ammo[15] = ( pic_t * )W_CacheLumpNum( num++, PU_LEVEL, Cvt_pic_t, 1 );
+
+
+ for(i=16; i < 26; i++ )
+ {
+ ammo[ i ] = ( pic_t * )W_CacheLumpNum( num++, PU_LEVEL, Cvt_pic_t, 1 );
+ }
+
+
+ oldplayerhealth = -1;
+ oldpercenthealth = -1;
+}
+
+
+
+//******************************************************************************
+//
+// GameMemToScreen()
+//
+//******************************************************************************
+
+void GameMemToScreen(pic_t *source, int x, int y, int bufferofsonly)
+{
+ if ( bufferofsonly )
+ {
+ VL_MemToScreen( ( byte * )&source->data, source->width,
+ source->height, x, y );
+ }
+ else
+ {
+ GM_MemToScreen( ( byte * )&source->data, source->width,
+ source->height, x, y );
+ }
+}
+int topBarCenterOffsetX;
+//int topBarCenterOffsetX = (iGLOBAL_SCREENWIDTH - 320) >> 1;
+
+//******************************************************************************
+//
+// DrawPlayScreen ()
+//
+//******************************************************************************
+void DrawPlayScreen (boolean bufferofsonly)
+{
+ pic_t *shape;
+ int shapenum;
+ int ShowKillsYoffset = 0;//bna++
+
+//return;
+ //figure out where the middle point of the status bar should be for top bar
+ topBarCenterOffsetX = (iGLOBAL_SCREENWIDTH - 320) >> 1;
+
+ if ( SHOW_TOP_STATUS_BAR() )
+ {
+ if (iGLOBAL_SCREENWIDTH == 640) {
+ //use this as dummy pic to fill out missing bar
+ shape = ( pic_t * ) W_CacheLumpName( "bottbar", PU_CACHE, Cvt_pic_t, 1 );
+ GameMemToScreen( shape, 0, 0, bufferofsonly );
+ GameMemToScreen( shape, 320, 0, bufferofsonly );
+ // delete heart in middle of topbar
+ DrawPPic( 3,1, 8 >> 2, 16,
+ ( byte * )&erase->data, 2, true, bufferofsonly );
+ // delete bullet in end of topbar
+ DrawPPic( 620,1, 8 >> 2, 16,
+ ( byte * )&erase->data, 2, true, bufferofsonly );
+ shape = ( pic_t * )W_CacheLumpName( "stat_bar", PU_CACHE, Cvt_pic_t, 1 );
+ GameMemToScreen( shape, topBarCenterOffsetX, 0, bufferofsonly );
+ } else if (iGLOBAL_SCREENWIDTH == 800) {
+ //use this as dummy pic to fill out missing bar
+ shape = ( pic_t * ) W_CacheLumpName( "bottbar", PU_CACHE, Cvt_pic_t, 1 );
+ GameMemToScreen( shape, 0, 0, bufferofsonly );
+ GameMemToScreen( shape, 260, 0, bufferofsonly );
+ GameMemToScreen( shape, 800-320, 0, bufferofsonly );
+ // delete heart in middle of topbar
+ DrawPPic( 480+3,1, 8 >> 2, 16,
+ ( byte * )&erase->data, 2, true, bufferofsonly );
+ // delete bullet in end of topbar
+ DrawPPic( 780,1, 8 >> 2, 16,
+ ( byte * )&erase->data, 2, true, bufferofsonly );
+
+ //delete heart in left side of topbar
+ DrawPPic( 3,1, 8 >> 2, 16,
+ ( byte * )&erase->data, 2, true, bufferofsonly );
+
+ shape = ( pic_t * )W_CacheLumpName( "stat_bar", PU_CACHE, Cvt_pic_t, 1 );
+ GameMemToScreen( shape, topBarCenterOffsetX, 0, bufferofsonly );
+
+ //shape = ( pic_t * ) W_CacheLumpName( "bottbar", PU_CACHE, Cvt_pic_t, 1 );
+ } else if (iGLOBAL_SCREENWIDTH == 320) {
+
+ //SetTextMode ( );
+ shape = ( pic_t * )W_CacheLumpName( "stat_bar", PU_CACHE, Cvt_pic_t, 1 );
+ GameMemToScreen( shape, 0, 0, bufferofsonly );
+ }
+ }
+
+ if ( BATTLEMODE )
+ {
+ DrawKills( bufferofsonly );
+ }
+
+ if ( SHOW_BOTTOM_STATUS_BAR() )
+ {
+ shape = ( pic_t * ) W_CacheLumpName( "bottbar", PU_CACHE, Cvt_pic_t, 1 );
+
+ if ( SHOW_KILLS() )
+ {
+ ShowKillsYoffset = KILLS_HEIGHT;
+ //shape = ( pic_t * )W_CacheLumpName( "backtile", PU_CACHE, Cvt_pic_t, 1 );
+ //DrawTiledRegion( 0, 584, iGLOBAL_SCREENWIDTH, 32-16, 0, 16, shape );//bna++
+
+
+ // health_y = iGLOBAL_HEALTH_Y;
+// if ( SHOW_KILLS() )
+ // {
+ // health_y -= KILLS_HEIGHT;
+ //GameMemToScreen( shape, 0, (iGLOBAL_SCREENHEIGHT-40)+16, bufferofsonly );
+
+ //GameMemToScreen( shape, 0, 160, bufferofsonly );bna++
+ }
+ //else
+ //{
+
+ if (iGLOBAL_SCREENWIDTH == 640) {
+ //bna fix - not to good? but no one has 286 any more
+ //statusbar dosent cover hole screen, because its a lump picture width max 320
+ //first write dummy shape and next over it
+ GameMemToScreen( shape, 320, (224*2)+16-ShowKillsYoffset, bufferofsonly );
+ //copy next shape to mem
+ GameMemToScreen( shape, 0, (224*2)+16-ShowKillsYoffset, bufferofsonly );
+ // delete bullet in middle of shape picture
+ DrawPPic( 310, (224*2)+17-ShowKillsYoffset, 8 >> 2, 16,
+ ( byte * )&erase->data, 2, true, bufferofsonly );
+ // delete hart in middle of shape picture
+ DrawPPic( 324, (224*2)+17-ShowKillsYoffset, 8 >> 2, 16,
+ ( byte * )&erase->data, 2, true, bufferofsonly );
+
+ } else if (iGLOBAL_SCREENWIDTH == 800) {
+ GameMemToScreen( shape, 800-320, 584-ShowKillsYoffset, bufferofsonly );
+ //copy next shape to mem
+ GameMemToScreen( shape, 300, 584-ShowKillsYoffset, bufferofsonly );
+ //copy next shape to mem
+ GameMemToScreen( shape, 0, 584-ShowKillsYoffset, bufferofsonly );
+ // delete 2 bullets in middle of shape picture
+ DrawPPic( 305, 584+1-ShowKillsYoffset, 8 >> 2, 16,
+ ( byte * )&erase->data, 2, true, bufferofsonly );
+ // delete hart in middle of shape picture
+ DrawPPic( 610, 584+1-ShowKillsYoffset, 8 >> 2, 16,
+ ( byte * )&erase->data, 2, true, bufferofsonly );
+
+ } else {
+ GameMemToScreen( shape, 0, 184, bufferofsonly );
+ }
+ //}
+
+ DrawBarAmmo( bufferofsonly );
+ DrawBarHealth( bufferofsonly );
+
+ if ( demoplayback )
+ {
+ shape = ( pic_t * )W_CacheLumpName( "demo", PU_CACHE, Cvt_pic_t, 1 );
+ if (iGLOBAL_SCREENWIDTH == 640) {
+ //DrawPPic( 148, 185, shape->width, shape->height,
+ // ( byte * )&shape->data, 1, true, bufferofsonly );bna
+ DrawPPic( 148*2, 465, shape->width, shape->height,
+ ( byte * )&shape->data, 1, true, bufferofsonly );
+ } else if (iGLOBAL_SCREENWIDTH == 800) {
+ DrawPPic( 380, 585, shape->width, shape->height,
+ ( byte * )&shape->data, 1, true, bufferofsonly );
+ } else {
+ DrawPPic( 148, 185, shape->width, shape->height,
+ ( byte * )&shape->data, 1, true, bufferofsonly );
+ }
+ }
+ }
+
+ if ( !SHOW_TOP_STATUS_BAR() )
+ {
+ return;
+ }
+
+//draws small player picture and name in topbar
+ oldsec = -1;
+
+ //DrawTime( bufferofsonly );
+
+ if ( !BATTLEMODE )
+ {
+ int character;
+ int width;
+ int height;
+
+ character = locplayerstate->player;
+ GameMemToScreen( men[ character ], MEN_X + topBarCenterOffsetX, MEN_Y,bufferofsonly );
+
+ CurrentFont = tinyfont;
+
+ // Draw player's name
+
+ if (iGLOBAL_SCREENWIDTH == 800)
+ {
+ DrawGameString ( MEN_X + 3 + topBarCenterOffsetX, MEN_Y + 2, Names[ character ], bufferofsonly );
+ VW_MeasurePropString( LastNames[ character ], &width, &height );
+ DrawGameString ( MEN_X + 44 - width + topBarCenterOffsetX, MEN_Y + 8,
+ LastNames[ character ], bufferofsonly );
+ }
+ else
+ {
+/*
+ DrawGameString ( MEN_X + 3, MEN_Y + 2, Names[ character ], bufferofsonly );
+
+ VW_MeasurePropString( LastNames[ character ], &width, &height );
+
+ DrawGameString ( MEN_X + 44 - width, MEN_Y + 8,
+ LastNames[ character ], bufferofsonly );
+*/
+
+
+ DrawGameString ( MEN_X + 3 + topBarCenterOffsetX, MEN_Y + 2, Names[ character ], bufferofsonly );
+ VW_MeasurePropString( LastNames[ character ], &width, &height );
+ DrawGameString ( MEN_X + 44 - width + topBarCenterOffsetX, MEN_Y + 8,
+ LastNames[ character ], bufferofsonly );
+
+ }
+ UpdateLives( locplayerstate->lives );
+ UpdateScore( gamestate.score );
+ DrawTriads( bufferofsonly );
+ DrawLives( bufferofsonly );
+ DrawScore( bufferofsonly );
+ }
+
+ DrawKeys( bufferofsonly );
+
+ if ( locplayerstate->poweruptime )
+ {
+ if ( player->flags & FL_GODMODE )
+ {
+ shapenum = powerpics;
+ }
+ else if ( player->flags & FL_DOGMODE )
+ {
+ shapenum = powerpics + 1;
+ }
+ else if ( player->flags & FL_FLEET )
+ {
+ shapenum = powerpics + 2;
+ }
+ else if ( player->flags & FL_ELASTO )
+ {
+ shapenum = powerpics + 3;
+ }
+ else if ( player->flags & FL_SHROOMS )
+ {
+ shapenum = powerpics + 4;
+ }
+
+ shape = ( pic_t * )W_CacheLumpNum ( shapenum, PU_CACHE, Cvt_pic_t, 1 );
+
+ GameMemToScreen( eraseb, POWERUP1X + topBarCenterOffsetX, POWERUPY, bufferofsonly );
+
+ DrawMPPic( POWERUP1X + topBarCenterOffsetX, POWERUPY + powerupheight, shape->width,
+ shape->height - powerupheight, powerupheight,
+ ( byte * )&shape->data, bufferofsonly );
+ }
+
+
+ if ( locplayerstate->protectiontime )
+ {
+ if ( player->flags & FL_BPV )
+ {
+ shapenum = powerpics + 6;
+ }
+ else if ( player->flags & FL_GASMASK )
+ {
+ shapenum = powerpics + 5;
+ }
+ else if ( player->flags & FL_AV )
+ {
+ shapenum = powerpics + 7;
+ }
+
+ shape = ( pic_t * )W_CacheLumpNum( shapenum, PU_CACHE, Cvt_pic_t, 1 );
+
+ GameMemToScreen( eraseb, POWERUP2X + topBarCenterOffsetX, POWERUPY, bufferofsonly );
+
+ DrawMPPic( POWERUP2X + topBarCenterOffsetX, POWERUPY + protectionheight, shape->width,
+ shape->height - protectionheight, protectionheight,
+ ( byte * )&shape->data, bufferofsonly );
+ }
+}
+
+
+//******************************************************************************
+//
+// ShortenCodeName()
+//
+//******************************************************************************
+void GetShortCodeName
+(
+ char *dest,
+ char *source,
+ int maxwidth
+)
+
+{
+ int width;
+ int height;
+ int length;
+
+ strcpy( dest, source );
+
+ // Shorten name to fit
+ length = strlen( dest );
+ VW_MeasurePropString( dest, &width, &height );
+ while( width > maxwidth )
+ {
+ dest[ length ] = 0;
+ length--;
+ VW_MeasurePropString( dest, &width, &height );
+ }
+}
+
+
+//******************************************************************************
+//
+// DrawKills ()
+//
+//******************************************************************************
+void DrawKills
+(
+ boolean bufferofsonly
+)
+{
+ int rank;
+ int xpos;
+ char codename[ MAXCODENAMELENGTH ];
+ int width;
+ int playernum;
+ int playerimage;
+ int temp;
+ int iKILLS_Y;
+ pic_t *pic;
+
+ CurrentFont = tinyfont;
+
+ if ( SHOW_TOP_STATUS_BAR() )
+ {
+ playernum = BATTLE_Team[ consoleplayer ];
+ playerimage = BATTLE_TeamLeader[ playernum ];
+
+ // Set uniformcolor
+ playeruniformcolor = PLAYERSTATE[ playerimage ].uniformcolor;
+
+ // Draw player's point box
+ pic = men[ PLAYERSTATE[ playerimage ].player ];
+ if ( ( gamestate.ShowScores ) && ( BATTLE_Points[ playernum ] < 0 ) )
+ {
+ pic = menneg[ PLAYERSTATE[ playerimage ].player ];
+ }
+
+ DrawPPic( MEN_X, MEN_Y, pic->width, pic->height,
+ ( byte * )&pic->data, 1, true, bufferofsonly );
+
+ // Draw player's name
+ if ( gamestate.teamplay )
+ {
+ GetShortCodeName( codename, colorname[ playeruniformcolor ],
+ 42 );
+ }
+ else
+ {
+ GetShortCodeName( codename, PLAYERSTATE[ playerimage ].codename,
+ 42 );
+ }
+
+ DrawGameString ( MEN_X + 2, MEN_Y + 2, codename, bufferofsonly );
+ // Draw "It" if player is 'it'
+ if ( ( ( gamestate.battlemode == battle_Tag ) ||
+ ( gamestate.battlemode == battle_Hunter ) ) &&
+ ( BATTLE_It == BATTLE_Team[ consoleplayer ] ) )
+ {
+ DrawGameString ( MEN_X + 22, MEN_Y + 8,
+ "It", bufferofsonly);
+ }
+
+ // Draw triad if player is 'it' or has caught a triad
+ if ( PLAYER[ consoleplayer ]->flags & FL_DESIGNATED )
+ {
+ pic = W_CacheLumpName( "smalltri", PU_CACHE, Cvt_pic_t, 1 );
+ DrawPPic( TRIAD_X - 1, TRIAD_Y - 2, pic->width, pic->height,
+ ( byte * )&pic->data, 1, true, bufferofsonly );
+ }
+ else if ( ( gamestate.ShowScores ) &&
+ ( DisplayPoints != bo_kills_infinite ) )
+ {
+ // Draw Kill goal
+ if ( ( gamestate.battlemode == battle_Collector ) ||
+ ( gamestate.battlemode == battle_StandAloneGame ) )
+ {
+ temp = BATTLE_NumCollectorItems;
+ }
+ else
+ {
+ temp = DisplayPoints;
+ }
+
+ ltoa ( temp % 1000, KillStr.str, 10);
+ KillStr.length = strlen (KillStr.str);
+ DrawNumber (TRIAD_X - 6, TRIAD_Y, 3, 5, bufferofsonly);
+ }
+
+ // Set uniformcolor
+ playeruniformcolor = PLAYERSTATE[ consoleplayer ].uniformcolor;
+
+ if ( gamestate.ShowScores )
+ {
+ // Draw local player's points
+ temp = BATTLE_Points[ playernum ] % 1000;
+ if ( temp < 0 )
+ {
+ temp = -temp;
+ }
+ ltoa ( temp, KillStr.str, 10);
+ KillStr.length = strlen (KillStr.str);
+
+ DrawNumber( LIVES_X - 12, LIVES_Y, 3, 4, bufferofsonly);
+ }
+ else
+ {
+ pic = W_CacheLumpName( "minus", PU_CACHE, Cvt_pic_t, 1 );
+ StatusDrawColoredPic( LIVES_X - 12, LIVES_Y, pic, bufferofsonly, playeruniformcolor );
+ StatusDrawColoredPic( LIVES_X - 4, LIVES_Y, pic, bufferofsonly, playeruniformcolor );
+ }
+
+ // Draw whoever is 'It'
+ playernum = BATTLE_It;
+ playerimage = BATTLE_TeamLeader[ playernum ];
+
+ // Set uniformcolor
+ playeruniformcolor = PLAYERSTATE[ playerimage ].uniformcolor;
+
+ // Draw player's point box
+ pic = men[ PLAYERSTATE[ playerimage ].player ];
+ if ( ( gamestate.ShowScores ) && ( BATTLE_Points[ playernum ] < 0 ) )
+ {
+ pic = menneg[ PLAYERSTATE[ playerimage ].player ];
+ }
+
+ DrawPPic( LEADER_X, LEADER_Y, pic->width, pic->height,
+ (byte *)&pic->data, 1, true, bufferofsonly );
+
+ if ( ( gamestate.battlemode == battle_Tag ) ||
+ ( gamestate.battlemode == battle_Hunter ) )
+ {
+ DrawGameString ( LEADER_X + 22, LEADER_Y + 8,
+ "It", bufferofsonly);
+ }
+
+ if ( gamestate.ShowScores )
+ {
+ // Draw number of points
+ temp = BATTLE_Points[ playernum ] % 1000;
+ if ( temp < 0 )
+ {
+ temp = -temp;
+ }
+ ltoa ( temp, KillStr.str, 10);
+ KillStr.length = strlen (KillStr.str);
+ DrawNumber ( LEADER_NUM_X, LEADER_NUM_Y, 3, 4, bufferofsonly);
+ }
+ else
+ {
+ pic = W_CacheLumpName( "minus", PU_CACHE, Cvt_pic_t, 1 );
+ StatusDrawColoredPic( LEADER_NUM_X, LEADER_NUM_Y, pic, bufferofsonly, playeruniformcolor );
+ StatusDrawColoredPic( LEADER_NUM_X + 8, LEADER_NUM_Y, pic, bufferofsonly, playeruniformcolor );
+ }
+
+ // Draw name
+ if ( gamestate.teamplay )
+ {
+ DrawGameString ( LEADER_NAME_X, LEADER_NAME_Y - 1,
+ colorname[ playeruniformcolor ], bufferofsonly);
+ }
+ else
+ {
+ GetShortCodeName( codename, PLAYERSTATE[ playerimage ].codename,
+ 42 );
+ DrawGameString ( LEADER_NAME_X - 1, LEADER_NAME_Y,
+ codename, bufferofsonly);
+ }
+ }
+
+ // Only draw the rest of the rifraff when the kill count is selected
+
+ if ( !SHOW_KILLS() )
+ {
+ return;
+ }
+// SetTextMode ( );
+ // Draw all the other losers
+ //#define KILLS_Y 176
+ iKILLS_Y = iGLOBAL_SCREENHEIGHT - 24;
+ //draw blank status pic->width = 8;pic->height = 24
+ pic = blankfragpic;
+ for (temp = iGLOBAL_SCREENWIDTH-pic->width-24; temp > pic->width; temp -= pic->width) {
+ DrawPPic( temp, iKILLS_Y, pic->width, pic->height,
+ (byte *)&pic->data, 1, true, bufferofsonly );
+
+ }
+
+ xpos = KILLS_X;
+ for( rank = 0; rank < BATTLE_NumberOfTeams; rank++ )
+ {
+ playernum = BATTLE_PlayerOrder[ rank ];
+ playerimage = BATTLE_TeamLeader[ playernum ];
+
+ if ( ( playernum == BATTLE_It ) && SHOW_TOP_STATUS_BAR() )
+ {
+ continue;
+ }
+
+ // Set uniformcolor
+ playeruniformcolor = PLAYERSTATE[ playerimage ].uniformcolor;
+
+ // Draw player's point box
+ pic = fragpic[ PLAYERSTATE[ playerimage ].player ];
+ if ( gamestate.ShowScores )
+ {
+ if ( BATTLE_Points[ playernum ] < 0 )
+ {
+ pic = negfragpic[ PLAYERSTATE[ playerimage ].player ];
+ }
+ else if ( BATTLE_Points[ playernum ] >= 100 )
+ {
+ pic = frag100pic[ PLAYERSTATE[ playerimage ].player ];
+ }
+ }
+ DrawPPic( xpos, iKILLS_Y, pic->width, pic->height,
+ (byte *)&pic->data, 1, true, bufferofsonly );
+
+ // Draw number of points
+ if ( gamestate.ShowScores )
+ {
+ temp = BATTLE_Points[ playernum ] % 1000;
+ if ( temp < 0 )
+ {
+ temp = -temp;
+ }
+ ltoa ( temp, KillStr.str, 10);
+ KillStr.length = strlen (KillStr.str);
+ width = 2;
+ if ( temp > 99 )
+ {
+ width = 3;
+ }
+ DrawNumber( xpos + KILLS_OFFSET + 16 - ( 8 * width ), iKILLS_Y, width, 4, bufferofsonly);
+ }
+ else
+ {
+ pic = ( pic_t * )W_CacheLumpName( "minus", PU_CACHE, Cvt_pic_t, 1 );
+ StatusDrawColoredPic( ( xpos + KILLS_OFFSET ), iKILLS_Y, pic, bufferofsonly, playeruniformcolor );
+ StatusDrawColoredPic( ( xpos + KILLS_OFFSET + 8 ), iKILLS_Y, pic, bufferofsonly, playeruniformcolor );
+ }
+
+ // Get codename
+ if ( gamestate.teamplay )
+ {
+ GetShortCodeName( codename, colorname[ playeruniformcolor ],
+ KILLS_WIDTH - 2 );
+ }
+ else
+ {
+ GetShortCodeName( codename, PLAYERSTATE[ playerimage ].codename,
+ KILLS_WIDTH - 2 );
+ }
+
+ // Draw name
+ DrawGameString (xpos + 1, KILLS_NAME_Y, codename, bufferofsonly);
+
+ // Advance to next position
+ xpos += KILLS_WIDTH;
+
+ if ( xpos >= iGLOBAL_SCREENWIDTH )
+ {
+ break;
+ }
+ }
+
+ for( rank = BATTLE_NumberOfTeams; rank <= MAXKILLBOXES; rank++ )
+ {
+ if ( xpos >= iGLOBAL_SCREENWIDTH )
+ {
+ break;
+ }
+
+ pic = blankfragpic;
+ DrawPPic( xpos, iKILLS_Y, pic->width, pic->height,
+ (byte *)&pic->data, 1, true, bufferofsonly );
+
+ // Advance to next position
+ xpos += KILLS_WIDTH;
+ }
+}
+
+
+//******************************************************************************
+//
+// DrawPlayers ()
+//
+//******************************************************************************
+void DrawPlayers
+(
+ void
+)
+
+{
+ int num;
+ int xpos;
+ char codename[ MAXCODENAMELENGTH ];
+ int length;
+ int width;
+ int height;
+ int team;
+ int player;
+ int character;
+ pic_t *pic;
+ pic_t *enemy;
+ pic_t *friend;
+
+ num = W_GetNumForName( "botpic1" );
+
+ scorenums[ 0 ]= ( pic_t * )W_CacheLumpName( "kilnum0", PU_CACHE, Cvt_pic_t, 1 );
+ friend = ( pic_t * )W_CacheLumpName( "t_friend", PU_CACHE, Cvt_pic_t, 1 );
+ enemy = ( pic_t * )W_CacheLumpName( "t_enemy", PU_CACHE, Cvt_pic_t, 1 );
+
+ // Draw all the losers
+ CurrentFont = tinyfont;
+
+ xpos = (iGLOBAL_SCREENWIDTH - min( numplayers, MAXKILLBOXES ) * KILLS_WIDTH ) / 2;
+//SetTextMode ( );//PLAYERSTATE
+ for( team = 0; team < BATTLE_NumberOfTeams; team++ )
+ {
+ for( player = 0; player < numplayers; player++ )
+ {
+ if ( BATTLE_Team[ player ] == team )
+ {
+ character = PLAYERSTATE[ player ].player;
+
+ fragpic[ character ] = ( pic_t * )W_CacheLumpNum( num +
+ character, PU_CACHE, Cvt_pic_t, 1 );
+
+ if ( ( numplayers <= MAXKILLBOXES ) ||
+ ( player != consoleplayer ) )
+ {
+ // Set uniformcolor
+ playeruniformcolor = PLAYERSTATE[ player ].uniformcolor;
+
+ // Draw player's point box
+ pic = fragpic[ PLAYERSTATE[ player ].player ];
+
+ VWB_DrawPic ( xpos, PLAYERS_Y, pic );
+ if ( gamestate.teamplay )
+ {
+ if ( BATTLE_Team[ player ] == BATTLE_Team[ consoleplayer ] )
+ {
+ VWB_DrawPic ( xpos, PLAYERS_TEAM_Y, friend );
+ }
+ else
+ {
+ VWB_DrawPic ( xpos, PLAYERS_TEAM_Y, enemy );
+ }
+ }
+
+ strcpy( KillStr.str, "00" );
+ KillStr.length = strlen ( KillStr.str );
+ DrawNumber( xpos + KILLS_OFFSET, PLAYERS_Y, 2, 4, true );
+
+ // Get codename
+ strcpy( codename, PLAYERSTATE[ player ].codename );
+
+ // Shorten name to fit into point count
+ length = strlen( codename );
+ US_MeasureStr( &width, &height, "%s", codename );
+ while( width > KILLS_WIDTH )
+ {
+ codename[ length ] = 0;
+ length--;
+ US_MeasureStr( &width, &height, "%s", codename );
+ }
+
+ // Draw name
+ PrintX = xpos;
+ PrintY = PLAYERS_NAME_Y;
+ US_Print( codename );
+
+ // Advance to next position
+ xpos += KILLS_WIDTH;
+ }
+ }
+ if ( xpos >= iGLOBAL_SCREENWIDTH )
+ {
+ break;
+ }
+ }
+ if ( xpos >= iGLOBAL_SCREENWIDTH )
+ {
+ break;
+ }
+ }
+}
+
+//******************************************************************************
+//
+// StatusDrawPic ()
+//
+//******************************************************************************
+
+void StatusDrawPic (unsigned x, unsigned y, pic_t *nums, boolean bufferofsonly)
+{
+ DrawMPPic (x, y, nums->width, nums->height, 0,
+ (byte *)&nums->data, bufferofsonly);
+}
+
+//******************************************************************************
+//
+// StatusDrawColoredPic ()
+//
+//******************************************************************************
+
+void StatusDrawColoredPic (unsigned x, unsigned y, pic_t *nums, boolean bufferofsonly, int color)
+{
+ DrawColoredMPPic (x, y, nums->width, nums->height, 0,
+ (byte *)&nums->data, bufferofsonly, color);
+}
+
+//******************************************************************************
+//
+// DrawGameString ()
+//
+// draw string to game screen at x,y
+//
+//******************************************************************************
+
+void DrawGameString (int x, int y, const char * str, boolean bufferofsonly)
+{
+ byte *tempbuf;
+
+ px=x;
+ py=y;
+
+ if (bufferofsonly==true)
+ VW_DrawPropString (str);
+ else
+ {
+ tempbuf=bufferofs;
+ bufferofs=page1start;
+ VW_DrawPropString (str);
+#ifdef DOS
+ px=x;
+ py=y;
+ bufferofs=page2start;
+ VW_DrawPropString (str);
+ px=x;
+ py=y;
+ bufferofs=page3start;
+ VW_DrawPropString (str);
+#endif
+ bufferofs=tempbuf;
+ }
+}
+
+
+//******************************************************************************
+//
+// DrawNumber ()
+//
+// right justifies and pads with zeros
+//
+//******************************************************************************
+
+void DrawNumber (int x, int y, int width, int which, boolean bufferofsonly)
+{
+ unsigned length,c;
+ char *str;
+ byte z;
+
+ switch (which)
+ {
+ case 1:
+ str = ScoreStr.str;
+ length = ScoreStr.length;
+ break;
+
+ case 2:
+ str = LivesStr.str;
+ length = LivesStr.length;
+ break;
+
+ case 3:
+ str = TriadStr.str;
+ length = TriadStr.length;
+ break;
+
+ case 4:
+ case 5:
+ case 6:
+ str = KillStr.str;
+ length = KillStr.length;
+ break;
+ }
+
+ z = width - length; // Num zeros
+
+ while (z)
+ {
+ switch (which)
+ {
+ case 1:
+ StatusDrawPic (x, y, scorenums[0], bufferofsonly);
+ x+=8;
+ break;
+ case 2:
+ StatusDrawPic (x, y, lifenums[0], bufferofsonly);
+ x+=8;
+ break;
+ case 3:
+ StatusDrawPic (x, y, lifeptnums[0], bufferofsonly);
+ x+=6;
+ break;
+ case 4:
+ StatusDrawColoredPic (x, y, scorenums[0], bufferofsonly, playeruniformcolor);
+ x+=8;
+ break;
+ case 5:
+ StatusDrawPic (x, y, lifeptnums[0], bufferofsonly);
+ x+=6;
+ break;
+ case 6:
+ StatusDrawPic (x, y, lifenums[0], bufferofsonly);
+ x+=8;
+ break;
+ }
+ z--;
+ }
+
+ c = length <= (unsigned)width ? 0 : length-width;
+ while (c < length)
+ {
+ switch (which)
+ {
+ case 1:
+ StatusDrawPic (x, y, scorenums[str[c]-'0'], bufferofsonly);
+ x+=8;
+ break;
+ case 2:
+ StatusDrawPic (x, y, lifenums[str[c]-'0'], bufferofsonly);
+ x+=8;
+ break;
+ case 3:
+ StatusDrawPic (x, y, lifeptnums[str[c]-'0'], bufferofsonly);
+ x+=6;
+ break;
+ case 4:
+ StatusDrawColoredPic (x, y, scorenums[str[c]-'0'], bufferofsonly, playeruniformcolor);
+ x+=8;
+ break;
+ case 5:
+ StatusDrawPic (x, y, lifeptnums[str[c]-'0'], bufferofsonly);
+ x+=6;
+ break;
+ case 6:
+ StatusDrawPic (x, y, lifenums[str[c]-'0'], bufferofsonly);
+ x+=8;
+ break;
+ }
+ c++;
+ }
+}
+
+
+
+//******************************************************************************
+//
+// HealPlayer ()
+//
+//******************************************************************************
+
+void HealPlayer
+(
+ int points,
+ objtype *ob
+)
+
+{
+ playertype *pstate;
+ int maxhitpoints;
+
+ M_LINKSTATE( ob, pstate );
+
+ pstate->health += points;
+ maxhitpoints = MaxHitpointsForCharacter( pstate );
+ if ( pstate->health > maxhitpoints )
+ {
+ pstate->health = maxhitpoints;
+ }
+
+ if ( ( SHOW_BOTTOM_STATUS_BAR() ) && ( ob == player ) )
+ {
+ DrawBarHealth( false );
+ }
+}
+
+//******************************************************************************
+//
+// DrawLives ()
+//
+//******************************************************************************
+
+void DrawLives
+(
+ boolean bufferofsonly
+)
+
+{
+ if ( !SHOW_TOP_STATUS_BAR() )
+ {
+ return;
+ }
+
+ if ( !EndLevelStuff )
+ {
+ DrawNumber( LIVES_X + topBarCenterOffsetX, LIVES_Y, 2, 2, bufferofsonly );
+ }
+}
+
+
+//******************************************************************************
+//
+// GiveExtraMan ()
+//
+//******************************************************************************
+
+void GiveExtraMan (void)
+{
+ if (locplayerstate->lives < 99)
+ locplayerstate->lives++;
+ UpdateLives (locplayerstate->lives);
+ DrawLives (false);
+// SD_PlaySound (BONUS1UPSND);
+}
+
+
+
+//******************************************************************************
+//
+// DrawScore ()
+//
+//******************************************************************************
+
+void DrawScore
+(
+ boolean bufferofsonly
+)
+
+{
+ if ( !SHOW_TOP_STATUS_BAR() )
+ {
+ return;
+ }
+
+ if ( !BATTLEMODE )
+ {
+ DrawNumber( SCORE_X + topBarCenterOffsetX, SCORE_Y, 10, 1, bufferofsonly );
+ }
+}
+
+
+//******************************************************************************
+//
+// GivePoints ()
+//
+//******************************************************************************
+
+void GivePoints (long points)
+{
+ gamestate.score += points;
+
+ UpdateScore (gamestate.score);
+
+ if (!EndLevelStuff)
+ DrawScore (false);
+}
+
+
+//******************************************************************************
+//
+// GiveKey ()
+//
+//******************************************************************************
+
+void GiveKey (int key)
+{
+ locplayerstate->keys |= (1<<key);
+ DrawKeys (false);
+}
+
+
+//******************************************************************************
+//
+// GiveLives ()
+//
+//******************************************************************************
+
+void GiveLives (int newlives)
+{
+ if ((locplayerstate->lives + newlives) <= 99)
+ locplayerstate->lives += newlives;
+ else
+ locplayerstate->lives = 99;
+ UpdateLives (locplayerstate->lives);
+ DrawLives (false);
+}
+
+
+#define EnableOldWeapon(pstate) \
+ { \
+ LASTSTAT->flags |= FL_ABP; \
+ LASTSTAT->flags &= ~FL_RESPAWN; \
+ MakeStatActive(LASTSTAT); \
+ pstate->weaponx = ob->tilex; \
+ pstate->weapony = ob->tiley; \
+ }
+
+
+//******************************************************************************
+//
+// GiveWeapon ()
+//
+//******************************************************************************
+
+void GiveWeapon
+(
+ objtype *ob,
+ int weapon
+)
+
+{
+ playertype *pstate;
+
+ M_LINKSTATE( ob, pstate );
+
+ if ( pstate->weapon == weapon )
+ {
+ return;
+ }
+
+ pstate->HASBULLETWEAPON[ weapon ] = 1;
+ if ( ( pstate->weapon == pstate->bulletweapon ) &&
+ ( pstate->weapon < weapon ) )
+ {
+ pstate->new_weapon = weapon;
+ pstate->weapondowntics = WEAPONS[ pstate->weapon ].screenheight / GMOVE;
+ if ( ( ob == player ) && ( SHOW_BOTTOM_STATUS_BAR() ) )
+ {
+ DrawBarAmmo( false );
+ }
+ }
+
+ if ( gamestate.BattleOptions.WeaponPersistence )
+ {
+ SpawnStatic(ob->tilex,ob->tiley,GetItemForWeapon(weapon),9);
+ EnableOldWeapon(pstate);
+ }
+
+ if ( weapon > pstate->bulletweapon )
+ {
+ pstate->bulletweapon = weapon;
+ }
+}
+
+//LT added
+//******************************************************************************
+//
+// GivePlayerAmmo ()
+//
+//******************************************************************************
+
+
+void GivePlayerAmmo(objtype *ob, statobj_t *item_pickup, int which)
+{
+ playertype * pstate;
+
+ M_LINKSTATE(ob, pstate);
+
+ signed char * playerCurrentAmmo = pstate->ammo;
+ signed char * ammoInItem = item_pickup->ammo;
+ signed char * maxAmmoInWeapon = stats[item_pickup->itemnumber].ammo;
+ signed char newAmmoAmount = (signed char)((int)ammoInItem + (int)playerCurrentAmmo);
+
+ if (newAmmoAmount > maxAmmoInWeapon)
+ {
+ ammoInItem = (signed char)((int)newAmmoAmount - (int)maxAmmoInWeapon);
+ if (ammoInItem < 0)
+ {
+ Error("Ammo in item cannot be set to a negative number!");
+ }
+ item_pickup->ammo = ammoInItem;
+ newAmmoAmount = maxAmmoInWeapon;
+ }
+ else
+ {
+ ammoInItem = 0;
+ }
+ pstate->ammo = newAmmoAmount;
+
+ //if (!gamestate.BattleOptions.WeaponPersistence)
+ //{
+ if (pstate->ammo &&
+ (pstate->missileweapon != -1) &&
+ (!(WEAPON_IS_MAGICAL(which))) &&
+ (!(WEAPON_IS_MAGICAL(pstate->missileweapon))))
+ {
+ int nx,ny;
+
+
+ nx = ob->tilex;
+ ny = ob->tiley;
+
+ //If the missile weapon still has ammo in it after taking ammo from it, spawn it on the ground
+ if (ammoInItem)
+ {
+ if (IsPlatform(nx,ny))
+ SpawnStatic(nx,ny,GetItemForWeapon(pstate->missileweapon),9);
+ else
+ {
+ int newz = sprites[ob->tilex][ob->tiley]->z;
+ SpawnStatic(nx,ny,GetItemForWeapon(pstate->missileweapon),-1);
+ LASTSTAT->z = newz;
+ }
+
+ //update ammo count on missile weapon on ground
+ LASTSTAT->ammo = ammoInItem;
+ EnableOldWeapon(pstate);
+ }
+
+
+ }
+ //}
+}
+
+//******************************************************************************
+//
+// GiveMissileWeapon ()
+//
+//******************************************************************************
+
+void GiveMissileWeapon(objtype * ob, int which)
+{
+ playertype * pstate;
+
+
+ //pstate = (ob==player)?(&playerstate):(&remoteplayerstate);
+ M_LINKSTATE(ob,pstate);
+
+ if (!gamestate.BattleOptions.WeaponPersistence)
+ {
+ if (pstate->ammo &&
+ (pstate->missileweapon != -1) &&
+ (!(WEAPON_IS_MAGICAL(which))) &&
+ (!(WEAPON_IS_MAGICAL(pstate->missileweapon)))
+ )
+ {
+ int nx,ny;
+
+
+ nx = ob->tilex;
+ ny = ob->tiley;
+ //FindEmptyTile(&nx,&ny);
+
+ if (IsPlatform(nx,ny))
+ SpawnStatic(nx,ny,GetItemForWeapon(pstate->missileweapon),9);
+ else
+ {
+ int newz = sprites[ob->tilex][ob->tiley]->z;
+ SpawnStatic(nx,ny,GetItemForWeapon(pstate->missileweapon),-1);
+ LASTSTAT->z = newz;
+ }
+ LASTSTAT->ammo = pstate->ammo;
+ EnableOldWeapon(pstate);
+
+ }
+ }
+
+ else if (!WEAPON_IS_MAGICAL(which))
+ {
+ int newz = sprites[ob->tilex][ob->tiley]->z;
+ SpawnStatic(ob->tilex,ob->tiley,GetItemForWeapon(which),9);
+ LASTSTAT->z = newz;
+ EnableOldWeapon(pstate);
+
+ }
+ pstate->new_weapon = pstate->missileweapon = which;
+ pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/GMOVE;
+
+
+}
+
+
+//******************************************************************************
+//
+// DrawKeys ()
+//
+//******************************************************************************
+
+void DrawKeys(boolean bufferofsonly)
+{
+ if ( !SHOW_TOP_STATUS_BAR() )
+ {
+ return;
+ }
+
+ if ( locplayerstate->keys & 1 )
+ {
+ GameMemToScreen( keys[ 0 ], KeyX[ 0 ] + topBarCenterOffsetX, KEY_Y, bufferofsonly );
+ }
+
+ if ( locplayerstate->keys & 2 )
+ {
+ GameMemToScreen( keys[ 1 ], KeyX[ 1 ] + topBarCenterOffsetX, KEY_Y, bufferofsonly );
+ }
+
+ if ( locplayerstate->keys & 4 )
+ {
+ GameMemToScreen( keys[ 2 ], KeyX[ 2 ] + topBarCenterOffsetX, KEY_Y, bufferofsonly );
+ }
+
+ if ( locplayerstate->keys & 8 )
+ {
+ GameMemToScreen( keys[ 3 ], KeyX[ 3 ] + topBarCenterOffsetX, KEY_Y, bufferofsonly );
+ }
+}
+
+
+//******************************************************************************
+//
+// StatusDrawTime ()
+//
+//******************************************************************************
+
+void StatusDrawTime
+(
+ unsigned x,
+ unsigned y,
+ unsigned num,
+ boolean bufferofsonly
+)
+
+{
+ DrawMPPic( x, y, timenums[ num ]->width, timenums[ num ]->height, 0,
+ ( byte * )&timenums[ num ]->data, bufferofsonly );
+}
+
+
+//******************************************************************************
+//
+// DrawTimeNumber ()
+//
+// right justifies and pads with blanks
+//
+//******************************************************************************
+
+void DrawTimeNumber (int x, int y, int number, boolean seconds, boolean bufferofsonly)
+{
+ char str[20];
+
+ ltoa (number,str,10);
+
+ if (seconds)
+ {
+ if (number < 10)
+ {
+ StatusDrawTime (x, y, 0, bufferofsonly);
+ StatusDrawTime (x+8, y, str[0]-'0', bufferofsonly);
+ }
+ else
+ {
+ StatusDrawTime (x, y, str[0]-'0', bufferofsonly);
+ StatusDrawTime (x+8, y, str[1]-'0', bufferofsonly);
+ }
+ }
+ else
+ {
+ if (number < 10)
+ StatusDrawTime (x+8, y, str[0]-'0', bufferofsonly);
+ else
+ {
+ StatusDrawTime (x, y, str[0]-'0', bufferofsonly);
+ StatusDrawTime (x+8, y, str[1]-'0', bufferofsonly);
+ }
+ }
+}
+
+
+//******************************************************************************
+//
+// DrawTimeXY ()
+//
+//******************************************************************************
+
+void DrawTimeXY
+(
+ int x,
+ int y,
+ int sec,
+ boolean bufferofsonly
+)
+
+{
+ int min;
+ int hour;
+
+ while (sec > ( ( 9 * 3600 ) + 3599 ) )
+ {
+ sec -= ( ( 9 * 3600 ) + 3599 );
+ }
+
+ hour = sec / 3600;
+ min = ( sec / 60 ) - ( hour * 60 );
+ sec %= 60;
+
+ DrawTimeNumber ( x + HOUR_X, y, hour, false, bufferofsonly );
+ DrawTimeNumber ( x + MIN_X, y, min, true, bufferofsonly );
+ DrawTimeNumber ( x + SEC_X, y, sec, true, bufferofsonly );
+}
+
+
+//******************************************************************************
+//
+// DrawTime ()
+//
+//******************************************************************************
+
+void DrawTime
+(
+ boolean bufferofsonly
+)
+
+{
+ int sec;
+
+ if ( !SHOW_TOP_STATUS_BAR() )
+ {
+ return;
+ }
+
+ if (timelimitenabled == true)
+ {
+ sec = (timelimit-gamestate.TimeCount) / VBLCOUNTER;
+ }
+ else
+ {
+ sec = gamestate.TimeCount / VBLCOUNTER;
+ }
+
+ if ( oldsec != sec )
+ {
+ oldsec = sec;
+ DrawTimeXY( GAMETIME_X + topBarCenterOffsetX, GAMETIME_Y, sec, bufferofsonly) ;
+ }
+}
+
+
+//******************************************************************************
+//
+// DrawMPPic ()
+//
+// Purpose
+// Draws a masked, planer pic at xpos, ypos.
+//
+// Parms
+// xpos - x position.
+// ypos - y position.
+// width - width of pic : should be << 2.
+// height - height of pic.
+// src - data to draw.
+//
+// Returns
+// Nothing.
+//
+//******************************************************************************
+
+void DrawMPPic (int xpos, int ypos, int width, int height, int heightmod, byte *src, boolean bufferofsonly)
+{
+ int olddest;
+ int dest;
+ int x;
+ int y;
+ int planes;
+ byte mask;
+ byte pixel;
+
+ mask = 1 << (xpos&3);
+
+#ifdef DOS
+ olddest = ylookup[ypos] + (xpos>>2);
+#else
+ olddest = ylookup[ypos] + xpos;
+#endif
+
+ for (planes = 0; planes < 4; planes++)
+ {
+ VGAMAPMASK (mask);
+
+ dest = olddest;
+
+#ifndef DOS
+ dest += planes;
+#endif
+
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < width; x++)
+ {
+ pixel = *src++;
+
+ if (pixel != 255)
+ {
+ if (bufferofsonly)
+ *(dest+bufferofs) = pixel;
+ else
+ {
+ *(dest+page1start) = pixel;
+ *(dest+page2start) = pixel;
+ *(dest+page3start) = pixel;
+ }
+ }
+
+#ifdef DOS
+ dest++;
+#else
+ dest += 4;
+#endif
+ }
+
+#ifdef DOS
+ dest += (linewidth-width);
+#else
+ dest += (linewidth-width*4);
+#endif
+ }
+
+ if (heightmod)
+ src += (heightmod*width);
+
+#ifdef DOS
+ mask <<= 1;
+ if (mask == 16)
+ {
+ mask = 1;
+ olddest++;
+ }
+#endif
+ }
+}
+
+
+//******************************************************************************
+//
+// DrawColoredMPPic ()
+//
+// Purpose
+// Draws a masked, planer pic at xpos, ypos.
+//
+// Parms
+// xpos - x position.
+// ypos - y position.
+// width - width of pic : should be << 2.
+// height - height of pic.
+// src - data to draw.
+//
+// Returns
+// Nothing.
+//
+//******************************************************************************
+
+void DrawColoredMPPic (int xpos, int ypos, int width, int height, int heightmod, byte *src, boolean bufferofsonly, int color)
+{
+ int olddest;
+ int dest;
+ int x;
+ int y;
+ int planes;
+ byte mask;
+ byte pixel;
+ byte * cmap;
+
+ cmap=playermaps[color]+(1<<12);
+
+ mask = 1 << (xpos&3);
+
+#ifdef DOS
+ olddest = ylookup[ypos] + (xpos>>2);
+#else
+ olddest = ylookup[ypos] + xpos;
+#endif
+
+ for (planes = 0; planes < 4; planes++)
+ {
+ VGAMAPMASK (mask);
+
+ dest = olddest;
+
+#ifndef DOS
+ dest += planes;
+#endif
+
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < width; x++)
+ {
+ pixel = *src++;
+
+ pixel = *(cmap+pixel);
+
+ if (pixel != 255)
+ {
+ if (bufferofsonly)
+ *(dest+bufferofs) = pixel;
+ else
+ {
+ *(dest+page1start) = pixel;
+ *(dest+page2start) = pixel;
+ *(dest+page3start) = pixel;
+ }
+ }
+
+#ifdef DOS
+ dest++;
+#else
+ dest += 4;
+#endif
+ }
+
+#ifdef DOS
+ dest += (linewidth-width);
+#else
+ dest += (linewidth-width*4);
+#endif
+ }
+
+ if (heightmod)
+ src += (heightmod*width);
+
+#ifdef DOS
+ mask <<= 1;
+ if (mask == 16)
+ {
+ mask = 1;
+ olddest++;
+ }
+#endif
+ }
+}
+
+
+//******************************************************************************
+//
+// UpdateScore ()
+//
+//******************************************************************************
+
+void UpdateScore (unsigned int num)
+{
+ if (num > 999999999)
+ {
+ num = 999999999;
+ gamestate.score = 999999999;
+ }
+
+ ltoa (num, ScoreStr.str, 10);
+ ScoreStr.length = strlen (ScoreStr.str);
+}
+
+
+//******************************************************************************
+//
+// UpdateLives ()
+//
+//******************************************************************************
+
+void UpdateLives (int num)
+{
+ ltoa (num, LivesStr.str, 10);
+ LivesStr.length = strlen (LivesStr.str);
+}
+
+//****************************************************************************
+//
+// ClearTriads ()
+//
+//****************************************************************************
+void ClearTriads (playertype * pstate)
+{
+ pstate->triads = 0;
+ ltoa (pstate->triads, TriadStr.str, 10);
+ TriadStr.length = strlen (TriadStr.str);
+}
+
+//****************************************************************************
+//
+// UpdateTriads ()
+//
+//****************************************************************************
+
+void UpdateTriads (objtype * ob, int num)
+{
+ playertype * pstate;
+
+ M_LINKSTATE(ob,pstate);
+
+ pstate->triads += num;
+
+ if (pstate->triads >= 100)
+ {
+ GiveLives(1);
+ if (ob==player)
+ {
+ AddMessage("100 Life Item Points! Extra Life!",MSG_BONUS);
+ SD_PlaySoundRTP (SD_GET1UPSND, player->x, player->y);
+ }
+ pstate->triads -= 100;
+ }
+
+ if (ob==player)
+ {
+ ltoa (pstate->triads, TriadStr.str, 10);
+ TriadStr.length = strlen (TriadStr.str);
+ }
+}
+
+//****************************************************************************
+//
+// DrawTriads ()
+//
+//****************************************************************************
+
+void DrawTriads(boolean bufferofsonly)
+
+{
+ if ( !SHOW_TOP_STATUS_BAR() )
+ {
+ return;
+ }
+
+ if ( !EndLevelStuff )
+ {
+ DrawNumber( TRIAD_X + topBarCenterOffsetX, TRIAD_Y, 2, 3, bufferofsonly );
+ }
+}
+
+
+//******************************************************************************
+//
+// DrawPPic ()
+//
+//******************************************************************************
+
+void DrawPPic (int xpos, int ypos, int width, int height, byte *src, int num, boolean up, boolean bufferofsonly)
+{
+ int olddest;
+ int dest;
+ int x;
+ int y;
+ int planes;
+ byte mask;
+ byte pixel;
+ int k;
+ int amt;
+
+#ifdef DOS
+ if (up)
+ amt = 2;
+ else
+ amt = -2;
+#else
+ if (up)
+ amt = 8;
+ else
+ amt = -8;
+#endif
+
+ mask = 1;
+
+#ifdef DOS
+ olddest = ylookup[ypos] + (xpos>>2);
+#else
+ olddest = ylookup[ypos] + xpos;
+#endif
+
+ for (planes = 0; planes < 4; planes++)
+ {
+ VGAMAPMASK (mask);
+
+ dest = olddest;
+
+#ifndef DOS
+ dest += planes;
+#endif
+
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < width; x++)
+ {
+ pixel = *src++;
+
+ if (pixel != 255)
+ {
+ for (k = 0; k < num; k++)
+ {
+ if (bufferofsonly)
+ *(dest+bufferofs+(amt*k)) = pixel;
+ else
+ {
+ *(dest+page1start+(amt*k)) = pixel;
+ *(dest+page2start+(amt*k)) = pixel;
+ *(dest+page3start+(amt*k)) = pixel;
+ }
+ }
+ }
+
+#ifdef DOS
+ dest++;
+#else
+ dest += 4;
+#endif
+ }
+
+#ifdef DOS
+ dest += (linewidth-width);
+#else
+ dest += (linewidth-width*4);
+#endif
+ }
+
+ mask <<= 1;
+ }
+}
+
+
+//****************************************************************************
+//
+// DrawBarHealth ()
+//
+//****************************************************************************
+
+void DrawBarHealth
+(
+ boolean bufferofsonly
+)
+
+{
+ int percenthealth;
+ int health_y;
+
+ if ( !SHOW_BOTTOM_STATUS_BAR() )
+ {
+ return;
+ }
+
+ health_y = iGLOBAL_HEALTH_Y;
+ if ( SHOW_KILLS() )
+ {
+ health_y -= KILLS_HEIGHT;
+ }
+
+ percenthealth = ( locplayerstate->health * 10 ) /
+ MaxHitpointsForCharacter( locplayerstate );
+
+ oldpercenthealth = percenthealth + 1;
+
+ if ( playstate == ex_died )
+ {
+ DrawPPic( iGLOBAL_HEALTH_X, health_y, 8 >> 2, 16, ( byte * )&erase->data,
+ 10, true, bufferofsonly );
+
+ return;
+ }
+
+ if ( locplayerstate->health <= 0 )
+ {
+ oldpercenthealth = 0;
+ }
+
+ if ( oldpercenthealth >= 11 )
+ {
+ oldpercenthealth = 10;
+ }
+
+ if ( oldpercenthealth < 4 )
+ {
+ DrawPPic( iGLOBAL_HEALTH_X, health_y, 8 >> 2, 16,
+ ( byte * )&health[ 0 ]->data, oldpercenthealth,
+ true, bufferofsonly );
+ }
+ else if ( oldpercenthealth < 5 )
+ {
+ DrawPPic( iGLOBAL_HEALTH_X, health_y, 8 >> 2, 16,
+ (byte *)&health[ 1 ]->data, oldpercenthealth,
+ true, bufferofsonly );
+ }
+ else
+ {
+ DrawPPic( iGLOBAL_HEALTH_X, health_y, 8 >> 2, 16,
+ ( byte * )&health[ 2 ]->data, oldpercenthealth,
+ true, bufferofsonly );
+ }
+
+ if ( oldpercenthealth < 10 )
+ {
+ DrawPPic( iGLOBAL_HEALTH_X + ( 8 * oldpercenthealth ), health_y,
+ 8 >> 2, 16, ( byte * )&erase->data, 10 - oldpercenthealth,
+ true, bufferofsonly );
+ }
+}
+
+
+//****************************************************************************
+//
+// DrawBarAmmo ()
+//
+//****************************************************************************
+
+void DrawBarAmmo(boolean bufferofsonly)
+{
+ int ammo_y;
+
+ if ( ( !SHOW_BOTTOM_STATUS_BAR() ) || ( playstate == ex_died ) )
+ {
+ return;
+ }
+
+ ammo_y = iGLOBAL_AMMO_Y;
+ if ( SHOW_KILLS() )
+ {
+ ammo_y -= KILLS_HEIGHT;
+ }
+
+ DrawPPic ( iGLOBAL_AMMO_X, ammo_y + 1, 8 >> 2, 16, ( byte * )&erase->data,
+ 10, false, bufferofsonly );
+
+ if ( !ARMED( player->dirchoosetime ) )
+ {
+ return;
+ }
+ if ((locplayerstate->new_weapon < wp_bazooka) ||
+ (locplayerstate->new_weapon == wp_godhand) ||
+ ( gamestate.BattleOptions.Ammo == bo_infinite_shots )
+ )
+ {
+ DrawPPic( iGLOBAL_AMMO_X - 16, ammo_y, 24 >> 2, 16,
+ ( byte * )&ammo[ 0 ]->data, 1, true, bufferofsonly);
+
+ DrawPPic( iGLOBAL_AMMO_X - 32, ammo_y + 1, 8 >> 2, 16,
+ ( byte * )&erase->data, 2, true, bufferofsonly );
+ }
+#if (SHAREWARE == 0)
+ else if ( locplayerstate->new_weapon == wp_dog )
+ {
+ DrawPPic( iGLOBAL_AMMO_X - 16, ammo_y, 24 >> 2, 16,
+ ( byte * )&ammo[12]->data, 1, true, bufferofsonly );
+
+ DrawPPic( iGLOBAL_AMMO_X - 32, ammo_y + 1, 8 >> 2, 16,
+ ( byte * )&erase->data, 2, true, bufferofsonly );
+ }
+#endif
+ else
+ {
+ DrawPPic( iGLOBAL_AMMO_X, ammo_y + 1, 8 >> 2, 16,
+ ( byte * )&ammo[ locplayerstate->new_weapon]->data,
+ locplayerstate->ammo, false, bufferofsonly );
+ }
+}
+
+
+//******************************************************************************
+//
+// SingleDrawPPic ()
+//
+//******************************************************************************
+
+void SingleDrawPPic (int xpos, int ypos, int width, int height, byte *src, int num, boolean up)
+{
+ byte *olddest;
+ byte *dest;
+ int x;
+ int y;
+ int planes;
+ byte mask;
+ byte pixel;
+ int k;
+ int amt;
+
+#ifdef DOS
+ if (up)
+ amt = 2;
+ else
+ amt = -2;
+#else
+ if (up)
+ amt = 8;
+ else
+ amt = -8;
+#endif
+
+ mask = 1;
+
+#ifdef DOS
+ olddest = (byte *)(bufferofs - screenofs + ylookup[ypos] + (xpos>>2));
+#else
+ olddest = (byte *)(bufferofs - screenofs + ylookup[ypos] + xpos);
+#endif
+
+ for (planes = 0; planes < 4; planes++)
+ {
+ VGAMAPMASK (mask);
+
+ dest = olddest;
+
+#ifndef DOS
+ dest += planes;
+#endif
+
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < width; x++)
+ {
+ pixel = *src++;
+
+ if (pixel != 255)
+ {
+ for (k = 0; k < num; k++)
+ {
+ *(dest+(amt*k)) = pixel;
+ }
+ }
+
+#ifdef DOS
+ dest++;
+#else
+ dest += 4;
+#endif
+ }
+
+#ifdef DOS
+ dest += (linewidth-width);
+#else
+ dest += (linewidth-width*4);
+#endif
+ }
+
+ mask <<= 1;
+ }
+}
+
+
+
+//****************************************************************************
+//
+// DrawStats ()
+//
+//****************************************************************************
+
+void DrawStats
+(
+ void
+)
+
+{
+ int percenthealth;
+ int health_y;
+ int ammo_y;
+
+ if ( ( !SHOW_PLAYER_STATS() ) || ( playstate == ex_died ) ||
+ ( locplayerstate->health <= 0 ) )
+ {
+ return;
+ }
+
+// Uncomment this if we want transparent health only on sizes < 16
+// if ( viewsize < 16 )
+// {
+// pic_t *shape;
+//
+// shape = W_CacheLumpName( "backtile", PU_CACHE );
+// DrawTiledRegion( 0, 160, 320, 24, shape );
+// }
+
+ health_y = iGLOBAL_HEALTH_Y;
+ ammo_y = iGLOBAL_AMMO_Y;
+
+ if ( SHOW_KILLS() )
+ {
+ health_y -= KILLS_HEIGHT;
+ ammo_y -= KILLS_HEIGHT;
+ }
+
+ if ( oldplayerhealth != locplayerstate->health )
+ {
+ oldplayerhealth = locplayerstate->health;
+
+ percenthealth = ( locplayerstate->health * 10 ) /
+ MaxHitpointsForCharacter( locplayerstate );
+
+ oldpercenthealth = percenthealth + 1;
+ }
+
+ if ( oldpercenthealth > 10 )
+ {
+ oldpercenthealth = 10;
+ }
+
+ if ( oldpercenthealth < 4 )
+ {
+ SingleDrawPPic( iGLOBAL_HEALTH_X - 16, health_y, 8 >> 2, 16,
+ ( byte * )&health[ 3 ]->data, oldpercenthealth, true);
+ }
+ else if ( oldpercenthealth < 5 )
+ {
+ SingleDrawPPic( iGLOBAL_HEALTH_X - 16, health_y, 8 >> 2, 16,
+ ( byte * )&health[ 4 ]->data, oldpercenthealth, true );
+ }
+ else
+ {
+ SingleDrawPPic( iGLOBAL_HEALTH_X - 16, health_y, 8 >> 2, 16,
+ ( byte * )&health[ 5 ]->data, oldpercenthealth, true );
+ }
+
+ if ( ARMED( consoleplayer ) )
+ {
+ if ((locplayerstate->new_weapon < wp_bazooka) ||
+ (locplayerstate->new_weapon == wp_godhand) ||
+ (gamestate.BattleOptions.Ammo == bo_infinite_shots )
+ )
+
+ {
+ SingleDrawPPic( iGLOBAL_AMMO_X - 16, ammo_y, 24 >> 2, 16,
+ ( byte * )&ammo[13]->data, 1, true );
+ }
+#if (SHAREWARE == 0)
+ else if ( locplayerstate->new_weapon == wp_dog )
+ {
+ SingleDrawPPic( iGLOBAL_AMMO_X - 16, ammo_y + 1, 24 >> 2, 16,
+ ( byte * )&ammo[25]->data, 1, true );
+ }
+#endif
+ else
+ {
+ SingleDrawPPic( iGLOBAL_AMMO_X, ammo_y + 1, 8 >> 2, 16,
+ ( byte * )&ammo[13 + locplayerstate->new_weapon]->data,
+ locplayerstate->ammo, false );
+ }
+ }
+}
+
+
+//****************************************************************************
+//
+// DrawPauseXY ()
+//
+//****************************************************************************
+
+void DrawPauseXY (int x, int y)
+{
+ pic_t *p;
+ byte *buftmp;
+
+ buftmp = bufferofs;
+
+ if (GamePaused == true)
+ {
+ p = (pic_t *) W_CacheLumpNum (W_GetNumForName ("paused"), PU_CACHE, Cvt_pic_t, 1);
+ VL_MemToScreen ((byte *)&p->data, p->width, p->height,x, y);
+ //VWB_DrawPic (x, y, p);
+ bufferofs = buftmp;
+ DrawEpisodeLevel (x,y);
+ //VL_MemToScreen ((byte *)&p->data, p->width, p->height,x, y);
+
+ }
+ else
+ {
+ p = (pic_t *) W_CacheLumpNum (W_GetNumForName ("wait"), PU_CACHE, Cvt_pic_t, 1);
+ VL_MemToScreen ((byte *)&p->data, p->width, p->height,x, y);
+ //VWB_DrawPic (x, y, p);
+ }
+ bufferofs = buftmp;
+}
+
+//****************************************************************************
+//
+// DrawPause ()
+//
+//****************************************************************************
+
+void DrawPause (void)
+{
+ pic_t *p;
+ byte *bufftemp = bufferofs;
+
+ bufferofs -= screenofs;
+
+ if (GamePaused == true)
+ {
+ bufferofs = bufftemp;
+ p = (pic_t *) W_CacheLumpNum (W_GetNumForName ("paused"), PU_CACHE, Cvt_pic_t, 1);
+ DrawPauseXY( (iGLOBAL_SCREENWIDTH-(p->width<<2) ) >>1, (iGLOBAL_SCREENHEIGHT-p->height)>>1);//bna++
+ //DrawPauseXY( (320-(p->width<<2) ) >>1, (200-p->height)>>1);
+ /*
+ //buf = (byte *) SafeMalloc (64000);
+ w = p->width;
+ h = p->height;
+ x = (iGLOBAL_SCREENWIDTH-((p->width)<<2) ) >>1;
+ y = (iGLOBAL_SCREENHEIGHT-(p->height))>>1;
+
+ x1 = (iGLOBAL_SCREENWIDTH-((p->width*2)<<2) ) >>1;
+ y1 = (iGLOBAL_SCREENHEIGHT-(p->height*2))>>1;
+
+ source = bufferofs + (iGLOBAL_SCREENWIDTH*y)+x;
+ target = bufferofs + (iGLOBAL_SCREENWIDTH*y1)+x1;
+
+ // memcpy(tmpPICbuf,bufftemp,iGLOBAL_SCREENWIDTH*iGLOBAL_SCREENHEIGHT);
+
+ bufferofs = bufftemp;//(byte *)tmpPICbuf;//buf;//write picture in tmpbuf
+ VL_MemToScreen ((byte *)&p->data, p->width, p->height,x, y);
+ bufferofs = bufftemp;
+ DrawEpisodeLevel (x,y);
+
+
+ //VL_MemStrechedToScreen ((byte *)&p->data, p->width, p->height,(iGLOBAL_SCREENWIDTH-((p->width*2)<<2) ) >>1, (iGLOBAL_SCREENHEIGHT-(p->height*2))>>1);
+ //DrawEpisodeLevel (x,y);
+
+ //VL_MemToScreen ((byte *)&p->data, p->width, p->height,0, 0);
+ //bufferofs = bufftemp;//move ptr back
+ //write it back to bufferofs while streching
+
+ //buf = bufftemp;
+ //b = tmpPICbuf ;
+
+ source = bufferofs + (iGLOBAL_SCREENWIDTH*y)+x+(w*4);
+ target = bufferofs + (iGLOBAL_SCREENWIDTH*y1)+x+(2*w*4);
+
+ //first strech lines in x direction
+ for (y=0;y<h;y++){
+ c=target;t2=source;
+ for (x=0;x<w*4;x++){
+ *target-- = *source;
+ *target-- = *source--;
+ }
+ target=c;source=t2;
+ target += iGLOBAL_SCREENWIDTH;
+ source += iGLOBAL_SCREENWIDTH;
+ }
+ //strech then lines in y direction
+ source -= ((iGLOBAL_SCREENWIDTH*(y/2))+(w*4));//bufferofs + (iGLOBAL_SCREENWIDTH*y)+x+(iGLOBAL_SCREENWIDTH*(y));
+ target = (source+(iGLOBAL_SCREENWIDTH*(y))+1);//bufferofs + (iGLOBAL_SCREENWIDTH*y)+x+(iGLOBAL_SCREENWIDTH*(y1));
+
+ for (y=0;y<h;y++){
+ memcpy(target,source,(w*4*2));
+ memcpy(target+iGLOBAL_SCREENWIDTH,source,(w*4*2));
+
+ target -= iGLOBAL_SCREENWIDTH*2;
+ source -= iGLOBAL_SCREENWIDTH;
+ }
+
+ / *
+ for (y=0;y<h;y++){
+ c=target;t2=source;
+ for (x=0;x<w*4;x++){
+ *target = *source;
+ *(target+++iGLOBAL_SCREENWIDTH) = *source;
+ *target = *source;
+ *(target+++iGLOBAL_SCREENWIDTH) = *source;
+ source++;
+ }
+ target=c;source=t2;
+ target += iGLOBAL_SCREENWIDTH*2;
+ source += iGLOBAL_SCREENWIDTH;
+ }
+ */
+
+// memcpy( bufftemp,tmpPICbuf,iGLOBAL_SCREENWIDTH*iGLOBAL_SCREENHEIGHT);
+
+ }
+ else
+ {
+ p = (pic_t *) W_CacheLumpNum (W_GetNumForName ("wait"), PU_CACHE, Cvt_pic_t, 1);
+ DrawPauseXY( (iGLOBAL_SCREENWIDTH-(p->width<<2) ) >>1, (iGLOBAL_SCREENHEIGHT-p->height)>>1);//bna++
+ //DrawPauseXY( (320-(p->width<<2) ) >>1, (200-p->height)>>1);
+ }
+// VH_UpdateScreen () ;
+
+ bufferofs = bufftemp;
+}
+
+//****************************************************************************
+//
+// GM_DrawBonus ()
+//
+//****************************************************************************
+
+void GM_DrawBonus
+(
+ int which
+)
+
+{
+ int x;
+
+ if ( which < stat_gasmask )
+ {
+ x = POWERUP1X;
+ poweruptime = GetBonusTimeForItem(which);
+ poweradjust = (poweruptime >> 4);
+ powerupheight = 0;
+ GM_UpdateBonus(poweruptime-poweradjust - 1,true);
+
+ }
+ else
+ {
+ x = POWERUP2X;
+ protectiontime = GetBonusTimeForItem(which);
+ poweradjust = (protectiontime >> 4);
+ protectionheight = 0;
+ GM_UpdateBonus(protectiontime-poweradjust-1,false);
+
+ }
+
+}
+
+
+//******************************************************************************
+//
+// GM_UpdateBonus ()
+//
+//******************************************************************************
+
+void GM_UpdateBonus
+(
+ int time,
+ int powerup
+)
+
+{
+ pic_t *shape;
+ int shapenum;
+
+ if ( powerup )
+ {
+ if ( time < ( poweruptime - poweradjust ) )
+ {
+ powerupheight++;
+ if ( !SHOW_TOP_STATUS_BAR() )
+ {
+ poweruptime = time;
+ }
+ }
+ }
+ else
+ {
+ if ( time < ( protectiontime - poweradjust ) )
+ {
+ protectionheight++;
+ if ( !SHOW_TOP_STATUS_BAR() )
+ {
+ protectiontime = time;
+ }
+ }
+ }
+
+
+ if ( !SHOW_TOP_STATUS_BAR() )
+ {
+ return;
+ }
+
+ if ( !time )
+ {
+ if ( powerup == 1 )
+ {
+ shapenum = POWERUP1X;
+ }
+ else
+ {
+ shapenum = POWERUP2X;
+ }
+
+ GM_MemToScreen( ( byte * )&eraseb->data, eraseb->width,
+ eraseb->height, shapenum + topBarCenterOffsetX, POWERUPY );
+
+ return;
+ }
+
+ if ( powerup )
+ {
+ if ( time < ( poweruptime - poweradjust ) )
+ {
+ if ( player->flags & FL_GODMODE )
+ {
+ shapenum = powerpics;
+ }
+ else if ( player->flags & FL_DOGMODE )
+ {
+ shapenum = powerpics + 1;
+ }
+ else if ( player->flags & FL_FLEET )
+ {
+ shapenum = powerpics + 2;
+ }
+ else if ( player->flags & FL_ELASTO )
+ {
+ shapenum = powerpics + 3;
+ }
+ else if ( player->flags & FL_SHROOMS )
+ {
+ shapenum = powerpics + 4;
+ }
+ else
+ {
+ GM_MemToScreen( ( byte * )&eraseb->data,
+ eraseb->width, eraseb->height, POWERUP1X + topBarCenterOffsetX, POWERUPY );
+
+ return;
+ }
+
+ poweruptime = time;
+
+ shape = ( pic_t * )W_CacheLumpNum( shapenum, PU_CACHE, Cvt_pic_t, 1 );
+
+ GM_MemToScreen( ( byte * )&eraseb->data, eraseb->width,
+ eraseb->height, POWERUP1X + topBarCenterOffsetX, POWERUPY );
+
+ DrawMPPic( POWERUP1X + topBarCenterOffsetX, POWERUPY + powerupheight, shape->width,
+ shape->height - powerupheight, powerupheight,
+ ( byte * )&shape->data, false );
+ }
+ }
+ else
+ {
+ if ( time < ( protectiontime - poweradjust ) )
+ {
+ if ( player->flags & FL_BPV )
+ {
+ shapenum = powerpics + 6;
+ }
+ else if ( player->flags & FL_GASMASK )
+ {
+ shapenum = powerpics + 5;
+ }
+ else if ( player->flags & FL_AV )
+ {
+ shapenum = powerpics + 7;
+ }
+
+ protectiontime = time;
+
+ shape = ( pic_t * )W_CacheLumpNum( shapenum, PU_CACHE, Cvt_pic_t, 1 );
+
+ GM_MemToScreen( ( byte * )&eraseb->data, eraseb->width,
+ eraseb->height, POWERUP2X + topBarCenterOffsetX, POWERUPY );
+
+ DrawMPPic( POWERUP2X + topBarCenterOffsetX, POWERUPY + protectionheight,
+ shape->width, shape->height - protectionheight,
+ protectionheight, ( byte * )&shape->data, false );
+ }
+ }
+}
+
+
+//******************************************************************************
+//
+// Drawpic ()
+//
+// Purpose
+// Draws a masked, planer pic at xpos, ypos.
+//
+// Parms
+// xpos - x position.
+// ypos - y position.
+// width - width of pic : should be << 2.
+// height - height of pic.
+// src - data to draw.
+//
+// Returns
+// Nothing.
+//
+//******************************************************************************
+
+void Drawpic (int xpos, int ypos, int width, int height, byte *src)
+{
+ byte *olddest;
+ byte *dest;
+ int x;
+ int y;
+ int planes;
+ byte mask;
+ byte pixel;
+
+
+ mask = 1 << (xpos&3);
+
+#ifdef DOS
+ olddest = (byte *)(bufferofs + ylookup[ypos] + (xpos>>2));
+#else
+ olddest = (byte *)(bufferofs + ylookup[ypos] + xpos);
+#endif
+ for (planes = 0; planes < 4; planes++)
+ {
+ VGAMAPMASK (mask);
+
+ dest = olddest;
+
+#ifdef DOS
+ dest += planes;
+#endif
+
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < width; x++)
+ {
+ pixel = *src++;
+
+ if (pixel != 255)
+ *(dest) = pixel;
+
+#ifdef DOS
+ dest++;
+#else
+ dest += 4;
+#endif
+ }
+
+#ifdef DOS
+ dest += (linewidth-width);
+#else
+ dest += (linewidth-width*4);
+#endif
+ }
+
+#ifdef DOS
+ mask <<= 1;
+ if (mask == 16)
+ {
+ mask = 1;
+ olddest++;
+ }
+#endif
+ }
+}
+
+
+//******************************************************************************
+//
+// DrawEpisodeLevel ()
+//
+// right justifies and pads with blanks
+//
+//******************************************************************************
+
+void DrawEpisodeLevel (int x, int y)
+{
+ int level;
+ char str[20];
+ pic_t *p;
+
+ if (!BATTLEMODE)
+ {
+ ltoa (gamestate.episode, str, 10);
+
+ //bna-- Drawpic (x+29, y+16, 8>>2, 16, (byte *)&timenums[str[0]-'0']->data);
+ VL_MemToScreenClipped ((byte *)&timenums[str[0]-'0']->data, 8>>2, 16, x+29, y+16);
+
+ if ((gamestate.mapon == 6) || (gamestate.mapon == 14) ||
+ (gamestate.mapon == 22) || (gamestate.mapon == 32) ||
+ (gamestate.mapon == 33))
+ {
+ p = (pic_t *) W_CacheLumpName ("tnumb", PU_CACHE, Cvt_pic_t, 1);
+ //Drawpic (x+40, y+16, 8>>2, 16, (byte *)&p->data);
+ VL_MemToScreenClipped ((byte *)&p->data, 8>>2, 16, x+40, y+16);
+
+ if (gamestate.mapon == 6)
+ level = 1;
+ else if (gamestate.mapon == 14)
+ level = 2;
+ else if (gamestate.mapon == 22)
+ level = 3;
+ else if (gamestate.mapon == 32)
+ level = 4;
+ else
+ level = 5;
+ }
+ else
+ level = GetLevel (gamestate.episode, gamestate.mapon);
+
+ level = abs(level);
+ ltoa (level, str, 10);
+
+ if (level < 10) {
+ //Drawpic (x+49, y+16, 8>>2, 16, (byte *)&timenums[str[0]-'0']->data);
+ VL_MemToScreenClipped ((byte *)&timenums[str[0]-'0']->data, 8>>2, 16, x+49, y+16);
+ } else {
+ //Drawpic (x+49, y+16, 8>>2, 16, (byte *)&timenums[str[0]-'0']->data);
+ VL_MemToScreenClipped ((byte *)&timenums[str[0]-'0']->data, 8>>2, 16, x+49, y+16);
+ //Drawpic (x+57, y+16, 8>>2, 16, (byte *)&timenums[str[1]-'0']->data);
+ VL_MemToScreenClipped ((byte *)&timenums[str[1]-'0']->data, 8>>2, 16, x+57, y+16);
+
+ }
+ }
+ else
+ {
+ p = (pic_t *) W_CacheLumpName ("battp", PU_CACHE, Cvt_pic_t, 1);
+ //Drawpic (x+16, y+15, 32>>2, 16, (byte *)&p->data);
+ VL_MemToScreenClipped ((byte *)&p->data, 32>>2, 16, x+16, y+15);
+
+ level = abs(gamestate.mapon + 1);
+ ltoa (level, str, 10);
+
+ if (level < 10) {
+ //Drawpic (x+49, y+16, 8>>2, 16, (byte *)&timenums[str[0]-'0']->data);
+ VL_MemToScreenClipped ((byte *)&timenums[str[0]-'0']->data, 8>>2, 16, x+49, y+16);
+ } else {
+ //Drawpic (x+49, y+16, 8>>2, 16, (byte *)&timenums[str[0]-'0']->data);
+ VL_MemToScreenClipped ((byte *)&timenums[str[0]-'0']->data, 8>>2, 16, x+49, y+16);
+ //Drawpic (x+57, y+16, 8>>2, 16, (byte *)&timenums[str[1]-'0']->data);
+ VL_MemToScreenClipped ((byte *)&timenums[str[1]-'0']->data, 8>>2, 16, x+57, y+16);
+ }
+ }
+}
+
+
+//******************************************************************************
+//
+// GM_MemToScreen ()
+//
+//******************************************************************************
+
+void GM_MemToScreen (byte *source, int width, int height, int x, int y)
+{
+ int dest;
+ byte *dest1, *dest2, *dest3, mask;
+ byte *screen1, *screen2, *screen3;
+ int plane;
+ int w;
+
+#ifdef DOS
+ dest = ylookup[y]+(x>>2);
+#else
+ dest = ylookup[y]+x;
+#endif
+ mask = 1 << (x&3);
+
+ dest1 = (byte *)(dest+page1start);
+ dest2 = (byte *)(dest+page2start);
+ dest3 = (byte *)(dest+page3start);
+
+ for (plane = 0; plane<4; plane++)
+ {
+ VGAMAPMASK (mask);
+
+ screen1 = dest1;
+ screen2 = dest2;
+ screen3 = dest3;
+ for (y = 0; y < height; y++, screen1 += linewidth,
+ screen2 += linewidth,
+ screen3 += linewidth, source+=width)
+ {
+#ifdef DOS
+ memcpy (screen1, source, width);
+ memcpy (screen2, source, width);
+ memcpy (screen3, source, width);
+#else
+ for (x = 0; x < width; x++) {
+ screen1[x*4+plane] = source[x];
+ screen2[x*4+plane] = source[x];
+ screen3[x*4+plane] = source[x];
+ }
+#endif
+ }
+
+#ifdef DOS
+ mask <<= 1;
+
+ if (mask == 16)
+ {
+ mask = 1;
+ dest1++;
+ dest2++;
+ dest3++;
+ }
+#endif
+ }
+}
+
+
+//==========================================================================
+
+/*
+==================
+=
+= ScreenShake
+=
+==================
+*/
+
+void ScreenShake (void)
+{
+ static int which = 0;
+// SetTextMode ( );
+ if (SHAKETICS != 0xFFFF)
+ {
+ SHAKETICS -= tics;
+ if (SHAKETICS >= 0xFF00) {
+ SHAKETICS = 0xFFFF; //bna safety val check
+ }
+
+ which = (RandomNumber ("ScreenShake",0) & 3);
+
+ switch (which)
+ {
+ case 0:
+ displayofs += 1;
+ MoveScreenUpLeft();//SetTextMode ( );
+ DrawPlayScreen(true);//repaint ammo and life stat
+ break;
+
+ case 1:
+ displayofs -= 1;
+ MoveScreenUpRight();
+ DrawPlayScreen(true);//repaint ammo and life stat
+ break;
+
+ case 2:
+ displayofs += 3*iGLOBAL_SCREENBWIDE;
+ MoveScreenDownLeft();
+ DrawPlayScreen(true);//repaint ammo and life stat
+ break;
+
+ case 3:
+ displayofs -= 3*iGLOBAL_SCREENBWIDE;
+ MoveScreenDownRight();
+ DrawPlayScreen(true);//repaint ammo and life stat
+ break;
+ }
+
+ }
+}
+
+//******************************************************************************
+//
+// DoBorderShifts ()
+//
+//******************************************************************************
+
+void DoBorderShifts (void)
+{
+ if (damagecount)
+ {
+ if (damagecount > 100)
+ damagecount = 100;
+
+ damagecount -= 6;
+
+ if (damagecount < 0)
+ damagecount = 0;
+
+ SetBorderColor (*(colormap+(((100-damagecount)>>2)<<8)+48));
+
+ borderset = true;
+ }
+ else if (borderset)
+ {
+ SetBorderColor (0);
+ borderset = false;
+ }
+}
+
+
+//******************************************************************************
+//
+// DrawHighScores ()
+//
+//******************************************************************************
+
+void DrawHighScores (void)
+{
+ char buffer[16];
+#if (SHAREWARE == 0)
+ char buffer1[5];
+#endif
+ int i,
+ w,
+ h;
+ HighScore *s;
+
+ for (i = 0, s = Scores; i < MaxScores; i++, s++)
+ {
+ PrintY = 25 + (16 * i);
+
+ //
+ // name
+ //
+ PrintX = 3*8;
+ DrawMenuBufPropString (PrintX, PrintY, s->name);
+
+ //
+ // level
+ //
+ ultoa (s->completed, buffer, 10);
+
+ PrintX = (17 * 8)-10;
+#if (SHAREWARE == 0)
+ itoa (s->episode, buffer1, 10);
+
+ DrawMenuBufPropString (PrintX, PrintY, buffer1);
+#else
+ DrawMenuBufPropString (PrintX, PrintY, "S");
+#endif
+
+ DrawMenuBufPropString (PrintX, PrintY, "-");
+
+#if (SHAREWARE == 0)
+ if (s->completed == 7)
+ DrawMenuBufPropString (PrintX, PrintY, "B");
+ else if (s->completed == 8)
+ DrawMenuBufPropString (PrintX, PrintY, "S");
+ else if (s->completed == 9)
+ DrawMenuBufPropString (PrintX, PrintY, "C");
+ else if (s->completed == 10)
+ DrawMenuBufPropString (PrintX, PrintY, "D");
+ else
+ DrawMenuBufPropString (PrintX, PrintY, buffer);
+#else
+ DrawMenuBufPropString (PrintX, PrintY, buffer);
+#endif
+
+ //
+ // score
+ //
+ ultoa(s->score,buffer,10);
+
+ VW_MeasurePropString (buffer, &w, &h);
+ PrintX = (33 * 8) - w;
+ DrawMenuBufPropString (PrintX, PrintY, buffer);
+ }
+}
+
+
+
+//******************************************************************************
+//
+// CheckHighScore ()
+//
+//******************************************************************************
+
+void CheckHighScore (long score, word other, boolean INMENU)
+{
+ word i,j;
+ int n;
+ HighScore myscore;
+ int level;
+
+ MenuFadeIn();
+ if (!INMENU)
+ SetupMenuBuf ();
+
+ strcpy (myscore.name,"");
+ myscore.score = score;
+
+ level = GetLevel (gamestate.episode, other-1);
+
+ myscore.episode = gamestate.episode;
+ myscore.completed = level;
+
+ CurrentFont = smallfont;
+
+ for (i = 0, n = -1; i < MaxScores; i++)
+ {
+ if ((myscore.score > Scores[i].score) ||
+ ((myscore.score == Scores[i].score) &&
+ (myscore.completed > Scores[i].completed)))
+ {
+ for (j = MaxScores; --j > i;)
+ Scores[j] = Scores[j - 1];
+ Scores[i] = myscore;
+ n = i;
+ break;
+ }
+ }
+
+ if (INMENU)
+ {
+ SetAlternateMenuBuf();
+ SetMenuTitle ("High Scores");
+ ClearMenuBuf();
+ DrawHighScores ();
+ if (n != -1)
+ DisplayInfo (6);
+ else
+ DisplayInfo (5);
+ FlipMenuBuf ();
+ }
+ else
+ {
+ ClearMenuBuf ();
+ SetMenuTitle ("High Scores");
+ DrawHighScores ();
+ if (n != -1)
+ DisplayInfo (6);
+ else
+ DisplayInfo (5);
+ RefreshMenuBuf (0);
+ }
+
+ if (n != -1)
+ {
+ PrintY = 25 + (16 * n);
+ PrintX = 3*8;
+ US_LineInput (PrintX, PrintY, Scores[n].name, NULL,
+ true, 10, 98, 0);
+ }
+ else
+ {
+ IN_ClearKeysDown ();
+ if ( INMENU )
+ {
+ while( !IN_CheckAck () )
+ {
+ RefreshMenuBuf (0);
+ }
+ }
+ else
+ {
+ for( i = 0; i <= 150; i += tics )
+ {
+ RefreshMenuBuf (0);
+ if (IN_CheckAck ())
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ if (INMENU)
+ {
+ SD_Play (SD_ESCPRESSEDSND);
+ }
+ else
+ {
+ ShutdownMenuBuf ();
+ }
+}
+
+
+//===========================================================================
+
+//#define HEADERX 140
+//#define BONERNAMEX 170
+#define HEADERX 152
+#define BONERNAMEX 166
+
+
+/*
+==================
+=
+= DrawEOLHeader ()
+=
+==================
+*/
+void DrawEOLHeader
+(
+ int playstate
+)
+
+{
+ int health;
+ char tempstr[ 15 ];
+ char *string;
+ int level;
+ int w;
+ int h;
+
+ VWB_TBar( 30, 5, 250, 75 );
+
+ switch( playstate )
+ {
+ case ex_skiplevel :
+ if ( ( gamestate.violence >= vl_high ) &&
+ ( gamestate.difficulty >= gd_hard ) )
+ {
+ string = "LEVEL WUSSED OUT ON!";
+ }
+ else
+ {
+ string = "LEVEL SKIPPED.";
+ }
+ break;
+
+ case ex_secretdone :
+ string = "SECRET LEVEL COMPLETED!";
+ break;
+
+ case ex_secretlevel :
+ string = "SECRET EXIT TAKEN!";
+ break;
+
+ case ex_gameover :
+ string = "GAME COMPLETED!";
+ break;
+
+ case ex_bossdied :
+ string = "BOSS DEFEATED!";
+ break;
+
+ default :
+ string = "LEVEL COMPLETED!";
+ break;
+ }
+
+ VW_MeasurePropString( string, &w, &h );
+
+ px = ( 320 - w ) / 2;
+ py = 10;
+ VWB_DrawPropString( string );
+
+ // draw episode number
+ string = "EPISODE";
+ VW_MeasurePropString( string, &w, &h );
+ px = HEADERX - w;
+ py = 25;
+ VWB_DrawPropString( string );
+
+ itoa( gamestate.episode, tempstr, 10 );
+ px = BONERNAMEX;
+ VWB_DrawPropString( tempstr );
+
+ // draw area number
+ level = GetLevel( gamestate.episode, gamestate.mapon );
+ itoa( level, tempstr, 10 );
+
+ py = 35;
+
+ if ( playstate == ex_secretdone )
+ {
+ string = "SECRET AREA";
+ }
+ else if ( playstate == ex_bossdied )
+ {
+ string = "BOSS AREA";
+ }
+ else if ( gamestate.mapon == 32 )
+ {
+ string = "CHASE AREA";
+ }
+ else
+ {
+ string = "AREA";
+ }
+
+ VW_MeasurePropString( string, &w, &h);
+ px = HEADERX - w;
+ VWB_DrawPropString( string );
+
+ if ( gamestate.mapon != 33 )
+ {
+ px = BONERNAMEX;
+ VWB_DrawPropString( tempstr );
+ }
+
+ string = "SCORE";
+ VW_MeasurePropString( string, &w, &h);
+ px = HEADERX - w;
+ py = 45;
+ VWB_DrawPropString( string );
+
+ px = BONERNAMEX;
+ itoa( gamestate.score, tempstr, 10 );
+ VWB_DrawPropString( tempstr );
+
+ string = "HEALTH";
+ VW_MeasurePropString( string, &w, &h );
+ px = HEADERX - w;
+ py = 55;
+ VWB_DrawPropString( string );
+
+ px = BONERNAMEX;
+ health = ( ( locplayerstate->health * 100 ) /
+ MaxHitpointsForCharacter( locplayerstate ) );
+
+ itoa( health, tempstr, 10 );
+ VWB_DrawPropString( tempstr );
+ VWB_DrawPropString( "%" );
+
+ //
+ // Secret count
+ //
+
+ {
+ char str1[10];
+ char str2[10];
+
+ itoa(gamestate.secretcount,&(str1[0]),10);
+ strcat(str1," / ");
+ itoa(gamestate.secrettotal,&(str2[0]),10);
+ strcat(str1,str2);
+ string = "SECRET WALLS";
+ VW_MeasurePropString( string, &w, &h );
+ px = HEADERX - w;
+ py = 65;
+ VWB_DrawPropString( string );
+
+ px = BONERNAMEX;
+ VWB_DrawPropString( str1 );
+ }
+
+ VW_UpdateScreen ();
+}
+
+boolean EndBonusFirst;
+boolean EndBonusSkip;
+int EndBonusNumBonuses;
+int EndBonusVoice;
+int EndBonusStartY;
+
+void DrawEndBonus
+(
+ char *string,
+ char *bonusstring,
+ int type
+)
+
+{
+ int w;
+ int h;
+ int health;
+ char tempstr[ 15 ];
+
+ if ( EndBonusFirst )
+ {
+ VWB_TBar( 5, EndBonusStartY - 2, 310, 4 );
+ EndBonusFirst = false;
+ }
+
+ VWB_TBar( 5, EndBonusStartY + 2, 310, 10 );
+ VW_MeasurePropString( string, &w, &h );
+
+ py = EndBonusStartY;
+ if ( bonusstring == NULL )
+ {
+ px = ( 320 - w ) / 2;
+ VWB_DrawPropString( string );
+ }
+ else
+ {
+ px = BONERNAMEX - w;
+ VWB_DrawPropString( string );
+
+ EndBonusNumBonuses++;
+ VW_MeasurePropString( bonusstring, &w, &h );
+ px = 310 - w;
+ py = EndBonusStartY;
+ VWB_DrawPropString( bonusstring );
+ }
+
+ // Update Score
+ py = 45;
+ px = BONERNAMEX;
+ V_ReDrawBkgnd( px, py, 107, 11, false );
+ VWB_TBar( px, py, 107, 11 );
+ itoa( gamestate.score, tempstr, 10 );
+ VWB_DrawPropString( tempstr );
+
+ // Update Health
+ py = 55;
+ px = BONERNAMEX;
+ V_ReDrawBkgnd( px, py, 107, 11, false );
+ VWB_TBar( px, py, 107, 11 );
+ health = ( ( locplayerstate->health * 100 ) /
+ MaxHitpointsForCharacter( locplayerstate ) );
+ itoa( health, tempstr, 10 );
+ VWB_DrawPropString( tempstr );
+ VWB_DrawPropString( "%" );
+
+ switch( type )
+ {
+ case 0 :
+ EndBonusVoice = SD_Play( SD_ENDBONUS1SND );
+ break;
+
+ case 1 :
+ EndBonusVoice = SD_Play( SD_NOBONUSSND );
+ break;
+
+ case 2 :
+ VL_FillPalette(255,255,255);
+ //bna--VW_UpdateScreen();
+ VL_FadeIn(0,255,origpal,10);
+ EndBonusVoice = SD_Play( SD_LIGHTNINGSND );
+ break;
+ }
+
+ EndBonusStartY += 10;
+
+ //bna--VW_UpdateScreen();
+ while( SD_SoundActive( EndBonusVoice ) && !EndBonusSkip )
+ {
+ if ( IN_CheckAck() )
+ {
+ EndBonusSkip = true;
+ }
+ }
+}
+
+
+
+/*
+==================
+=
+= LevelCompleted
+=
+= Exit with the screen faded out
+=
+==================
+*/
+
+extern int OLDLMWEAPON;
+extern int OLDLWEAPON;
+
+void LevelCompleted
+(
+ exit_t playstate
+)
+
+{
+ objtype *obj;
+ boolean dobonus;
+ int i;
+ int kr;
+ int sr;
+ int tr;
+ int missileratio;
+ int superratio;
+ int healthratio;
+ int democraticratio;
+ int plantratio;
+ int cnt;
+
+ pic_t *tmpPic;
+// byte *picbuf;
+
+ EndBonusNumBonuses = 0;
+ EndBonusFirst = true;
+ EndBonusSkip = false;
+ EndBonusStartY = 90;
+
+ EnableScreenStretch();
+ tmpPic = ( pic_t * )W_CacheLumpName( "mmbk", PU_CACHE, Cvt_pic_t, 1 );
+ VWB_DrawPic( 0, 0, tmpPic );
+ VW_UpdateScreen();
+// DisableScreenStretch();
+
+ IN_StartAck();
+ EndBonusVoice = 0;
+
+
+ if ( playstate != ex_bossdied )
+ {
+ EndBonusVoice = SD_Play( SD_LEVELDONESND );
+ VL_FillPalette( 255, 255, 255 );
+ VL_FadeIn( 0, 255, origpal, 10 );
+ if ( player->flags & FL_DOGMODE )
+ {
+ MU_StartSong( song_dogend );
+ }
+ else
+ {
+ MU_StartSong( song_endlevel );
+ }
+ }
+
+ BkPic = ( pic_t * )W_CacheLumpName( "mmbk", PU_CACHE, Cvt_pic_t, 1 );
+ VWB_DrawPic( 0, 0, BkPic );
+
+ CheckHolidays();
+ CurrentFont = smallfont;
+
+ // Kill powerups
+ if ( player->flags & FL_ELASTO )
+ {
+ player->flags &= ~FL_NOFRICTION;
+ }
+
+ player->flags &= ~( FL_FLEET | FL_SHROOMS | FL_ELASTO | FL_GODMODE |
+ FL_DOGMODE | FL_BPV | FL_AV | FL_GASMASK );
+
+ // Turn off quickload for next level
+ pickquick = false;
+
+ //
+ // FIGURE RATIOS OUT BEFOREHAND
+ //
+ kr = 0;
+ tr = 0;
+ tr = 0;
+ superratio = 0;
+ missileratio = 0;
+ healthratio = 0;
+ democraticratio = 0;
+ plantratio = 0;
+
+ if ( gamestate.killtotal )
+ {
+ kr = ( int )( ( ( int )gamestate.killcount ) * 100 ) /
+ ( ( int )gamestate.killtotal );
+ }
+
+ if ( gamestate.secrettotal )
+ {
+ sr = ( int )( ( ( int )gamestate.secretcount ) * 100 ) /
+ ( ( int )gamestate.secrettotal );
+ }
+
+ if ( gamestate.treasuretotal )
+ {
+ tr = ( int )( ( ( int )gamestate.treasurecount ) * 100 ) /
+ ( ( int )gamestate.treasuretotal );
+ }
+
+ if ( gamestate.supertotal )
+ {
+ superratio = ( int )( ( ( int )gamestate.supercount ) * 100 ) /
+ ( ( int )gamestate.supertotal );
+ }
+
+ if ( gamestate.missiletotal )
+ {
+ missileratio = ( int )( ( ( int )gamestate.missilecount ) * 100 ) /
+ ( ( int )gamestate.missiletotal );
+ }
+
+ if ( gamestate.healthtotal )
+ {
+ healthratio = ( int )( ( ( int )gamestate.healthcount ) * 100 ) /
+ ( ( int )gamestate.healthtotal );
+ }
+
+ if ( gamestate.democratictotal )
+ {
+ democraticratio = ( int )( ( ( int )gamestate.democraticcount ) *
+ 100 ) / ( ( int )gamestate.democratictotal );
+ }
+
+ if ( gamestate.planttotal )
+ {
+ plantratio = ( int )( ( ( int )gamestate.plantcount ) * 100 ) /
+ ( ( int )gamestate.planttotal );
+ }
+
+ DrawEOLHeader( playstate );
+ /*
+ //bna section store picture because its written on again
+ // store screen first
+ picbuf = (byte *)SafeMalloc (64000);
+ memcpy(picbuf ,bufferofs ,64000);
+
+ EnableScreenStretch();
+ VW_UpdateScreen();//tmpPICbuf is destroyed here
+ DisableScreenStretch();
+ //copy it back
+
+ memcpy(bufferofs ,picbuf , 64000);
+ //bna section end
+ */
+
+ EndBonusSkip = true;
+
+ while( SD_SoundActive( EndBonusVoice ) && !EndBonusSkip )
+ {
+
+ //bna--VW_UpdateScreen();
+
+ if ( IN_CheckAck() )
+ {
+ EndBonusSkip = true;
+ }
+ }
+// tmpPic = ( pic_t * )W_CacheLumpName( "mmbk", PU_CACHE, Cvt_pic_t, 1 );
+// VWB_DrawPic( 0, 0, tmpPic );
+
+ if ( GetNextMap(player->tilex,player->tiley) == -1)
+ {
+ if ( gamestate.dipballs == 3 )
+ {
+ gamestate.score += 100000;
+ DrawEndBonus( "DIP BONUS", "100000 POINTS", 0 );
+ EndBonusStartY += 10;
+ }
+
+ if ( locplayerstate->lives > 0 )
+ {
+ char str[20];
+ char str2[60];
+
+ DrawEndBonus( "EXTRA LIVES BONUS", "\0", 0 );
+ itoa(locplayerstate->lives,str,10);
+ strcpy(str2,str);
+ strcat(str2," EXTRA LIVES =");
+ DrawEndBonus( "\0", str2, 0 );
+ itoa(locplayerstate->lives,str,10);
+ strcpy(str2,str);
+ strcat(str2," X 10000 = ");
+ itoa(locplayerstate->lives*10000,str,10);
+ strcat(str2,str);
+ strcat(str2," POINTS");
+ gamestate.score += 10000*locplayerstate->lives;
+ DrawEndBonus( "\0", str2, 0 );
+ }
+ }
+ else
+ {
+ //
+ // Check for SKIN OF YO TEETH
+ //
+ if ( locplayerstate->health <= 10 )
+ {
+ locplayerstate->health = MaxHitpointsForCharacter( locplayerstate );
+ DrawEndBonus( "SKIN OF YOUR TEETH", "100% HEALTH", 0 );
+ }
+
+ // BULL IN CHINA SHOP BONUS
+ if ( tr == 100 )
+ {
+ gamestate.score += 10000;
+ DrawEndBonus( "BULL IN CHINA SHOP", "10000 POINTS", 0 );
+ }
+
+ // SUPERCHARE BONUS
+ if ( superratio == 100 )
+ {
+ gamestate.score += 10000;
+ DrawEndBonus( "SUPERCHARGE BONUS", "10000 POINTS", 0 );
+ }
+
+ // BLEEDER BONUS
+ if ( healthratio == 100 )
+ {
+ gamestate.score += 10000;
+ DrawEndBonus( "BLEEDER BONUS", "10000 POINTS", 0 );
+ }
+
+ // ADRENALINE BONUS
+ if ( kr == 100 )
+ {
+ gamestate.score += 10000;
+ DrawEndBonus( "ADRENALINE BONUS", "10000 POINTS", 0 );
+ }
+
+ // CURIOSITY BONUS
+ dobonus = true;
+
+ //
+ // Check switches
+ cnt = lastswitch - &switches[ 0 ];
+ if ( cnt != 0 )
+ {
+ for ( i = 0; i < cnt; i++ )
+ {
+ if ( ( switches[ i ].flags & FL_S_FLIPPED ) == 0 )
+ {
+ dobonus = false;
+ break;
+ }
+ }
+ }
+
+ //
+ // Check pillars
+ for ( obj = FIRSTACTOR; obj != NULL; obj = obj->next )
+ {
+ if ( ( obj->obclass == pillarobj ) &&
+ ( ( obj->flags & FL_FLIPPED ) == 0 ) )
+ {
+ dobonus = false;
+ }
+ }
+
+ if ( ( gamestate.secrettotal ) && ( sr != 100 ) )
+ {
+ dobonus = false;
+ }
+
+ if ( dobonus )
+ {
+ gamestate.score += 10000;
+ DrawEndBonus( "CURIOSITY BONUS", "10000 POINTS", 0 );
+ }
+
+ // GROUND ZERO BONUS
+ if ( gamestate.DOGROUNDZEROBONUS )
+ {
+ gamestate.score += 10000;
+ DrawEndBonus( "GROUND ZERO BONUS", "10000 POINTS", 0 );
+ }
+
+ // REPUBLICAN BONUS 1
+ if ( missileratio == 100 )
+ {
+ gamestate.score += 5000;
+ DrawEndBonus( "REPUBLICAN BONUS 1", " 5000 POINTS", 0 );
+ }
+
+ // REPUBLICAN BONUS 2
+ if (plantratio == 100)
+ {
+ gamestate.score += 5000;
+ DrawEndBonus( "REPUBLICAN BONUS 2", " 5000 POINTS", 0 );
+ }
+
+ // DEMOCRATIC BONUS 1
+ if ( gamestate.DODEMOCRATICBONUS1 )
+ {
+ gamestate.score += 5000;
+ DrawEndBonus( "DEMOCRATIC BONUS 1", " 5000 POINTS", 0 );
+ }
+
+ // DEMOCRATIC BONUS 2
+ if (democraticratio == 100)
+ {
+ gamestate.score += 5000;
+ DrawEndBonus( "DEMOCRATIC BONUS 2", " 5000 POINTS", 0 );
+ }
+ }
+
+ if ( EndBonusNumBonuses == 0 )
+ {
+ DrawEndBonus( "NO BONUS!", NULL, 1 );
+ }
+
+ if ( ( EndBonusNumBonuses != 0 ) || ( playstate == ex_gameover ) )
+ {
+ SD_Play( PlayerSnds[ locplayerstate->player ] );
+
+ // DO BONUS BONUS
+ if ( EndBonusNumBonuses == NUMBONUSES )
+ {
+ IN_StartAck();
+ while( !IN_CheckAck() )
+ {
+ ;
+ }
+
+ BkPic = ( pic_t * )W_CacheLumpName( "mmbk", PU_CACHE, Cvt_pic_t, 1 );
+ VWB_DrawPic( 0, 0, BkPic );
+
+ gamestate.score += BONUSBONUS;
+ DrawEOLHeader( playstate );
+ EndBonusFirst = true;
+ EndBonusStartY = 110;
+ EndBonusSkip = true;
+ DrawEndBonus( "BONUS BONUS! 1,000,000 POINTS!", NULL, 2 );
+ }
+ else if ( ( kr == 100 ) && ( dobonus ) )
+ {
+ IN_StartAck();
+ while( !IN_CheckAck() )
+ {
+ ;
+ }
+
+ BkPic = ( pic_t * )W_CacheLumpName( "mmbk", PU_CACHE, Cvt_pic_t, 1 );
+ VWB_DrawPic( 0, 0, BkPic );
+
+ DrawEOLHeader( playstate );
+ EndBonusFirst = true;
+ EndBonusStartY = 110;
+ DrawEndBonus( "You have done well.", NULL, 3 );
+
+#if (SHAREWARE==1)
+ EndBonusVoice = SD_Play( SD_RICOCHET3SND );
+#else
+ EndBonusVoice = SD_Play( SD_PERCENT100SND );
+#endif
+
+ EndBonusSkip = false;
+ DrawEndBonus( "This level is toast.", NULL, 3 );
+
+ }
+ }
+
+
+
+ //bna section
+// EnableScreenStretch();//bna++
+ VW_UpdateScreen();//bna++
+// DisableScreenStretch();//bna++
+ //bna section end
+
+
+ IN_StartAck();
+ while( !IN_CheckAck() )
+ {
+ ;
+ }
+
+ EndLevelStuff = false;
+ CurrentFont = smallfont;
+}
+
+
+void DrawTallyHeader
+(
+ int which
+)
+
+{
+ pic_t *Name;
+ pic_t *KillCount;
+ pic_t *TimesYouKilledPerson;
+ pic_t *TimesPersonKilledYou;
+ pic_t *Suicides;
+ pic_t *Score;
+ pic_t *Blank;
+ pic_t *TopBar;
+
+ Name = ( pic_t * )W_CacheLumpName( "t_name", PU_CACHE, Cvt_pic_t, 1 );
+ Blank = ( pic_t * )W_CacheLumpName( "t_blnk", PU_CACHE, Cvt_pic_t, 1 );
+ KillCount = ( pic_t * )W_CacheLumpName( "t_kcount", PU_CACHE, Cvt_pic_t, 1 );
+ TimesYouKilledPerson = ( pic_t * )W_CacheLumpName( "t_kilper", PU_CACHE, Cvt_pic_t, 1 );
+ TimesPersonKilledYou = ( pic_t * )W_CacheLumpName( "t_perkil", PU_CACHE, Cvt_pic_t, 1 );
+ Suicides = ( pic_t * )W_CacheLumpName( "t_suicid", PU_CACHE, Cvt_pic_t, 1 );
+ Score = ( pic_t * )W_CacheLumpName( "t_score", PU_CACHE, Cvt_pic_t, 1 );
+ TopBar = ( pic_t * )W_CacheLumpName( "t_bar", PU_CACHE, Cvt_pic_t, 1 );
+
+ IFont = ( cfont_t * )W_CacheLumpName( "sifont", PU_CACHE, Cvt_cfont_t, 1 );
+
+ switch( which )
+ {
+ case 0 :
+ VWB_DrawPic ( 8, 8, TopBar );
+ DrawIntensityString( 12, 11, "FINAL SCORE", 20 );
+ VWB_DrawPic ( 8, 24, Name );
+ VWB_DrawPic ( 136, 24, KillCount );
+ VWB_DrawPic ( 184, 24, Suicides );
+ VWB_DrawPic ( 272, 24, Score );
+ break;
+
+ case 1 :
+ VWB_DrawPic ( 8, 8, TopBar );
+ DrawIntensityString( 12, 11, "FINAL SCORE", 20 );
+ VWB_DrawPic ( 8, 24, Name );
+ VWB_DrawPic ( 136, 24, Blank );
+ VWB_DrawPic ( 272, 24, Score );
+ break;
+
+ case 2 :
+ VWB_DrawPic ( 8, 8, TopBar );
+ DrawIntensityString( 12, 11, "YOUR KILLS", 20 );
+ VWB_DrawPic ( 8, 24, Name );
+ VWB_DrawPic ( 136, 24, KillCount );
+ VWB_DrawPic ( 184, 24, TimesYouKilledPerson );
+ break;
+
+ case 3 :
+ VWB_DrawPic ( 8, 8, TopBar );
+ DrawIntensityString( 12, 11, "YOUR DEATHS", 20 );
+ VWB_DrawPic ( 8, 24, Name );
+ VWB_DrawPic ( 136, 24, TimesPersonKilledYou );
+ break;
+//bna added
+ case 4 :
+ VWB_DrawPic ( 198+48, 8, Blank );
+ VWB_DrawPic ( 8, 8, TopBar );
+ DrawIntensityString( 12, 11, "FINAL SCORE", 20 );
+ VWB_DrawPic ( 8, 24, TopBar );//used to blank
+ VWB_DrawPic ( 8, 24, Name );
+ VWB_DrawPic ( 136, 24, KillCount);
+ VWB_DrawPic ( 198, 24, TimesPersonKilledYou);
+ VWB_DrawPic ( 198+48, 24, Blank );
+ VWB_DrawPic ( 272, 24, Score );
+ break;
+//bna added end
+ }
+
+ DrawTimeXY( TALLYTIME_X, TALLYTIME_Y, gamestate.TimeCount / VBLCOUNTER,
+ true );
+}
+
+
+#define BT_RANK_X 23
+#define BT_PLAYER_X 30
+#define BT_KILLS_X ( 139 + ( ( 40 + 20 ) / 2 ) )
+#define BT_DEATHS_X ( 193 + ( ( 56 + 20 ) / 2 ) )
+//#define BT_SCORE_X ( 263 + ( ( 46 + 20 ) / 2 ) )
+#define BT_SCORE_X ( 273 + ( ( 46 + 20 ) / 2 ) )
+
+
+void ShowKills( int localplayer )
+{
+ int w;
+ int h;
+ int i;
+ int j;
+ int temp;
+ int rank;
+ int player;
+ int killer;
+ int victim;
+ int color;
+ char tempstr[15];
+ int KillCount[ MAXPLAYERS ];
+ int Order[ MAXPLAYERS ];
+ int NumPlayers;
+
+ // show at the most 11 players
+ NumPlayers = min( numplayers, 11 );
+
+ // Count kills
+ for( killer = 0; killer < NumPlayers; killer++ )
+ {
+ Order[ killer ] = killer;
+ KillCount[ killer ] = 0;
+ for( victim = 0; victim < NumPlayers; victim++ )
+ {
+ if ( BATTLE_Team[ victim ] != BATTLE_Team[ killer ] )
+ {
+ KillCount[ killer ] += WhoKilledWho[ killer ][ victim ];
+ }
+ }
+ }
+
+ for( i = 0; i < NumPlayers - 1; i++ )
+ {
+ for( j = i + 1; j < NumPlayers; j++ )
+ {
+ if ( KillCount[ Order[ i ] ] < KillCount[ Order[ j ] ] )
+ {
+ temp = Order[ i ];
+ Order[ i ] = Order[ j ];
+ Order[ j ] = temp;
+ }
+ }
+ }
+
+ DrawTallyHeader( 2 );
+
+ IFont = (cfont_t * )W_CacheLumpNum (W_GetNumForName ("sifont"), PU_CACHE, Cvt_cfont_t, 1);
+ CurrentFont = smallfont;
+ py = 43;
+
+ for( rank = 0; rank < NumPlayers; rank++ )
+ {
+ player = Order[ rank ];
+
+ color = 21;
+
+ // Highlight the your score
+ if ( player == localplayer )
+ {
+ // Change to Intensity
+ color = 241;
+ }
+
+ // Draw rank if not tied with previous rank
+ if ( ( rank == 0 ) || ( KillCount[ player ] !=
+ KillCount[ Order[ rank - 1 ] ] ) )
+ {
+ itoa( rank + 1, tempstr, 10 );
+ }
+ else
+ {
+ strcpy( tempstr, "Tie" );
+ }
+
+ VW_MeasureIntensityPropString ( tempstr, &w, &h);
+ DrawIntensityString( BT_RANK_X - w, py, tempstr, color );
+
+ // Draw name
+ DrawIntensityString( BT_PLAYER_X, py, PLAYERSTATE[ player ].codename, color );
+
+ // Draw kills
+ itoa( KillCount[ player ], tempstr, 10 );
+ VW_MeasureIntensityPropString ( tempstr, &w, &h);
+ DrawIntensityString( BT_KILLS_X - w, py, tempstr, color );
+
+ // Draw times you killed that person
+ if ( player != localplayer )
+ {
+ itoa( WhoKilledWho[ localplayer ][ player ], tempstr, 10 );
+ }
+ else
+ {
+ strcpy( tempstr, "-" );
+ }
+
+ VW_MeasureIntensityPropString ( tempstr, &w, &h);
+ DrawIntensityString( BT_DEATHS_X - w, py, tempstr, color );
+
+ if ( gamestate.teamplay )
+ {
+ DrawIntensityString( BT_DEATHS_X + 16, py,
+ colorname[ PLAYERSTATE[ player ].uniformcolor ], color );
+ }
+
+ py += h;
+ }
+}
+
+
+void ShowDeaths( int localplayer )
+{
+ int w;
+ int h;
+ int i;
+ int j;
+ int temp;
+ int rank;
+ int player;
+ int killer;
+ int victim;
+ int color;
+ char tempstr[15];
+ int DeathCount[ MAXPLAYERS ];
+ int Order[ MAXPLAYERS ];
+ int NumPlayers;
+
+ // show at the most 11 players
+ NumPlayers = min( numplayers, 11 );
+
+ // Count Deaths
+ for( victim = 0; victim < NumPlayers; victim++ )
+ {
+ Order[ victim ] = victim;
+ DeathCount[ victim ] = 0;
+ for( killer = 0; killer < NumPlayers; killer++ )
+ {
+ DeathCount[ victim ] += WhoKilledWho[ killer ][ victim ];
+ }
+ }
+
+ for( i = 0; i < NumPlayers - 1; i++ )
+ {
+ for( j = i + 1; j < NumPlayers; j++ )
+ {
+ if ( DeathCount[ Order[ i ] ] < DeathCount[ Order[ j ] ] )
+ {
+ temp = Order[ i ];
+ Order[ i ] = Order[ j ];
+ Order[ j ] = temp;
+ }
+ }
+ }
+
+ DrawTallyHeader( 3 );
+
+ IFont = (cfont_t * )W_CacheLumpNum (W_GetNumForName ("sifont"), PU_CACHE, Cvt_cfont_t, 1);
+ CurrentFont = smallfont;
+ py = 43;
+
+ for( rank = 0; rank < NumPlayers; rank++ )
+ {
+ player = Order[ rank ];
+ color = 21;
+
+ // Highlight the your score
+ if ( player == localplayer )
+ {
+ // Change to Intensity
+ color = 241;
+ }
+
+ // Draw rank if not tied with previous rank
+ if ( ( rank == 0 ) || ( DeathCount[ player ] !=
+ DeathCount[ Order[ rank - 1 ] ] ) )
+ {
+ itoa( rank + 1, tempstr, 10 );
+ }
+ else
+ {
+ strcpy( tempstr, "Tie" );
+ }
+
+ VW_MeasureIntensityPropString ( tempstr, &w, &h);
+ DrawIntensityString( BT_RANK_X - w, py, tempstr, color );
+
+ // Draw name
+ DrawIntensityString( BT_PLAYER_X, py, PLAYERSTATE[ player ].codename, color );
+
+ // Draw deaths
+ itoa( DeathCount[ player ], tempstr, 10 );
+ VW_MeasureIntensityPropString ( tempstr, &w, &h);
+ DrawIntensityString( BT_KILLS_X - w, py, tempstr, color );
+
+ // Draw times you were killed by that person
+ itoa( WhoKilledWho[ player ][ localplayer ], tempstr, 10 );
+ VW_MeasureIntensityPropString ( tempstr, &w, &h);
+ DrawIntensityString( BT_DEATHS_X - w, py, tempstr, color );
+
+ if ( gamestate.teamplay )
+ {
+ DrawIntensityString( BT_DEATHS_X + 16, py,
+ colorname[ PLAYERSTATE[ player ].uniformcolor ], color );
+ }
+
+ py += h;
+ }
+}
+
+
+void ShowEndScore( int localplayer )
+{
+ int w;
+ int h;
+ int rank;
+ int leader;
+ int team;
+ int color;
+ int killer;
+ int victim;
+ int killcount;
+ int suicidecount;
+ char tempstr[15];
+ boolean dofullstats;
+ int NumPlayers;
+
+ // show at the most 11 players
+ NumPlayers = min( numplayers, 11 );
+
+ dofullstats = false;
+ switch( gamestate.battlemode )
+ {
+ case battle_Normal :
+ case battle_ScoreMore :
+ case battle_Hunter :
+ dofullstats = true;
+ DrawTallyHeader( 0 );
+ break;
+
+ case battle_Collector :
+ case battle_Scavenger :
+ case battle_Tag :
+ case battle_Eluder :
+ case battle_Deluder :
+ case battle_CaptureTheTriad :
+ dofullstats = false;
+ DrawTallyHeader( 1 );
+ break;
+ }
+
+ IFont = (cfont_t * )W_CacheLumpNum (W_GetNumForName ("sifont"), PU_CACHE, Cvt_cfont_t, 1);
+ CurrentFont = smallfont;
+ py = 43;
+
+ for( rank = 0; rank < BATTLE_NumberOfTeams; rank++ )
+ {
+ team = BATTLE_PlayerOrder[ rank ];
+
+ color = 21;
+ if ( team == BATTLE_Team[ localplayer ] )
+ {
+ // Change to Intensity
+ color = 241;
+ }
+
+ // Draw rank if not tied with previous rank
+ if ( ( rank == 0 ) || ( BATTLE_Points[ team ] !=
+ BATTLE_Points[ BATTLE_PlayerOrder[ rank - 1 ] ] ) )
+ {
+ itoa( rank + 1, tempstr, 10 );
+ }
+ else
+ {
+ strcpy( tempstr, "Tie" );
+ }
+
+ VW_MeasureIntensityPropString ( tempstr, &w, &h);
+ DrawIntensityString( BT_RANK_X - w, py, tempstr, color );
+
+ // Draw name of team leader
+ leader = BATTLE_TeamLeader[ team ];
+ if ( gamestate.teamplay )
+ {
+ DrawIntensityString( BT_PLAYER_X, py,
+ colorname[ PLAYERSTATE[ leader ].uniformcolor ], color );
+ }
+ else
+ {
+ DrawIntensityString( BT_PLAYER_X, py,
+ PLAYERSTATE[ leader ].codename, color );
+ }
+
+ if ( dofullstats )
+ {
+ // Count how many kills each person on the team got
+ killcount = 0;
+ suicidecount = 0;
+ for( killer = 0; killer < NumPlayers; killer++ )
+ {
+ if ( BATTLE_Team[ killer ] == team )
+ {
+ for( victim = 0; victim < NumPlayers; victim++ )
+ {
+ if ( BATTLE_Team[ victim ] != team )
+ {
+ killcount += WhoKilledWho[ killer ][ victim ];
+ }
+ else
+ {
+ suicidecount += WhoKilledWho[ killer ][ victim ];
+ }
+ }
+ }
+ }
+
+ // Draw kills
+ itoa( killcount, tempstr, 10 );
+ VW_MeasureIntensityPropString ( tempstr, &w, &h);
+ DrawIntensityString( BT_KILLS_X - w, py, tempstr, color );
+
+ // Draw suicides
+ itoa( suicidecount, tempstr, 10 );
+ VW_MeasureIntensityPropString ( tempstr, &w, &h);
+ DrawIntensityString( BT_DEATHS_X - w, py, tempstr, color );
+ }
+
+ // Draw Score
+ itoa( BATTLE_Points[ team ], tempstr, 10 );
+ VW_MeasureIntensityPropString ( tempstr, &w, &h);
+ DrawIntensityString( BT_SCORE_X - w, py, tempstr, color );
+
+ py += h;
+ }
+}
+
+
+void BattleLevelCompleted ( int localplayer )
+{
+ ControlInfo ci;
+ int w;
+ int h;
+ int key;
+ int Screen;
+ int LastScreen;
+ int Player;
+ char text[80];
+
+ EnableScreenStretch();
+
+ IN_ClearKeysDown ();
+
+ Player = localplayer;
+ Screen = 1;
+ LastScreen = 0;
+ key = -1;
+ while( 1 )
+ {
+ if ( Screen != LastScreen )
+ {
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+
+ switch( Screen )
+ {
+ case 1 :
+ ShowEndScore( Player );
+ break;
+
+ case 2 :
+ ShowKills( Player );
+ break;
+
+ case 3 :
+ ShowDeaths( Player );
+ break;
+ }
+
+ CurrentFont = tinyfont;
+
+ sprintf ( text, "Page %d of 3. Use arrows to switch stats. "
+ "Press Esc to quit.", Screen );
+ VW_MeasurePropString ( text, &w, &h);
+ py = 192;
+ px = ( 320 - w ) / 2;
+ VWB_DrawPropString ( text );
+ VW_UpdateScreen ();
+
+ do
+ {
+ ReadAnyControl (&ci);
+ }
+ while( ci.dir == (dirtype)key );
+ }
+
+ LastScreen = Screen;
+ ReadAnyControl ( &ci );
+ key = ci.dir;
+ if ( ( Screen > 1 ) && ( key == dir_West ) )
+ {
+ Screen--;
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ }
+ else if ( ( Screen < 3 ) && ( key == dir_East ) )
+ {
+ Screen++;
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ }
+ // Allow us to select which player to view
+ if ( Keyboard[ sc_RShift ] && ( key == dir_South ) )
+ {
+ Player++;
+ if ( Player >= numplayers )
+ {
+ Player = 0;
+ }
+ LastScreen = 0;
+ MN_PlayMenuSnd (SD_SELECTSND);
+ }
+
+ if ( Keyboard[ sc_RShift ] && ( key == dir_North ) )
+ {
+ Player--;
+ if ( Player < 0 )
+ {
+ Player = numplayers - 1;
+ }
+ LastScreen = 0;
+ MN_PlayMenuSnd (SD_SELECTSND);
+ }
+
+ if ( Keyboard[sc_Escape] )
+ {
+ break;
+ }
+ }
+
+ while ( Keyboard[sc_Escape] )
+ {
+ IN_UpdateKeyboard ();
+ }
+
+ MN_PlayMenuSnd (SD_ESCPRESSEDSND);
+
+ CurrentFont = smallfont;
+}
+
+//==========================================================================
+
+/*
+==================
+=
+= FindAngleToWindow
+=
+==================
+*/
+int FindAngleToWindow ( int tx, int ty )
+{
+ if (!IsWindow(tx+1,ty))
+ return ANG180;
+ else if (!IsWindow(tx-1,ty))
+ return 0;
+ else if (!IsWindow(tx,ty+1))
+ return ANG90;
+ else
+ return ANG270;
+}
+
+#define STARTRADIUS (0xa000)
+#define STOPRADIUS (0x14000)
+#define DEATHRADIUS (STOPRADIUS-STARTRADIUS)
+#define ROTRATE (5)
+#define TOTALDEATHROT (FINEANGLES<<1)
+#define RADIUSINC ((DEATHRADIUS)/(TOTALDEATHROT))
+
+/*
+==================
+=
+= ZoomDeathOkay
+=
+==================
+*/
+boolean ZoomDeathOkay ( void )
+{
+ int x,y;
+ int radius;
+
+ if (
+ !(
+ (player->state==&s_ashwait) ||
+ ((player->flags & FL_HBM) && (gamestate.violence >= vl_high))
+ )
+ )
+ return false;
+
+ radius=STOPRADIUS;
+ x=player->x;
+ y=player->y;
+ while (radius>0)
+ {
+ if (tilemap[x>>16][(y+radius)>>16])
+ return false;
+ if (tilemap[x>>16][(y-radius)>>16])
+ return false;
+ if (tilemap[(x-radius)>>16][y>>16])
+ return false;
+ if (tilemap[(x+radius)>>16][y>>16])
+ return false;
+ if (tilemap[(x+radius)>>16][(y+radius)>>16])
+ return false;
+ if (tilemap[(x+radius)>>16][(y-radius)>>16])
+ return false;
+ if (tilemap[(x-radius)>>16][(y+radius)>>16])
+ return false;
+ if (tilemap[(x-radius)>>16][(y-radius)>>16])
+ return false;
+ radius-=0x10000;
+ }
+ return true;
+}
+
+/*
+==================
+=
+= Died
+=
+==================
+*/
+
+#define DEATHROTATE 6
+
+extern boolean dopefish;
+void Died (void)
+{
+ long dx,dy;
+ int iangle,curangle,clockwise,change;
+ int da;
+ int rate;
+ lbm_t *LBM;
+ int slowrate;
+ playertype *pstate;
+ objtype * killerobj=(objtype *)player->target;
+ player->yzangle=0;
+
+ if (killerobj == NULL)
+ killerobj = player;
+
+ if (CheckParm("slowdeath"))
+ slowrate=3;
+ else
+ slowrate=0;
+
+ M_LINKSTATE (player, pstate);
+
+ if ( (ZoomDeathOkay()==true) && (pstate->falling==false))
+ {
+ int x,y,z,radius,heightoffset;
+ int endangle,startangle,killangle;
+ boolean deadflagset;
+ objtype * dummy;
+
+ x=player->x;
+ y=player->y;
+ z=player->z;
+ dummy=player;
+ SpawnPlayerobj (x>>16, y>>16, 0, 0);
+ player=dummy;
+ dummy=new;
+ dummy->x=x;
+ dummy->drawx=x;
+ dummy->y=y;
+ dummy->z=z;
+ dummy->drawy=y;
+ dummy->flags=player->flags;
+ player->momentumx=0;
+ player->momentumy=0;
+ player->speed=0;
+ radius=STARTRADIUS;
+ heightoffset=pstate->heightoffset;
+ deadflagset=false;
+ startangle=(player->angle+ANG180)&(FINEANGLES-1);
+ endangle=startangle+TOTALDEATHROT;
+ killangle=startangle+(TOTALDEATHROT>>1);
+ if (dopefish==true)
+ {
+ AddMessage("Dopefish Death Cam",MSG_SYSTEM);
+ }
+ for (iangle=startangle;;)
+ {
+ if ( iangle > killangle )
+ {
+ if ( deadflagset==false )
+ {
+ dummy->hitpoints=0;
+ pstate->health=0;
+ dummy->flags &= ~FL_DYING;
+ dummy->flags |= FL_SHOOTABLE;
+ if (player->state==&s_ashwait)
+ dummy->flags |= FL_SKELETON;
+ Collision(dummy,(objtype*)NULL,0,0);
+ deadflagset=true;
+ if ( ( killerobj==player ) && ( gamestate.violence >=
+ vl_high ) && ( gamestate.difficulty >= gd_hard ) )
+ {
+ SD_Play( SD_YOUSUCKSND );
+ }
+ else
+ {
+ SD_Play (SD_PLAYERTCDEATHSND+(pstate->player));
+ }
+ }
+ }
+ else
+ {
+ dummy->flags &= ~FL_DYING;
+ }
+ if (dopefish==true)
+ {
+ dummy->momentumx+=(RandomNumber("Died",0)<<6)-(256<<5);
+ dummy->momentumy+=(RandomNumber("Died",0)<<6)-(256<<5);
+ }
+ player->x=x+FixedMul(radius,costable[iangle&(FINEANGLES-1)]);
+ player->y=y-FixedMul(radius,sintable[iangle&(FINEANGLES-1)]);
+ player->z=dummy->z;
+ player->angle=(iangle+ANG180)&(FINEANGLES-1);
+ if (dopefish==true)
+ {
+ int dx,dy;
+
+ dx = dummy->x - player->x;
+ dy = player->y - dummy->y;
+
+ if (dx && dy)
+ player->angle = atan2_appx (dx,dy);
+ }
+ pstate->heightoffset=heightoffset;
+ player->yzangle=0;
+ UpdateGameObjects();
+ player->momentumx=0;
+ player->momentumy=0;
+ player->speed=0;
+ ThreeDRefresh ();
+ AnimateWalls();
+ DoSprites();
+ DoAnimatedMaskedWalls();
+ UpdatePlayers();
+ UpdateLightLevel(player->areanumber);
+
+ if (iangle<endangle)
+ {
+ iangle+=(tics<<ROTRATE);
+ radius+=tics*(RADIUSINC<<ROTRATE);
+ }
+ if ( (dummy->state==dummy->state->next) && (iangle>=endangle) )
+ break;
+ }
+ }
+ else if (pstate->falling==false)
+ {
+
+ //
+ // swing around to face attacker
+ //
+
+ rate=DEATHROTATE-slowrate;
+ {
+ if (killerobj==player)
+ {
+ iangle=player->angle;
+ if ( ( gamestate.violence >= vl_high ) &&
+ ( gamestate.difficulty >= gd_hard ) )
+ {
+ SD_Play( SD_YOUSUCKSND );
+ }
+ }
+ else
+ {
+ SD_Play (SD_PLAYERTCDEATHSND+(pstate->player));
+ if (killerobj->which==PWALL)
+ {
+ dx = ((pwallobj_t *)killerobj)->x - player->x;
+ dy = player->y - ((pwallobj_t *)killerobj)->y;
+ }
+ else
+ {
+ dx = killerobj->x - player->x;
+ dy = player->y - killerobj->y;
+ }
+
+ iangle = atan2_appx (dx,dy); // returns -pi to pi
+ }
+ }
+
+ da = iangle-player->angle;
+
+ if (da>0)
+ clockwise=1;
+ else
+ clockwise=0;
+ da=abs(da);
+ if (da>ANG180)
+ {
+ clockwise^=1;
+ da=ANGLES-da;
+ }
+
+ curangle = player->angle;
+
+ do
+ {
+ DoBorderShifts ();
+ change = tics<<rate;
+ if (clockwise==1)
+ curangle+=change;
+ else
+ curangle-=change;
+ da-=change;
+ if (curangle >= ANGLES)
+ curangle -= ANGLES;
+ if (curangle < 0)
+ curangle += ANGLES;
+ player->angle = (curangle & (FINEANGLES-1));
+ ThreeDRefresh ();
+ CalcTics ();
+ } while (da>0);
+ }
+ else
+ {
+ DrawFullSky();
+ FlipPage();
+ }
+
+ while (damagecount)
+ DoBorderShifts ();
+ DoBorderShifts ();
+
+ locplayerstate->weapon = -1; // take away weapon
+
+ if (
+ (tedlevel == false) && // SO'S YA DON'T GET KILLED WHILE LAUNCHING!
+ (timelimitenabled == false)
+ )
+ locplayerstate->lives--;
+
+ if (pstate->falling==false)
+ {
+ ThreeDRefresh ();
+ }
+
+ FlipPage();
+ FlipPage();
+
+ if (locplayerstate->lives > -1)
+ {
+ int rng;
+
+ rng = RandomNumber ("Died",0);
+
+ if (pstate->falling==true)
+ {
+ RotateBuffer (0, 0, (FINEANGLES), (FINEANGLES>>6), (VBLCOUNTER*(1+slowrate)));
+ SD_Play (SD_PLAYERTCDEATHSND+(pstate->player));
+ pstate->falling=false;
+ }
+
+ else if (rng < 64)
+ RotateBuffer (0, 0, (FINEANGLES), (FINEANGLES*64), (VBLCOUNTER*(2+slowrate)));
+ else if (rng < 128)
+ {
+ RotateBuffer (0, 0, (FINEANGLES), (FINEANGLES>>6), (VBLCOUNTER*(1+slowrate)));
+ }
+ else if (rng < 192)
+ RotateBuffer(0, (FINEANGLES*4), (FINEANGLES), (FINEANGLES*64), (VBLCOUNTER*(3+slowrate)));
+ else
+ VL_FadeToColor (VBLCOUNTER*2, 100, 0, 0);
+
+ screenfaded=false;
+
+ VL_FadeOut (0, 255, 0,0,0,VBLCOUNTER>>1);
+ gamestate.episode = 1;
+ player->flags &= ~FL_DONE;
+
+ InitializeWeapons (locplayerstate);
+ ResetPlayerstate(locplayerstate);
+
+ UpdateLives (locplayerstate->lives);
+ UpdateScore (gamestate.score);
+
+ DrawTriads(true);
+ DrawLives (true);
+ DrawKeys (true);
+ DrawScore (true);
+ }
+ else
+ {
+ int rng;
+
+ SD_Play (SD_GAMEOVERSND);
+ rng=RandomNumber("Died",0);
+ if (rng<64)
+ RotateBuffer(0,(FINEANGLES>>1),(FINEANGLES),(FINEANGLES*64),(VBLCOUNTER*(3+slowrate)));
+ else if (rng<128)
+ VL_FadeToColor (VBLCOUNTER*3, 255, 255, 255);
+ else if (rng<192)
+ RotateBuffer(0,(FINEANGLES*2),(FINEANGLES),(FINEANGLES*64),(VBLCOUNTER*(3+slowrate)));
+ else
+ RotateBuffer(0,(FINEANGLES*2),(FINEANGLES),(FINEANGLES*64),(VBLCOUNTER*(3+slowrate)));
+
+ screenfaded=false;
+
+ VL_FadeOut (0, 255, 0,0,0,VBLCOUNTER>>1);
+
+ MU_StartSong(song_gameover);
+
+#if (SHAREWARE==0)
+ if (gamestate.violence==vl_excessive)
+ LBM = (lbm_t *) W_CacheLumpNum (W_GetNumForName ("bootblod"), PU_CACHE, Cvt_lbm_t, 1);
+ else
+ LBM = (lbm_t *) W_CacheLumpNum (W_GetNumForName ("bootnorm"), PU_CACHE, Cvt_lbm_t, 1);
+#else
+ LBM = (lbm_t *) W_CacheLumpNum (W_GetNumForName ("bootblod"), PU_CACHE, Cvt_lbm_t, 1);
+#endif
+ VL_DecompressLBM (LBM,true);
+
+ StopWind();
+
+ IN_UserInput (VBLCOUNTER*60);
+
+ MainMenu[savegame].active = 0;
+ MainMenu[viewscores].routine = (void *)CP_ViewScores;
+ MainMenu[viewscores].texture[6] = '7';
+ MainMenu[viewscores].texture[7] = '\0';
+ MainMenu[viewscores].letter = 'V';
+ }
+ ClearGraphicsScreen();
+
+ VL_FadeIn (0, 255, origpal, 15);
+}
+
+
+//******************************************************************************
+//
+// DoLoadGameAction ()
+//
+//******************************************************************************
+
+static byte whichstr = 0;
+
+void DoLoadGameAction (void)
+{
+ if ((SaveTime+1) < GetTicCount())
+ {
+ byte *temp = bufferofs;
+
+ bufferofs = displayofs;
+ SaveTime = GetTicCount();
+
+ CurrentFont=tinyfont;
+
+ px = 92;
+ py = 152;
+ if (whichstr)
+ {
+// VW_DrawPropString ("�");
+ VW_DrawPropString (".");
+ whichstr = 0;
+ }
+ else
+ {
+// VW_DrawPropString ("�");
+ VW_DrawPropString (".");
+ whichstr = 1;
+ }
+ bufferofs = temp;
+ }
+}
+
+//******************************************************************************
+//
+// DoCheckSum ()
+//
+//******************************************************************************
+
+long DoCheckSum (byte *source, int size, long csum)
+{
+ int i;
+ long checksum;
+
+ checksum = csum;
+
+ for (i = 0; i < size; i++)
+ checksum=updatecrc(checksum,*(source+i));
+
+ return checksum;
+}
+
+//******************************************************************************
+//
+// CaculateSaveGameCheckSum ()
+//
+//******************************************************************************
+
+#define SAVECHECKSUMSIZE (10000)
+long CalculateSaveGameCheckSum (char * filename)
+{
+ int handle;
+ int lengthleft;
+ int length;
+ byte * altbuffer;
+ long checksum;
+
+ altbuffer=SafeMalloc(SAVECHECKSUMSIZE);
+
+ checksum = 0;
+
+ // Open the savegame file
+
+ handle = SafeOpenRead (filename);
+ lengthleft = filelength (handle);
+
+ while (lengthleft>0)
+ {
+ length=SAVECHECKSUMSIZE;
+ if (length>lengthleft)
+ length=lengthleft;
+
+ SafeRead(handle,altbuffer,length);
+ checksum = DoCheckSum (altbuffer, length, checksum);
+
+ lengthleft-=length;
+ }
+
+ SafeFree(altbuffer);
+
+ close (handle);
+
+ return checksum;
+}
+
+//******************************************************************************
+//
+// StoreBuffer
+//
+//******************************************************************************
+void StoreBuffer (int handle, byte * src, int size)
+{
+ SafeWrite(handle,&size,sizeof(size));
+ SafeWrite(handle,src,size);
+}
+
+//******************************************************************************
+//
+// SaveTag
+//
+//******************************************************************************
+void SaveTag (int handle, char * tag, int size)
+{
+ SafeWrite(handle,tag,size);
+}
+
+
+//******************************************************************************
+//
+// SaveTheGame ()
+//
+// Expects game to be premalloced
+//
+//******************************************************************************
+
+extern boolean enableZomROTT;
+extern boolean allowBlitzMoreMissileWeps;
+extern boolean enableAmmoPickups;
+
+boolean SaveTheGame (int num, gamestorage_t * game)
+{
+ char loadname[MAX_PATH]="rottgam0.rot";
+ char filename[MAX_PATH];
+ byte * altbuffer;
+ int size;
+ int avail;
+ int savehandle;
+ int crc;
+ int i;
+ char letter;
+ int myticcount;
+
+ if (num > 15 || num < 0)
+ Error("Illegal Saved game value=%d\n",num);
+
+ //
+ // Save Alternate Game Level information for reloading game
+ //
+ memset (&game->info, 0, sizeof (game->info));
+ if (GameLevels.avail == true)
+ {
+ game->info.path = GameLevels.path;
+ game->info.file = GameLevels.file;
+ game->info.avail = true;
+ }
+
+ game->mapcrc=GetMapCRC (gamestate.mapon);
+
+ // Create the proper file name
+
+ itoa(num,&loadname[7],16);
+ loadname[8]='.';
+
+
+ GetPathFromEnvironment( filename, ApogeePath, loadname );
+
+#if PLATFORM_DOS
+ {
+ struct diskfree_t dfree;
+ // Determine available disk space
+ letter = toupper(filename[0]);
+ if (
+ (letter >= 'A') &&
+ (letter <= 'Q')
+ )
+ {
+ if (_dos_getdiskfree ((letter-'A'+1), &dfree))
+ Error ("Error in _dos_getdiskfree call\n");
+ }
+ else
+ {
+ if (_dos_getdiskfree (0, &dfree))
+ Error ("Error in _dos_getdiskfree call\n");
+ }
+
+ avail = (int) dfree.avail_clusters *
+ dfree.bytes_per_sector *
+ dfree.sectors_per_cluster;
+ avail -= 8192;
+
+ // Check to see if we have enough
+
+ if (avail < MAXSAVEDGAMESIZE)
+ {
+ CP_DisplayMsg ("There is not enough\nspace on your disk\nto Save Game!\nPress any key to continue", 13);
+ return (false);
+ }
+ }
+#endif
+
+ // Open the savegame file
+
+ savehandle = SafeOpenWrite (filename);
+
+ // Save out file tag
+
+ size=4;
+ SaveTag(savehandle,"ROTT",size);
+
+ // Save out header
+
+ size=sizeof(*game);
+
+ SafeWrite(savehandle,game,size);
+
+/////////////////////////////////////////////////////////////////////////////
+// Save out rest of save game file beyond this point
+/////////////////////////////////////////////////////////////////////////////
+
+ // Door Tag
+
+ size=4;
+ SaveTag(savehandle,"DOOR",size);
+
+ // Doors
+
+ SaveDoors(&altbuffer,&size);
+ StoreBuffer(savehandle,altbuffer,size);
+ SafeFree(altbuffer);
+
+ // Elevator Tag
+
+ size = 9;
+ SaveTag(savehandle,"ELEVATORS",size);
+
+ // Elevators
+
+ SaveElevators(&altbuffer,&size);
+ StoreBuffer(savehandle,altbuffer,size);
+ SafeFree(altbuffer);
+
+ // Pushwall Tag
+
+ size=5;
+ SaveTag(savehandle,"PWALL",size);
+
+ // PushWalls
+
+ SavePushWalls(&altbuffer,&size);
+ StoreBuffer(savehandle,altbuffer,size);
+ SafeFree(altbuffer);
+
+ // MaskedWalls Tag
+
+ size=5;
+ SaveTag(savehandle,"MWALL",size);
+
+ // Masked Walls
+
+ SaveMaskedWalls(&altbuffer,&size);
+ StoreBuffer(savehandle,altbuffer,size);
+ SafeFree(altbuffer);
+
+ // Switches Tag
+
+ size=6;
+ SaveTag(savehandle,"SWITCH",size);
+
+ // Switches
+
+ SaveSwitches(&altbuffer,&size);
+ StoreBuffer(savehandle,altbuffer,size);
+ SafeFree(altbuffer);
+
+ // Statics Tag
+
+ size=6;
+ SaveTag(savehandle,"STATIC",size);
+
+ // Statics
+
+ SaveStatics(&altbuffer,&size);
+ StoreBuffer(savehandle,altbuffer,size);
+ SafeFree(altbuffer);
+
+ // Actors Tag
+
+ size=5;
+ SaveTag(savehandle,"ACTOR",size);
+
+ // Actors
+
+ SaveActors(&altbuffer,&size);
+ StoreBuffer(savehandle,altbuffer,size);
+ SafeFree(altbuffer);
+
+ // TouchPlates Tag
+
+ size=5;
+ SaveTag(savehandle,"TOUCH",size);
+
+ // TouchPlates
+
+ SaveTouchPlates(&altbuffer,&size);
+ StoreBuffer(savehandle,altbuffer,size);
+ SafeFree(altbuffer);
+
+ // GameState Tag
+
+ size=9;
+ SaveTag(savehandle,"GAMESTATE",size);
+
+ // GameState
+
+ size=sizeof(gamestate);
+ SafeWrite(savehandle,&gamestate,size);
+
+ // PlayerState Tag
+
+ size=12;
+ SaveTag(savehandle,"PLAYERSTATES",size);
+
+ // PlayerStates
+ size=sizeof(playertype);
+ for(i=0; i<numplayers; i++)
+ {
+ SafeWrite(savehandle,&PLAYERSTATE[i],size);
+ }
+
+ // Mapseen Tag
+
+ size=7;
+ SaveTag(savehandle,"MAPSEEN",size);
+
+ // MapSeen
+
+ size=sizeof(mapseen);
+ SafeWrite(savehandle,&mapseen,size);
+
+ // Song Tag
+
+ size=4;
+ SaveTag(savehandle,"SONG",size);
+
+ // Song info
+
+ MU_SaveMusic(&altbuffer,&size);
+ StoreBuffer(savehandle,altbuffer,size);
+ SafeFree(altbuffer);
+
+ // Misc Tag
+
+ size=4;
+ SaveTag(savehandle,"MISC",size);
+
+ // Misc
+
+ // ticcount
+ myticcount = GetTicCount();
+ size=sizeof(myticcount);
+ SafeWrite(savehandle,&myticcount,size);
+
+ // shaketics
+ size=sizeof(SHAKETICS);
+ SafeWrite(savehandle,&SHAKETICS,size);
+
+ // damagecount
+ size=sizeof(damagecount);
+ SafeWrite(savehandle,&damagecount,size);
+
+ // viewsize
+ size=sizeof(viewsize);
+ SafeWrite(savehandle,&viewsize,size);
+
+ // poweruptimes
+ size = sizeof (poweruptime);
+ SafeWrite(savehandle,&poweruptime,size);
+
+ size = sizeof (protectiontime);
+ SafeWrite(savehandle,&protectiontime,size);
+
+ size = sizeof (powerupheight);
+ SafeWrite(savehandle,&powerupheight,size);
+
+ size = sizeof (protectionheight);
+ SafeWrite(savehandle,&protectionheight,size);
+
+ size = sizeof (poweradjust);
+ SafeWrite(savehandle,&poweradjust,size);
+
+ size = sizeof (allowBlitzMoreMissileWeps);
+ SafeWrite(savehandle, &allowBlitzMoreMissileWeps, size);
+
+ size = sizeof (enableAmmoPickups);
+ SafeWrite(savehandle, &enableAmmoPickups, size);
+
+ size = sizeof(enableZomROTT);
+ SafeWrite(savehandle, &enableZomROTT, size);
+
+ //ZomROTT Stuff
+ if(enableZomROTT)
+ {
+ SaveResurrectList(&altbuffer, &size);
+ StoreBuffer(savehandle,altbuffer,size);
+ SafeFree(altbuffer);
+ }
+
+ close (savehandle);
+
+ // Calculate CRC
+
+ crc = CalculateSaveGameCheckSum (filename);
+
+ // Append the crc
+
+ savehandle = SafeOpenAppend (filename);
+
+ size=sizeof(crc);
+ SafeWrite(savehandle,&crc,size);
+
+ close (savehandle);
+
+ pickquick = true;
+ return (true);
+}
+
+
+//******************************************************************************
+//
+// LoadTag
+//
+//******************************************************************************
+
+void LoadTag (byte ** src, char * tag, int size)
+{
+ if (StringsNotEqual((char *)*src,(char *)tag,size)==true)
+ Error("Could not locate %s header in saved game file\n",tag);
+ *src+=size;
+}
+
+//******************************************************************************
+//
+// LoadBuffer
+//
+//******************************************************************************
+int LoadBuffer (byte ** dest, byte ** src)
+{
+ int size;
+
+ memcpy(&size,*src,sizeof(size));
+ *src+=sizeof(size);
+ *dest=SafeMalloc(size);
+ memcpy(*dest,*src,size);
+ *src+=size;
+ return size;
+}
+
+
+//******************************************************************************
+//
+// LoadTheGame ()
+//
+// Expects game to be premalloced
+//
+//******************************************************************************
+
+extern objtype* enemiesToRes;
+extern unsigned int freeSlot;
+
+boolean LoadTheGame (int num, gamestorage_t * game)
+{
+ char loadname[45]="rottgam0.rot";
+ char filename[128];
+ byte * loadbuffer;
+ byte * bufptr;
+ byte * altbuffer;
+ int size;
+ int totalsize;
+ int checksum;
+ int savedchecksum;
+ int i;
+ word mapcrc;
+ int myticcount;
+
+ if (num>15 || num<0)
+ Error("Illegal Load game value=%d\n",num);
+
+ // Create the proper file name
+
+ itoa(num,&loadname[7],16);
+ loadname[8]='.';
+
+ GetPathFromEnvironment( filename, ApogeePath, loadname );
+
+ // Load the file
+
+ totalsize=LoadFile(filename,(void **)&loadbuffer);
+ bufptr=loadbuffer;
+
+ // Calculate checksum
+
+ checksum = DoCheckSum (loadbuffer, totalsize-sizeof(checksum), 0);
+
+ // Retrieve saved checksum
+
+ memcpy (&savedchecksum,loadbuffer+(totalsize-sizeof(savedchecksum)),sizeof(savedchecksum));
+
+ // Compare the two checksums;
+
+ if (checksum!=savedchecksum)
+ {
+ if (CP_DisplayMsg ("Your Saved Game file is\n"
+ "shall we say, \"corrupted\".\n"
+ "Would you like to\n"
+ "continue anyway (Y/N)?\n", 12)==false)
+ {
+ return false;
+ }
+ }
+
+ // Load in file tag
+
+ size=4;
+ LoadTag(&bufptr,"ROTT",size);
+
+ // Load in header
+
+ size=sizeof(*game);
+ memcpy(game,bufptr,size);
+ bufptr+=size;
+
+ if (game->version!=ROTTVERSION)
+ return false;
+
+ memcpy (&GameLevels, &game->info, sizeof (GameLevels));
+
+ gamestate.episode=game->episode;
+ gamestate.mapon=game->area;
+
+ mapcrc=GetMapCRC (gamestate.mapon);
+
+ if (mapcrc!=game->mapcrc)
+ return false;
+
+/////////////////////////////////////////////////////////////////////////////
+// Load in rest of saved game file beyond this point
+/////////////////////////////////////////////////////////////////////////////
+
+ // Free up the current level
+ Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level
+
+ gamestate.battlemode = battle_StandAloneGame;
+ BATTLE_SetOptions( &BATTLE_Options[ battle_StandAloneGame ] );
+ BATTLE_Init( gamestate.battlemode, 1 );
+
+ DoLoadGameAction ();
+ SetupGameLevel();
+
+ // This prevents a nasty glitch when loading some saved games
+ PreCacheGroup(W_GetNumForName("BULLETHO"),W_GetNumForName("ALTBHO"),cache_transpatch_t);
+
+ // Door Tag
+
+ size=4;
+ LoadTag(&bufptr,"DOOR",size);
+
+ // Doors
+
+ DoLoadGameAction ();
+ size=LoadBuffer(&altbuffer,&bufptr);
+ LoadDoors(altbuffer,size);
+ SafeFree(altbuffer);
+
+ // Elevator Tag
+
+ size = 9;
+ LoadTag(&bufptr,"ELEVATORS",size);
+
+
+ // Elevators
+
+ DoLoadGameAction ();
+ size=LoadBuffer(&altbuffer,&bufptr);
+ LoadElevators(altbuffer,size);
+ SafeFree(altbuffer);
+
+ // Pushwall Tag
+
+ size=5;
+ LoadTag(&bufptr,"PWALL",size);
+
+ // PushWalls
+
+ DoLoadGameAction ();
+ size=LoadBuffer(&altbuffer,&bufptr);
+ LoadPushWalls(altbuffer,size);
+ SafeFree(altbuffer);
+#if 0
+ // Animated Walls Tag
+
+ size=5;
+ LoadTag(&bufptr,"AWALL",size);
+
+ // Animated Walls
+ size=LoadBuffer(&altbuffer,&bufptr);
+ LoadAnimWalls(altbuffer,size);
+ SafeFree(altbuffer);
+#endif
+
+ // MaskedWalls Tag
+
+ size=5;
+ LoadTag(&bufptr,"MWALL",size);
+
+ // Masked Walls
+
+ DoLoadGameAction ();
+ size=LoadBuffer(&altbuffer,&bufptr);
+ LoadMaskedWalls(altbuffer,size);
+ SafeFree(altbuffer);
+
+ // Switches Tag
+
+ size=6;
+ LoadTag(&bufptr,"SWITCH",size);
+
+ // Switches
+
+ DoLoadGameAction ();
+ size=LoadBuffer(&altbuffer,&bufptr);
+ LoadSwitches(altbuffer,size);
+ SafeFree(altbuffer);
+
+
+ // Statics Tag
+
+ size=6;
+ LoadTag(&bufptr,"STATIC",size);
+
+ // Statics
+
+ DoLoadGameAction ();
+ size=LoadBuffer(&altbuffer,&bufptr);
+ LoadStatics(altbuffer,size);
+ SafeFree(altbuffer);
+
+ // Actors Tag
+
+ size=5;
+ LoadTag(&bufptr,"ACTOR",size);
+
+ // Actors
+
+ DoLoadGameAction ();
+ size=LoadBuffer(&altbuffer,&bufptr);
+ LoadActors(altbuffer,size);
+ SafeFree(altbuffer);
+
+ // TouchPlates Tag
+
+ size=5;
+ LoadTag(&bufptr,"TOUCH",size);
+
+ // TouchPlates
+
+ DoLoadGameAction ();
+ size=LoadBuffer(&altbuffer,&bufptr);
+ LoadTouchPlates(altbuffer,size);
+ SafeFree(altbuffer);
+
+ // SetupWindows
+
+ SetupWindows();
+
+ // GameState Tag
+
+ size=9;
+ LoadTag(&bufptr,"GAMESTATE",size);
+
+ // GameState
+
+ DoLoadGameAction ();
+ size=sizeof(gamestate);
+ memcpy(&gamestate,bufptr,size);
+ bufptr+=size;
+
+ // PlayerState Tag
+
+ size=12;
+ LoadTag(&bufptr,"PLAYERSTATES",size);
+
+ // PlayerState
+
+ DoLoadGameAction ();
+ size=sizeof(playertype);
+ for(i=0; i<numplayers; i++)
+ { memcpy(&PLAYERSTATE[i],bufptr,size);
+ bufptr+=size;
+ }
+
+ // Zero out player targets
+
+ locplayerstate->guntarget=0;
+ locplayerstate->targettime=0;
+
+ // Mapseen Tag
+
+ size=7;
+ LoadTag(&bufptr,"MAPSEEN",size);
+
+ // MapSeen
+
+ DoLoadGameAction ();
+ size=sizeof(mapseen);
+ memcpy(&mapseen,bufptr,size);
+ bufptr+=size;
+
+ // Song Tag
+
+ size=4;
+ LoadTag(&bufptr,"SONG",size);
+
+ // Song info
+
+ DoLoadGameAction ();
+ size=LoadBuffer(&altbuffer,&bufptr);
+ MU_LoadMusic(altbuffer,size);
+ SafeFree(altbuffer);
+
+ // Misc Tag
+
+ size=4;
+ LoadTag(&bufptr,"MISC",size);
+
+ // Misc
+
+ // ticcount
+ DoLoadGameAction ();
+ size=sizeof(myticcount);
+ memcpy((void *)&myticcount,bufptr,size);
+ bufptr+=size;
+ SaveTime = myticcount;
+ ISR_SetTime(myticcount);
+
+ // shaketics
+ DoLoadGameAction ();
+ size=sizeof(SHAKETICS);
+ memcpy(&SHAKETICS,bufptr,size);
+ bufptr+=size;
+
+ // damagecount
+ DoLoadGameAction ();
+ size=sizeof(damagecount);
+ memcpy(&damagecount,bufptr,size);
+ bufptr+=size;
+
+ // viewsize
+ DoLoadGameAction ();
+ size=sizeof(viewsize);
+ memcpy(&viewsize,bufptr,size);
+ bufptr+=size;
+
+ // powerup times
+ DoLoadGameAction ();
+ size = sizeof (poweruptime);
+ memcpy (&poweruptime, bufptr, size);
+ bufptr += size;
+ size = sizeof (protectiontime);
+ memcpy (&protectiontime, bufptr, size);
+ bufptr += size;
+ size = sizeof (powerupheight);
+ memcpy (&powerupheight, bufptr, size);
+ bufptr += size;
+ size = sizeof (protectionheight);
+ memcpy (&protectionheight, bufptr, size);
+ bufptr += size;
+ size = sizeof (poweradjust);
+ memcpy (&poweradjust, bufptr, size);
+ bufptr += size;
+
+ size = sizeof(allowBlitzMoreMissileWeps);
+ memcpy (&allowBlitzMoreMissileWeps, bufptr, size);
+ bufptr += size;
+
+ size = sizeof(enableAmmoPickups);
+ memcpy (&enableAmmoPickups, bufptr, size);
+ bufptr += size;
+
+ size = sizeof(enableZomROTT);
+ memcpy(&enableZomROTT, bufptr, size);
+ bufptr += size;
+
+
+ //ZomROTT Stuff
+ if(enableZomROTT)
+ {
+ enemiesToRes = calloc(sizeof(objtype), gamestate.killtotal);
+ memset(enemiesToRes, 0, sizeof(enemiesToRes));
+ size = sizeof(enemiesToRes);
+ memcpy(enemiesToRes, bufptr, size);
+ bufptr += size;
+
+ objtype * findFreeSlotPtr;
+ //find index of free
+ for (findFreeSlotPtr = &enemiesToRes[0]; findFreeSlotPtr != 0; findFreeSlotPtr++)
+ {
+ freeSlot++;
+ }
+ }
+
+ // Set the viewsize
+
+ SetViewSize(viewsize);
+ DoLoadGameAction ();
+
+ // Connect areas
+
+ ConnectAreas ();
+ DoLoadGameAction ();
+
+ // Free up the loadbuffer
+
+ SafeFree (loadbuffer);
+ DoLoadGameAction ();
+
+ Illuminate();
+
+ IN_UpdateKeyboard ();
+ LoadPlayer ();
+ DoLoadGameAction ();
+ SetupPlayScreen();
+ UpdateScore (gamestate.score);
+ UpdateLives (locplayerstate->lives);
+ UpdateTriads (player, 0);
+ PreCache ();
+ InitializeMessages();
+
+ for (i=0; i<100; i++)
+ UpdateLightLevel(player->areanumber);
+
+ CalcTics();
+ CalcTics();
+
+ pickquick = true;
+
+ return (true);
+}
+
+
+//******************************************************************************
+//
+// GetSavedMessage ()
+//
+// Expects message to be premalloced
+//
+//******************************************************************************
+
+void GetSavedMessage (int num, char * message)
+{
+ gamestorage_t game;
+ char loadname[45]="rottgam0.rot";
+ char filename[128];
+ byte * loadbuffer;
+ byte * bufptr;
+ int size;
+
+ if (num>15 || num<0)
+ Error("Illegal Load game value=%d\n",num);
+
+ // Create the proper file name
+
+ itoa(num,&loadname[7],16);
+ loadname[8]='.';
+
+ GetPathFromEnvironment( filename, ApogeePath, loadname );
+
+ // Load the file
+
+ size=LoadFile(filename,(void **)&loadbuffer);
+ bufptr=loadbuffer;
+
+ size=4;
+ LoadTag(&bufptr,"ROTT",size);
+
+ // Load in header
+
+ size=sizeof(game);
+ memcpy(&game,bufptr,size);
+ strcpy(message,game.message);
+ SafeFree(loadbuffer);
+}
+
+//******************************************************************************
+//
+// GetSavedHeader ()
+//
+// Expects game to be premalloced
+//
+//******************************************************************************
+
+void GetSavedHeader (int num, gamestorage_t * game)
+{
+ char loadname[45]="rottgam0.rot";
+ char filename[128];
+ byte * loadbuffer;
+ byte * bufptr;
+ int size;
+
+ if (num>15 || num<0)
+ Error("Illegal Load game value=%d\n",num);
+
+ // Create the proper file name
+
+ itoa(num,&loadname[7],16);
+ loadname[8]='.';
+
+ GetPathFromEnvironment( filename, ApogeePath, loadname );
+
+ // Load the file
+
+ size=LoadFile(filename, (void **)&loadbuffer);
+ bufptr=loadbuffer;
+
+ size=4;
+ LoadTag(&bufptr,"ROTT",size);
+
+ // Load in header
+
+ size=sizeof(*game);
+ memcpy(game,bufptr,size);
+ SafeFree(loadbuffer);
+}
+
+
+
+//******************************************************************************
+//
+// GetLevel ()
+//
+//******************************************************************************
+
+int GetLevel (int episode, int mapon)
+{
+ int level;
+
+ level = (mapon+1) - ((episode-1) << 3);
+
+ return (level);
+}
--- /dev/null
+++ b/rott/rt_game.h
@@ -1,0 +1,148 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_game_public
+#define _rt_game_public
+
+//***************************************************************************
+//
+// Public header for RT_GAME.C
+//
+//***************************************************************************
+
+#include "rt_actor.h"
+#include "lumpy.h"
+#include "rt_cfg.h"
+#include "rt_playr.h"
+
+//***************************************************************************
+//
+// DEFINES
+//
+//***************************************************************************
+
+#define MaxHighName 57
+#define MaxScores 7
+
+
+//***************************************************************************
+//
+// TYPEDEFS
+//
+//***************************************************************************
+
+typedef struct
+{
+ char message[30];
+ byte episode;
+ byte area;
+ byte version;
+ byte picture[16000];
+ word mapcrc;
+ AlternateInformation info;
+} gamestorage_t;
+
+typedef struct
+{
+ char name[MaxHighName + 1];
+ long score;
+ word completed,episode;
+} HighScore;
+
+
+//***************************************************************************
+//
+// GLOBALS
+//
+//***************************************************************************
+
+extern int PlayerSnds[5];
+
+//extern int SHAKETICS;
+extern unsigned short SHAKETICS;//bna++
+extern int damagecount;
+
+extern HighScore Scores[MaxScores];
+extern int SaveTime;
+
+//***************************************************************************
+//
+// PROTOTYPES
+//
+//***************************************************************************
+
+void SetupPlayScreen (void);
+void SD_PreCache (void);
+void GameMemToScreen( pic_t *source, int x, int y, int bufferofsonly );
+void DrawPlayScreen (boolean bufferofsonly);
+
+void DrawKills (boolean bufferofsonly);
+void DrawPlayers ( void );
+void DrawGameString (int x, int y, const char * str, boolean bufferofsonly);
+void DrawNumber (int x, int y, int width, int which, boolean bufferofsonly);
+void TakeDamage (int points, objtype *attacker);
+void HealPlayer (int points, objtype * ob);
+void DrawLives (boolean bufferofsonly);
+void GiveExtraMan (void);
+void DrawScore (boolean bufferofsonly);
+void GivePoints (long points);
+void DrawKeys (boolean bufferofsonly);
+void GiveKey (int key);
+void GiveWeapon (objtype * ob, int weapon);
+void GiveMissileWeapon(objtype * ob, int which);
+void GiveLives (int newlives);
+
+void UpdateScore (unsigned int num);
+void UpdateLives (int num);
+
+void DrawTimeXY( int x, int y, int sec, boolean bufferofsonly );
+void DrawTime (boolean bufferofsonly);
+
+boolean SaveTheGame (int num, gamestorage_t * game);
+boolean LoadTheGame (int num, gamestorage_t * game);
+void GetSavedMessage (int num, char * message);
+void GetSavedHeader (int num, gamestorage_t * game);
+
+void DrawHighScores (void);
+void CheckHighScore (long score, word other, boolean INMENU);
+void LevelCompleted ( exit_t playstate );
+void BattleLevelCompleted ( int localplayer );
+void Died (void);
+void ScreenShake (void);
+void UpdateTriads (objtype * ob, int num);
+void DrawTriads (boolean bufferofsonly);
+void DrawStats (void);
+void DrawBarHealth (boolean bufferonly);
+void DrawBarAmmo (boolean bufferonly);
+void GM_DrawBonus (int which);
+
+void DrawEpisodeLevel ( int x, int y );
+void DoBorderShifts (void);
+void GM_UpdateBonus (int time, int powerup);
+void DoLoadGameAction (void);
+int GetLevel (int episode, int mapon);
+void DrawPause (void);
+void DrawPauseXY (int x, int y);
+void GivePlayerAmmo(objtype *ob, statobj_t *item_pickup, int which);
+
+void DrawColoredMPPic (int xpos, int ypos, int width, int height, int heightmod, byte *src, boolean bufferofsonly, int color);
+void StatusDrawColoredPic (unsigned x, unsigned y, pic_t *nums, boolean bufferofsonly, int color);
+
+void ClearTriads (playertype * pstate);
+#endif
--- /dev/null
+++ b/rott/rt_in.c
@@ -1,0 +1,1957 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if PLATFORM_DOS
+#include <conio.h>
+#include <dos.h>
+#include <i86.h>
+#endif
+
+#if USE_SDL
+#include "SDL.h"
+#endif
+
+#include "rt_main.h"
+#include "rt_spbal.h"
+#include "rt_def.h"
+#include "rt_in.h"
+#include "_rt_in.h"
+#include "isr.h"
+#include "rt_util.h"
+#include "rt_swift.h"
+#include "rt_vh_a.h"
+#include "rt_cfg.h"
+#include "rt_msg.h"
+#include "rt_playr.h"
+#include "rt_net.h"
+#include "rt_com.h"
+#include "rt_cfg.h"
+//MED
+#include "memcheck.h"
+#include "keyb.h"
+
+#define MAXMESSAGELENGTH (COM_MAXTEXTSTRINGLENGTH-1)
+
+//****************************************************************************
+//
+// GLOBALS
+//
+//****************************************************************************]
+
+//
+// Used by menu routines that need to wait for a button release.
+// Sometimes the mouse driver misses an interrupt, so you can't wait for
+// a button to be released. Instead, you must ignore any buttons that
+// are pressed.
+//
+int IgnoreMouse = 0;
+
+// configuration variables
+//
+boolean SpaceBallPresent;
+boolean CybermanPresent;
+boolean AssassinPresent;
+boolean MousePresent;
+boolean JoysPresent[MaxJoys];
+boolean JoyPadPresent = 0;
+
+// Global variables
+//
+boolean Paused;
+char LastASCII;
+volatile int LastScan;
+
+byte Joy_xb,
+ Joy_yb,
+ Joy_xs,
+ Joy_ys;
+word Joy_x,
+ Joy_y;
+
+
+int LastLetter = 0;
+char LetterQueue[MAXLETTERS];
+ModemMessage MSG;
+
+
+#if USE_SDL
+static SDL_Joystick* sdl_joysticks[MaxJoys];
+static int sdl_mouse_delta_x = 0;
+static int sdl_mouse_delta_y = 0;
+static word sdl_mouse_button_mask = 0;
+static int sdl_total_sticks = 0;
+static word *sdl_stick_button_state = NULL;
+static word sdl_sticks_joybits = 0;
+static int sdl_mouse_grabbed = 0;
+static unsigned int scancodes[SDLK_LAST];
+extern boolean sdl_fullscreen;
+#endif
+
+
+// 'q','w','e','r','t','y','u','i','o','p','[',']','\\', 0 ,'a','s',
+
+const char ScanChars[128] = // Scan code names with single chars
+{
+ 0, 0,'1','2','3','4','5','6','7','8','9','0','-','=', 0, 0,
+ 'q','w','e','r','t','y','u','i','o','p','[',']', 0, 0,'a','s',
+ 'd','f','g','h','j','k','l',';','\'','`', 0,'\\','z','x','c','v',
+ 'b','n','m',',','.','/', 0, 0, 0,' ', 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'-', 0,'5', 0,'+', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+const char ShiftedScanChars[128] = // Shifted Scan code names with single chars
+{
+ 0, 0,'!','@','#','$','%','^','&','*','(',')','_','+', 0, 0,
+ 'Q','W','E','R','T','Y','U','I','O','P','{','}', 0, 0,'A','S',
+ 'D','F','G','H','J','K','L',':','"','~', 0,'|','Z','X','C','V',
+ 'B','N','M','<','>','?', 0, 0, 0,' ', 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'-', 0,'5', 0,'+', 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#if 0
+const char ScanChars[128] = // Scan code names with single chars
+{
+ '?','?','1','2','3','4','5','6','7','8','9','0','-','+','?','?',
+ 'Q','W','E','R','T','Y','U','I','O','P','[',']','|','?','A','S',
+ 'D','F','G','H','J','K','L',';','\'','?','?','?','Z','X','C','V',
+ 'B','N','M',',','.','/','?','?','?',' ','?','?','?','?','?','?',
+ '?','?','?','?','?','?','?','?','?','?','-','?','5','?','+','?',
+ '?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?',
+ '?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?',
+ '?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?'
+};
+#endif
+
+
+
+//****************************************************************************
+//
+// LOCALS
+//
+//****************************************************************************]
+
+static KeyboardDef KbdDefs = {0x1d,0x38,0x47,0x48,0x49,0x4b,0x4d,0x4f,0x50,0x51};
+static JoystickDef JoyDefs[MaxJoys];
+static ControlType Controls[MAXPLAYERS];
+
+
+static boolean IN_Started;
+
+static Direction DirTable[] = // Quick lookup for total direction
+{
+ dir_NorthWest, dir_North, dir_NorthEast,
+ dir_West, dir_None, dir_East,
+ dir_SouthWest, dir_South, dir_SouthEast
+};
+
+int (far *function_ptr)();
+
+static char *ParmStrings[] = {"nojoys","nomouse","spaceball","cyberman","assassin",NULL};
+
+
+#if USE_SDL
+#define sdldebug printf
+
+static int sdl_mouse_button_filter(SDL_Event const *event)
+{
+ /*
+ * What DOS games expect:
+ * 0 left button pressed if 1
+ * 1 right button pressed if 1
+ * 2 middle button pressed if 1
+ *
+ * (That is, this is what Int 33h (AX=0x05) returns...)
+ */
+
+ Uint8 bmask = SDL_GetMouseState(NULL, NULL);
+ sdl_mouse_button_mask = 0; /* this is a static var. */
+ if (bmask & SDL_BUTTON_LMASK) sdl_mouse_button_mask |= 1;
+ if (bmask & SDL_BUTTON_RMASK) sdl_mouse_button_mask |= 2;
+ if (bmask & SDL_BUTTON_MMASK) sdl_mouse_button_mask |= 4;
+ return(0);
+} /* sdl_mouse_up_filter */
+
+
+static int sdl_mouse_motion_filter(SDL_Event const *event)
+{
+ static int mouse_x = 0;
+ static int mouse_y = 0;
+ int mouse_relative_x = 0;
+ int mouse_relative_y = 0;
+
+ if (event->type == SDL_JOYBALLMOTION)
+ {
+ mouse_relative_x = event->jball.xrel/100;
+ mouse_relative_y = event->jball.yrel/100;
+ mouse_x += mouse_relative_x;
+ mouse_y += mouse_relative_y;
+ } /* if */
+ else
+ {
+ if (sdl_mouse_grabbed || sdl_fullscreen)
+ {
+ mouse_relative_x = event->motion.xrel;
+ mouse_relative_y = event->motion.yrel;
+ mouse_x += mouse_relative_x;
+ mouse_y += mouse_relative_y;
+ } /* if */
+ else
+ {
+ mouse_relative_x = event->motion.x - mouse_x;
+ mouse_relative_y = event->motion.y - mouse_y;
+ mouse_x = event->motion.x;
+ mouse_y = event->motion.y;
+ } /* else */
+ } /* else */
+
+#if 0
+ if (mouse_x < 0) mouse_x = 0;
+ if (mouse_x > surface->w) mouse_x = surface->w;
+ if (mouse_y < 0) mouse_y = 0;
+ if (mouse_y > surface->h) mouse_y = surface->h;
+#endif
+
+ /* set static vars... */
+ sdl_mouse_delta_x += mouse_relative_x;
+ sdl_mouse_delta_y += mouse_relative_y;
+
+ return(0);
+} /* sdl_mouse_motion_filter */
+
+
+/**
+ * Attempt to flip the video surface to fullscreen or windowed mode.
+ * Attempts to maintain the surface's state, but makes no guarantee
+ * that pointers (i.e., the surface's pixels field) will be the same
+ * after this call.
+ *
+ * Caveats: Your surface pointers will be changing; if you have any other
+ * copies laying about, they are invalidated.
+ *
+ * Do NOT call this from an SDL event filter on Windows. You can
+ * call it based on the return values from SDL_PollEvent, etc, just
+ * not during the function you passed to SDL_SetEventFilter().
+ *
+ * Thread safe? Likely not.
+ *
+ * @param surface pointer to surface ptr to toggle. May be different
+ * pointer on return. MAY BE NULL ON RETURN IF FAILURE!
+ * @param flags pointer to flags to set on surface. The value pointed
+ * to will be XOR'd with SDL_FULLSCREEN before use. Actual
+ * flags set will be filled into pointer. Contents are
+ * undefined on failure. Can be NULL, in which case the
+ * surface's current flags are used.
+ * @return non-zero on success, zero on failure.
+ */
+static int attempt_fullscreen_toggle(SDL_Surface **surface, Uint32 *flags)
+{
+ long framesize = 0;
+ void *pixels = NULL;
+ SDL_Rect clip;
+ Uint32 tmpflags = 0;
+ int w = 0;
+ int h = 0;
+ int bpp = 0;
+ int grabmouse = (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_ON);
+ int showmouse = SDL_ShowCursor(-1);
+ SDL_Color *palette = NULL;
+ int ncolors = 0;
+
+ /*
+ sdldebug("attempting to toggle fullscreen flag...");
+ */
+
+ if ( (!surface) || (!(*surface)) ) /* don't try if there's no surface. */
+ {
+ /*
+ sdldebug("Null surface (?!). Not toggling fullscreen flag.");
+ */
+ return(0);
+ } /* if */
+
+ if (SDL_WM_ToggleFullScreen(*surface))
+ {
+ /*
+ sdldebug("SDL_WM_ToggleFullScreen() seems to work on this system.");
+ */
+ if (flags)
+ *flags ^= SDL_FULLSCREEN;
+ return(1);
+ } /* if */
+
+ if ( !(SDL_GetVideoInfo()->wm_available) )
+ {
+ /*
+ sdldebug("No window manager. Not toggling fullscreen flag.");
+ */
+ return(0);
+ } /* if */
+
+ /*
+ sdldebug("toggling fullscreen flag The Hard Way...");
+ */
+ tmpflags = (*surface)->flags;
+ w = (*surface)->w;
+ h = (*surface)->h;
+ bpp = (*surface)->format->BitsPerPixel;
+
+ if (flags == NULL) /* use the surface's flags. */
+ flags = &tmpflags;
+
+ SDL_GetClipRect(*surface, &clip);
+
+ /* save the contents of the screen. */
+ if ( (!(tmpflags & SDL_OPENGL)) && (!(tmpflags & SDL_OPENGLBLIT)) )
+ {
+ framesize = (w * h) * ((*surface)->format->BytesPerPixel);
+ pixels = malloc(framesize);
+ if (pixels == NULL)
+ return(0);
+ memcpy(pixels, (*surface)->pixels, framesize);
+ } /* if */
+
+#if 1
+ STUB_FUNCTION; /* palette is broken. FIXME !!! --ryan. */
+#else
+ if ((*surface)->format->palette != NULL)
+ {
+ ncolors = (*surface)->format->palette->ncolors;
+ palette = malloc(ncolors * sizeof (SDL_Color));
+ if (palette == NULL)
+ {
+ free(pixels);
+ return(0);
+ } /* if */
+ memcpy(palette, (*surface)->format->palette->colors,
+ ncolors * sizeof (SDL_Color));
+ } /* if */
+#endif
+
+ if (grabmouse)
+ SDL_WM_GrabInput(SDL_GRAB_OFF);
+
+ SDL_ShowCursor(1);
+
+ *surface = SDL_SetVideoMode(w, h, bpp, (*flags) ^ SDL_FULLSCREEN);
+
+ if (*surface != NULL)
+ *flags ^= SDL_FULLSCREEN;
+
+ else /* yikes! Try to put it back as it was... */
+ {
+ *surface = SDL_SetVideoMode(w, h, bpp, tmpflags);
+ if (*surface == NULL) /* completely screwed. */
+ {
+ if (pixels != NULL)
+ free(pixels);
+ if (palette != NULL)
+ free(palette);
+ return(0);
+ } /* if */
+ } /* if */
+
+ /* Unfortunately, you lose your OpenGL image until the next frame... */
+
+ if (pixels != NULL)
+ {
+ memcpy((*surface)->pixels, pixels, framesize);
+ free(pixels);
+ } /* if */
+
+#if 1
+ STUB_FUNCTION; /* palette is broken. FIXME !!! --ryan. */
+#else
+ if (palette != NULL)
+ {
+ /* !!! FIXME : No idea if that flags param is right. */
+ SDL_SetPalette(*surface, SDL_LOGPAL, palette, 0, ncolors);
+ free(palette);
+ } /* if */
+#endif
+
+ SDL_SetClipRect(*surface, &clip);
+
+ if (grabmouse)
+ SDL_WM_GrabInput(SDL_GRAB_ON);
+
+ SDL_ShowCursor(showmouse);
+
+#if 0
+ STUB_FUNCTION; /* pull this out of buildengine/sdl_driver.c ... */
+ output_surface_info(*surface);
+#endif
+
+ return(1);
+} /* attempt_fullscreen_toggle */
+
+
+/*
+ * The windib driver can't alert us to the keypad enter key, which
+ * Ken's code depends on heavily. It sends it as the same key as the
+ * regular return key. These users will have to hit SHIFT-ENTER,
+ * which we check for explicitly, and give the engine a keypad enter
+ * enter event.
+ */
+static int handle_keypad_enter_hack(const SDL_Event *event)
+{
+ static int kp_enter_hack = 0;
+ int retval = 0;
+
+ if (event->key.keysym.sym == SDLK_RETURN)
+ {
+ if (event->key.state == SDL_PRESSED)
+ {
+ if (event->key.keysym.mod & KMOD_SHIFT)
+ {
+ kp_enter_hack = 1;
+ retval = scancodes[SDLK_KP_ENTER];
+ } /* if */
+ } /* if */
+
+ else /* key released */
+ {
+ if (kp_enter_hack)
+ {
+ kp_enter_hack = 0;
+ retval = scancodes[SDLK_KP_ENTER];
+ } /* if */
+ } /* if */
+ } /* if */
+
+ return(retval);
+} /* handle_keypad_enter_hack */
+
+
+static int sdl_key_filter(const SDL_Event *event)
+{
+ int k;
+ int keyon;
+ int strippedkey;
+ SDL_GrabMode grab_mode = SDL_GRAB_OFF;
+ int extended;
+
+ if ( (event->key.keysym.sym == SDLK_g) &&
+ (event->key.state == SDL_PRESSED) &&
+ (event->key.keysym.mod & KMOD_CTRL) )
+ {
+ if (!sdl_fullscreen)
+ {
+ sdl_mouse_grabbed = ((sdl_mouse_grabbed) ? 0 : 1);
+ if (sdl_mouse_grabbed)
+ grab_mode = SDL_GRAB_ON;
+ SDL_WM_GrabInput(grab_mode);
+ }
+ return(0);
+ } /* if */
+
+ else if ( ( (event->key.keysym.sym == SDLK_RETURN) ||
+ (event->key.keysym.sym == SDLK_KP_ENTER) ) &&
+ (event->key.state == SDL_PRESSED) &&
+ (event->key.keysym.mod & KMOD_ALT) )
+ {
+ if (SDL_WM_ToggleFullScreen(SDL_GetVideoSurface()))
+ sdl_fullscreen ^= 1;
+ return(0);
+ } /* if */
+
+ /* HDG: put this above the scancode lookup otherwise it is never reached */
+ if ( (event->key.keysym.sym == SDLK_PAUSE) &&
+ (event->key.state == SDL_PRESSED))
+ {
+ PausePressed = true;
+ return(0);
+ }
+
+ k = handle_keypad_enter_hack(event);
+ if (!k)
+ {
+ k = scancodes[event->key.keysym.sym];
+ if (!k) /* No DOS equivalent defined. */
+ return(0);
+ } /* if */
+
+ /* Fix elweirdo SDL capslock/numlock handling, always treat as press */
+ if ( (event->key.keysym.sym != SDLK_CAPSLOCK) &&
+ (event->key.keysym.sym != SDLK_NUMLOCK) &&
+ (event->key.state == SDL_RELEASED) )
+ k += 128; /* +128 signifies that the key is released in DOS. */
+
+ if (event->key.keysym.sym == SDLK_SCROLLOCK)
+ PanicPressed = true;
+
+ else
+ {
+ extended = ((k & 0xFF00) >> 8);
+
+ keyon = k & 0x80;
+ strippedkey = k & 0x7f;
+
+ if (extended != 0)
+ {
+ KeyboardQueue[ Keytail ] = extended;
+ Keytail = ( Keytail + 1 )&( KEYQMAX - 1 );
+ k = scancodes[event->key.keysym.sym] & 0xFF;
+ if (event->key.state == SDL_RELEASED)
+ k += 128; /* +128 signifies that the key is released in DOS. */
+ }
+
+ if (keyon) // Up event
+ Keystate[strippedkey]=0;
+ else // Down event
+ {
+ Keystate[strippedkey]=1;
+ LastScan = k;
+ }
+
+ KeyboardQueue[ Keytail ] = k;
+ Keytail = ( Keytail + 1 )&( KEYQMAX - 1 );
+ }
+
+ return(0);
+} /* sdl_key_filter */
+
+
+static int root_sdl_event_filter(const SDL_Event *event)
+{
+ switch (event->type)
+ {
+ case SDL_KEYUP:
+ case SDL_KEYDOWN:
+ return(sdl_key_filter(event));
+ case SDL_JOYBALLMOTION:
+ case SDL_MOUSEMOTION:
+ return(sdl_mouse_motion_filter(event));
+ case SDL_MOUSEBUTTONUP:
+ case SDL_MOUSEBUTTONDOWN:
+ return(sdl_mouse_button_filter(event));
+ case SDL_QUIT:
+ /* !!! rcg TEMP */
+ fprintf(stderr, "\n\n\nSDL_QUIT!\n\n\n");
+ SDL_Quit();
+ exit(42);
+ } /* switch */
+
+ return(1);
+} /* root_sdl_event_filter */
+
+
+static void sdl_handle_events(void)
+{
+ SDL_Event event;
+ while (SDL_PollEvent(&event))
+ root_sdl_event_filter(&event);
+} /* sdl_handle_events */
+#endif
+
+
+//******************************************************************************
+//
+// IN_PumpEvents () - Let platform process an event queue.
+//
+//******************************************************************************
+void IN_PumpEvents(void)
+{
+#if USE_SDL
+ sdl_handle_events();
+
+#elif PLATFORM_DOS
+ /* no-op. */
+
+#else
+#error please define for your platform.
+#endif
+}
+
+
+
+//******************************************************************************
+//
+// INL_GetMouseDelta () - Gets the amount that the mouse has moved from the
+// mouse driver
+//
+//******************************************************************************
+
+void INL_GetMouseDelta(int *x,int *y)
+{
+ IN_PumpEvents();
+
+#ifdef PLATFORM_DOS
+ union REGS inregs;
+ union REGS outregs;
+
+ if (!MousePresent)
+ *x = *y = 0;
+ else
+ {
+ inregs.w.ax = MDelta;
+ int386 (MouseInt, &inregs, &outregs);
+ *x = outregs.w.cx;
+ *y = outregs.w.dx;
+ }
+
+#elif USE_SDL
+ *x = sdl_mouse_delta_x;
+ *y = sdl_mouse_delta_y;
+
+ sdl_mouse_delta_x = sdl_mouse_delta_y = 0;
+
+#else
+#error please define for your platform.
+#endif
+}
+
+
+
+//******************************************************************************
+//
+// IN_GetMouseButtons () - Gets the status of the mouse buttons from the
+// mouse driver
+//
+//******************************************************************************
+
+word IN_GetMouseButtons
+(
+ void
+)
+
+{
+ word buttons = 0;
+
+ IN_PumpEvents();
+
+#if USE_SDL
+ buttons = sdl_mouse_button_mask;
+
+#elif PLATFORM_DOS
+ union REGS inregs;
+ union REGS outregs;
+
+ if (!MousePresent || !mouseenabled)
+ return (0);
+
+ inregs.w.ax = MButtons;
+ int386 (MouseInt, &inregs, &outregs);
+
+ buttons = outregs.w.bx;
+
+#else
+# error please define for your platform.
+#endif
+
+// Used by menu routines that need to wait for a button release.
+// Sometimes the mouse driver misses an interrupt, so you can't wait for
+// a button to be released. Instead, you must ignore any buttons that
+// are pressed.
+
+ IgnoreMouse &= buttons;
+ buttons &= ~IgnoreMouse;
+
+ return (buttons);
+}
+
+
+//******************************************************************************
+//
+// IN_IgnoreMouseButtons () -
+// Tells the mouse to ignore the currently pressed buttons.
+//
+//******************************************************************************
+
+void IN_IgnoreMouseButtons
+(
+ void
+)
+
+{
+ IgnoreMouse |= IN_GetMouseButtons();
+}
+
+
+//******************************************************************************
+//
+// IN_GetJoyAbs () - Reads the absolute position of the specified joystick
+//
+//******************************************************************************
+
+void IN_GetJoyAbs (word joy, word *xp, word *yp)
+{
+ Joy_x = Joy_y = 0;
+ Joy_xs = joy? 2 : 0; // Find shift value for x axis
+ Joy_xb = 1 << Joy_xs; // Use shift value to get x bit mask
+ Joy_ys = joy? 3 : 1; // Do the same for y axis
+ Joy_yb = 1 << Joy_ys;
+
+#ifdef DOS
+ JoyStick_Vals ();
+#else
+ if (joy < sdl_total_sticks)
+ {
+ Joy_x = SDL_JoystickGetAxis (sdl_joysticks[joy], 0);
+ Joy_y = SDL_JoystickGetAxis (sdl_joysticks[joy], 1);
+ } else {
+ Joy_x = 0;
+ Joy_y = 0;
+ }
+#endif
+
+ *xp = Joy_x;
+ *yp = Joy_y;
+}
+
+void JoyStick_Vals (void)
+{
+
+}
+
+
+//******************************************************************************
+//
+// INL_GetJoyDelta () - Returns the relative movement of the specified
+// joystick (from +/-127)
+//
+//******************************************************************************
+
+void INL_GetJoyDelta (word joy, int *dx, int *dy)
+{
+ word x, y;
+ JoystickDef *def;
+ static longword lasttime;
+
+ IN_GetJoyAbs (joy, &x, &y);
+ def = JoyDefs + joy;
+
+ if (x < def->threshMinX)
+ {
+ if (x < def->joyMinX)
+ x = def->joyMinX;
+
+ x = -(x - def->threshMinX);
+ x *= def->joyMultXL;
+ x >>= JoyScaleShift;
+ *dx = (x > 127)? -127 : -x;
+ }
+ else if (x > def->threshMaxX)
+ {
+ if (x > def->joyMaxX)
+ x = def->joyMaxX;
+
+ x = x - def->threshMaxX;
+ x *= def->joyMultXH;
+ x >>= JoyScaleShift;
+ *dx = (x > 127)? 127 : x;
+ }
+ else
+ *dx = 0;
+
+ if (y < def->threshMinY)
+ {
+ if (y < def->joyMinY)
+ y = def->joyMinY;
+
+ y = -(y - def->threshMinY);
+ y *= def->joyMultYL;
+ y >>= JoyScaleShift;
+ *dy = (y > 127)? -127 : -y;
+ }
+ else if (y > def->threshMaxY)
+ {
+ if (y > def->joyMaxY)
+ y = def->joyMaxY;
+
+ y = y - def->threshMaxY;
+ y *= def->joyMultYH;
+ y >>= JoyScaleShift;
+ *dy = (y > 127)? 127 : y;
+ }
+ else
+ *dy = 0;
+
+ lasttime = GetTicCount();
+}
+
+
+
+//******************************************************************************
+//
+// INL_GetJoyButtons () - Returns the button status of the specified
+// joystick
+//
+//******************************************************************************
+
+word INL_GetJoyButtons (word joy)
+{
+ word result = 0;
+
+#if USE_SDL
+ if (joy < sdl_total_sticks)
+ result = sdl_stick_button_state[joy];
+
+#elif PLATFORM_DOS
+ result = inp (0x201); // Get all the joystick buttons
+ result >>= joy? 6 : 4; // Shift into bits 0-1
+ result &= 3; // Mask off the useless bits
+ result ^= 3;
+
+#else
+#error please define for your platform.
+#endif
+
+ return result;
+}
+
+#if 0
+//******************************************************************************
+//
+// IN_GetJoyButtonsDB () - Returns the de-bounced button status of the
+// specified joystick
+//
+//******************************************************************************
+
+word IN_GetJoyButtonsDB (word joy)
+{
+ longword lasttime;
+ word result1,result2;
+
+ do
+ {
+ result1 = INL_GetJoyButtons (joy);
+ lasttime = GetTicCount();
+ while (GetTicCount() == lasttime)
+ ;
+ result2 = INL_GetJoyButtons (joy);
+ } while (result1 != result2);
+
+ return(result1);
+}
+#endif
+
+//******************************************************************************
+//
+// INL_StartMouse () - Detects and sets up the mouse
+//
+//******************************************************************************
+
+boolean INL_StartMouse (void)
+{
+
+ boolean retval = false;
+
+#if USE_SDL
+ /* no-op. */
+ retval = true;
+
+#elif PLATFORM_DOS
+ union REGS inregs;
+ union REGS outregs;
+
+ inregs.w.ax = 0;
+ int386 (MouseInt, &inregs, &outregs);
+
+ retval = ((outregs.w.ax == 0xffff) ? true : false);
+
+#else
+#error please define your platform.
+#endif
+
+ return (retval);
+}
+
+
+
+//******************************************************************************
+//
+// INL_SetJoyScale () - Sets up scaling values for the specified joystick
+//
+//******************************************************************************
+
+void INL_SetJoyScale (word joy)
+{
+ JoystickDef *def;
+
+ def = &JoyDefs[joy];
+ def->joyMultXL = JoyScaleMax / (def->threshMinX - def->joyMinX);
+ def->joyMultXH = JoyScaleMax / (def->joyMaxX - def->threshMaxX);
+ def->joyMultYL = JoyScaleMax / (def->threshMinY - def->joyMinY);
+ def->joyMultYH = JoyScaleMax / (def->joyMaxY - def->threshMaxY);
+}
+
+
+
+//******************************************************************************
+//
+// IN_SetupJoy () - Sets up thresholding values and calls INL_SetJoyScale()
+// to set up scaling values
+//
+//******************************************************************************
+
+void IN_SetupJoy (word joy, word minx, word maxx, word miny, word maxy)
+{
+ word d,r;
+ JoystickDef *def;
+
+ def = &JoyDefs[joy];
+
+ def->joyMinX = minx;
+ def->joyMaxX = maxx;
+ r = maxx - minx;
+ d = r / 3;
+ def->threshMinX = ((r / 2) - d) + minx;
+ def->threshMaxX = ((r / 2) + d) + minx;
+
+ def->joyMinY = miny;
+ def->joyMaxY = maxy;
+ r = maxy - miny;
+ d = r / 3;
+ def->threshMinY = ((r / 2) - d) + miny;
+ def->threshMaxY = ((r / 2) + d) + miny;
+
+ INL_SetJoyScale (joy);
+}
+
+
+//******************************************************************************
+//
+// INL_StartJoy () - Detects & auto-configures the specified joystick
+// The auto-config assumes the joystick is centered
+//
+//******************************************************************************
+
+
+boolean INL_StartJoy (word joy)
+{
+ word x,y;
+
+#if USE_SDL
+ if (!SDL_WasInit(SDL_INIT_JOYSTICK))
+ {
+ SDL_Init(SDL_INIT_JOYSTICK);
+ sdl_total_sticks = SDL_NumJoysticks();
+ if (sdl_total_sticks > MaxJoys) sdl_total_sticks = MaxJoys;
+
+ if ((sdl_stick_button_state == NULL) && (sdl_total_sticks > 0))
+ {
+ sdl_stick_button_state = (word *) malloc(sizeof (word) * sdl_total_sticks);
+ if (sdl_stick_button_state == NULL)
+ SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
+ else
+ memset(sdl_stick_button_state, '\0', sizeof (word) * sdl_total_sticks);
+ }
+ SDL_JoystickEventState(SDL_ENABLE);
+ }
+
+ if (joy >= sdl_total_sticks) return (false);
+ sdl_joysticks[joy] = SDL_JoystickOpen (joy);
+#endif
+
+ IN_GetJoyAbs (joy, &x, &y);
+
+ if
+ (
+ ((x == 0) || (x > MaxJoyValue - 10))
+ || ((y == 0) || (y > MaxJoyValue - 10))
+ )
+ return(false);
+ else
+ {
+ IN_SetupJoy (joy, 0, x * 2, 0, y * 2);
+ return (true);
+ }
+}
+
+
+
+//******************************************************************************
+//
+// INL_ShutJoy() - Cleans up the joystick stuff
+//
+//******************************************************************************
+
+void INL_ShutJoy (word joy)
+{
+ JoysPresent[joy] = false;
+#ifndef DOS
+ if (joy < sdl_total_sticks) SDL_JoystickClose (sdl_joysticks[joy]);
+#endif
+}
+
+
+
+//******************************************************************************
+//
+// IN_Startup() - Starts up the Input Mgr
+//
+//******************************************************************************
+
+
+void IN_Startup (void)
+{
+ boolean checkjoys,
+ checkmouse,
+ checkcyberman,
+ checkspaceball,
+ swiftstatus,
+ checkassassin;
+
+ word i;
+
+ if (IN_Started==true)
+ return;
+
+#if USE_SDL
+
+#if PLATFORM_WIN32
+// fixme: remove this.
+ sdl_mouse_grabbed = 1;
+#endif
+
+ /*
+ all keys are now mapped to the wolf3d-style names,
+ except where no such name is available.
+ */
+ memset(scancodes, '\0', sizeof (scancodes));
+ scancodes[SDLK_ESCAPE] = sc_Escape;
+ scancodes[SDLK_1] = sc_1;
+ scancodes[SDLK_2] = sc_2;
+ scancodes[SDLK_3] = sc_3;
+ scancodes[SDLK_4] = sc_4;
+ scancodes[SDLK_5] = sc_5;
+ scancodes[SDLK_6] = sc_6;
+ scancodes[SDLK_7] = sc_7;
+ scancodes[SDLK_8] = sc_8;
+ scancodes[SDLK_9] = sc_9;
+ scancodes[SDLK_0] = sc_0;
+
+ //scancodes[SDLK_EQUALS] = 0x4E;
+ scancodes[SDLK_EQUALS] = sc_Equals;
+
+ scancodes[SDLK_BACKSPACE] = sc_BackSpace;
+ scancodes[SDLK_TAB] = sc_Tab;
+ scancodes[SDLK_q] = sc_Q;
+ scancodes[SDLK_w] = sc_W;
+ scancodes[SDLK_e] = sc_E;
+ scancodes[SDLK_r] = sc_R;
+ scancodes[SDLK_t] = sc_T;
+ scancodes[SDLK_y] = sc_Y;
+ scancodes[SDLK_u] = sc_U;
+ scancodes[SDLK_i] = sc_I;
+ scancodes[SDLK_o] = sc_O;
+ scancodes[SDLK_p] = sc_P;
+ scancodes[SDLK_LEFTBRACKET] = sc_OpenBracket;
+ scancodes[SDLK_RIGHTBRACKET] = sc_CloseBracket;
+ scancodes[SDLK_RETURN] = sc_Return;
+ scancodes[SDLK_LCTRL] = sc_Control;
+ scancodes[SDLK_a] = sc_A;
+ scancodes[SDLK_s] = sc_S;
+ scancodes[SDLK_d] = sc_D;
+ scancodes[SDLK_f] = sc_F;
+ scancodes[SDLK_g] = sc_G;
+ scancodes[SDLK_h] = sc_H;
+ scancodes[SDLK_j] = sc_J;
+ scancodes[SDLK_k] = sc_K;
+ scancodes[SDLK_l] = sc_L;
+ scancodes[SDLK_SEMICOLON] = 0x27;
+ scancodes[SDLK_QUOTE] = 0x28;
+ scancodes[SDLK_BACKQUOTE] = 0x29;
+
+ /* left shift, but ROTT maps it to right shift in isr.c */
+ scancodes[SDLK_LSHIFT] = sc_RShift; /* sc_LShift */
+
+ scancodes[SDLK_BACKSLASH] = 0x2B;
+ /* Accept the German eszett as a backslash key */
+ scancodes[SDLK_WORLD_63] = 0x2B;
+ scancodes[SDLK_z] = sc_Z;
+ scancodes[SDLK_x] = sc_X;
+ scancodes[SDLK_c] = sc_C;
+ scancodes[SDLK_v] = sc_V;
+ scancodes[SDLK_b] = sc_B;
+ scancodes[SDLK_n] = sc_N;
+ scancodes[SDLK_m] = sc_M;
+ scancodes[SDLK_COMMA] = sc_Comma;
+ scancodes[SDLK_PERIOD] = sc_Period;
+ scancodes[SDLK_SLASH] = 0x35;
+ scancodes[SDLK_RSHIFT] = sc_RShift;
+ scancodes[SDLK_KP_DIVIDE] = 0x35;
+
+ /* 0x37 is printscreen */
+ //scancodes[SDLK_KP_MULTIPLY] = 0x37;
+
+ scancodes[SDLK_LALT] = sc_Alt;
+ scancodes[SDLK_RALT] = sc_Alt;
+ scancodes[SDLK_MODE] = sc_Alt;
+ scancodes[SDLK_RCTRL] = sc_Control;
+ scancodes[SDLK_SPACE] = sc_Space;
+ scancodes[SDLK_CAPSLOCK] = sc_CapsLock;
+ scancodes[SDLK_F1] = sc_F1;
+ scancodes[SDLK_F2] = sc_F2;
+ scancodes[SDLK_F3] = sc_F3;
+ scancodes[SDLK_F4] = sc_F4;
+ scancodes[SDLK_F5] = sc_F5;
+ scancodes[SDLK_F6] = sc_F6;
+ scancodes[SDLK_F7] = sc_F7;
+ scancodes[SDLK_F8] = sc_F8;
+ scancodes[SDLK_F9] = sc_F9;
+ scancodes[SDLK_F10] = sc_F10;
+ scancodes[SDLK_F11] = sc_F11;
+ scancodes[SDLK_F12] = sc_F12;
+ scancodes[SDLK_NUMLOCK] = 0x45;
+ scancodes[SDLK_SCROLLOCK] = 0x46;
+
+ //scancodes[SDLK_MINUS] = 0x4A;
+ scancodes[SDLK_MINUS] = sc_Minus;
+
+ scancodes[SDLK_KP7] = sc_Home;
+ scancodes[SDLK_KP8] = sc_UpArrow;
+ scancodes[SDLK_KP9] = sc_PgUp;
+ scancodes[SDLK_HOME] = sc_Home;
+ scancodes[SDLK_UP] = sc_UpArrow;
+ scancodes[SDLK_PAGEUP] = sc_PgUp;
+ // Make this a normal minus, for viewport changing
+ //scancodes[SDLK_KP_MINUS] = 0xE04A;
+ scancodes[SDLK_KP_MINUS] = sc_Minus;
+ scancodes[SDLK_KP4] = sc_LeftArrow;
+ scancodes[SDLK_KP5] = 0x4C;
+ scancodes[SDLK_KP6] = sc_RightArrow;
+ scancodes[SDLK_LEFT] = sc_LeftArrow;
+ scancodes[SDLK_RIGHT] = sc_RightArrow;
+
+ //scancodes[SDLK_KP_PLUS] = 0x4E;
+ scancodes[SDLK_KP_PLUS] = sc_Plus;
+
+ scancodes[SDLK_KP1] = sc_End;
+ scancodes[SDLK_KP2] = sc_DownArrow;
+ scancodes[SDLK_KP3] = sc_PgDn;
+ scancodes[SDLK_END] = sc_End;
+ scancodes[SDLK_DOWN] = sc_DownArrow;
+ scancodes[SDLK_PAGEDOWN] = sc_PgDn;
+ scancodes[SDLK_DELETE] = sc_Delete;
+ scancodes[SDLK_KP0] = sc_Insert;
+ scancodes[SDLK_INSERT] = sc_Insert;
+ scancodes[SDLK_KP_ENTER] = sc_Return;
+#endif
+
+ checkjoys = true;
+ checkmouse = true;
+ checkcyberman = false;
+ checkassassin = false;
+ checkspaceball = false;
+ SpaceBallPresent = false;
+ CybermanPresent = false;
+ AssassinPresent = false;
+
+ for (i = 1; i < _argc; i++)
+ {
+ switch (US_CheckParm (_argv[i], ParmStrings))
+ {
+ case 0:
+ checkjoys = false;
+ break;
+
+ case 1:
+ checkmouse = false;
+ break;
+
+ case 2:
+ checkspaceball = true;
+ break;
+
+ case 3:
+ checkcyberman = true;
+ checkmouse = false;
+ break;
+
+ case 4:
+ checkassassin = true;
+ checkmouse = false;
+ break;
+ }
+ }
+
+ MousePresent = checkmouse ? INL_StartMouse() : false;
+
+ if (!MousePresent)
+ mouseenabled = false;
+ else
+ {
+ if (!quiet)
+ printf("IN_Startup: Mouse Present\n");
+ }
+
+ for (i = 0; i < MaxJoys; i++)
+ {
+ JoysPresent[i] = checkjoys ? INL_StartJoy(i) : false;
+ if (INL_StartJoy(i))
+ {
+ if (!quiet)
+ printf("IN_Startup: Joystick Present\n");
+ }
+ }
+
+ if (checkspaceball)
+ {
+ OpenSpaceBall ();
+ spaceballenabled=true;
+ }
+
+ if ((checkcyberman || checkassassin) && (swiftstatus = SWIFT_Initialize ()))
+ {
+ int dynamic;
+
+ if (checkcyberman)
+ {
+ CybermanPresent = swiftstatus;
+ cybermanenabled = true;
+ }
+ else if (checkassassin)
+ {
+ AssassinPresent = checkassassin & swiftstatus;
+ assassinenabled = true;
+ }
+
+ dynamic = SWIFT_GetDynamicDeviceData ();
+
+ SWIFT_TactileFeedback (40, 20, 20);
+
+ if (SWIFT_GetDynamicDeviceData () == 2)
+ Error ("SWIFT ERROR : External Power too high!\n");
+
+ SWIFT_TactileFeedback (100, 10, 10);
+ if (!quiet)
+ printf("IN_Startup: Swift Device Present\n");
+ }
+
+ IN_Started = true;
+}
+
+
+#if 0
+//******************************************************************************
+//
+// IN_Default() - Sets up default conditions for the Input Mgr
+//
+//******************************************************************************
+
+void IN_Default (boolean gotit, ControlType in)
+{
+ if
+ (
+ (!gotit)
+ || ((in == ctrl_Joystick1) && !JoysPresent[0])
+ || ((in == ctrl_Joystick2) && !JoysPresent[1])
+ || ((in == ctrl_Mouse) && !MousePresent)
+ )
+ in = ctrl_Keyboard1;
+ IN_SetControlType (0, in);
+}
+#endif
+
+//******************************************************************************
+//
+// IN_Shutdown() - Shuts down the Input Mgr
+//
+//******************************************************************************
+
+void IN_Shutdown (void)
+{
+ word i;
+
+ if (IN_Started==false)
+ return;
+
+// INL_ShutMouse();
+
+ for (i = 0; i < MaxJoys; i++)
+ INL_ShutJoy(i);
+
+ if (CybermanPresent || AssassinPresent)
+ SWIFT_Terminate ();
+
+ CloseSpaceBall ();
+
+ IN_Started = false;
+}
+
+
+//******************************************************************************
+//
+// IN_ClearKeysDown() - Clears the keyboard array
+//
+//******************************************************************************
+
+void IN_ClearKeysDown (void)
+{
+ LastScan = sc_None;
+ memset ((void *)Keyboard, 0, sizeof (Keyboard));
+}
+
+
+//******************************************************************************
+//
+// IN_ReadControl() - Reads the device associated with the specified
+// player and fills in the control info struct
+//
+//******************************************************************************
+
+void IN_ReadControl (int player, ControlInfo *info)
+{
+ boolean realdelta;
+ word buttons;
+ int dx,dy;
+ Motion mx,my;
+ ControlType type;
+
+ KeyboardDef *def;
+
+ dx = dy = 0;
+ mx = my = motion_None;
+ buttons = 0;
+
+
+ switch (type = Controls[player])
+ {
+ case ctrl_Keyboard:
+ def = &KbdDefs;
+
+#if 0
+ if (Keyboard[def->upleft])
+ mx = motion_Left,my = motion_Up;
+ else if (Keyboard[def->upright])
+ mx = motion_Right,my = motion_Up;
+ else if (Keyboard[def->downleft])
+ mx = motion_Left,my = motion_Down;
+ else if (Keyboard[def->downright])
+ mx = motion_Right,my = motion_Down;
+#endif
+ if (Keyboard[sc_UpArrow])
+ my = motion_Up;
+ else if (Keyboard[sc_DownArrow])
+ my = motion_Down;
+
+ if (Keyboard[sc_LeftArrow])
+ mx = motion_Left;
+ else if (Keyboard[sc_RightArrow])
+ mx = motion_Right;
+
+ if (Keyboard[def->button0])
+ buttons += 1 << 0;
+ if (Keyboard[def->button1])
+ buttons += 1 << 1;
+ realdelta = false;
+ break;
+
+#if 0
+ case ctrl_Joystick1:
+ case ctrl_Joystick2:
+ INL_GetJoyDelta (type - ctrl_Joystick, &dx, &dy);
+ buttons = INL_GetJoyButtons (type - ctrl_Joystick);
+ realdelta = true;
+ break;
+
+ case ctrl_Mouse:
+ INL_GetMouseDelta (&dx,&dy);
+ buttons = IN_GetMouseButtons ();
+ realdelta = true;
+ break;
+
+#endif
+ default:
+ ;
+ }
+
+ if (realdelta)
+ {
+ mx = (dx < 0)? motion_Left : ((dx > 0)? motion_Right : motion_None);
+ my = (dy < 0)? motion_Up : ((dy > 0)? motion_Down : motion_None);
+ }
+ else
+ {
+ dx = mx * 127;
+ dy = my * 127;
+ }
+
+ info->x = dx;
+ info->xaxis = mx;
+ info->y = dy;
+ info->yaxis = my;
+ info->button0 = buttons & (1 << 0);
+ info->button1 = buttons & (1 << 1);
+ info->button2 = buttons & (1 << 2);
+ info->button3 = buttons & (1 << 3);
+ info->dir = DirTable[((my + 1) * 3) + (mx + 1)];
+}
+
+
+//******************************************************************************
+//
+// IN_WaitForKey() - Waits for a scan code, then clears LastScan and
+// returns the scan code
+//
+//******************************************************************************
+
+ScanCode IN_WaitForKey (void)
+{
+ ScanCode result;
+
+ while (!(result = LastScan))
+ IN_PumpEvents();
+ LastScan = 0;
+ return (result);
+}
+
+
+//******************************************************************************
+//
+// IN_Ack() - waits for a button or key press. If a button is down, upon
+// calling, it must be released for it to be recognized
+//
+//******************************************************************************
+
+boolean btnstate[8];
+
+void IN_StartAck (void)
+{
+ unsigned i,
+ buttons = 0;
+
+//
+// get initial state of everything
+//
+ LastScan = 0;
+
+ IN_ClearKeysDown ();
+ memset (btnstate, 0, sizeof(btnstate));
+
+ IN_PumpEvents();
+
+ buttons = IN_JoyButtons () << 4;
+
+ buttons |= IN_GetMouseButtons();
+
+ if (SpaceBallPresent && spaceballenabled)
+ {
+ buttons |= GetSpaceBallButtons ();
+ }
+
+ for (i=0; i<8; i++,buttons>>=1)
+ if (buttons&1)
+ btnstate[i] = true;
+}
+
+
+
+//******************************************************************************
+//
+// IN_CheckAck ()
+//
+//******************************************************************************
+
+boolean IN_CheckAck (void)
+{
+ unsigned i,
+ buttons = 0;
+
+//
+// see if something has been pressed
+//
+ if (LastScan)
+ return true;
+
+ IN_PumpEvents();
+
+ buttons = IN_JoyButtons () << 4;
+
+ buttons |= IN_GetMouseButtons();
+
+ for (i=0; i<8; i++,buttons>>=1)
+ if ( buttons&1 )
+ {
+ if (!btnstate[i])
+ return true;
+ }
+ else
+ btnstate[i]=false;
+
+ return false;
+}
+
+
+
+//******************************************************************************
+//
+// IN_Ack ()
+//
+//******************************************************************************
+
+void IN_Ack (void)
+{
+ IN_StartAck ();
+
+ while (!IN_CheckAck ())
+ ;
+}
+
+
+
+//******************************************************************************
+//
+// IN_UserInput() - Waits for the specified delay time (in ticks) or the
+// user pressing a key or a mouse button. If the clear flag is set, it
+// then either clears the key or waits for the user to let the mouse
+// button up.
+//
+//******************************************************************************
+
+boolean IN_UserInput (long delay)
+{
+ long lasttime;
+
+ lasttime = GetTicCount();
+
+ IN_StartAck ();
+ do
+ {
+ if (IN_CheckAck())
+ return true;
+ } while ((GetTicCount() - lasttime) < delay);
+
+ return (false);
+}
+
+//===========================================================================
+
+
+/*
+===================
+=
+= IN_JoyButtons
+=
+===================
+*/
+
+byte IN_JoyButtons (void)
+{
+ unsigned joybits = 0;
+
+#if USE_SDL
+ joybits = sdl_sticks_joybits;
+
+#elif PLATFORM_DOS
+ joybits = inp (0x201); // Get all the joystick buttons
+ joybits >>= 4; // only the high bits are useful
+ joybits ^= 15; // return with 1=pressed
+
+#else
+#error define your platform.
+#endif
+
+ return (byte) joybits;
+}
+
+
+//******************************************************************************
+//
+// IN_UpdateKeyboard ()
+//
+//******************************************************************************
+
+/* HACK HACK HACK */
+static int queuegotit=0;
+
+void IN_UpdateKeyboard (void)
+{
+ int tail;
+ int key;
+
+ if (!queuegotit)
+ IN_PumpEvents();
+
+ queuegotit=0;
+
+ if (Keytail != Keyhead)
+ {
+ tail = Keytail;
+
+ while (Keyhead != tail)
+ {
+ if (KeyboardQueue[Keyhead] & 0x80) // Up event
+ {
+ key = KeyboardQueue[Keyhead] & 0x7F; // AND off high bit
+
+// if (keysdown[key])
+// {
+// KeyboardQueue[Keytail] = KeyboardQueue[Keyhead];
+// Keytail = (Keytail+1)&(KEYQMAX-1);
+// }
+// else
+ Keyboard[key] = 0;
+ }
+ else // Down event
+ {
+ Keyboard[KeyboardQueue[Keyhead]] = 1;
+// keysdown[KeyboardQueue[Keyhead]] = 1;
+ }
+
+ Keyhead = (Keyhead+1)&(KEYQMAX-1);
+
+ } // while
+ } // if
+
+ // Carry over movement keys from the last refresh
+// keysdown[sc_RightArrow] = Keyboard[sc_RightArrow];
+// keysdown[sc_LeftArrow] = Keyboard[sc_LeftArrow];
+// keysdown[sc_UpArrow] = Keyboard[sc_UpArrow];
+// keysdown[sc_DownArrow] = Keyboard[sc_DownArrow];
+}
+
+
+
+//******************************************************************************
+//
+// IN_InputUpdateKeyboard ()
+//
+//******************************************************************************
+
+int IN_InputUpdateKeyboard (void)
+{
+ int key;
+ int returnval = 0;
+ boolean done = false;
+
+// _disable ();
+
+ if (Keytail != Keyhead)
+ {
+ int tail = Keytail;
+
+ while (!done && (Keyhead != tail))
+ {
+ if (KeyboardQueue[Keyhead] & 0x80) // Up event
+ {
+ key = KeyboardQueue[Keyhead] & 0x7F; // AND off high bit
+
+ Keyboard[key] = 0;
+ }
+ else // Down event
+ {
+ Keyboard[KeyboardQueue[Keyhead]] = 1;
+ returnval = KeyboardQueue[Keyhead];
+ done = true;
+ }
+
+ Keyhead = (Keyhead+1)&(KEYQMAX-1);
+ }
+ } // if
+
+// _enable ();
+
+ return (returnval);
+}
+
+
+//******************************************************************************
+//
+// IN_ClearKeyboardQueue ()
+//
+//******************************************************************************
+
+void IN_ClearKeyboardQueue (void)
+{
+ return;
+
+// IN_ClearKeysDown ();
+
+// Keytail = Keyhead = 0;
+// memset (KeyboardQueue, 0, sizeof (KeyboardQueue));
+// I_SendKeyboardData(0xf6);
+// I_SendKeyboardData(0xf4);
+}
+
+
+#if 0
+//******************************************************************************
+//
+// IN_DumpKeyboardQueue ()
+//
+//******************************************************************************
+
+void IN_DumpKeyboardQueue (void)
+{
+ int head = Keyhead;
+ int tail = Keytail;
+ int key;
+
+ if (tail != head)
+ {
+ SoftError( "START DUMP\n");
+
+ while (head != tail)
+ {
+ if (KeyboardQueue[head] & 0x80) // Up event
+ {
+ key = KeyboardQueue[head] & 0x7F; // AND off high bit
+
+// if (keysdown[key])
+// {
+// SoftError( "%s - was put in next refresh\n",
+// IN_GetScanName (key));
+// }
+// else
+// {
+ if (Keyboard[key] == 0)
+ SoftError( "%s %ld - was lost\n", IN_GetScanName (key), key);
+ else
+ SoftError( "%s %ld - up\n", IN_GetScanName (key), key);
+// }
+ }
+ else // Down event
+ SoftError( "%s %ld - down\n", IN_GetScanName (KeyboardQueue[head]), KeyboardQueue[head]);
+
+ head = (head+1)&(KEYQMAX-1);
+ } // while
+
+ SoftError( "END DUMP\n");
+
+ } // if
+}
+#endif
+
+
+//******************************************************************************
+//
+// QueueLetterInput ()
+//
+//******************************************************************************
+
+void QueueLetterInput (void)
+{
+ int head = Keyhead;
+ int tail = Keytail;
+ char c;
+ int scancode;
+ boolean send = false;
+
+#ifndef PLATFORM_DOS
+ /* HACK HACK HACK */
+ /*
+ OK, we want the new keys NOW, and not when the update gets them.
+ Since this called before IN_UpdateKeyboard in PollKeyboardButtons,
+ we shall update here. The hack is there to prevent IN_UpdateKeyboard
+ from stealing any keys... - SBF
+ */
+ IN_PumpEvents();
+ head = Keyhead;
+ tail = Keytail;
+ queuegotit=1;
+ /* HACK HACK HACK */
+#endif
+
+ while (head != tail)
+ {
+ if (!(KeyboardQueue[head] & 0x80)) // Down event
+ {
+ scancode = KeyboardQueue[head];
+
+ if (Keyboard[sc_RShift] || Keyboard[sc_LShift])
+ {
+ c = ShiftedScanChars[scancode];
+ }
+ else
+ {
+ c = ScanChars[scancode];
+ }
+
+ // If "is printable char", queue the character
+ if (c)
+ {
+ LetterQueue[LastLetter] = c;
+ LastLetter = (LastLetter+1)&(MAXLETTERS-1);
+
+ // If typing a message, update the text with 'c'
+
+ if ( MSG.messageon )
+ {
+ Keystate[scancode]=0;
+ KeyboardQueue[head] = 0;
+ if ( MSG.inmenu )
+ {
+ if ( ( c == 'A' ) || ( c == 'a' ) )
+ {
+ MSG.towho = MSG_DIRECTED_TO_ALL;
+ send = true;
+ }
+
+ if ( ( gamestate.teamplay ) &&
+ ( ( c == 'T' ) || ( c == 't' ) ) )
+ {
+ MSG.towho = MSG_DIRECTED_TO_TEAM;
+ send = true;
+ }
+
+ if ( ( c >= '0' ) && ( c <= '9' ) )
+ {
+ int who;
+
+ if ( c == '0' )
+ {
+ who = 10;
+ }
+ else
+ {
+ who = c - '1';
+ }
+
+ // Skip over local player
+ if ( who >= consoleplayer )
+ {
+ who++;
+ }
+
+ if ( who < numplayers )
+ {
+ MSG.towho = who;
+ send = true;
+ }
+ }
+
+ if ( send )
+ {
+ MSG.messageon = false;
+ KeyboardQueue[ head ] = 0;
+ Keyboard[ scancode ] = 0;
+ LastScan = 0;
+ FinishModemMessage( MSG.textnum, true );
+ }
+ }
+ else if ( ( scancode >= sc_1 ) && ( scancode <= sc_0 ) &&
+ ( Keyboard[ sc_Alt ] ) )
+ {
+ int msg;
+
+ msg = scancode - sc_1;
+
+ if ( CommbatMacros[ msg ].avail )
+ {
+ MSG.length = strlen( CommbatMacros[ msg ].macro ) + 1;
+ strcpy( Messages[ MSG.textnum ].text,
+ CommbatMacros[ msg ].macro );
+
+ MSG.messageon = false;
+ FinishModemMessage( MSG.textnum, true );
+ KeyboardQueue[ head ] = 0;
+ Keyboard[ sc_Enter ] = 0;
+ Keyboard[ sc_Escape ] = 0;
+ LastScan = 0;
+ }
+ else
+ {
+ MSG.messageon = false;
+ MSG.directed = false;
+
+ FinishModemMessage( MSG.textnum, false );
+ AddMessage( "No macro.", MSG_MACRO );
+ KeyboardQueue[ head ] = 0;
+ Keyboard[ sc_Enter ] = 0;
+ Keyboard[ sc_Escape ] = 0;
+ LastScan = 0;
+ }
+ }
+ else if ( MSG.length < MAXMESSAGELENGTH )
+ {
+ UpdateModemMessage (MSG.textnum, c);
+ }
+ }
+ }
+ else
+ {
+ // If typing a message, check for special characters
+
+ if ( MSG.messageon && MSG.inmenu )
+ {
+ if ( scancode == sc_Escape )
+ {
+ MSG.messageon = false;
+ MSG.directed = false;
+ FinishModemMessage( MSG.textnum, false );
+ KeyboardQueue[head] = 0;
+ Keyboard[sc_Enter] = 0;
+ Keyboard[sc_Escape] = 0;
+ LastScan = 0;
+ }
+ }
+ else if ( MSG.messageon && !MSG.inmenu )
+ {
+ if ( ( scancode >= sc_F1 ) &&
+ ( scancode <= sc_F10 ) )
+ {
+ MSG.remoteridicule = scancode - sc_F1;
+ MSG.messageon = false;
+ FinishModemMessage(MSG.textnum, true);
+ KeyboardQueue[head] = 0;
+ Keyboard[sc_Enter] = 0;
+ Keyboard[sc_Escape] = 0;
+ LastScan = 0;
+ }
+
+ switch (scancode)
+ {
+ case sc_BackSpace:
+ KeyboardQueue[head] = 0;
+ if (MSG.length > 1)
+ {
+ ModemMessageDeleteChar (MSG.textnum);
+ }
+ Keystate[scancode]=0;
+ break;
+
+ case sc_Enter:
+ MSG.messageon = false;
+ FinishModemMessage(MSG.textnum, true);
+ KeyboardQueue[head] = 0;
+ Keyboard[sc_Enter] = 0;
+ Keyboard[sc_Escape] = 0;
+ LastScan = 0;
+ Keystate[scancode]=0;
+ break;
+
+ case sc_Escape:
+ MSG.messageon = false;
+ MSG.directed = false;
+ FinishModemMessage(MSG.textnum, false);
+ KeyboardQueue[head] = 0;
+ Keyboard[sc_Enter] = 0;
+ Keyboard[sc_Escape] = 0;
+ LastScan = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ head = (head+1)&(KEYQMAX-1);
+ } // while
+}
--- /dev/null
+++ b/rott/rt_in.h
@@ -1,0 +1,212 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// Public header for RT_IN.C.
+//
+//***************************************************************************
+
+#ifndef _rt_in_public
+#define _rt_in_public
+
+#include "develop.h"
+#include "rottnet.h"
+
+//***************************************************************************
+//
+// DEFINES
+//
+//***************************************************************************
+
+#define MAXLETTERS 32
+
+
+//***************************************************************************
+//
+// TYPEDEFS
+//
+//***************************************************************************
+
+typedef enum
+{
+ motion_Left = -1,
+ motion_Up = -1,
+ motion_None = 0,
+ motion_Right = 1,
+ motion_Down = 1
+} Motion;
+
+
+typedef enum
+{
+ dir_North,
+ dir_NorthEast,
+ dir_East,
+ dir_SouthEast,
+ dir_South,
+ dir_SouthWest,
+ dir_West,
+ dir_NorthWest,
+ dir_None
+} Direction;
+
+typedef byte ScanCode;
+
+typedef enum
+{
+ ctrl_Keyboard,
+ ctrl_Keyboard1 = ctrl_Keyboard, ctrl_Keyboard2,
+ ctrl_Joystick,
+ ctrl_Joystick1 = ctrl_Joystick, ctrl_Joystick2,
+ ctrl_Mouse
+} ControlType;
+
+typedef struct
+{
+ boolean button0,
+ button1,
+ button2,
+ button3;
+ int x,
+ y;
+ Motion xaxis,
+ yaxis;
+ Direction dir;
+} CursorInfo;
+
+
+typedef CursorInfo ControlInfo;
+
+
+typedef struct
+{
+ ScanCode button0,
+ button1,
+ upleft,
+ up,
+ upright,
+ left,
+ right,
+ downleft,
+ down,
+ downright;
+} KeyboardDef;
+
+
+typedef struct
+{
+ word joyMinX,joyMinY,
+ threshMinX,threshMinY,
+ threshMaxX,threshMaxY,
+ joyMaxX,joyMaxY,
+ joyMultXL,joyMultYL,
+ joyMultXH,joyMultYH;
+} JoystickDef;
+
+
+typedef struct
+{
+ boolean messageon;
+ boolean directed;
+ boolean inmenu;
+ int remoteridicule;
+ int towho;
+ int textnum;
+ int length;
+} ModemMessage;
+
+
+//***************************************************************************
+//
+// GLOBALS
+//
+//***************************************************************************
+
+extern boolean MousePresent;
+extern boolean JoysPresent[MaxJoys];
+extern boolean JoyPadPresent;
+extern int mouseadjustment;
+extern int threshold;
+
+extern boolean Paused;
+extern volatile int LastScan;
+/* extern KeyboardDef KbdDefs;
+extern JoystickDef JoyDefs[];
+extern ControlType Controls[MAXPLAYERS]; */
+
+extern boolean SpaceBallPresent;
+extern boolean CybermanPresent;
+extern boolean AssassinPresent;
+extern char LastASCII;
+extern volatile int LastScan;
+
+extern byte Joy_xb,
+ Joy_yb,
+ Joy_xs,
+ Joy_ys;
+extern word Joy_x,
+ Joy_y;
+
+extern int LastLetter;
+extern char LetterQueue[MAXLETTERS];
+extern ModemMessage MSG;
+
+extern const char ScanChars[128];
+
+//***************************************************************************
+//
+// PROTOTYPES
+//
+//***************************************************************************
+
+void INL_GetMouseDelta(int *x,int *y);
+word IN_GetMouseButtons (void);
+void IN_IgnoreMouseButtons( void );
+boolean INL_StartMouse (void);
+void INL_ShutMouse (void);
+void IN_Startup(void);
+void IN_Default (boolean gotit, ControlType in);
+void IN_Shutdown (void);
+void IN_SetKeyHook(void (*hook)());
+void IN_ClearKeysDown (void);
+void IN_ReadControl (int player, ControlInfo *info);
+void IN_SetControlType (int player, ControlType type);
+ScanCode IN_WaitForKey (void);
+char IN_WaitForASCII (void);
+void IN_StartAck (void);
+boolean IN_CheckAck (void);
+void IN_Ack (void);
+boolean IN_UserInput (long delay);
+void IN_GetJoyAbs (word joy, word *xp, word *yp);
+void INL_GetJoyDelta (word joy, int *dx, int *dy);
+word INL_GetJoyButtons (word joy);
+//word IN_GetJoyButtonsDB (word joy);
+void INL_SetJoyScale (word joy);
+void IN_SetupJoy (word joy, word minx, word maxx, word miny, word maxy);
+boolean INL_StartJoy (word joy);
+void INL_ShutJoy (word joy);
+byte IN_JoyButtons (void);
+void IN_UpdateKeyboard (void);
+void IN_ClearKeyboardQueue (void);
+int IN_InputUpdateKeyboard (void);
+void IN_PumpEvents (void);
+void QueueLetterInput (void);
+
+#endif
--- /dev/null
+++ b/rott/rt_main.c
@@ -1,0 +1,3549 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "rt_def.h"
+#include "lumpy.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <fcntl.h>
+#include <string.h>
+
+#ifdef DOS
+#include <malloc.h>
+#include <dos.h>
+#include <io.h>
+#include <conio.h>
+#include <graph.h>
+#include <process.h>
+#include <direct.h>
+#include <bios.h>
+#else
+#include <signal.h>
+#endif
+
+#if USE_SDL
+/* Need to redefine main to SDL_main on some platforms... */
+#include "SDL.h"
+#endif
+
+#include "rt_actor.h"
+#include "rt_stat.h"
+#include "rt_vid.h"
+#include "rt_menu.h"
+#include "rt_sound.h"
+#include "watcom.h"
+#include "scriplib.h"
+#include "rt_main.h"
+#include "_rt_main.h"
+#include "rt_com.h"
+#include "rt_util.h"
+#include "z_zone.h"
+#include "w_wad.h"
+#include "rt_game.h"
+#include "rt_floor.h"
+#include "rt_playr.h"
+#include "rt_draw.h"
+#include "rt_str.h"
+#include "rt_view.h"
+#include "rt_door.h"
+#include "rt_ted.h"
+#include "rt_in.h"
+#include "rt_map.h"
+#include "rt_rand.h"
+#include "rt_debug.h"
+#include "isr.h"
+#include "rt_cfg.h"
+#include "develop.h"
+#include "version.h"
+#include "rt_menu.h"
+#include "rt_dr_a.h"
+#include "rt_msg.h"
+#include "rt_build.h"
+#include "rt_error.h"
+#include "modexlib.h"
+#include "rt_net.h"
+#include "cin_main.h"
+#include "rottnet.h"
+#include "rt_scale.h"
+
+#include "music.h"
+#include "fx_man.h"
+//MED
+#include "memcheck.h"
+
+volatile int oldtime;
+volatile int gametime;
+
+boolean tedlevel;
+int tedlevelnum;
+int tedx=0;
+int tedy=0;
+boolean warp;
+int warpx=0;
+int warpy=0;
+int warpa=0;
+int NoSound;
+int polltime;
+int oldpolltime;
+boolean fizzlein = false;
+int pheight;
+
+boolean SCREENSHOTS = false;
+boolean MONOPRESENT = false;
+boolean MAPSTATS = false;
+boolean TILESTATS = false;
+boolean HUD = false;
+boolean IS8250 = false;
+
+boolean dopefish;
+
+boolean newlevel = false;
+boolean infopause;
+#ifdef DOS
+boolean SOUNDSETUP=false;
+#endif
+boolean quiet = false;
+
+#if (DEVELOPMENT == 1)
+boolean DebugOk = true;
+#else
+boolean DebugOk = false;
+#endif
+
+#if (WHEREAMI==1)
+int programlocation=-1;
+#endif
+
+#if SAVE_SCREEN
+static char savename[13] = "ROTT0000.LBM";
+static int totalbytes;
+static byte *bptr;
+#endif
+static boolean turbo;
+
+static int NoWait;
+static int startlevel=0;
+static int demonumber=-1;
+
+char CWD[40]; // curent working directory
+static boolean quitactive = false;
+
+int timelimit;
+int maxtimelimit;
+boolean timelimitenabled;
+boolean demoexit;
+boolean noecho;
+
+void CheckCommandLineParameters( void );
+void PlayTurboGame( void );
+void Init_Tables (void);
+void CheckRemoteRidicule ( int scancode );
+void SetRottScreenRes (int Width, int Height);
+
+#ifndef DOS
+extern void crash_print (int);
+extern int setup_homedir (void);
+#endif
+
+//extern int G_argc;
+//extern char G_argv[30][80];
+int G_weaponscale;
+extern int iDropDemo;
+extern boolean iG_aimCross;
+extern boolean sdl_fullscreen;
+
+extern void ComSetTime ( void );
+extern void VH_UpdateScreen (void);
+extern void RottConsole ( void );
+extern void ReadDelay(long delay);
+extern void RecordDemoQuery ( void );
+
+
+int main (int argc, char *argv[])
+{
+ char *macwd;
+ extern char *BATTMAPS;
+#ifndef DOS
+ _argc = argc;
+ _argv = argv;
+#endif
+
+#if defined(PLATFORM_MACOSX)
+ {
+ /* OS X will give us a path in the form '/Applications/Rise of the Triad.app/Contents/MacOS/Rise of the Triad'.
+ Our data is in Contents/Resources. */
+ char *path;
+ const char suffix[] = "/Resources/";
+ int end;
+ path = (char *)malloc(strlen(argv[0]) + strlen(suffix) + 1);
+ if (path == NULL) return 1;
+ strcpy(path, argv[0]);
+ /* Back up two '/'s. */
+ for (end = strlen(path)-1; end >= 0 && path[end] != '/'; end--);
+ if (end >= 0) for (--end; end >= 0 && path[end] != '/'; end--);
+ strcpy(&path[end], suffix);
+ printf("Changing to working directory: %s\n", path);
+ chdir(path);
+ free(path);
+ }
+#endif
+
+#ifndef DOS
+ signal (11, crash_print);
+
+ if (setup_homedir() == -1) return 1;
+#endif
+
+ // Set which release version we're on
+ gamestate.Version = ROTTVERSION;
+
+#if ( SHAREWARE == 1 )
+ BATTMAPS = strdup(STANDARDBATTLELEVELS);
+ FixFilePath(BATTMAPS);
+ gamestate.Product = ROTT_SHAREWARE;
+#else
+ BATTMAPS = strdup(SITELICENSEBATTLELEVELS);
+ FixFilePath(BATTMAPS);
+ if (!access(BATTMAPS, R_OK))
+ {
+ gamestate.Product = ROTT_SITELICENSE;
+ }
+ else
+ {
+ free(BATTMAPS);
+ BATTMAPS = strdup(SUPERROTTBATTLELEVELS);
+ FixFilePath(BATTMAPS);
+ if (!access(BATTMAPS, R_OK))
+ {
+ gamestate.Product = ROTT_SUPERCD;
+ }
+ else
+ {
+ free(BATTMAPS);
+ BATTMAPS = strdup(STANDARDBATTLELEVELS);
+ FixFilePath(BATTMAPS);
+ gamestate.Product = ROTT_REGISTERED;
+ }
+ }
+#endif
+
+ DrawRottTitle ();
+ gamestate.randomseed=-1;
+
+ gamestate.autorun = 0;
+ StartupSoftError();
+// UL_ErrorStartup ();
+
+ CheckCommandLineParameters();
+
+ // Start up Memory manager with a certain amount of reserved memory
+
+ Z_Init(50000,1000000);
+
+ IN_Startup ();
+
+ InitializeGameCommands();
+ if (standalone==false)
+ {
+ ReadConfig ();
+ ReadSETUPFiles ();
+ doublestep=0;
+ SetupWads();
+ BuildTables ();
+ GetMenuInfo ();
+ }
+
+ SetRottScreenRes (iGLOBAL_SCREENWIDTH, iGLOBAL_SCREENHEIGHT);
+
+// if (modemgame==true)
+// {
+// SCREENSHOTS=true;
+// if (standalone==false)
+// {
+// MenuFixup ();
+// }
+// MAPSTATS=true;
+// }
+ if (standalone==false)
+ {
+ int status1 = 0;
+ int status2 = 0;
+ int status3 = 0;
+
+ if ( !NoSound && !IS8250 )
+ {
+ if (!quiet)
+ printf( "MU_Startup: " );
+ status1 = MU_Startup(false);
+ if (!quiet)
+ printf( "%s\n", MUSIC_ErrorString( MUSIC_Error ) );
+ }
+ else if ( IS8250 )
+ {
+ printf( "==============================================================================\n");
+ printf( "WARNING: 8250 detected.\n" );
+ printf( "Music has been disabled. This is necessary to maintain high interrupt\n" );
+ printf( "rates with the 8250 UART which will improve overall game performance.\n");
+ printf( " < Press any key to continue >\n");
+ printf( "==============================================================================\n");
+ getch();
+ }
+
+ if (!NoSound)
+ {
+ int nv, nb, nc;
+
+ if (!quiet)
+ printf( "SD_SetupFXCard: " );
+ status2 = SD_SetupFXCard (&nv, &nb, &nc);
+ if (!quiet)
+ printf( "%s\n", FX_ErrorString( FX_Error ) );
+
+ if ( !status2 )
+ {
+ if (!quiet)
+ printf( "SD_Startup: " );
+ status3 = SD_Startup(false);
+ if (!quiet)
+ printf( "%s\n", FX_ErrorString( FX_Error ) );
+ }
+ }
+ else
+ {
+ if (!quiet)
+ printf( "Sound FX disabled.\n" );
+ }
+
+#ifdef DOS
+ if ( status1 || status2 || status3 )
+ {
+ printf( "\n\nROTT was unable to initialize your " );
+ if ( status1 )
+ {
+ printf( "music " );
+ MusicMode = 0;
+ }
+ if ( status2 || status3 )
+ {
+ if ( status1 )
+ {
+ printf( "or " );
+ }
+ printf( "sound fx " );
+
+ FXMode = 0;
+ }
+
+ printf( "hardware.\n"
+ "Now entering sound setup.\n" );
+ SOUNDSETUP = true;
+ }
+#endif
+
+ Init_Tables ();
+ InitializeRNG ();
+ InitializeMessages();
+ LoadColorMap();
+ }
+ if (infopause==true)
+ {
+ printf("\n< Press any key to continue >\n");
+ getch();
+ }
+ I_StartupTimer();
+ I_StartupKeyboard();
+#if 0
+#if (SHAREWARE == 1)
+ if ((!SOUNDSETUP) && (standalone==false))
+ {
+ byte * txtscn;
+ int i;
+
+ for (i=0; i<20; i++)
+ printf("\n");
+ txtscn = (byte *) W_CacheLumpNum (W_GetNumForName ("rotts10"), PU_CACHE);
+ memcpy ((byte *)0xB8000, txtscn, 4000);
+ I_Delay (600);
+ }
+#endif
+#endif
+ locplayerstate = &PLAYERSTATE[consoleplayer];
+
+ if (standalone==true)
+ ServerLoop();
+
+ VL_SetVGAPlaneMode();
+ VL_SetPalette(origpal);
+
+// SetTextMode();
+// GraphicsMode();
+// SetTextMode();
+// VL_SetVGAPlaneMode();
+// VL_SetPalette(origpal);
+// SetBorderColor(155);
+ SetViewSize(8);
+
+#ifdef DOS
+ if ( SOUNDSETUP )
+ {
+ SwitchPalette( origpal, 35 );
+ CP_SoundSetup();
+ }
+#endif
+
+ playstate = ex_titles;
+
+// I_SetKeyboardLEDs( caps_lock, 0 );
+
+ gamestate.battlemode = battle_StandAloneGame;
+
+ BATTLE_SetOptions( &BATTLE_Options[ battle_StandAloneGame ] );
+
+ if (turbo || tedlevel)
+ {
+ if (modemgame == true)
+ {
+ turbo = false;
+ NoWait = true;
+ }
+ else
+ {
+ PlayTurboGame();
+ }
+ }
+ else
+ {
+#if (SHAREWARE == 0)
+ if ( dopefish == true )
+ {
+ DopefishTitle();
+ }
+ else if ( NoWait == false )
+ {
+ ApogeeTitle();
+ }
+#else
+ if ( NoWait == false )
+ {
+ if (W_CheckNumForName("svendor") != -1)
+ {
+ lbm_t * LBM;
+
+ LBM = (lbm_t *) W_CacheLumpName( "svendor", PU_CACHE, Cvt_lbm_t, 1);
+ VL_DecompressLBM (LBM,true);
+ I_Delay(40);
+ MenuFadeOut();
+ }
+// ParticleIntro ();
+ ApogeeTitle();
+ }
+#endif
+ }
+
+ GameLoop();
+
+
+ QuitGame();
+
+ return 0;
+}
+
+void DrawRottTitle ( void )
+{
+ char title[80];
+ char buf[5];
+
+ SetTextMode();
+ TurnOffTextCursor ();
+
+ if (CheckParm("QUIET") == 0)
+ {
+ SetTextMode();
+ TurnOffTextCursor ();
+#ifdef DOS
+ if (CheckParm ("SOUNDSETUP") == 0)
+ {
+#endif
+#ifdef ANSIESC
+ printf("\n\n\n");
+#endif
+ strcpy (title,"Rise of the Triad Startup Version ");
+ strcat (title,itoa(ROTTMAJORVERSION,&buf[0],10));
+ strcat (title,".");
+//MED
+#if (SHAREWARE==1)||(DOPEFISH==0)
+ strcat (title,itoa(ROTTMINORVERSION,&buf[0],10));
+#else
+ strcat (title,"DFISH");
+#endif
+#ifndef ANSIESC
+ strcat (title,"\n");
+#endif
+
+ px=(80-strlen(title))>>1;
+ py=0;
+
+ UL_printf(title);
+
+ memset (title,0,sizeof(title));
+
+ if (gamestate.Product == ROTT_SHAREWARE)
+ {
+#if (DELUXE==1)
+ strcpy(title,"Lasersoft Deluxe Version");
+#elif (LOWCOST==1)
+ strcpy(title,"Episode One");
+#else
+ strcpy(title,"Shareware Version");
+#endif
+ }
+ else if (gamestate.Product == ROTT_SUPERCD)
+ strcpy(title,"CD Version");
+ else if (gamestate.Product == ROTT_SITELICENSE)
+ strcpy(title,"Site License CD Version");
+ else
+ strcpy(title,"Commercial Version");
+
+ px=(80-strlen(title))>>1;
+ py=1;
+
+ UL_printf(title);
+#ifndef ANSIESC
+ printf ("\n");
+#endif
+
+ UL_ColorBox (0, 0, 80, 2, 0x1e);
+#ifdef DOS
+ }
+ else
+ {
+ printf("\n\n");
+ strcpy (title,"Rise of the Triad Sound Setup Version ");
+ strcat (title,itoa(ROTTMAJORVERSION,&buf[0],10));
+ strcat (title,".");
+ strcat (title,itoa(ROTTMINORVERSION,&buf[0],10));
+
+ px=(80-strlen(title))>>1;
+ py=0;
+
+ UL_printf(title);
+
+ UL_ColorBox (0, 0, 80, 1, 0x1e);
+ }
+#endif
+ }
+ else
+ {
+ TurnOffTextCursor ();
+ }
+
+}
+
+void CheckCommandLineParameters( void )
+{
+ char *PStrings[] = {"TEDLEVEL","NOWAIT","NOSOUND","NOW",
+ "TRANSPORT","DOPEFISH","SCREENSHOTS",
+ "MONO","MAPSTATS","TILESTATS","VER","net",
+ "PAUSE","SOUNDSETUP","WARP","IS8250","ENABLEVR",
+ "TIMELIMIT","MAXTIMELIMIT","NOECHO","DEMOEXIT","QUIET",NULL
+ };
+ int i,n;
+
+ infopause=false;
+#ifdef DOS
+ SOUNDSETUP = false;
+#endif
+ tedlevel=false;
+ NoWait=false;
+ NoSound=false;
+ turbo=false;
+ warp=false;
+ dopefish=false;
+ modemgame=false;
+ SCREENSHOTS=false;
+ MONOPRESENT=false;
+ MAPSTATS=false;
+ TILESTATS=false;
+ IS8250 = false;
+ vrenabled = false;
+ demoexit = false;
+
+ modemgame=false;
+ networkgame=false;
+ consoleplayer=0;
+ numplayers = 1;
+ timelimit=-1;
+ timelimitenabled=false;
+ noecho = false;
+ quiet = false;
+
+ if (
+ (CheckParm("?\0")) ||
+ (CheckParm("HELP")) ||
+ (
+ (_argc>1) &&
+ (_argv[1][0]=='?')
+ )
+ )
+ {
+ SetTextMode ();
+ printf ("Rise of the Triad (c) 1995 Apogee Software\n\n");
+ printf ("COMMAND LINE PARAMETERS\n");
+ printf (" AIM - Give Aim Crosshair.\n");
+ printf (" FULLSCREEN - Start in fullscreen mode\n");
+ printf (" WINDOW - Start in windowed mode\n");
+ printf (" RESOLUTION - Specify the screen resolution to use\n");
+ printf (" - next param is <widthxheight>, valid resolutions are:\n");
+ printf (" - 320x200, 640x480 and 800x600\n");
+#if (SHAREWARE==0)
+ printf (" FILERTL - used to load Userlevels (RTL files)\n");
+ printf (" - next parameter is RTL filename\n");
+ printf (" FILERTC - used to load Battlelevels (RTC files)\n");
+ printf (" - next parameter is RTC filename\n");
+ printf (" FILE - used to load Extern WAD files\n");
+ printf (" - next parameter is WAD filename\n");
+#endif
+ printf (" SPACEBALL - Enable check for Spaceball.\n");
+ printf (" NOJOYS - Disable check for joystick.\n");
+ printf (" NOMOUSE - Disable check for mouse.\n");
+ printf (" CYBERMAN - Enable check for Cyberman.\n");
+ printf (" ASSASSIN - Enable check for Wingman Assassin.\n");
+ printf (" VER - Version number.\n");
+ printf (" MAPSTATS - Dump Map statistics to ERROR.\n");
+ printf (" TILESTATS - Dump Tile statistics to ERROR.\n");
+ printf (" MONO - Enable mono-monitor support.\n");
+ printf (" SCREENSHOTS- Clean screen capture for shots.\n");
+ printf (" PAUSE - Pauses startup screen information.\n");
+#ifdef DOS
+ printf (" SOUNDSETUP - Setup sound for ROTT\n");
+#endif
+ printf (" ENABLEVR - Enable VR helmet input devices\n");
+ printf (" NOECHO - Turn off sound reverb\n");
+ printf (" DEMOEXIT - Exit program when demo is terminated\n");
+ printf (" WARP - Warp to specific ROTT level\n");
+ printf (" next parameter is level to start on\n");
+ printf (" TIMELIMIT - Play ROTT in time limit mode\n");
+ printf (" next parameter is time in seconds\n");
+ printf (" MAXTIMELIMIT - Maximimum time to count down from\n");
+ printf (" next parameter is time in seconds\n");
+ printf (" DOPEFISH - ?\n");
+ printf (" \n");
+ printf ("CONTROLS\n");
+ printf (" Arrows - Move\n");
+ printf (" Ctrl - Fire\n");
+ printf (" Comma/Alt+left - Sidestep Left\n");
+ printf (" Period/Alt+right - Sidestep Right\n");
+ printf (" Shift - Run/Turn faster\n");
+ printf (" Space - Use/Open\n");
+ printf (" 1-4 - Choose Weapon\n");
+ printf (" 5-6 - Scale Weapon Up/Down\n");
+ printf (" Enter - Swap Weapon\n");
+ printf (" Backspace - Turn 180\n");
+ printf (" Delete - Drop Weapon\n");
+ printf (" +/- - Change Viewsize\n");
+ printf (" PgUp/PgDn - Look Up/Down\n");
+ printf (" Home/End - Aim Up/Down\n");
+ printf (" [ ] - Sound Volumen\n");
+ printf (" ( ) - Music Volumen\n");
+ printf (" Tab - Enter Automapper\n");
+ printf (" \n");
+ printf ("AUTO-MAPPER\n");
+ printf (" Arrows - Scroll around\n");
+ printf (" PgUp - Zoom Out\n");
+ printf (" PgDn - Zoom In\n");
+ printf (" Tab - Exit Auto-Mapper\n");
+ printf (" \n");
+ printf ("HOTKEYS\n");
+ printf (" F1 - Help\n");
+ printf (" F2 - Save Game\n");
+ printf (" F3 - Restore Game\n");
+ printf (" F4 - Controls/Sound/Music\n");
+ printf (" F5 - Change Detail Level\n");
+ printf (" F6 - Quick Save\n");
+ printf (" F7 - Messages On/Off\n");
+ printf (" F8 - End Game\n");
+ printf (" F9 - Quick Load\n");
+ printf (" F10 - Quit\n");
+ printf (" F11 - Gamma Correction\n");
+ printf (" \n");
+ printf ("COMM-BAT\n");
+ printf (" F1 - F10 - RemoteRidicule(tm) sounds\n");
+ printf (" F12 - Live RemoteRidicule\n");
+ printf (" T - Type message to all\n");
+ printf (" Z - Type directed message\n");
+ printf (" Tab - Toggle KillCount display\n");
+ printf (" \n");
+ printf ("SCREENSHOOT\n");
+#ifdef DOS /* makes no sense under Linux as there are no lbm viewers there */
+ printf (" Alt+V - Screenshoot in LBM format\n");
+#endif
+ printf (" Alt+C - Screenshoot in PCX format\n");
+ exit (0);
+ }
+
+ // Check For command line parameters
+
+ for (i = 1; i < _argc; i++)
+ {
+ n = US_CheckParm(_argv[i],PStrings);
+ switch(n)
+ {
+#if (TEDLAUNCH==1)
+ case 0:
+ tedlevelnum = ParseNum(_argv[i + 1]);
+ tedlevel=true;
+ if (i+3>=_argc)
+ {
+ tedx=0;
+ tedy=0;
+ }
+ else
+ {
+ tedx=ParseNum(_argv[i + 2]);
+ tedy=ParseNum(_argv[i + 3]);
+ }
+ MenuFixup ();
+ break;
+#endif
+ case 1:
+ NoWait = true;
+ break;
+ case 2:
+ NoSound = true;
+ break;
+ case 3:
+ turbo = true;
+ break;
+ case 4:
+ warp = true;
+ warpx=ParseNum(_argv[i + 1]);
+ warpy=ParseNum(_argv[i + 2]);
+ warpa=ParseNum(_argv[i + 3]);
+ break;
+ case 5:
+ dopefish=true;
+ break;
+ case 6:
+ SCREENSHOTS = true;
+ break;
+ case 7:
+ MONOPRESENT = true;
+ break;
+ case 8:
+ MAPSTATS = true;
+ break;
+ case 9:
+ TILESTATS = true;
+ break;
+ case 10:
+ SetTextMode ();
+ printf ("Rise of the Triad (c) 1995 Apogee Software\n");
+//MED
+ if (gamestate.Product == ROTT_SHAREWARE)
+ {
+#if (DELUXE==1)
+ printf("Lasersoft Deluxe ");
+#elif (LOWCOST==1)
+ printf("Episode One ");
+#else
+ printf("Shareware ");
+#endif
+ }
+ else if (gamestate.Product == ROTT_SUPERCD)
+ printf("CD ");
+ else if (gamestate.Product == ROTT_SITELICENSE)
+ printf("Site License ");
+ else
+ printf("Commercial ");
+ printf ("Version %d.%d\n", ROTTMAJORVERSION,ROTTMINORVERSION);
+ exit (0);
+ break;
+ case 11:
+ InitROTTNET();
+ numplayers = rottcom->numplayers;
+ if (numplayers>MAXPLAYERS)
+ Error("Too many players.\n");
+ if (!quiet)
+ printf("Playing %ld player ROTT\n",(long int)numplayers);
+ modemgame=true;
+ if (rottcom->gametype==NETWORK_GAME)
+ {
+ if (!quiet)
+ printf("NETWORK GAME\n");
+ networkgame=true;
+ }
+ else
+ {
+ if (!quiet)
+ printf("MODEM GAME\n");
+ }
+ break;
+ case 12:
+ infopause=true;
+ break;
+ case 13:
+#ifdef DOS
+ SOUNDSETUP = true;
+#endif
+ break;
+ case 14:
+ startlevel = (ParseNum(_argv[i + 1])-1);
+ break;
+ case 15:
+ IS8250 = true;
+ break;
+ case 16:
+ vrenabled = true;
+ if (!quiet)
+ printf("Virtual Reality Mode enabled\n");
+ break;
+ case 17:
+ timelimitenabled = true;
+ timelimit = ParseNum(_argv[i + 1]);
+ if (!quiet)
+ printf("Time Limit = %ld Seconds\n",(long int)timelimit);
+ timelimit *= VBLCOUNTER;
+ break;
+
+ case 18:
+ maxtimelimit = ParseNum(_argv[i + 1]);
+ maxtimelimit *= VBLCOUNTER;
+ break;
+ case 19:
+ noecho = true;
+ break;
+ case 20:
+ demoexit = true;
+ break;
+ case 21:
+ quiet = true;
+ break;
+ }
+ }
+}
+
+void SetupWads( void )
+{
+ char *newargs[99];
+ int i, arg, argnum = 0;
+ char *tempstr = NULL;
+ char *PStrings[] = {"AIM", "FULLSCREEN", "WINDOW", "RESOLUTION", NULL };
+
+ // These must be checked here so that they can override the cfg file
+ for (i = 1; i < _argc; i++)
+ {
+ arg = US_CheckParm(_argv[i],PStrings);
+ switch(arg)
+ {
+ case 0:
+ iG_aimCross = 1;
+ break;
+ case 1:
+ sdl_fullscreen = 1;
+ break;
+ case 2:
+ sdl_fullscreen = 0;
+ break;
+ case 3:
+ i++;
+ if (i < _argc)
+ {
+ int width, height;
+ if ( (sscanf(_argv[i], "%dx%d", &width, &height) == 2) &&
+ ( ( (width == 320) && (height == 200) ) ||
+ ( (width == 640) && (height == 480) ) ||
+ ( (width == 800) && (height == 600) ) ) )
+ {
+ iGLOBAL_SCREENWIDTH = width;
+ iGLOBAL_SCREENHEIGHT = height;
+ }
+ else
+ printf("Invalid resolution parameter: %s\n", _argv[i]);
+ }
+ else
+ printf("Missing resolution parameter\n");
+ break;
+ }
+ }
+
+
+#if (SHAREWARE==0)
+ // Check for rtl files
+ arg = CheckParm ("filertl");
+ if (arg!=0)
+ {
+ FILE *f;
+ char *buf = malloc(32);
+ if (_argv[arg+1] != 0) { //are there a filename included
+ tempstr = realloc(tempstr, 129 + strlen(_argv[arg+1]));
+ strcpy (tempstr,_argv[arg+1]);//copy it to tempstr
+ if (strlen (tempstr) < MAX_PATH) {
+ if (access (tempstr, 0) != 0) { //try open
+ strcat (tempstr,".rtc");//non exists, try add .rtc
+ if (access (tempstr, 0) != 0) { //try open again
+ //stil no useful filename
+ strcat (tempstr," not found, skipping RTL file ");
+ printf("%s", tempstr);
+ goto NoRTL;
+ }
+ }
+ if((f = fopen( tempstr, "r" )) == NULL ) { //try opnong file
+ strcat (tempstr," not could not be opened, skipping RTL file ");
+ printf("%s", tempstr);
+ goto NoRTL;
+ } else {
+ fread(buf,3,3,f);//is the 3 first letters RTL (RTC)
+ if (((strstr(buf,"RTL") != 0)||strstr(buf,"RTC") != 0)) {
+ GameLevels.file = strdup(tempstr);
+ GameLevels.avail++;
+ buf = realloc(buf, 32 + strlen(tempstr));
+ strcpy (buf,"Adding ");
+ strcat (buf,tempstr);
+ printf("%s", buf);
+ }
+ fclose(f);
+ }
+ }
+ } else {
+ printf("Missing RTL filename");
+ }
+ free(buf);
+ }
+NoRTL:
+ ;
+ // Check for rtc files
+ arg = CheckParm ("filertc");
+ if (arg!=0)
+ {
+ FILE *f;
+ char *buf = malloc(32);
+ if (_argv[arg+1] != 0) { //are there a filename included
+ tempstr = realloc(tempstr, 129 + strlen(_argv[arg+1]));
+ strcpy (tempstr,_argv[arg+1]);//copy it to tempstr
+ if (strlen (tempstr) < MAX_PATH) {
+ if (access (tempstr, 0) != 0) { //try open
+ strcat (tempstr,".rtc");//non exists, try add .rtc
+ if (access (tempstr, 0) != 0) { //try open again
+ //stil no useful filename
+ strcat (tempstr," not found, skipping RTC file ");
+ printf("%s", tempstr);
+ goto NoRTL;
+ }
+ }
+ if((f = fopen( tempstr, "r" )) == NULL ) { //try opening file
+ strcat (tempstr," not could not be opened, skipping RTC file ");
+ printf("%s", tempstr);
+ goto NoRTL;
+ } else {
+ fread(buf,3,3,f);//is the 3 first letters RTL (RTC)
+ if (((strstr(buf,"RTL") != 0)||strstr(buf,"RTC") != 0)) {
+ BattleLevels.file = strdup(tempstr);
+ BattleLevels.avail++;
+ buf = realloc(buf, 32 + strlen(tempstr));
+ strcpy (buf,"Adding ");
+ strcat (buf,tempstr);
+ printf("%s", buf);
+ }
+ fclose(f);
+ }
+ }
+ } else {
+ printf("Missing RTC filename");
+ }
+ free(buf);
+ }
+NoRTC:
+ ;
+
+ // Check for User wads
+ arg = CheckParm ("file");
+ if (arg!=0)
+ {
+ newargs [argnum++] = _argv[arg+1];
+ }
+
+ arg = CheckParm ("file1");
+ if (arg!=0)
+ {
+ newargs [argnum++] = _argv[arg+1];
+ }
+
+ arg = CheckParm ("file2");
+ if (arg!=0)
+ {
+ newargs [argnum++] = _argv[arg+1];
+ }
+
+#else
+ if (
+ (CheckParm ("file") > 0) ||
+ (CheckParm ("file1") > 0) ||
+ (CheckParm ("file2") > 0)
+ )
+ printf("External wads ignored.\n");
+
+#endif
+
+ // Normal ROTT wads
+
+#if (SHAREWARE)
+ newargs [argnum++] = DATADIR "HUNTBGIN.WAD";
+#else
+ newargs [argnum++] = DATADIR "DARKWAR.WAD";
+#endif
+
+// newargs [argnum++] = "credits.wad";
+
+ // Check for Remote Ridicule WAD
+
+ if (RemoteSounds.avail == true)
+ {
+ char *src;
+
+ tempstr = realloc(tempstr, strlen(RemoteSounds.path) + strlen(RemoteSounds.file) + 2);
+ strcpy (tempstr,RemoteSounds.path);
+ src = RemoteSounds.path + strlen(RemoteSounds.path) - 1;
+ if (*src != '\\')
+ strcat (tempstr,"\\\0");
+ strcat (tempstr,RemoteSounds.file);
+ newargs [argnum++] = strdup(tempstr);
+ }
+ else
+ {
+ newargs [argnum++] = DATADIR "REMOTE1.RTS";
+ }
+
+ if (tempstr)
+ free(tempstr);
+
+ newargs [argnum++] = NULL;
+
+ W_InitMultipleFiles(newargs);
+}
+
+void PlayTurboGame
+(
+ void
+)
+
+{
+ NewGame = true;
+ locplayerstate->player = DefaultPlayerCharacter;
+ playstate = ex_resetgame;
+ GameLoop();
+}
+
+
+//***************************************************************************
+//
+// Init_Tables () - Init tables needed for double buffering
+//
+//***************************************************************************
+
+void Init_Tables (void)
+{
+ int i;
+ int x,
+ y;
+ unsigned *blockstart;
+ byte * shape;
+
+ memset (&CWD[0], 0, 40);
+ getcwd (CWD, 40); // get the current directory
+
+ origpal=SafeMalloc(768);
+ memcpy (origpal, W_CacheLumpName("pal",PU_CACHE, CvtNull, 1), 768);
+
+ FindEGAColors();
+
+ for (i=0; i<PORTTILESHIGH; i++)
+ uwidthtable[i] = UPDATEWIDE*i;
+
+ updateptr = &update[0];
+
+ blockstart = &blockstarts[0];
+ for (y=0; y<UPDATEHIGH; y++)
+ for (x=0; x<UPDATEWIDE; x++)
+ *blockstart++ = iG_SCREENWIDTH*16*y+x*TILEWIDTH;
+
+ for (i = 0; i < 0x300; i++)
+ *(origpal+(unsigned int)i) = (*(origpal+(unsigned int)i))>>2;
+
+ // Cache in fonts
+ shape = W_CacheLumpNum (W_GetNumForName ("smallfont"), PU_STATIC, Cvt_font_t, 1);
+ smallfont = (font_t *)shape;
+ CurrentFont = smallfont;
+
+ // Cache in tiny font
+ shape = W_CacheLumpNum (W_GetNumForName ("tinyfont"), PU_STATIC, Cvt_font_t, 1);
+ tinyfont = (font_t *)shape;
+
+ intensitytable=W_CacheLumpNum(W_GetNumForName("menucmap"),PU_STATIC, CvtNull, 1);
+ fontcolor = egacolor[4];
+
+ if (!quiet)
+ printf("RT_MAIN: Fonts Initialized\n");
+}
+
+
+
+
+int NumberOfTeams
+(
+ void
+)
+
+{
+ int index;
+ int team[ MAXPLAYERCOLORS ];
+ int count;
+ int color;
+
+ memset( team, 0, sizeof( team ) );
+
+ count = 0;
+ for( index = 0; index < numplayers; index++ )
+ {
+ color = PLAYERSTATE[ index ].uniformcolor;
+ if ( !team[ color ] )
+ {
+ team[ color ] = true;
+ count++;
+ }
+ }
+
+ return( count );
+}
+
+extern boolean allowBlitzMoreMissileWeps;
+extern boolean enableZomROTT;
+
+void GameLoop (void)
+{
+ boolean done = false;
+ boolean loadit = false;
+ int NextLevel;
+
+ wami(1);
+
+ while (1)
+ {
+ if ( playstate == ex_battledone )
+ {
+ while( damagecount > 0 )
+ {
+ DoBorderShifts();
+ }
+ damagecount = 0;
+ SetBorderColor (0);
+
+ StopWind();
+
+ ShutdownClientControls();
+
+ SD_Play (SD_LEVELDONESND);
+
+ if ( ( player->flags & FL_DOGMODE ) ||
+ ( gamestate.battlemode == battle_Eluder ) )
+ MU_StartSong(song_dogend);
+ else
+ MU_StartSong(song_endlevel);
+
+
+ VL_FillPalette(255,255,255);
+ VL_FadeIn(0,255,origpal,10);
+
+ BattleLevelCompleted( consoleplayer );
+
+ BATTLE_Shutdown();
+
+ Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level
+
+ ingame = false;
+
+ if ( networkgame == true )
+ {
+ AddGameEndCommand ();
+ }
+
+ AdjustMenuStruct ();
+
+ CalcTics();
+ CalcTics();
+
+
+ playstate = ex_titles;
+ }
+
+ switch (playstate)
+ {
+ case ex_titles:
+
+ BATTLE_Shutdown();
+ MU_StartSong(song_title);
+ EnableScreenStretch();
+ if ((NoWait==false)&&(!modemgame))
+ {
+ byte dimpal[768];
+ int i;
+
+ for (i = 0; i < 0x300; i++)
+ dimpal[i] = origpal[i]>>2;
+ CalcTics();
+ CalcTics();
+ IN_ClearKeysDown ();
+ while (IN_GetMouseButtons()) {}
+ while ((!LastScan) && (!IN_GetMouseButtons()))
+ {
+ int i;
+ byte *tempbuf;
+ MenuFadeOut();
+ ClearGraphicsScreen();
+ SetPalette(&dimpal[0]);
+ PlayMovie ("shartitl", true);
+ if ( ( LastScan ) || ( IN_GetMouseButtons() ) )
+ {
+ break;
+ }
+
+ PlayMovie ("shartit2", true);
+
+ if ( ( LastScan ) || ( IN_GetMouseButtons() ) )
+ {
+ break;
+ }
+ SD_Play (SD_LIGHTNINGSND);
+ MenuFadeIn();
+ I_Delay(30);
+ SD_Play (SD_ACTORSQUISHSND);
+ tempbuf=bufferofs;
+ bufferofs=page1start; // fixed, was displayofs
+ DrawNormalSprite(320-94,200-41,W_GetNumForName("rsac"));
+ VW_UpdateScreen(); // fixed, was missing
+ bufferofs=tempbuf;
+ I_Delay(30);
+
+ if ( ( LastScan ) || ( IN_GetMouseButtons() ) )
+ {
+ break;
+ }
+
+ DoCreditScreen ();
+ if ((!LastScan) && (!IN_GetMouseButtons()))
+ CheckHighScore (0, 0, false);
+#if (SHAREWARE==0)
+ if ((!LastScan) && (!IN_GetMouseButtons()))
+ {
+ DoMicroStoryScreen ();
+ }
+#endif
+ if (
+ (!LastScan) &&
+ (!IN_GetMouseButtons()) &&
+ (lowmemory==0) &&
+ (GameLevels.avail==false)
+ )
+ {
+ if (demonumber==-1)
+ demonumber=RandomNumber("GameLoop",0);
+ for (i=0; i<4; i++)
+ {
+ demonumber=(demonumber+1)%4;
+ if (DemoExists (demonumber+1) == true)
+ break;
+ }
+ if (DemoExists (demonumber+1) == true)
+ {
+ ingame=true;
+ LoadDemo (demonumber+1);
+ break;
+ }
+ }
+ }
+ }
+
+ if (playstate != ex_demoplayback)
+ {
+ if (demoexit == true)
+ {
+ QuitGame();
+ }
+ NoWait = false;
+ SwitchPalette(origpal,35);
+ CP_MainMenu();
+
+ }
+ break;
+
+ case ex_resetgame:
+
+ // SetTextMode ( ); //12345678
+ EnableScreenStretch();//bna++ shut on streech mode
+ InitCharacter();
+
+ InitializeMessages();
+
+ fizzlein = true;
+ BATTLE_GetSpecials();
+ BATTLE_SetOptions( &BATTLE_Options[ gamestate.battlemode ] );
+
+ if ( modemgame == true )
+ {
+ fizzlein = false;
+
+ if ( consoleplayer == 0 )
+ {
+ // Setup Master
+ SetupGameMaster();
+ }
+ else
+ {
+ // Setup slave
+ SetupGamePlayer();
+ }
+
+ if ( gamestate.Version < ROTTVERSION )
+ {
+ Error( "This version of Rise of the Triad (%d.%d) is incompatible with\n"
+ "version %d.%d.", ROTTMAJORVERSION, ROTTMINORVERSION,
+ gamestate.Version / 10, gamestate.Version % 10 );
+ }
+ if ( gamestate.teamplay )
+ {
+ int teams;
+
+ teams = NumberOfTeams();
+ if ( gamestate.battlemode == battle_CaptureTheTriad )
+ {
+ if ( teams != 2 )
+ {
+ CP_CaptureTheTriadError();
+ playstate = ex_titles;
+ continue;
+ }
+ }
+ else if ( teams < 2 )
+ {
+ CP_TeamPlayErrorMessage();
+ playstate = ex_titles;
+ continue;
+ }
+ }
+ }
+
+ InitCharacter();
+
+ BATTLE_Init( gamestate.battlemode, numplayers );
+
+ NewGame = true;
+
+ if ( ( BATTLEMODE ) && ( BATTLE_ShowKillCount ) )
+ {
+ StatusBar |= STATUS_KILLS;
+ }
+ else
+ {
+ StatusBar &= ~STATUS_KILLS;
+ }
+
+ if (loadedgame == false)
+ {
+ if ( !BATTLEMODE )
+ {
+ PlayCinematic();
+ }
+
+ SetupGameLevel();
+ }
+
+ IN_ClearKeyboardQueue();
+
+ SetupScreen (true);
+
+ MenuFixup ();
+ playstate=ex_stillplaying;
+
+ DisableScreenStretch();//bna++ shut off streech mode
+
+ break;
+
+ case ex_stillplaying:
+ InitializeMessages();
+
+ SHAKETICS = 0xFFFF;
+ if (modemgame==true)
+ {
+ ComSetTime();
+ turbo = false;
+ }
+ else if (turbo==true)
+ turbo=false;
+ else
+ newlevel=true;
+ PlayLoop ();
+ break;
+
+ case ex_died:
+ loadit = done = false;
+// SetTextMode ( ); //12345678
+ Died ();
+ StopWind();
+ DisableScreenStretch();//bna++ shut off streech mode
+ while (damagecount>0)
+ DoBorderShifts();
+
+ damagecount = 0;
+ SetBorderColor (0);
+ if (demorecord)
+ {
+ FreeDemo ();
+ }
+ if (demoplayback)
+ {
+ FreeDemo ();
+ playstate=ex_demodone;
+ }
+ else
+ {
+ ShutdownClientControls();
+
+ Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level
+
+ if (CheckForQuickLoad()==false)
+ {
+ if (locplayerstate->lives < 0)
+ {
+ if (timelimitenabled == false)
+ {
+ CheckHighScore (gamestate.score, gamestate.mapon+1, false);
+ playstate = ex_titles;
+ AdjustMenuStruct ();
+ ingame = false;
+ locplayerstate->health = MaxHitpointsForCharacter(locplayerstate);
+ gamestate.score = 0;
+ locplayerstate->lives = 3;
+ locplayerstate->weapon = wp_pistol;
+ locplayerstate->triads = 0;
+ UpdateLives (locplayerstate->lives);
+ UpdateScore (gamestate.score);
+ }
+ else
+ {
+ QuitGame();
+ }
+ }
+ else
+ {
+ fizzlein = true;
+ SetupGameLevel ();
+ UpdateTriads(player,0);
+ playstate = ex_stillplaying;
+ }
+ }
+ }
+ break;
+
+ case ex_warped:
+ StopWind();
+ TurnShakeOff();
+ SHAKETICS = 0xffff;
+ gamestate.TimeCount = 0;
+ gamestate.frame=0;
+
+ Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level
+
+ fizzlein = true;
+ SetupGameLevel ();
+
+ playstate = ex_stillplaying;
+ break;
+
+ case ex_skiplevel:
+ case ex_secretdone:
+ case ex_secretlevel:
+ case ex_completed:
+ case ex_bossdied:
+ ShutdownClientControls();
+ TurnShakeOff();
+ SHAKETICS = 0xffff;
+ if (timelimitenabled == false)
+ {
+ gamestate.TimeCount = 0;
+ gamestate.frame=0;
+ }
+ StopWind();
+#if (SHAREWARE==0)
+ if ((playstate==ex_bossdied) && (gamestate.mapon!=30))
+ {
+ int shape;
+ lbm_t * LBM;
+ byte *s;
+ patch_t *p;
+ char str[50];
+ int width, height;
+
+ LBM = (lbm_t *) W_CacheLumpName( "deadboss", PU_CACHE, Cvt_lbm_t, 1);
+ VL_DecompressLBM (LBM,false);
+ MenuFadeOut();
+ switch (gamestate.mapon)
+ {
+ case 6:
+ shape = W_GetNumForName("deadstev");
+ break;
+ case 14:
+ shape = W_GetNumForName("deadjoe");
+ break;
+ case 22:
+ shape = W_GetNumForName("deadrobo");
+ break;
+ case 33:
+ shape = W_GetNumForName("deadtom");
+ break;
+// default:
+// Error("Boss died on an illegal level\n");
+// break;
+ }
+ s = W_CacheLumpNum (shape, PU_CACHE, Cvt_patch_t, 1);
+ p = (patch_t *)s;
+ DrawNormalSprite ((320-p->origsize)>>1, (230-(p->height-p->topoffset))>>1, shape);
+ switch (gamestate.mapon)
+ {
+ case 6:
+ strcpy(&str[0],"\"General\" John Darian");
+ break;
+ case 14:
+ strcpy(&str[0],"Sebastian \"Doyle\" Krist");
+ break;
+ case 22:
+ strcpy(&str[0],"the NME");
+ break;
+ case 33:
+ strcpy(&str[0],"El Oscuro");
+ break;
+// default:
+// Error("Boss died on an illegal level\n");
+// break;
+ }
+ CurrentFont=smallfont;
+ US_MeasureStr (&width, &height, "%s", str);
+ US_ClippedPrint ((320-width)>>1, 180, str);
+ VW_UpdateScreen();
+ MenuFadeIn();
+
+ WaitKeyUp();
+ LastScan = 0;
+ while (!LastScan) IN_UpdateKeyboard(); // Thanks again DrLex
+ LastScan=0;
+ }
+#endif
+
+ LevelCompleted ( playstate );
+
+ NextLevel = GetNextMap(player->tilex,player->tiley);
+
+ demoplayback = false;
+
+ Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level
+ if (NextLevel != -1 )
+ {
+ gamestate.mapon = NextLevel;
+ PlayCinematic();
+ fizzlein = true;
+ SetupGameLevel ();
+ playstate = ex_stillplaying;
+ }
+ else
+ {
+ playstate = ex_gameover;
+ }
+ break;
+
+ case ex_demodone:
+ ingame=false;
+ ShutdownClientControls();
+ TurnShakeOff();
+ SHAKETICS = 0xffff;
+ gamestate.TimeCount = 0;
+ gamestate.frame=0;
+
+ demoplayback = false;
+
+ Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level
+ if (predemo_violence != -1)
+ {
+ gamestate.violence = predemo_violence;
+ predemo_violence = -1;
+ }
+ playstate=ex_titles;
+ break;
+
+ case ex_gameover:
+ StopWind();
+ DoEndCinematic();
+ if (playstate==ex_gameover)
+ {
+ CheckHighScore (gamestate.score, gamestate.mapon+1, false);
+
+ ingame = false;
+ AdjustMenuStruct ();
+ playstate = ex_titles;
+ }
+ break;
+
+ case ex_demorecord:
+ ShutdownClientControls();
+ Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level
+
+ RecordDemo();
+ SetupGameLevel ();
+
+ fizzlein = true;
+ playstate = ex_stillplaying;
+ break;
+
+ case ex_demoplayback:
+ ShutdownClientControls();
+ Z_FreeTags (PU_LEVELSTRUCT, PU_LEVELEND); // Free current level
+
+ SetupDemo();
+ SetupGameLevel ();
+
+ fizzlein = true;
+ playstate = ex_stillplaying;
+ break;
+ default:
+ ;
+ }
+ }
+ waminot();
+}
+
+boolean CheckForQuickLoad (void )
+
+{
+
+ EnableScreenStretch();//bna++
+
+ if ( pickquick )
+ {
+ SetupMenuBuf();
+
+ pickquick = CP_DisplayMsg( "\nQuick load saved game?\n", 12 );
+ if ( pickquick )
+ {
+ AllocateSavedScreenPtr();
+ CP_LoadGame( 1, 1 );
+ FreeSavedScreenPtr();
+ }
+ else
+ {
+ // Erase the quick load message
+ VL_FadeOut( 0, 255, 0, 0, 0, 20 );
+ }
+
+ ShutdownMenuBuf();
+ }
+
+ return( pickquick );
+}
+
+//===========================================================================
+
+void ShutDown ( void )
+{
+ if ( ( standalone == false )
+#ifdef DOS
+ || ( SOUNDSETUP )
+#endif
+ )
+ {
+ WriteConfig ();
+ }
+
+// if (
+// (networkgame==false) &&
+// (modemgame==true)
+// )
+// {
+// ShutdownModemGame ();
+// }
+
+ ShutdownClientControls();
+ I_ShutdownKeyboard();
+#ifdef DOS /* the UL_ErrorStartup() call is commented out... */
+ UL_ErrorShutdown ();
+#endif
+ ShutdownGameCommands();
+ MU_Shutdown();
+ I_ShutdownTimer();
+ SD_Shutdown();
+ IN_Shutdown ();
+ ShutdownSoftError ();
+ Z_ShutDown();
+// _settextcursor (0x0607);
+}
+
+//===========================================================================
+
+#if (DEVELOPMENT == 1)
+extern int totallevelsize;
+#endif
+
+void QuitGame ( void )
+{
+#if (DEBUG == 1)
+ char buf[5];
+#endif
+
+#if (DEVELOPMENT == 1)
+ int temp;
+#else
+ byte *txtscn;
+#endif
+ int k;
+
+ MU_FadeOut(200);
+ while (MU_FadeActive())
+ {
+ int time=GetTicCount();
+ while (GetTicCount()==time) {}
+ }
+
+ PrintMapStats();
+ PrintTileStats();
+ SetTextMode();
+
+#if (DEVELOPMENT == 1)
+ printf("Clean Exit\n");
+ if (gamestate.TimeCount)
+ {
+ temp=(gamestate.frame*VBLCOUNTER*100)/gamestate.TimeCount;
+ printf("fps = %2ld.%2ld\n",temp/100,temp%100);
+ }
+ printf("argc=%ld\n",_argc);
+ for (k=0; k<_argc; k++) printf("%s\n",_argv[k]);
+ switch( _heapchk() )
+ {
+ case _HEAPOK:
+ printf( "OK - heap is good\n" );
+ break;
+ case _HEAPEMPTY:
+ printf( "OK - heap is empty\n" );
+ break;
+ case _HEAPBADBEGIN:
+ printf( "ERROR - heap is damaged\n" );
+ break;
+ case _HEAPBADNODE:
+ printf( "ERROR - bad node in heap\n" );
+ break;
+ }
+ printf("\nLight Characteristics\n");
+ printf("---------------------\n");
+ if (fog)
+ printf("FOG is ON\n");
+ else
+ printf("FOG is OFF\n");
+ printf("LIGHTLEVEL=%ld\n",GetLightLevelTile());
+ printf("LIGHTRATE =%ld\n",GetLightRateTile());
+ printf("\nCENTERY=%ld\n",centery);
+#else
+#ifdef DOS
+ if ( !SOUNDSETUP )
+ {
+#endif
+#if (SHAREWARE==0)
+ txtscn = (byte *) W_CacheLumpNum (W_GetNumForName ("regend"), PU_CACHE, CvtNull, 1);
+#else
+ txtscn = (byte *) W_CacheLumpNum (W_GetNumForName ("shareend"), PU_CACHE, CvtNull, 1);
+#endif
+#if DOS
+ for (k = 0; k < 23; k++)
+ printf ("\n");
+ memcpy ((byte *)0xB8000, txtscn, 4000);
+#elif defined (ANSIESC)
+ DisplayTextSplash (txtscn, 25);
+#endif
+
+#if (DEBUG == 1)
+ px = ERRORVERSIONCOL;
+ py = ERRORVERSIONROW;
+#if (BETA == 1)
+ UL_printf ("�");
+#else
+ UL_printf (itoa(ROTTMAJORVERSION,&buf[0],10));
+#endif
+ // Skip the dot
+ px++;
+
+ UL_printf (itoa(ROTTMINORVERSION,&buf[0],10));
+#endif
+#ifdef DOS
+ }
+#endif
+#endif
+
+#ifdef DOS
+ if ( SOUNDSETUP )
+ {
+ printf( "\nSound setup complete.\n"
+ "Type ROTT to run the game.\n" );
+ }
+ ShutDown();
+#endif
+
+ exit(0);
+}
+
+void InitCharacter
+(
+ void
+)
+
+{
+ locplayerstate->health = MaxHitpointsForCharacter( locplayerstate );
+ if (timelimitenabled == true)
+ {
+ locplayerstate->lives = 1;
+ }
+ else
+ {
+ locplayerstate->lives = 3;
+ }
+
+ ClearTriads (locplayerstate);
+ locplayerstate->playerheight = characters[ locplayerstate->player ].height;
+// locplayerstate->stepwhich = 0;
+// locplayerstate->steptime = 0;
+
+ gamestate.score = 0;
+
+ if ( gamestate.battlemode == battle_StandAloneGame )
+ {
+ gamestate.mapon = startlevel;
+ gamestate.difficulty = DefaultDifficulty;
+ }
+ else
+ {
+ gamestate.difficulty = gd_hard;
+ }
+
+ gamestate.dipballs = 0;
+ gamestate.TimeCount = 0;
+
+ godmode = 0;
+ damagecount = 0;
+
+ UpdateScore( gamestate.score );
+}
+
+
+
+extern boolean enableZomROTT;
+void UpdateGameObjects ( void )
+{
+ int j;
+ volatile int atime;
+ objtype * ob,*temp;
+ battle_status BattleStatus;
+
+ wami(2);
+
+ if (controlupdatestarted==0)
+ {
+ return;
+ waminot();
+ }
+
+ atime=GetFastTics();
+
+ UpdateClientControls ();
+
+ if (demoplayback == false)
+ PollControls ();
+
+ CalcTics ();
+
+ UpdateClientControls ();
+
+
+ while (oldpolltime<oldtime)
+ {
+ UpdateClientControls ();
+ MoveDoors();
+ ProcessElevators();
+ MovePWalls();
+ UpdateLightning ();
+ TriggerStuff();
+ CheckCriticalStatics();
+ if (((gamestate.TimeCount/VBLCOUNTER) % 60 == 0) && gamestate.TimeCount/VBLCOUNTER >= 60 && enableZomROTT)
+ {
+ ResurrectEnemies();
+ }
+
+ for(j=0; j<numclocks; j++)
+ if (Clocks[j].time1 &&
+ ((gamestate.TimeCount == Clocks[j].time1) ||
+ (gamestate.TimeCount == Clocks[j].time2)))
+ TRIGGER[Clocks[j].linkindex]=1;
+ for (ob = firstactive; ob;)
+ {
+ temp = ob->nextactive;
+ DoActor (ob);
+#if (DEVELOPMENT == 1)
+ if ((ob->x<=0) || (ob->y<=0))
+ Error("object xy below zero obj->x=%ld obj->y=%ld obj->obclass=%ld\n",ob->x,ob->y,ob->obclass);
+ if ((ob->angle<0) || (ob->angle>=FINEANGLES))
+ Error("object angle below zero obj->angle=%ld obj->obclass=%ld\n",ob->angle,ob->obclass);
+#endif
+ ob = temp;
+ }
+
+ BattleStatus = BATTLE_CheckGameStatus( battle_refresh, 0 );
+ if ( BattleStatus != battle_no_event )
+ {
+ switch( BattleStatus )
+ {
+ case battle_end_game :
+ case battle_out_of_time :
+ playstate = ex_battledone;
+ break;
+
+ case battle_end_round :
+ SetWhoHaveWeapons();
+ break;
+ default:
+ ;
+ }
+ if ( playstate == ex_battledone )
+ {
+ break;
+ }
+ }
+#if (SYNCCHECK == 1)
+ CheckForSyncCheck();
+#endif
+ if (timelimitenabled == true)
+ {
+ if (timelimit-gamestate.TimeCount>maxtimelimit)
+ timelimit = maxtimelimit+gamestate.TimeCount;
+ if (gamestate.TimeCount == timelimit)
+ {
+ locplayerstate->lives=-1;
+ playstate=ex_died;
+ }
+ }
+
+ gamestate.TimeCount ++;
+
+ ResetCurrentCommand();
+
+ oldpolltime++;
+ if (GamePaused==true)
+ break;
+ }
+ actortime=GetFastTics()-atime;
+
+ UpdateClientControls ();
+
+ if (noecho == false)
+ {
+ if ( player->flags & FL_SHROOMS )
+ {
+ FX_SetReverb( 230 );
+ }
+ else if (sky == 0)
+ {
+ FX_SetReverb( min( numareatiles[ player->areanumber ] >> 1, 90 ) );
+ }
+ }
+
+ waminot();
+
+}
+
+
+void PauseLoop ( void )
+{
+ StopWind();
+
+ UpdateClientControls ();
+
+ while (oldpolltime<oldtime)
+ {
+ CheckUnPause();
+#if (SYNCCHECK == 1)
+ CheckForSyncCheck();
+#endif
+ oldpolltime++;
+ if (GamePaused==false)
+ {
+ //bna++ section
+ if (( playstate == ex_stillplaying )&&(iGLOBAL_SCREENWIDTH > 320)) {
+ pic_t *shape;
+ shape = ( pic_t * )W_CacheLumpName( "backtile", PU_CACHE, Cvt_pic_t, 1 );
+ DrawTiledRegion( 0, 16, iGLOBAL_SCREENWIDTH, iGLOBAL_SCREENHEIGHT - 32, 0, 16, shape );
+ DisableScreenStretch();//dont strech when we go BACK TO GAME
+ DrawPlayScreen(true);//repaint ammo and life stat
+ VW_UpdateScreen ();//update screen
+ }
+ StartupClientControls();
+ //bna section end
+ break;
+ }
+ }
+
+ CalcTics ();
+ if (demoplayback==false)
+ PollControls ();
+
+ if ((RefreshPause == true) &&
+ (GamePaused == true) &&
+ ((GetTicCount() - pausedstartedticcount) >= blanktime))
+ {
+ RefreshPause = false;
+ StartupScreenSaver();
+ }
+}
+
+
+
+void PlayLoop
+(
+ void
+)
+
+{
+ volatile int atime;
+
+ boolean canquit = true;
+ int quittime = 0;
+
+ wami(3);
+
+
+ if ( (loadedgame == false) && (timelimitenabled == false) )
+ {
+ gamestate.TimeCount = 0;
+ gamestate.frame = 0;
+ }
+
+fromloadedgame:
+
+ GamePaused = false;
+
+ if ( loadedgame == false )
+ {
+ DrawPlayScreen( true );
+ missobj = NULL;
+ }
+ else
+ {
+ loadedgame = false;
+ DoLoadGameSequence();
+ }
+
+ drawtime = 0;
+ actortime = 0;
+ tics = 0;
+ SetFastTics(0);
+
+ if ( fizzlein == false )
+ {
+ StartupClientControls();
+ }
+ else
+ {
+ ShutdownClientControls();
+ }
+
+ // set detail level
+ doublestep = 2 - DetailLevel;
+
+ ResetMessageTime();
+ DeletePriorityMessage( MSG_SYSTEM );
+
+ if ( ( gamestate.battlemode == battle_Normal ) &&
+ ( numplayers == 1 ) )
+ {
+ AddMessage( "Comm-bat is for Modem and Network games.", MSG_GAME );
+ AddMessage( "You will not be facing any", MSG_GAME );
+ AddMessage( "opponents. Have fun and explore.", MSG_GAME );
+ }
+
+
+ while( playstate == ex_stillplaying )
+ {
+ UpdateClientControls();
+
+ if ( GamePaused )
+ {
+ PauseLoop();
+
+ atime = GetFastTics();
+
+ if ( RefreshPause )
+ {
+ ThreeDRefresh();
+ }
+ else
+ {
+ UpdateScreenSaver();
+ }
+ }
+ else
+ {
+ if (controlupdatestarted == 1)
+ UpdateGameObjects();
+
+ atime = GetFastTics();
+
+ ThreeDRefresh();
+ }
+
+ SyncToServer();
+
+ drawtime = GetFastTics() - atime;
+
+ // Don't allow player to quit if entering message
+ canquit = !MSG.messageon;
+
+ PollKeyboard();
+
+ MISCVARS->madenoise = false;
+
+ AnimateWalls();
+
+ UpdateClientControls();
+
+#if (DEVELOPMENT == 1)
+ Z_CheckHeap();
+#endif
+
+ if ( AutoDetailOn == true )
+ {
+ AdaptDetail();
+ }
+
+ UpdateClientControls();
+
+ DoSprites();
+ DoAnimatedMaskedWalls();
+
+ UpdatePlayers();
+
+ DrawTime( false );
+
+ UpdateClientControls();
+
+ if ( ( !BATTLEMODE ) && ( CP_CheckQuick( LastScan ) ) )
+ {
+ boolean escaped=false;
+
+ if (LastScan == sc_Escape)
+ {
+ MU_StoreSongPosition();
+ MU_StartSong(song_menu);
+ escaped = true;
+ }
+ TurnShakeOff();
+ StopWind();
+ SetBorderColor( 0 );
+ ShutdownClientControls();
+ if (demoplayback==true)
+ {
+ FreeDemo();
+ playstate = ex_demodone;
+ if (demoexit==true)
+ {
+ QuitGame();
+ }
+ return;
+ }
+
+ ControlPanel( LastScan );
+
+ // set detail level
+ doublestep = 2 - DetailLevel;
+
+ inmenu = false;
+
+ if ( playstate == ex_titles )
+ {
+ return;
+ }
+
+ if ( playstate == ex_stillplaying )
+ {
+ SetupScreen( false );
+ }
+
+ if ( loadedgame == true )
+ {
+ goto fromloadedgame;
+ }
+
+ if (
+ ( playstate == ex_stillplaying ) &&
+ ( ( fizzlein == false ) ||
+ ( GamePaused )
+ )
+ )
+ {
+ StartupClientControls();
+ }
+
+ if (
+ (playstate == ex_stillplaying) &&
+ (GamePaused == false) &&
+ (escaped == true)
+ )
+ {
+ MU_StartSong(song_level);
+ MU_RestoreSongPosition();
+ }
+ }
+
+ if ( BATTLEMODE )
+ {
+ if ( MSG.messageon == false )
+ {
+ CheckRemoteRidicule( LastScan );
+ }
+ if ( quitactive == false )
+ {
+ if ( ( LastScan == sc_Escape ) && ( canquit ) )
+ {
+ quitactive = true;
+ quittime = GetTicCount() + QUITTIMEINTERVAL;
+
+ if ( (consoleplayer == 0) || (networkgame == false) )
+ {
+ AddMessage( "Do you want to end this game? "
+ "(\\FY\\O/\\FN\\O)", MSG_QUIT );
+ }
+ else
+ {
+ AddMessage( "Do you want to exit to DOS? "
+ "(\\FY\\O/\\EN\\O)", MSG_QUIT );
+ }
+ }
+ }
+ else
+ {
+ if ( GetTicCount() > quittime )
+ {
+ quitactive = false;
+ }
+ else if ( LastScan == sc_N )
+ {
+ DeletePriorityMessage( MSG_QUIT );
+ quitactive = false;
+ }
+ else if ( LastScan == sc_Y )
+ {
+ DeletePriorityMessage( MSG_QUIT );
+ if ( (consoleplayer == 0) || (networkgame==false) )
+ {
+ AddEndGameCommand();
+ }
+ else
+ {
+ AddQuitCommand();
+ }
+ }
+ }
+ }
+ }
+ waminot();
+}
+
+//******************************************************************************
+//
+// CheckRemoteRidicule ()
+//
+//******************************************************************************
+
+void CheckRemoteRidicule ( int scancode )
+{
+ int num=-1;
+
+ wami(4);
+ switch (scancode)
+ {
+ case sc_F1:
+ num=0;
+ break;
+ case sc_F2:
+ num=1;
+ break;
+ case sc_F3:
+ num=2;
+ break;
+ case sc_F4:
+ num=3;
+ break;
+ case sc_F5:
+ if ( !Keyboard[ sc_RShift ] )
+ {
+ num=4;
+ }
+ break;
+ case sc_F6:
+ num=5;
+ break;
+ case sc_F7:
+ if ( !Keyboard[ sc_RShift ] )
+ {
+ num=6;
+ }
+ break;
+ case sc_F8:
+ num=7;
+ break;
+ case sc_F9:
+ num=8;
+ break;
+ case sc_F10:
+ num=9;
+ break;
+ }
+ if (num>=0)
+ {
+ AddRemoteRidiculeCommand ( consoleplayer, MSG_DIRECTED_TO_ALL, num );
+ LastScan=0;
+ }
+ waminot();
+}
+
+//******************************************************************************
+//
+// DoBossKey ()
+//
+//******************************************************************************
+
+void DoBossKey ( void )
+{
+#ifdef DOS
+ union REGS regs;
+ ShutdownClientControls();
+
+ SetTextMode();
+
+ // move cursor to the row 0 column 4
+ regs.w.ax = 0x0200;
+ regs.w.bx = 0;
+ regs.w.dx = 0x0004;
+ int386(0x10,®s,®s);
+ px=0;
+ py=0;
+ UL_printf("C:\\>\n");
+
+ LastScan = 0;
+ IN_WaitForKey ();
+ VL_SetVGAPlaneMode();
+ VL_SetPalette(origpal);
+ SetBorderColor(0);
+ TurnShakeOff();
+ SetupScreen(true);
+ ThreeDRefresh();
+
+ StartupClientControls();
+#else
+ STUB_FUNCTION;
+#endif
+}
+
+
+//******************************************************************************
+//
+// PollKeyboard ()
+//
+//******************************************************************************
+
+void PollKeyboard
+(
+ void
+)
+
+{
+ static char autopressed = false;
+
+ wami(5);
+
+ if (demoplayback==true)
+ {
+ IN_UpdateKeyboard();
+ }
+
+ if ( !BATTLEMODE )
+ {
+ CheckDebug ();
+ if (
+ ( Keyboard[ sc_CapsLock ] ) &&
+ ( DebugOk )
+ )
+ {
+ DebugKeys ();
+ }
+ }
+
+ if ( locplayerstate->buttonstate[ bt_autorun ] )
+ {
+ if ( !autopressed )
+ {
+ autopressed = true;
+ gamestate.autorun ^= 1;
+ if ( gamestate.autorun == 0 )
+ {
+ AddMessage( "AutoRun is \\cOFF", MSG_SYSTEM );
+ }
+ else
+ {
+ AddMessage( "AutoRun is \\cON", MSG_SYSTEM );
+ }
+ }
+ }
+ else
+ {
+ autopressed = false;
+ }
+
+#if 0
+ if ( modemgame == false )
+ {
+ CheckDevelopmentKeys();
+ }
+#endif
+
+ if ( ( MSG.messageon == false ) && ( !quitactive ) )
+ {
+ if ( ( Keyboard[ buttonscan[ bt_message ] ] ) && ( BATTLEMODE ) )
+ {
+ // Send message to all
+ MSG.messageon = true;
+ MSG.directed = false;
+ MSG.inmenu = false;
+ MSG.remoteridicule = -1;
+ MSG.towho = MSG_DIRECTED_TO_ALL;
+ MSG.textnum = AddMessage( "_", MSG_MODEM );
+ MSG.length = 1;
+ DeletePriorityMessage( MSG_MACRO );
+ }
+ else if ( ( Keyboard[ buttonscan[ bt_directmsg ] ] ) && ( BATTLEMODE ) )
+ {
+ // Send directed message
+ MSG.messageon = true;
+ MSG.directed = true;
+ MSG.inmenu = false;
+ MSG.remoteridicule = -1;
+ MSG.towho = 0;
+ MSG.textnum = AddMessage( "_", MSG_MODEM );
+ MSG.length = 1;
+ DeletePriorityMessage( MSG_MACRO );
+ }
+ if ( buttonpoll[ bt_map ] )
+ {
+ if ( !BATTLEMODE )
+ {
+ // Automap
+ StopWind();
+ DoMap( player->tilex, player->tiley );
+ }
+ else
+ {
+ // Show kill counts
+ if ( SHOW_KILLS() )
+ {
+ BATTLE_ShowKillCount = false;
+ StatusBar &= ~STATUS_KILLS;
+ }
+ else
+ {
+ StatusBar |= STATUS_KILLS;
+ BATTLE_ShowKillCount = true;
+ }
+
+ SetupScreen( true );
+ }
+ }
+
+ // Shrink screen
+ if ( Keyboard[ sc_Minus ] )
+ {
+ Keyboard[ sc_Minus ] = false; // HDG debounce
+ if ( viewsize > 0 )
+ {
+ viewsize--;
+ SetupScreen( true );
+ }
+ }
+
+ // Expand screen
+ if ( Keyboard[ sc_Plus ] )
+ {
+ Keyboard[ sc_Plus ] = false; // HDG debounce
+ if ( viewsize < MAXVIEWSIZES - 1 )
+ {
+ viewsize++;
+ SetupScreen( true );
+ }
+ }
+
+ // Set detail
+ if ( ( Keyboard[ sc_F5 ] ) && ( ( !BATTLEMODE ) ||
+ ( Keyboard[ sc_RShift ] ) ) )
+ {
+ Keyboard[ sc_F5 ] = false;
+ LastScan = 0;
+ DetailLevel++;
+ if ( DetailLevel > 2 )
+ {
+ DetailLevel = 0;
+ }
+
+ switch( DetailLevel )
+ {
+ case 0 :
+ AddMessage( "Low detail", MSG_SYSTEM );
+ break;
+
+ case 1 :
+ AddMessage( "Medium detail", MSG_SYSTEM );
+ break;
+
+ case 2 :
+ AddMessage( "High detail", MSG_SYSTEM );
+ break;
+ }
+ doublestep = 2 - DetailLevel;
+ }
+
+ // Turn messages on/off
+
+ if ( ( Keyboard[ sc_F7 ] ) && ( ( !BATTLEMODE ) ||
+ ( Keyboard[ sc_RShift ] ) ) )
+ {
+ Keyboard[ sc_F7 ] = false;
+ LastScan = 0;
+ MessagesEnabled = !MessagesEnabled;
+ if ( !MessagesEnabled )
+ {
+ AddMessage( "Messages disabled.", MSG_MSGSYSTEM );
+ }
+ else
+ {
+ AddMessage( "Messages enabled.", MSG_MSGSYSTEM );
+ }
+ }
+
+ if ( ( Keyboard[ sc_F6 ] ) && ( !BATTLEMODE ) )
+ {
+ Keyboard[ sc_F6 ] = false;
+ if (Keyboard[sc_RShift])
+ {
+ ShutdownClientControls();
+ UndoQuickSaveGame();
+ StartupClientControls();
+ }
+ else if (quicksaveslot==-1)
+ {
+ ShutdownClientControls();
+ LastScan=sc_F2;
+ inmenu = true;
+ ControlPanel( LastScan );
+ StartupClientControls();
+ }
+ else
+ {
+ LastScan = 0;
+ ShutdownClientControls();
+ ThreeDRefresh();
+ QuickSaveGame();
+ StartupClientControls();
+ }
+ }
+
+//#if 0
+ if ( ( Keyboard[ sc_F12 ] ) && ( !BATTLEMODE ) )
+ {
+ Keyboard[ sc_F12 ] = false;
+ LastScan = 0;
+ DoBossKey();
+ }
+//#endif
+
+ // Gamma correction
+ if ( Keyboard[ sc_F11 ] )
+ {
+ char str[ 50 ] = "Gamma Correction Level ";
+ char str2[ 10 ];
+
+ gammaindex++;
+ if ( gammaindex == NUMGAMMALEVELS )
+ {
+ gammaindex = 0;
+ }
+ VL_SetPalette( origpal );
+ itoa( gammaindex, str2, 10 );
+ strcat( str, str2 );
+ AddMessage( str, MSG_SYSTEM );
+
+ while( Keyboard[ sc_F11 ] )
+ {
+ IN_UpdateKeyboard();
+ }
+ }
+#if 0
+ if ( Keyboard[ sc_M ] )
+ {
+ char str[ 50 ] = "Mouse Y-Rotation Input Scale ";
+ char str2[ 10 ];
+
+ if ( Keyboard[ sc_RShift ] )
+ mouse_ry_input_scale += 50;
+ else
+ mouse_ry_input_scale -= 50;
+
+ itoa(mouse_ry_input_scale,str2,10);
+ strcat( str, str2 );
+ AddMessage( str, MSG_SYSTEM );
+
+ }
+#endif
+ // Increase volume
+ if ( Keyboard[ sc_CloseBracket ] )
+ {
+ if ( Keyboard[ sc_RShift ] )
+ {
+ char str[ 50 ] = "Music Volume Level ";
+ char str2[ 10 ];
+
+ if ( MUvolume < 255 )
+ {
+ MUvolume++;
+ }
+ MU_SetVolume( MUvolume );
+
+ itoa( MUvolume, str2, 10 );
+ strcat( str, str2 );
+ AddMessage( str, MSG_SYSTEM );
+ }
+ else
+ {
+ char str[ 50 ] = "Sound FX Volume Level ";
+ char str2[ 10 ];
+
+ if ( FXvolume < 255 )
+ {
+ FXvolume++;
+ }
+ FX_SetVolume( FXvolume );
+
+ itoa( FXvolume, str2, 10 );
+ strcat( str, str2 );
+ AddMessage( str, MSG_SYSTEM );
+ }
+ }
+
+ // Decrease volume
+ if ( Keyboard[ sc_OpenBracket ] )
+ {
+ if ( Keyboard[ sc_RShift ] )
+ {
+ char str[ 50 ] = "Music Volume Level ";
+ char str2[ 10 ];
+
+ if ( MUvolume > 0 )
+ {
+ MUvolume--;
+ }
+ MU_SetVolume( MUvolume );
+
+ itoa( MUvolume, str2, 10 );
+ strcat( str, str2 );
+ AddMessage( str, MSG_SYSTEM );
+ }
+ else
+ {
+ char str[ 50 ] = "Sound FX Volume Level ";
+ char str2[ 10 ];
+
+ if ( FXvolume > 0 )
+ {
+ FXvolume--;
+ }
+ FX_SetVolume( FXvolume );
+
+ itoa( FXvolume, str2, 10 );
+ strcat( str, str2 );
+ AddMessage( str, MSG_SYSTEM );
+ }
+ }
+
+#if SAVE_SCREEN
+#if (DEVELOPMENT == 1)
+ if ( Keyboard[ sc_CapsLock ] && Keyboard[ sc_C ] )
+ {
+ SaveScreen( true );
+ }
+ else if ( Keyboard[ sc_CapsLock ] && Keyboard[ sc_X ] )
+ {
+ SaveScreen( false );
+ }
+#endif
+ else if ( Keyboard[ sc_Alt] && Keyboard[ sc_C ] )
+ {
+ SaveScreen( false );
+ }
+#ifdef DOS /* makes no sense under Linux as there are no lbm viewers there */
+ else if ( Keyboard[ sc_Alt] && Keyboard[ sc_V ] )
+ {
+ SaveScreen( true );
+ }
+#endif
+#endif
+ }
+#ifdef USE_SDL
+ /* SDL doesn't send proper release events for these */
+ if (Keystate[sc_CapsLock])
+ {
+ Keystate[sc_CapsLock]++;
+ if (Keystate[sc_CapsLock] == 3)
+ Keystate[sc_CapsLock] = 0;
+ }
+ if (Keystate[0x45]) /* numlock */
+ {
+ Keystate[0x45]++;
+ if (Keystate[0x45] == 3)
+ Keystate[0x45] = 0;
+ }
+#endif
+ waminot();
+}
+
+
+//******************************************************************************
+//
+// CheckDevelopmentKeys ()
+//
+//******************************************************************************
+#if 0
+void CheckDevelopmentKeys
+(
+ void
+)
+
+{
+#if (DEBUG == 1)
+ if ( Keyboard[ sc_CapsLock ] && Keyboard[ sc_T ] )
+ {
+ if ( warp == true )
+ {
+ player->x = warpx;
+ player->y = warpy;
+ player->angle = warpa;
+ locplayerstate->anglefrac = warpa << ANGLEBITS;
+ player->momentumx = 0;
+ player->momentumy = 0;
+ player->momentumz = 0;
+ }
+ return;
+ }
+#endif
+
+ // Lower wall height
+ if ( Keyboard[ sc_5 ] )
+ {
+ if ( levelheight > 1 )
+ {
+ levelheight--;
+ }
+
+ while( Keyboard[ sc_5 ] )
+ {
+ IN_UpdateKeyboard ();
+ }
+
+ maxheight = ( levelheight << 6 ) - 32;
+ nominalheight = maxheight - 32;
+ }
+
+ // Raise wall height
+ if ( Keyboard[ sc_6 ] )
+ {
+ levelheight++;
+
+ while( Keyboard[ sc_6 ] )
+ {
+ IN_UpdateKeyboard();
+ }
+
+ maxheight = ( levelheight << 6 ) - 32;
+ nominalheight = maxheight - 32;
+ }
+
+ if ( Keyboard[ sc_8 ] )
+ {
+ char str[ 50 ] = "You are now player ";
+ char str2[ 10 ];
+
+ locplayerstate->player++;
+ if ( locplayerstate->player == 5 )
+ {
+ locplayerstate->player = 0;
+ }
+
+ while( Keyboard[ sc_8 ] )
+ {
+ IN_UpdateKeyboard ();
+ }
+
+ itoa( locplayerstate->player, str2, 10 );
+ strcat( str, str2 );
+ AddMessage( str, MSG_SYSTEM );
+ }
+
+#if 0
+ // Cycle forward through wall textures
+ if (Keyboard[sc_W] && (modemgame==false))
+ { int i,j;
+
+ for(i=0; i<128; i++)
+ for(j=0; j<128; j++)
+ { if (IsWall(i,j))
+ { if (tilemap[i][j] ==
+ (W_GetNumForName("WALLSTOP")-W_GetNumForName("WALLSTRT")-1))
+ tilemap[i][j] = 1;
+ else
+ tilemap[i][j] ++;
+ }
+ }
+ while(Keyboard[sc_W])
+ IN_UpdateKeyboard ();
+
+ }
+
+
+
+ if (Keyboard[sc_Q] && (modemgame==false))
+ { int i,j;
+
+ for(i=0; i<128; i++)
+ for(j=0; j<128; j++)
+ { if (IsWall(i,j))
+ { if (tilemap[i][j] == 1)
+ tilemap[i][j] = 74;
+ else
+ tilemap[i][j] --;
+ }
+ }
+ while(Keyboard[sc_Q])
+ IN_UpdateKeyboard ();
+
+ }
+
+#endif
+ // Step through cieling/skies
+ if ( Keyboard[ sc_K ] )
+ {
+ if ( sky > 0 )
+ {
+ MAPSPOT( 1, 0, 0 )++;
+ if ( MAPSPOT( 1, 0, 0 ) > 239 )
+ {
+ MAPSPOT( 1, 0, 0 ) = 234;
+ }
+ }
+ else
+ {
+ MAPSPOT( 1, 0, 0 )++;
+ if ( MAPSPOT( 1, 0, 0 ) > 198 + 15 )
+ {
+ MAPSPOT( 1, 0, 0 ) = 198;
+ }
+ }
+
+ SetPlaneViewSize();
+
+ while( Keyboard[ sc_K ] )
+ {
+ IN_UpdateKeyboard();
+ }
+ }
+
+ // Step through floors
+ if ( Keyboard[ sc_L ] )
+ {
+ MAPSPOT( 0, 0, 0 )++;
+ if ( MAPSPOT( 0, 0, 0 ) > 180 + 15 )
+ {
+ MAPSPOT( 0, 0, 0 ) = 180;
+ SetPlaneViewSize();
+
+ while( Keyboard[ sc_L ] )
+ {
+ IN_UpdateKeyboard();
+ }
+ }
+ }
+
+ // Increase darkness level
+ if ( Keyboard[ sc_M ] )
+ {
+ if ( darknesslevel < 7 )
+ {
+ darknesslevel++;
+ }
+
+ SetLightLevels( darknesslevel );
+
+ while( Keyboard[ sc_M ] )
+ {
+ IN_UpdateKeyboard();
+ }
+ }
+
+ // Decrease darkness level
+ if ( Keyboard[ sc_N ] )
+ {
+ if ( darknesslevel > 0 )
+ {
+ darknesslevel--;
+ }
+
+ SetLightLevels( darknesslevel );
+
+ while( Keyboard[ sc_N ] )
+ {
+ IN_UpdateKeyboard();
+ }
+ }
+
+ // Increase light rate
+ if ( Keyboard[ sc_B ] )
+ {
+ SetLightRate( GetLightRate() + 1 );
+ myprintf( "normalshade = %ld\n", normalshade );
+
+ while( Keyboard[ sc_B ] )
+ {
+ IN_UpdateKeyboard();
+ }
+ }
+
+ // Decrease light rate
+ if ( Keyboard[ sc_V ] )
+ {
+ SetLightRate( GetLightRate() - 1 );
+ myprintf( "normalshade = %ld\n", normalshade );
+
+ while( Keyboard[ sc_V ] )
+ {
+ IN_UpdateKeyboard();
+ }
+ }
+
+ // Toggle light diminishing on/off
+ if ( Keyboard[ sc_T ] )
+ {
+ fulllight ^= 1;
+
+ while( Keyboard[ sc_T ] )
+ {
+ IN_UpdateKeyboard();
+ }
+ }
+}
+#endif
+
+
+#if SAVE_SCREEN
+
+
+short BigShort (short l)
+{
+ byte b1,b2;
+
+ b1 = l&255;
+ b2 = (l>>8)&255;
+
+ return (b1<<8) + b2;
+}
+
+long BigLong (long l)
+{
+ byte b1,b2,b3,b4;
+
+ b1 = l&255;
+ b2 = (l>>8)&255;
+ b3 = (l>>16)&255;
+ b4 = (l>>24)&255;
+
+ return ((long)b1<<24) + ((long)b2<<16) + ((long)b3<<8) + b4;
+}
+
+/*
+==============
+=
+= WriteLBMfile
+=
+==============
+*/
+
+void WriteLBMfile (char *filename, byte *data, int width, int height)
+{
+ byte *lbm, *lbmptr;
+ long *formlength, *bmhdlength, *cmaplength, *bodylength;
+ long length;
+ bmhd_t basebmhd;
+ int handle;
+ int i;
+
+ lbm = lbmptr = (byte *) SafeMalloc ((iGLOBAL_SCREENWIDTH*iGLOBAL_SCREENHEIGHT)+4000);
+
+//
+// start FORM
+//
+ *lbmptr++ = 'F';
+ *lbmptr++ = 'O';
+ *lbmptr++ = 'R';
+ *lbmptr++ = 'M';
+
+ formlength = (long*)lbmptr;
+ lbmptr+=4; // leave space for length
+
+ *lbmptr++ = 'P';
+ *lbmptr++ = 'B';
+ *lbmptr++ = 'M';
+ *lbmptr++ = ' ';
+
+//
+// write BMHD
+//
+ *lbmptr++ = 'B';
+ *lbmptr++ = 'M';
+ *lbmptr++ = 'H';
+ *lbmptr++ = 'D';
+
+ bmhdlength = (long *)lbmptr;
+ lbmptr+=4; // leave space for length
+
+ memset (&basebmhd,0,sizeof(basebmhd));
+ basebmhd.w = BigShort(width);
+ basebmhd.h = BigShort(height);
+ basebmhd.nPlanes = BigShort(8);
+ basebmhd.xAspect = BigShort(5);
+ basebmhd.yAspect = BigShort(6);
+ basebmhd.pageWidth = BigShort(width);
+ basebmhd.pageHeight = BigShort(height);
+
+ memcpy (lbmptr,&basebmhd,sizeof(basebmhd));
+ lbmptr += sizeof(basebmhd);
+
+ length = lbmptr-(byte *)bmhdlength-4;
+ *bmhdlength = BigLong(length);
+ if (length&1)
+ *lbmptr++ = 0; // pad chunk to even offset
+
+//
+// write CMAP
+//
+ *lbmptr++ = 'C';
+ *lbmptr++ = 'M';
+ *lbmptr++ = 'A';
+ *lbmptr++ = 'P';
+
+ cmaplength = (long *)lbmptr;
+ lbmptr+=4; // leave space for length
+
+ for (i = 0; i < 0x300; i++)
+ *lbmptr++ = (*(origpal+i))<<2;
+
+// memcpy (lbmptr,&origpal[0],768);
+// lbmptr += 768;
+
+ length = lbmptr-(byte *)cmaplength-4;
+ *cmaplength = BigLong(length);
+ if (length&1)
+ *lbmptr++ = 0; // pad chunk to even offset
+
+//
+// write BODY
+//
+ *lbmptr++ = 'B';
+ *lbmptr++ = 'O';
+ *lbmptr++ = 'D';
+ *lbmptr++ = 'Y';
+
+ bodylength = (long *)lbmptr;
+ lbmptr+=4; // leave space for length
+
+ memcpy (lbmptr,data,width*height);
+ lbmptr += width*height;
+
+ length = lbmptr-(byte *)bodylength-4;
+ *bodylength = BigLong(length);
+ if (length&1)
+ *lbmptr++ = 0; // pad chunk to even offset
+
+//
+// done
+//
+ length = lbmptr-(byte *)formlength-4;
+ *formlength = BigLong(length);
+ if (length&1)
+ *lbmptr++ = 0; // pad chunk to even offset
+
+//
+// write output file
+//
+ handle = SafeOpenWrite (filename);
+
+ SafeWrite (handle, lbm, lbmptr-lbm);
+
+ close (handle);
+ SafeFree(lbm);
+}
+
+
+//****************************************************************************
+//
+// GetFileName ()
+//
+//****************************************************************************
+
+void GetFileName (boolean saveLBM)
+{
+#ifdef DOS
+ char num[4];
+ int cnt = 0;
+ struct find_t fblock;
+
+ if (saveLBM)
+ memcpy (savename, "ROTT0000.LBM\0", 13);
+ else
+ memcpy (savename, "ROTT0000.PCX\0", 13);
+
+ if (_dos_findfirst (savename, 0, &fblock) != 0)
+ return;
+
+ do
+ {
+ cnt++;
+ memset (&num[0], 0, 4);
+ itoa (cnt, num, 10);
+
+ if (cnt > 99)
+ {
+ savename[5] = num[0];
+ savename[6] = num[1];
+ savename[7] = num[2];
+ }
+ else if (cnt > 9)
+ {
+ savename[6] = num[0];
+ savename[7] = num[1];
+ }
+ else
+ savename[7] = num[0];
+ }
+ while (_dos_findfirst (savename, 0, &fblock) == 0);
+#else
+ int i;
+
+ for (i = 0; i < 9999; i++) {
+ char filename[128];
+
+ if (saveLBM) {
+ sprintf(savename, "rott%04d.lbm", i);
+ } else {
+ sprintf(savename, "rott%04d.pcx", i);
+ }
+
+ GetPathFromEnvironment( filename, ApogeePath, savename );
+
+ if (access(filename, F_OK) != 0) {
+ return;
+ }
+ }
+#endif
+}
+
+//****************************************************************************
+//
+// SaveScreen ()
+//
+//****************************************************************************
+
+boolean inhmenu;
+
+#if (BETA == 1)
+#define SSX (160-(46*2))
+#define SSY (17)
+#endif
+void SaveScreen (boolean saveLBM)
+{
+ byte *buffer;
+ byte * screen;
+ boolean oldHUD;
+ char filename[ 128 ];
+
+#if (BETA == 1)
+ unsigned tmp;
+ char buf[30];
+ int i;
+#endif
+
+
+ oldHUD=HUD;
+ HUD=false;
+ doublestep=0;
+ if (inhmenu==false)
+ screen = (byte *) bufferofs;
+ else
+ screen = (byte *) displayofs;
+
+ if (inhmenu==false)
+ ThreeDRefresh ();
+ doublestep = 2 - DetailLevel;
+
+ //buffer = (byte *) SafeMalloc (65000);
+ buffer = (byte *) SafeMalloc ((iGLOBAL_SCREENHEIGHT*iGLOBAL_SCREENWIDTH)+4000);
+
+#if (BETA == 1)
+ if (SCREENSHOTS == false)
+ {
+ if (screen!=(byte *)bufferofs)
+ {
+ tmp=bufferofs;
+ bufferofs=displayofs;
+ }
+ CurrentFont=tinyfont;
+
+ VGAMAPMASK(15);
+ for (i=-1; i<6; i++)
+ memset((byte *)bufferofs+(ylookup[i+SSY])+(SSX>>2),0,46);
+ px=SSX;
+ py=SSY;
+ VW_DrawPropString(" Rise of the Triad (c) 1995 Apogee Version ");
+ VW_DrawPropString(itoa(ROTTMAJORVERSION,&buf[0],10));
+ VW_DrawPropString(".");
+ VW_DrawPropString(itoa(ROTTMINORVERSION,&buf[0],10));
+ px=SSX+13;
+ py=SSY+8;
+ VW_DrawPropString(" Episode ");
+ VW_DrawPropString(itoa(gamestate.episode,&buf[0],10));
+ VW_DrawPropString(" Area ");
+ VW_DrawPropString(itoa(GetLevel(gamestate.episode, gamestate.mapon),&buf[0],10));
+
+ if (screen!=(byte *)bufferofs)
+ bufferofs=tmp;
+ }
+#endif
+
+
+
+ GetFileName (saveLBM);
+ GetPathFromEnvironment( filename, ApogeePath, savename );
+ //
+ memcpy(buffer,screen, iGLOBAL_SCREENWIDTH*iGLOBAL_SCREENHEIGHT); //bna
+ //bna--VL_CopyPlanarPageToMemory(screen,buffer);
+
+ if (saveLBM)
+ {
+ WriteLBMfile (filename, buffer, iGLOBAL_SCREENWIDTH, iGLOBAL_SCREENHEIGHT);
+#if (DEVELOPMENT == 1)
+ while (Keyboard[sc_CapsLock] && Keyboard[sc_C])
+#else
+ while (Keyboard[sc_Alt] && Keyboard[sc_V])
+#endif
+ IN_UpdateKeyboard ();
+ }
+ else
+ {
+ WritePCX (filename, buffer);
+#if (DEVELOPMENT == 1)
+ while (Keyboard[sc_CapsLock] && Keyboard[sc_X])
+#else
+ while (Keyboard[sc_Alt] && Keyboard[sc_C])
+#endif
+ IN_UpdateKeyboard ();
+ }
+
+ SafeFree(buffer);
+ HUD=oldHUD;
+}
+
+//****************************************************************************
+//
+// WritePCX ()
+//
+//****************************************************************************
+
+void WritePCX (char * file, byte * source)
+{
+ PCX_HEADER pcxHDR;
+ byte *tempbuffer;
+ byte pal[0x300];
+ int pcxhandle;
+ int i, j, y;
+ unsigned char c;
+ unsigned char buffer1[GAP_SIZE];
+
+ pcxhandle = SafeOpenWrite (file);
+
+ /* --- init the header that we'll write.
+ * Note: since DPaint never reads & writes at the same time,
+ * it is okay to share the same read & write structure,
+ * unlike in CONVERT.EXE.
+ */
+
+ memset (&pcxHDR, 0, sizeof(PCX_HEADER));
+
+ pcxHDR.manufacturer = 10;
+ pcxHDR.version = 5;
+ pcxHDR.encoding = 1;
+
+ pcxHDR.bitsperpixel = 8; //bpp;
+ pcxHDR.xmin = pcxHDR.ymin = 0;
+ pcxHDR.xmax = iGLOBAL_SCREENWIDTH - 1;
+ pcxHDR.ymax = iGLOBAL_SCREENHEIGHT - 1;
+ pcxHDR.hres = iGLOBAL_SCREENWIDTH; //N_COLUMNS;
+ pcxHDR.vres = iGLOBAL_SCREENHEIGHT; //N_LINES;
+
+ // bytesperline doesn't take into account multiple planes.
+ // Output in same format as bitmap (planar vs packed).
+ //
+ pcxHDR.bytesperline = iGLOBAL_SCREENWIDTH; //bitmap->width;
+
+ pcxHDR.nplanes = 1; //bitmap->planes;
+ pcxHDR.reserved = 0;
+
+ // First 16 colors of our palette info.
+ for (i = 0, j = 0; i < 16; ++i, j += 3) {
+ pcxHDR.colormap[i][0] = (unsigned char)(origpal[j]);
+ pcxHDR.colormap[i][1] = (unsigned char)(origpal[j]+2);
+ pcxHDR.colormap[i][2] = (unsigned char)(origpal[j]+3);
+ }
+
+ //
+ // Write the 128-byte header
+ //
+ SafeWrite(pcxhandle,&pcxHDR, sizeof (PCX_HEADER));
+
+ memset (buffer1, 0, GAP_SIZE);
+
+ SafeWrite (pcxhandle, &buffer1, GAP_SIZE);
+
+ tempbuffer = (byte *) SafeMalloc ((iGLOBAL_SCREENHEIGHT*iGLOBAL_SCREENWIDTH)+4000);
+ bptr = tempbuffer;
+ totalbytes = 0;
+
+ //
+ // Write to a bit-packed file.
+ //
+ for (y = 0; y < iGLOBAL_SCREENHEIGHT; ++y) // for each line in band
+ if (PutBytes (((unsigned char *) (source+(y*iGLOBAL_SCREENWIDTH))),
+ pcxHDR.bytesperline))
+ Error ("Error writing PCX bit-packed line!\n");
+
+ SafeWrite (pcxhandle, tempbuffer, totalbytes);
+
+ //
+ // Write out PCX palette
+ //
+ c = 0x0C;
+
+ for (i = 0; i < 0x300; i++)
+ pal[i] = (*(origpal+i))<<2;
+
+ SafeWrite (pcxhandle, &c, 1);
+ SafeWrite (pcxhandle, &pal[0], 768);
+
+ close (pcxhandle);
+ SafeFree (tempbuffer);
+}
+
+
+//****************************************************************************
+//
+// PutBytes ()
+//
+// Write bytes to a file, handling packing as it goes.
+// Returns : 0 == SUCCESS
+// 1 == FAIL.
+//
+//****************************************************************************
+
+int PutBytes (unsigned char *ptr, unsigned int bytes)
+{
+ unsigned int startbyte, count;
+ char b;
+
+ while (bytes > 0) {
+ // check for a repeating byte value
+ startbyte = *ptr;
+ *ptr++ = 0;
+ --bytes;
+ count = 1;
+ while (*ptr == startbyte && bytes > 0 && count < 63)
+ {
+ *ptr = 0;
+ ++ptr;
+ --bytes;
+ ++count;
+ }
+ // If we can pack the sequence, or if we have to add a
+ // byte before it because the top 2 bits of the value
+ // are 1's, write a packed sequence of 2 bytes.
+ // Otherwise, just write the byte value.
+ //
+ if (count > 1 || (startbyte & 0xc0) == 0xc0)
+ {
+ b = 0xc0 | count;
+
+ *bptr++ = b;
+ totalbytes++;
+ }
+ b = startbyte;
+
+ *bptr++ = b;
+ totalbytes++;
+ }
+ return (0);
+}
+
+
+#endif
+
+
+//****************************************************************************
+//
+// PlayCinematic () - Play intro cinematics
+//
+//****************************************************************************
+
+void PlayCinematic (void)
+{
+
+ if ((tedlevel == true) || (turbo == true))
+ return;
+
+ switch (gamestate.mapon)
+ {
+#if (SHAREWARE == 0)
+ byte pal[768];
+ case 0: // Start of EPISODE 1
+
+ MU_StartSong ( song_cinematic1 );
+ VL_FadeOut (0, 255, 0, 0, 0, 20);
+ VL_ClearBuffer (bufferofs, 0);
+ DrawNormalSprite(0,30,W_GetNumForName("nicolas"));
+ DrawNormalSprite(0,168,W_GetNumForName("oneyear"));
+ FlipPage();
+ memcpy(&pal[0],W_CacheLumpName("nicpal",PU_CACHE, CvtNull, 1),768);
+ VL_NormalizePalette(&pal[0]);
+ VL_FadeIn(0,255,pal,20);
+ I_Delay (60);
+ VL_FadeOut (0, 255, 0, 0, 0, 20);
+ IN_UpdateKeyboard();
+ if (LastScan!=0)
+ {
+ LastScan=0;
+ return;
+ }
+ SD_PlayPitchedSound(SD_LIGHTNINGSND,255,-1500);
+ DoInBetweenCinematic (20, W_GetNumForName("binoculr"), 80,
+ "The HUNT cases an\n"
+ "ancient monastery."
+ );
+ IN_UpdateKeyboard();
+ if (LastScan!=0)
+ {
+ LastScan=0;
+ return;
+ }
+ SD_Play(SD_NMESEESND);
+ DoInBetweenCinematic (20, W_GetNumForName("binosee"), 80,
+ "\"There they are,\" says\n"
+ "Cassatt. \"Let's get back\n"
+ "to the boat and inform HQ.\""
+ );
+ IN_UpdateKeyboard();
+ if (LastScan!=0)
+ {
+ LastScan=0;
+ return;
+ }
+ SD_Play(SD_HIGHGUARD1SEESND);
+ DoInBetweenCinematic (20, W_GetNumForName("boatgard"), 80,
+ "\"The intruders, on that hill!\""
+ );
+ IN_UpdateKeyboard();
+ if (LastScan!=0)
+ {
+ LastScan=0;
+ return;
+ }
+ SD_Play(SD_EXPLODESND);
+ DoInBetweenCinematic (20, W_GetNumForName("boatblow"), 80,
+ "\"There goes our ride home,\"\n"
+ "says Barrett. \"Looks like\n"
+ "the only way out is in....\""
+ );
+ IN_UpdateKeyboard();
+ LastScan=0;
+ break;
+
+ case 8: // Start of EPISODE 2
+ MU_StartSong ( song_cinematic2 );
+ DoInBetweenCinematic (0, W_GetNumForName("epi12"), 1200,
+ "The HUNT makes their way\n"
+ "into the main keep."
+ );
+ IN_UpdateKeyboard();
+ LastScan=0;
+ break;
+
+ case 16: // Start of EPISODE 3
+ MU_StartSong ( song_cinematic1 );
+ DoInBetweenCinematic (20, W_GetNumForName("epi23"), 1200,
+ "The HUNT stands before a pair\n"
+ "of ominous wooden doors.\n"
+ "The sounds of machinery and\n"
+ "servomotors fill the air.\n"
+ );
+ IN_UpdateKeyboard();
+ LastScan=0;
+ break;
+
+ case 24: // Start of EPISODE 4
+ MU_StartSong ( song_cinematic2 );
+ DoInBetweenCinematic (0, W_GetNumForName("epi34"), 1200,
+ "Stairs lead down beneath the\n"
+ "keep. From behind the doors\n"
+ "come the moans of the undead."
+ );
+ IN_UpdateKeyboard();
+ LastScan=0;
+ break;
+#endif
+ }
+}
--- /dev/null
+++ b/rott/rt_main.h
@@ -1,0 +1,178 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// RT_MAIN.H
+//
+//***************************************************************************
+
+#ifndef _rt_main_public
+#define _rt_main_public
+
+#include "develop.h"
+#include "rt_def.h"
+#include "rottnet.h"
+#include "rt_battl.h"
+
+#if (SHAREWARE==0)
+#define STANDARDGAMELEVELS (DATADIR "DARKWAR.RTL")
+#define STANDARDBATTLELEVELS (DATADIR "DARKWAR.RTC")
+#define SUPERROTTBATTLELEVELS (DATADIR "ROTTCD.RTC")
+#define SITELICENSEBATTLELEVELS (DATADIR "ROTTSITE.RTC")
+#else
+#define STANDARDGAMELEVELS (DATADIR "HUNTBGIN.RTL")
+#define STANDARDBATTLELEVELS (DATADIR "HUNTBGIN.RTC")
+#endif
+
+enum
+{ vl_low,
+ vl_medium,
+ vl_high,
+ vl_excessive
+};
+
+// Enum for each version of the game
+typedef enum
+{
+ ROTT_SHAREWARE,
+ ROTT_REGISTERED,
+ ROTT_SUPERCD,
+ ROTT_SITELICENSE
+} version_type;
+
+typedef struct
+{
+ int GodModeTime;
+ int DogModeTime;
+ int ShroomsModeTime;
+ int ElastoModeTime;
+ int AsbestosVestTime;
+ int BulletProofVestTime;
+ int GasMaskTime;
+ int MercuryModeTime;
+
+ int GodModeRespawnTime;
+ int DogModeRespawnTime;
+ int ShroomsModeRespawnTime;
+ int ElastoModeRespawnTime;
+ int AsbestosVestRespawnTime;
+ int BulletProofVestRespawnTime;
+ int GasMaskRespawnTime;
+ int MercuryModeRespawnTime;
+
+} specials;
+
+
+typedef struct
+{
+ unsigned Version;
+ // Variable for which version of the game can be played
+ version_type Product;
+
+ int TimeCount;
+ int frame;
+ int secrettotal,treasuretotal,killtotal;
+ int secretcount,treasurecount,killcount;
+ int supertotal,healthtotal,missiletotal;
+ int supercount,healthcount,missilecount;
+ int democratictotal,planttotal;
+ int democraticcount,plantcount;
+ int dipballs;
+ int difficulty;
+ int violence;
+ int mapon;
+ int score;
+ int episode;
+ int battlemode;
+ int battleoption;
+ int randomseed;
+ boolean teamplay;
+ boolean DODEMOCRATICBONUS1;
+ boolean DOGROUNDZEROBONUS;
+ int autorun;
+
+ // Battle Options
+ battle_type BattleOptions;
+
+ boolean SpawnCollectItems;
+ boolean SpawnEluder;
+ boolean SpawnDeluder;
+ boolean ShowScores;
+ boolean PlayerHasGun[ MAXPLAYERS ];
+ specials SpecialsTimes;
+
+} gametype;
+
+
+extern int doublestep;
+extern boolean tedlevel;
+extern int tedlevelnum;
+extern int tedx;
+extern int tedy;
+extern boolean fizzlein;
+extern int pheight;
+extern int NoSound;
+extern int timelimit;
+extern boolean timelimitenabled;
+extern boolean noecho;
+extern boolean demoexit;
+extern boolean quiet;
+
+extern gametype gamestate;
+extern boolean DebugOk;
+extern boolean newlevel;
+
+void QuitGame( void );
+void PlayCinematic (void);
+void InitCharacter(void);
+void ShutDown ( void );
+void UpdateGameObjects ( void );
+
+#if (WHEREAMI==1)
+extern int programlocation;
+#endif
+
+extern int polltime;
+extern int oldpolltime;
+extern volatile int oldtime;
+void PauseLoop ( void );
+#if SAVE_SCREEN
+extern boolean inhmenu;
+void SaveScreen (boolean saveLBM);
+#endif
+void SetupWads( void );
+
+extern boolean SCREENSHOTS;
+extern boolean MEMORYTEST;
+extern boolean MODEMTEST;
+extern boolean STATICMEMORYTEST;
+extern boolean STATICMEMORYPREVIEWTEST;
+extern boolean COMPUTELEVELSIZE;
+extern boolean MONOPRESENT;
+extern boolean MAPSTATS;
+extern boolean TILESTATS;
+extern boolean HUD;
+#ifdef DOS
+extern boolean SOUNDSETUP;
+#endif
+
+extern char CWD[40];
+
+#endif
--- /dev/null
+++ b/rott/rt_map.c
@@ -1,0 +1,1075 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "rt_def.h"
+#include <string.h>
+
+#ifdef DOS
+#include <conio.h>
+#include <dos.h>
+#endif
+
+#include "sprites.h"
+#include "rt_map.h"
+#include "rt_dr_a.h"
+#include "_rt_map.h"
+#include "isr.h"
+#include "rt_util.h"
+#include "modexlib.h"
+#include "rt_draw.h"
+#include "rt_stat.h"
+#include "z_zone.h"
+#include "w_wad.h"
+#include "rt_main.h"
+#include "rt_playr.h"
+#include "lumpy.h"
+#include "rt_door.h"
+#include "rt_scale.h"
+#include "rt_vid.h"
+#include "rt_in.h"
+#include "rt_ted.h"
+#include "rt_game.h"
+#include "rt_rand.h"
+#include "rt_view.h"
+#include "rt_floor.h"
+#include "engine.h"
+#include "develop.h"
+#include "rt_spbal.h"
+#include "rt_menu.h"
+#include "rt_net.h"
+#include "rt_str.h"
+#include "watcom.h"
+//MED
+#include "memcheck.h"
+
+//===========================================================================
+
+
+static int tilesize;
+static fixed xscale;
+static fixed yscale;
+static int mapscale=2;
+static int oldw,oldh;
+static byte * skytile;
+static int mapcolor=8;
+
+typedef struct PType {
+ int x;
+ int y;
+} Ptype;
+
+static Ptype arrows[8][7]=
+{
+ { {4,2}, {2,4}, {2,3}, {0,3}, {0,1}, {2,1}, {2,0} },
+ { {4,0}, {4,3}, {3,2}, {1,4}, {0,3}, {2,1}, {1,0} },
+ { {2,0}, {4,2}, {3,2}, {3,4}, {1,4}, {1,2}, {0,2} },
+ { {0,0}, {3,0}, {2,1}, {4,3}, {3,4}, {1,2}, {0,3} },
+ { {0,2}, {2,0}, {2,1}, {4,1}, {4,3}, {2,3}, {2,4} },
+ { {0,4}, {0,1}, {1,2}, {3,0}, {4,1}, {2,3}, {3,4} },
+ { {2,4}, {0,2}, {1,2}, {1,0}, {3,0}, {3,2}, {4,2} },
+ { {4,4}, {1,4}, {2,3}, {0,1}, {1,0}, {3,2}, {4,1} },
+};
+
+void DrawMap_MaskedShape (int x, int y, int lump, int type);
+
+void CheatMap( void )
+{
+ int i;
+ int j;
+ statobj_t * temp;
+ objtype * a;
+
+ for(temp=FIRSTSTAT; temp; temp=temp->statnext)
+ temp->flags|=FL_SEEN;
+
+ for(a=FIRSTACTOR; a; a=a->next)
+ a->flags|=FL_SEEN;
+
+
+ for (j=0; j<MAPSIZE; j++)
+ for (i=0; i<MAPSIZE; i++)
+ mapseen[i][j]=1;
+}
+
+
+void FixMapSeen( void )
+{
+ int i;
+ int j;
+
+ for (j=0; j<MAPSIZE; j++)
+ for (i=0; i<MAPSIZE; i++)
+ if (!mapseen[i][j])
+ {
+ if (i==0 && ((mapseen[i][j+1] && j<MAPSIZE-1) || (mapseen[i][j-1] && j>0)) && mapseen[i+1][j])
+ mapseen[i][j]=1;
+ else if (i==MAPSIZE-1 && mapseen[i-1][j] && ((mapseen[i][j+1] && j<MAPSIZE-1) || (mapseen[i][j-1] && j>0)))
+ mapseen[i][j]=1;
+ else if (j==0 && ((mapseen[i+1][j] && i<MAPSIZE-1) || (mapseen[i-1][j] && i>0)) && mapseen[i][j+1])
+ mapseen[i][j]=1;
+ else if (j==MAPSIZE-1 && mapseen[i][j-1] && ((mapseen[i+1][j] && i<MAPSIZE-1) || (mapseen[i-1][j] && i>0)))
+ mapseen[i][j]=1;
+ else if (
+ ( ((mapseen[i-1][j]) && (mapseen[i][j+1]) && (!(tilemap[i-1][j+1])))
+ ||
+ ((mapseen[i-1][j]) && (mapseen[i][j-1]) && (!(tilemap[i-1][j-1])))
+ ||
+ ((mapseen[i+1][j]) && (mapseen[i][j+1]) && (!(tilemap[i+1][j+1])))
+ ||
+ ((mapseen[i+1][j]) && (mapseen[i][j-1]) && (!(tilemap[i+1][j-1])))
+ ) &&
+ tilemap[i][j])
+ mapseen[i][j]=1;
+ }
+}
+
+
+/*
+=======================
+=
+= DrawMap_Wall
+=
+=======================
+*/
+
+void DrawMap_Wall (int x, int y, int tile)
+{
+ byte * buf;
+ int p;
+ byte * b;
+ byte * source;
+ byte * s;
+ int i;
+
+ x*=tilesize;
+ y*=tilesize;
+
+#ifdef DOS
+ buf=(byte *)bufferofs+ylookup[y]+(x>>2);
+#else
+ buf=(byte *)bufferofs+ylookup[y]+x;
+#endif
+
+ source=W_CacheLumpNum(tile,PU_CACHE, CvtNull, 1);
+
+#ifdef DOS
+ for (p=0; p<4; p++)
+#endif
+ {
+#ifdef DOS
+ VGAWRITEMAP(p);
+ s=source+((p*hp_srcstep)>>10);
+#else
+ s=source;
+#endif
+ b=buf;
+
+#ifdef DOS
+ for (i=p; i<tilesize; i+=4,b++)
+#else
+ for (i=0; i<tilesize; i++,b++)
+#endif
+ {
+ DrawMapPost(tilesize,s,b);
+#ifdef DOS
+ s+=(hp_srcstep>>8);
+#else
+ s+=(hp_srcstep>>10);
+#endif
+ }
+ }
+}
+
+/*
+=======================
+=
+= DrawMap_AnimatedWall
+=
+=======================
+*/
+
+void DrawMap_AnimatedWall (int x, int y, int tile)
+{
+ DrawMap_Wall(x,y,animwalls[tile].texture);
+}
+
+/*
+=======================
+=
+= DrawMap_SkyTile
+=
+=======================
+*/
+
+void DrawMap_SkyTile (int x, int y)
+{
+ byte * buf;
+ int p;
+ byte * b;
+ byte * s;
+ int i;
+
+ x*=tilesize;
+ y*=tilesize;
+
+#ifdef DOS
+ buf=(byte *)bufferofs+ylookup[y]+(x>>2);
+#else
+ buf=(byte *)bufferofs+ylookup[y]+x;
+#endif
+
+#ifdef DOS
+ for (p=0; p<4; p++)
+#endif
+ {
+#ifdef DOS
+ VGAWRITEMAP(p);
+ s=skytile+((p*hp_srcstep)>>10);
+#else
+ s=skytile;
+#endif
+
+ b=buf;
+#ifdef DOS
+ for (i=p; i<tilesize; i+=4,b++)
+#else
+ for (i=0; i<tilesize; i++,b++)
+#endif
+ {
+ DrawMapPost(tilesize,s,b);
+#ifdef DOS
+ s+=(hp_srcstep>>8);
+#else
+ s+=(hp_srcstep>>10);
+#endif
+ }
+ }
+}
+
+/*
+=======================
+=
+= DrawMap_MaskedWall
+=
+=======================
+*/
+
+void DrawMap_MaskedWall (int x, int y, int tile)
+{
+ if (IsPlatform(maskobjlist[tile]->tilex,maskobjlist[tile]->tiley))
+ {
+ if (!(maskobjlist[tile]->flags&MW_ABOVEPASSABLE))
+ DrawMap_MaskedShape(x,y,maskobjlist[tile]->toptexture,0);
+ else if (!(maskobjlist[tile]->flags&MW_BOTTOMPASSABLE))
+ DrawMap_MaskedShape(x,y,maskobjlist[tile]->bottomtexture,1);
+ else
+ DrawMap_MaskedShape(x,y,maskobjlist[tile]->midtexture,0);
+ }
+ else
+ {
+ DrawMap_MaskedShape(x,y,maskobjlist[tile]->bottomtexture,1);
+ }
+}
+
+/*
+=======================
+=
+= DrawMap_Door
+=
+=======================
+*/
+
+void DrawMap_Door (int x, int y, int tile)
+{
+ if (
+ (doorobjlist[tile]->lock > 0) &&
+ (doorobjlist[tile]->lock <= 4)
+ )
+ DrawMap_Wall(x,y,W_GetNumForName("lock1")+doorobjlist[tile]->lock-1);
+ else if (doorobjlist[tile]->texture==doorobjlist[tile]->basetexture)
+ DrawMap_Wall(x,y,doorobjlist[tile]->texture);
+ else
+ DrawMap_MaskedShape(x,y,doorobjlist[tile]->texture,0);
+}
+
+/*
+=======================
+=
+= DrawMap_PushWall
+=
+=======================
+*/
+
+void DrawMap_PushWall (int x, int y, pwallobj_t * pw)
+{
+ if (pw->texture&0x1000)
+ DrawMap_AnimatedWall(x,y,pw->texture&0x3ff);
+ else
+ DrawMap_Wall(x,y,pw->texture&0x3ff);
+}
+
+/*
+=======================
+=
+= DrawMap_Actor
+=
+=======================
+*/
+
+void DrawMap_Actor (int x, int y, objtype * a)
+{
+ int translucent;
+
+ if (!(a->flags&FL_SEEN))
+ return;
+
+ translucent=0;
+ if (a->flags&FL_TRANSLUCENT)
+ translucent=1;
+ DrawMap_MaskedShape(x,y,a->shapenum+shapestart,translucent);
+}
+
+/*
+=======================
+=
+= DrawMap_Sprite
+=
+=======================
+*/
+
+void DrawMap_Sprite (int x, int y, statobj_t * s)
+{
+ int translucent;
+
+ if (!(s->flags&FL_SEEN))
+ return;
+
+ translucent=0;
+ if (s->flags&FL_TRANSLUCENT)
+ translucent=1;
+ DrawMap_MaskedShape(x,y,s->shapenum+shapestart,translucent);
+}
+
+/*
+=======================
+=
+= DrawMap_MaskedShape
+=
+=======================
+*/
+
+void DrawMap_MaskedShape (int x, int y, int lump, int type)
+{
+
+ // Calculate center coordinates for sprites
+
+ x*=tilesize;
+ y*=tilesize;
+ x+=tilesize>>1;
+ y+=tilesize>>1;
+ DrawPositionedScaledSprite(x,y,lump,tilesize,type);
+}
+
+/*
+=======================
+=
+= DrawMap_PlayerArrow
+=
+=======================
+*/
+
+/* Indices: mapscale, reduced coordinate */
+static const int arrowscale[4][5] =
+{ { 1,17,32,47,63}, /* Mapscale 0: 64 pixels/sprite */
+ { 1, 9,16,23,31}, /* Mapscale 1: 32 pixels/sprite */
+ { 1, 5, 8,11,15}, /* Mapscale 2: 16 pixels/sprite */
+ { 1, 3, 4, 5, 7}
+}; /* Mapscale 3: 8 pixels/sprite */
+
+void DrawMap_PlayerArrow (int x, int y, int dir)
+{
+ int i;
+
+ x*=tilesize;
+ y*=tilesize;
+
+ /* You can't draw a 4x4 arrow */
+ if(mapscale == 4)
+ {
+ VL_Bar(x+1,y+1,2,2,244);
+ return;
+ }
+
+ for (i=0; i<6; i++)
+ {
+ VL_DrawLine (arrowscale[mapscale][arrows[dir][i].x]+x,
+ arrowscale[mapscale][arrows[dir][i].y]+y,
+ arrowscale[mapscale][arrows[dir][i+1].x]+x,
+ arrowscale[mapscale][arrows[dir][i+1].y]+y,
+ 244
+ );
+ }
+ VL_DrawLine ( arrowscale[mapscale][arrows[dir][6].x]+x,
+ arrowscale[mapscale][arrows[dir][6].y]+y,
+ arrowscale[mapscale][arrows[dir][0].x]+x,
+ arrowscale[mapscale][arrows[dir][0].y]+y,
+ 244
+ );
+}
+
+/*
+=======================
+=
+= DrawMap_Player
+=
+=======================
+*/
+
+void DrawMap_Player (int x, int y)
+{
+ if (player->flags&FL_SHROOMS)
+ DrawMap_PlayerArrow(x,y,( RandomNumber("DrawMap_PLAYER",0)>>5) );
+ else
+ DrawMap_PlayerArrow(x,y,( ( (player->angle+(FINEANGLES/16)) & (FINEANGLES-1) ) >>8) );
+ DrawMap_MaskedShape(x,y,player->shapenum+shapestart,0);
+}
+
+/*
+=======================
+=
+= DrawMap
+=
+=======================
+*/
+
+void DrawMap( int cx, int cy )
+{
+ fixed x,y;
+ statobj_t * s;
+ objtype * a;
+ int i,j;
+ int mapx,mapy;
+ int wall;
+
+ // Clear buffer
+
+ VL_ClearBuffer (bufferofs, egacolor[mapcolor]);
+
+ x=cx>>16;
+ y=cy>>16;
+
+ // Draw Walls,Doors,maskedwalls,animatingwalls
+
+ for (j=0; j<yscale; j++)
+ {
+
+ // Don't go off the bottom of the map
+
+ mapy=j+y;
+
+ if (mapy<0)
+ continue;
+
+ if (mapy>127)
+ break;
+
+ for (i=0; i<xscale; i++)
+ {
+
+ // Don't go off the right side of the map
+
+ mapx=i+x;
+
+ if (mapx<0)
+ continue;
+
+ if (mapx>127)
+ break;
+
+ if ((mapx==player->tilex ) && (mapy==player->tiley))
+ {
+ DrawMap_Player(i,j);
+ continue;
+ }
+
+ wall=tilemap[mapx][mapy];
+
+ // Check for absence of wall
+
+ if (wall)
+ {
+
+ if (!mapseen[mapx][mapy])
+ continue;
+
+ // Check to see if it is a door or masked wall
+
+ if (wall&0x8000)
+ {
+ if (wall&0x4000)
+ {
+ // Must be a masked wall
+ DrawMap_MaskedWall(i,j,wall&0x3ff);
+ }
+ else
+ {
+ // Must be a door
+ DrawMap_Door(i,j,wall&0x3ff);
+ }
+ }
+
+ // Check to see if it is an animating wall
+
+ else if (wall&0x1000)
+ {
+ DrawMap_AnimatedWall(i,j,wall&0x3ff);
+ }
+ else if (IsWindow(mapx,mapy))
+ {
+ if (sky!=0)
+ DrawMap_SkyTile(i,j);
+ else
+ Error("Trying to draw a sky on a level without sky\n");
+ }
+ else
+ {
+ // Must be a normal wall or a wall with something above
+ DrawMap_Wall(i,j,wall&0x3ff);
+ }
+ }
+ else
+ {
+ a=actorat[mapx][mapy];
+
+ // Check for absence of actor
+
+ if (a)
+ {
+ switch(a->which)
+ {
+ case PWALL:
+ if (!mapseen[mapx][mapy])
+ continue;
+ DrawMap_PushWall(i,j,(pwallobj_t *)a);
+ break;
+ case ACTOR:
+ DrawMap_Actor(i,j,a);
+ break;
+ case SPRITE:
+ DrawMap_Actor(i,j,a);
+ break;
+ default:
+ SoftError("Unable to resolve actorat at x=%d y=%d which=%d\n",mapx,mapy,a->which);
+ break;
+ }
+ }
+ else
+ {
+ s=sprites[mapx][mapy];
+
+ // Check for absence of sprite
+
+ if (s)
+ {
+ DrawMap_Sprite(i,j,s);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+
+/*
+=======================
+=
+= SetupFullMap
+=
+=======================
+*/
+
+void SetupFullMap( void )
+{
+ int ty;
+ pic_t *pic;
+
+ // Fill in backgrounds
+
+ pic = (pic_t *) W_CacheLumpNum (W_GetNumForName ("mmbk"), PU_CACHE, Cvt_pic_t, 1);
+ VWB_DrawPic (0, 0, pic);
+ CheckHolidays();
+
+ // Clear area for map
+
+#ifdef DOS
+ VGAMAPMASK(15);
+ for (ty=37; ty<37+127; ty++)
+ memset((byte *)bufferofs+ylookup[ty]+24,0,32);
+#else
+ for (ty=37; ty<37+127; ty++)
+ memset((byte *)bufferofs+ylookup[ty]+96,0,128);
+#endif
+}
+
+/*
+=======================
+=
+= DrawFullMap
+=
+=======================
+*/
+
+void DrawFullMap( void )
+{
+ statobj_t * s;
+ objtype * a;
+ int mapx,mapy;
+ int wall;
+ byte * buf;
+
+ SetupFullMap();
+
+ // Draw Walls,Doors,maskedwalls,animatingwalls
+
+ for (mapx=0; mapx<mapwidth; mapx++)
+ {
+#ifdef DOS
+ VGAWRITEMAP(mapx&3);
+ buf=(byte *)bufferofs+ylookup[37]+((96+mapx)>>2);
+#else
+ buf=(byte *)bufferofs+ylookup[37]+((96+mapx));
+#endif
+
+#ifdef DOS
+ for (mapy=0; mapy<mapheight; mapy++,buf+=iGLOBAL_SCREENBWIDE)
+#else
+ for (mapy=0; mapy<mapheight; mapy++,buf+=iGLOBAL_SCREENWIDTH)
+#endif
+ {
+ if ((mapx==player->tilex ) && (mapy==player->tiley))
+ {
+ *buf=egacolor[MAP_PLAYERCOLOR];
+ continue;
+ }
+
+ wall=tilemap[mapx][mapy];
+
+ // Check for absence of wall
+
+ if (wall)
+ {
+
+ if (!mapseen[mapx][mapy])
+ continue;
+
+ // Check to see if it is a door or masked wall
+
+ if (wall&0x8000)
+ {
+ if (wall&0x4000)
+ {
+ // Must be a maskedwall
+ *(buf)=egacolor[MAP_MWALLCOLOR];
+ }
+ else
+ {
+ // Must be a door
+ *(buf)=egacolor[MAP_DOORCOLOR];
+ }
+ }
+
+ // Check to see if it is an animating wall
+
+ else if (wall&0x1000)
+ {
+ *(buf)=egacolor[MAP_AWALLCOLOR];
+ }
+ else if (IsWindow(mapx,mapy))
+ {
+ if (sky!=0)
+ *(buf)=egacolor[MAP_SKYCOLOR];
+ else
+ Error("Trying to draw a sky on a level without sky\n");
+ }
+ else
+ {
+ // Must be a normal wall or a wall with something above
+ *(buf)=egacolor[MAP_WALLCOLOR];
+ }
+ }
+ else
+ {
+ a=actorat[mapx][mapy];
+
+ // Check for absence of actor
+
+ if (a)
+ {
+ switch(a->which)
+ {
+ case PWALL:
+ if (!mapseen[mapx][mapy])
+ continue;
+ *(buf)=egacolor[MAP_PWALLCOLOR];
+ break;
+ case ACTOR:
+ if (a->flags&FL_SEEN)
+ {
+ if (a->obclass==inertobj)
+ *(buf)=egacolor[MAP_SPRITECOLOR];
+ else
+ *(buf)=egacolor[MAP_ACTORCOLOR];
+ }
+ break;
+ case SPRITE:
+ if (a->flags&FL_SEEN)
+ *(buf)=egacolor[MAP_SPRITECOLOR];
+ break;
+ default:
+ SoftError("Unable to resolve actorat at x=%d y=%d which=%d\n",mapx,mapy,a->which);
+ break;
+ }
+ }
+ else
+ {
+ s=sprites[mapx][mapy];
+
+ // Check for absence of sprite
+
+ if (s && (s->flags&FL_SEEN))
+ {
+ *(buf)=egacolor[MAP_SPRITECOLOR];
+ }
+ }
+ }
+ }
+ }
+ FlipPage();
+}
+
+/*
+=======================
+=
+= DrawMapInfo
+=
+=======================
+*/
+
+void DrawMapInfo ( void )
+{
+ char temp[80];
+ int width,height;
+
+ CurrentFont=tinyfont;
+
+ PrintX = 2;
+ PrintY = 2;
+ strcpy (&temp[0], &(LevelName[0]));
+ US_MeasureStr (&width, &height, "%s", &temp[0]);
+
+ VWB_TBar (0, 0, 320, height+4);
+
+ US_BufPrint (&temp[0]);
+
+ strcpy (&temp[0], "TAB=EXIT");
+ US_MeasureStr (&width, &height, "%s", &temp[0]);
+
+ PrintX = 316-width;
+ PrintY = 2;
+
+ US_BufPrint (&temp[0]);
+
+ strcpy (&temp[0], "< > CHANGE BACKGROUND COLOR");
+ US_MeasureStr (&width, &height, "%s", &temp[0]);
+
+ PrintX = (320-width)>>1;
+ PrintY = 2;
+
+ US_BufPrint (&temp[0]);
+}
+
+/*
+=======================
+=
+= SetupMapScale
+=
+=======================
+*/
+
+void SetupMapScale( int s )
+{
+ mapscale=s;
+ tilesize=64>>mapscale;
+ xscale=320/tilesize;
+ yscale=200/tilesize;
+ hp_srcstep=0x10000<<mapscale;
+}
+
+
+/*
+=======================
+=
+= ChangeMapScale
+=
+=======================
+*/
+
+void ChangeMapScale( int * newx, int * newy, int newmapscale )
+{
+ if (newmapscale<0)
+ return;
+ if (newmapscale>FULLMAP_SCALE)
+ return;
+
+ if (newmapscale==FULLMAP_SCALE)
+ DrawFullMap();
+
+ *newx=*newx+(xscale<<15);
+ *newy=*newy+(yscale<<15);
+
+ SetupMapScale(newmapscale);
+
+ *newx=*newx-(xscale<<15);
+ *newy=*newy-(yscale<<15);
+}
+
+
+/*
+=======================
+=
+= SetupMapper
+=
+=======================
+*/
+void SetupMapper ( void )
+{
+ FixMapSeen();
+
+ tics=0;
+ oldw=viewwidth;
+ oldh=viewheight;
+ viewwidth=320;
+ viewheight=200;
+
+ if (sky!=0)
+ {
+ skytile=SafeMalloc(64*64);
+ MakeSkyTile(skytile);
+ }
+}
+
+/*
+=======================
+=
+= ShutdownMapper
+=
+=======================
+*/
+void ShutdownMapper ( void )
+{
+ VL_ClearVideo (0);
+ viewwidth=oldw;
+ viewheight=oldh;
+ SetupScreen (true);
+
+ if (sky!=0)
+ SafeFree(skytile);
+ if (mouseenabled && MousePresent)
+ PollMouseMove();
+}
+
+/*
+=======================
+=
+= DoMap
+=
+=======================
+*/
+
+void DoMap (int cx, int cy)
+{
+ int x,y;
+ int dx;
+ int dy;
+ boolean done;
+ int quitkey;
+ ControlInfo control;
+
+ EnableScreenStretch();//bna++
+
+ ShutdownClientControls();
+
+ done=false;
+
+ while (Keyboard[sc_Tab])
+ IN_UpdateKeyboard ();
+ if (SpaceBallPresent && spaceballenabled)
+ {
+ while (GetSpaceBallButtons()) ;
+ }
+
+ x=(cx-(xscale>>1))<<16;
+ y=(cy-(yscale>>1))<<16;
+
+ SetupMapper();
+
+ transparentlevel=25;
+
+ ChangeMapScale(&x, &y, mapscale);
+
+ while (done==false)
+ {
+ IN_UpdateKeyboard ();
+ if ((Keyboard[sc_Tab]) || (Keyboard[sc_Escape]))
+ {
+ if (Keyboard[sc_Tab])
+ quitkey=sc_Tab;
+ else
+ quitkey=sc_Escape;
+ done=true;
+ }
+ if (SpaceBallPresent && spaceballenabled)
+ {
+ if (GetSpaceBallButtons()!=0)
+ done=true;
+ }
+ if ( Keyboard[ sc_Home ] )
+ {
+ x=(cx-(xscale>>1))<<16;
+ y=(cy-(yscale>>1))<<16;
+ }
+ dx=0;
+ dy=0;
+ if (mapscale==FULLMAP_SCALE)
+ CalcTics();
+ else
+ {
+ DrawMap(x,y);
+ DrawMapInfo ();
+ FlipPage();
+ CalcTics();
+ DoSprites();
+ AnimateWalls();
+ }
+ ReadAnyControl (&control);
+ if ((Keyboard[sc_PgUp]) ||
+ (Keyboard[sc_Plus]) ||
+ (control.button1))
+ {
+ ChangeMapScale(&x, &y, mapscale+1);
+ while(Keyboard[sc_PgUp])
+ IN_UpdateKeyboard ();
+ while(Keyboard[sc_Plus])
+ IN_UpdateKeyboard ();
+ while(control.button1)
+ ReadAnyControl (&control);
+ }
+ if ((Keyboard[sc_PgDn]) ||
+ (Keyboard[sc_Minus]) ||
+ (control.button0))
+ {
+ ChangeMapScale(&x, &y, mapscale-1);
+ while(Keyboard[sc_PgDn])
+ IN_UpdateKeyboard ();
+ while(Keyboard[sc_Minus])
+ IN_UpdateKeyboard ();
+ while(control.button0)
+ ReadAnyControl (&control);
+ }
+ if (Keyboard[sc_CapsLock] && Keyboard[sc_C])
+ {
+ inhmenu=true;
+ SaveScreen (true);
+ inhmenu=false;
+ }
+ if (Keyboard[sc_CapsLock] && Keyboard[sc_X])
+ {
+ inhmenu=true;
+ SaveScreen (false);
+ inhmenu=false;
+ }
+ if (Keyboard[sc_Comma])
+ {
+ if (mapcolor>0)
+ mapcolor--;
+ while(Keyboard[sc_Comma])
+ IN_UpdateKeyboard ();
+ }
+ if (Keyboard[sc_Period])
+ {
+ if (mapcolor<15)
+ mapcolor++;
+ while(Keyboard[sc_Period])
+ IN_UpdateKeyboard ();
+ }
+ if (mapscale!=FULLMAP_SCALE)
+ {
+ if (control.dir==dir_East)
+ dx=(tics<<17)/(5-mapscale);
+ if (control.dir==dir_West)
+ dx=-(tics<<17)/(5-mapscale);
+ if (control.dir==dir_South)
+ dy=(tics<<17)/(5-mapscale);
+ if (control.dir==dir_North)
+ dy=-(tics<<17)/(5-mapscale);
+ }
+#if (DEVELOPMENT == 1)
+ if (Keyboard[sc_M])
+ {
+ CheatMap();
+ ChangeMapScale( &x, &y, mapscale );
+ }
+#endif
+
+ x+=dx;
+ y+=dy;
+
+ if (x>0x7effff)
+ x=0x7effff;
+ else if (x<-(xscale<<15))
+ x=-(xscale<<15);
+ if (y>0x7effff)
+ y=0x7effff;
+ else if (y<-(yscale<<15))
+ y=-(yscale<<15);
+ }
+
+ if ( playstate == ex_stillplaying ) {//bna++
+ pic_t *shape;
+ shape = ( pic_t * )W_CacheLumpName( "backtile", PU_CACHE, Cvt_pic_t, 1 );
+ DrawTiledRegion( 0, 16, iGLOBAL_SCREENWIDTH, iGLOBAL_SCREENHEIGHT - 32, 0, 16, shape );//bna++
+ DisableScreenStretch();//dont strech when we go BACK TO GAME
+ VW_UpdateScreen ();
+ DrawPlayScreen(true);//repaint ammo and life stat
+
+ }
+ while (Keyboard[quitkey])
+ IN_UpdateKeyboard ();
+
+ LastScan=0;
+ Keyboard[sc_Escape]=0;
+ Keyboard[sc_Tab]=0;
+
+ ShutdownMapper();
+
+ StartupClientControls();
+}
+
--- /dev/null
+++ b/rott/rt_map.h
@@ -1,0 +1,32 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// RT_MAP.C
+//
+//***************************************************************************
+
+#ifndef _rt_map_public
+#define _rt_map_public
+
+void DoMap(int x, int y);
+void CheatMap( void );
+
+#endif
--- /dev/null
+++ b/rott/rt_menu.c
@@ -1,0 +1,10510 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//******************************************************************************
+//
+// RT_MENU.C
+// Contains the menu stuff!
+//
+//******************************************************************************
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <string.h>
+#include <ctype.h>
+
+#if PLATFORM_DOS
+#include <conio.h>
+#include <dos.h>
+#include <io.h>
+#elif PLATFORM_UNIX
+#include <unistd.h>
+#include "SDL.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "rt_def.h"
+#include "_rt_menu.h"
+#include "rt_menu.h"
+#include "rt_sound.h"
+#include "fx_man.h"
+#include "rt_build.h"
+#include "rt_in.h"
+#include "isr.h"
+#include "z_zone.h"
+#include "w_wad.h"
+#include "rt_util.h"
+#include "rt_main.h"
+#include "rt_playr.h"
+#include "rt_rand.h"
+#include "rt_game.h"
+#include "rt_floor.h"
+#include "rt_draw.h"
+#include "rt_view.h"
+#include "rt_str.h"
+#include "rt_vid.h"
+#include "rt_ted.h"
+#include "rt_com.h"
+#include "lumpy.h"
+#include "rt_cfg.h"
+#include "version.h"
+#include "modexlib.h"
+#include "rt_msg.h"
+#include "rt_net.h"
+#include "rt_spbal.h"
+#include "rt_scale.h"
+
+#include "rt_battl.h"
+#include "develop.h"
+//MED
+#include "memcheck.h"
+
+
+//******************************************************************************
+//
+// GLOBALS
+//
+//******************************************************************************
+
+#define DELAYAMT 2
+
+#define SNDCARDS 12
+
+#define CP_NO 0
+#define CP_ESC -1
+#define CP_YES 1
+
+int CP_Acknowledge;
+
+boolean POK = false;
+char pword[ 13 ];
+
+boolean ingame = false;
+boolean inmenu = false;
+boolean pickquick = false;
+boolean NewGame = false;
+
+//
+// Global window coords
+//
+int PrintX;
+int PrintY;
+int WindowX;
+int WindowY;
+int WindowH = 160;
+int WindowW;
+
+int px;
+int py;
+int bufferheight;
+int bufferwidth;
+
+cfont_t *IFont;
+font_t *CurrentFont;
+font_t *newfont1;
+font_t *smallfont;
+font_t *bigfont;
+font_t *tinyfont;
+
+boolean loadedgame = false;
+
+battle_type BATTLE_Options[ battle_NumBattleModes ];
+
+int quicksaveslot=-1;
+
+//******************************************************************************
+//
+// LOCALS
+//
+//******************************************************************************
+
+char order[ 21 ] = {
+ di_west, di_east, di_north, di_south, bt_run, bt_use, bt_attack,
+ bt_strafe, bt_strafeleft, bt_straferight, bt_lookup, bt_lookdown,
+ bt_aimbutton, bt_horizonup, bt_horizondown, bt_swapweapon, bt_dropweapon,
+ bt_turnaround, bt_autorun, bt_message, bt_directmsg
+};
+
+// bt_pistol, bt_dualpistol, bt_mp40, bt_missileweapon, bt_recordsound,
+
+#define RETURNVAL 100
+
+static boolean loadsavesound = false;
+static int numdone;
+
+static char *endStrings[ 7 ] =
+{
+ "Press Y to reformat \nand install Windows.\0\0",
+ "Press Y to activate \nguillotine.\0\0",
+ "Press Y to release \nthe cyanide gas.\0\0",
+ "Press Y to open \ntrap door.\0\0",
+ "Press Y to drive your \ncar off the cliff.\0\0",
+ "Press Y to pull \nyour plug.\0\0",
+ "Press Y to activate \nelectric chair.\0\0"
+};
+
+static char *BattleModeDescriptions[ battle_NumBattleModes - 1 ] =
+{
+ "Kill your enemies! Don't get killed! Kill some more!",
+ "Score more points for more difficult kills.",
+ "Collect the most triads to win the game. Whoopee!",
+ "Collect triads to win the game--this time with weapons!",
+ "Armed hunters vs. unarmed prey--then the tables are turned!",
+ "Tag your enemies. Run away. Lowest points wins.",
+ "Chase roving 'Eluders'--tag them for points.",
+ "Use weapons to destroy roving Eluder triads for points.",
+ "Capture the opposing team's triad while guarding your own."
+};
+
+static char *BattleOptionDescriptions[ 9 ] =
+{
+ "Adjust the Gravitational Constant of the game universe!",
+ "Adjust the top speed for all players in the game",
+ "Adjust the amount of ammo in all missile weapons",
+ "Adjust the hit points of all players in the game",
+ "Radically change the way the game plays",
+ "Adjust the light characteristics of the game",
+ "Adjust the point goal of the game",
+ "Adjust the damage done by environment dangers",
+ "Adjust the time limit for the game"
+};
+
+static char *GravityOptionDescriptions[ 3 ] =
+{
+ "Similar to gravity on the moon",
+ "Normal Gravity (9.81 m/s^2 !)",
+ "Similar to gravity on Jupiter"
+};
+
+static char *SpeedOptionDescriptions[ 2 ] =
+{
+ "Player speeds are determined by character",
+ "All players can move at the fastest possible speed"
+};
+
+static char *AmmoOptionDescriptions[ 3 ] =
+{
+ "One piece of ammo per missile weapon",
+ "Normal ammo for all missile weapons",
+ "Infinite ammo for all missile weapons"
+};
+
+static char *HitPointsOptionDescriptions[ 7 ] =
+{
+ "One hit point for each player",
+ "25 hit points for each player",
+ "Hit points determined by character",
+ "100 hit points for each player",
+ "250 hit points for each player (default)",
+ "500 hit points for each player",
+ "4000 hit points for each player",
+};
+
+static char *RadicalOptionDescriptions[ 8 ] =
+{
+ "Control spawning of environment dangers",
+ "Control spawning of health items",
+ "Control spawning of missile weapons",
+ "Spawn mines instead of health items",
+ "Objects reappear a short time after being picked up",
+ "Missile weapons remain when picked up",
+ "Weapons are chosen randomly at the start of the game",
+ "Killing yourself or a team member counts as a suicide"
+};
+
+static char *LightLevelOptionDescriptions[ 6 ] =
+{
+ "Very dark, cave-like",
+ "Lighting determined by level design",
+ "Full brightness",
+ "Bright with fog",
+ "Periodic lighting (voobing)",
+ "Dark with lightning"
+};
+
+static char *PointGoalOptionDescriptions[ 9 ] =
+{
+ "One Point/Kill",
+ "5 Points/Kills",
+ "11 Points/Kills",
+ "21 Points/Kills",
+ "50 Points/Kills",
+ "100 Points/Kills",
+ "Random Points/Kills",
+ "Random Points/Kills but goal is not revealed",
+ "Infinite Points/Kills"
+};
+
+static char *DangerDamageOptionDescriptions[ 3 ] =
+{
+ "Environmental dangers' damage is relatively low",
+ "Environmental dangers' damage normal",
+ "One touch and you are dead!"
+};
+
+static char *TimeLimitOptionDescriptions[ 8 ] =
+{
+ "One Minute",
+ "2 Minutes",
+ "5 Minutes",
+ "10 Minutes",
+ "21 Minutes",
+ "30 Minutes",
+ "99 Minutes",
+ "No Time Limit"
+};
+
+
+static char *BattleModeNames[ battle_NumBattleModes - 1 ] =
+{
+ "NORMAL COMM-BAT", "SCORE MORE", "COLLECTOR", "SCAVENGER",
+ "HUNTER", "TAG", "ELUDER", "DELUDER", "CAPTURE THE TRIAD"
+};
+
+static int OptionNums[ 12 ] =
+{
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
+};
+
+static int HitPointNums[ 7 ] =
+{
+ 1, 25, bo_character_hitpoints, 100, 250, 500, 4000
+};
+
+static int KillNums[ 9 ] =
+{
+ 1, 5, 11, 21, 50, 100, bo_kills_random,
+ bo_kills_blind, bo_kills_infinite
+};
+
+static int GravityNums[ 3 ] =
+{
+ LOW_GRAVITY, NORMAL_GRAVITY, HIGH_GRAVITY
+};
+
+static int TimeLimitNums[ 8 ] =
+{
+ 1, 2, 5, 10, 21, 30, 99, bo_time_infinite
+};
+
+static int DangerNums[ 3 ] =
+{
+ bo_danger_low, bo_danger_normal, bo_danger_kill
+};
+
+static int MenuNum = 0;
+static int handlewhich;
+static int CSTactive = 0;
+static boolean INFXSETUP = false;
+static int MaxVoices;
+static int MaxBits;
+static int MaxChannels;
+
+//
+// MENU CURSOR SHAPES
+//
+
+#define MAXCURSORNUM 24
+
+static int cursorwidth;
+static int cursorheight;
+static int yinc;
+
+static char *FontNames[] = { "itnyfont", "ifnt", "sifont", "lifont" };
+static int FontSize[] = { 6, 7, 9, 14 };
+static char *SmallCursor = "smallc01";
+static char *LargeCursor = "cursor01";
+static char *CursorLump = "cursor01";
+static int CursorNum = 0;
+static int CursorFrame[ MAXCURSORNUM ] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3,
+ 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1
+};
+
+typedef enum
+{
+ MOUSEENABLE,
+ JOYENABLE,
+ USEPORT2,
+ PADENABLE,
+ SPACEBALLENABLE,
+ CYBERMANENABLE,
+ THRESSENS,
+ MOUSESENS,
+ CUSTOMIZE
+} controltypes;
+
+
+static char *playerwadname[] =
+{
+ "cass1", "bars1", "wens1", "lnis1", "ipfs1"
+};
+
+char *colorname[] =
+{
+ "Gray", "Brown", "Black", "Tan", "Red", "Olive",
+ "Blue", "White", "Green", "Purple", "Orange"
+};
+
+//
+// MENU ITEMS
+//
+CP_MenuNames MainMenuNames[] =
+{
+ "NEW GAME",
+ "COMM-BAT� GAME",
+ "RESTORE GAME",
+ "SAVE GAME",
+ "OPTIONS",
+ "ORDERING INFO",
+ "VIEW SCORES", //"END GAME"
+ "BACK TO DEMO", //"BACK TO GAME"
+ "QUIT"
+};
+
+CP_iteminfo MainItems = { MENU_X, MENU_Y + 1, 9, STARTITEM, 32, MainMenuNames, mn_largefont };
+CP_itemtype MainMenu[] =
+{
+ { CP_CursorLocation, "mm_opt1\0", 'N', (menuptr)CP_NewGame },
+ { CP_Active, "battle\0", 'C', (menuptr)CP_BattleModes },
+ { CP_Active, "mm_opt2\0", 'R', (menuptr)CP_LoadGame },
+ { CP_Inactive, "mm_opt3\0", 'S', (menuptr)CP_SaveGame },
+ { CP_Active, "mm_opt5\0", 'O', (menuptr)CP_ControlMenu },
+ { CP_Active, "ordrinfo\0", 'O', (menuptr)CP_OrderInfo },
+ { CP_Active, "mm_opt7\0", 'V', (menuptr)CP_ViewScores },
+ { CP_Active, "mm_opt8\0", 'B', (menuptr)NULL },
+ { CP_Active, "mm_opt9\0", 'Q', (menuptr)CP_Quit }
+};
+
+
+CP_iteminfo LSItems = { LSM_X, LSM_Y, NUMSAVEGAMES, 0, 10, NULL, mn_largefont };
+CP_itemtype LSMenu[] =
+{
+ { CP_Active, "", 'a', NULL },
+ { CP_Active, "", 'b', NULL },
+ { CP_Active, "", 'c', NULL },
+ { CP_Active, "", 'd', NULL },
+ { CP_Active, "", 'e', NULL },
+ { CP_Active, "", 'f', NULL },
+ { CP_Active, "", 'g', NULL },
+ { CP_Active, "", 'h', NULL },
+ { CP_Active, "", 'i', NULL },
+ { CP_Active, "", 'j', NULL },
+ { CP_Active, "", 'k', NULL },
+ { CP_Active, "", 'l', NULL },
+ { CP_Active, "", 'm', NULL },
+ { CP_Active, "", 'n', NULL },
+ { CP_Active, "", 'o', NULL }
+};
+
+CP_MenuNames CtlMenuNames[] =
+{
+ "MOUSE ENABLED",
+ "JOYSTICK ENABLED",
+ "USE JOYSTICK PORT 2",
+ "GAMEPAD ENABLED",
+ "SPACEBALL ENABLED",
+ "CYBERMAN ENABLED",
+ "ADJUST THRESHOLD",
+ "MOUSE SENSITIVITY",
+ "CUSTOMIZE CONTROLS"
+};
+
+CP_iteminfo CtlItems = { CTL_X, MENU_Y, 9, -1, 36, CtlMenuNames, mn_largefont };
+CP_itemtype CtlMenu[] =
+{
+ { CP_Inactive, "ctl_mic\0", 'M', NULL },
+ { CP_Inactive, "ctl_jen\0", 'J', NULL },
+ { CP_Inactive, "ctl_jp2\0", 'U', NULL },
+ { CP_Inactive, "ctl_gpd\0", 'G', NULL },
+ { CP_Inactive, "spball\0", 'S', NULL },
+ { CP_Inactive, "cyberman\0",'C', NULL },
+ { CP_Inactive, "ctl_thr\0", 'A', (menuptr)DoThreshold },
+ { CP_Inactive, "ctl_mse\0", 'M', (menuptr)MouseSensitivity },
+ { CP_Active, "ctl_cus\0", 'C', (menuptr)CP_Custom }
+};
+
+CP_iteminfo CusItems = { 32, CST_Y + 13 * 2, 9, -1, 0, NULL, mn_largefont };
+CP_itemtype CusMenu[] =
+{
+ { CP_Active, "ctl_mic\0", 'a', NULL },
+ { CP_Inactive, "ctl_mic\0", 'a', NULL },
+ { CP_Inactive, "ctl_mic\0", 'a', NULL },
+ { CP_Active, "ctl_mic\0", 'a', NULL },
+ { CP_Inactive, "ctl_mic\0", 'a', NULL },
+ { CP_Inactive, "ctl_mic\0", 'a', NULL },
+ { CP_Active, "ctl_mic\0", 'a', NULL },
+ { CP_Inactive, "ctl_mic\0", 'a', NULL },
+ { CP_Active, "ctl_mic\0", 'a', NULL }
+};
+
+
+CP_iteminfo TufItems = { TUF_X, TUF_Y, 7, 0, 80, NULL, mn_largefont };
+CP_itemtype TufMenu[ 4 ][ 7 ] =
+{
+ {
+ { 2, "new11\0", 'a', NULL },
+ { 3, "new11\0", 'a', NULL },
+ { 1, "new12\0", 'a', NULL },
+ { 3, "new12\0", 'a', NULL },
+ { 1, "new13\0", 'a', NULL },
+ { 3, "new13\0", 'a', NULL },
+ { 1, "new14\0", 'a', NULL },
+ },
+
+ {
+ { 2, "new21\0", 'a', NULL },
+ { 3, "new21\0", 'a', NULL },
+ { 1, "new22\0", 'a', NULL },
+ { 3, "new22\0", 'a', NULL },
+ { 1, "new23\0", 'a', NULL },
+ { 3, "new23\0", 'a', NULL },
+ { 1, "new24\0", 'a', NULL },
+ },
+
+ {
+ { 2, "new31\0", 'a', NULL },
+ { 3, "new31\0", 'a', NULL },
+ { 1, "new32\0", 'a', NULL },
+ { 3, "new32\0", 'a', NULL },
+ { 1, "new33\0", 'a', NULL },
+ { 3, "new33\0", 'a', NULL },
+ { 1, "new34\0", 'a', NULL },
+ },
+
+ {
+ { 2, "stk_1\0", 'a', NULL },
+ { 3, "stk_1\0", 'a', NULL },
+ { 1, "stk_2\0", 'a', NULL },
+ { 3, "stk_2\0", 'a', NULL },
+ { 1, "stk_3\0", 'a', NULL },
+ { 3, "stk_3\0", 'a', NULL },
+ { 1, "stk_4\0", 'a', NULL },
+ }
+};
+
+CP_MenuNames CustomMenuNames[] =
+{
+ "CUSTOMIZE KEYBOARD",
+ "CUSTOMIZE MOUSE",
+ "CUSTOMIZE JOYSTICK"
+};
+
+CP_iteminfo CustomItems = {32, 64, 3, 0, 24, CustomMenuNames, mn_largefont };
+
+CP_itemtype CustomMenu[] =
+{
+ {2, "custom1\0", 'C', (menuptr)CP_Keyboard},
+ {1, "custom2\0", 'C', (menuptr)CP_Mouse},
+ {1, "custom3\0", 'C', (menuptr)CP_Joystick}
+};
+
+#define KEYNAMEINDEX 21
+
+CP_MenuNames NormalKeyNames[] =
+{
+ "LEFT \x9 ",
+ "RIGHT \x9 ",
+ "FORWARD \x9 ",
+ "BACKWARD \x9 ",
+ "RUN \x9 ",
+ "OPEN \x9 ",
+ "FIRE \x9 ",
+ "STRAFE \x9 ",
+ "STRAFE LEFT \x9 ",
+ "STRAFE RIGHT \x9 ",
+ "LOOK/FLY UP \x9 ",
+ "LOOK/FLY DOWN \x9 ",
+ "AIM \x9 ",
+ "AIM UP \x9 ",
+ "AIM DOWN \x9 ",
+ "TOGGLE WEAPON \x9 ",
+ "DROP WEAPON \x9 ",
+ "VOLTE-FACE \x9 ",
+ "AUTORUN \x9 ",
+ "SEND MESSAGE \x9 ",
+ "DIRECT MESSAGE \x9 "
+};
+
+#define NORMALKEY_X 74
+#define NORMALKEY_Y 16
+CP_iteminfo NormalKeyItems = { NORMALKEY_X, 17, 21, 0, 16, NormalKeyNames, mn_tinyfont };
+
+CP_itemtype NormalKeyMenu[] =
+{
+ { 2, "\0", 'L', (menuptr)DefineKey },
+ { 1, "\0", 'R', (menuptr)DefineKey },
+ { 1, "\0", 'F', (menuptr)DefineKey },
+ { 1, "\0", 'B', (menuptr)DefineKey },
+ { 1, "\0", 'R', (menuptr)DefineKey },
+ { 1, "\0", 'O', (menuptr)DefineKey },
+ { 1, "\0", 'F', (menuptr)DefineKey },
+ { 1, "\0", 'S', (menuptr)DefineKey },
+ { 1, "\0", 'S', (menuptr)DefineKey },
+ { 1, "\0", 'S', (menuptr)DefineKey },
+ { 1, "\0", 'L', (menuptr)DefineKey },
+ { 1, "\0", 'L', (menuptr)DefineKey },
+ { 1, "\0", 'A', (menuptr)DefineKey },
+ { 1, "\0", 'A', (menuptr)DefineKey },
+ { 1, "\0", 'T', (menuptr)DefineKey },
+ { 1, "\0", 'D', (menuptr)DefineKey },
+ { 1, "\0", 'V', (menuptr)DefineKey },
+ { 1, "\0", 'A', (menuptr)DefineKey },
+ { 1, "\0", 'A', (menuptr)DefineKey },
+ { 1, "\0", 'S', (menuptr)DefineKey },
+ { 1, "\0", 'D', (menuptr)DefineKey }
+};
+
+#define NUMCONTROLNAMES 21
+
+CP_MenuNames ControlNames[] =
+{
+ "NONE",
+ "LEFT",
+ "RIGHT",
+ "FORWARD",
+ "BACKWARD",
+ "RUN",
+ "OPEN",
+ "FIRE",
+ "STRAFE",
+ "STRAFE LEFT",
+ "STRAFE RIGHT",
+ "LOOK/FLY UP",
+ "LOOK/FLY DOWN",
+ "AIM",
+ "AIM UP",
+ "AIM DOWN",
+ "TOGGLE WEAPON",
+ "DROP WEAPON",
+ "VOLTE-FACE",
+ "AUTORUN",
+ "MAP"
+};
+
+int controlorder[ NUMCONTROLNAMES ] = {
+ bt_nobutton, di_west, di_east, di_north, di_south, bt_run, bt_use,
+ bt_attack, bt_strafe, bt_strafeleft, bt_straferight, bt_lookup,
+ bt_lookdown, bt_aimbutton, bt_horizonup, bt_horizondown,
+ bt_swapweapon, bt_dropweapon, bt_turnaround, bt_autorun, bt_map
+};
+
+#define CONTROLSELECT_X 106
+CP_iteminfo ControlSelectItems = { CONTROLSELECT_X, 17, NUMCONTROLNAMES, 0, 16, ControlNames, mn_tinyfont };
+
+CP_itemtype ControlSelectMenu[] =
+{
+ { 2, "\0", 'N', NULL },
+ { 1, "\0", 'L', NULL },
+ { 1, "\0", 'R', NULL },
+ { 1, "\0", 'F', NULL },
+ { 1, "\0", 'B', NULL },
+ { 1, "\0", 'R', NULL },
+ { 1, "\0", 'O', NULL },
+ { 1, "\0", 'F', NULL },
+ { 1, "\0", 'S', NULL },
+ { 1, "\0", 'S', NULL },
+ { 1, "\0", 'S', NULL },
+ { 1, "\0", 'L', NULL },
+ { 1, "\0", 'L', NULL },
+ { 1, "\0", 'A', NULL },
+ { 1, "\0", 'A', NULL },
+ { 1, "\0", 'A', NULL },
+ { 1, "\0", 'T', NULL },
+ { 1, "\0", 'D', NULL },
+ { 1, "\0", 'V', NULL },
+ { 1, "\0", 'A', NULL },
+ { 1, "\0", 'M', NULL }
+};
+
+#define MOUSEBTNINDEX 17
+
+CP_MenuNames MouseBtnNames[] =
+{
+ " B0 \x9 ",
+ " B1 \x9 ",
+ " B2 \x9 ",
+ "DOUBLE-CLICK B0 \x9 ",
+ "DOUBLE-CLICK B1 \x9 ",
+ "DOUBLE-CLICK B2 \x9 "
+};
+
+CP_iteminfo MouseBtnItems = { 19, 52, 6, 0, 11, MouseBtnNames, mn_8x8font };
+
+CP_itemtype MouseBtnMenu[] =
+{
+ { 2, "\0", 'B', (menuptr)DefineMouseBtn },
+ { 1, "\0", 'B', (menuptr)DefineMouseBtn },
+ { 1, "\0", 'B', (menuptr)DefineMouseBtn },
+ { 1, "\0", 'D', (menuptr)DefineMouseBtn },
+ { 1, "\0", 'D', (menuptr)DefineMouseBtn },
+ { 1, "\0", 'D', (menuptr)DefineMouseBtn }
+};
+
+
+#define JOYBTNINDEX 17
+
+CP_MenuNames JoyBtnNames[] =
+{
+ " B0 \x9 ",
+ " B1 \x9 ",
+ " B2 \x9 ",
+ " B3 \x9 ",
+ "DOUBLE-CLICK B0 \x9 ",
+ "DOUBLE-CLICK B1 \x9 ",
+ "DOUBLE-CLICK B2 \x9 ",
+ "DOUBLE-CLICK B3 \x9 "
+};
+
+CP_iteminfo JoyBtnItems = { 19, 48, 8, 0, 11, JoyBtnNames, mn_8x8font };
+
+CP_itemtype JoyBtnMenu[] =
+{
+ { 2, "\0", 'B', (menuptr)DefineJoyBtn },
+ { 1, "\0", 'B', (menuptr)DefineJoyBtn },
+ { 1, "\0", 'B', (menuptr)DefineJoyBtn },
+ { 1, "\0", 'B', (menuptr)DefineJoyBtn },
+ { 1, "\0", 'D', (menuptr)DefineJoyBtn },
+ { 1, "\0", 'D', (menuptr)DefineJoyBtn },
+ { 1, "\0", 'D', (menuptr)DefineJoyBtn },
+ { 1, "\0", 'D', (menuptr)DefineJoyBtn }
+};
+
+CP_MenuNames PlayerMenuNames[] =
+{
+ "TARADINO CASSATT",
+ "THI BARRETT",
+ "DOUG WENDT",
+ "LORELEI NI",
+ "IAN PAUL FREELEY"
+};
+
+CP_iteminfo PlayerItems = {TUF_X, 48, 5, 0, 80, PlayerMenuNames, mn_largefont };
+
+CP_itemtype PlayerMenu[] =
+{
+ {2, "name1\0", 'T', NULL},
+ {1, "name2\0", 'T', NULL},
+ {1, "name3\0", 'D', NULL},
+ {1, "name4\0", 'L', NULL},
+ {1, "name5\0", 'I', NULL},
+};
+
+CP_MenuNames ControlMMenuNames[] =
+{
+ "CONTROLS",
+ "USER OPTIONS",
+ "EXT USER OPTIONS",//bna added
+ "EXT GAME OPTIONS", //added by LT
+ "MUSIC VOLUME",
+ "SOUND FX VOLUME"
+
+};
+CP_iteminfo ControlMItems = {32, 48-8, 6, 0, 32, ControlMMenuNames, mn_largefont };//bna added
+//CP_iteminfo ControlMItems = {32, 48, 4, 0, 32, ControlMMenuNames, mn_largefont };
+
+CP_itemtype ControlMMenu[] =
+{
+ {2, "cntl\0", 'C', (menuptr)CP_Control},
+ {1, "uopt\0", 'U', (menuptr)CP_OptionsMenu},
+ {1, "euopt\0", 'E', (menuptr)CP_ExtOptionsMenu},//bna added
+ {1, "eaopt\0", 'A', (menuptr)CP_ExtGameOptionsMenu},
+ {1, "muvolumn\0", 'M', (menuptr)MusicVolume},
+ {1, "fxvolumn\0", 'S', (menuptr)FXVolume}
+
+};
+
+CP_MenuNames OptionsNames[] =
+{
+ "AUTO DETAIL ADJUST",
+ "LIGHT DIMINISHING",
+ "BOBBIN'",
+ "FLOOR AND CEILING",
+ "DOUBLE-CLICK SPEED",
+ "MENU FLIP SPEED",
+ "DETAIL LEVELS",
+ "VIOLENCE LEVEL",
+ "SCREEN SIZE"
+};
+//bna added
+CP_MenuNames ExtOptionsNames[] =
+{
+ "MOUSELOOK",
+ "INVERSE MOUSE",
+ "CROSS HAIR",
+ "JUMPING",
+ "FULLSCREEN",
+ "AUTOAIM MISSILE WEPS",
+ "ENABLE AUTOAIM"
+};
+
+CP_MenuNames ExtGameOptionsNames[] =
+{
+ "BLITZ RANDOM WEPS",
+ "ENABLE AMMO PICKUP",
+ "EXTRA PISTOL DROPS",
+ "ENABLE ZOMROTT"
+}; //LT added
+
+CP_iteminfo ExtOptionsItems = { 20, MENU_Y, 7, 0, 43, ExtOptionsNames, mn_largefont };
+
+CP_iteminfo ExtGameOptionsItems = { 20, MENU_Y, 4, 0, 43, ExtGameOptionsNames, mn_largefont }; //LT added
+
+CP_itemtype ExtOptionsMenu[] =
+{
+ {1, "", 'M', NULL},
+ {1, "", 'I', NULL},
+ {1, "", 'C', NULL},
+ {1, "", 'J', NULL},
+ {1, "", 'F', NULL},
+ {1, "", 'A', NULL},
+ {1, "", 'U', NULL}
+};
+
+CP_itemtype ExtGameMenu[] =
+{
+ {1, "", 'A', NULL},
+ {1, "", 'P', NULL},
+ {1, "", 'E', NULL},
+ {1, "", 'Z', NULL},
+}; //LT added
+
+//bna added end
+
+CP_iteminfo OptionsItems = { 20, MENU_Y, 9, 0, 43, OptionsNames, mn_largefont };
+
+CP_itemtype OptionsMenu[] =
+{
+ {2, "autoadj\0", 'A', NULL},
+ {1, "lightdim\0",'L', NULL},
+ {1, "bobbin\0", 'B', NULL},
+ {1, "fandc\0", 'F', NULL},
+ {1, "double\0", 'D', (menuptr)CP_DoubleClickSpeed},
+ {1, "menuspd\0", 'M', (menuptr)MenuFlipSpeed},
+ {1, "detail\0", 'D', (menuptr)CP_DetailMenu},
+ {1, "vlevel\0", 'V', (menuptr)CP_ViolenceMenu},
+ {1, "\0", 'S', (menuptr)CP_ScreenSize}
+};
+
+CP_MenuNames DetailMenuNames[] =
+{
+ "LOW DETAIL",
+ "MEDIUM DETAIL",
+ "HIGH DETAIL"
+};
+
+CP_iteminfo DetailItems = { 32, 64, 3, 0, 43, DetailMenuNames, mn_largefont };
+
+CP_itemtype DetailMenu[] =
+{
+ {2, "lowdtl\0", 'L', NULL},
+ {1, "meddtl\0", 'M', NULL},
+ {1, "hidtl\0", 'H', NULL}
+};
+
+CP_MenuNames BattleMenuNames[] =
+{
+ "PLAY GAME",
+ "PLAY TEAM GAME",
+ "COMM-BAT OPTIONS"
+};
+
+CP_iteminfo BattleItems = { 32, 19, 3, 0, 24, BattleMenuNames, mn_largefont };
+
+CP_itemtype BattleMenu[] =
+{
+ {2, "bplay\0", 'P', (menuptr)BattleNoTeams},
+ {1, "playteam\0", 'P', (menuptr)BattleTeams},
+ {1, "comopt\0", 'C', (menuptr)CP_BattleOptions}
+};
+
+CP_MenuNames ViolenceMenuNames[] =
+{
+ "NONE",
+ "SOME",
+ "A LOT",
+ "EXCESSIVE"
+};
+
+CP_iteminfo ViolenceItems = { 32, 64, 4, 0, 45, ViolenceMenuNames, mn_largefont };
+
+CP_itemtype ViolenceMenu[] =
+{
+ {2, "vnone\0", 'N', NULL},
+ {1, "vsome\0", 'S', NULL},
+ {1, "valot\0", 'A', NULL},
+ {1, "vexcess\0", 'E', NULL}
+};
+
+CP_MenuNames VMenuNames[] =
+{
+ "SET VIOLENCE LEVEL",
+ "" // "ENTER PASSWORD" // "CHANGE PASSWORD"
+};
+
+CP_iteminfo VItems = { 32, MP_Y, 2, 0, 24, VMenuNames, mn_largefont };
+
+CP_itemtype VMenu[] =
+{
+ {2, "msetv\0", 'S', (menuptr)CP_ViolenceLevel},
+ {1, "mepass\0", 'E', (menuptr)CP_PWMenu}
+};
+
+CP_MenuNames ModeMenuNames[] =
+{
+ "NORMAL",
+ "SCORE MORE",
+ "COLLECTOR",
+ "SCAVENGER",
+ "HUNTER",
+ "TAG",
+ "ELUDER",
+ "DELUDER",
+ "CAPTURE THE TRIAD"
+};
+
+CP_iteminfo ModeItems = { MENU_X, MENU_Y + 1, 9, 0, 24, ModeMenuNames, mn_largefont };
+
+CP_itemtype ModeMenu[] =
+{
+ {CP_CursorLocation, "normal\0", 'N', (menuptr)CP_BattleMenu},
+ {CP_Active, "scorem\0", 'S', (menuptr)CP_BattleMenu},
+ {CP_Active, "collect\0", 'C', (menuptr)CP_BattleMenu},
+ {CP_Active, "scaven\0", 'S', (menuptr)CP_BattleMenu},
+ {CP_Active, "hunter\0", 'H', (menuptr)CP_BattleMenu},
+ {CP_Active, "tag\0", 'T', (menuptr)CP_BattleMenu},
+ {CP_Active, "eluder\0", 'E', (menuptr)CP_BattleMenu},
+ {CP_Active, "deluder\0", 'D', (menuptr)CP_BattleMenu},
+ {CP_Active, "captriad\0", 'C', (menuptr)CP_BattleMenu}
+};
+
+CP_MenuNames BOptNames[] =
+{
+ "GRAVITY",
+ "SPEED",
+ "AMMO PER WEAPON",
+ "HIT POINTS",
+ "RADICAL OPTIONS",
+ "LIGHT LEVELS",
+ "POINT GOAL",
+ "DANGER DAMAGE",
+ "TIME LIMIT"
+};
+
+CP_iteminfo BOptItems = { MENU_X, MENU_Y + 1, 9, 0, 24, BOptNames, mn_largefont };
+
+CP_itemtype BOptMenu[] =
+{
+ {2, "gravity\0", 'G', (menuptr)CP_GravityOptions},
+ {1, "speed\0", 'S', (menuptr)CP_SpeedOptions},
+ {1, "ammoper\0", 'A', (menuptr)CP_AmmoPerWeaponOptions},
+ {1, "hitp\0", 'H', (menuptr)CP_HitPointsOptions},
+ {1, "radical\0", 'R', (menuptr)CP_SpawnControlOptions},
+ {1, "lightl\0", 'L', (menuptr)CP_LightLevelOptions},
+ {1, "pntgoal\0", 'P', (menuptr)CP_PointGoalOptions},
+ {1, "danger\0", 'D', (menuptr)CP_DangerOptions},
+ {1, "timel\0", 'T', (menuptr)CP_TimeLimitOptions}
+};
+
+CP_MenuNames GravityMenuNames[] =
+{
+ "LOW",
+ "NORMAL",
+ "HIGH"
+};
+
+CP_iteminfo GravityItems = { 32, 26, 3, 0, 45, GravityMenuNames, mn_largefont };
+
+CP_itemtype GravityMenu[] =
+{
+ {2, "b_low\0", 'L', NULL},
+ {1, "b_normal\0", 'N', NULL},
+ {1, "b_high\0", 'H', NULL}
+};
+
+CP_MenuNames SpeedMenuNames[] =
+{
+ "NORMAL",
+ "FAST"
+};
+
+CP_iteminfo SpeedItems = { 32, MP_Y, 2, 0, 45, SpeedMenuNames, mn_largefont };
+
+CP_itemtype SpeedMenu[] =
+{
+ {2, "b_normal\0", 'N', NULL},
+ {1, "b_fast\0", 'F', NULL}
+};
+
+CP_MenuNames AmmoPerWeaponMenuNames[] =
+{
+ "ONE",
+ "NORMAL",
+ "GUNFINITY"
+};
+
+CP_iteminfo AmmoPerWeaponItems = { 32, 26, 3, 0, 45, AmmoPerWeaponMenuNames, mn_largefont };
+
+CP_itemtype AmmoPerWeaponMenu[] =
+{
+ {2, "b_one\0", 'O', NULL},
+ {1, "b_normal\0", 'N', NULL},
+ {1, "b_gunf\0", 'G', NULL}
+};
+
+CP_MenuNames HitPointMenuNames[] =
+{
+ "ONE",
+ "25",
+ "BY CHARACTER",
+ "100",
+ "250",
+ "500",
+ "4000"
+};
+
+CP_iteminfo HitPointItems = { 32, 32, 7, 0, 45, HitPointMenuNames, mn_largefont };
+
+CP_itemtype HitPointMenu[] =
+{
+ {2, "b_one\0", 'O', NULL},
+ {1, "b_25\0", 'a', NULL},
+ {1, "b_char\0", 'C', NULL},
+ {1, "b_100\0", 'a', NULL},
+ {1, "b_250\0", 'a', NULL},
+ {1, "b_500\0", 'a', NULL},
+ {1, "b_4000\0", 'a', NULL}
+};
+
+CP_MenuNames SpawnMenuNames[] =
+{
+ "SPAWN DANGERS",
+ "SPAWN HEALTH",
+ "SPAWN WEAPONS",
+ "SPAWN MINES",
+ "RESPAWN ITEMS",
+ "WEAPON PERSISTENCE",
+ "RANDOM WEAPONS",
+ "FRIENDLY FIRE"
+};
+
+CP_iteminfo SpawnItems = { 20, 24, 8, 0, 35, SpawnMenuNames, mn_largefont };
+
+CP_itemtype SpawnMenu[] =
+{
+ {2, "b_danger\0", 'S', NULL},
+ {1, "b_health\0", 'S', NULL},
+ {1, "b_weap\0", 'S', NULL},
+ {1, "b_mines\0", 'S', NULL},
+ {1, "b_rpawn\0", 'R', NULL},
+ {1, "b_persis\0", 'W', NULL},
+ {1, "b_rndwpn\0", 'R', NULL},
+ {1, "b_friend\0", 'F', NULL}
+};
+
+CP_MenuNames LightLevelMenuNames[] =
+{
+ "DARK",
+ "NORMAL",
+ "BRIGHT",
+ "FOG",
+ "PERIODIC",
+ "LIGHTNING"
+};
+
+CP_iteminfo LightLevelItems = { 32, 40, 6, 0, 45, LightLevelMenuNames, mn_largefont };
+
+CP_itemtype LightLevelMenu[] =
+{
+ {2, "b_dark\0", 'D', NULL},
+ {1, "b_normal\0", 'N', NULL},
+ {1, "b_bright\0", 'B', NULL},
+ {1, "b_fog\0", 'F', NULL},
+ {1, "b_period\0", 'P', NULL},
+ {1, "b_light\0", 'L', NULL}
+};
+
+CP_MenuNames PointGoalMenuNames[] =
+{
+ "1",
+ "5",
+ "11",
+ "21",
+ "50",
+ "100",
+ "RANDOM",
+ "RANDOM BLIND",
+ "INFINITE"
+};
+
+CP_iteminfo PointGoalItems = { 32, 16, 9, 0, 45, PointGoalMenuNames, mn_largefont };
+
+CP_itemtype PointGoalMenu[] =
+{
+ {2, "b_1\0", 'a', NULL},
+ {1, "b_5\0", 'a', NULL},
+ {1, "b_11\0", 'a', NULL},
+ {1, "b_21\0", 'a', NULL},
+ {1, "b_50\0", 'a', NULL},
+ {1, "b_100\0", 'a', NULL},
+ {1, "b_random\0", 'R', NULL},
+ {1, "b_randb\0", 'R', NULL},
+ {1, "b_inf\0", 'I', NULL}
+};
+
+CP_MenuNames DangerMenuNames[] =
+{
+ "LOW",
+ "NORMAL",
+ "KILL"
+};
+
+CP_iteminfo DangerItems = { 32, 56, 3, 0, 45, DangerMenuNames, mn_largefont };
+
+CP_itemtype DangerMenu[] =
+{
+ {2, "b_low\0", 'L', NULL},
+ {1, "b_normal\0", 'N', NULL},
+ {1, "b_kill\0", 'K', NULL}
+};
+
+CP_MenuNames TimeLimitMenuNames[] =
+{
+ "1",
+ "2",
+ "5",
+ "10",
+ "21",
+ "30",
+ "99",
+ "NONE"
+};
+
+CP_iteminfo TimeLimitItems = { 32, 24, 8, 0, 45, TimeLimitMenuNames, mn_largefont };
+
+CP_itemtype TimeLimitMenu[] =
+{
+ {2, "b_1\0", 'a', NULL},
+ {1, "b_2\0", 'a', NULL},
+ {1, "b_5\0", 'a', NULL},
+ {1, "b_10\0", 'a', NULL},
+ {1, "b_21\0", 'a', NULL},
+ {1, "b_30\0", 'a', NULL},
+ {1, "b_99\0", 'a', NULL},
+ {1, "vnone\0", 'N', NULL}
+};
+
+CP_MenuNames MultiPageCustomNames[ MAXCUSTOM + 2 ] =
+{
+ "NEXT PAGE",
+ "PREVIOUS PAGE"
+};
+
+CP_iteminfo MultiPageCustomItems = { 18, 17, 0, 0, 12, MultiPageCustomNames, mn_smallfont };
+CP_itemtype MultiPageCustomMenu[] =
+{
+ {1, "", 'N', NULL},
+ {1, "", 'P', NULL},
+ {1, "", 'a', NULL},
+ {1, "", 'a', NULL},
+ {1, "", 'a', NULL},
+ {1, "", 'a', NULL},
+ {1, "", 'a', NULL},
+ {1, "", 'a', NULL},
+ {1, "", 'a', NULL},
+ {1, "", 'a', NULL},
+ {1, "", 'a', NULL},
+ {1, "", 'a', NULL},
+ {1, "", 'a', NULL},
+ {1, "", 'a', NULL},
+};
+
+#define COLORX 113
+#define COLORY 43
+#define COLORW 60
+#define COLORH 96
+
+// Custom menu stuff
+static int CUSTOM_y[ 7 ] = { 31, 0, 63, 0, 94, 0, 126 };
+
+//
+// Save globals
+//
+static boolean StartGame = false;
+
+static int SaveGamesAvail[ NUMSAVEGAMES ];
+static char SaveGameNames[ NUMSAVEGAMES ][ 32 ];
+static char SaveName[ 13 ] = "rottgam?.rot\0";
+
+static byte *savedscreen;
+static mapfileinfo_t * mapinfo;
+
+static void HideCursor
+(
+ CP_iteminfo *item_i,
+ CP_itemtype *items,
+ int x,
+ int y,
+ int which
+);
+static void ShowCursor
+(
+ CP_iteminfo *item_i,
+ CP_itemtype *items,
+ int x,
+ int *y,
+ int which,
+ int basey
+);
+void CP_DrawSelectedGame (int w);
+int HandleMenu (CP_iteminfo *item_i, CP_itemtype *items, void (*routine)(int w));
+void DrawStoredGame ( byte * pic, int episode, int area );
+void DrawCustomKeyboard (void);
+void DrawBattleModeName( int which );
+void DrawBattleModeDescription( int w );
+void DrawSoundSetupMainMenu( void );
+int ColorMenu(void);
+
+//******************************************************************************
+//
+// MN_DrawButtons
+//
+//******************************************************************************
+
+void MN_DrawButtons
+(
+ CP_iteminfo *item_i,
+ CP_itemtype *items,
+ int check,
+ int *nums
+)
+
+{
+ int i;
+ int button_on;
+ int button_off;
+
+ button_on = W_GetNumForName( "snd_on" );
+ button_off = W_GetNumForName( "snd_off" );
+
+ for( i = 0; i < item_i->amount; i++ )
+ {
+ if ( items[ i ].active != CP_Active3 )
+ {
+ if ( nums[ i ] == check )
+ {
+ DrawMenuBufItem( item_i->x + 27, item_i->y + i *
+ FontSize[ item_i->fontsize ] - 1, button_on);
+ }
+ else
+ {
+ DrawMenuBufItem( item_i->x + 27, item_i->y + i *
+ FontSize[ item_i->fontsize ] - 1, button_off);
+ }
+ }
+ }
+}
+
+
+//****************************************************************************
+//
+// MN_GetCursorLocation()
+//
+//****************************************************************************
+
+void MN_GetCursorLocation
+(
+ CP_iteminfo *item_i,
+ CP_itemtype *items
+)
+
+{
+ int i;
+ int position;
+
+ position = -1;
+ for( i = 0; i < item_i->amount; i++ )
+ {
+ if ( items[ i ].active == CP_CursorLocation )
+ {
+ position = i;
+ break;
+ }
+
+ if ( ( items[ i ].active == CP_Active ) && ( position == -1 ) )
+ {
+ position = i;
+ }
+ }
+
+ if ( position != -1 )
+ {
+ item_i->curpos = position;
+ items[ position ].active = CP_CursorLocation;
+ }
+}
+
+
+//****************************************************************************
+//
+// MN_GetActive ()
+//
+//****************************************************************************
+
+int MN_GetActive
+(
+ CP_iteminfo *item_i,
+ CP_itemtype *items,
+ int check,
+ int *nums
+)
+
+{
+ int i;
+ int returnval;
+
+ returnval = 0;
+ for( i = 0; i < item_i->amount; i++ )
+ {
+ items[ i ].active = CP_Active;
+ if ( nums[ i ] == check )
+ {
+ item_i->curpos = i;
+ items[ i ].active = CP_CursorLocation;
+ returnval = i;
+ }
+ }
+
+ return( returnval );
+}
+
+
+//****************************************************************************
+//
+// MN_MakeActive ()
+//
+//****************************************************************************
+
+void MN_MakeActive
+(
+ CP_iteminfo *item_i,
+ CP_itemtype *items,
+ int which
+)
+
+{
+ int i;
+
+ for( i = 0; i < item_i->amount; i++ )
+ if (i == which)
+ {
+ items[i].active = CP_CursorLocation;
+ item_i->curpos = i;
+ }
+ else
+ items[i].active = CP_Active;
+}
+
+
+//******************************************************************************
+//
+// DrawMenu ()
+//
+// Purpose - Draws a menu
+//
+//******************************************************************************
+void DrawMenu
+(
+ CP_iteminfo *item_i,
+ CP_itemtype *items
+)
+
+{
+ int i;
+ int active;
+ int color;
+ int posx;
+ int posy;
+
+ posx = item_i->x + item_i->indent;
+ posy = item_i->y;
+ WindowX = posx;
+ WindowY = posy;
+ WindowW = 320;
+ WindowH = 200;
+
+ for ( i = 0; i < item_i->amount; i++ )
+ {
+ posy = item_i->y + i * FontSize[ item_i->fontsize ];
+ active = items[ i ].active;
+
+ color = -1;
+ switch( active )
+ {
+ case CP_CursorLocation :
+ color = ACTIVECOLOR;
+ break;
+
+ case CP_Inactive :
+ color = NOTAVAILABLECOLOR;
+ break;
+
+ case CP_Active :
+ color = NORMALCOLOR;
+ break;
+
+ case CP_SemiActive :
+ color = DIMMEDCOLOR;
+ break;
+
+ case CP_Highlight :
+ color = HIGHLIGHTCOLOR;
+ break;
+ }
+
+ if ( color != -1 )
+ {
+ if ( item_i->names == NULL )
+ {
+ DrawIMenuBufItem( posx, posy, W_GetNumForName( items[ i ].texture ),
+ color );
+ }
+ else
+ {
+ IFont = ( cfont_t * )W_CacheLumpName( FontNames[ item_i->fontsize ],
+ PU_CACHE, Cvt_cfont_t, 1 );
+ if ( item_i->fontsize == mn_tinyfont )
+ {
+ DrawMenuBufIString( posx + 1, posy, item_i->names[ i ], 0 );
+ }
+ DrawMenuBufIString( posx, posy - 1, item_i->names[ i ], color );
+ }
+ }
+ }
+}
+
+
+//******************************************************************************
+//
+// getASCII () - Gets info from Keyboard.
+//
+//******************************************************************************
+
+int getASCII ( void )
+{
+ int i;
+ int LS;
+ int RS;
+ int returnvalue = 0;
+ int scancode = 0;
+
+#ifdef DOS
+ _disable (); // must disable for SHIFT purposes
+#endif
+
+ IN_UpdateKeyboard ();
+
+ LS = Keyboard[sc_LShift];
+ RS = Keyboard[sc_RShift];
+
+ Keyboard[sc_LShift] = Keyboard[sc_RShift] = 0;
+
+ scancode = 0;
+
+ for (i = 0; i < 127; i++)
+ if (Keyboard[i])
+ {
+ scancode = i;
+ break;
+ }
+
+ if (scancode)
+ {
+ if (LS || RS)
+ returnvalue = ShiftNames[scancode];
+ else
+ returnvalue = ASCIINames[scancode];
+ }
+
+ Keyboard[sc_LShift] = LS;
+ Keyboard[sc_RShift] = RS;
+
+#ifdef DOS
+ _enable ();
+#endif
+
+ return (returnvalue);
+}
+
+
+//******************************************************************************
+//
+// ScanForSavedGames ()
+//
+//******************************************************************************
+
+void ScanForSavedGames ()
+{
+ struct find_t f;
+ char filename[256];
+ char str[45];
+ int which;
+ boolean found = false;
+#ifndef DOS
+ char *pathsave;
+#endif
+
+ //
+ // SEE WHICH SAVE GAME FILES ARE AVAILABLE & READ STRING IN
+ //
+ memset (&SaveGamesAvail[0], 0, sizeof (SaveGamesAvail));
+#if PLATFORM_DOS || PLATFORM_WIN32
+ GetPathFromEnvironment( filename, ApogeePath, SaveName );
+#else
+ strncpy (filename, SaveName, 256);
+ pathsave = getcwd (NULL, 0);
+ chdir (ApogeePath);
+#endif
+
+ if (!_dos_findfirst (filename, 0, &f))
+ do
+ {
+ strcpy(str,&f.name[7]);
+ sscanf((const char *)&str[0],"%x",&which);
+
+ if (which < NUMSAVEGAMES)
+ {
+ found = true;
+ SaveGamesAvail[which] = 1;
+ GetSavedMessage (which, &SaveGameNames[which][0]);
+ }
+
+ } while (!_dos_findnext (&f));
+
+ if (found)
+ {
+ if (MainMenu[loadgame].active == CP_Inactive)
+ MainMenu[loadgame].active = CP_Active;
+ }
+ else
+ MainMenu[loadgame].active = CP_Inactive;
+#if ((!PLATFORM_DOS) && (!PLATFORM_WIN32))
+ chdir (pathsave);
+ free (pathsave);
+#endif
+}
+
+
+//******************************************************************************
+//
+// SetUpControlPanel ()
+//
+//******************************************************************************
+
+void SetUpControlPanel (void)
+{
+ int i;
+ int j;
+ byte * b;
+ byte * s;
+
+// int Xres = 320;//org
+// int Yres = 200;//org
+ int Xres = 640;
+ int Yres = 400;
+
+ //dont work in 800x600 until we get a better screen schrinker
+ // int Xres = iGLOBAL_SCREENWIDTH;//640;
+// int Yres = iGLOBAL_SCREENHEIGHT;//400;
+
+ Xres = 640;
+ Yres = 400;
+
+
+
+ // Save the current game screen
+
+ //bna--savedscreen = SafeMalloc (16000);
+ savedscreen = SafeMalloc (16000*8);
+
+ // Copy the current save game screen (� size) to this buffer
+
+ if (RefreshPause==false)
+ {
+ GamePaused=false;
+ ThreeDRefresh();
+ FlipPage();
+ FlipPage();
+ GamePaused=true;
+ }
+
+
+ s=savedscreen;
+
+
+
+ if (iGLOBAL_SCREENWIDTH == 320) {
+ for (i=0; i<Xres; i+=2) {
+ b=(byte *)bufferofs+i;
+ for (j=0; j<100; j++,s++,b+=(iGLOBAL_SCREENWIDTH<<1))
+ *s=*b;
+ }
+ }
+ if (iGLOBAL_SCREENWIDTH >= 640) {
+ for (i=0; i<Xres; i+=4) {
+ b=(byte *)bufferofs+i;//schrink screen to 1/2 size
+ for (j=0; j<(Yres/4); j++,s++,b+=(iGLOBAL_SCREENWIDTH<<1)*2)
+ *s=*b;
+ }
+ }/*
+ if (iGLOBAL_SCREENWIDTH == 800) {
+ for (i=0;i<Xres;i+=8) {
+ b=(byte *)bufferofs+i;//schrink screen to 1/3 size
+ for (j=0;j<(Yres/8);j++,s++,b+=(iGLOBAL_SCREENWIDTH<<1)*3)
+ *s=*b;
+ }
+
+ }*/
+
+ ScanForSavedGames ();
+
+
+
+ if (modemgame == true)
+ {
+ // Make battle mode active
+ //
+ MainMenu[battlemode].active = CP_Active;
+
+ // No save or load game in modem game
+ //
+ MainMenu[newgame].active = CP_Inactive;
+ MainMenu[backtodemo].active = CP_Inactive;
+ MainMenu[loadgame].active = CP_Inactive;
+ MainMenu[savegame].active = CP_Inactive;
+
+ if ( MainMenu[ MainItems.curpos ].active == CP_Inactive )
+ {
+ MainItems.curpos = battlemode;
+ }
+
+ MainMenu[MainItems.curpos].active = CP_CursorLocation;
+
+ if ( consoleplayer != 0 )
+ {
+ MainMenu[battlemode].routine = ( void (*)(int) )BattleGamePlayerSetup;
+ }
+ }
+}
+
+//******************************************************************************
+//
+// GetMenuInfo ()
+//
+// Gets the user's password
+//
+//******************************************************************************
+
+void GetMenuInfo (void)
+{
+ ConvertPasswordStringToPassword ();
+
+ POK=true;
+ if (pword[0]==0)
+ POK=false;
+}
+
+
+//******************************************************************************
+//
+// WriteMenuInfo ()
+//
+// Writes out password
+//
+//******************************************************************************
+
+void WriteMenuInfo (void)
+{
+ ConvertPasswordToPasswordString ();
+}
+
+//******************************************************************************
+//
+// AllocateSavedScreenPtr ()
+//
+//******************************************************************************
+
+void AllocateSavedScreenPtr (void)
+{
+ // Save the current game screen
+
+ savedscreen = SafeMalloc(16000);
+ inmenu = true;
+ numdone = 0;
+}
+
+
+//******************************************************************************
+//
+// FreeSavedScreenPtr ()
+//
+//******************************************************************************
+
+void FreeSavedScreenPtr (void)
+{
+ SafeFree (savedscreen);
+ inmenu = false;
+}
+
+
+//******************************************************************************
+//
+// CleanUpControlPanel ()
+//
+//******************************************************************************
+
+void CleanUpControlPanel (void)
+{
+ int joyx, joyy;
+
+ if ((playstate==ex_resetgame) || (loadedgame==true))
+ ShutdownClientControls();
+
+ // Free up saved screen image
+
+ FreeSavedScreenPtr ();
+
+ WriteConfig ();
+
+ INL_GetJoyDelta (joystickport, &joyx, &joyy);
+
+ if (mouseenabled)
+ PollMouseMove (); // Trying to kill movement
+
+ if (cybermanenabled)
+ PollCyberman ();
+
+ RefreshPause = true;
+}
+
+
+//******************************************************************************
+//
+// CP_CheckQuick ()
+//
+//******************************************************************************
+boolean CP_CheckQuick
+(
+ byte scancode
+)
+
+{
+ if (demoplayback==true)
+ {
+ switch ( scancode )
+ {
+ case sc_Escape:
+ inmenu = true;
+ return( true );
+ break;
+ }
+ }
+ else
+ {
+ switch ( scancode )
+ {
+ case sc_Escape:
+ case sc_F1:
+ case sc_F2:
+ case sc_F3:
+ case sc_F4:
+ case sc_F8:
+ case sc_F9:
+ case sc_F10:
+ inmenu = true;
+ return( true );
+ break;
+ }
+ }
+
+ return( false );
+}
+
+
+//******************************************************************************
+//
+// ControlPanel
+//
+// ROTT Control Panel!
+//
+//******************************************************************************
+void ControlPanel
+(
+ byte scancode
+)
+
+{
+ if ( scancode == sc_Escape )
+ {
+ CP_MainMenu();
+ if ( ( playstate == ex_stillplaying ) && ( loadedgame == false ) )
+ {
+ fizzlein = true;
+ }
+ return;
+ }
+
+ SetupMenuBuf();
+
+ numdone = 0;
+ StartGame = false;
+
+ SetUpControlPanel();
+ EnableScreenStretch();
+ //
+ // F-KEYS FROM WITHIN GAME
+ //
+ switch( scancode )
+ {
+ case sc_F1:
+ CP_F1Help();
+ break;
+
+ case sc_F2:
+ CP_SaveGame();
+ break;
+
+ case sc_F3:
+ CP_LoadGame( 0, 0 );
+ break;
+
+ case sc_F4:
+ CP_ControlMenu();
+ break;
+
+ case sc_F8:
+ LastScan = 0;
+ Keyboard[ sc_F8 ] = 0;
+ CP_EndGame();
+ break;
+
+ case sc_F9:
+ LastScan = 0;
+ Keyboard[ sc_F9 ] = 0;
+
+ loadsavesound = true;
+ CP_LoadGame( 1, 0 );
+ break;
+
+ case sc_F10:
+ SetMenuTitle ("Quit");
+
+ LastScan = 0;
+ Keyboard[ sc_F10 ] = 0;
+ CP_Quit( -1 );
+ break;
+
+ }
+
+ CleanUpControlPanel();
+ ShutdownMenuBuf();
+
+ if ( loadedgame == false )
+ {
+ SetupScreen( false );
+ fizzlein = true;
+ inmenu = false;
+ }
+
+ loadsavesound = false;
+}
+
+
+//******************************************************************************
+//
+// CP_MainMenu
+//
+//******************************************************************************
+menuitems CP_MainMenu
+(
+ void
+)
+
+{
+ int which;
+
+ SetupMenuBuf();
+
+ numdone = 0;
+
+ SetUpControlPanel();
+
+ DrawMainMenu();
+
+ //
+ // Main menu loop. "Exit options" or "New game" exits
+ //
+ StartGame = false;
+ EnableScreenStretch();
+
+ while( !StartGame )
+ {
+ StartGame = false;
+
+ IN_ClearKeysDown();
+
+ which = HandleMenu( &MainItems, &MainMenu[ 0 ], NULL );
+
+ switch( which )
+ {
+ case backtodemo:
+ if ( !ingame )
+ {
+ playstate = ex_titles;
+ }
+
+ StartGame = true;
+ DisableScreenStretch();//bna++ shut off streech mode
+ break;
+
+ case -1:
+ CP_Quit( 0 );
+ break;
+
+ default:
+ if ( !StartGame )
+ {
+ DoMainMenu();
+ }
+ }
+ }
+
+ // Deallocate everything
+ CleanUpControlPanel();
+ ShutdownMenuBuf();
+
+ return( which );
+}
+
+
+//******************************************************************************
+//
+// DrawMainMenu ()
+//
+//******************************************************************************
+
+void DrawMainMenu(void)
+{
+
+ MenuNum = 1;
+ EnableScreenStretch();//bna++ shut off streech mode
+ //
+ // CHANGE "GAME" AND "DEMO"
+ //
+ if ( ingame )
+ {
+ MainMenu[ backtodemo ].texture[ 6 ] = '1';
+ MainMenu[ backtodemo ].texture[ 7 ] = '1';
+ MainMenu[ backtodemo ].texture[ 8 ] = '\0';
+ strcpy (MainMenuNames[ backtodemo ], "BACK TO GAME");
+ }
+ else
+ {
+ MainMenu[ backtodemo ].texture[ 6 ] = '8';
+ MainMenu[ backtodemo ].texture[ 7 ] = '\0';
+ strcpy (MainMenuNames[ backtodemo ], "BACK TO DEMO");
+ }
+
+ MN_GetCursorLocation( &MainItems, &MainMenu[ 0 ] );
+ SetMenuTitle ("Main Menu");
+ DrawMenu (&MainItems, &MainMenu[0]);
+
+ numdone ++;
+ DisplayInfo (0);
+}
+
+
+//******************************************************************************
+//
+// Handle moving triad around a menu
+//
+//******************************************************************************
+
+int HandleMenu (CP_iteminfo *item_i, CP_itemtype *items, void (*routine)(int w))
+{
+
+ char key;
+ int i,
+ x,
+ y,
+ basey,
+ exit,
+ numactive,
+ count;
+ int newpos;
+ volatile int timer;
+ ControlInfo ci;
+ boolean playsnd = false;
+
+ handlewhich = item_i->curpos;
+ x = item_i->x;
+ if ((MenuNum == 4) || (MenuNum == 6) ||
+ ( item_i->fontsize == mn_smallfont ) )
+ {
+ basey = item_i->y;
+
+ CursorLump = SmallCursor;
+ yinc = 9;
+ cursorwidth = cursorheight = 8;
+ }
+ else if ( item_i->fontsize == mn_8x8font )
+ {
+ basey = item_i->y - 1;
+
+ CursorLump = SmallCursor;
+ yinc = 7;
+ cursorwidth = cursorheight = 8;
+ }
+ else if ( item_i->fontsize == mn_tinyfont )
+ {
+ basey = item_i->y - 2;
+
+ CursorLump = SmallCursor;
+ yinc = 6;
+ cursorwidth = cursorheight = 8;
+ }
+ else
+ {
+ basey = item_i->y-2;
+
+ CursorLump = LargeCursor;
+ yinc = 14;
+ cursorwidth = cursorheight = 16;
+ }
+
+
+ if (MenuNum)
+ y = basey + handlewhich*yinc;
+ else
+ y = CUSTOM_y[handlewhich];
+
+
+ if (MenuNum != 5)
+ DrawMenuBufItem (x, y, W_GetNumForName( CursorLump ) +
+ CursorFrame[ CursorNum ] );
+
+ if (routine)
+ routine (handlewhich);
+
+ count = 2;
+ exit = 0;
+ timer = GetTicCount();
+ IN_ClearKeysDown ();
+
+ numactive = GetNumActive (item_i, items);
+
+ do
+ {
+ ReadAnyControl (&ci);
+ RefreshMenuBuf (0);
+ // Change Cursor Shape
+ if ((GetTicCount() > (timer+count)) && (MenuNum != 5))
+ {
+ timer = GetTicCount();
+
+ CursorNum++;
+ if (CursorNum > (MAXCURSORNUM-1))
+ CursorNum = 0;
+
+ EraseMenuBufRegion(x, y, cursorwidth, cursorheight);
+ DrawMenuBufItem (x, y, W_GetNumForName( CursorLump ) +
+ CursorFrame[ CursorNum ] );
+
+ }
+
+ // Initial char - pass 1
+ key = getASCII ();
+ if (key)
+ {
+ int ok = 0;
+
+ key = toupper (key);
+
+ for (i = (handlewhich + 1); i < item_i->amount; i++)
+ if ((items+i)->active && (items+i)->letter == key)
+ {
+ HideCursor (item_i, items, x, y, handlewhich);
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ handlewhich = i;
+
+
+ if (routine)
+ routine (handlewhich);
+
+ ShowCursor (item_i, items, x, &y, handlewhich, basey);
+ ok = 1;
+ IN_ClearKeysDown();
+ break;
+ }
+
+ // Initial char - pass 2
+ if (!ok)
+ {
+ for (i = 0; i < handlewhich; i++)
+ if ((items+i)->active && (items+i)->letter == key)
+ {
+ HideCursor (item_i, items, x, y, handlewhich);
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ handlewhich = i;
+
+
+ if (routine)
+ routine (handlewhich);
+
+ ShowCursor (item_i, items, x,& y, handlewhich, basey);
+ IN_ClearKeysDown ();
+ break;
+ }
+ }
+ }
+
+ ReadAnyControl (&ci);
+
+ if (numactive > 1)
+ {
+ switch (ci.dir)
+ {
+ case dir_North:
+ HideCursor (item_i, items, x, y, handlewhich);
+
+
+ CursorNum++;
+ if (CursorNum > (MAXCURSORNUM-1))
+ CursorNum = 0;
+
+
+ // Do a half step if possible
+ if ((handlewhich) &&
+ (((items+handlewhich-1)->active == CP_CursorLocation) ||
+ ((items+handlewhich-1)->active == CP_Active)))
+ {
+ y -= 6;
+ DrawHalfStep (x, y);
+ playsnd = false;
+
+ RefreshMenuBuf (0);
+
+ CursorNum++;
+ if (CursorNum > (MAXCURSORNUM-1))
+ CursorNum = 0;
+ }
+ else
+ {
+ playsnd = true;
+ RefreshMenuBuf (0);
+ }
+
+ do
+ {
+ if (!handlewhich)
+ handlewhich = item_i->amount-1;
+ else
+ handlewhich--;
+ } while (((items+handlewhich)->active == CP_Inactive) || ((items+handlewhich)->active == CP_Active3));
+
+ if (playsnd)
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ ShowCursor (item_i, items, x, &y, handlewhich, basey);
+
+ if (routine)
+ routine (handlewhich);
+
+ RefreshMenuBuf(0);
+ break;
+
+ case dir_South:
+ HideCursor (item_i, items, x, y, handlewhich);
+
+ CursorNum++;
+ if (CursorNum > (MAXCURSORNUM-1))
+ CursorNum = 0;
+
+ // Do a half step if possible
+ if ((handlewhich != item_i->amount-1) &&
+ (((items+handlewhich+1)->active == CP_CursorLocation) ||
+ ((items+handlewhich+1)->active == CP_Active)))
+ {
+ y += 6;
+ DrawHalfStep(x,y);
+ playsnd = false;
+
+ RefreshMenuBuf (0);
+
+ CursorNum++;
+ if (CursorNum > (MAXCURSORNUM-1))
+ CursorNum = 0;
+ }
+ else
+ {
+ playsnd = true;
+ RefreshMenuBuf (0);
+ }
+
+ do
+ {
+ if (handlewhich==item_i->amount-1)
+ handlewhich=0;
+ else
+ handlewhich++;
+ } while (((items+handlewhich)->active == CP_Inactive) || ((items+handlewhich)->active == CP_Active3));
+
+ if (playsnd)
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ ShowCursor(item_i,items,x,&y,handlewhich,basey);
+
+ if (routine)
+ routine (handlewhich);
+
+ RefreshMenuBuf (0);
+ break;
+ default:
+ ;
+ }
+ }
+
+ ReadAnyControl (&ci);
+ if (ci.button0 || Keyboard[sc_Space] || Keyboard[sc_Enter])
+ {
+ exit = 1;
+ WaitKeyUp ();
+ MN_PlayMenuSnd (SD_SELECTSND);
+ }
+
+ if (ci.button1 || Keyboard[sc_Escape])
+ {
+ WaitKeyUp ();
+ exit = 2;
+ }
+
+ if ( ( Keyboard[ sc_Home ] ) && ( numactive > 1 ) )
+ {
+ newpos = 0;
+ while( ( items[ newpos ].active == CP_Inactive ) ||
+ ( items[ newpos ].active == CP_Active3 ) )
+ {
+ newpos++;
+ }
+
+ if ( newpos != handlewhich )
+ {
+ HideCursor( item_i, items, x, y, handlewhich );
+
+ CursorNum++;
+ if ( CursorNum > ( MAXCURSORNUM - 1 ) )
+ {
+ CursorNum = 0;
+ }
+
+ RefreshMenuBuf( 0 );
+
+ handlewhich = newpos;
+
+ MN_PlayMenuSnd( SD_MOVECURSORSND );
+
+ ShowCursor( item_i, items, x, &y, handlewhich, basey );
+
+ if ( routine )
+ {
+ routine( handlewhich );
+ }
+
+ RefreshMenuBuf( 0 );
+ }
+ }
+ else if ( ( Keyboard[ sc_End ] ) && ( numactive > 1 ) )
+ {
+ newpos = item_i->amount - 1;
+ while( ( items[ newpos ].active == CP_Inactive ) ||
+ ( items[ newpos ].active == CP_Active3 ) )
+ {
+ newpos--;
+ }
+
+ if ( newpos != handlewhich )
+ {
+ HideCursor( item_i, items, x, y, handlewhich );
+
+ CursorNum++;
+ if ( CursorNum > ( MAXCURSORNUM - 1 ) )
+ {
+ CursorNum = 0;
+ }
+
+ RefreshMenuBuf( 0 );
+
+ handlewhich = newpos;
+
+ MN_PlayMenuSnd( SD_MOVECURSORSND );
+
+ ShowCursor( item_i, items, x, &y, handlewhich, basey );
+
+ if ( routine )
+ {
+ routine( handlewhich );
+ }
+
+ RefreshMenuBuf( 0 );
+ }
+ }
+
+ // Page Up/Down
+ if ( MenuNum == 11 )
+ {
+ if ( ( Keyboard[ sc_PgUp ] ) &&
+ ( ( items + 1 )->active != CP_Inactive ) )
+ {
+ item_i->curpos = handlewhich;
+ handlewhich = PAGEUP;
+ exit = 3;
+ MN_PlayMenuSnd( SD_SELECTSND );
+ }
+ else if ( ( Keyboard[ sc_PgDn ] ) &&
+ ( ( items + 0 )->active != CP_Inactive ) )
+ {
+ item_i->curpos = handlewhich;
+ handlewhich = PAGEDOWN;
+ exit = 3;
+ MN_PlayMenuSnd( SD_SELECTSND );
+ }
+ }
+
+ // Delete save games
+ if ((MenuNum == 4) || (MenuNum == 6))
+ {
+ if (Keyboard[sc_Delete] && SaveGamesAvail[handlewhich])
+ {
+ if (CP_DisplayMsg ("Delete saved game?\nAre you sure?", 12) == true)
+ {
+ char loadname[45] = "rottgam0.rot";
+ char filename[128];
+
+ // Create the proper file name
+ itoa (handlewhich, &loadname[7], 16);
+ loadname[8]='.';
+
+ GetPathFromEnvironment( filename, ApogeePath, loadname );
+
+ // Delete the file
+
+ unlink (filename);
+
+ memset (&SaveGameNames[handlewhich][0], 0, 32);
+ SaveGamesAvail[handlewhich] = 0;
+ if (handlewhich==quicksaveslot)
+ quicksaveslot=-1;
+
+ PrintX = LSM_X+LSItems.indent+2;
+ PrintY = LSM_Y+handlewhich*9+2;
+ }
+ ScanForSavedGames ();
+
+ LSItems.curpos = handlewhich;
+ if (MenuNum == 4)
+ DrawLoadSaveScreenAlt (1);
+ else
+ DrawLoadSaveScreenAlt (0);
+ CP_DrawSelectedGame (handlewhich);
+ }
+ }
+
+
+#if SAVE_SCREEN
+ if (Keyboard[sc_CapsLock] && Keyboard[sc_C])
+ {
+ inhmenu=true;
+ SaveScreen (true);
+ inhmenu=false;
+ }
+ else if (Keyboard[sc_CapsLock] && Keyboard[sc_X])
+ {
+ inhmenu=true;
+ SaveScreen (false);
+ inhmenu=false;
+ }
+ else if (Keyboard[sc_CapsLock] && Keyboard[sc_Q])
+ Error ("Insta-Menu Quit!\n");
+#endif
+
+ } while (!exit);
+
+
+ IN_ClearKeysDown();
+
+ if (routine)
+ routine (handlewhich);
+
+ if ( exit != 3 )
+ {
+ item_i->curpos = handlewhich;
+ }
+
+ if (MenuNum == 3)
+ {
+ if (exit != 2)
+ CSTactive = handlewhich;
+ else
+ CSTactive = -1;
+ }
+
+ switch (exit)
+ {
+ case 1:
+ if ((items+handlewhich)->routine!=NULL)
+ (items+handlewhich)->routine(0);
+ return (handlewhich);
+
+ case 2:
+ MN_PlayMenuSnd (SD_ESCPRESSEDSND);
+ return (-1);
+
+ case 3:
+ return( handlewhich );
+ }
+
+
+ return (0);
+}
+
+//******************************************************************************
+//
+// HideCursor
+//
+//******************************************************************************
+void HideCursor
+(
+ CP_iteminfo *item_i,
+ CP_itemtype *items,
+ int x,
+ int y,
+ int which
+)
+
+{
+ int time = GetTicCount();
+ int color;
+ int delay;
+ int posx;
+ int posy;
+
+ if ( MenuNum != 5 )
+ {
+ EraseMenuBufRegion( x, y, cursorwidth, cursorheight );
+ }
+
+ if ( MenuNum && ( MenuNum != 4 ) && ( MenuNum != 6 ) )
+ {
+ posx = item_i->x + item_i->indent;
+ posy = item_i->y + ( which * yinc );
+
+ color = -1;
+ switch( items[ which ].active )
+ {
+ case CP_Inactive :
+ color = NOTAVAILABLECOLOR;
+ break;
+
+ case CP_CursorLocation :
+ case CP_Active :
+ color = NORMALCOLOR;
+ break;
+
+ case CP_SemiActive :
+ color = DIMMEDCOLOR;
+ break;
+
+ case CP_Highlight :
+ color = HIGHLIGHTCOLOR;
+ break;
+ }
+
+ if ( color != -1 )
+ {
+ if ( item_i->names == NULL )
+ {
+ DrawIMenuBufItem( posx, posy,
+ W_GetNumForName( items[ which ].texture ), color );
+ }
+ else
+ {
+ IFont = ( cfont_t * )W_CacheLumpName( FontNames[ item_i->fontsize ],
+ PU_CACHE, Cvt_cfont_t, 1 );
+ if ( item_i->fontsize == mn_tinyfont )
+ {
+ DrawMenuBufIString( posx + 1, posy, item_i->names[ which ], 0 );
+ }
+ DrawMenuBufIString( posx, posy - 1, item_i->names[ which ],
+ color );
+ }
+ }
+ }
+
+ if ( ( items[ which ].active != CP_Inactive ) &&
+ ( items[ which ].active != CP_SemiActive ) )
+ {
+ items[ which ].active = CP_Active;
+ }
+
+ delay = DELAYAMT - tics;
+ while( ( time + delay ) > GetTicCount() )
+ {
+ RefreshMenuBuf (0);
+ }
+}
+
+
+//******************************************************************************
+//
+// DrawHalfStep
+//
+//******************************************************************************
+
+void DrawHalfStep (int x, int y)
+{
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ if (MenuNum == 5)
+ return;
+
+ DrawMenuBufItem (x, y, W_GetNumForName( CursorLump ) +
+ CursorFrame[ CursorNum ] );
+}
+
+
+//******************************************************************************
+//
+// GetNumActive ()
+//
+//******************************************************************************
+
+int GetNumActive (CP_iteminfo *item_i, CP_itemtype *items)
+{
+ int cnt;
+ int num = 0;
+
+ for (cnt = 0; cnt < item_i->amount; cnt ++)
+ {
+ if ((items+cnt)->active != CP_Inactive)
+ num++;
+ }
+
+ return (num);
+}
+
+
+//******************************************************************************
+//
+// ShowCursor
+// Draw triad at new position.
+//
+//******************************************************************************
+void ShowCursor
+(
+ CP_iteminfo *item_i,
+ CP_itemtype *items,
+ int x,
+ int *y,
+ int which,
+ int basey
+)
+
+{
+ int time = GetTicCount();
+ int delay;
+ int posx;
+ int posy;
+
+ if ( MenuNum )
+ {
+ EraseMenuBufRegion( x, *y, cursorwidth, cursorheight );
+ *y = basey + which * yinc;
+ }
+ else
+ {
+ *y = CUSTOM_y[ which ];
+ }
+
+ if ( MenuNum != 5 )
+ {
+ DrawMenuBufItem( x, *y, W_GetNumForName( CursorLump ) +
+ CursorFrame[ CursorNum ] );
+ }
+
+ if ( items[ which ].active != CP_SemiActive )
+ {
+ if ( MenuNum && ( MenuNum != 4 ) && ( MenuNum != 6 ) )
+ {
+ posx = item_i->x + item_i->indent;
+ posy = item_i->y + which * yinc;
+
+ if ( item_i->names == NULL )
+ {
+ DrawIMenuBufItem( posx, posy,
+ W_GetNumForName( items[ which ].texture ), ACTIVECOLOR);
+ }
+ else
+ {
+ IFont = ( cfont_t * )W_CacheLumpName( FontNames[ item_i->fontsize ],
+ PU_CACHE, Cvt_cfont_t, 1 );
+ if ( item_i->fontsize == mn_tinyfont )
+ {
+ DrawMenuBufIString( posx + 1, posy, item_i->names[ which ], 0 );
+ }
+ DrawMenuBufIString( posx, posy - 1, item_i->names[ which ],
+ ACTIVECOLOR );
+ }
+ }
+
+ items[ which ].active = CP_CursorLocation;
+ }
+
+ delay = DELAYAMT - tics;
+ while( ( time + delay ) > GetTicCount() )
+ {
+ RefreshMenuBuf( 0 );
+ }
+}
+
+//******************************************************************************
+//
+// DrawOrderInfo()
+//
+//******************************************************************************
+
+void DrawOrderInfo
+(
+ int which
+)
+
+{
+ int start;
+ char *lumpname;
+
+ start = W_GetNumForName( "ORDRSTRT" ) + 1;
+
+ lumpname = W_GetNameForNum( start + which );
+
+ // Screen shots are grabbed as pics
+ if ( lumpname[ 0 ] == 'S' )
+ {
+ VWB_DrawPic( 0, 0, ( pic_t * )W_CacheLumpNum( start + which, PU_CACHE, Cvt_pic_t, 1 ) );
+ }
+ else
+ {
+ VL_DrawPostPic( W_GetNumForName( "trilogo" ) );
+ DrawNormalSprite( 0, 0, start );
+ DrawNormalSprite( 0, 0, start + which );
+ }
+
+ VW_UpdateScreen();
+}
+
+
+//******************************************************************************
+//
+// CP_OrderInfo()
+//
+//******************************************************************************
+
+void CP_OrderInfo
+(
+ void
+)
+
+{
+ int maxpage;
+ int page;
+ int key;
+ boolean newpage;
+
+
+
+ maxpage = W_GetNumForName( "ORDRSTOP" ) - W_GetNumForName( "ORDRSTRT" ) - 2;
+ newpage = false;
+ page = 1;
+
+ do
+ {
+ EnableScreenStretch();//bna++
+ DrawOrderInfo( page );
+ DisableScreenStretch();//bna++ turn off or screen will be strected every time it passes VW_UpdateScreen
+ if ( newpage )
+ {
+ while( Keyboard[ key ] )
+ {
+ VW_UpdateScreen();
+ IN_UpdateKeyboard ();
+ }
+ }
+
+ LastScan=0;
+ while( LastScan == 0 )
+ {
+ VW_UpdateScreen();
+ IN_UpdateKeyboard ();
+ }
+
+ key = LastScan;
+ switch( key )
+ {
+ case sc_Home :
+ if ( page != 1 )
+ {
+ page = 1;
+ newpage = true;
+ MN_PlayMenuSnd( SD_MOVECURSORSND );
+ }
+ break;
+
+ case sc_End :
+ if ( page != maxpage )
+ {
+ page = maxpage;
+ newpage = true;
+ MN_PlayMenuSnd( SD_MOVECURSORSND );
+ }
+ break;
+
+ case sc_PgUp :
+ case sc_UpArrow :
+ case sc_LeftArrow :
+ if ( page > 1 )
+ {
+ page--;
+ newpage = true;
+ MN_PlayMenuSnd( SD_MOVECURSORSND );
+ }
+ break;
+
+ case sc_PgDn :
+ case sc_DownArrow :
+ case sc_RightArrow :
+ if ( page < maxpage )
+ {
+ page++;
+ newpage = true;
+ MN_PlayMenuSnd( SD_MOVECURSORSND );
+ }
+ break;
+ }
+ }
+ while( key != sc_Escape );
+
+ Keyboard[ key ] = 0;
+ LastScan = 0;
+ EnableScreenStretch();//bna++
+ MN_PlayMenuSnd( SD_ESCPRESSEDSND );
+}
+
+
+//******************************************************************************
+//
+// CP_ViewScores ()
+//
+//******************************************************************************
+
+void CP_ViewScores (void)
+{
+ CheckHighScore (0, 0, true);
+}
+
+
+//******************************************************************************
+//
+// CP_Quit () - QUIT THIS INFERNAL GAME!
+//
+//******************************************************************************
+void CP_Quit ( int which )
+{
+ int num = 100;
+ static int oldnum;
+
+ while ((num >= 7) || (oldnum == num))
+ num = (RandomNumber ("CP_QUIT", 0) & 7);
+
+ oldnum = num;
+
+ if (CP_DisplayMsg (endStrings[num], num))
+ {
+ int handle;
+
+ MU_FadeOut(310);
+ handle=SD_Play(SD_QUIT1SND+num);
+ VL_FadeOut (0, 255, 0, 0, 0, 10);
+ CleanUpControlPanel();
+ SD_WaitSound (handle);
+ QuitGame ();
+ }
+
+ if ( which != -1 )
+ {
+ ClearMenuBuf();
+ DrawMainMenu();
+ DrawMenuBufItem (MainItems.x, ((MainItems.curpos*14)+(MainItems.y-2)),
+ W_GetNumForName ( LargeCursor ) + CursorFrame[ CursorNum ] );
+ RefreshMenuBuf (0);
+ }
+}
+
+//******************************************************************************
+//
+// CP_DisplayMsg ()
+//
+//******************************************************************************
+
+boolean CP_DisplayMsg
+(
+ char *s,
+ int number
+)
+
+{
+#define Q_W 184
+#define Q_H 72
+#define Q_X ((320-Q_W)/2)-18
+#define Q_Y ((200-Q_H)/2)-33
+
+#define Q_b1X (Q_X+85)
+#define Q_b2X (Q_X+135)
+#define Q_bY (Q_Y+45)
+#define Q_bW 33
+#define Q_bH 10
+
+#define W_X 72
+#define W_Y 11
+#define W_W 102
+
+#define YES "q_yes\0"
+#define NO "q_no\0"
+
+ ControlInfo ci;
+ boolean retval;
+ boolean done;
+ boolean YESON;
+ boolean redraw;
+ boolean blowout;
+ char *temp;
+ char *active;
+ char *inactive;
+ int activex;
+ int inactivex;
+ int W_H = 0;
+ int L_Y = 0;
+ int tri;
+ int QUITPIC;
+ int t;
+
+ W_H = 1;
+ retval = false;
+ done = false;
+ YESON = true;
+ redraw = false;
+ blowout = false;
+
+ IN_ClearKeysDown();
+ IN_IgnoreMouseButtons();
+
+
+ QUITPIC = W_GetNumForName( "quitpic" );
+
+ if ( number < 11 )
+ {
+ tri = W_GetNumForName( "QUIT01" ) + number;
+ MN_PlayMenuSnd( SD_WARNINGBOXSND );
+ }
+ else
+ {
+ if ( number == 11 )
+ {
+ tri = W_GetNumForName( "tri1pic" );
+ MN_PlayMenuSnd( SD_INFOBOXSND );
+ }
+ else
+ {
+ if ( number == 12 )
+ {
+ tri = W_GetNumForName( "tri2pic" );
+ MN_PlayMenuSnd( SD_QUESTIONBOXSND );
+ }
+ if ( number == 13 )
+ {
+ tri = W_GetNumForName( "tri1pic" );
+ MN_PlayMenuSnd( SD_WARNINGBOXSND );
+ }
+ }
+ }
+
+ DrawMenuBufPic( Q_X, Q_Y, QUITPIC );
+ DrawMenuBufPic( Q_X + 12, Q_Y + 11, tri );
+
+ temp = s;
+ while( *temp )
+ {
+ if ( *temp == '\n' )
+ {
+ W_H++;
+ }
+ temp++;
+ }
+
+ CurrentFont = tinyfont;
+ W_H = ( W_H * CurrentFont->height ) + 3;
+
+ WindowX = Q_X + W_X;
+ WindowY = L_Y + 2;
+ L_Y = Q_Y + W_Y;
+ PrintX = WindowX;
+ PrintY = WindowY;
+
+ WindowW = W_W;
+ WindowH = W_H;
+
+ redraw = true;
+
+ IFont = ( cfont_t * )W_CacheLumpName( FontNames[ mn_smallfont ],
+ PU_CACHE, Cvt_cfont_t, 1 );
+ /*
+ DrawSTMenuBuf( WindowX, L_Y, W_W, W_H, false );
+ MenuBufCPrint( s );
+
+ DrawSTMenuBuf( Q_b1X, Q_bY, Q_bW, Q_bH, false );
+ DrawMenuBufIString( Q_b1X + 3, Q_Y + 46, "YES", NORMALCOLOR );
+ // DrawIMenuBufItem (PrintX, PrintY, W_GetNumForName (YES), NORMALCOLOR);
+
+ DrawSTMenuBuf( Q_b2X, Q_bY, Q_bW, Q_bH, true );
+ DrawMenuBufIString( Q_b2X + 2, Q_Y + 45, "NO", ACTIVECOLOR );
+ // DrawIMenuBufItem (PrintX, PrintY, W_GetNumForName (NO), ACTIVECOLOR);
+ */
+ if (number != 13)
+ {
+ while ( !done )
+ {
+ RefreshMenuBuf( 0 );
+
+ ReadAnyControl( &ci );
+
+ if ( ( ci.dir == dir_West ) && ( !YESON ) )
+ {
+ MN_PlayMenuSnd( SD_MOVECURSORSND );
+ YESON = 1;
+ redraw = true;
+ }
+ else if ( ( ci.dir == dir_East ) && ( YESON ) )
+ {
+ MN_PlayMenuSnd( SD_MOVECURSORSND );
+ YESON = 0;
+ redraw = true;
+ }
+
+ if ( Keyboard[ sc_Y ] )
+ {
+ YESON = 1;
+ redraw = true;
+ Keyboard[ sc_Enter ] = true;
+ blowout = true;
+ }
+ else if ( Keyboard[ sc_N ] )
+ {
+ YESON = 0;
+ redraw = true;
+ Keyboard[ sc_Enter ] = true;
+ blowout = true;
+ }
+
+ if ( redraw )
+ {
+ redraw = false;
+
+ DrawMenuBufPic( Q_X, Q_Y, QUITPIC );
+ DrawMenuBufPic( Q_X + 12, Q_Y + 11, tri );
+
+ PrintX = Q_X + W_X;
+ PrintY = Q_Y + W_Y + 2;
+ DrawSTMenuBuf( WindowX, L_Y, W_W, W_H, false );
+ CurrentFont = tinyfont;
+ MenuBufCPrint( s );
+
+ if ( YESON )
+ {
+ active = "YES";
+ inactive = "NO";
+ activex = Q_b1X;
+ inactivex = Q_b2X;
+ }
+ else
+ {
+ active = "NO";
+ inactive = "YES";
+ activex = Q_b2X;
+ inactivex = Q_b1X;
+ }
+
+ DrawSTMenuBuf( activex, Q_bY, Q_bW, Q_bH, false );
+ DrawMenuBufIString( activex + 3, Q_Y + 46, active, ACTIVECOLOR );
+// DrawIMenuBufItem (PrintX, PrintY, W_GetNumForName (YES), NORMALCOLOR);
+
+ DrawSTMenuBuf( inactivex, Q_bY, Q_bW, Q_bH, true );
+ DrawMenuBufIString( inactivex + 2, Q_Y + 45, inactive, NORMALCOLOR );
+// DrawIMenuBufItem (PrintX, PrintY, W_GetNumForName (NO), ACTIVECOLOR);
+
+ for( t = 0; t < 5; t++ )
+ {
+ RefreshMenuBuf( 0 );
+ }
+ }
+
+ if ( ( Keyboard[ sc_Space ] || Keyboard[ sc_Enter ] ||
+ ci.button0 ) && YESON )
+ {
+ done = true;
+ retval = true;
+ MN_PlayMenuSnd( SD_SELECTSND );
+ CP_Acknowledge = CP_YES;
+ }
+ else if ( Keyboard[ sc_Escape ] || ci.button1 )
+ {
+ done = true;
+ retval = false;
+ CP_Acknowledge = CP_ESC;
+ MN_PlayMenuSnd( SD_ESCPRESSEDSND );
+ }
+ else if ( ( Keyboard[ sc_Space ] || Keyboard[ sc_Enter ] ||
+ ci.button0 ) && !YESON )
+ {
+ done = true;
+ retval = false;
+ CP_Acknowledge = CP_NO;
+
+ if ( Keyboard[ sc_N ] )
+ {
+ MN_PlayMenuSnd( SD_SELECTSND );
+ }
+ else
+ {
+ MN_PlayMenuSnd( SD_ESCPRESSEDSND );
+ }
+ }
+ }
+
+ while( ( Keyboard[ sc_Enter ] || Keyboard[ sc_Space ] ||
+ Keyboard[ sc_Escape ] ) && !blowout )
+ {
+ IN_UpdateKeyboard();
+ RefreshMenuBuf( 0 );
+ }
+ }
+ else
+ {
+ PrintX = Q_X + W_X;
+ PrintY = Q_Y + W_Y + 2;
+ DrawSTMenuBuf( WindowX, L_Y, W_W, W_H, false );
+ CurrentFont = tinyfont;
+ MenuBufCPrint( s );
+ LastScan=0;
+ while (LastScan == 0)
+ {
+ IN_UpdateKeyboard();
+ RefreshMenuBuf( 0 );
+ }
+ LastScan = 0;
+ }
+ IN_ClearKeysDown();
+ return( retval );
+}
+
+
+//******************************************************************************
+//
+// EndGameStuff ()
+//
+//******************************************************************************
+
+void EndGameStuff (void)
+{
+ Z_FreeTags( PU_LEVELSTRUCT, PU_LEVELEND );
+
+ pickquick = false;
+ CheckHighScore (gamestate.score, gamestate.mapon+1, true);
+ locplayerstate->lives = 0;
+ playstate = ex_died;
+ damagecount = 0;
+ SetBorderColor (0);
+
+ AdjustMenuStruct ();
+ ingame = false;
+
+ GamePaused = false;
+}
+
+
+//******************************************************************************
+//
+// START A NEW GAME
+//
+//******************************************************************************
+
+#define CURGAME "You are currently in\n"\
+ "a game. Continuing will\n"\
+ "erase old game. Ok?\0"
+
+int ToughMenuNum;
+
+void CP_NewGame
+(
+ void
+)
+
+{
+ int which;
+
+#if ( SHAREWARE == 1 )
+ ToughMenuNum = 0;
+#else
+ int temp;
+
+ temp = ToughMenuNum;
+
+ while( ToughMenuNum == temp )
+ {
+ temp = ( ( RandomNumber( "TOUGH MENU", 0 ) ) & 3 );
+ if ( temp == 3 )
+ {
+ temp = 1;
+ }
+ }
+
+ ToughMenuNum = temp;
+#endif
+
+ //
+ // ALREADY IN A GAME?
+ //
+ if ( ingame )
+ {
+ if ( !CP_DisplayMsg( CURGAME, 12 ) )
+ {
+ return;
+ }
+ else
+ {
+ EndGameStuff();
+ }
+ }
+ else
+ {
+ handlewhich = 100;
+ }
+
+ if ( CP_PlayerSelection() == 0 )
+ {
+ return;
+ }
+
+ TufMenu[ ToughMenuNum ][ 0 ].active = CP_Active;
+ TufMenu[ ToughMenuNum ][ 2 ].active = CP_Active;
+ TufMenu[ ToughMenuNum ][ 4 ].active = CP_Active;
+ TufMenu[ ToughMenuNum ][ 6 ].active = CP_Active;
+
+ switch( DefaultDifficulty )
+ {
+ case gd_baby :
+ TufItems.curpos = 0;
+ break;
+
+ case gd_easy :
+ TufItems.curpos = 2;
+ break;
+
+ case gd_medium :
+ TufItems.curpos = 4;
+ break;
+
+ case gd_hard :
+ TufItems.curpos = 6;
+ break;
+
+ default :
+ TufItems.curpos = 0;
+ break;
+ }
+
+ TufMenu[ ToughMenuNum ][ TufItems.curpos ].active = CP_CursorLocation;
+
+ DrawNewGame();
+
+ which = HandleMenu( &TufItems, &TufMenu[ ToughMenuNum ][ 0 ],
+ DrawNewGameDiff );
+
+ if ( which < 0 )
+ {
+ handlewhich = 1;
+ return;
+ }
+
+ handlewhich = 0;
+
+ switch( which )
+ {
+ case 0 :
+ DefaultDifficulty = gd_baby;
+ break;
+
+ case 2 :
+ DefaultDifficulty = gd_easy;
+ break;
+
+ case 4 :
+ DefaultDifficulty = gd_medium;
+ break;
+
+ case 6 :
+ DefaultDifficulty = gd_hard;
+ break;
+ }
+
+ MainMenu[ savegame ].active = CP_Active;
+
+ gamestate.battlemode = battle_StandAloneGame;
+ StartGame = true;
+ DisableScreenStretch();
+ playstate = ex_resetgame;
+
+
+}
+
+//******************************************************************************
+//
+// CP_EndGame ()
+//
+//******************************************************************************
+
+#define ENDGAMESTR "Are you sure you want\n"\
+ "to end the game you\n"\
+ "are playing? (Y or N):"
+
+void CP_EndGame
+(
+ void
+)
+
+{
+ boolean action;
+
+ SetMenuTitle( "End Game" );
+ action = CP_DisplayMsg( ENDGAMESTR, 12 );
+
+ StartGame = false;
+ EnableScreenStretch();
+ if ( action )
+ {
+ EndGameStuff ();
+ pickquick = false;
+ }
+}
+
+//******************************************************************************
+//
+// AdjustMenuStruct ()
+//
+//******************************************************************************
+void AdjustMenuStruct
+(
+ void
+)
+
+{
+ MainMenu[ savegame ].active = CP_Inactive;
+ MainMenu[ viewscores ].routine = ( void * )CP_ViewScores;
+ MainMenu[ viewscores ].texture[ 6 ] = '7';
+ MainMenu[ viewscores ].texture[ 7 ] = '\0';
+ MainMenu[ viewscores ].letter = 'V';
+ strcpy (MainMenuNames[ viewscores ], "VIEW SCORES");
+}
+
+//******************************************************************************
+//
+// CP_DrawSelectedGame
+//
+//******************************************************************************
+
+void CP_DrawSelectedGame (int w)
+{
+ gamestorage_t game;
+
+ if (SaveGamesAvail[w])
+ {
+ GetSavedHeader(w,&game);
+
+ DrawStoredGame(&game.picture[0],game.episode,game.area);
+ }
+ else
+ EraseMenuBufRegion(SaveGamePicX,SaveGamePicY,160,124);
+}
+
+//******************************************************************************
+//
+// DrawStoredGame
+//
+//******************************************************************************
+
+void DrawStoredGame ( byte * pic, int episode, int area )
+{
+ char str[3];
+ int level;
+ byte *shape;
+
+ shape = W_CacheLumpNum (W_GetNumForName ("newfnt1"), PU_CACHE, Cvt_font_t, 1);
+ newfont1 = (font_t *)shape;
+ CurrentFont = newfont1;
+ EraseMenuBufRegion (74, 128, 85, 14);
+
+ DrawMenuBufPropString (74, 128, "E");
+
+ itoa (episode, str, 10);
+ DrawMenuBufPropString (87, 128, str);
+
+ DrawMenuBufPropString (103, 128, "A");
+
+ if (episode > 1)
+ level = (area+1) - ((episode-1) << 3);
+ else
+ level = area+1;
+
+ ltoa (level, str, 10);
+ DrawMenuBufPropString (117, 128, str);
+ CurrentFont = tinyfont;
+
+ DrawMenuBufPicture(SaveGamePicX,SaveGamePicY,pic,160,100);
+}
+
+
+
+//******************************************************************************
+//
+// DoLoad ()
+//
+//******************************************************************************
+
+int DoLoad (int which)
+{
+ gamestorage_t game;
+ int exit = 0;
+
+ if ((which >= 0) && SaveGamesAvail[which])
+ {
+ loadedgame = true;
+
+ if (loadsavesound)
+ MN_PlayMenuSnd (SD_SELECTSND);
+
+ if (LoadTheGame (which, &game) == true)
+ {
+ MenuFixup ();
+ DisableScreenStretch();
+ StartGame = true;
+ exit = 1;
+ }
+ else
+ {
+ if (CP_DisplayMsg ("Saved Game is\n old or incompatible\nDelete it?", 12)==true)
+ {
+ char loadname[45] = "rottgam0.rot";
+ char filename[128];
+
+ // Create the proper file name
+ itoa (which, &loadname[7], 16);
+ loadname[8]='.';
+
+ GetPathFromEnvironment( filename, ApogeePath, loadname );
+
+ // Delete the file
+
+ unlink (filename);
+
+ memset (&SaveGameNames[which][0], 0, 32);
+ SaveGamesAvail[which] = 0;
+ }
+
+ loadedgame = false;
+ DrawLoadSaveScreenAlt (0);
+ }
+ }
+
+ return (exit);
+}
+
+
+//******************************************************************************
+//
+// LOAD SAVED GAMES
+//
+//******************************************************************************
+
+int CP_LoadGame (int quick, int dieload)
+{
+ int which,
+ exit = 0;
+
+
+ MenuNum = 6;
+
+ SaveTime = GetTicCount();
+
+ //
+ // QUICKLOAD?
+ //
+ if (quick)
+ {
+ which = LSItems.curpos;
+
+ if (SaveGamesAvail[which])
+ {
+ if (dieload)
+ {
+ DrawLoadSaveScreenAlt (0);
+ CP_DrawSelectedGame (which);
+ RefreshMenuBuf (0);
+ DoLoad (which);
+
+ return (1);
+ }
+ else
+ {
+ DrawLoadSaveScreen (0);
+ if (CP_DisplayMsg ("Quick load saved game?\nAre you sure?", 12) == true)
+ {
+ DrawLoadSaveScreen (0);
+ CP_DrawSelectedGame (which);
+ RefreshMenuBuf (0);
+ DoLoad (which);
+
+ return (1);
+ }
+ else
+ {
+ return (0);
+ }
+ }
+ }
+ }
+
+ DrawLoadSaveScreen (0);
+ do
+ {
+ which = HandleMenu (&LSItems, &LSMenu[0], CP_DrawSelectedGame);
+
+ if ((exit = DoLoad (which)))
+ break;
+
+ } while (which >= 0);
+
+ handlewhich = OUTOFRANGE;
+
+ if (MainMenu[loadgame].active == CP_Inactive) // If all the saved games have been
+ {
+ MainItems.curpos = 0; // deleted dehighlight LOADGAME
+ MainMenu[newgame].active = CP_CursorLocation;
+ }
+
+ return exit;
+}
+
+//******************************************************************************
+//
+// QuickSaveGame ()
+//
+//******************************************************************************
+
+void QuickSaveGame (void)
+{
+ int i;
+ int j;
+ byte * b;
+ byte * s;
+ int which;
+ gamestorage_t game;
+ byte * buf;
+ int length;
+
+ char loadname[45]="rottgam0.rot";
+ char filename[128];
+
+ // Create the proper file name
+
+ itoa(quicksaveslot,&loadname[7],16);
+ loadname[8]='.';
+
+ GetPathFromEnvironment( filename, ApogeePath, loadname );
+ length=LoadFile(filename,(void **)&buf);
+ GetPathFromEnvironment( filename, ApogeePath, QUICKSAVEBACKUP );
+ SaveFile(filename,buf,length);
+ SafeFree(buf);
+
+ s=&game.picture[0];
+ for (i=0; i<320; i+=2)
+ {
+#ifdef DOS
+ VGAREADMAP(i&3);
+ b=(byte *)bufferofs+(i>>2);
+ for (j=0; j<100; j++,s++,b+=iGLOBAL_SCREENBWIDE<<1)
+ *s=*b;
+#else
+ b=(byte *)bufferofs+i;
+ for (j=0; j<100; j++,s++,b+=(iGLOBAL_SCREENWIDTH<<1))
+ *s=*b;
+#endif
+ }
+
+ ScanForSavedGames ();
+ which = quicksaveslot;
+
+ if (SaveGamesAvail[which])
+ {
+ game.episode = gamestate.episode;
+ game.area = gamestate.mapon;
+ game.version = ROTTVERSION;
+ strcpy (game.message, &SaveGameNames[which][0]);
+
+ if (SaveTheGame (which, &game) == true)
+ {
+ char str[50];
+
+ strcpy (str, "Game Saved: ");
+ strcat (str, &SaveGameNames[which][0]);
+ AddMessage(str,MSG_SYSTEM);
+ }
+ else
+ {
+ AddMessage("Game Not Saved.",MSG_SYSTEM);
+ }
+ }
+ else
+ {
+ AddMessage("No Quick Save Slot.",MSG_SYSTEM);
+ }
+
+}
+
+//******************************************************************************
+//
+// UndoQuickSaveGame ()
+//
+//******************************************************************************
+
+void UndoQuickSaveGame (void)
+{
+ byte * buf;
+ char loadname[45]="rottgam0.rot";
+ char filename[128];
+ int length;
+
+ if (quicksaveslot!=-1)
+ {
+ // Create the proper file name
+
+ itoa(quicksaveslot,&loadname[7],16);
+ loadname[8]='.';
+ GetPathFromEnvironment( filename, ApogeePath, QUICKSAVEBACKUP );
+ length=LoadFile(filename,(void **)&buf);
+ GetPathFromEnvironment( filename, ApogeePath, loadname );
+ SaveFile(filename,buf,length);
+ SafeFree(buf);
+ AddMessage("Previous Quicksave Game Restored.",MSG_SYSTEM);
+ }
+ else
+ {
+ AddMessage("No Quick Save Slot Selected.",MSG_SYSTEM);
+ }
+}
+
+
+//******************************************************************************
+//
+// SAVE CURRENT GAME
+//
+//******************************************************************************
+int CP_SaveGame ( void )
+{
+ int which,
+ exit=0;
+
+ char input[32];
+ gamestorage_t game;
+
+
+ MenuNum = 4;
+
+
+ DrawLoadSaveScreen (1);
+
+ do
+ {
+ which = HandleMenu (&LSItems, &LSMenu[0], CP_DrawSelectedGame);
+ if (which >= 0)
+ {
+ //
+ // OVERWRITE EXISTING SAVEGAME?
+ //
+ if (SaveGamesAvail[which]) {
+ if (!CP_DisplayMsg (GAMESVD, 12))
+ {
+ DrawLoadSaveScreenAlt (1);
+ continue;
+ }
+ else
+ {
+ DrawLoadSaveScreenAlt (1);
+ EraseMenuBufRegion (LSM_X+LSItems.indent, LSM_Y+1+which*9, 80, 8);
+ PrintLSEntry (which);
+ }
+ }
+ quicksaveslot=which;
+
+ DrawStoredGame (savedscreen, gamestate.episode, gamestate.mapon);
+
+ strcpy (input, &SaveGameNames[which][0]);
+
+ if (!SaveGamesAvail[which])
+ EraseMenuBufRegion (LSM_X+LSItems.indent+1, LSM_Y+which*9+2,
+ 77, 6);
+
+ if (US_LineInput (LSM_X+LSItems.indent+2, LSM_Y+which*9+2,
+ input, input, true, 22, 75, 0))
+ {
+ SaveGamesAvail[which] = 1;
+ memcpy(&game.picture[0],savedscreen,16000);
+ game.episode=gamestate.episode;
+ game.area=gamestate.mapon;
+ game.version=ROTTVERSION;
+ strcpy (game.message, input);
+ strcpy (&SaveGameNames[which][0], input);
+
+ if (SaveTheGame(which,&game)==true)
+ {
+ MainMenu[loadgame].active=CP_Active;
+
+// MN_PlayMenuSnd (SD_SELECTSND);
+ exit = 1;
+ }
+ WaitKeyUp ();
+ }
+ else
+ {
+ EraseMenuBufRegion (LSM_X+LSItems.indent+1, LSM_Y+which*9+2,
+ 77, 6);
+
+ PrintX = LSM_X+LSItems.indent+2;
+ PrintY = LSM_Y+which*9+2;
+
+ if (SaveGamesAvail[which])
+ DrawMenuBufPropString (PrintX, PrintY, SaveGameNames[which]);
+ else
+ DrawMenuBufPropString (PrintX, PrintY, " - � -");
+
+// MN_PlayMenuSnd (SD_ESCPRESSEDSND);
+ continue;
+ }
+ break;
+ }
+
+ } while (which >= 0);
+
+ handlewhich = OUTOFRANGE;
+
+ return (exit);
+}
+
+
+
+//******************************************************************************
+//
+// DEFINE CONTROLS
+//
+//******************************************************************************
+
+void CP_Control (void)
+{
+#define CTL_SPC 70
+
+ int which;
+
+ DrawCtlScreen ();
+ WaitKeyUp ();
+
+ do
+ {
+ which = HandleMenu (&CtlItems, &CtlMenu[0], NULL);
+
+ switch (CSTactive)
+ {
+ case MOUSEENABLE:
+ if (MousePresent)
+ {
+ mouseenabled^=1;
+ DrawCtlButtons ();
+ CusItems.curpos=-1;
+ }
+ else
+ mouseenabled = 0;
+ break;
+
+ case JOYENABLE:
+ joystickenabled^=1;
+ if ( joystickenabled )
+ {
+ if ( !CalibrateJoystick() )
+ {
+ joystickenabled = 0;
+ joypadenabled = 0;
+ }
+ }
+ else
+ {
+ joypadenabled = 0;
+ }
+ DrawCtlScreen();
+ break;
+
+ case USEPORT2:
+ joystickport^=1;
+ if ( joystickport )
+ {
+ joypadenabled = 0;
+ }
+
+ joystickenabled = 1;
+ if ( !CalibrateJoystick() )
+ {
+ joystickenabled = 0;
+ joystickport = 0;
+ }
+
+ if ( joystickport )
+ {
+ CtlMenu[ 3 ].active = CP_Inactive;
+ joypadenabled = 0;
+ }
+ else
+ {
+ CtlMenu[ 3 ].active = CP_Active;
+ }
+
+ DrawCtlScreen();
+ break;
+
+ case PADENABLE:
+ joypadenabled^=1;
+ if ( ( joypadenabled ) && ( !joystickenabled ) )
+ {
+ joystickenabled=1;
+ if ( !CalibrateJoystick() )
+ {
+ joystickenabled = 0;
+ joypadenabled = 0;
+ }
+
+ DrawCtlScreen();
+ }
+ else
+ {
+ DrawCtlButtons ();
+ }
+ break;
+
+ case SPACEBALLENABLE:
+ spaceballenabled ^= 1;
+ DrawCtlButtons ();
+ break;
+
+ case CYBERMANENABLE:
+ cybermanenabled ^= 1;
+ DrawCtlButtons ();
+ break;
+
+ case THRESSENS:
+ case MOUSESENS:
+ case CUSTOMIZE:
+ DrawCtlScreen ();
+ break;
+ }
+
+ } while (which >= 0);
+
+ DrawControlMenu ();
+
+ if (which < 0)
+ {
+ handlewhich = 1;
+ return;
+ }
+}
+
+
+//****************************************************************************
+//
+// CP_Custom ()
+//
+//****************************************************************************
+
+void CP_Custom (void)
+{
+ int which;
+
+ DrawCustomMenu();
+
+ do
+ {
+ which = HandleMenu (&CustomItems, &CustomMenu[0], NULL);
+ } while (which >= 0);
+
+ DrawCtlScreen ();
+}
+
+
+//******************************************************************************
+//
+// CUSTOMIZE CONTROLS
+//
+//******************************************************************************
+
+//****************************************************************************
+//
+// CP_Keyboard ()
+//
+//****************************************************************************
+void CP_Keyboard
+(
+ void
+)
+
+{
+ int which;
+
+ MenuNum = 1;
+
+ DrawCustomKeyboard ();
+
+ do
+ {
+ which = HandleMenu( &NormalKeyItems, &NormalKeyMenu[ 0 ], NULL );
+ }
+ while( which >= 0 );
+
+ DrawCustomMenu();
+}
+
+
+//******************************************************************************
+//
+// DEFINE THE KEYBOARD BUTTONS
+//
+//******************************************************************************
+
+void DefineKey
+(
+ void
+)
+
+{
+ boolean tick;
+ boolean picked;
+ int timer;
+ int x;
+ int y;
+
+ tick = false;
+ picked = false;
+ timer = GetTicCount();
+
+ x = NORMALKEY_X + 97;
+ y = NORMALKEY_Y + ( handlewhich * FontSize[ NormalKeyItems.fontsize ] );
+
+ strcpy( &NormalKeyNames[ handlewhich ][ KEYNAMEINDEX ],
+ " " );
+
+// SetMenuTitle ( "Select which key to use" );
+ ClearMenuBuf();
+ DrawMenu( &NormalKeyItems, &NormalKeyMenu[ 0 ] );
+ DisplayInfo( 0 );
+
+ DrawMenuBufIString( x + 3, y, "?", 0 );
+ DrawMenuBufIString( x + 2, y - 1, "?", HIGHLIGHTCOLOR );
+
+ RefreshMenuBuf( 0 );
+
+ do
+ {
+
+ IN_PumpEvents();
+
+ //
+ // FLASH CURSOR
+ //
+ if ( ( GetTicCount() - timer ) > 10 )
+ {
+ int color;
+
+ if ( tick )
+ {
+ color = HIGHLIGHTCOLOR;
+ }
+ else
+ {
+ color = DIMMEDCOLOR;
+ }
+
+ DrawMenuBufIString( x + 3, y, "?", 0 );
+ DrawMenuBufIString( x + 2, y - 1, "?", color );
+
+ tick = !tick;
+ timer = GetTicCount();
+ }
+
+ RefreshMenuBuf( 0 );
+
+
+ if ( LastScan )
+ {
+ int key;
+
+ key = LastScan;
+ LastScan = 0;
+
+ buttonscan[ (unsigned int)order[ handlewhich ] ] = key;
+
+ strcpy( &NormalKeyNames[ handlewhich ][ KEYNAMEINDEX ],
+ IN_GetScanName( key ) );
+
+ picked = true;
+
+ WaitKeyUp();
+ Keyboard[ key ] = 0;
+
+ IN_ClearKeysDown();
+ }
+ }
+ while( !picked );
+
+ ClearMenuBuf();
+ SetMenuTitle( "Customize Keyboard" );
+
+ DrawMenu( &NormalKeyItems, &NormalKeyMenu[ 0 ] );
+ DisplayInfo( 0 );
+ RefreshMenuBuf (0);
+}
+
+//****************************************************************************
+//
+// DrawControlSelect ()
+//
+//****************************************************************************
+
+void DrawControlSelect
+(
+ void
+)
+
+{
+ MenuNum = 1;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Select Button Function");
+
+ MN_GetCursorLocation( &ControlSelectItems, &ControlSelectMenu[ 0 ] );
+ DrawMenu( &ControlSelectItems, &ControlSelectMenu[ 0 ] );
+
+ DisplayInfo( 0 );
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// DefineMouseBtn()
+//
+//****************************************************************************
+
+void DefineMouseBtn
+(
+ void
+)
+
+{
+ int button;
+ int which;
+
+ button = handlewhich;
+
+ MN_GetActive( &ControlSelectItems, &ControlSelectMenu[ 0 ],
+ buttonmouse[ button ], controlorder );
+
+ DrawControlSelect();
+
+ which = HandleMenu( &ControlSelectItems, &ControlSelectMenu[ 0 ], NULL );
+ if ( which != -1 )
+ {
+ buttonmouse[ button ] = controlorder[ which ];
+ }
+
+ handlewhich = OUTOFRANGE;
+}
+
+//****************************************************************************
+//
+// CP_Mouse ()
+//
+//****************************************************************************
+void CP_Mouse
+(
+ void
+)
+
+{
+ int which;
+
+ MenuNum = 1;
+
+ do
+ {
+ DrawCustomMouse();
+ which = HandleMenu( &MouseBtnItems, &MouseBtnMenu[ 0 ], NULL );
+ }
+ while( which >= 0 );
+
+ handlewhich = OUTOFRANGE;
+
+ DrawCustomMenu();
+}
+
+
+//****************************************************************************
+//
+// DrawCustomMouse ()
+//
+//****************************************************************************
+
+void DrawCustomMouse
+(
+ void
+)
+
+{
+ int i;
+ int j;
+ int num;
+ int button;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Customize Mouse");
+
+ for( i = 0; i < 6; i++ )
+ {
+ num = 0;
+ button = buttonmouse[ i ];
+ buttonmouse[ i ] = bt_nobutton;
+ MouseBtnNames[ i ][ MOUSEBTNINDEX ] = 0;
+
+ for( j = 0; j < NUMCONTROLNAMES; j++ )
+ {
+ if ( button == controlorder[ j ] )
+ {
+ buttonmouse[ i ] = button;
+ num = j;
+ break;
+ }
+ }
+
+ strcpy( &MouseBtnNames[ i ][ MOUSEBTNINDEX ],
+ ControlNames[ num ] );
+ }
+
+ MN_GetCursorLocation( &MouseBtnItems, &MouseBtnMenu[ 0 ] );
+ DrawMenu( &MouseBtnItems, &MouseBtnMenu[ 0 ] );
+
+ DisplayInfo( 0 );
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// DefineJoyBtn()
+//
+//****************************************************************************
+
+void DefineJoyBtn
+(
+ void
+)
+
+{
+ int button;
+ int which;
+
+ button = handlewhich;
+
+ MN_GetActive( &ControlSelectItems, &ControlSelectMenu[ 0 ],
+ buttonjoy[ button ], controlorder );
+
+ DrawControlSelect();
+
+ which = HandleMenu( &ControlSelectItems, &ControlSelectMenu[ 0 ], NULL );
+ if ( which != -1 )
+ {
+ buttonjoy[ button ] = controlorder[ which ];
+ }
+
+ handlewhich = OUTOFRANGE;
+}
+
+
+//****************************************************************************
+//
+// DrawCustomJoystick ()
+//
+//****************************************************************************
+
+void DrawCustomJoystick
+(
+ void
+)
+
+{
+ int i;
+ int j;
+ int num;
+ int button;
+ int active;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Customize Joystick");
+
+ for( i = 0; i < 8; i++ )
+ {
+ num = 0;
+ button = buttonjoy[ i ];
+ buttonjoy[ i ] = bt_nobutton;
+ JoyBtnNames[ i ][ JOYBTNINDEX ] = 0;
+
+ for( j = 0; j < NUMCONTROLNAMES; j++ )
+ {
+ if ( button == controlorder[ j ] )
+ {
+ buttonjoy[ i ] = button;
+ num = j;
+ break;
+ }
+ }
+
+ strcpy( &JoyBtnNames[ i ][ JOYBTNINDEX ], ControlNames[ num ] );
+ }
+
+ JoyBtnMenu[ 0 ].active = CP_Active;
+ JoyBtnMenu[ 1 ].active = CP_Active;
+ JoyBtnMenu[ 4 ].active = CP_Active;
+ JoyBtnMenu[ 5 ].active = CP_Active;
+
+ if ( joypadenabled )
+ {
+ active = CP_Active;
+ }
+ else
+ {
+ active = CP_Inactive;
+ }
+
+ JoyBtnMenu[ 2 ].active = active;
+ JoyBtnMenu[ 3 ].active = active;
+ JoyBtnMenu[ 6 ].active = active;
+ JoyBtnMenu[ 7 ].active = active;
+
+ if ( JoyBtnMenu[ JoyBtnItems.curpos ].active == CP_Inactive )
+ {
+ MN_GetCursorLocation( &JoyBtnItems, &JoyBtnMenu[ 0 ] );
+ }
+ else
+ {
+ JoyBtnMenu[ JoyBtnItems.curpos ].active = CP_CursorLocation;
+ }
+
+ DrawMenu( &JoyBtnItems, &JoyBtnMenu[ 0 ] );
+
+ DisplayInfo( 0 );
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// CP_Joystick ()
+//
+//****************************************************************************
+
+void CP_Joystick
+(
+ void
+)
+
+{
+ int which;
+
+ MenuNum = 1;
+
+ do
+ {
+ DrawCustomJoystick();
+ which = HandleMenu( &JoyBtnItems, &JoyBtnMenu[ 0 ], NULL );
+ }
+ while( which >= 0 );
+
+ handlewhich = OUTOFRANGE;
+
+ DrawCustomMenu();
+}
+
+
+//******************************************************************************
+//
+// PRINT A MESSAGE IN A WINDOW
+//
+//******************************************************************************
+
+void Message (char *string)
+{
+ int h = 0,
+ w = 0,
+ mw = 0,
+ i;
+ byte *shape;
+
+ shape = W_CacheLumpNum (W_GetNumForName ("newfnt1"), PU_CACHE, Cvt_font_t, 1);
+ newfont1 = (font_t *)shape;
+ CurrentFont = newfont1;
+ h = CurrentFont->height;
+
+ for (i = 0; i < (int)strlen (string); i++)
+ if (string[i] == '\n')
+ {
+ if (w > mw)
+ mw = w;
+ w = 0;
+ h += CurrentFont->height;
+ }
+ else
+ w += CurrentFont->width[string[i]-31];
+
+ if ((w + 10) > mw)
+ mw = w+10;
+
+ PrintY = 78 - (h / 2);
+ PrintX = WindowX = 143 - (mw / 2);
+ WindowW = mw;
+
+ EraseMenuBufRegion (WindowX-5, PrintY-5, (mw+14)&0xFFFC, h+10);
+ DrawSTMenuBuf (WindowX-5, PrintY-5, (mw+14)&0xFFFC, h+10, true);
+
+ MenuBufCPrint (string);
+ RefreshMenuBuf (0);
+}
+
+
+
+//******************************************************************************
+//
+// DRAW NEW GAME MENU
+//
+//******************************************************************************
+
+void DrawNewGame (void)
+{
+ MenuNum = 5;
+
+ SetAlternateMenuBuf ();
+ ClearMenuBuf ();
+ SetMenuTitle ("Choose Difficulty");
+ DrawMenu (&TufItems, &TufMenu[ToughMenuNum][0]);
+ DrawNewGameDiff (TufItems.curpos);
+ DisplayInfo (0);
+ FlipMenuBuf();
+
+}
+
+//******************************************************************************
+//
+// DRAW NEW GAME GRAPHIC
+//
+//******************************************************************************
+
+int newgameY[7] = {19, 0, 42, 0, 74, 0, 93};
+char *DifficultyStrings[ 4 ] =
+{
+ "Easy", "Medium", "Hard", "Crezzy Man"
+};
+
+void DrawNewGameDiff
+(
+ int w
+)
+
+{
+ int x;
+
+ switch ( w )
+ {
+ case 0:
+ x = 0;
+ break;
+
+ case 2:
+ x = 1;
+ break;
+
+ case 4:
+ x = 2;
+ break;
+
+ case 6:
+ x = 3;
+ break;
+ }
+
+ EraseMenuBufRegion( 25, 18, 52, 125 );
+ DrawMenuBufPic( 25, newgameY[ w ], W_GetNumForName( "NEWG1" ) +
+ ( ToughMenuNum * 4 ) + x );
+ EraseMenuBufRegion( 25, 149, 64, 8 );
+// DrawMenuBufPic (25, 149, W_GetNumForName( "O_EASY" ) + x );
+
+ CurrentFont = tinyfont;
+ DrawMenuBufPropString( 25, 149, DifficultyStrings[ x ] );
+}
+
+
+//******************************************************************************
+//
+// DRAW THE LOAD/SAVE SCREEN
+//
+//******************************************************************************
+
+void DrawLoadSaveScreen (int loadsave)
+{
+ int i;
+ byte *shape;
+
+ shape = W_CacheLumpNum (W_GetNumForName ("newfnt1"), PU_CACHE, Cvt_font_t, 1);
+ newfont1 = (font_t *)shape;
+ CurrentFont = newfont1;
+
+ if (numdone || (!ingame) || (!inmenu))
+ SetAlternateMenuBuf();
+
+ ClearMenuBuf();
+ if (loadsave)
+ {
+ SetMenuTitle ("Save Game");
+ }
+ else
+ {
+ SetMenuTitle ("Load Game");
+ }
+
+ for (i = 0; i < NUMSAVEGAMES; i++)
+ PrintLSEntry (i);
+ DrawMenuBufItem (LSItems.x, ((LSItems.curpos*9)+(LSItems.y)),
+ W_GetNumForName( SmallCursor ) + CursorFrame[ CursorNum ] );
+ DisplayInfo (7);
+ if ((!numdone) && ingame && inmenu)
+ RefreshMenuBuf (0);
+ else
+ FlipMenuBuf();
+
+ WaitKeyUp ();
+
+ numdone++;
+}
+
+//******************************************************************************
+//
+// DRAW THE LOAD/SAVE SCREEN - no flip
+//
+//******************************************************************************
+
+void DrawLoadSaveScreenAlt (int loadsave)
+{
+ int i;
+ byte *shape;
+
+ shape = W_CacheLumpNum (W_GetNumForName ("newfnt1"), PU_CACHE, Cvt_font_t, 1);
+ newfont1 = (font_t *)shape;
+ CurrentFont = newfont1;
+
+ ClearMenuBuf();
+ if (loadsave)
+ {
+ SetMenuTitle ("Save Game");
+ }
+ else
+ {
+ SetMenuTitle ("Load Game");
+ }
+
+ for (i = 0; i < NUMSAVEGAMES; i++)
+ PrintLSEntry (i);
+ DrawMenuBufItem (LSItems.x, ((LSItems.curpos*9)+(LSItems.y)),
+ W_GetNumForName( SmallCursor ) + CursorFrame[ CursorNum ] );
+ DisplayInfo (7);
+ RefreshMenuBuf (0);
+
+ WaitKeyUp ();
+
+ numdone++;
+}
+
+
+//******************************************************************************
+//
+// PRINT LOAD/SAVE GAME ENTRY W/BOX OUTLINE
+//
+//******************************************************************************
+
+void PrintLSEntry (int w)
+{
+
+ DrawSTMenuBuf (LSM_X+LSItems.indent, LSM_Y+1+w*9, 80, 7, false);
+
+ PrintX = LSM_X+LSItems.indent+2;
+ PrintY = LSM_Y+(w*9)+2;
+
+ CurrentFont = tinyfont;
+
+ if (SaveGamesAvail[w])
+ DrawMenuBufPropString (PrintX, PrintY, SaveGameNames[w]);
+ else
+ DrawMenuBufPropString (PrintX, PrintY, " - � -");
+}
+
+
+
+//******************************************************************************
+//
+// CALIBRATE JOYSTICK
+//
+//******************************************************************************
+int CalibrateJoystick
+(
+ void
+)
+
+{
+#define CALX 45
+#define CALY 22
+
+ word xmax, ymax, xmin, ymin, jb;
+ int checkbits;
+ int status;
+ boolean done;
+
+ if ( joypadenabled )
+ {
+ // Gravis GamePad : Check all buttons
+ checkbits = ( 1 << 0 ) + ( 1 << 1 ) + ( 1 << 2 ) + ( 1 << 3 );
+ }
+ else if ( joystickport )
+ {
+ // Joystick port 2 : check only buttons 2 and 3
+ checkbits = ( 1 << 2 ) + ( 1 << 3 );
+ }
+ else
+ {
+ // Joystick port 1 : check only buttons 0 and 1
+ checkbits = ( 1 << 0 ) + ( 1 << 1 );
+ }
+
+ status = 0;
+ done = false;
+ while( !done )
+ {
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Calibrate Joystick");
+ //DrawMenuBufItem( CALX, CALY, W_GetNumForName( "joystk2" ) );
+ WindowW = 288;
+ WindowH = 158;
+ PrintX = WindowX = 0;
+ PrintY = WindowY = 50;
+
+ newfont1 = (font_t *)W_CacheLumpName( "newfnt1", PU_CACHE, Cvt_font_t, 1 );
+ CurrentFont = newfont1;
+ MenuBufCPrint( "MOVE JOYSTICK TO\nUPPER LEFT AND\nPRESS A BUTTON." );
+
+ DisplayInfo( 2 );
+ FlipMenuBuf();
+
+ do
+ {
+ RefreshMenuBuf( 0 );
+ jb = IN_JoyButtons();
+ IN_UpdateKeyboard();
+
+ if ( Keyboard[ sc_Escape ] )
+ {
+ return( 0 );
+ }
+ }
+ while( !( jb & checkbits ) );
+
+ IN_GetJoyAbs( joystickport, &xmin, &ymin );
+ MN_PlayMenuSnd( SD_SELECTSND );
+
+ while( IN_JoyButtons() & checkbits )
+ {
+ IN_UpdateKeyboard();
+
+ if ( Keyboard[ sc_Escape ] )
+ {
+ return( 0 );
+ }
+ }
+
+ ClearMenuBuf();
+// DrawMenuBufItem( CALX, CALY, W_GetNumForName( "joystk1" ) );
+ WindowW = 288;
+ WindowH = 158;
+ PrintX = WindowX = 0;
+ PrintY = WindowY = 50;
+
+ newfont1 = (font_t *)W_CacheLumpName( "newfnt1", PU_CACHE, Cvt_font_t, 1 );
+ CurrentFont = newfont1;
+ MenuBufCPrint( "MOVE JOYSTICK TO\nLOWER RIGHT AND\nPRESS A BUTTON." );
+
+ DisplayInfo( 2 );
+
+ do
+ {
+ RefreshMenuBuf( 0 );
+ jb = IN_JoyButtons();
+ IN_UpdateKeyboard();
+
+ if ( Keyboard[ sc_Escape ] )
+ {
+ return( 0 );
+ }
+ }
+ while( !( jb & checkbits ) );
+
+ IN_GetJoyAbs( joystickport, &xmax, &ymax );
+ MN_PlayMenuSnd( SD_SELECTSND );
+
+ while( IN_JoyButtons() & checkbits )
+ {
+ IN_UpdateKeyboard();
+
+ if ( Keyboard[ sc_Escape ] )
+ {
+ return( 0 );
+ }
+ }
+
+ //
+ // ASSIGN ACTUAL VALUES HERE
+ //
+ if ( ( xmin < xmax ) && ( ymin < ymax ) )
+ {
+ IN_SetupJoy( joystickport, xmin, xmax, ymin, ymax );
+ joyxmin = xmin;
+ joyxmax = xmax;
+ joyymin = ymin;
+ joyymax = ymax;
+
+ status = 1;
+ done = true;
+ }
+ else
+ {
+ CP_ErrorMsg( "Joystick Error",
+ "Calibration failed. The joystick must be moved "
+ "to the upper-left first and then the lower-right.",
+ mn_smallfont );
+ }
+ }
+
+ return( status );
+}
+
+
+//******************************************************************************
+//
+// ADJUST MOUSE SENSITIVITY
+//
+//******************************************************************************
+
+void MouseSensitivity
+(
+ void
+)
+
+{
+ SliderMenu( &mouseadjustment, 11, 0, 21, 81, 240, 1, "block1", NULL,
+ "Mouse Sensitivity", "Slow", "Fast" );
+}
+
+//******************************************************************************
+//
+// ADJUST MOUSE AND JOYSTICK THRESHOLD
+//
+//******************************************************************************
+
+void DoThreshold
+(
+ void
+)
+
+{
+ SliderMenu (&threshold, 15, 1, 44, 81, 194, 1, "block2", NULL,
+ "Adjust Threshold", "Small", "Large" );
+}
+
+//******************************************************************************
+//
+// DRAW CONTROL MENU SCREEN
+//
+//******************************************************************************
+
+void DrawCtlScreen (void)
+{
+ MenuNum = 3;
+
+ if (numdone || (!ingame) || (!inmenu))
+ SetAlternateMenuBuf();
+
+ ClearMenuBuf();
+ SetMenuTitle ("Options");
+
+
+ DrawCtlButtons ();
+
+ DisplayInfo (0);
+ DrawMenu (&CtlItems, &CtlMenu[0]);
+ DrawMenuBufItem (CtlItems.x, ((CtlItems.curpos*14)+(CtlItems.y-2)),
+ W_GetNumForName( LargeCursor ) + CursorFrame[ CursorNum ] );
+
+ if (ingame && inmenu && (!numdone))
+ RefreshMenuBuf (0);
+ else
+ FlipMenuBuf();
+
+ numdone++;
+}
+
+
+//******************************************************************************
+//
+// DrawCtlButtons ()
+//
+//******************************************************************************
+
+void DrawCtlButtons (void)
+{
+ int i,
+ x,
+ y;
+ static boolean first = true;
+ int button_on;
+ int button_off;
+
+ button_on = W_GetNumForName ("snd_on");
+ button_off = W_GetNumForName ("snd_off");
+
+ WindowX = 0;
+ WindowW = 320;
+
+ if (first)
+ {
+ if (JoysPresent[0] || JoysPresent[1])
+ {
+ CtlMenu[JOYENABLE].active = CP_Active;
+ CtlMenu[USEPORT2].active = CP_Active;
+ CtlMenu[PADENABLE].active = CP_Active;
+ CtlMenu[THRESSENS].active = CP_Active;
+ }
+ else
+ {
+ joystickenabled = 0;
+ joypadenabled = 0;
+ joystickport = 0;
+ }
+
+ if (MousePresent)
+ {
+ CtlMenu[THRESSENS].active = CP_Active;
+ CtlMenu[MOUSESENS].active = CP_Active;
+ CtlMenu[MOUSEENABLE].active = CP_Active;
+ }
+ else
+ {
+ CtlMenu[0].active = CP_Inactive;
+ mouseenabled = 0;
+ }
+
+ if (SpaceBallPresent)
+ CtlMenu[SPACEBALLENABLE].active = CP_Active;
+
+ if (CybermanPresent)
+ CtlMenu[CYBERMANENABLE].active = CP_Active;
+
+ for (x = 0; x < CtlItems.amount; x++)
+ {
+ if (CtlMenu[x].active)
+ {
+ CtlMenu[x].active = CP_CursorLocation;
+ break;
+ }
+ }
+ first = false;
+ }
+
+ x = CTL_X+CtlItems.indent-18;
+ y = MENU_Y-1;
+
+ if (mouseenabled)
+ DrawMenuBufItem (x, y, button_on);
+ else
+ {
+ EraseMenuBufRegion (x, y, 16, 16);
+ DrawMenuBufItem (x, y, button_off);
+ }
+
+ y += 14;
+ if (joystickenabled)
+ DrawMenuBufItem (x, y, button_on);
+ else
+ {
+ EraseMenuBufRegion (x, y, 16, 16);
+ DrawMenuBufItem (x, y, button_off);
+ }
+
+ y += 14;
+ if (joystickport)
+ DrawMenuBufItem (x, y, button_on);
+ else
+ {
+ EraseMenuBufRegion (x, y, 16, 16);
+ DrawMenuBufItem (x, y, button_off);
+ }
+
+ y += 14;
+ if (joypadenabled)
+ DrawMenuBufItem (x, y, button_on);
+ else
+ {
+ EraseMenuBufRegion (x, y, 16, 16);
+ DrawMenuBufItem (x, y, button_off);
+ }
+
+ y += 14;
+ if (spaceballenabled)
+ DrawMenuBufItem (x, y, button_on);
+ else
+ {
+ EraseMenuBufRegion (x, y, 16, 16);
+ DrawMenuBufItem (x, y, button_off);
+ }
+
+ y += 14;
+ if (cybermanenabled)
+ DrawMenuBufItem (x, y, button_on);
+ else
+ {
+ EraseMenuBufRegion (x, y, 16, 16);
+ DrawMenuBufItem (x, y, button_off);
+ }
+
+
+ if ((CtlItems.curpos < 0) || (!CtlMenu[CtlItems.curpos].active))
+ for (i = 0; i < CtlItems.amount; i++)
+ if (CtlMenu[i].active)
+ {
+ CtlItems.curpos = i;
+ break;
+ }
+
+}
+
+//******************************************************************************
+//
+// WAIT FOR CTRLKEY-UP OR BUTTON-UP
+//
+//******************************************************************************
+
+void WaitKeyUp (void)
+{
+ ControlInfo ci;
+
+ IN_IgnoreMouseButtons();
+ ReadAnyControl (&ci);
+
+ while (ci.button0 || ci.button1 || ci.button2 || ci.button3 ||
+ Keyboard[sc_Space] || Keyboard[sc_Enter] || Keyboard[sc_Escape])
+ {
+ ReadAnyControl (&ci);
+ RefreshMenuBuf (0);
+ if (Keystate[sc_CapsLock] && Keystate[sc_Q])
+ Error("Stuck in WaitKeyUp\n");
+ }
+}
+
+#define PMOUSE 3
+#define SMOUSE 4
+
+//******************************************************************************
+//
+// READ KEYBOARD, JOYSTICK AND MOUSE FOR INPUT
+//
+//******************************************************************************
+
+void ReadAnyControl (ControlInfo *ci)
+{
+
+#if PLATFORM_DOS
+ union REGS inregs;
+ union REGS outregs;
+#endif
+
+ int mouseactive = 0;
+ word buttons = 0;
+// struct Spw_IntPacket packet;
+
+
+ IN_UpdateKeyboard (); /* implies IN_PumpEvents() ... */
+ IN_ReadControl (0, ci);
+
+ if (MousePresent && mouseenabled)
+ {
+ int mousey,
+ mousex;
+
+#if USE_SDL
+ INL_GetMouseDelta(&mousex, &mousey);
+ if (mousex >= SENSITIVE)
+ {
+ ci->dir = dir_East;
+ mouseactive = 1;
+ }
+ else if (mousex <= -SENSITIVE)
+ {
+ ci->dir = dir_West;
+ mouseactive = 1;
+ }
+
+ if (mousey >= SENSITIVE)
+ {
+ ci->dir = dir_South;
+ mouseactive = 1;
+ }
+ else if (mousey <= -SENSITIVE)
+ {
+ ci->dir = dir_North;
+ mouseactive = 1;
+ }
+
+#elif PLATFORM_DOS
+ // READ MOUSE MOTION COUNTERS
+ // RETURN DIRECTION
+ // HOME MOUSE
+ // CHECK MOUSE BUTTONS
+
+ inregs.w.ax = PMOUSE;
+ int386 (MouseInt, &inregs, &outregs);
+
+ mousex = outregs.w.cx;
+ mousey = outregs.w.dx;
+
+
+ if (mousey < (CENTER-SENSITIVE))
+ {
+ ci->dir = dir_North;
+
+ inregs.w.cx = CENTER;
+ inregs.w.dx = CENTER;
+
+ inregs.w.ax = SMOUSE;
+ int386 (MouseInt, &inregs, &outregs);
+
+ mouseactive = 1;
+
+ }
+ else if (mousey > (CENTER+SENSITIVE))
+ {
+ ci->dir = dir_South;
+
+ inregs.w.cx = CENTER;
+ inregs.w.dx = CENTER;
+
+ inregs.w.ax = SMOUSE;
+ int386 (MouseInt, &inregs, &outregs);
+
+ mouseactive = 1;
+ }
+
+ if (mousex < (CENTER-SENSITIVE))
+ {
+ ci->dir = dir_West;
+
+ inregs.w.cx = CENTER;
+ inregs.w.dx = CENTER;
+
+ inregs.w.ax = SMOUSE;
+ int386 (MouseInt, &inregs, &outregs);
+
+
+ mouseactive = 1;
+ }
+ else if (mousex > (CENTER+SENSITIVE))
+ {
+ ci->dir = dir_East;
+
+ inregs.w.cx = CENTER;
+ inregs.w.dx = CENTER;
+
+ inregs.w.ax = SMOUSE;
+ int386 (MouseInt, &inregs, &outregs);
+
+ mouseactive = 1;
+ }
+#else
+#error please define your platform. /* or maybe just nuke the DOS section? */
+#endif
+
+ buttons = IN_GetMouseButtons();
+ if ( buttons )
+ {
+ ci->button0 = buttons & 1;
+ ci->button1 = buttons & 2;
+ ci->button2 = buttons & 4;
+ ci->button3 = false;
+ mouseactive = 1;
+ }
+ }
+
+ if (joystickenabled && !mouseactive)
+ {
+ int jx,jy,jb;
+
+
+ INL_GetJoyDelta (joystickport, &jx, &jy);
+
+ if (jy<-SENSITIVE)
+ ci->dir=dir_North;
+ else if (jy>SENSITIVE)
+ ci->dir=dir_South;
+
+ if (jx<-SENSITIVE)
+ ci->dir=dir_West;
+ else if (jx>SENSITIVE)
+ ci->dir=dir_East;
+
+ jb = IN_JoyButtons();
+ if (jb)
+ {
+ ci->button0=jb&1;
+ ci->button1=jb&2;
+ if (joypadenabled)
+ {
+ ci->button2=jb&4;
+ ci->button3=jb&8;
+ }
+ else
+ ci->button2=ci->button3=false;
+ }
+ }
+
+
+#if 0
+ if (SpaceBallPresent && spaceballenabled)
+ {
+ SP_Get(&packet);
+
+ if (packet.button)
+ {
+ if (packet.button & SP_BTN_1)
+ ci->button0 = true;
+
+ if (packet.button & SP_BTN_2)
+ ci->button1 = true;
+ }
+
+ if (packet.ty > MENU_AMT)
+ ci->dir = dir_North;
+ else if (packet.ty < -MENU_AMT)
+ ci->dir = dir_South;
+
+ if (packet.tx < (-MENU_AMT* 6))
+ ci->dir = dir_West;
+ else if (packet.tx > (MENU_AMT * 6))
+ ci->dir = dir_East;
+ }
+#endif
+}
+
+
+//******************************************************************************
+//
+// IN_GetScanName () - Returns a string containing the name of the
+// specified scan code
+//
+//******************************************************************************
+
+byte * IN_GetScanName (ScanCode scan)
+{
+ byte **p;
+ ScanCode *s;
+
+ for (s = ExtScanCodes, p = ExtScanNames; *s; p++, s++)
+ if (*s == scan)
+ return (*p);
+
+ return(ScanNames[scan]);
+}
+
+
+//******************************************************************************
+//
+// DisplayInfo ()
+//
+//******************************************************************************
+
+void DisplayInfo (int which)
+{
+ patch_t *p;
+ int x;
+ int num;
+
+ num = W_GetNumForName ( "info1" ) + which;
+ p = (patch_t *) W_CacheLumpNum (num, PU_CACHE, Cvt_patch_t, 1);
+
+ x = (288 - p->width) >> 1;
+
+ DrawMenuBufItem (x, 149, num);
+}
+
+
+//******************************************************************************
+//
+// DrawSTMenuBuf()
+//
+//******************************************************************************
+
+void DrawSTMenuBuf (int x, int y, int w, int h, boolean up)
+{
+ if (!up)
+ {
+ DrawTMenuBufHLine (x, y, w+1, false);
+ DrawTMenuBufVLine (x, y+1, h-1, false);
+ DrawTMenuBufHLine (x, y+h, w+1, true);
+ DrawTMenuBufVLine (x+w, y+1, h-1, true);
+ }
+ else
+ {
+ DrawTMenuBufHLine (x, y, w+1, true);
+ DrawTMenuBufVLine (x, y+1, h-1, true);
+ DrawTMenuBufHLine (x, y+h, w+1, false);
+ DrawTMenuBufVLine (x+w, y+1, h-1, false);
+ }
+}
+
+
+//****************************************************************************
+//
+// DoMainMenu ()
+//
+//****************************************************************************
+
+void DoMainMenu (void)
+{
+ EnableScreenStretch();//bna++ shut on streech mode
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ DrawMainMenu();
+ DrawMenuBufItem (MainItems.x, ((MainItems.curpos*14)+(MainItems.y-2)),
+ W_GetNumForName( LargeCursor ) + CursorFrame[ CursorNum ] );
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// DrawCustomMenu ()
+//
+//****************************************************************************
+
+void DrawCustomMenu (void)
+{
+ MenuNum = 3;
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Customize Menu");
+ MN_GetCursorLocation( &CustomItems, &CustomMenu[ 0 ] );
+ DrawMenu (&CustomItems, &CustomMenu[0]);
+ DrawMenuBufItem (CustomItems.x, ((CustomItems.curpos*14)+(CustomItems.y-2)),
+ W_GetNumForName( LargeCursor ) + CursorFrame[ CursorNum ] );
+ DisplayInfo (0);
+ FlipMenuBuf();
+}
+
+
+
+//****************************************************************************
+//
+// DrawCustomKeyboard ()
+//
+//****************************************************************************
+void DrawCustomKeyboard (void)
+{
+ int i;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Customize Keyboard");
+
+ for( i = 0; i < NormalKeyItems.amount; i++ )
+ {
+ strcpy( &NormalKeyNames[ i ][ KEYNAMEINDEX ],
+ IN_GetScanName( buttonscan[ (unsigned int)order[ i ] ] ) );
+ }
+
+ MN_GetCursorLocation( &NormalKeyItems, &NormalKeyMenu[ 0 ] );
+ DrawMenu( &NormalKeyItems, &NormalKeyMenu[ 0 ] );
+
+ DisplayInfo( 0 );
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// MusicVolume ()
+//
+//****************************************************************************
+
+void MusicVolume
+(
+ void
+)
+
+{
+#ifdef DOS
+ extern boolean SOUNDSETUP;
+#endif
+
+ SliderMenu( &MUvolume, 254, 0, 33, 81, 225, 8, "block3", MUSIC_SetVolume,
+ "Music Volume", "Low", "High" );
+
+#ifdef DOS
+ if ( SOUNDSETUP )
+ {
+ DrawSoundSetupMainMenu();
+ }
+ else
+ {
+#endif
+ DrawControlMenu();
+#ifdef DOS
+ }
+#endif
+}
+
+
+//****************************************************************************
+//
+// FXVolume ()
+//
+//****************************************************************************
+
+void FXVolume
+(
+ void
+)
+
+{
+#ifdef DOS
+ extern boolean SOUNDSETUP;
+#endif
+ int oldvolume;
+
+ oldvolume = FXvolume;
+
+ SliderMenu( &FXvolume, 254, 0, 33, 81, 225, 8, "block3", FX_SetVolume,
+ "Sound Volume", "Low", "High" );
+
+#ifdef DOS
+ if ( SOUNDSETUP )
+ {
+ DrawSoundSetupMainMenu();
+ }
+ else
+ {
+#endif
+ DrawControlMenu();
+#ifdef DOS
+ }
+#endif
+}
+
+
+
+//****************************************************************************
+//
+// DrawPlayerMenu ()
+//
+//****************************************************************************
+
+void DrawPlayerMenu (void)
+{
+ MenuNum = 5;
+
+
+ MN_MakeActive( &PlayerItems, &PlayerMenu[0], DefaultPlayerCharacter );
+
+#if ( SHAREWARE == 1 )
+ PlayerMenu[ 1 ].active = CP_SemiActive; // Thi Barrett
+ PlayerMenu[ 2 ].active = CP_SemiActive; // Doug Wendt
+ PlayerMenu[ 3 ].active = CP_SemiActive; // Lorelei Ni
+ PlayerMenu[ 4 ].active = CP_SemiActive; // Ian Paul Freeley
+#endif
+
+ if (numdone || (!ingame) || (!inmenu))
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Choose Player");
+
+ DrawMenu (&PlayerItems, &PlayerMenu[0]);
+ DrawNewPlayerDiff (PlayerItems.curpos);
+
+ DisplayInfo (0);
+
+
+ if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
+ ( consoleplayer == 0 ) )
+ {
+ DrawBattleModeName( gamestate.battlemode );
+ }
+
+ if (ingame && inmenu && (!numdone))
+ RefreshMenuBuf (0);
+ else
+ FlipMenuBuf();
+}
+
+//******************************************************************************
+//
+// DRAW NEW PLAYER GRAPHIC
+//
+//******************************************************************************
+
+int newplayerY[5] = {28, 42, 56, 70, 84};
+
+void DrawNewPlayerDiff (int w)
+{
+ EraseMenuBufRegion (25, 18, 52, 125);
+ DrawMenuBufPic (25, newplayerY[w], W_GetNumForName( "PLAYER1" ) + w );
+}
+
+
+//******************************************************************************
+//
+// MenuFixup ()
+//
+//******************************************************************************
+void MenuFixup
+(
+ void
+)
+
+{
+ MainMenu[ viewscores ].texture[ 6 ] = '1';
+ MainMenu[ viewscores ].texture[ 7 ] = '0';
+ MainMenu[ viewscores ].texture[ 8 ] = '\0';
+ MainMenu[ viewscores ].routine = ( void * )CP_EndGame;
+ MainMenu[ viewscores ].letter = 'E';
+ strcpy (MainMenuNames[ viewscores ], "END GAME");
+ MainMenu[ savegame ].active = CP_Active;
+ ingame = true;
+}
+
+//******************************************************************************
+//
+// GetEpisode ()
+//
+//******************************************************************************
+
+void GetEpisode (int level)
+{
+ if (level < 8)
+ gamestate.episode = 1;
+ else if (level < 16)
+ gamestate.episode = 2;
+ else if (level < 24)
+ gamestate.episode = 3;
+ else
+ gamestate.episode = 4;
+}
+
+
+//****************************************************************************
+//
+// DrawControlMenu ()
+//
+//****************************************************************************
+
+void DrawControlMenu (void)
+{
+ MenuNum = 1;
+
+ if (numdone || (!ingame) || (!inmenu))
+ SetAlternateMenuBuf();
+
+ ClearMenuBuf();
+ SetMenuTitle ("Options");
+
+ MN_GetCursorLocation( &ControlMItems, &ControlMMenu[ 0 ] );
+ DrawMenu (&ControlMItems, &ControlMMenu[0]);
+ DisplayInfo (0);
+
+ if (ingame && inmenu && (!numdone))
+ RefreshMenuBuf (0);
+ else
+ FlipMenuBuf();
+
+ numdone ++;
+}
+
+//****************************************************************************
+//
+// CP_ControlMenu ()
+//
+//****************************************************************************
+
+void CP_ControlMenu (void)
+{
+ int which;
+
+ DrawControlMenu();
+
+ do
+ {
+ which = HandleMenu (&ControlMItems, &ControlMMenu[0], NULL);
+
+ } while (which >= 0);
+
+ handlewhich = OUTOFRANGE;
+}
+
+
+
+//****************************************************************************
+//
+// DrawOptionsMenu ()
+//
+//****************************************************************************
+
+void DrawOptionsMenu (void)
+{
+ MenuNum = 1;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("User Options");
+
+ MN_GetCursorLocation( &OptionsItems, &OptionsMenu[ 0 ] );
+ DrawMenu (&OptionsItems, &OptionsMenu[0]);
+ DrawOptionsButtons ();
+ DisplayInfo (0);
+ FlipMenuBuf();
+}
+//****************************************************************************
+//
+// DrawExtOptionsMenu () () bna added
+//
+//****************************************************************************
+
+void DrawExtOptionsMenu (void)
+{
+ MenuNum = 1;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Extended User Options");
+
+ MN_GetCursorLocation( &ExtOptionsItems, &ExtOptionsMenu[ 0 ] );
+ DrawMenu (&ExtOptionsItems, &ExtOptionsMenu[0]);
+ DrawExtOptionsButtons ();
+ DisplayInfo (0);
+
+ FlipMenuBuf();
+}
+extern int inverse_mouse;
+extern boolean usemouselook;
+extern boolean iG_aimCross;
+extern boolean usejump;
+extern boolean sdl_fullscreen;
+extern boolean autoAimMissileWeps;
+extern boolean autoAim;
+
+void CP_ExtOptionsMenu (void)
+{
+ int which;
+
+ DrawExtOptionsMenu();
+
+ do
+ {
+ which = HandleMenu (&ExtOptionsItems, &ExtOptionsMenu[0], NULL);
+
+ switch (which)
+ {
+ case 0:
+ usemouselook ^= 1;
+ DrawExtOptionsButtons ();
+ break;
+ case 1:
+ if (inverse_mouse == 1) {
+ inverse_mouse = -1;
+ } else {
+ inverse_mouse = 1;
+ }
+ DrawExtOptionsButtons ();
+ break;
+ case 2:
+ iG_aimCross ^= 1;
+ DrawExtOptionsButtons ();
+ break;
+ case 3:
+ usejump ^= 1;
+ DrawExtOptionsButtons ();
+ break;
+ case 4:
+ if (SDL_WM_ToggleFullScreen(SDL_GetVideoSurface()))
+ {
+ sdl_fullscreen ^= 1;
+ DrawExtOptionsButtons ();
+ }
+ break;
+ case 5:
+ autoAimMissileWeps ^= 1;
+ DrawExtOptionsButtons();
+ break;
+ case 6:
+ autoAim ^= 1;
+ DrawExtOptionsButtons();
+ break;
+ }
+
+ } while (which >= 0);
+
+ DrawControlMenu();
+}
+void DrawExtOptionsButtons (void)
+{
+ int i,
+ on;
+ int button_on;
+ int button_off;
+
+ button_on = W_GetNumForName ("snd_on");
+ button_off = W_GetNumForName ("snd_off");
+
+ for (i = 0; i < ExtOptionsItems.amount; i++)
+ if (ExtOptionsMenu[i].active != CP_Active3)
+ {
+ //
+ // DRAW SELECTED/NOT SELECTED GRAPHIC BUTTONS
+ //
+
+ on = 0;
+
+ switch (i)
+ {
+ case 0:
+ if (usemouselook == 1) on = 1;
+ break;
+ case 1:
+ if (inverse_mouse == -1)on = 1;
+ break;
+ case 2:
+ if (iG_aimCross == 1) on = 1;
+ break;
+ case 3:
+ if (usejump == 1) on = 1;
+ break;
+ case 4:
+ if (sdl_fullscreen== 1) on = 1;
+ break;
+ case 5:
+ if (autoAimMissileWeps == 1) on = 1;
+ break;
+ case 6:
+ if (autoAim == 1) on = 1;
+ break;
+ }
+
+ if (on)
+ DrawMenuBufItem (20+22, ExtOptionsItems.y+i*14-1, button_on);
+ else
+ DrawMenuBufItem (20+22, ExtOptionsItems.y+i*14-1, button_off);
+ }
+}
+extern boolean allowBlitzMoreMissileWeps;
+extern boolean enableAmmoPickups;
+extern boolean enableZomROTT = 0;
+extern boolean enableExtraPistolDrops = 0;
+
+void DrawExtGameOptionsButtons (void)
+{
+ int i,
+ on;
+ int button_on;
+ int button_off;
+
+ button_on = W_GetNumForName ("snd_on");
+ button_off = W_GetNumForName ("snd_off");
+
+ for (i = 0; i < ExtGameOptionsItems.amount; i++)
+ if (ExtGameMenu[i].active != CP_Active3)
+ {
+ //
+ // DRAW SELECTED/NOT SELECTED GRAPHIC BUTTONS
+ //
+
+ on = 0;
+
+ switch (i)
+ {
+ case 0:
+ if (allowBlitzMoreMissileWeps == 1) on = 1;
+ break;
+ case 1:
+ if (enableAmmoPickups == 1) on = 1;
+ break;
+ case 2:
+ if (enableExtraPistolDrops == 1) on = 1;
+ break;
+ case 3:
+ if (enableZomROTT == 1) on = 1;
+ break;
+ }
+
+
+ if (on)
+ DrawMenuBufItem (20+22, ExtGameOptionsItems.y+i*14-1, button_on);
+ else
+ DrawMenuBufItem (20+22, ExtGameOptionsItems.y+i*14-1, button_off);
+ }
+
+}
+
+
+
+
+void DrawExtGameMenu (void)
+{
+ MenuNum = 1;
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Extended Game Options");
+
+ MN_GetCursorLocation( &ExtGameOptionsItems, &ExtGameOptionsNames[0]);
+
+ DrawMenu(&ExtGameOptionsItems, &ExtGameMenu[0]);
+
+ DrawExtGameOptionsButtons();
+
+ DisplayInfo(0);
+
+ FlipMenuBuf();
+
+}
+//****************************************************************************
+//
+// DrawExtGameOptionsMenu () () LT added
+//
+//****************************************************************************
+
+void CP_ExtGameOptionsMenu (void)
+{
+ int which;
+
+ DrawExtGameMenu();
+
+ do
+ {
+ which = HandleMenu (&ExtGameOptionsItems, &ExtGameMenu[0], NULL);
+
+ switch (which)
+ {
+ case 0:
+ allowBlitzMoreMissileWeps ^= 1;
+ DrawExtGameOptionsButtons ();
+ break;
+ case 1:
+ enableAmmoPickups ^= 1;
+ DrawExtGameOptionsButtons();
+ break;
+ case 2:
+ enableExtraPistolDrops ^= 1;
+ DrawExtGameOptionsButtons();
+ break;
+ case 3:
+ enableZomROTT ^= 1;
+ DrawExtGameOptionsButtons();
+ break;
+ }
+ } while (which >= 0);
+
+ DrawControlMenu();
+}
+
+
+//****************************************************************************
+//
+// CP_OptionsMenu ()
+//
+//****************************************************************************
+
+void CP_OptionsMenu (void)
+{
+ int which;
+
+ DrawOptionsMenu();
+
+ do
+ {
+ which = HandleMenu (&OptionsItems, &OptionsMenu[0], NULL);
+
+ switch (which)
+ {
+ case 0:
+ AutoDetailOn ^= 1;
+ DrawOptionsButtons ();
+ break;
+ case 1:
+ fulllight ^= 1;
+ DrawOptionsButtons ();
+ break;
+ case 2:
+ BobbinOn ^= 1;
+ DrawOptionsButtons ();
+ break;
+ case 3:
+ fandc ^= 1;
+ DrawOptionsButtons ();
+ break;
+ }
+
+ } while (which >= 0);
+
+ DrawControlMenu();
+}
+
+//****************************************************************************
+//
+// DrawOptionsButtons
+//
+//****************************************************************************
+
+void DrawOptionsButtons (void)
+{
+ int i,
+ on;
+ int button_on;
+ int button_off;
+
+ button_on = W_GetNumForName ("snd_on");
+ button_off = W_GetNumForName ("snd_off");
+
+ for (i = 0; i < OptionsItems.amount-5; i++)
+ if (OptionsMenu[i].active != CP_Active3)
+ {
+ //
+ // DRAW SELECTED/NOT SELECTED GRAPHIC BUTTONS
+ //
+
+ on = 0;
+
+ switch (i)
+ {
+ case 0:
+ if (AutoDetailOn == 1) on = 1;
+ break;
+ case 1:
+ if (fulllight == 0) on = 1;
+ break;
+ case 2:
+ if (BobbinOn == 1) on = 1;
+ break;
+ case 3:
+ if (fandc == 1) on = 1;
+ break;
+ }
+
+ if (on)
+ DrawMenuBufItem (20+22, OptionsItems.y+i*14-1, button_on);
+ else
+ DrawMenuBufItem (20+22, OptionsItems.y+i*14-1, button_off);
+ }
+}
+
+
+//****************************************************************************
+//
+// CP_DoubleClickSpeed()
+//
+//****************************************************************************
+
+void CP_DoubleClickSpeed
+(
+ void
+)
+
+{
+ int temp;
+
+ temp = 50 - ( DoubleClickSpeed - 5 );
+ SliderMenu( &temp, 50, 5, 31, 81, 225, 3, "block1", NULL,
+ "Double-Click Speed", "Slow", "Fast" );
+ DoubleClickSpeed = 50 - ( temp - 5 );
+
+ handlewhich = 100;
+ DrawOptionsMenu();
+}
+
+//****************************************************************************
+//
+// MenuFlipSpeed ()
+//
+//****************************************************************************
+
+void MenuFlipSpeed
+(
+ void
+)
+
+{
+ int temp;
+
+ temp = 50 - ( Menuflipspeed - 5 );
+
+ SliderMenu( &temp, 50, 5, 31, 81, 225, 3, "block1", NULL,
+ "Menu Flip Speed", "Slow", "Fast" );
+
+ Menuflipspeed = 50 - ( temp - 5 );
+
+ DrawOptionsMenu ();
+ handlewhich = 10;
+}
+
+
+//****************************************************************************
+//
+// DrawDetailMenu ()
+//
+//****************************************************************************
+
+void DrawDetailMenu (void)
+{
+ MenuNum = 1;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Detail Menu");
+
+ MN_DrawButtons (&DetailItems, &DetailMenu[0], DetailLevel, OptionNums);
+ MN_GetCursorLocation( &DetailItems, &DetailMenu[ 0 ] );
+ DrawMenu (&DetailItems, &DetailMenu[0]);
+ DisplayInfo (0);
+ FlipMenuBuf();
+}
+
+//****************************************************************************
+//
+// CP_DetailMenu ()
+//
+//****************************************************************************
+
+void CP_DetailMenu (void)
+{
+ int which;
+
+ DrawDetailMenu();
+
+ do
+ {
+ which = HandleMenu (&DetailItems, &DetailMenu[0], NULL);
+
+ switch (which)
+ {
+ case 0:
+ DetailLevel = 0;
+ MN_DrawButtons (&DetailItems, &DetailMenu[0], DetailLevel, OptionNums);
+ break;
+
+ case 1:
+ DetailLevel = 1;
+ MN_DrawButtons (&DetailItems, &DetailMenu[0], DetailLevel, OptionNums);
+ break;
+
+ case 2:
+ DetailLevel = 2;
+ MN_DrawButtons (&DetailItems, &DetailMenu[0], DetailLevel, OptionNums);
+ break;
+ }
+
+ } while (which >= 0);
+
+ handlewhich = 10;
+ DrawOptionsMenu();
+}
+
+
+//****************************************************************************
+//
+// DrawBattleMenu ()
+//
+//****************************************************************************
+
+void DrawBattleMenu (void)
+{
+ MenuNum = 1;
+
+ if (numdone || (!ingame) || (!inmenu))
+ SetAlternateMenuBuf();
+
+ ClearMenuBuf();
+ SetMenuTitle ("Battle Menu");
+
+ DrawBattleModeName( gamestate.battlemode );
+
+ MN_GetCursorLocation( &BattleItems, &BattleMenu[ 0 ] );
+ DrawMenu (&BattleItems, &BattleMenu[0]);
+ DisplayInfo (0);
+
+ BATTLE_SetOptions( &BATTLE_Options[ gamestate.battlemode ] );
+ ShowBattleOptions( true, MENU_X, MENU_Y + 49 );
+
+ if (ingame && inmenu && (!numdone))
+ RefreshMenuBuf (0);
+ else
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// BattleGamePlayerSetup()
+//
+//****************************************************************************
+
+void BattleGamePlayerSetup( void )
+{
+ int status;
+ int pos;
+
+ pos = 1;
+ if ( consoleplayer == 0 )
+ {
+ pos = 0;
+ }
+
+ while( 1 )
+ {
+ switch( pos )
+ {
+ case 0 :
+ // Select level to play on
+ status = CP_LevelSelectionMenu ();
+ if ( status >= 0 )
+ {
+ gamestate.mapon=status;
+ pos = 1;
+ }
+ else
+ {
+ DrawBattleMenu();
+ return;
+ }
+ break;
+
+ case 1 :
+ // Select CodeName
+ status = CP_EnterCodeNameMenu();
+ pos = 2;
+ if ( !status )
+ {
+ if ( consoleplayer == 0 )
+ {
+ pos = 0;
+ }
+ else
+ {
+ return;
+ }
+ }
+ break;
+
+ case 2 :
+ // Select character
+ status = CP_PlayerSelection ();
+ pos = 1;
+ if ( status )
+ {
+ pos = 3;
+ }
+ break;
+
+ case 3 :
+ // Select color/team
+ status = CP_ColorSelection();
+ pos = 2;
+ if ( status )
+ {
+ StartGame = true;
+ DisableScreenStretch();
+ handlewhich = -2;
+ playstate = ex_resetgame;
+ BATTLEMODE = true;
+ // Show please wait
+ CP_ModemGameMessage( consoleplayer );
+ return;
+ }
+ break;
+ }
+ }
+}
+
+
+//****************************************************************************
+//
+// BattleNoTeams()
+//
+//****************************************************************************
+
+void BattleNoTeams( void )
+{
+ BattleGamePlayerSetup();
+ if ( StartGame )
+ {
+ gamestate.teamplay = false;
+ }
+}
+
+
+//****************************************************************************
+//
+// BattleTeams()
+//
+//****************************************************************************
+
+void BattleTeams( void )
+{
+ BattleGamePlayerSetup();
+ if ( StartGame )
+ {
+ gamestate.teamplay = true;
+ }
+}
+
+
+//****************************************************************************
+//
+// CP_BattleMenu ()
+//
+//****************************************************************************
+
+void CP_BattleMenu (void)
+{
+ int which;
+
+ gamestate.battlemode = handlewhich + battle_Normal;
+
+ BattleMenu[0].active = CP_Active;
+ BattleMenu[1].active = CP_Active;
+
+
+ // Tag can't be played in team mode
+ // Also, can't play teams if only 1 person is playing
+ if ( ( gamestate.battlemode == battle_Tag ) ||
+ ( numplayers < 2 ) )
+ {
+ BattleMenu[1].active = CP_Inactive;
+ if ( BattleItems.curpos == 1 )
+ {
+ BattleItems.curpos = 0;
+ }
+ }
+
+ // Capture the Triad can only be played in team mode
+ if ( gamestate.battlemode == battle_CaptureTheTriad )
+ {
+ BattleMenu[0].active = CP_Inactive;
+ if ( BattleItems.curpos == 0 )
+ {
+ BattleItems.curpos = 1;
+ }
+ }
+
+ BattleMenu[ BattleItems.curpos ].active = CP_CursorLocation;
+ DrawBattleMenu();
+
+ do
+ {
+ which = HandleMenu (&BattleItems, &BattleMenu[0], NULL);
+ }
+ while (which >= 0);
+
+ if ( which == -1 )
+ {
+ DrawBattleModes ();
+ handlewhich = OUTOFRANGE;
+ }
+}
+
+
+//****************************************************************************
+//
+// MN_PlayMenuSnd ()
+//
+//****************************************************************************
+
+extern boolean dopefish;
+void MN_PlayMenuSnd (int which)
+{
+ if (INFXSETUP || (SD_Started == false))
+ return;
+#if (SHAREWARE==0)
+ if (dopefish==true)
+ {
+ switch (which)
+ {
+ case SD_ESCPRESSEDSND:
+ which = SD_SOUNDESCSND;
+ break;
+ case SD_MOVECURSORSND:
+ which = SD_SILLYMOVESND;
+ break;
+ case SD_SELECTSND:
+ which = SD_SOUNDSELECTSND;
+ break;
+ }
+ }
+#endif
+ SD_Play (which);
+}
+
+
+//******************************************************************************
+//
+// SliderMenu ()
+//
+//******************************************************************************
+
+boolean SliderMenu
+(
+ int *number,
+ int upperbound,
+ int lowerbound,
+ int erasex,
+ int erasey,
+ int erasew,
+ int numadjust,
+ char *blockname,
+ void ( *routine )( int w ),
+ char *title,
+ char *left,
+ char *right
+)
+
+{
+ ControlInfo ci;
+ Direction lastdir;
+ patch_t *shape;
+ boolean returnval;
+ boolean moved;
+ unsigned long scale;
+ int exit;
+ int range;
+ int timer;
+ int width;
+ int height;
+ int blkx;
+ int eraseh;
+ int block;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle( title );
+
+ newfont1 = (font_t *)W_CacheLumpName( "newfnt1", PU_CACHE, Cvt_font_t, 1);
+ CurrentFont = newfont1;
+ PrintX = 25;
+ PrintY = 62;
+ DrawMenuBufPropString( PrintX, PrintY, left );
+
+ VW_MeasurePropString( right, &width, &height );
+ DrawMenuBufPropString( 263 - width, PrintY, right );
+
+ block = W_GetNumForName( blockname );
+ shape = ( patch_t * )W_CacheLumpNum( block, PU_CACHE, Cvt_patch_t, 1 );
+ blkx = erasex - shape->leftoffset;
+ eraseh = shape->height;
+ scale = ( erasew + shape->leftoffset - shape->width ) << 16;
+ range = upperbound - lowerbound;
+
+ DrawSTMenuBuf( erasex - 1, erasey - 1, erasew + 1, eraseh + 1, false );
+
+ DrawMenuBufItem( blkx + ( ( ( ( *number - lowerbound ) *
+ scale ) / range ) >> 16 ), erasey, block );
+
+ DisplayInfo( 1 );
+ FlipMenuBuf();
+
+ exit = 0;
+ moved = false;
+ timer = GetTicCount();
+ lastdir = dir_None;
+
+ do
+ {
+ RefreshMenuBuf( 0 );
+
+ ReadAnyControl( &ci );
+ if ( ( ( GetTicCount() - timer ) > 5 ) || ( ci.dir != lastdir ) )
+ {
+ timer = GetTicCount();
+
+ switch( ci.dir )
+ {
+ case dir_North:
+ case dir_West:
+ if ( *number > lowerbound )
+ {
+ *number = *number - numadjust;
+
+ if ( *number < lowerbound )
+ {
+ *number = lowerbound;
+ }
+
+ moved = true;
+ }
+ break;
+
+ case dir_South:
+ case dir_East:
+ if ( *number < upperbound )
+ {
+ *number = *number + numadjust;
+
+ if ( *number > upperbound )
+ {
+ *number = upperbound;
+ }
+
+ moved = true;
+ }
+ break;
+ default:
+ ;
+ }
+
+ lastdir = ci.dir;
+ }
+
+ if ( moved )
+ {
+ moved = false;
+
+ EraseMenuBufRegion( erasex, erasey, erasew, eraseh );
+
+ DrawMenuBufItem( blkx + ( ( ( ( *number - lowerbound ) *
+ scale ) / range ) >> 16 ), erasey, block );
+
+ if ( routine )
+ {
+ routine( *number );
+ }
+
+ MN_PlayMenuSnd( SD_MOVECURSORSND );
+ }
+
+ if ( ci.button0 || Keyboard[ sc_Space ] || Keyboard[ sc_Enter ] )
+ {
+ exit = 1;
+ }
+ else if ( ci.button1 || Keyboard[ sc_Escape ] )
+ {
+ exit = 2;
+ }
+ }
+ while( !exit );
+
+ if ( exit == 2 )
+ {
+ MN_PlayMenuSnd( SD_ESCPRESSEDSND );
+ returnval = false;
+ }
+ else
+ {
+ MN_PlayMenuSnd( SD_SELECTSND );
+ returnval = true;
+ }
+
+ WaitKeyUp ();
+ return( returnval );
+}
+
+
+//******************************************************************************
+//
+// DrawF1Help ()
+//
+//******************************************************************************
+
+void DrawF1Help (void)
+{
+
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+
+ DrawNormalSprite (0, 0, W_GetNumForName("help"));
+
+ VW_UpdateScreen ();
+}
+
+//******************************************************************************
+//
+// CP_F1Help ()
+//
+//******************************************************************************
+
+void CP_F1Help (void)
+{
+ LastScan=0;
+
+ DrawF1Help ();
+
+ while (LastScan == 0)
+ {
+ IN_UpdateKeyboard ();
+ }
+
+ LastScan=0;
+#if (SHAREWARE==1)
+ {
+ DrawOrderInfo( 2 );
+ while (LastScan == 0)
+ {
+ IN_UpdateKeyboard ();
+ }
+
+ LastScan=0;
+ }
+#endif
+}
+
+
+//****************************************************************************
+//
+// CP_ScreenSize()
+//
+//****************************************************************************
+
+void CP_ScreenSize
+(
+ void
+)
+
+{
+ SliderMenu( &viewsize, MAXVIEWSIZES - 1, 0, 33, 81, 225, 1, "block1",
+ NULL, "Screen Size", "Small", "Large" );
+
+ handlewhich = 100;
+ DrawOptionsMenu();
+}
+
+
+//****************************************************************************
+//
+// DrawViolenceMenu ()
+//
+//****************************************************************************
+
+void DrawViolenceMenu (void)
+{
+ MenuNum = 1;
+ if ( POK )
+ {
+ memcpy( &VMenu[ 1 ].texture, "mcpass\0", 7 );
+ VMenu[ 1 ].letter = 'C';
+ strcpy (VMenuNames[ 1 ], "CHANGE PASSWORD");
+ }
+ else
+ {
+ memcpy( &VMenu[ 1 ].texture, "mepass\0", 7 );
+ VMenu[ 1 ].letter = 'E';
+ strcpy (VMenuNames[ 1 ], "ENTER PASSWORD");
+ }
+
+ if (VMenu[0].active != CP_CursorLocation)
+ VMenu[0].active = CP_Active;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Violence Level");
+
+ MN_GetCursorLocation( &VItems, &VMenu[ 0 ] );
+ DrawMenu (&VItems, &VMenu[0]);
+ DisplayInfo (0);
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// CP_ViolenceMenu ()
+//
+//****************************************************************************
+
+void CP_ViolenceMenu (void)
+{
+ int which;
+
+ CurrentFont = smallfont;
+ DrawViolenceMenu ();
+
+ do
+ {
+ which = HandleMenu (&VItems, &VMenu[0], NULL);
+
+ } while (which >= 0);
+
+ handlewhich = 100;
+ DrawOptionsMenu();
+}
+
+
+//****************************************************************************
+//
+// DrawViolenceLevel ()
+//
+//****************************************************************************
+
+void DrawViolenceLevel (void)
+{
+ MenuNum = 1;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Change Violence Level");
+
+ MN_DrawButtons (&ViolenceItems, &ViolenceMenu[0], gamestate.violence, OptionNums);
+ MN_GetActive (&ViolenceItems, &ViolenceMenu[0], gamestate.violence, OptionNums);
+
+// DrawMenuBufItem (58, 24, W_GetNumForName ("blood"));
+ IFont = ( cfont_t * )W_CacheLumpName( FontNames[ mn_largefont ],
+ PU_CACHE, Cvt_cfont_t, 1 );
+ DrawMenuBufIString( 58, 24, "HOW MUCH ", NORMALCOLOR );
+ DrawMenuBufIString( PrintX, PrintY, "BLOOD", 51 );
+ DrawMenuBufIString( 71, 37, "DO YOU WANT?", NORMALCOLOR );
+
+ DrawMenu (&ViolenceItems, &ViolenceMenu[0]);
+ DisplayInfo (0);
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// CP_ViolenceLevel ()
+//
+//****************************************************************************
+
+void CP_ViolenceLevel (void)
+{
+ int which;
+ char p1[13];
+ boolean passok=false;
+
+ if (ingame)
+ {
+ CP_ErrorMsg( "Change Violence Level",
+ "The current game must be ended to change the Violence Level.",
+ mn_largefont );
+ }
+ else if ( POK )
+ {
+ memset (p1, 0, 13);
+
+ CurrentFont = smallfont;
+ DrawViolenceLevelPWord ();
+
+ if (US_lineinput (PBOXX+2, PBOXY+1, p1, NULL, true, 12, 110, 0))
+ {
+ //compare user entered to password
+ if (StringsNotEqual (p1, pword, StringLength (p1)) == false)
+ passok=true;
+ else
+ {
+ CP_ErrorMsg( "Violence Password", "Incorrect Password.",
+ mn_largefont );
+ }
+ }
+ }
+ else
+ passok=true;
+ if (passok==true)
+ {
+ DrawViolenceLevel ();
+ do
+ {
+ which = HandleMenu (&ViolenceItems, &ViolenceMenu[0], NULL);
+
+ if (which >= 0)
+ gamestate.violence = which;
+
+ MN_DrawButtons (&ViolenceItems, &ViolenceMenu[0], gamestate.violence, OptionNums);
+
+ } while (which >= 0);
+
+ WriteMenuInfo ();
+ }
+
+ handlewhich = 100;
+ DrawViolenceMenu();
+}
+
+
+
+//****************************************************************************
+//
+// DrawViolenceLevelPWord ();
+//
+//****************************************************************************
+
+void DrawViolenceLevelPWord
+(
+ void
+)
+
+{
+ MenuNum = 1;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle( "Violence Password" );
+
+// CurrentFont = newfont1;
+// DrawMenuBufPropString( PWORDX, PWORDY, "ENTER PASSWORD" );
+
+ IFont = ( cfont_t * )W_CacheLumpName( FontNames[ mn_largefont ],
+ PU_CACHE, Cvt_cfont_t, 1 );
+ DrawMenuBufIString( PWORDX, PWORDY, "ENTER PASSWORD", NORMALCOLOR );
+
+ DrawSTMenuBuf( PBOXX, PBOXY, PBOXW, PBOXH, false );
+ FlipMenuBuf();
+}
+
+
+
+//****************************************************************************
+//
+// DrawPWMenu ()
+//
+//****************************************************************************
+
+void DrawPWMenu
+(
+ void
+)
+
+{
+ MenuNum = 1;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle( "Violence Password" );
+
+// CurrentFont = newfont1;
+ IFont = ( cfont_t * )W_CacheLumpName( FontNames[ mn_largefont ],
+ PU_CACHE, Cvt_cfont_t, 1 );
+
+ if ( POK )
+ {
+// DrawMenuBufPropString( PWORDX - 24, PWORDY, "ENTER OLD PASSWORD" );
+ DrawMenuBufIString( PWORDX - 24, PWORDY, "ENTER OLD PASSWORD", NORMALCOLOR );
+ }
+ else
+ {
+// DrawMenuBufPropString( PWORDX - 24, PWORDY, "ENTER PASSWORD" );
+ DrawMenuBufIString( PWORDX - 24, PWORDY, "ENTER PASSWORD", NORMALCOLOR );
+ }
+
+ DrawSTMenuBuf( PBOXX, PBOXY, PBOXW, PBOXH, false );
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// CP_PWMenu ()
+//
+//****************************************************************************
+
+void CP_PWMenu (void)
+{
+ char p1[13];
+ char p2[13];
+ boolean EnterNewPassword;
+ boolean AskForNew;
+ boolean RetypePassword;
+
+ memset (p1, 0, 13);
+ memset (p2, 0, 13);
+
+ CurrentFont = smallfont;
+
+ EnterNewPassword = true;
+ if ( POK )
+ {
+ DrawPWMenu ();
+
+ // get old password
+ //
+ EnterNewPassword = false;
+ if (US_lineinput (PBOXX+2, PBOXY+1, p1, NULL, true, 12, PSTRW, 0))
+ {
+ //compare user entered to old
+ //
+ if (StringsNotEqual (p1, pword, StringLength (p1))==false)
+ {
+
+ // Password was correct so they may change it.
+ EnterNewPassword = true;
+ }
+ else
+ {
+ CP_ErrorMsg( "Violence Password", "Incorrect Password.",
+ mn_largefont );
+ }
+ }
+ }
+
+ if ( EnterNewPassword )
+ {
+ MenuNum = 1;
+
+ // get new password
+ //
+ AskForNew = true;
+ RetypePassword = false;
+ while( AskForNew )
+ {
+ CurrentFont = smallfont;
+
+ SetAlternateMenuBuf ();
+ ClearMenuBuf();
+ SetMenuTitle ("Violence Password");
+
+ IFont = ( cfont_t * )W_CacheLumpName( FontNames[ mn_largefont ],
+ PU_CACHE, Cvt_cfont_t, 1 );
+ DrawMenuBufIString( PWORDX - 24, PWORDY, "ENTER NEW PASSWORD", NORMALCOLOR );
+
+// CurrentFont = newfont1;
+// DrawMenuBufPropString( PWORDX - 24, PWORDY, "ENTER NEW PASSWORD" );
+// DrawMenuBufItem (PWORDX-24, PWORDY, W_GetNumForName ("mnewpass"));
+
+ DrawSTMenuBuf (PBOXX, PBOXY, PBOXW, PBOXH, false);
+ FlipMenuBuf();
+
+ memset (p1, 0, 13);
+
+ AskForNew = false;
+ if (US_lineinput (PBOXX+2, PBOXY+1, p1, NULL, true, 12, PSTRW, 0))
+ {
+ // Check for blank password
+ if ( p1[ 0 ] == 0 )
+ {
+ if ( CP_DisplayMsg ( "Clear Password?\nAre you sure?", 12 ) )
+ {
+ AskForNew = false;
+ memset (pword, 0, 13);
+ WriteMenuInfo ();
+ POK = false;
+ }
+ else
+ {
+ AskForNew = true;
+ }
+ }
+ else
+ {
+ RetypePassword = true;
+ }
+ }
+ }
+
+ if ( RetypePassword )
+ {
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Violence Password");
+
+// CurrentFont = newfont1;
+// DrawMenuBufPropString( PWORDX, PWORDY, "RETYPE PASSWORD" );
+
+ IFont = ( cfont_t * )W_CacheLumpName( FontNames[ mn_largefont ],
+ PU_CACHE, Cvt_cfont_t, 1 );
+ DrawMenuBufIString( PWORDX, PWORDY, "RETYPE PASSWORD", NORMALCOLOR );
+
+ DrawSTMenuBuf (PBOXX, PBOXY, PBOXW, PBOXH, false);
+
+ FlipMenuBuf();
+
+ // reenter password
+ //
+ if ( US_lineinput (PBOXX+2, PBOXY+1, p2, NULL, true, 12, PSTRW, 0) )
+ {
+ // compare password and retyped password
+ //
+ if (stricmp (p1, p2) == 0)
+ {
+ memset (pword, 0, 13);
+ strcpy (pword, p1);
+ WriteMenuInfo ();
+
+ // If we have a null password, then we don't need to
+ // ask for one.
+ POK = true;
+ if ( pword[ 0 ] == 0 )
+ {
+ POK = false;
+ }
+ }
+ else
+ {
+ CP_ErrorMsg( "Violence Password", "Passwords did not match.",
+ mn_largefont );
+ }
+ }
+ }
+ }
+
+ DrawViolenceMenu ();
+}
+
+//****************************************************************************
+//
+// DrawOptionDescription()
+//
+//****************************************************************************
+
+void DrawOptionDescription( char ** options, int w )
+{
+ int width;
+ int height;
+ char *string;
+ font_t *temp;
+
+ EraseMenuBufRegion (25, 4, 287 - 25, 10 );
+
+ temp = CurrentFont;
+ CurrentFont = tinyfont;
+
+ string = options[ w ];
+
+ VW_MeasurePropString ( string, &width, &height );
+ DrawMenuBufPropString ( ( 288 - width) / 2, 4, string );
+
+ CurrentFont = temp;
+}
+
+//****************************************************************************
+//
+// DrawBattleOptionDescription()
+//
+//****************************************************************************
+
+void DrawBattleOptionDescription( int w )
+{
+ DrawOptionDescription( BattleOptionDescriptions, w );
+}
+//****************************************************************************
+//
+// DrawGravityOptionDescription()
+//
+//****************************************************************************
+
+void DrawGravityOptionDescription( int w )
+{
+ DrawOptionDescription( GravityOptionDescriptions, w );
+}
+//****************************************************************************
+//
+// DrawSpeedOptionDescription()
+//
+//****************************************************************************
+
+void DrawSpeedOptionDescription( int w )
+{
+ DrawOptionDescription( SpeedOptionDescriptions, w );
+}
+//****************************************************************************
+//
+// DrawAmmoOptionDescription()
+//
+//****************************************************************************
+
+void DrawAmmoOptionDescription( int w )
+{
+ DrawOptionDescription( AmmoOptionDescriptions, w );
+}
+//****************************************************************************
+//
+// DrawHitPointsOptionDescription()
+//
+//****************************************************************************
+
+void DrawHitPointsOptionDescription( int w )
+{
+ DrawOptionDescription( HitPointsOptionDescriptions, w );
+}
+//****************************************************************************
+//
+// DrawRadicalOptionDescription()
+//
+//****************************************************************************
+
+void DrawRadicalOptionDescription( int w )
+{
+ DrawOptionDescription( RadicalOptionDescriptions, w );
+}
+//****************************************************************************
+//
+// DrawLightLevelOptionDescription()
+//
+//****************************************************************************
+
+void DrawLightLevelOptionDescription( int w )
+{
+ DrawOptionDescription( LightLevelOptionDescriptions, w );
+}
+//****************************************************************************
+//
+// DrawPointGoalOptionDescription()
+//
+//****************************************************************************
+
+void DrawPointGoalOptionDescription( int w )
+{
+ DrawOptionDescription( PointGoalOptionDescriptions, w );
+}
+//****************************************************************************
+//
+// DrawDangerDamageOptionDescription()
+//
+//****************************************************************************
+
+void DrawDangerDamageOptionDescription( int w )
+{
+ DrawOptionDescription( DangerDamageOptionDescriptions, w );
+}
+
+//****************************************************************************
+//
+// DrawTimeLimitOptionDescription()
+//
+//****************************************************************************
+
+void DrawTimeLimitOptionDescription( int w )
+{
+ DrawOptionDescription( TimeLimitOptionDescriptions, w );
+}
+
+
+
+#define TURN_OFF_BATTLE_MODE( x ) \
+ ModeMenu[ ( x ) - 1 ].active = CP_SemiActive; \
+ ModeMenu[ ( x ) - 1 ].routine = NULL;
+
+
+//****************************************************************************
+//
+// DrawBattleModes ()
+//
+//****************************************************************************
+void DrawBattleModes
+(
+ void
+)
+
+{
+ int i;
+
+ MenuNum = 1;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Battle Modes");
+
+
+ MN_GetActive( &ModeItems, &ModeMenu[ 0 ], gamestate.battlemode -
+ battle_Normal, OptionNums );
+
+#if ( SHAREWARE == 1 )
+ TURN_OFF_BATTLE_MODE( battle_ScoreMore );
+ TURN_OFF_BATTLE_MODE( battle_Scavenger );
+ TURN_OFF_BATTLE_MODE( battle_Tag );
+ TURN_OFF_BATTLE_MODE( battle_Eluder );
+ TURN_OFF_BATTLE_MODE( battle_Deluder );
+ TURN_OFF_BATTLE_MODE( battle_CaptureTheTriad );
+#endif
+
+ // Capture the Triad, Tag, ScoreMore, and Hunter can only be
+ // played with 2 or more players
+ if ( numplayers < 2 )
+ {
+ TURN_OFF_BATTLE_MODE( battle_ScoreMore );
+ TURN_OFF_BATTLE_MODE( battle_Tag );
+ TURN_OFF_BATTLE_MODE( battle_Hunter );
+ TURN_OFF_BATTLE_MODE( battle_CaptureTheTriad );
+ }
+
+ if ( ModeMenu[ ModeItems.curpos ].active != CP_CursorLocation )
+ {
+ for( i = 0; i < ModeItems.amount; i++ )
+ {
+ if ( ModeMenu[ i ].active == CP_Active )
+ {
+ ModeItems.curpos = i;
+ ModeMenu[ i ].active = CP_CursorLocation;
+ break;
+ }
+ }
+ }
+
+ DrawMenu( &ModeItems, &ModeMenu[ 0 ] );
+ DisplayInfo( 0 );
+ DrawBattleModeDescription( ModeItems.curpos );
+
+ FlipMenuBuf();
+}
+
+
+
+//****************************************************************************
+//
+// DrawBattleModeName()
+//
+//****************************************************************************
+
+void DrawBattleModeName( int which )
+{
+ int width;
+ int height;
+ char *string;
+ font_t *temp;
+
+
+ if ( ( which < battle_Normal ) || ( which > battle_CaptureTheTriad ) )
+ {
+ return;
+ }
+
+ string = BattleModeNames[ which - battle_Normal ];
+
+ temp = CurrentFont;
+ CurrentFont = tinyfont;
+
+ VW_MeasurePropString ( string, &width, &height );
+ DrawMenuBufPropString ( ( 288 - width ) / 2, 4, string );
+// DrawMenuBufPropString ( 270-width, 4, string );
+
+ CurrentFont = temp;
+}
+
+
+//****************************************************************************
+//
+// DrawBattleModeDescription()
+//
+//****************************************************************************
+
+void DrawBattleModeDescription( int w )
+{
+ int width;
+ int height;
+ char *string;
+ font_t *temp;
+
+ EraseMenuBufRegion (25, 4, 287 - 25, 10 );
+
+ temp = CurrentFont;
+ CurrentFont = tinyfont;
+
+ string = BattleModeDescriptions[ w ];
+
+ // Capture the Triad, Tag, ScoreMore, and Hunter can only be
+ // played with 2 or more players
+ if ( numplayers < 2 )
+ {
+ switch( w + 1 )
+ {
+ case battle_ScoreMore :
+ case battle_Tag :
+ case battle_Hunter :
+ case battle_CaptureTheTriad :
+ string = "This mode can only be played with 2 or more players.";
+ break;
+ }
+ }
+
+#if ( SHAREWARE == 1 )
+ switch( w + 1 )
+ {
+ case battle_ScoreMore :
+ case battle_Scavenger :
+ case battle_Tag :
+ case battle_Eluder :
+ case battle_Deluder :
+ case battle_CaptureTheTriad :
+ string = "See Ordering Info to find out how to get this game.";
+ break;
+ }
+#endif
+
+ VW_MeasurePropString ( string, &width, &height );
+ DrawMenuBufPropString ( ( 288 - width ) / 2, 4, string );
+
+ CurrentFont = temp;
+}
+
+
+//****************************************************************************
+//
+// CP_BattleModes ()
+//
+//****************************************************************************
+
+void CP_BattleModes ( void )
+{
+ int which;
+ static char Warning = 0;
+
+ //
+ // ALREADY IN A GAME?
+ //
+ if ( ingame )
+ {
+ if ( !CP_DisplayMsg( CURGAME, 12 ) )
+ {
+ return;
+ }
+ else
+ {
+ EndGameStuff();
+ }
+ }
+
+ if ( ( numplayers==1 ) && ( Warning == 0 ) )
+ {
+ Warning = 1;
+ CP_OnePlayerWarningMessage();
+ }
+
+ DrawBattleModes ();
+
+ damagecount = 0;
+ BATTLEMODE = true;
+
+ do
+ {
+ which = HandleMenu( &ModeItems, &ModeMenu[ 0 ],
+ DrawBattleModeDescription );
+ }
+ while ( which >= 0 );
+
+ handlewhich = 100;
+
+ if ( !StartGame )
+ {
+ BATTLEMODE = false;
+ gamestate.battlemode = battle_StandAloneGame;
+ }
+}
+
+//****************************************************************************
+//
+// DrawBattleOptions ()
+//
+//****************************************************************************
+
+void DrawBattleOptions (void)
+{
+ int i;
+
+ MenuNum = 1;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Battle Mode Options");
+
+ MN_MakeActive ( &BOptItems, &BOptMenu[0], BOptItems.curpos );
+
+ switch( gamestate.battlemode )
+ {
+ case battle_Collector :
+ BOptMenu[2].active = CP_Inactive; // Ammo
+ BOptMenu[6].active = CP_Inactive; // Point Goal
+ break;
+
+ case battle_Scavenger :
+ BOptMenu[6].active = CP_Inactive; // Point Goal
+ break;
+
+ case battle_Tag :
+ BOptMenu[2].active = CP_Inactive; // Ammo
+ break;
+
+ case battle_Eluder :
+ BOptMenu[2].active = CP_Inactive; // Ammo
+ BOptMenu[3].active = CP_Inactive; // Hit points
+ BOptMenu[7].active = CP_Inactive; // Danger damage
+ break;
+ }
+
+ if ( BOptMenu[ BOptItems.curpos ].active == CP_Inactive )
+ {
+ // Find an available cursor position
+ for( i = 0; i < BOptItems.amount; i++ )
+ {
+ if ( BOptMenu[ i ].active == CP_Active )
+ {
+ BOptMenu[ i ].active = CP_CursorLocation;
+ BOptItems.curpos = i;
+ break;
+ }
+ }
+ }
+
+ DrawBattleModeName( gamestate.battlemode );
+ DrawBattleOptionDescription( BOptItems.curpos );
+ DrawMenu (&BOptItems, &BOptMenu[0]);
+ DisplayInfo (0);
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// CP_BattleOptions ()
+//
+//****************************************************************************
+
+void CP_BattleOptions (void)
+{
+ int which;
+
+ DrawBattleOptions ();
+
+ do
+ {
+ which = HandleMenu (&BOptItems, &BOptMenu[0], DrawBattleOptionDescription);
+
+ } while (which >= 0);
+
+ handlewhich = 100;
+// WriteBattleConfig();
+ CalcTics();
+
+ DrawBattleMenu ();
+}
+
+
+
+//****************************************************************************
+//
+// DrawColorMenu ()
+//
+//****************************************************************************
+
+
+void DrawColorMenu( void )
+{
+ int width;
+ int height;
+ char *text;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Uniform Color");
+
+ CurrentFont = smallfont;
+
+ text = colorname[ locplayerstate->uniformcolor ];
+ VW_MeasurePropString ( text, &width, &height );
+ DrawMenuBufPropString ( ( 320 - width ) / 2 - 16, MENU_Y + 5, text );
+ DisplayInfo( 8 );
+ EraseMenuBufRegion( COLORX, COLORY, COLORW, COLORH );
+ DrawTMenuBufBox( COLORX, COLORY, COLORW, COLORH );
+ DrawColoredMenuBufItem( COLORX - 36, COLORY - 33,
+ W_GetNumForName( playerwadname[ locplayerstate->player ] ),
+ locplayerstate->uniformcolor);
+
+
+ if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
+ ( consoleplayer == 0 ) )
+ {
+ DrawBattleModeName( gamestate.battlemode );
+ }
+
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// CP_ColorSelection ()
+//
+//****************************************************************************
+
+int CP_ColorSelection (void)
+{
+ int status;
+
+ locplayerstate->uniformcolor = DefaultPlayerColor;
+
+ DrawColorMenu ();
+ status = ColorMenu();
+ return( status );
+}
+
+int ColorMenu
+(
+ void
+)
+
+{
+ ControlInfo ci;
+ int colorindex;
+ char *text;
+ int width;
+ int height;
+ int timer;
+ int baseshape;
+ int status;
+ boolean update;
+ boolean done;
+
+ colorindex = DefaultPlayerColor;
+ timer = GetTicCount();
+ baseshape = W_GetNumForName( playerwadname[ locplayerstate->player ] );
+
+ update = false;
+ done = false;
+ while( !done )
+ {
+ ReadAnyControl( &ci );
+ if ( ( ci.dir == dir_East ) && ( ( GetTicCount() - timer ) > 5 ) )
+ {
+ update = true;
+ timer = GetTicCount();
+
+ colorindex++;
+ if ( colorindex >= MAXPLAYERCOLORS )
+ {
+ colorindex = 0;
+ }
+
+ MN_PlayMenuSnd( SD_MOVECURSORSND );
+ }
+
+ if ( ( ci.dir == dir_West ) && ( ( GetTicCount() - timer ) > 5 ) )
+ {
+ update = true;
+ timer = GetTicCount();
+
+ colorindex--;
+ if ( colorindex < 0 )
+ {
+ colorindex = MAXPLAYERCOLORS - 1;
+ }
+ MN_PlayMenuSnd( SD_MOVECURSORSND );
+ }
+
+ if ( update )
+ {
+ update = false;
+ DefaultPlayerColor = colorindex;
+ locplayerstate->uniformcolor = colorindex;
+ text = colorname[ locplayerstate->uniformcolor ];
+
+ EraseMenuBufRegion( 0, MENU_Y + 5, 200, 10 );
+ EraseMenuBufRegion( COLORX, COLORY, COLORW, COLORH );
+ VW_MeasurePropString( text, &width, &height );
+ DrawMenuBufPropString( ( 320 - width ) / 2 - 16, MENU_Y + 5, text );
+ DrawTMenuBufBox( COLORX, COLORY, COLORW, COLORH );
+ DrawColoredMenuBufItem( COLORX - 36, COLORY - 33,
+ baseshape, locplayerstate->uniformcolor );
+ }
+
+ if ( ci.button0 || Keyboard[ sc_Space ] || Keyboard[sc_Enter ] )
+ {
+ Keyboard[ sc_Space ] = 0;
+ Keyboard[ sc_Enter ] = 0;
+ MN_PlayMenuSnd( SD_SELECTSND );
+ status = 1;
+ done = true;
+ }
+ else if ( ci.button1 || Keyboard[ sc_Escape ] )
+ {
+ MN_PlayMenuSnd( SD_ESCPRESSEDSND );
+ status = 0;
+ done = true;
+ }
+
+ RefreshMenuBuf( 0 );
+ }
+
+ IN_ClearKeysDown();
+ return( status );
+}
+
+
+//****************************************************************************
+//
+// CP_PlayerSelection ()
+//
+//****************************************************************************
+int CP_PlayerSelection
+(
+ void
+)
+
+{
+ int which;
+
+ // Do Pick-A-Player menu
+ DrawPlayerMenu();
+
+ do
+ {
+ which = HandleMenu( &PlayerItems, &PlayerMenu[ 0 ], DrawNewPlayerDiff );
+ if ( which < 0 )
+ {
+ handlewhich = 1;
+ return( 0 );
+ }
+
+#if ( SHAREWARE == 1 )
+ if ( PlayerMenu[ which ].active == CP_SemiActive )
+ {
+ CP_ErrorMsg( "Choose Player",
+ "Read the Ordering Info section from the Main Menu to "
+ "find out how to get the other characters.",
+ mn_smallfont );
+
+ DrawPlayerMenu();
+ }
+#endif
+ }
+ while( PlayerMenu[ which ].active == CP_SemiActive );
+
+
+#if ( SHAREWARE == 1 )
+ DefaultPlayerCharacter = 0;
+ locplayerstate->player = 0;
+#else
+ DefaultPlayerCharacter = which;
+ locplayerstate->player = which;
+#endif
+
+ return (1);
+}
+
+//****************************************************************************
+//
+// CP_OnePlayerWarningMessage ()
+//
+//****************************************************************************
+
+void CP_OnePlayerWarningMessage
+(
+ void
+)
+
+{
+ CP_ErrorMsg( "Comm-bat Warning",
+ "Comm-bat is designed for modem and network play. "
+ "One player mode is provided for exploration. The "
+ "Collector battle mode is still fun on your own.",
+ mn_smallfont );
+}
+
+
+//****************************************************************************
+//
+// CP_CaptureTheTriadError()
+//
+//****************************************************************************
+
+void CP_CaptureTheTriadError
+(
+ void
+)
+
+{
+ SetupMenuBuf();
+ SetUpControlPanel();
+
+ CP_ErrorMsg( "Comm-bat Warning",
+ "Capture the Traid can only be played with 2 teams."
+ " All players must return to the menu to choose their "
+ "team colors.", mn_largefont );
+
+ CleanUpControlPanel();
+ ShutdownMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// CP_TeamPlayErrorMessage()
+//
+//****************************************************************************
+
+void CP_TeamPlayErrorMessage
+(
+ void
+)
+
+{
+ SetupMenuBuf();
+ SetUpControlPanel();
+
+ CP_ErrorMsg( "Comm-bat Warning",
+ "Team play can only be played with 2 or more teams."
+ " All players must return to the menu to choose their "
+ "team colors.", mn_largefont );
+
+ CleanUpControlPanel();
+ ShutdownMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// CP_ModemGameMessage ()
+//
+//****************************************************************************
+
+#define SITELINES 8
+
+char *sitemessage[] =
+{
+ "HEY! ARE YOU PLAYING ON AN ILLEGAL COPY?",
+ "Network players: it's easy to play legally!",
+ "Just get a site license. For a little over",
+ "the price of two games, you get 10 more battle",
+ "levels, 11 command cards, and a signed Site",
+ "License. We don't charge you for 11 copies--",
+ "just for two! Call 1-800-APOGEE1 to order.",
+ "For more on site licenses, see ORDERING INFO."
+};
+
+void CP_ModemGameMessage (int player )
+
+{
+ int i;
+ EnableScreenStretch();
+ // SetTextMode ( );
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Game Message");
+
+ newfont1 = (font_t *)W_CacheLumpName( "newfnt1", PU_CACHE, Cvt_font_t, 1);
+ CurrentFont = newfont1;
+ if ( modemgame == false )
+ {
+ WindowW = 288;
+ WindowH = 158;
+ PrintX = WindowX = 0;
+ PrintY = WindowY = 60;
+ MenuBufCPrint ("Please wait.\nLoading game.");
+ }
+ else
+ {
+ WindowW = 288;
+ WindowH = 158;
+ PrintX = WindowX = 0;
+ PrintY = WindowY = 50;
+
+ if (networkgame==true)
+ {
+ PrintY = WindowY = 28;
+ }
+
+ if ( player == 0 )
+ {
+ MenuBufCPrint ("Please wait for\nplayers to choose\ntheir characters.");
+ }
+ else
+ {
+ MenuBufCPrint ("Please wait while\nMaster selects\nCOMM-BAT options.");
+ }
+
+ if (gamestate.Product != ROTT_SITELICENSE)
+ {
+ if (networkgame==true)
+ {
+ for( i = 0; i < SITELINES; i++ )
+ {
+ PrintBattleOption( true, 68, 77 + i * 8,
+ sitemessage[ i ] );
+ }
+ }
+ }
+ }
+
+ FlipMenuBuf();
+ RefreshMenuBuf (0);
+
+ DisableScreenStretch();
+}
+
+
+//****************************************************************************
+//
+// DrawGravityMenu ()
+//
+//****************************************************************************
+
+void DrawGravityMenu (void)
+{
+ MenuNum = 1;
+
+ SetAlternateMenuBuf ();
+ ClearMenuBuf();
+ SetMenuTitle ("Gravity");
+
+
+ if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
+ ( consoleplayer == 0 ) )
+ {
+ DrawBattleModeName( gamestate.battlemode );
+ }
+
+ MN_DrawButtons (&GravityItems, &GravityMenu[0],
+ BATTLE_Options[gamestate.battlemode].Gravity, GravityNums);
+ MN_GetActive (&GravityItems, &GravityMenu[0],
+ BATTLE_Options[gamestate.battlemode].Gravity, GravityNums);
+
+ DrawMenu (&GravityItems, &GravityMenu[0]);
+ DrawGravityOptionDescription( GravityItems.curpos );
+ PrintBattleOption( true, 32, 79,
+ "WARNING: High gravity has an unfortunate side effect in" );
+ PrintBattleOption( true, 32, 87,
+ "some levels. It is possible to jump into an area that is" );
+ PrintBattleOption( true, 32, 95,
+ "impossible, or at least extremely difficult to get out" );
+ PrintBattleOption( true, 32, 103,
+ "of. In these situations, the only thing you can do is" );
+ PrintBattleOption( true, 32, 111,
+ "kill your character, or find some kindly soul to do it" );
+ PrintBattleOption( true, 32, 119,
+ "for you. If this fails, you'll just have to end your game." );
+
+ DisplayInfo( 0 );
+
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// CP_GravityOptions ()
+//
+//****************************************************************************
+
+void CP_GravityOptions (void)
+{
+ int which;
+
+ DrawGravityMenu ();
+
+ do
+ {
+ which = HandleMenu (&GravityItems, &GravityMenu[0], DrawGravityOptionDescription);
+
+ if (which >= 0)
+ BATTLE_Options[gamestate.battlemode].Gravity = GravityNums[ which ];
+
+ MN_DrawButtons (&GravityItems, &GravityMenu[0],
+ BATTLE_Options[gamestate.battlemode].Gravity, GravityNums);
+
+ } while (which >= 0);
+
+ handlewhich = 100;
+ DrawBattleOptions ();
+}
+
+
+//****************************************************************************
+//
+// DrawSpeedMenu ()
+//
+//****************************************************************************
+
+void DrawSpeedMenu (void)
+{
+ MenuNum = 1;
+
+ SetAlternateMenuBuf ();
+ ClearMenuBuf();
+ SetMenuTitle ("Speed");
+
+
+ if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
+ ( consoleplayer == 0 ) )
+ {
+ DrawBattleModeName( gamestate.battlemode );
+ }
+
+ MN_DrawButtons (&SpeedItems, &SpeedMenu[0],
+ BATTLE_Options[gamestate.battlemode].Speed, OptionNums );
+ MN_GetActive (&SpeedItems, &SpeedMenu[0],
+ BATTLE_Options[gamestate.battlemode].Speed, OptionNums );
+
+ DrawMenu (&SpeedItems, &SpeedMenu[0]);
+ DrawSpeedOptionDescription( SpeedItems.curpos );
+ DisplayInfo (0);
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// CP_SpeedOptions ()
+//
+//****************************************************************************
+
+void CP_SpeedOptions (void)
+{
+ int which;
+
+ DrawSpeedMenu ();
+
+ do
+ {
+ which = HandleMenu (&SpeedItems, &SpeedMenu[0], DrawSpeedOptionDescription);
+
+ if (which >= 0)
+ BATTLE_Options[gamestate.battlemode].Speed = which;
+
+ MN_DrawButtons (&SpeedItems, &SpeedMenu[0],
+ BATTLE_Options[gamestate.battlemode].Speed, OptionNums );
+ } while (which >= 0);
+
+ handlewhich = 100;
+ DrawBattleOptions ();
+}
+
+
+//****************************************************************************
+//
+// DrawAmmoPerWeaponMenu ()
+//
+//****************************************************************************
+void DrawAmmoPerWeaponMenu
+(
+ void
+)
+
+{
+ MenuNum = 1;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Ammo Per Weapon");
+
+ if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
+ ( consoleplayer == 0 ) )
+ {
+ DrawBattleModeName( gamestate.battlemode );
+ }
+
+ MN_DrawButtons( &AmmoPerWeaponItems, &AmmoPerWeaponMenu[ 0 ],
+ BATTLE_Options[ gamestate.battlemode ].Ammo, OptionNums );
+
+ MN_GetActive( &AmmoPerWeaponItems, &AmmoPerWeaponMenu[ 0 ],
+ BATTLE_Options[ gamestate.battlemode ].Ammo, OptionNums );
+
+ DrawMenu( &AmmoPerWeaponItems, &AmmoPerWeaponMenu[ 0 ] );
+
+ PrintBattleOption( true, 32, 79,
+ "WARNING: Infinite ammo can seriously alter the balance of" );
+ PrintBattleOption( true, 32, 87,
+ "the game. We recommend that you only use it occasionally." );
+ PrintBattleOption( true, 32, 95,
+ "It tends to only work well on small levels with lots of" );
+ PrintBattleOption( true, 32, 103,
+ "weapons, where the action is far more intense. On large" );
+ PrintBattleOption( true, 32, 111,
+ "levels, you may find it causes people to wait in easily" );
+ PrintBattleOption( true, 32, 119,
+ "guardable areas and pick off anyone that comes in the room" );
+ PrintBattleOption( true, 32, 127,
+ "(creating an unfair advantage)." );
+
+ if ( AmmoPerWeaponItems.curpos == 2 )
+ {
+ PrintBattleOption( true, 102, 136, "You have been warned." );
+ }
+
+ DrawAmmoOptionDescription( AmmoPerWeaponItems.curpos );
+ DisplayInfo( 0 );
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// CP_AmmoPerWeaponOptions ()
+//
+//****************************************************************************
+void CP_AmmoPerWeaponOptions
+(
+ void
+)
+
+{
+ int which;
+
+ DrawAmmoPerWeaponMenu();
+
+ do
+ {
+ which = HandleMenu( &AmmoPerWeaponItems, &AmmoPerWeaponMenu[ 0 ], DrawAmmoOptionDescription);
+
+ if (which >= 0)
+ {
+ if ( AmmoPerWeaponItems.curpos == 2 )
+ {
+ MN_PlayMenuSnd( SD_LIGHTNINGSND );
+ PrintBattleOption( true, 102, 136, "You have been warned." );
+ VL_FillPalette(255,255,255);
+ VL_FadeIn(0,255,origpal,10);
+ }
+ else if ( BATTLE_Options[ gamestate.battlemode ].Ammo == 2 )
+ {
+ EraseMenuBufRegion( 102, 136, 84, 8 );
+ MN_PlayMenuSnd( SD_PLAYERTCSND );
+ }
+
+ BATTLE_Options[ gamestate.battlemode ].Ammo = which;
+ }
+
+ MN_DrawButtons( &AmmoPerWeaponItems, &AmmoPerWeaponMenu[ 0 ],
+ BATTLE_Options[ gamestate.battlemode ].Ammo, OptionNums );
+ }
+ while( which >= 0 );
+
+ handlewhich = 100;
+ DrawBattleOptions();
+}
+
+
+//****************************************************************************
+//
+// DrawHitPointsMenu ()
+//
+//****************************************************************************
+void DrawHitPointsMenu
+(
+ void
+)
+
+{
+ MenuNum = 1;
+
+ SetAlternateMenuBuf ();
+ ClearMenuBuf();
+ SetMenuTitle ("Player Hitpoints");
+
+ if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
+ ( consoleplayer == 0 ) )
+ {
+ DrawBattleModeName( gamestate.battlemode );
+ }
+
+ MN_DrawButtons( &HitPointItems, &HitPointMenu[ 0 ],
+ BATTLE_Options[ gamestate.battlemode ].HitPoints, HitPointNums );
+
+ MN_GetActive( &HitPointItems, &HitPointMenu[ 0 ],
+ BATTLE_Options[ gamestate.battlemode ].HitPoints, HitPointNums );
+
+ DrawMenu( &HitPointItems, &HitPointMenu[ 0 ] );
+ DrawHitPointsOptionDescription( HitPointItems.curpos );
+ DisplayInfo( 0 );
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// CP_HitPointsOptions ()
+//
+//****************************************************************************
+
+void CP_HitPointsOptions (void)
+{
+ int which;
+
+ DrawHitPointsMenu ();
+
+ do
+ {
+ which = HandleMenu (&HitPointItems, &HitPointMenu[0], DrawHitPointsOptionDescription);
+
+ if (which >= 0)
+ BATTLE_Options[gamestate.battlemode].HitPoints = HitPointNums[ which ];
+
+ MN_DrawButtons (&HitPointItems, &HitPointMenu[0],
+ BATTLE_Options[gamestate.battlemode].HitPoints, HitPointNums);
+
+ } while (which >= 0);
+
+ handlewhich = 100;
+ DrawBattleOptions ();
+}
+
+
+
+//****************************************************************************
+//
+// DrawSpawnControlMenu ()
+//
+//****************************************************************************
+void DrawSpawnControlMenu
+(
+ void
+)
+
+{
+ int i;
+
+ MenuNum = 1;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Radical Options");
+
+ MN_MakeActive( &SpawnItems, &SpawnMenu[ 0 ], SpawnItems.curpos );
+
+#if ( SHAREWARE == 1 )
+ BATTLE_Options[ gamestate.battlemode ].SpawnMines = false;
+ SpawnMenu[ 3 ].active = CP_Inactive; // Mines
+#endif
+
+ switch( gamestate.battlemode )
+ {
+ case battle_Normal :
+ break;
+
+ case battle_ScoreMore :
+ break;
+
+ case battle_Collector :
+ SpawnMenu[ 2 ].active = CP_Inactive; // Weapons
+ SpawnMenu[ 5 ].active = CP_Inactive; // Persistence
+ SpawnMenu[ 6 ].active = CP_Inactive; // Random Weapons
+ SpawnMenu[ 7 ].active = CP_Inactive; // Friendly Fire
+ break;
+
+ case battle_Scavenger :
+ SpawnMenu[ 7 ].active = CP_Inactive; // Friendly Fire
+ break;
+
+ case battle_Hunter :
+ break;
+
+ case battle_Tag :
+ SpawnMenu[ 2 ].active = CP_Inactive; // Weapons
+ SpawnMenu[ 5 ].active = CP_Inactive; // Persistence
+ SpawnMenu[ 6 ].active = CP_Inactive; // Random Weapons
+ break;
+
+ case battle_Eluder :
+ SpawnMenu[ 1 ].active = CP_Inactive; // Health
+ SpawnMenu[ 2 ].active = CP_Inactive; // Weapons
+ SpawnMenu[ 4 ].active = CP_Inactive; // Respawn
+ SpawnMenu[ 5 ].active = CP_Inactive; // Persistence
+ SpawnMenu[ 6 ].active = CP_Inactive; // Random Weapons
+ SpawnMenu[ 7 ].active = CP_Inactive; // Friendly Fire
+ break;
+
+ case battle_Deluder :
+ SpawnMenu[ 7 ].active = CP_Inactive; // Friendly Fire
+ break;
+
+ case battle_CaptureTheTriad :
+ SpawnMenu[ 7 ].active = CP_Inactive; // Friendly Fire
+ break;
+ }
+
+ if ( SpawnMenu[ SpawnItems.curpos ].active == CP_Inactive )
+ {
+ // Find an available cursor position
+ for( i = 0; i < SpawnItems.amount; i++ )
+ {
+ if ( SpawnMenu[ i ].active == CP_Active )
+ {
+ SpawnMenu[ i ].active = CP_CursorLocation;
+ SpawnItems.curpos = i;
+ break;
+ }
+ }
+ }
+
+ if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
+ ( consoleplayer == 0 ) )
+ {
+ DrawBattleModeName( gamestate.battlemode );
+ }
+
+ DrawSpawnControlButtons();
+
+ MN_GetCursorLocation( &SpawnItems, &SpawnMenu[ 0 ] );
+
+ DrawMenu( &SpawnItems, &SpawnMenu[ 0 ] );
+ DrawRadicalOptionDescription( SpawnItems.curpos );
+ DisplayInfo( 0 );
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// DrawSpawnControlButtons ()
+//
+//****************************************************************************
+void DrawSpawnControlButtons
+(
+ void
+)
+
+{
+ int x;
+ int y;
+ int button_on;
+ int button_off;
+
+ button_on = W_GetNumForName( "snd_on" );
+ button_off = W_GetNumForName( "snd_off" );
+
+ x = SpawnItems.x + 18;
+ y = SpawnItems.y - 1;
+
+ if ( BATTLE_Options[ gamestate.battlemode ].SpawnDangers )
+ {
+ DrawMenuBufItem( x, y, button_on );
+ }
+ else
+ {
+ EraseMenuBufRegion( x, y, 16, 16 );
+ DrawMenuBufItem( x, y, button_off );
+ }
+
+ y += 14;
+ if ( BATTLE_Options[ gamestate.battlemode ].SpawnHealth )
+ {
+ DrawMenuBufItem( x, y, button_on );
+ }
+ else
+ {
+ EraseMenuBufRegion( x, y, 16, 16 );
+ DrawMenuBufItem( x, y, button_off );
+ }
+
+ y += 14;
+ if ( BATTLE_Options[ gamestate.battlemode ].SpawnWeapons )
+ {
+ DrawMenuBufItem( x, y, button_on );
+ }
+ else
+ {
+ EraseMenuBufRegion( x, y, 16, 16 );
+ DrawMenuBufItem( x, y, button_off );
+ }
+
+ y += 14;
+ if ( BATTLE_Options[ gamestate.battlemode ].SpawnMines )
+ {
+ DrawMenuBufItem( x, y, button_on );
+ }
+ else
+ {
+ EraseMenuBufRegion( x, y, 16, 16 );
+ DrawMenuBufItem( x, y, button_off );
+ }
+
+ y += 14;
+ if ( BATTLE_Options[ gamestate.battlemode ].RespawnItems )
+ {
+ DrawMenuBufItem( x, y, button_on );
+ }
+ else
+ {
+ EraseMenuBufRegion( x, y, 16, 16 );
+ DrawMenuBufItem( x, y, button_off );
+ }
+
+ y += 14;
+ if ( BATTLE_Options[ gamestate.battlemode ].WeaponPersistence )
+ {
+ DrawMenuBufItem( x, y, button_on );
+ }
+ else
+ {
+ EraseMenuBufRegion( x, y, 16, 16 );
+ DrawMenuBufItem( x, y, button_off );
+ }
+
+ y += 14;
+ if ( BATTLE_Options[ gamestate.battlemode ].RandomWeapons )
+ {
+ DrawMenuBufItem( x, y, button_on );
+ }
+ else
+ {
+ EraseMenuBufRegion( x, y, 16, 16 );
+ DrawMenuBufItem( x, y, button_off );
+ }
+
+ y += 14;
+ if ( BATTLE_Options[ gamestate.battlemode ].FriendlyFire )
+ {
+ DrawMenuBufItem( x, y, button_on );
+ }
+ else
+ {
+ EraseMenuBufRegion( x, y, 16, 16 );
+ DrawMenuBufItem( x, y, button_off );
+ }
+}
+
+
+//****************************************************************************
+//
+// CP_SpawnControlOptions ()
+//
+//****************************************************************************
+void CP_SpawnControlOptions
+(
+ void
+)
+
+{
+ int which;
+
+ DrawSpawnControlMenu();
+
+ do
+ {
+ which = HandleMenu( &SpawnItems, &SpawnMenu[ 0 ], DrawRadicalOptionDescription );
+ switch( which )
+ {
+ case 0 :
+ BATTLE_Options[ gamestate.battlemode ].SpawnDangers =
+ !BATTLE_Options[ gamestate.battlemode ].SpawnDangers;
+ break;
+
+ case 1 :
+ BATTLE_Options[ gamestate.battlemode ].SpawnHealth =
+ !BATTLE_Options[ gamestate.battlemode ].SpawnHealth;
+ break;
+
+ case 2 :
+ BATTLE_Options[ gamestate.battlemode ].SpawnWeapons =
+ !BATTLE_Options[ gamestate.battlemode ].SpawnWeapons;
+ break;
+
+ case 3 :
+ BATTLE_Options[ gamestate.battlemode ].SpawnMines =
+ !BATTLE_Options[ gamestate.battlemode ].SpawnMines;
+ break;
+
+ case 4 :
+ BATTLE_Options[ gamestate.battlemode ].RespawnItems =
+ !BATTLE_Options[ gamestate.battlemode ].RespawnItems;
+ break;
+
+ case 5 :
+ BATTLE_Options[ gamestate.battlemode ].WeaponPersistence =
+ !BATTLE_Options[ gamestate.battlemode ].WeaponPersistence;
+ break;
+
+ case 6 :
+ BATTLE_Options[ gamestate.battlemode ].RandomWeapons =
+ !BATTLE_Options[ gamestate.battlemode ].RandomWeapons;
+ break;
+
+ case 7 :
+ BATTLE_Options[ gamestate.battlemode ].FriendlyFire =
+ !BATTLE_Options[ gamestate.battlemode ].FriendlyFire;
+ break;
+ }
+
+ DrawSpawnControlButtons();
+ }
+ while( which >= 0 );
+
+ handlewhich = 100;
+ DrawBattleOptions();
+}
+
+
+
+//****************************************************************************
+//
+// DrawLightLevelMenu ()
+//
+//****************************************************************************
+
+void DrawLightLevelMenu (void)
+{
+ MenuNum = 1;
+
+ SetAlternateMenuBuf ();
+ ClearMenuBuf();
+ SetMenuTitle ("Light Levels");
+
+
+ if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
+ ( consoleplayer == 0 ) )
+ {
+ DrawBattleModeName( gamestate.battlemode );
+ }
+
+ MN_DrawButtons (&LightLevelItems, &LightLevelMenu[0],
+ BATTLE_Options[gamestate.battlemode].LightLevel, OptionNums );
+ MN_GetActive (&LightLevelItems, &LightLevelMenu[0],
+ BATTLE_Options[gamestate.battlemode].LightLevel, OptionNums );
+
+ DrawMenu (&LightLevelItems, &LightLevelMenu[0]);
+ DrawLightLevelOptionDescription( LightLevelItems.curpos );
+ DisplayInfo (0);
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// CP_LightLevelOptions ()
+//
+//****************************************************************************
+
+void CP_LightLevelOptions (void)
+{
+ int which;
+
+ DrawLightLevelMenu ();
+
+ do
+ {
+ which = HandleMenu (&LightLevelItems, &LightLevelMenu[0], DrawLightLevelOptionDescription);
+
+ if (which >= 0)
+ BATTLE_Options[gamestate.battlemode].LightLevel = which;
+
+ MN_DrawButtons (&LightLevelItems, &LightLevelMenu[0],
+ BATTLE_Options[gamestate.battlemode].LightLevel, OptionNums );
+
+ } while (which >= 0);
+
+ handlewhich = 100;
+ DrawBattleOptions ();
+}
+
+
+
+//****************************************************************************
+//
+// DrawPointGoalMenu()
+//
+//****************************************************************************
+
+void DrawPointGoalMenu
+(
+ void
+)
+
+{
+ MenuNum = 1;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Point Goal");
+
+ if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
+ ( consoleplayer == 0 ) )
+ {
+ DrawBattleModeName( gamestate.battlemode );
+ }
+
+ MN_DrawButtons( &PointGoalItems, &PointGoalMenu[ 0 ],
+ BATTLE_Options[ gamestate.battlemode ].Kills, KillNums );
+
+ MN_GetActive( &PointGoalItems, &PointGoalMenu[ 0 ],
+ BATTLE_Options[ gamestate.battlemode ].Kills, KillNums );
+
+ DrawMenu( &PointGoalItems, &PointGoalMenu[ 0 ] );
+ DrawPointGoalOptionDescription( PointGoalItems.curpos );
+ DisplayInfo( 0 );
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// CP_PointGoalOptions()
+//
+//****************************************************************************
+
+void CP_PointGoalOptions
+(
+ void
+)
+
+{
+ int which;
+
+ DrawPointGoalMenu();
+
+ do
+ {
+ which = HandleMenu( &PointGoalItems, &PointGoalMenu[ 0 ], DrawPointGoalOptionDescription );
+
+ if ( which >= 0 )
+ {
+ BATTLE_Options[ gamestate.battlemode ].Kills = KillNums[ which ];
+
+ MN_DrawButtons( &PointGoalItems, &PointGoalMenu[ 0 ],
+ BATTLE_Options[ gamestate.battlemode ].Kills, KillNums );
+ }
+ }
+ while( which >= 0 );
+
+ handlewhich = 100;
+ DrawBattleOptions();
+}
+
+
+//****************************************************************************
+//
+// DrawDangerMenu ()
+//
+//****************************************************************************
+
+void DrawDangerMenu (void)
+{
+ MenuNum = 1;
+
+ SetAlternateMenuBuf ();
+ ClearMenuBuf();
+ SetMenuTitle ("Danger Damage");
+
+
+ if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
+ ( consoleplayer == 0 ) )
+ {
+ DrawBattleModeName( gamestate.battlemode );
+ }
+ MN_DrawButtons (&DangerItems, &DangerMenu[0],
+ BATTLE_Options[gamestate.battlemode].DangerDamage, DangerNums);
+ MN_GetActive (&DangerItems, &DangerMenu[0],
+ BATTLE_Options[gamestate.battlemode].DangerDamage, DangerNums);
+
+ DrawMenu (&DangerItems, &DangerMenu[0]);
+ DrawDangerDamageOptionDescription( DangerItems.curpos );
+ DisplayInfo (0);
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// CP_DangerOptions ()
+//
+//****************************************************************************
+
+void CP_DangerOptions (void)
+{
+ int which;
+
+ DrawDangerMenu ();
+
+ do
+ {
+ which = HandleMenu (&DangerItems, &DangerMenu[0], DrawDangerDamageOptionDescription);
+
+ if (which >= 0)
+ BATTLE_Options[gamestate.battlemode].DangerDamage = DangerNums[which];
+
+ MN_DrawButtons (&DangerItems, &DangerMenu[0],
+ BATTLE_Options[gamestate.battlemode].DangerDamage, DangerNums);
+
+ } while (which >= 0);
+
+ handlewhich = 100;
+ DrawBattleOptions ();
+}
+
+
+//****************************************************************************
+//
+// DrawTimeLimitMenu ()
+//
+//****************************************************************************
+
+void DrawTimeLimitMenu (void)
+{
+ MenuNum = 1;
+
+ SetAlternateMenuBuf ();
+ ClearMenuBuf();
+ SetMenuTitle ("Time Limit");
+
+
+ if ( ( gamestate.battlemode != battle_StandAloneGame ) &&
+ ( consoleplayer == 0 ) )
+ {
+ DrawBattleModeName( gamestate.battlemode );
+ }
+ MN_DrawButtons (&TimeLimitItems, &TimeLimitMenu[0],
+ BATTLE_Options[gamestate.battlemode].TimeLimit, TimeLimitNums);
+ MN_GetActive (&TimeLimitItems, &TimeLimitMenu[0],
+ BATTLE_Options[gamestate.battlemode].TimeLimit, TimeLimitNums);
+
+ if ( gamestate.battlemode == battle_Hunter )
+ {
+ TimeLimitMenu[7].active = CP_Inactive; // No time limit
+ if ( TimeLimitItems.curpos == 7 )
+ {
+ TimeLimitMenu[0].active = CP_CursorLocation;
+ TimeLimitItems.curpos = 0;
+ }
+ }
+
+ DrawMenu (&TimeLimitItems, &TimeLimitMenu[0]);
+ DrawTimeLimitOptionDescription( TimeLimitItems.curpos );
+ DisplayInfo (0);
+ FlipMenuBuf();
+}
+
+
+//****************************************************************************
+//
+// CP_TimeLimitOptions ()
+//
+//****************************************************************************
+
+void CP_TimeLimitOptions (void)
+{
+ int which;
+
+ DrawTimeLimitMenu ();
+
+ do
+ {
+ which = HandleMenu (&TimeLimitItems, &TimeLimitMenu[0], DrawTimeLimitOptionDescription);
+
+ if (which >= 0)
+ BATTLE_Options[gamestate.battlemode].TimeLimit = TimeLimitNums[which];
+
+ MN_DrawButtons (&TimeLimitItems, &TimeLimitMenu[0],
+ BATTLE_Options[gamestate.battlemode].TimeLimit, TimeLimitNums);
+
+ } while (which >= 0);
+
+ handlewhich = 100;
+ DrawBattleOptions ();
+}
+
+void PrintBattleOption
+(
+ boolean inmenu,
+ int x,
+ int y,
+ char *text
+)
+
+{
+ if ( inmenu )
+ {
+ IFont = ( cfont_t * )W_CacheLumpName( "itnyfont", PU_CACHE, Cvt_cfont_t, 1 );
+ DrawMenuBufIString( x + 1, y + 1, text, 0 );
+ DrawMenuBufIString( x, y, text, ACTIVECOLOR );
+ }
+ else
+ {
+ PrintX = x;
+ PrintY = y;
+ US_BufPrint( text );
+ }
+}
+
+void ShowBattleOption
+(
+ boolean inmenu,
+ int PosX,
+ int PosY,
+ int column,
+ int Line,
+ char *text1,
+ char *text2
+)
+
+{
+ char text[ 80 ];
+ int x;
+ int y;
+
+ y = PosY + ( Line * 7 );
+ x = PosX + column * 120;
+
+ PrintBattleOption( inmenu, x, y, text1 );
+
+ strcpy( text, ": " );
+ strcat( text, text2 );
+
+ PrintBattleOption( inmenu, x + 60, y, text );
+}
+
+void ShowBattleOptions
+(
+ boolean inmenu,
+ int PosX,
+ int PosY
+)
+
+{
+ battle_type *options;
+ battle_type BatOps;
+ char *string;
+ char text[ 80 ];
+ int width;
+ int height;
+ int temp;
+
+ CurrentFont = tinyfont;
+
+ strcpy( text, "CURRENT OPTIONS FOR " );
+ strcat( text, BattleModeNames[ gamestate.battlemode - battle_Normal ] );
+ VW_MeasurePropString ( text, &width, &height );
+ if ( inmenu )
+ {
+ temp = 288;
+ }
+ else
+ {
+ temp = 320;
+ }
+ PrintBattleOption( inmenu, (temp - width)/2, PosY, text );
+
+ PosY++;
+
+ BATTLE_GetOptions( &BatOps );
+ options = &BatOps;
+
+ ShowBattleOption( inmenu, PosX, PosY, 0, 1, "Friendly Fire",
+ ( options->FriendlyFire ) ? "On" : "Off" );
+
+ ShowBattleOption( inmenu, PosX, PosY, 0, 2, "Weapon Persist",
+ ( options->WeaponPersistence ) ? "On" : "Off" );
+
+ ShowBattleOption( inmenu, PosX, PosY, 0, 3, "Random Weapons",
+ ( options->RandomWeapons ) ? "On" : "Off" );
+
+ ShowBattleOption( inmenu, PosX, PosY, 0, 4, "Respawn Items",
+ ( options->RespawnItems ) ? "On" : "Off" );
+
+ ShowBattleOption( inmenu, PosX, PosY, 0, 5, "Spawn Health",
+ ( options->SpawnHealth ) ? "On" : "Off" );
+
+ ShowBattleOption( inmenu, PosX, PosY, 0, 6, "Spawn Weapons",
+ ( options->SpawnWeapons ) ? "On" : "Off" );
+
+ ShowBattleOption( inmenu, PosX, PosY, 0, 7, "Spawn Mines",
+ ( options->SpawnMines ) ? "On" : "Off" );
+
+ ShowBattleOption( inmenu, PosX, PosY, 0, 8, "Spawn Dangers",
+ ( options->SpawnDangers ) ? "On" : "Off" );
+
+ switch( options->DangerDamage )
+ {
+ case bo_danger_low :
+ string = "Low";
+ break;
+
+ case bo_danger_normal :
+ string = "Normal";
+ break;
+
+ case bo_danger_kill :
+ string = "Kill";
+ break;
+
+ default :
+ itoa( options->DangerDamage, text, 10 );
+ string = text;
+ }
+ ShowBattleOption( inmenu, PosX, PosY, 0, 9, "Danger Damage", string );
+
+ GetMapFileName ( text );
+ ShowBattleOption( inmenu, PosX, PosY, 0, 10, "Filename", text );
+
+ itoa( numplayers, text, 10 );
+ ShowBattleOption( inmenu, PosX, PosY, 1, 1, "Players", text );
+
+ if ( options->TimeLimit == bo_time_infinite )
+ {
+ string = "None";
+ }
+ else
+ {
+ itoa( options->TimeLimit, text, 10 );
+ string = text;
+ }
+ ShowBattleOption( inmenu, PosX, PosY, 1, 2, "Time Limit", string );
+
+ if ( ( gamestate.battlemode == battle_Collector ) ||
+ ( gamestate.battlemode == battle_Scavenger ) )
+ {
+ string = "?";
+ }
+ else
+ {
+ switch( options->Kills )
+ {
+ case bo_kills_random :
+ string = "Random";
+ break;
+
+ case bo_kills_blind :
+ string = "Blind";
+ break;
+
+ case bo_kills_infinite :
+ string = "Infinite";
+ break;
+
+ default :
+ itoa( options->Kills, text, 10 );
+ string = text;
+ }
+ }
+ ShowBattleOption( inmenu, PosX, PosY, 1, 3, "Point Goal", string );
+
+ switch( options->Ammo )
+ {
+ case bo_one_shot :
+ string = "One shot";
+ break;
+
+ case bo_normal_shots :
+ string = "Normal";
+ break;
+
+ case bo_infinite_shots :
+ string = "Gunfinity";
+ break;
+ }
+ ShowBattleOption( inmenu, PosX, PosY, 1, 4, "Ammo", string );
+
+ if ( options->HitPoints == bo_character_hitpoints )
+ {
+ string = "Character";
+ }
+ else
+ {
+ itoa( options->HitPoints, text, 10 );
+ string = text;
+ }
+ ShowBattleOption( inmenu, PosX, PosY, 1, 5, "Hit Points", string );
+
+ itoa( options->RespawnTime, text, 10 );
+ ShowBattleOption( inmenu, PosX, PosY, 1, 6, "Respawn Time", text );
+
+ switch( options->Speed )
+ {
+ case bo_normal_speed :
+ string = "Normal";
+ break;
+
+ case bo_fast_speed :
+ string = "Fast";
+ break;
+ }
+ ShowBattleOption( inmenu, PosX, PosY, 1, 7, "Speed", string );
+
+ switch( options->LightLevel )
+ {
+ case bo_light_dark :
+ string = "Dark";
+ break;
+
+ case bo_light_normal :
+ string = "Normal";
+ break;
+
+ case bo_light_bright :
+ string = "Bright";
+ break;
+
+ case bo_light_fog :
+ string = "Fog";
+ break;
+
+ case bo_light_periodic :
+ string = "Periodic";
+ break;
+
+ case bo_light_lightning :
+ string = "Lightning";
+ break;
+ }
+ ShowBattleOption( inmenu, PosX, PosY, 1, 8, "Light", string );
+
+ if ( options->Gravity == NORMAL_GRAVITY )
+ {
+ string = "Normal";
+ temp = NORMAL_GRAVITY;
+ }
+ else if ( options->Gravity < NORMAL_GRAVITY )
+ {
+ string = "Low";
+ temp = LOW_GRAVITY;
+ }
+ else
+ {
+ string = "High";
+ temp = HIGH_GRAVITY;
+ }
+
+ strcpy( text, string );
+ if ( options->Gravity < (unsigned int)temp )
+ {
+ strcat( text, "-" );
+ }
+
+ if ( options->Gravity > (unsigned int)temp )
+ {
+ strcat( text, "+" );
+ }
+ ShowBattleOption( inmenu, PosX, PosY, 1, 9, "Gravity", text );
+}
+
+
+//****************************************************************************
+//
+// SetMenuHeader()
+//
+//****************************************************************************
+
+void SetMenuHeader
+(
+ char *header
+)
+
+{
+ int width;
+ int height;
+
+ EraseMenuBufRegion( 16, 0, 256, 16 );
+
+ CurrentFont = tinyfont;
+ VW_MeasurePropString ( header, &width, &height );
+ DrawMenuBufPropString ( ( 288 - width ) / 2, 4, header );
+
+ RefreshMenuBuf( 0 );
+}
+
+
+//****************************************************************************
+//
+// DrawMultiPageCustomMenu()
+//
+//****************************************************************************
+
+void DrawMultiPageCustomMenu
+(
+ char *title,
+ void ( *redrawfunc )( void )
+)
+
+{
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle( title );
+
+ DrawMenu( &MultiPageCustomItems, &MultiPageCustomMenu[ 0 ] );
+
+ DisplayInfo( 0 );
+
+ if ( redrawfunc != NULL )
+ {
+ redrawfunc();
+ }
+
+ CalcTics();
+ FlipMenuBuf();
+ RefreshMenuBuf( 0 );
+}
+
+
+//****************************************************************************
+//
+// HandleMultiPageCustomMenu()
+//
+//****************************************************************************
+
+int HandleMultiPageCustomMenu
+(
+ char **names,
+ int amount,
+ int curpos,
+ char *title,
+ void ( *routine )( int w ),
+ void ( *redrawfunc )( void ),
+ boolean exitonselect
+)
+
+{
+ boolean redraw;
+ int page;
+ int cursorpos;
+ int maxpos;
+ int numpos;
+ int which;
+ int selection;
+ int i;
+ char letter;
+
+ MenuNum = 11;
+
+ cursorpos = curpos % MAXCUSTOM;
+ page = curpos - cursorpos;
+ MultiPageCustomItems.curpos = cursorpos + 2;
+
+ redraw = true;
+
+ do
+ {
+ if ( redraw )
+ {
+ redraw = false;
+ MultiPageCustomMenu[ 0 ].active = CP_Active;
+ MultiPageCustomMenu[ 1 ].active = CP_Active;
+ if ( page == 0 )
+ {
+ MultiPageCustomMenu[ 1 ].active = CP_Inactive;
+ }
+
+ maxpos = page + MAXCUSTOM;
+ if ( maxpos >= amount )
+ {
+ MultiPageCustomMenu[ 0 ].active = CP_Inactive;
+ maxpos = amount;
+ }
+
+ numpos = maxpos - page + 2;
+ MultiPageCustomItems.amount = numpos;
+
+ for( i = 2; i < numpos; i++ )
+ {
+ MultiPageCustomMenu[ i ].active = CP_Active;
+
+ // Set the name of the level
+ strcpy (MultiPageCustomNames[ i ], names[ page + i - 2 ]);
+
+ // Set the quick key
+ letter = *names[ page + i - 2 ];
+
+ // Force it to upper case
+ if ( ( letter >= 'a' ) && ( letter <= 'z' ) )
+ {
+ letter = letter - 'a' + 'A';
+ }
+
+ // Only use letters
+ if ( ( letter < 'A' ) || ( letter > 'Z' ) )
+ {
+ letter = 'a';
+ }
+ MultiPageCustomMenu[ i ].letter = letter;
+ }
+
+ // If the cursor is at an invalid position, find a valid one
+ cursorpos = MultiPageCustomItems.curpos;
+ if ( cursorpos >= numpos )
+ {
+ cursorpos = numpos - 1;
+ }
+ else
+ {
+ while( MultiPageCustomMenu[ cursorpos ].active == CP_Inactive )
+ {
+ cursorpos++;
+ }
+ }
+ MultiPageCustomItems.curpos = cursorpos;
+ MultiPageCustomMenu[ cursorpos ].active = CP_CursorLocation;
+
+ DrawMultiPageCustomMenu( title, redrawfunc );
+ }
+
+ which = HandleMenu( &MultiPageCustomItems, &MultiPageCustomMenu[ 0 ],
+ NULL );
+
+ switch( which )
+ {
+ case ESCPRESSED :
+ selection = -1;
+ break;
+
+ case PAGEDOWN :
+ case 0 :
+ page += MAXCUSTOM;
+ which = 0;
+ redraw = true;
+ break;
+
+ case PAGEUP :
+ case 1 :
+ page -= MAXCUSTOM;
+ which = 0;
+ redraw = true;
+ break;
+
+ default :
+ selection = page + which - 2;
+ if ( routine )
+ {
+ routine( selection );
+ }
+
+ if ( exitonselect )
+ {
+ which = -1;
+ }
+ break;
+ }
+ }
+ while( which >= 0 );
+
+ return( selection );
+}
+
+
+//****************************************************************************
+//
+// CP_LevelSelectionRedraw()
+//
+//****************************************************************************
+
+void CP_LevelSelectionRedraw
+(
+ void
+)
+
+{
+ if ( gamestate.battlemode >= battle_Normal )
+ {
+ SetMenuHeader( BattleModeNames[ gamestate.battlemode - battle_Normal ] );
+ }
+}
+
+
+//****************************************************************************
+//
+// CP_LevelSelectionMenu ()
+//
+//****************************************************************************
+int CP_LevelSelectionMenu
+(
+ void
+)
+
+{
+ static char levelcursorpos[ 2 ] = { 0 };
+
+ char *LevelNames[ 100 ];
+ int whichlevels;
+ int numlevels;
+ int level;
+ int i;
+
+ whichlevels = 0;
+ if ( BATTLEMODE )
+ {
+ whichlevels = 1;
+ }
+
+ mapinfo = ( mapfileinfo_t * )SafeMalloc( sizeof( mapfileinfo_t ) );
+ GetMapInfo( mapinfo );
+
+ numlevels = mapinfo->nummaps;
+ if ( numlevels <= 0 )
+ {
+ Error( "CP_LevelSelectionMenu : No maps found in RTL/RTC file." );
+ }
+
+ for( i = 0; i < numlevels; i++ )
+ {
+ LevelNames[ i ] = mapinfo->maps[ i ].mapname;
+ }
+
+ level = HandleMultiPageCustomMenu( LevelNames, numlevels,
+ levelcursorpos[ whichlevels ], "Level Selection", NULL,
+ CP_LevelSelectionRedraw, true );
+
+ SafeFree( mapinfo );
+
+ if ( level >= 0 )
+ {
+ levelcursorpos[ whichlevels ] = level;
+ }
+
+ return( level );
+}
+
+
+//****************************************************************************
+//
+// DrawEnterCodeNameMenu ()
+//
+//****************************************************************************
+void DrawEnterCodeNameMenu
+(
+ void
+)
+
+{
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Enter CodeName");
+
+ if ( consoleplayer == 0 )
+ {
+ DrawBattleModeName( gamestate.battlemode );
+ }
+
+ WindowW = 288;
+ WindowH = 158;
+ WindowX = 0;
+ WindowY = 50;
+ PrintX = 0;
+ PrintY = 50;
+
+ CurrentFont = smallfont;
+
+ MenuBufCPrint( "Enter CodeName\n" );
+ MenuBufCPrint( "maximum 8 letters\n" );
+
+ DrawSTMenuBuf( ( 288 - 92 ) / 2 - 2, 80 - 2, 92 + 4, 10 + 4, false );
+
+ DrawMenuBufPropString( ( 288 - 92 ) / 2, 80, CodeName );
+
+ WindowX = 144 - ( 9 * 4 );
+ PrintX = WindowX;
+
+ FlipMenuBuf();
+ RefreshMenuBuf( 0 );
+}
+
+//****************************************************************************
+//
+// CP_EnterCodeNameMenu ()
+//
+//****************************************************************************
+int CP_EnterCodeNameMenu
+(
+ void
+)
+
+{
+ char input[10];
+
+ DrawEnterCodeNameMenu();
+
+ memset(input,0,sizeof(input));
+ strcpy(input,CodeName);
+
+
+ if (US_LineInput ((288-92)/2, 80, input, input, true, 8, 92, 0))
+ {
+ strcpy (&locplayerstate->codename[0], input);
+ strcpy (CodeName, input);
+ WaitKeyUp();
+ return 1;
+ }
+ else
+ {
+ WaitKeyUp();
+ return 0;
+ }
+}
+
+#ifdef DOS
+void SS_DrawSBTypeMenu( void );
+void SS_SBTypeMenu( void );
+void SS_DrawPortMenu( void );
+void SS_PortMenu( void );
+void SS_Draw8BitDMAMenu( void );
+void SS_8BitDMAMenu( void );
+void SS_Draw16BitDMAMenu( void );
+void SS_16BitDMAMenu( void );
+void SS_DrawIrqMenu( void );
+void SS_IrqMenu( void );
+void SS_Quit( void );
+void DrawSoundSetupMainMenu( void );
+void CP_SoundSetup( void );
+void SS_MusicMenu( void );
+void SS_DrawMusicMenu( void );
+void SS_SoundMenu( void );
+void SS_DrawSoundMenu( void );
+void SS_SetupMusicCardMenu( void );
+void DrawMusicCardMenu( void );
+void SS_SetupSoundBlaster( int sbmenu );
+void SS_SetupSoundCardMenu( void );
+void SS_VoiceMenu( int sbmenu );
+void SS_DrawVoiceMenu( void );
+void SS_ChannelMenu( void );
+void SS_DrawChannelMenu( void );
+void SS_BitMenu( void );
+void SS_DrawBitMenu( void );
+
+extern int musicnums[ 11 ];
+extern int fxnums[ 11 ];
+
+static int midinums[ 12 ] = {
+ 0x220, 0x230, 0x240, 0x250, 0x300, 0x320,
+ 0x330, 0x332, 0x334, 0x336, 0x340, 0x360
+};
+static int voicenums[8] = {1, 2, 3, 4, 5, 6, 7, 8};
+static int resnums[2] = {8, 16};
+static int smnums[2] = {1, 2};
+
+//
+// MENU ITEMS
+//
+CP_MenuNames SoundSetupMenuNames[] =
+{
+ "SETUP SOUND FX",
+ "SETUP MUSIC",
+ "SOUND FX VOLUME",
+ "MUSIC VOLUME",
+ "QUIT"
+};
+
+CP_iteminfo SoundSetupMenuItems = { MENU_X, 48, 5, STARTITEM, 32, SoundSetupMenuNames, mn_largefont };
+CP_itemtype SoundSetupMenu[] =
+{
+ { CP_CursorLocation, "\0", 'S', (menuptr)SS_SoundMenu },
+ { CP_Active, "\0", 'S', (menuptr)SS_MusicMenu },
+ { CP_Active, "\0", 'S', (menuptr)FXVolume },
+ { CP_Active, "\0", 'M', (menuptr)MusicVolume },
+ { CP_Active, "\0", 'Q', (menuptr)SS_Quit }
+};
+
+CP_MenuNames SoundSetupMusicNames[] =
+{
+ "None",
+ "Ultrasound",
+ "Sound Blaster",
+ "Sound Man 16",
+ "Pro Audio Spectrum",
+ "AWE 32",
+ "Soundscape",
+ "Wave Blaster",
+ "General Midi",
+ "Sound Canvas",
+ "Adlib"
+};
+
+CP_iteminfo SoundSetupMusicItems = { 44, MENU_Y + 15, 11, STARTITEM, 16, SoundSetupMusicNames, mn_smallfont };
+CP_itemtype SoundSetupMusic[] =
+{
+ { CP_CursorLocation, "\0", 'N', (menuptr)SS_SetupMusicCardMenu },
+ { CP_Active, "\0", 'U', (menuptr)SS_SetupMusicCardMenu },
+ { CP_Active, "\0", 'S', (menuptr)SS_SetupMusicCardMenu },
+ { CP_Active, "\0", 'S', (menuptr)SS_SetupMusicCardMenu },
+ { CP_Active, "\0", 'P', (menuptr)SS_SetupMusicCardMenu },
+ { CP_Active, "\0", 'A', (menuptr)SS_SetupMusicCardMenu },
+ { CP_Active, "\0", 'S', (menuptr)SS_SetupMusicCardMenu },
+ { CP_Active, "\0", 'W', (menuptr)SS_SetupMusicCardMenu },
+ { CP_Active, "\0", 'G', (menuptr)SS_SetupMusicCardMenu },
+ { CP_Active, "\0", 'S', (menuptr)SS_SetupMusicCardMenu },
+ { CP_Active, "\0", 'A', (menuptr)SS_SetupMusicCardMenu }
+};
+
+
+CP_MenuNames SoundSetupSoundNames[] =
+{
+ "None",
+ "Ultrasound",
+ "Sound Blaster",
+ "Sound Man 16",
+ "Pro Audio Spectrum",
+ "AWE 32",
+ "Soundscape",
+ "Adlib",
+ "Disney Sound Source",
+ "Tandy Sound Source",
+ "PC Speaker"
+};
+
+CP_iteminfo SoundSetupSoundItems = { MENU_X, MENU_Y + 15, 11, STARTITEM, 16, SoundSetupSoundNames, mn_smallfont };
+CP_itemtype SoundSetupSound[] =
+{
+ { CP_CursorLocation, "\0", 'N', (menuptr)SS_SetupSoundCardMenu },
+ { CP_Active, "\0", 'U', (menuptr)SS_SetupSoundCardMenu },
+ { CP_Active, "\0", 'S', (menuptr)SS_SetupSoundCardMenu },
+ { CP_Active, "\0", 'S', (menuptr)SS_SetupSoundCardMenu },
+ { CP_Active, "\0", 'P', (menuptr)SS_SetupSoundCardMenu },
+ { CP_Active, "\0", 'A', (menuptr)SS_SetupSoundCardMenu },
+ { CP_Active, "\0", 'S', (menuptr)SS_SetupSoundCardMenu },
+ { CP_Active, "\0", 'A', (menuptr)SS_SetupSoundCardMenu },
+ { CP_Active, "\0", 'S', (menuptr)SS_SetupSoundCardMenu },
+ { CP_Active, "\0", 'T', (menuptr)SS_SetupSoundCardMenu },
+ { CP_Active, "\0", 'P', (menuptr)SS_SetupSoundCardMenu }
+};
+
+CP_MenuNames SoundSetupMidiPortNames[] =
+{
+ "220", "230", "240", "250", "300", "320",
+ "330", "332", "334", "336", "340", "360"
+};
+
+CP_iteminfo SoundSetupMidiPortItems = { 108, MENU_Y + 10, 12, STARTITEM, 16, SoundSetupMidiPortNames, mn_smallfont };
+CP_itemtype SoundSetupMidiPort[] =
+{
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_CursorLocation, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL }
+};
+
+CP_MenuNames SoundSetupVoiceNames[] =
+{
+ "1 voice",
+ "2 voices",
+ "3 voices",
+ "4 voices",
+ "5 voices",
+ "6 voices",
+ "7 voices",
+ "8 voices"
+};
+
+CP_iteminfo SoundSetupVoiceItems = { MENU_X + 36, 24, 8, STARTITEM, 32, SoundSetupVoiceNames, mn_largefont };
+CP_itemtype SoundSetupVoice[] =
+{
+ { CP_CursorLocation, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL }
+};
+
+CP_MenuNames SoundSetupChannelNames[] =
+{
+ " Mono Sound FX",
+ "Stereo Sound FX"
+};
+
+CP_iteminfo SoundSetupChannelItems = { MENU_X, MP_Y, 2, STARTITEM, 32, SoundSetupChannelNames, mn_largefont };
+CP_itemtype SoundSetupChannel[] =
+{
+ { CP_CursorLocation, "\0", 'M', NULL },
+ { CP_Active, "\0", 'S', NULL }
+};
+
+CP_MenuNames SoundSetupResolutionNames[] =
+{
+ "8 Bit Mixing",
+ "16 Bit Mixing"
+};
+
+CP_iteminfo SoundSetupResolutionItems = { MENU_X, MP_Y, 2, STARTITEM, 32, SoundSetupResolutionNames, mn_largefont };
+CP_itemtype SoundSetupResolution[] =
+{
+ { CP_CursorLocation, "\0", 'a', NULL },
+ { CP_Active, "\0", 'b', NULL }
+};
+
+static int typenums[ 5 ] =
+{
+ fx_SB, fx_SB20, fx_SBPro, fx_SBPro2, fx_SB16
+};
+
+static char typetostring[ 6 ] =
+{
+ 5, 0, 2, 1, 3, 4
+};
+
+#define UNDEFINED -1
+
+CP_MenuNames TypeNames[] =
+{
+ "Sound Blaster or compatible",
+ "Sound Blaster 2.0",
+ "Sound Blaster Pro (old)",
+ "Sound Blaster Pro 2.0 (new)",
+ "Sound Blaster 16 or AWE32",
+ "Undefined"
+};
+
+CP_iteminfo TypeItems = { MENU_X - 13, MENU_Y + 36, 5, STARTITEM, 10, TypeNames, mn_smallfont };
+CP_itemtype TypeMenu[] =
+{
+ { CP_CursorLocation, "\0", 'S', NULL },
+ { CP_Active, "\0", 'S', NULL },
+ { CP_Active, "\0", 'S', NULL },
+ { CP_Active, "\0", 'S', NULL },
+ { CP_Active, "\0", 'S', NULL }
+};
+
+static int portnums[ 7 ] =
+{
+ 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x280
+};
+
+CP_MenuNames PortNames[] =
+{
+ "210", "220", "230", "240", "250", "260", "280"
+};
+
+CP_iteminfo PortItems = { 92, 32, 7, STARTITEM, 32, PortNames, mn_largefont };
+CP_itemtype PortMenu [] =
+{
+ { CP_CursorLocation, "\0", '2', NULL },
+ { CP_Active, "\0", '2', NULL },
+ { CP_Active, "\0", '2', NULL },
+ { CP_Active, "\0", '2', NULL },
+ { CP_Active, "\0", '2', NULL },
+ { CP_Active, "\0", '2', NULL },
+ { CP_Active, "\0", '2', NULL }
+};
+
+static int _8BitDMAnums[ 3 ] =
+{
+ 0, 1, 3
+};
+
+CP_MenuNames _8BitDMANames[] =
+{
+ "DMA channel 0",
+ "DMA channel 1",
+ "DMA channel 3"
+};
+
+CP_iteminfo _8BitDMAItems = { 32, 60, 3, STARTITEM, 32, _8BitDMANames, mn_largefont };
+CP_itemtype _8BitDMAMenu [] =
+{
+ { CP_CursorLocation, "\0", '0', NULL },
+ { CP_Active, "\0", '1', NULL },
+ { CP_Active, "\0", '3', NULL }
+};
+
+static int _16BitDMAnums[ 3 ] =
+{
+ 5, 6, 7
+};
+
+CP_MenuNames _16BitDMANames[] =
+{
+ "DMA channel 5",
+ "DMA channel 6",
+ "DMA channel 7"
+};
+
+CP_iteminfo _16BitDMAItems = { 32, 60, 3, STARTITEM, 32, _16BitDMANames, mn_largefont };
+CP_itemtype _16BitDMAMenu [] =
+{
+ { CP_CursorLocation, "\0", '5', NULL },
+ { CP_Active, "\0", '6', NULL },
+ { CP_Active, "\0", '7', NULL }
+};
+
+static int irqnums[ 8 ] =
+{
+ 2, 3, 5, 7, 10, 11, 12, 15
+};
+
+CP_MenuNames IrqNames[] =
+{
+ "IRQ 2",
+ "IRQ 3",
+ "IRQ 5",
+ "IRQ 7",
+ "IRQ 10",
+ "IRQ 11",
+ "IRQ 12",
+ "IRQ 15"
+};
+
+CP_iteminfo IrqItems = { 82, 24, 8, STARTITEM, 32, IrqNames, mn_largefont };
+CP_itemtype IrqMenu [] =
+{
+ { CP_CursorLocation, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL },
+ { CP_Active, "\0", 'a', NULL }
+};
+
+CP_MenuNames SBSetupNames[] =
+{
+ "Use Current Settings",
+ "Custom Setup"
+};
+
+CP_iteminfo SBSetupItems = { MENU_X - 11, MENU_Y + 76, 2, STARTITEM, 19, SBSetupNames, mn_largefont };
+CP_itemtype SBSetupMenu[] =
+{
+ { CP_CursorLocation, "\0", 'U', SS_SetupSoundBlaster },
+ { CP_Active, "\0", 'C', (menuptr)SS_SBTypeMenu },
+};
+
+extern fx_blaster_config SBSettings;
+
+//******************************************************************************
+//
+// SS_DrawSBSetupMenu()
+//
+//******************************************************************************
+
+void SS_DrawSBSetupMenu
+(
+ void
+)
+
+{
+ char text[ 80 ];
+ char num[ 10 ];
+ char *undefined;
+
+ MenuNum = SNDCARDS;
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle( "Sound Blaster Setup" );
+
+ WindowW = 288;
+ WindowH = 158;
+ WindowX = 96;
+ WindowY = 32;
+ PrintX = 0;
+ PrintY = 32;
+
+ CurrentFont = tinyfont;
+
+ undefined = "Undefined";
+
+ SBSetupMenu[ 0 ].active = CP_Active;
+
+ PrintBattleOption( true, WindowX + 16, PrintY, "Current Settings:" );
+ PrintY += 9;
+
+ strcpy( text, "Card Type : " );
+
+ if ( ( SBSettings.Type < fx_SB ) || ( SBSettings.Type > fx_SB16 ) )
+ {
+ SBSettings.Type = UNDEFINED;
+ strcat( text, undefined );
+ SBSetupMenu[ 0 ].active = CP_Inactive;
+ }
+ else
+ {
+ strcat( text, TypeNames[ (unsigned int)typetostring[ SBSettings.Type ] ] );
+ }
+
+ PrintBattleOption( true, WindowX, PrintY, text );
+ PrintY += 6;
+
+ strcpy( text, "Port : " );
+ if ( SBSettings.Address != (unsigned long)UNDEFINED )
+ {
+ itoa( SBSettings.Address, num, 16 );
+ strcat( text, num );
+ }
+ else
+ {
+ strcat( text, undefined );
+ SBSetupMenu[ 0 ].active = CP_Inactive;
+ }
+
+ PrintBattleOption( true, WindowX + 19, PrintY, text );
+ PrintY += 6;
+
+ strcpy( text, "IRQ : " );
+ if ( SBSettings.Interrupt != (unsigned long)UNDEFINED )
+ {
+ itoa( SBSettings.Interrupt, num, 10 );
+ strcat( text, num );
+ }
+ else
+ {
+ strcat( text, undefined );
+ SBSetupMenu[ 0 ].active = CP_Inactive;
+ }
+ PrintBattleOption( true, WindowX + 23, PrintY, text );
+ PrintY += 6;
+
+ strcpy( text, "DMA : " );
+ if ( SBSettings.Dma8 != (unsigned long)UNDEFINED )
+ {
+ itoa( SBSettings.Dma8, num, 10 );
+ strcat( text, num );
+ }
+ else
+ {
+ strcat( text, undefined );
+ SBSetupMenu[ 0 ].active = CP_Inactive;
+ }
+ PrintBattleOption( true, WindowX + 21, PrintY, text );
+ PrintY += 6;
+
+ strcpy( text, "16-Bit DMA : " );
+ if ( SBSettings.Dma16 != (unsigned long)UNDEFINED )
+ {
+ itoa( SBSettings.Dma16, num, 10 );
+ strcat( text, num );
+ }
+ else
+ {
+ strcat( text, undefined );
+ }
+ PrintBattleOption( true, WindowX - 4, PrintY, text );
+ PrintY += 6;
+
+ MN_GetCursorLocation( &SBSetupItems, &SBSetupMenu[ 0 ] );
+ DrawMenu( &SBSetupItems, &SBSetupMenu[ 0 ] );
+ DisplayInfo( 0 );
+
+ FlipMenuBuf();
+ RefreshMenuBuf( 0 );
+}
+
+
+//******************************************************************************
+//
+// SS_DrawSBTypeMenu()
+//
+//******************************************************************************
+
+void SS_DrawSBTypeMenu
+(
+ void
+)
+
+{
+ MenuNum = SNDCARDS;
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle( "Select Sound Blaster Type" );
+ MN_GetActive( &TypeItems, &TypeMenu[ 0 ], SBSettings.Type, typenums );
+ DrawMenu( &TypeItems, &TypeMenu[ 0 ] );
+ DisplayInfo( 0 );
+
+ FlipMenuBuf();
+}
+
+//******************************************************************************
+//
+// SS_SBTypeMenu()
+//
+//******************************************************************************
+
+void SS_SBTypeMenu
+(
+ void
+)
+
+{
+ int which;
+
+ do
+ {
+ SS_DrawSBTypeMenu();
+ which = HandleMenu( &TypeItems, &TypeMenu[0], NULL );
+ if ( which >= 0 )
+ {
+ SBSettings.Type = typenums[ which ];
+ SS_PortMenu();
+ if ( handlewhich == -1 )
+ {
+ continue;
+ }
+ return;
+ }
+ }
+ while( which >= 0 );
+
+ handlewhich = -2;
+}
+
+//******************************************************************************
+//
+// SS_DrawPortMenu()
+//
+//******************************************************************************
+
+void SS_DrawPortMenu
+(
+ void
+)
+
+{
+ MenuNum = SNDCARDS;
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle( "Select Sound Blaster Port" );
+ MN_GetActive( &PortItems, &PortMenu[ 0 ], SBSettings.Address, portnums );
+ DrawMenu( &PortItems, &PortMenu[ 0 ] );
+ DisplayInfo( 0 );
+
+ FlipMenuBuf();
+}
+
+//******************************************************************************
+//
+// SS_PortMenu()
+//
+//******************************************************************************
+
+void SS_PortMenu
+(
+ void
+)
+
+{
+ int which;
+
+ do
+ {
+ SS_DrawPortMenu();
+ which = HandleMenu( &PortItems, &PortMenu[0], NULL );
+ if ( which >= 0 )
+ {
+ SBSettings.Address = portnums[ which ];
+ SBSettings.Emu = SBSettings.Address;
+ SS_8BitDMAMenu();
+ if ( handlewhich == -1 )
+ {
+ continue;
+ }
+ return;
+ }
+ }
+ while( which >= 0 );
+
+ handlewhich = -1;
+}
+
+//******************************************************************************
+//
+// SS_Draw8BitDMAMenu()
+//
+//******************************************************************************
+
+void SS_Draw8BitDMAMenu
+(
+ void
+)
+
+{
+ MenuNum = SNDCARDS;
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle( "Select 8-bit DMA Channel" );
+ MN_GetActive( &_8BitDMAItems, &_8BitDMAMenu[ 0 ], SBSettings.Dma8, _8BitDMAnums );
+ DrawMenu( &_8BitDMAItems, &_8BitDMAMenu[ 0 ] );
+ DisplayInfo( 0 );
+
+ FlipMenuBuf();
+}
+
+//******************************************************************************
+//
+// SS_8BitDMAMenu()
+//
+//******************************************************************************
+
+void SS_8BitDMAMenu
+(
+ void
+)
+
+{
+ int which;
+
+ do
+ {
+ SS_Draw8BitDMAMenu();
+ which = HandleMenu( &_8BitDMAItems, &_8BitDMAMenu[0], NULL );
+ if ( which >= 0 )
+ {
+ SBSettings.Dma8 = _8BitDMAnums[ which ];
+ SS_16BitDMAMenu();
+ if ( handlewhich == -1 )
+ {
+ continue;
+ }
+ return;
+ }
+ }
+ while( which >= 0 );
+
+ handlewhich = -1;
+}
+
+//******************************************************************************
+//
+// SS_Draw16BitDMAMenu()
+//
+//******************************************************************************
+
+void SS_Draw16BitDMAMenu
+(
+ void
+)
+
+{
+ MenuNum = SNDCARDS;
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle( "Select 16-bit DMA Channel" );
+ MN_GetActive( &_16BitDMAItems, &_16BitDMAMenu[ 0 ], SBSettings.Dma16, _16BitDMAnums );
+ DrawMenu( &_16BitDMAItems, &_16BitDMAMenu[ 0 ] );
+ DisplayInfo( 0 );
+
+ FlipMenuBuf();
+}
+
+//******************************************************************************
+//
+// SS_16BitDMAMenu()
+//
+//******************************************************************************
+
+void SS_16BitDMAMenu
+(
+ void
+)
+
+{
+ int which;
+
+ if ( SBSettings.Type != fx_SB16 )
+ {
+ SS_IrqMenu();
+ return;
+ }
+
+ do
+ {
+ SS_Draw16BitDMAMenu();
+ which = HandleMenu( &_16BitDMAItems, &_16BitDMAMenu[0], NULL );
+ if ( which >= 0 )
+ {
+ SBSettings.Dma16 = _16BitDMAnums[ which ];
+ SS_IrqMenu();
+ if ( handlewhich == -1 )
+ {
+ continue;
+ }
+ return;
+ }
+ }
+ while( which >= 0 );
+
+ handlewhich = -1;
+}
+
+//******************************************************************************
+//
+// SS_DrawIrqMenu()
+//
+//******************************************************************************
+
+void SS_DrawIrqMenu
+(
+ void
+)
+
+{
+ MenuNum = SNDCARDS;
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle( "Select Sound Blaster IRQ" );
+ MN_GetActive( &IrqItems, &IrqMenu[ 0 ], SBSettings.Interrupt, irqnums );
+ DrawMenu( &IrqItems, &IrqMenu[ 0 ] );
+ DisplayInfo( 0 );
+
+ FlipMenuBuf();
+}
+
+//******************************************************************************
+//
+// SS_IrqMenu()
+//
+//******************************************************************************
+
+void SS_IrqMenu
+(
+ void
+)
+
+{
+ int which;
+
+ do
+ {
+ SS_DrawIrqMenu();
+ which = HandleMenu( &IrqItems, &IrqMenu[0], NULL );
+
+ if ( which >= 0 )
+ {
+ SBSettings.Interrupt = irqnums[ which ];
+ SS_SetupSoundBlaster( true );
+
+ if ( handlewhich == -1 )
+ {
+ continue;
+ }
+
+ return;
+ }
+ }
+ while( which >= 0 );
+
+ handlewhich = -1;
+}
+#endif
+
+
+//******************************************************************************
+//
+// GetNextWord()
+//
+//******************************************************************************
+char *GetNextWord
+(
+ char *dest,
+ char *source,
+ int length
+)
+
+{
+ while( ( *source != 0 ) && ( isspace( *source ) ) && ( length > 0 ) )
+ {
+ *dest = *source;
+ length--;
+ dest++;
+ source++;
+ }
+
+ while( ( *source != 0 ) && ( !isspace( *source ) ) && ( length > 0 ) )
+ {
+ *dest = *source;
+ length--;
+ dest++;
+ source++;
+ }
+
+ *dest = 0;
+ return( source );
+}
+
+//******************************************************************************
+//
+// CP_ErrorMsg()
+//
+//******************************************************************************
+
+void CP_ErrorMsg
+(
+ char *title,
+ char *error,
+ int font
+)
+
+{
+ char wordtext[ 80 ];
+ char text[ 10 ][ 80 ];
+ int pos;
+ int length;
+ int line;
+ int w;
+ int h;
+ int y;
+ extern void VWL_MeasureIntensityString (char *s, int *width, int *height, cfont_t *font);
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle( title );
+
+ WindowW = 288;
+ WindowH = 158;
+ WindowX = 0;
+ WindowY = 40;
+
+ IFont = ( cfont_t * )W_CacheLumpName( FontNames[ font ], PU_CACHE, Cvt_cfont_t, 1 );
+
+ pos = 0;
+ line = 0;
+
+ text[ 0 ][ 0 ] = 0;
+
+ while( *error != 0 )
+ {
+ error = GetNextWord( wordtext, error, 79 );
+
+ pos = 0;
+ while( ( wordtext[ pos ] != 0 ) && ( isspace( wordtext[ pos ] ) ) )
+ {
+ pos++;
+ }
+
+ length = strlen( text[ line ] );
+ if ( length == 0 )
+ {
+ strcat( text[ line ], &wordtext[ pos ] );
+ }
+ else
+ {
+ strcat( text[ line ], wordtext );
+ }
+
+ VWL_MeasureIntensityString( text[ line ], &w, &h, IFont );
+
+ if ( w > WindowW - 32 )
+ {
+ text[ line ][ length ] = 0;
+ if ( line >= 10 )
+ {
+ break;
+ }
+ line++;
+ strcpy( text[ line ], &wordtext[ pos ] );
+ }
+ }
+
+ if ( strlen( text[ line ] ) == 0 )
+ {
+ line--;
+ }
+
+ VWL_MeasureIntensityString( text[ 0 ], &w, &h, IFont );
+
+ y = ( WindowH - ( line + 1 ) * h ) / 2;
+
+ for( pos = 0; pos <= line; pos++ )
+ {
+ VWL_MeasureIntensityString( text[ pos ], &w, &h, IFont );
+ DrawMenuBufIString( ( 288 - w ) / 2, y, text[ pos ], ACTIVECOLOR );
+ y += h;
+ }
+
+ DisplayInfo( 5 );
+ FlipMenuBuf();
+ RefreshMenuBuf( 0 );
+
+ IN_Ack();
+ WaitKeyUp();
+
+ MN_PlayMenuSnd( SD_ESCPRESSEDSND );
+}
+
+#ifdef DOS
+
+//****************************************************************************
+//
+// DrawSoundSetupMainMenu ()
+//
+//****************************************************************************
+void DrawSoundSetupMainMenu
+(
+ void
+)
+
+{
+ MenuNum = 1;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle( "Sound Setup" );
+ if ( FXMode == 0 )
+ {
+ SoundSetupMenu[ 2 ].active = CP_Inactive;
+ }
+ else if ( SoundSetupMenu[ 2 ].active == CP_Inactive )
+ {
+ SoundSetupMenu[ 2 ].active = CP_Active;
+ }
+
+ if ( MusicMode == 0 )
+ {
+ SoundSetupMenu[ 3 ].active = CP_Inactive;
+ }
+ else if ( SoundSetupMenu[ 3 ].active == CP_Inactive )
+ {
+ SoundSetupMenu[ 3 ].active = CP_Active;
+ }
+
+ MN_GetCursorLocation( &SoundSetupMenuItems, &SoundSetupMenu[ 0 ] );
+ DrawMenu( &SoundSetupMenuItems, &SoundSetupMenu[ 0 ] );
+ DisplayInfo( 0 );
+
+ FlipMenuBuf();
+}
+
+
+//******************************************************************************
+//
+// Sound Setup Quit
+//
+//******************************************************************************
+
+void SS_Quit
+(
+ void
+)
+
+{
+ extern boolean WriteSoundFile;
+
+ CP_DisplayMsg( "Do you wish to\nsave your changes?\n"
+ "Press ESC to return\nto sound setup.", 12 );
+
+ if ( CP_Acknowledge != CP_ESC )
+ {
+ WriteSoundFile = true;
+ if ( CP_Acknowledge == CP_NO )
+ {
+ WriteSoundFile = false;
+ }
+
+ MU_FadeOut(310);
+ VL_FadeOut (0, 255, 0, 0, 0, 10);
+ ShutdownMenuBuf();
+ QuitGame ();
+ }
+
+ DrawSoundSetupMainMenu();
+}
+
+//******************************************************************************
+//
+// Sound Setup
+//
+//******************************************************************************
+
+void CP_SoundSetup ( void )
+{
+ int which;
+ extern boolean WriteSoundFile;
+
+ WriteSoundFile = false;
+
+ SetupMenuBuf();
+ DrawSoundSetupMainMenu();
+ IN_ClearKeysDown();
+
+ if ( MusicMode != 0 )
+ {
+ MU_StartSong( song_title );
+ }
+
+ while( 1 )
+ {
+ which = HandleMenu( &SoundSetupMenuItems, SoundSetupMenu, NULL );
+ if ( which == -1 )
+ {
+ SS_Quit();
+ }
+ }
+}
+
+//******************************************************************************
+//
+// SS_MusicMenu ()
+//
+//******************************************************************************
+
+void SS_MusicMenu
+(
+ void
+)
+
+{
+ int which;
+
+ MN_MakeActive( &SoundSetupMusicItems, &SoundSetupMusic[ 0 ], MusicMode );
+
+ SS_DrawMusicMenu ();
+ IN_ClearKeysDown();
+
+ do
+ {
+ which = HandleMenu( &SoundSetupMusicItems, &SoundSetupMusic[ 0 ], NULL );
+ }
+ while( which > 0 );
+
+ DrawSoundSetupMainMenu();
+ handlewhich = RETURNVAL;
+}
+
+
+//******************************************************************************
+//
+// SS_DrawMusicMenu ()
+//
+//******************************************************************************
+
+void SS_DrawMusicMenu
+(
+ void
+)
+
+{
+ MenuNum = SNDCARDS;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle( "Select Music Card" );
+
+ MN_GetCursorLocation( &SoundSetupMusicItems, &SoundSetupMusic[ 0 ] );
+ DrawMenu( &SoundSetupMusicItems, &SoundSetupMusic[ 0 ] );
+ DisplayInfo( 0 );
+
+ FlipMenuBuf();
+}
+
+
+//******************************************************************************
+//
+// SS_SetupMusicCardMenu()
+//
+//******************************************************************************
+
+void SS_SetupMusicCardMenu
+(
+ void
+)
+
+{
+ int status;
+ int select;
+ if ( ( ( musicnums[ handlewhich ] == SoundBlaster ) ||
+ ( musicnums[ handlewhich ] == WaveBlaster ) ||
+ ( musicnums[ handlewhich ] == Awe32 ) ) &&
+ ( fxnums[ FXMode ] != SoundBlaster ) &&
+ ( fxnums[ FXMode ] != Awe32 ) )
+ {
+ CP_ErrorMsg( "Music Error",
+ "Please set your Sound FX card to Sound Blaster before "
+ "selecting this card for music.", mn_smallfont );
+
+ handlewhich = -1;
+ return;
+ }
+
+ MusicMode = handlewhich;
+
+ MU_Shutdown();
+
+ if ( ( musicnums[ MusicMode ] == GenMidi ) ||
+ ( musicnums[ MusicMode ] == SoundCanvas ) ||
+ ( musicnums[ MusicMode ] == WaveBlaster ) ||
+ ( musicnums[ MusicMode ] == Awe32 ) )
+ {
+ DrawMusicCardMenu();
+
+ IN_ClearKeysDown ();
+
+ select = HandleMenu( &SoundSetupMidiPortItems,
+ &SoundSetupMidiPort[0], NULL );
+
+ if ( select > -1 )
+ {
+ MidiAddress = midinums[ select ];
+ }
+ else
+ {
+ SS_DrawMusicMenu ();
+ handlewhich = RETURNVAL;
+ MusicMode = 0;
+ return;
+ }
+ }
+
+ if ( MusicMode != 0 )
+ {
+ if ( ( musicnums[ handlewhich ] == WaveBlaster ) ||
+ ( musicnums[ handlewhich ] == Awe32 ) )
+ {
+ SD_Shutdown();
+ }
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle( "Music Card Initialization" );
+ WindowW = 288;
+ WindowH = 158;
+ PrintX = WindowX = 0;
+ PrintY = WindowY = 65;
+ newfont1 = (font_t *)W_CacheLumpName( "newfnt1", PU_CACHE, Cvt_font_t, 1 );
+ CurrentFont = newfont1;
+ MenuBufCPrint( "Initializing card.\nPlease wait." );
+ FlipMenuBuf();
+ RefreshMenuBuf( 0 );
+
+ status = MU_Startup( false );
+ if ( status )
+ {
+ MusicMode = 0;
+
+ CP_ErrorMsg( "Music Error", MUSIC_ErrorString( MUSIC_Error ),
+ mn_smallfont );
+ SS_DrawMusicMenu ();
+ handlewhich = RETURNVAL;
+ }
+ else
+ {
+ handlewhich = -1;
+ MU_StartSong( song_title );
+ }
+
+ if ( ( musicnums[ MusicMode ] == WaveBlaster ) ||
+ ( musicnums[ MusicMode ] == Awe32 ) )
+ {
+ status = SD_Startup( false );
+ if ( status != FX_Ok )
+ {
+ CP_ErrorMsg( "Sound FX Error", FX_ErrorString( FX_Error ),
+ mn_smallfont );
+
+ handlewhich = -2;
+ }
+ }
+ }
+ else
+ {
+ handlewhich = -1;
+ MU_Shutdown();
+ }
+}
+
+
+//******************************************************************************
+//
+// DrawMusicCardMenu()
+//
+//******************************************************************************
+
+void DrawMusicCardMenu
+(
+ void
+)
+
+{
+ MenuNum = SNDCARDS;
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle( "Select MIDI Port Address" );
+ MN_GetActive( &SoundSetupMidiPortItems, &SoundSetupMidiPort[ 0 ],
+ MidiAddress, midinums );
+ DrawMenu( &SoundSetupMidiPortItems, &SoundSetupMidiPort[ 0 ] );
+ DisplayInfo( 0 );
+
+ FlipMenuBuf();
+}
+
+//******************************************************************************
+//
+// SS_SoundMenu ()
+//
+//******************************************************************************
+
+void SS_SoundMenu
+(
+ void
+)
+
+{
+ int which;
+
+ MN_MakeActive( &SoundSetupSoundItems, &SoundSetupSound[0], FXMode );
+
+ SS_DrawSoundMenu ();
+ IN_ClearKeysDown();
+
+ do {
+ which = HandleMenu( &SoundSetupSoundItems, &SoundSetupSound[ 0 ], NULL );
+ }
+ while( which >= 0 );
+
+ DrawSoundSetupMainMenu();
+ handlewhich = RETURNVAL;
+}
+
+
+//******************************************************************************
+//
+// SS_DrawSoundMenu ()
+//
+//******************************************************************************
+
+void SS_DrawSoundMenu
+(
+ void
+)
+
+{
+ MenuNum = SNDCARDS;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Select Sound FX Card");
+
+ MN_GetCursorLocation( &SoundSetupSoundItems, &SoundSetupSound[0] );
+
+ DrawMenu( &SoundSetupSoundItems, &SoundSetupSound[ 0 ] );
+ DisplayInfo( 0 );
+
+ FlipMenuBuf();
+}
+
+
+//******************************************************************************
+//
+// SS_SetupSoundBlaster()
+//
+//******************************************************************************
+
+void SS_SetupSoundBlaster
+(
+ int sbmenu
+)
+
+{
+ int status;
+
+ status = FX_SetupSoundBlaster( SBSettings, &MaxVoices,
+ &MaxBits, &MaxChannels );
+
+ if ( status == FX_Ok )
+ {
+ SS_VoiceMenu( sbmenu );
+
+ if ( handlewhich < 0 )
+ {
+ return;
+ }
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle( "Sound Card Initialization" );
+ WindowW = 288;
+ WindowH = 158;
+ PrintX = WindowX = 0;
+ PrintY = WindowY = 65;
+ newfont1 = (font_t *)W_CacheLumpName( "newfnt1", PU_CACHE, Cvt_font_t, 1 );
+ CurrentFont = newfont1;
+ MenuBufCPrint( "Initializing card.\nPlease wait." );
+ FlipMenuBuf();
+ RefreshMenuBuf( 0 );
+
+ status = SD_Startup( false );
+
+ RefreshMenuBuf( 0 );
+ }
+
+ if ( status != FX_Ok )
+ {
+ CP_ErrorMsg( "Sound FX Error", FX_ErrorString( FX_Error ),
+ mn_smallfont );
+
+ handlewhich = -2;
+ }
+}
+
+
+//******************************************************************************
+//
+// SS_SetupSoundCardMenu()
+//
+//******************************************************************************
+
+void SS_SetupSoundCardMenu
+(
+ void
+)
+
+{
+ int which;
+ int FXstatus;
+ extern int fxnums[];
+
+ INFXSETUP = true;
+
+ FXMode = handlewhich;
+
+ SD_Shutdown();
+
+ if ( FXMode == 0 )
+ {
+ handlewhich = -1;
+ }
+ else
+ {
+ if ( ( fxnums[ FXMode ] == SoundBlaster ) ||
+ ( fxnums[ FXMode ] == Awe32 ) )
+ {
+ do
+ {
+ SS_DrawSBSetupMenu();
+ which = HandleMenu( &SBSetupItems, &SBSetupMenu[ 0 ], NULL );
+ }
+ while( which == -2 );
+
+ if ( which == -1 )
+ {
+ FXMode = 0;
+ handlewhich = 0;
+ SS_DrawSoundMenu();
+ }
+ else
+ {
+ handlewhich = -1;
+ }
+
+ INFXSETUP = false;
+ return;
+ }
+
+ FXstatus = SD_SetupFXCard( &MaxVoices, &MaxBits, &MaxChannels );
+ if ( FXstatus == FX_Ok )
+ {
+ SS_VoiceMenu( true );
+
+ if ( handlewhich == -1 )
+ {
+ SS_DrawSoundMenu ();
+ handlewhich = RETURNVAL;
+ FXMode = 0;
+ SD_Shutdown ();
+ INFXSETUP = false;
+ return;
+ }
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle( "Sound Card Initialization" );
+ WindowW = 288;
+ WindowH = 158;
+ PrintX = WindowX = 0;
+ PrintY = WindowY = 65;
+ newfont1 = (font_t *)W_CacheLumpName( "newfnt1", PU_CACHE, Cvt_font_t, 1 );
+ CurrentFont = newfont1;
+ MenuBufCPrint( "Initializing card.\nPlease wait." );
+ FlipMenuBuf();
+ RefreshMenuBuf( 0 );
+
+ FXstatus = SD_Startup( false );
+
+ RefreshMenuBuf( 0 );
+ }
+
+ if ( FXstatus != FX_Ok )
+ {
+ FXMode = 0;
+ handlewhich = RETURNVAL;
+
+ CP_ErrorMsg( "Sound FX Error", FX_ErrorString( FX_Error ),
+ mn_smallfont );
+ SS_DrawSoundMenu();
+ }
+ else
+ {
+ handlewhich = -1;
+ }
+ }
+
+ INFXSETUP = false;
+}
+
+
+//******************************************************************************
+//
+// SS_VoiceMenu ()
+//
+//******************************************************************************
+
+void SS_VoiceMenu
+(
+ int sbmenu
+)
+
+{
+ int which;
+
+ if ( MaxVoices < 2 )
+ {
+ NumVoices = 1;
+ SS_ChannelMenu();
+ return;
+ }
+
+ do
+ {
+ SS_DrawVoiceMenu ();
+
+ which = HandleMenu( &SoundSetupVoiceItems, &SoundSetupVoice[0],
+ NULL );
+ if ( which >= 0 )
+ {
+ NumVoices = voicenums[ which ];
+ SS_ChannelMenu();
+ if ( handlewhich == -1 )
+ {
+ continue;
+ }
+ return;
+ }
+ }
+ while( which >= 0 );
+
+ if ( sbmenu )
+ {
+ handlewhich = -1;
+ }
+ else
+ {
+ handlewhich = -2;
+ }
+}
+
+//******************************************************************************
+//
+// SS_DrawVoiceMenu()
+//
+//******************************************************************************
+
+void SS_DrawVoiceMenu
+(
+ void
+)
+
+{
+ MenuNum = SNDCARDS;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Number of Voices");
+
+ MN_GetActive( &SoundSetupVoiceItems, &SoundSetupVoice[0],
+ NumVoices, voicenums );
+
+ DrawMenu( &SoundSetupVoiceItems, &SoundSetupVoice[ 0 ] );
+ DisplayInfo( 0 );
+
+ FlipMenuBuf();
+}
+
+//******************************************************************************
+//
+// SS_ChannelMenu ()
+//
+//******************************************************************************
+
+void SS_ChannelMenu
+(
+ void
+)
+
+{
+ int which;
+
+ if ( MaxChannels < 2 )
+ {
+ NumChannels = 1;
+ SS_BitMenu();
+ return;
+ }
+
+ do
+ {
+ SS_DrawChannelMenu ();
+ which = HandleMenu( &SoundSetupChannelItems, &SoundSetupChannel[0],
+ NULL );
+ if ( which >= 0 )
+ {
+ NumChannels = smnums[ which ];
+ SS_BitMenu();
+ if ( handlewhich == -1 )
+ {
+ continue;
+ }
+ return;
+ }
+ }
+ while( which >= 0 );
+
+ handlewhich = -1;
+}
+
+//******************************************************************************
+//
+// SS_DrawChannelMenu()
+//
+//******************************************************************************
+
+void SS_DrawChannelMenu
+(
+ void
+)
+
+{
+ MenuNum = SNDCARDS;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Number of Channels");
+
+ MN_GetActive( &SoundSetupChannelItems, &SoundSetupChannel[0],
+ NumChannels, smnums );
+
+ DrawMenu( &SoundSetupChannelItems, &SoundSetupChannel[ 0 ] );
+ DisplayInfo( 0 );
+
+ FlipMenuBuf();
+}
+
+//******************************************************************************
+//
+// SS_BitMenu ()
+//
+//******************************************************************************
+
+void SS_BitMenu
+(
+ void
+)
+
+{
+ int which;
+
+ if ( MaxBits < 16 )
+ {
+ NumBits = 8;
+ return;
+ }
+
+ SS_DrawBitMenu ();
+
+ which = HandleMenu( &SoundSetupResolutionItems,
+ &SoundSetupResolution[0], NULL );
+
+ if ( which >= 0 )
+ {
+ NumBits = resnums[ which ];
+ return;
+ }
+
+ handlewhich = -1;
+}
+
+
+//******************************************************************************
+//
+// SS_DrawBitMenu()
+//
+//******************************************************************************
+
+void SS_DrawBitMenu
+(
+ void
+)
+
+{
+ MenuNum = SNDCARDS;
+
+ SetAlternateMenuBuf();
+ ClearMenuBuf();
+ SetMenuTitle ("Playback Resolution");
+
+ MN_GetActive( &SoundSetupResolutionItems, &SoundSetupResolution[0],
+ NumBits, resnums );
+
+ DrawMenu( &SoundSetupResolutionItems, &SoundSetupResolution[ 0 ] );
+ DisplayInfo( 0 );
+
+ FlipMenuBuf();
+}
+#endif
--- /dev/null
+++ b/rott/rt_menu.h
@@ -1,0 +1,217 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_menu_public
+#define _rt_menu_public
+
+//******************************************************************************
+//
+// Public header for RT_MENU.C.
+//
+//******************************************************************************
+
+#include "lumpy.h"
+#include "rt_in.h"
+
+#define MaxX 320
+#define MaxY 200
+#define MaxString 128
+
+#define SaveGamePicX 18
+#define SaveGamePicY 18
+
+//******************************************************************************
+//
+// TYPEDEFS
+//
+//******************************************************************************
+
+typedef enum
+{
+ mn_tinyfont,
+ mn_8x8font,
+ mn_smallfont,
+ mn_largefont
+} mn_fontsize;
+
+typedef char CP_MenuNames[64];
+
+typedef struct
+{
+ int x;
+ int y;
+ int amount;
+ int curpos;
+ int indent;
+ CP_MenuNames *names;
+ mn_fontsize fontsize;
+} CP_iteminfo;
+
+
+//MED
+typedef void (*menuptr)(int);
+
+typedef struct
+{
+ int active;
+ char texture[9];
+ char letter;
+ void (* routine)(int temp1);
+} CP_itemtype;
+
+enum
+{
+ CP_Inactive,
+ CP_Active,
+ CP_CursorLocation,
+ CP_Active3
+};
+
+//******************************************************************************
+//
+// GLOBALS
+//
+//******************************************************************************
+
+extern char*colorname[];
+extern boolean NewGame;
+
+extern CP_itemtype MainMenu[];
+extern boolean pickquick;
+
+extern cfont_t *IFont;
+extern font_t *CurrentFont;
+extern font_t *tinyfont;
+
+//
+// Global window coords
+//
+extern int PrintX;
+extern int PrintY;
+extern int WindowX;
+extern int WindowY;
+extern int WindowH;
+extern int WindowW;
+
+extern int px;
+extern int py;
+extern int bufferheight;
+extern int bufferwidth;
+extern boolean loadedgame;
+extern int FXMode;
+extern int MusicMode;
+
+extern font_t *newfont1;
+extern font_t *smallfont;
+extern font_t *bigfont;
+
+
+extern boolean AutoDetailOn;
+extern boolean DoubleClickOn;
+extern boolean BobbinOn;
+extern int Menuflipspeed;
+extern int DetailLevel;
+
+extern boolean ingame;
+extern boolean inmenu;
+extern int scancode;
+
+extern int quicksaveslot;
+
+//****************************************************************************
+//
+// TYPEDEFS
+//
+//****************************************************************************
+typedef enum
+{
+ newgame,
+ battlemode,
+ loadgame,
+ savegame,
+ control,
+ orderinfo,
+ viewscores,
+ backtodemo,
+ quit
+} menuitems;
+
+
+
+//****************************************************************************
+//
+// PROTOTYPES
+//
+//****************************************************************************
+
+int CP_ColorSelection(void);
+void CP_BattleMode(void);
+void DisplayInfo (int which);
+boolean CP_DisplayMsg (char *s, int number);
+void Message (char *string);
+void DrawMenu (CP_iteminfo *item_i, CP_itemtype *items);
+void DrawMainMenu(void);
+void AllocateSavedScreenPtr (void);
+void FreeSavedScreenPtr (void);
+void CleanUpControlPanel (void);
+void SetUpControlPanel (void);
+void ControlPanel (byte scancode);
+menuitems CP_MainMenu( void );
+int getASCII ( void );
+void DoMainMenu (void);
+boolean CP_CheckQuick (byte scancode);
+void AdjustMenuStruct (void);
+void MenuFixup (void);
+void GetEpisode (int level);
+void MN_PlayMenuSnd (int which);
+void CP_ViewScores (void);
+void ReadAnyControl (ControlInfo *ci);
+void WaitKeyUp (void);
+
+void GetMenuInfo (void);
+void WriteMenuInfo (void);
+int GetNumActive (CP_iteminfo *item_i, CP_itemtype *items);
+int MN_GetActive (CP_iteminfo *item_i, CP_itemtype *items, int check, int *nums);
+void MN_MakeActive (CP_iteminfo *item_i, CP_itemtype *items, int which);
+void MN_PlayMenuSnd (int which);
+
+int CP_LoadGame (int quick, int dieload);
+
+int CP_PlayerSelection (void);
+void BattleGamePlayerSetup( void );
+void BattleNoTeams( void );
+void BattleTeams( void );
+void CP_BattleMenu (void);
+void CP_BattleModes (void);
+void CP_ModemGameMessage ( int player );
+void ShowBattleOptions( boolean inmenu, int PosX, int PosY );
+void SetMenuHeader( char *header );
+int HandleMultiPageCustomMenu( char **names, int amount, int curpos, char *title, void ( *routine )( int w ), void ( *redrawfunc )( void ), boolean exitonselect );
+int CP_LevelSelectionMenu ( void );
+int CP_EnterCodeNameMenu ( void );
+#ifdef DOS
+void CP_SoundSetup( void );
+#endif
+void QuickSaveGame (void);
+void UndoQuickSaveGame (void);
+void CP_CaptureTheTriadError( void );
+void CP_TeamPlayErrorMessage( void );
+void CP_ExtGameOptionsMenu( void );
+
+#endif
--- /dev/null
+++ b/rott/rt_msg.c
@@ -1,0 +1,812 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "rt_def.h"
+#include "rt_view.h"
+#include "z_zone.h"
+#include "w_wad.h"
+#include "lumpy.h"
+#include "rt_util.h"
+#include "rt_vid.h"
+#include "rt_str.h"
+#include "rt_menu.h"
+#include "_rt_msg.h"
+#include "rt_msg.h"
+#include "rt_playr.h"
+#include "isr.h"
+#include "rt_main.h"
+#include "rt_net.h"
+#include "rt_com.h"
+
+#ifdef DOS
+#include <mem.h>
+#endif
+
+#include <stdlib.h>
+//MED
+#include "memcheck.h"
+
+
+/*
+=============================================================================
+
+ GLOBALS
+
+=============================================================================
+*/
+messagetype Messages[MAXMSGS];
+
+/*
+=============================================================================
+
+ LOCAL
+
+=============================================================================
+*/
+
+static int UpdateMessageBackground;
+static int MessageSystemStarted=0;
+static int LastMessageTime;
+static boolean EraseMessage[ MAXMSGS ];
+static int MessageOrder[ MAXMSGS ];
+static int TotalMessages = 0;
+static int MsgPos = 0;
+
+boolean MessagesEnabled = true;
+
+int StringLength (char *string)
+{
+ int length=0;
+
+ while ((*string)!=0)
+ {
+ length++;
+ string++;
+ }
+
+ length++;
+
+ return length;
+}
+
+/*
+====================
+=
+= ResetMessageTime
+=
+====================
+*/
+
+void ResetMessageTime ( void )
+{
+ LastMessageTime=GetTicCount();
+}
+
+/*
+====================
+=
+= InitializeMessages
+=
+====================
+*/
+void InitializeMessages
+(
+ void
+)
+
+{
+ int i;
+ boolean start;
+
+ start = false;
+
+ if ( MessageSystemStarted == 0 )
+ {
+ start = true;
+ MessageSystemStarted = 1;
+ memset( Messages, 0, sizeof( Messages ) );
+ }
+
+ for ( i = 0; i < MAXMSGS; i++ )
+ {
+ if ( Messages[ i ].active == 1 )
+ {
+ SafeFree( Messages[ i ].text );
+ Messages[ i ].active = 0;
+ Messages[ i ].tictime = 0;
+ Messages[ i ].flags = 0;
+ Messages[ i ].text = NULL;
+ }
+ }
+
+ MSG.messageon = false;
+
+ LastMessageTime = 0;
+ UpdateMessageBackground = 0;
+ TotalMessages = 0;
+ memset( EraseMessage, 0, sizeof( EraseMessage ) );
+ memset( MessageOrder, -1, sizeof( MessageOrder ) );
+
+ // Only print startup message if it's the first time in
+ if ( start && !quiet )
+ {
+ printf( "RT_MSG: Message System Started\n" );
+ }
+}
+
+
+/*
+====================
+=
+= GetMessageOrder
+=
+====================
+*/
+void GetMessageOrder
+(
+ void
+)
+
+{
+ int i;
+ int lowest;
+ int lowesttime;
+ byte done[ MAXMSGS ];
+ boolean found;
+
+ memset( &done[ 0 ], 0, sizeof( done ) );
+ memset( MessageOrder, -1, sizeof( MessageOrder ) );
+
+ for( TotalMessages = 0; TotalMessages < MAXMSGS; TotalMessages++ )
+ {
+ found = false;
+ lowesttime = 1000;
+ lowest = 0;
+
+ for( i = 0; i < MAXMSGS; i++ )
+ {
+ if ( ( Messages[ i ].active == 1 ) && ( done[ i ] == 0 ) &&
+ ( Messages[ i ].tictime < lowesttime ) )
+ {
+ lowesttime = Messages[ i ].tictime;
+ lowest = i;
+ found = true;
+ }
+ }
+
+ if ( !found )
+ {
+ break;
+ }
+
+ done[ lowest ] = 1;
+ MessageOrder[ TotalMessages ] = lowest;
+ }
+}
+
+
+/*
+====================
+=
+= DeleteMessage
+=
+====================
+*/
+void DeleteMessage
+(
+ int num
+)
+
+{
+ int i;
+ int msg;
+ boolean found;
+
+ found = false;
+ for( i = 0; i < TotalMessages; i++ )
+ {
+ msg = MessageOrder[ i ];
+
+ if ( msg == num )
+ {
+ found = true;
+ }
+
+ if ( found )
+ {
+ UpdateMessageBackground -= EraseMessage[ i ];
+ UpdateMessageBackground += 3;
+ EraseMessage[ i ] = 3;
+ }
+ }
+
+ SafeFree( Messages[ num ].text );
+ memset( &Messages[ num ], 0, sizeof( messagetype ) );
+
+ GetMessageOrder();
+}
+
+
+/*
+====================
+=
+= DeletePriorityMessage
+=
+====================
+*/
+void DeletePriorityMessage ( int flags )
+{
+ int i;
+
+ for (i=0; i<MAXMSGS; i++)
+ {
+ if (Messages[i].active==1)
+ {
+ if (Messages[i].flags==flags)
+ DeleteMessage(i);
+ }
+ }
+}
+
+
+/*
+====================
+=
+= GetFreeMessage
+=
+====================
+*/
+int GetFreeMessage
+(
+ void
+)
+
+{
+ int i;
+ int found;
+
+ for( i = 0; i < MAXMSGS; i++ )
+ {
+ if ( Messages[ i ].active == 0 )
+ {
+ return( i );
+ }
+ }
+
+ found = -1;
+
+ for( i = 0; i < MAXMSGS; i++ )
+ {
+ if ( Messages[ i ].tictime >= 0 )
+ {
+ if ( found == -1 )
+ {
+ found = i;
+ }
+ else
+ {
+ if ( Messages[ i ].tictime < Messages[ found ].tictime )
+ {
+ found = i;
+ }
+ }
+ }
+ }
+
+ DeleteMessage( found );
+
+ return( found );
+}
+
+
+/*
+====================
+=
+= SetMessage
+=
+====================
+*/
+void SetMessage
+(
+ int num,
+ char *text,
+ int flags
+)
+
+{
+ int i;
+ int msg;
+ int length;
+ boolean found;
+
+ if (iGLOBAL_SCREENWIDTH >= 640) {
+ CurrentFont = newfont1;//smallfont;
+ } else {
+ CurrentFont = smallfont;
+ }
+
+
+ length = StringLength( text );
+
+ Messages[ num ].active = 1;
+ Messages[ num ].flags = flags;
+
+ if ( PERMANENT_MSG( flags ) )
+ {
+ int l;
+
+ l = COM_MAXTEXTSTRINGLENGTH + 1;
+ Messages[ num ].text = SafeMalloc( l );
+ memset( Messages[ num ].text, 0, l );
+
+ // Hack so that we can place menu in certain order
+ Messages[ num ].tictime = -100 + MsgPos;
+ }
+ else
+ {
+ Messages[ num ].text = SafeMalloc( length );
+
+ memset( Messages[ num ].text, 0, length );
+ Messages[ num ].tictime = MESSAGETIME;
+ }
+
+ memcpy( Messages[ num ].text, text, length );
+
+ GetMessageOrder();
+ found = false;
+ for( i = 0; i < TotalMessages; i++ )
+ {
+ msg = MessageOrder[ i ];
+ if ( msg == num )
+ {
+ found = true;
+ }
+ else if ( found )
+ {
+ UpdateMessageBackground -= EraseMessage[ i - 1 ];
+ UpdateMessageBackground += 3;
+ EraseMessage[ i - 1 ] = 3;
+ }
+ }
+}
+
+
+/*
+====================
+=
+= AddMessage
+=
+====================
+*/
+int AddMessage
+(
+ char *text,
+ int flags
+)
+
+{
+ int new;
+
+ if ( MessageSystemStarted == 0 )
+ {
+ Error( "Called AddMessage without starting Message system\n" );
+ }
+
+ if ( !( flags & MSG_NODELETE ) )
+ {
+ DeletePriorityMessage( flags );
+ }
+
+ new = GetFreeMessage();
+ SetMessage( new, text, flags );
+
+ return( new );
+}
+
+/*
+====================
+=
+= UpdateMessages
+=
+====================
+*/
+void UpdateMessages
+(
+ void
+)
+
+{
+ int messagetics;
+ int i;
+
+ messagetics = GetTicCount() - LastMessageTime;
+ LastMessageTime = GetTicCount();
+
+ if ( GamePaused == true )
+ {
+ return;
+ }
+
+ for( i = 0; i < MAXMSGS; i++ )
+ {
+ if ( ( Messages[ i ].active == 1 ) &&
+ ( !PERMANENT_MSG( Messages[ i ].flags ) ) )
+ {
+ Messages[ i ].tictime -= messagetics;
+ if ( Messages[ i ].tictime <= 0 )
+ {
+ DeleteMessage( i );
+ }
+ }
+ }
+}
+
+
+/*
+====================
+=
+= DisplayMessage
+=
+====================
+*/
+
+void DisplayMessage (int num,int position)
+{
+ PrintX = 1;
+ if (iGLOBAL_SCREENWIDTH > 320) {
+ PrintY = 2 + ( position * (9*2) );
+ } else {
+ PrintY = 2 + ( position * (9*1) );
+ }
+
+
+ if ( SHOW_TOP_STATUS_BAR() )
+ {
+ PrintY += 16;
+ }
+ if ( !MessagesEnabled )
+ {
+ switch ( Messages[ num ].flags )
+ {
+ case MSG_QUIT:
+ case MSG_MACRO:
+ case MSG_MODEM:
+ case MSG_NAMEMENU:
+ case MSG_MSGSYSTEM:
+ break;
+
+ case MSG_REMOTERIDICULE:
+ case MSG_REMOTE:
+ case MSG_GAME:
+ case MSG_DOOR:
+ case MSG_BONUS:
+ case MSG_BONUS1:
+ case MSG_CHEAT:
+ case MSG_SYSTEM:
+ default :
+ DeleteMessage( num );
+ return;
+ }
+ }
+
+ switch ( Messages[ num ].flags )
+ {
+ case MSG_REMOTERIDICULE:
+ case MSG_REMOTE:
+ fontcolor = egacolor[ WHITE ];
+ break;
+
+ case MSG_MODEM:
+ fontcolor = egacolor[ LIGHTBLUE ];
+ DrawIString( PrintX, PrintY, "Message>", Messages[ num ].flags );
+ if ( iGLOBAL_SCREENWIDTH == 320) {
+ PrintX += 8 * 8;
+ } else if ( iGLOBAL_SCREENWIDTH == 640) {
+ PrintX += 8 * 8*2;
+ } else if ( iGLOBAL_SCREENWIDTH == 800) {
+ PrintX += 8 * 8*2;
+ }
+
+ fontcolor = egacolor[ LIGHTGRAY ];
+ break;
+
+ case MSG_GAME:
+ case MSG_DOOR:
+ case MSG_BONUS:
+ case MSG_BONUS1:
+ case MSG_NAMEMENU:
+ fontcolor = egacolor[ GREEN ];
+ break;
+
+ case MSG_CHEAT:
+ fontcolor = egacolor[ YELLOW ];
+ break;
+ case MSG_MSGSYSTEM:
+ case MSG_SYSTEM:
+ case MSG_QUIT:
+ case MSG_MACRO:
+ fontcolor = egacolor[ RED ];
+ break;
+
+ default :
+#if ((DEVELOPMENT == 1))
+ Error( "DisplayMessage called with invalid priority number." );
+#else
+ fontcolor = egacolor[ LIGHTGREEN ];
+#endif
+ }
+
+ DrawIString( PrintX, PrintY, Messages[ num ].text, Messages[ num ].flags );
+}
+
+
+
+/*
+====================
+=
+= RestoreMessageBackground
+=
+====================
+*/
+void RestoreMessageBackground
+(
+ void
+)
+
+{
+ pic_t *shape;
+ int i;
+ int y;
+
+ if ( UpdateMessageBackground > 0 )
+ {
+ y = 18;
+ for( i = 0; i < MAXMSGS; i++ )
+ {
+ if ( EraseMessage[ i ] )
+ {
+ UpdateMessageBackground--;
+ EraseMessage[ i ]--;
+ if ( viewsize < 15 )
+ {
+ shape = ( pic_t * )W_CacheLumpName( "backtile", PU_CACHE, Cvt_pic_t, 1 );//w=32 h=8
+ //SetTextMode ( );
+ //DrawTiledRegion( 0, y, 320, 9, 0, y, shape );KILLS_HEIGHT bna--
+ DrawTiledRegion( 0, y, iGLOBAL_SCREENWIDTH, 9, 0, y, shape );
+ DrawTiledRegion( 0, y+8, iGLOBAL_SCREENWIDTH, 9, 0, y, shape );
+ DrawTiledRegion( 0, y+16, iGLOBAL_SCREENWIDTH, 9, 0, y, shape );
+
+ //DrawTiledRegion( 0, y, iGLOBAL_SCREENWIDTH, 212, 0, y, shape );
+ }
+ if ( viewsize == 0 )
+ {
+ if ( ( y + 9 > YOURCPUSUCKS_Y ) &&
+ ( y < ( YOURCPUSUCKS_Y + YOURCPUSUCKS_HEIGHT ) ) )
+ {
+ DrawCPUJape();
+ }
+ }
+ }
+
+ y += 9;
+ }
+ }
+}
+
+
+/*
+====================
+=
+= DrawMessages
+=
+====================
+*/
+void DrawMessages
+(
+ void
+)
+
+{
+ int i;
+
+ if ( TotalMessages > 0 )
+ {
+ IFont = ( cfont_t * )W_CacheLumpName( "ifnt", PU_CACHE, Cvt_cfont_t, 1 );
+
+ for( i = 0; i < TotalMessages; i++ )
+ {
+ DisplayMessage( MessageOrder[ i ], i );
+ }
+ }
+ UpdateMessages();
+}
+
+
+/*
+====================
+=
+= UpdateModemMessage
+=
+====================
+*/
+void UpdateModemMessage
+(
+ int num,
+ char c
+)
+
+{
+ int i;
+
+ Messages[ num ].text[ MSG.length - 1 ] = ( byte )c;
+ Messages[ num ].text[ MSG.length ] = ( byte )'_';
+ MSG.length++;
+
+ for( i = 0; i < TotalMessages; i++ )
+ {
+ if ( MessageOrder[ i ] == num )
+ {
+ UpdateMessageBackground -= EraseMessage[ i ];
+ UpdateMessageBackground += 3;
+ EraseMessage[ i ] = 3;
+ break;
+ }
+ }
+}
+
+
+/*
+====================
+=
+= ModemMessageDeleteChar
+=
+====================
+*/
+void ModemMessageDeleteChar
+(
+ int num
+)
+
+{
+ int i;
+
+ MSG.length--;
+ Messages[ num ].text[ MSG.length ] = ( byte )0;
+ Messages[ num ].text[ MSG.length - 1 ] = ( byte )'_';
+
+ for( i = 0; i < TotalMessages; i++ )
+ {
+ if ( MessageOrder[ i ] == num )
+ {
+ UpdateMessageBackground -= EraseMessage[ i ];
+ UpdateMessageBackground += 3;
+ EraseMessage[ i ] = 3;
+ break;
+ }
+ }
+}
+
+
+/*
+====================
+=
+= DrawPlayerSelectionMenu
+=
+====================
+*/
+
+void DrawPlayerSelectionMenu
+(
+ void
+)
+
+{
+ int i;
+ int p;
+ char str[ 20 ];
+
+ p = 1;
+ MsgPos = 1;
+ AddMessage( "Press a key from 0 to 9 to select", MSG_NAMEMENU );
+ MsgPos++;
+ AddMessage( "who to send your message to:", MSG_NAMEMENU );
+ MsgPos++;
+
+ for( i = 0; i < numplayers; i++ )
+ {
+ if ( i != consoleplayer )
+ {
+ strcpy( str, "0 - " );
+ strcat( str, PLAYERSTATE[ i ].codename );
+ str[ 0 ] = '0' + p;
+ p++;
+ if ( p > 9 )
+ {
+ p = 0;
+ }
+
+ AddMessage( str, MSG_NAMEMENU );
+ MsgPos++;
+ }
+ }
+
+ if ( ( MsgPos < MAXMSGS - 1 ) && ( gamestate.teamplay ) )
+ {
+ AddMessage( "T - All team members", MSG_NAMEMENU );
+ MsgPos++;
+ }
+
+ if ( MsgPos < MAXMSGS - 1 )
+ {
+ AddMessage( "A - All players", MSG_NAMEMENU );
+ }
+
+ MsgPos = 0;
+}
+
+
+/*
+====================
+=
+= FinishModemMessage
+=
+====================
+*/
+void FinishModemMessage
+(
+ int num,
+ boolean send
+)
+{
+ if ( ( !MSG.inmenu ) && ( MSG.length > 0 ) )
+ {
+ Messages[ num ].text[ MSG.length - 1 ] = ( byte )0;
+ MSG.length--;
+ }
+
+ if ( ( send == true ) && ( ( MSG.length > 0 ) ||
+ ( MSG.remoteridicule != -1 ) ) )
+ {
+ if ( ( MSG.directed ) && ( !MSG.inmenu ) )
+ {
+ DrawPlayerSelectionMenu();
+ MSG.messageon = true;
+ MSG.inmenu = true;
+ return;
+ }
+
+ MSG.messageon = false;
+ if ( MSG.remoteridicule != -1 )
+ {
+ AddRemoteRidiculeCommand( consoleplayer, MSG.towho,
+ MSG.remoteridicule );
+ }
+ if ( MSG.length > 0 )
+ {
+ AddTextMessage( Messages[ num ].text, MSG.length, MSG.towho );
+ }
+ }
+
+ if ( MSG.inmenu )
+ {
+ DeletePriorityMessage( MSG_NAMEMENU );
+ }
+
+ DeleteMessage( num );
+}
--- /dev/null
+++ b/rott/rt_msg.h
@@ -1,0 +1,71 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_msg_public
+#define _rt_msg_public
+
+#define MSG_PERMANENT 0x80
+#define MSG_NODELETE 0x40
+#define MSG_PRIORITY( x ) ( ( x ) & 0x3f )
+
+#define PERMANENT_MSG( x ) ( ( x ) & MSG_PERMANENT )
+#define DELETABLE_MSG( x ) ( ( x ) & MSG_NODELETE )
+
+#define MSG_MODEM ( 1 | MSG_PERMANENT )
+#define MSG_SYSTEM ( 2 )
+#define MSG_REMOTERIDICULE ( 3 )
+#define MSG_REMOTE ( 4 | MSG_NODELETE )
+#define MSG_GAME ( 5 | MSG_NODELETE )
+#define MSG_DOOR ( 6 )
+#define MSG_CHEAT ( 7 )
+#define MSG_NAMEMENU ( 8 | MSG_PERMANENT | MSG_NODELETE )
+#define MSG_QUIT ( 9 )
+#define MSG_MACRO ( 10 )
+#define MSG_BONUS1 ( 11 )
+#define MSG_BONUS ( 12 )
+#define MSG_MSGSYSTEM ( 13 )
+
+#define MAXMSGS 15
+
+typedef struct msgt
+{
+ byte active;
+ byte flags;
+ int tictime;
+ char * text;
+} messagetype;
+
+extern messagetype Messages[MAXMSGS];
+
+extern boolean MessagesEnabled;
+
+
+void RestoreMessageBackground( void );
+void DrawMessages ( void );
+int AddMessage (char * text, int flags);
+void InitializeMessages ( void );
+void ResetMessageTime ( void );
+int StringLength (char *string);
+void UpdateModemMessage (int num, char c);
+void ModemMessageDeleteChar (int num);
+void DeleteMessage ( int num );
+void FinishModemMessage( int num, boolean send );
+void DeletePriorityMessage( int flags );
+
+#endif
--- /dev/null
+++ b/rott/rt_net.c
@@ -1,0 +1,3338 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+#ifdef DOS
+#include <dos.h>
+#include <io.h>
+#endif
+
+#include "rt_def.h"
+#include "rt_main.h"
+#include "rt_net.h"
+#include "rt_com.h"
+#include "_rt_net.h"
+#include "rt_actor.h"
+#include "rt_playr.h"
+#include "isr.h"
+#include "z_zone.h"
+#include "develop.h"
+#include "rottnet.h"
+#include "rt_msg.h"
+#include "rt_sound.h"
+#include "rt_menu.h"
+#include "rt_util.h"
+#include "rt_rand.h"
+#include "rt_game.h"
+#include "rt_draw.h"
+#include "myprint.h"
+#include "rt_debug.h"
+#include "rt_view.h"
+#include "rt_battl.h"
+#include "rt_dmand.h"
+//MED
+#include "memcheck.h"
+
+#if (SYNCCHECK == 1)
+int lastsynccheck;
+COM_CheckSyncType PlayerSync[MAXPLAYERS];
+#endif
+
+
+CommandType * LocalCmds;
+CommandType * ServerCmds;
+
+
+int controlupdatestartedtime=-1;
+int controlupdatetime=-1;
+int serverupdatetime=-1;
+int controlupdatestarted=0;
+boolean GamePaused=false;
+
+boolean modemgame;
+boolean networkgame;
+int numplayers;
+int server;
+boolean IsServer;
+boolean standalone;
+boolean restartgame=false;
+boolean respawnactive=false;
+boolean playerdead=false;
+boolean controlschanged=true;
+boolean battlegibs=false;
+boolean remoteridicule = false;
+/*
+=============================================================================
+
+ LOCAL FUNCTION PROTOTYPES and VARIABLES
+
+=============================================================================
+*/
+boolean demorecord,
+ demoplayback;
+byte *demoptr,
+ *lastdemoptr,
+ *demobuffer=NULL;
+boolean demodone = false;
+int predemo_violence = -1;
+int oldmomx;
+int oldmomy;
+int oldspdang;
+
+static boolean GameCommandsStarted=false;
+
+static int oldcontrolbuf[3];
+static int oldbuttonbits;
+static CommandType * PlayerCmds[MAXPLAYERS];
+static CommandType * ClientCmds[MAXPLAYERS];
+
+static boolean GotPlayersDesc[MAXPLAYERS];
+static boolean PlayersReady[MAXPLAYERS];
+static int LastCommandTime[MAXPLAYERS];
+
+static CommandStatusType * CommandState[MAXPLAYERS+1];
+
+static boolean InProcessServer=false;
+static int lastcontrolupdatetime;
+static int largesttime;
+static int PlayerStatus[MAXPLAYERS];
+//static int syncservertime;
+//static boolean FixingPackets;
+static int controldivisor=1;
+static int nextupdatetime;
+static boolean UpdateServer=true;
+
+void CheckForPacket ( void );
+void PrepareLocalPacket ( void );
+void SendSyncCheckPacket ( void );
+void AddModemSubPacket(void * incoming);
+void SetPlayerDescription( void * pkt );
+void UpdateDemoPlayback (int time);
+int GetTypeSize (int type);
+int MaxSpeedForCharacter(playertype *pstate);
+
+/*
+=============================================================================
+
+ Game Command Section
+
+=============================================================================
+*/
+
+//****************************************************************************
+//
+// ComError ()
+//
+//****************************************************************************
+
+#define ComError SoftError
+#if 0
+void ComError (char *error, ...)
+{
+#if 0
+ va_list argptr;
+#endif
+
+ SoftError(error);
+#if 0
+ if (standalone==true)
+ {
+ va_start (argptr, error);
+ vprintf (error, argptr);
+ va_end (argptr);
+ }
+#endif
+}
+#endif
+
+//****************************************************************************
+//
+// ConsoleIsServer()
+//
+//****************************************************************************
+boolean ConsoleIsServer ( void )
+{
+ if (modemgame==true)
+ {
+ if (networkgame==true)
+ {
+ if (rottcom->client==0)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+//****************************************************************************
+//
+// GamePacketSize()
+//
+//****************************************************************************
+int GamePacketSize( void )
+{
+ if ((remoteridicule == true) || (ConsoleIsServer() == true))
+ {
+ return GetTypeSize(COM_SOUNDANDDELTA);
+ }
+ else
+ return GetTypeSize(COM_TEXT);
+}
+
+//****************************************************************************
+//
+// InitializeGameCommands()
+//
+//****************************************************************************
+void InitializeGameCommands( void )
+{
+ int i;
+ int j;
+
+ // default to player 0
+
+ if (GameCommandsStarted==true)
+ return;
+
+ GameCommandsStarted=true;
+
+ if ((modemgame==true))
+ controldivisor=rottcom->ticstep;
+
+ standalone=false;
+ IsServer=false;
+
+ if (modemgame==true)
+ {
+ consoleplayer=rottcom->consoleplayer;
+
+ if (networkgame==true)
+ {
+ if (rottcom->client==0)
+ {
+ IsServer=true;
+ // turn it on absolutely for the server
+ remoteridicule = true;
+ if (consoleplayer==0)
+ standalone=true;
+ }
+ if (consoleplayer>0)
+ consoleplayer--; // playernumber fixup
+ }
+ }
+
+ if (standalone==false)
+ {
+ int size;
+
+ size = GamePacketSize ();
+
+ for (i=0; i<numplayers; i++)
+ {
+ PlayerCmds[i]=(CommandType *)SafeLevelMalloc(sizeof(CommandType));
+ for (j=0; j<MAXCMDS; j++)
+ {
+ PlayerCommand(i,j)=SafeLevelMalloc(size);
+ }
+ }
+ }
+
+
+ // allocate local commands
+
+ LocalCmds=(CommandType *)SafeLevelMalloc(sizeof(CommandType));
+ for (j=0; j<MAXCMDS; j++)
+ {
+ int size;
+
+ size = GamePacketSize();
+
+ LocalCommand(j)=SafeLevelMalloc(size);
+ memset(LocalCommand(j),COM_DELTANULL,size);
+ }
+
+ CommandState[0]=(CommandStatusType *)SafeLevelMalloc(sizeof(CommandStatusType));
+
+ if (modemgame==true)
+ {
+ for (i=0; i<numplayers; i++)
+ {
+ PlayerStatus[i]=player_ingame;
+ }
+ if (networkgame==true)
+ {
+ server=1;
+
+ // initialize the Server
+
+ if (IsServer==true)
+ {
+ server=0;
+ ServerCmds=(CommandType *)SafeMalloc(sizeof(CommandType));
+ for (j=0; j<MAXCMDS; j++)
+ {
+ int size;
+ size=( (numplayers * GetTypeSize(COM_TEXT)) +
+ GetTypeSize(COM_SOUNDANDDELTA) +
+ sizeof(COM_ServerHeaderType) -
+ sizeof(byte)
+ );
+ ServerCommand(j)=SafeMalloc( size );
+ memset(ServerCommand(j),COM_DELTANULL,size);
+ }
+ for (i=1; i<=numplayers; i++)
+ {
+ CommandState[i]=(CommandStatusType *)
+ SafeMalloc(sizeof(CommandStatusType));
+ }
+ for (i=0; i<numplayers; i++)
+ {
+ ClientCmds[i]=(CommandType *)SafeMalloc(sizeof(CommandType));
+ for (j=0; j<MAXCMDS; j++)
+ {
+ int size;
+
+ size=GetTypeSize(COM_SOUNDANDDELTA);
+ ClientCommand(i,j)=SafeMalloc(size);
+ memset(ClientCommand(i,j),COM_DELTANULL,size);
+ }
+ }
+ }
+ }
+ else // must be a two player game
+ {
+ server=consoleplayer^1;
+ }
+ }
+#if 0
+#if (DEVELOPMENT == 1)
+ if (IsServer)
+ ComError("I am the server\n");
+ ComError("consoleplayer=%ld\n",consoleplayer);
+ ComError("server=%ld mynumber=%ld\n",server,consoleplayer);
+#endif
+#endif
+}
+
+
+//****************************************************************************
+//
+// ShutdownGameCommands()
+//
+//****************************************************************************
+void ShutdownGameCommands( void )
+{
+ int i;
+ int j;
+
+ if (GameCommandsStarted==false)
+ return;
+
+ GameCommandsStarted=false;
+
+ // free up playercmds;
+ if (standalone==false)
+ {
+ for (i=0; i<numplayers; i++)
+ {
+ for (j=0; j<MAXCMDS; j++)
+ {
+ if (PlayerCommand(i,j))
+ {
+ SafeFree(PlayerCommand(i,j));
+ PlayerCommand(i,j)=NULL;
+ }
+ }
+ SafeFree( PlayerCmds[i] );
+ PlayerCmds[i]=NULL;
+ }
+ }
+
+ // free up command status
+
+ SafeFree(CommandState[0]);
+ CommandState[0]=NULL;
+
+ if (modemgame==true)
+ {
+
+ // free up local commands
+
+ for (j=0; j<MAXCMDS; j++)
+ {
+ if (LocalCommand(j))
+ {
+ SafeFree(LocalCommand(j));
+ LocalCommand(j)=NULL;
+ }
+ }
+ SafeFree(LocalCmds);
+ LocalCmds=NULL;
+
+
+ // free up Server
+
+ if (networkgame==true)
+ {
+ if (IsServer==true)
+ {
+ for (j=0; j<MAXCMDS; j++)
+ {
+ if (ServerCommand(j))
+ {
+ SafeFree(ServerCommand(j));
+ ServerCommand(j)=NULL;
+ }
+ }
+ SafeFree(ServerCmds);
+ ServerCmds=NULL;
+ for (i=1; i<=numplayers; i++)
+ {
+ SafeFree(CommandState[i]);
+ CommandState[i]=NULL;
+ }
+ for (i=0; i<numplayers; i++)
+ {
+ for (j=0; j<MAXCMDS; j++)
+ {
+ if (ClientCommand(i,j))
+ {
+ SafeFree(ClientCommand(i,j));
+ ClientCommand(i,j)=NULL;
+ }
+ }
+ SafeFree( ClientCmds[i] );
+ ClientCmds[i]=NULL;
+ }
+ }
+ }
+ }
+}
+
+
+
+
+/*
+=============================================================================
+
+ Client Controls Section
+
+=============================================================================
+*/
+
+
+//****************************************************************************
+//
+// ShutdownClientControls ()
+//
+//****************************************************************************
+
+void ShutdownClientControls ( void )
+{
+ int i;
+#if (DEVELOPMENT == 1)
+ SoftError ("LARGEST time difference=%ld\n",largesttime);
+#endif
+ controlupdatestarted=0;
+ for (i=0; i<numplayers; i++)
+ {
+ if (PlayerStatus[i] == player_leftgame)
+ PlayerStatus[i]=player_ingame;
+ }
+}
+
+
+//****************************************************************************
+//
+// StartupClientControls ()
+//
+//****************************************************************************
+
+void StartupClientControls ( void )
+{
+ int i,j;
+
+ if (controlupdatestarted==1)
+ return;
+
+ controlupdatestarted=1;
+
+ memset(oldcontrolbuf,-1,sizeof(oldcontrolbuf));
+ oldbuttonbits=-1;
+ controlschanged=true;
+
+ INL_GetMouseDelta(&i,&i);
+
+
+ locplayerstate->dmomx = 0;
+ locplayerstate->dmomy = 0;
+ locplayerstate->angle = 0;
+ locplayerstate->topspeed=MaxSpeedForCharacter(locplayerstate);
+
+
+ CalcTics();
+ CalcTics();
+
+// FixingPackets=false;
+
+ memset (controlbuf, 0, sizeof (controlbuf));
+ buttonbits = 0;
+ lastpolltime=-1;
+ IN_ClearKeyboardQueue ();
+
+ if (modemgame==true)
+ {
+ controlupdatetime=controlsynctime+(VBLCOUNTER*2);
+ SoftError("Controls started at %d\n",controlupdatetime);
+ }
+ else if (demoplayback || demorecord)
+ {
+ ISR_SetTime(20);
+ oldtime = 20;
+ controlupdatetime=20;
+ }
+ else
+ controlupdatetime=GetTicCount();
+
+ controlupdatetime-=(controlupdatetime%controldivisor);
+
+ serverupdatetime=controlupdatetime;
+ oldpolltime=controlupdatetime;
+ nextupdatetime=oldpolltime;
+#if (SYNCCHECK == 1)
+ lastsynccheck=oldpolltime+CHECKSYNCTIME;
+#endif
+ controlupdatestartedtime=controlupdatetime;
+
+ for( j = 0; j < numplayers; j++ )
+ {
+ memset( PLAYERSTATE[ j ].buttonheld, 0,
+ sizeof( PLAYERSTATE[ j ].buttonheld ) );
+ memset( PLAYERSTATE[ j ].buttonstate, 0,
+ sizeof( PLAYERSTATE[ j ].buttonstate ) );
+ }
+
+ for (i=0; i<MAXCMDS; i++)
+ {
+ ServerCommandNumberStatus( i ) = cs_notarrived;
+ }
+
+ LastCommandTime[0]=controlupdatetime-controldivisor;
+ if (IsServer==true)
+ {
+ int size;
+
+ UpdateServer=true;
+ size=( (numplayers * GetTypeSize(COM_TEXT)) +
+ GetTypeSize(COM_SOUNDANDDELTA) +
+ sizeof(COM_ServerHeaderType) -
+ sizeof(byte)
+ );
+
+ for (j=0; j<numplayers; j++)
+ {
+ for (i=0; i<MAXCMDS; i++)
+ {
+ ClientCommandNumberStatus( j, i ) = cs_notarrived;
+ }
+ LastCommandTime[j]=controlupdatetime-controldivisor;
+ }
+ for (i=0; i<MAXCMDS; i++)
+ memset(ServerCommand(i),COM_DELTANULL,size);
+ }
+ else if (modemgame==true)
+ {
+ int nump;
+
+ nump=numplayers;
+ if (nump<2) nump=2;
+
+ for (i=0; i<nump; i++)
+ {
+ LastCommandTime[i]=controlupdatetime-controldivisor;
+ }
+ }
+
+
+#if (DEVELOPMENT == 1)
+// ComError("StartupClientControls: GetTicCount()=%ld oldtime=%ld controlupdatetime=%ld\n",GetTicCount(),oldtime,controlupdatetime);
+#endif
+
+ if ((demoplayback==false) && (standalone==false))
+ {
+ if (modemgame==true)
+ {
+ while (GetTicCount()<(controlupdatetime-10))
+ {
+ CalcTics();
+ }
+ }
+ lastcontrolupdatetime=GetTicCount();
+ largesttime=0;
+ PollControls();
+ }
+ if (standalone==true)
+ printf("Packet Server started\n");
+}
+
+
+
+//****************************************************************************
+//
+// UpdateClientControls ()
+//
+//****************************************************************************
+
+static boolean InUCC=false;
+void UpdateClientControls ( void )
+{
+ int time;
+// int delta;
+
+ if (controlupdatestarted==0)
+ return;
+
+ if (InUCC)
+ return;
+ else
+ InUCC = true;
+
+ wami(6);
+
+#if 0
+
+ delta=GetTicCount()-lastcontrolupdatetime;
+ if (delta>largesttime)
+ {
+ if (delta>10)
+ largesttime=delta;
+ largesttime=delta;
+ }
+
+#endif
+ lastcontrolupdatetime=GetTicCount();
+
+ if (standalone==false)
+ {
+ time=GetTicCount();
+
+ // if we are a fixing the current packet stop update of deltas
+ // in non-network games.
+ if (
+ (networkgame == false) &&
+ (ServerCommandStatus(oldpolltime)==cs_fixing)
+ )
+ {
+ time=controlupdatetime-controldivisor;
+ }
+
+ while (time>=controlupdatetime)
+ {
+ MoveType * Delta;
+ boolean soundready;
+
+ soundready = SD_SoundDataReady();
+
+ if (demoplayback==true)
+ {
+ UpdateDemoPlayback(controlupdatetime);
+ }
+// else
+// {
+// PollControls();
+// }
+
+ if (
+ (memcmp(&controlbuf[0],&oldcontrolbuf[0],sizeof(controlbuf))!=0) ||
+ (buttonbits!=oldbuttonbits)
+ )
+ {
+ controlschanged=true;
+ memcpy(&oldcontrolbuf[0],&controlbuf[0],sizeof(controlbuf));
+ oldbuttonbits=buttonbits;
+ }
+ else
+ {
+ controlschanged=false;
+ }
+
+ if ((controlschanged==false) && (soundready==false))
+ {
+ NullMoveType * NullDelta;
+
+ NullDelta=(NullMoveType *)NextLocalCommand();
+ NullDelta->type=COM_DELTANULL;
+ }
+ else
+ {
+ Delta=(MoveType *)NextLocalCommand();
+ Delta->type=COM_DELTA;
+ Delta->momx=(controlbuf[0]>>1);
+ Delta->momy=(controlbuf[1]>>1);
+ Delta->dangle=controlbuf[2]>>11;
+ Delta->buttons=buttonbits;
+
+ // See if we need to update sound packet
+
+ if (soundready==true)
+ {
+ COM_SoundType * sndpkt;
+ recordstate status;
+
+ if (remoteridicule == false)
+ Error("Attempt to record Remote Ridicule without adequate storage");
+ sndpkt=(COM_SoundType *)Delta->Sounddata;
+
+ // Turn the packet into a COM_SOUNDANDDELTA packet
+
+ Delta->type=COM_SOUNDANDDELTA;
+ status = SD_GetSoundData ( &(sndpkt->data[0]),
+ COM_SOUND_BUFFERSIZE );
+ switch (status)
+ {
+ case rs_nodata:
+ Delta->type=COM_DELTA;
+ break;
+ case rs_newsound:
+ sndpkt->type=COM_SOUND_START_TRANSMISSION;
+ break;
+ case rs_endsound:
+ sndpkt->type=COM_SOUND_END_TRANSMISSION;
+ break;
+ case rs_data:
+ sndpkt->type=COM_SOUND_NORMAL_TRANSMISSION;
+ break;
+ default:
+ Error("Illegal return value for SD_GetSoundData");
+ break;
+ }
+ }
+ if (demorecord==true)
+ RecordDemoCmd();
+ }
+ PrepareLocalPacket();
+
+ if (
+ (controlupdatetime != -1) &&
+ (controlupdatetime > (lastpolltime+MAXPOLLTICS)) &&
+ (demoplayback==false)
+ )
+ {
+ controlbuf[0] = controlbuf[1] = controlbuf[2] = 0;
+ }
+ }
+ }
+ if (modemgame==true)
+ {
+ CheckForPacket ();
+ }
+
+ if ((standalone == false) && (IsServer==true) && (UpdateServer==true))
+ ProcessServer();
+
+// take out
+ if (modemgame==true)
+ {
+//#if (DEVELOPMENT == 1)
+ if (PanicPressed==true)
+ {
+ Error("Game Aborted. Scroll Lock pressed\n");
+ }
+//#endif
+ if (Keyboard[sc_Insert] && Keyboard[sc_Q])
+ Error("Game Aborted. Insert->Q pressed\n");
+ }
+
+ InUCC = false;
+
+ waminot();
+}
+
+//****************************************************************************
+//
+// PlayerInGame()
+//
+//****************************************************************************
+boolean PlayerInGame ( int p )
+{
+ if (PlayerStatus[p]!=player_ingame)
+ return false;
+ return true;
+}
+
+/*
+=============================================================================
+
+ Packet Section
+
+=============================================================================
+*/
+
+//****************************************************************************
+//
+// CheckForPacket()
+//
+//****************************************************************************
+void CheckForPacket ( void )
+{
+ wami(7);
+ while (ReadPacket()==true)
+ {
+ if (badpacket==0)
+ {
+ ProcessPacket(&ROTTpacket[0], rottcom->remotenode);
+#if (DEVELOPMENT == 1)
+// ComError("CheckForPacket: from=%ld\n",rottcom->remotenode);
+#endif
+ }
+ else
+ RequestPacket (LastCommandTime[rottcom->remotenode]+controldivisor, rottcom->remotenode, controldivisor);
+ }
+ waminot();
+}
+
+
+//****************************************************************************
+//
+// AddRemoteRidiculeCommand()
+//
+//****************************************************************************
+void AddRemoteRidiculeCommand ( int player, int towho, int num )
+{
+ ((COM_RemoteRidiculeType *)NextLocalCommand())->type=COM_REMRID;
+ ((COM_RemoteRidiculeType *)NextLocalCommand())->num=num;
+ ((COM_RemoteRidiculeType *)NextLocalCommand())->player=player;
+ ((COM_RemoteRidiculeType *)NextLocalCommand())->towho=towho;
+
+ PrepareLocalPacket();
+}
+
+//****************************************************************************
+//
+// ProcessRemoteRidicule()
+//
+//****************************************************************************
+void ProcessRemoteRidicule ( void * pkt )
+{
+ COM_RemoteRidiculeType * remrot;
+ char name[ 50 ];
+ int from;
+ int who;
+
+ remrot = (COM_RemoteRidiculeType *)pkt;
+ from = remrot->player;
+ who = remrot->towho;
+ if ( ( who == consoleplayer ) || ( who == MSG_DIRECTED_TO_ALL ) ||
+ ( ( who == MSG_DIRECTED_TO_TEAM ) && ( BATTLE_Team[ from ] ==
+ BATTLE_Team[ consoleplayer ] ) ) )
+ {
+ strcpy( name, "(� RR from " );
+ strcat( name, PLAYERSTATE[from].codename );
+ strcat( name, ")" );
+ AddMessage( name, MSG_REMOTERIDICULE );
+
+ SD_Play( SD_REMOTEM1SND + remrot->num );
+ }
+}
+
+//****************************************************************************
+//
+// AddEndGameCommand()
+//
+//****************************************************************************
+void AddEndGameCommand ( void )
+{
+ ((COM_EndGameType *)NextLocalCommand())->type=COM_ENDGAME;
+
+ PrepareLocalPacket();
+}
+
+//****************************************************************************
+//
+// AddGameEndCommand()
+//
+//****************************************************************************
+void AddGameEndCommand ( void )
+{
+ ((COM_GameEndType *)NextLocalCommand())->type=COM_GAMEEND;
+
+ PrepareLocalPacket();
+}
+
+//****************************************************************************
+//
+// AddQuitCommand()
+//
+//****************************************************************************
+void AddQuitCommand ( void )
+{
+ ((COM_QuitType *)NextLocalCommand())->type=COM_QUIT;
+ PrepareLocalPacket();
+}
+
+//****************************************************************************
+//
+// AddExitCommand()
+//
+//****************************************************************************
+void AddExitCommand ( void )
+{
+ ((COM_ExitType *)NextLocalCommand())->type=COM_EXIT;
+ PrepareLocalPacket();
+}
+
+//****************************************************************************
+//
+// AddPauseStateCommand()
+//
+//****************************************************************************
+void AddPauseStateCommand ( int type )
+{
+ ((COM_PauseType *)NextLocalCommand())->type=type;
+
+ PrepareLocalPacket();
+}
+
+
+//****************************************************************************
+//
+// AddRespawnCommand()
+//
+//****************************************************************************
+void AddRespawnCommand ( void )
+{
+ if (respawnactive==true)
+ return;
+
+ respawnactive=true;
+
+ ((COM_RespawnType *)NextLocalCommand())->type=COM_RESPAWN;
+
+ PrepareLocalPacket();
+}
+
+
+//****************************************************************************
+//
+// AddTextMessage()
+//
+//****************************************************************************
+void AddTextMessage
+(
+ char *message,
+ int length,
+ int towho
+)
+
+{
+ COM_TextType *Text;
+
+ Text = ( COM_TextType * )NextLocalCommand();
+
+ Text->type = COM_TEXT;
+ memset( &Text->string[ 0 ], 0, COM_MAXTEXTSTRINGLENGTH );
+
+ if ( length >= COM_MAXTEXTSTRINGLENGTH )
+ {
+ length = COM_MAXTEXTSTRINGLENGTH - 1;
+ }
+
+ memcpy( &Text->string[ 0 ], message, length );
+
+ Text->towho = towho;
+
+ PrepareLocalPacket();
+}
+
+
+//****************************************************************************
+//
+// PrepareLocalPacket
+//
+//****************************************************************************
+
+void PrepareLocalPacket ( void )
+{
+ MoveType * pkt;
+
+ wami(8);
+
+ pkt=(MoveType *)NextLocalCommand();
+
+ pkt->time=controlupdatetime;
+
+ if (networkgame==false) // Whether it is a modem game or not we do this
+ {
+ AddClientPacket (pkt, consoleplayer);
+ if (modemgame==false)
+ {
+ ServerCommandStatus ( controlupdatetime ) = cs_ready;
+ }
+ }
+
+ if (modemgame==true)
+ SendPacket (pkt, server);
+
+#if (DEVELOPMENT == 1)
+// ComError("packet sent: realtime=%ld time=%ld type=%ld dest=%ld\n",GetTicCount(),pkt->time,pkt->type,server);
+#endif
+
+ controlupdatetime+=controldivisor;
+ waminot();
+}
+
+
+
+//****************************************************************************
+//
+// GetPacketSize ()
+//
+//****************************************************************************
+
+int GetPacketSize (void * pkt)
+{
+ int size;
+
+ switch (((MoveType *)pkt)->type)
+ {
+ case COM_DELTA:
+ size=sizeof(MoveType);
+ break;
+ case COM_DELTANULL:
+ size=sizeof(NullMoveType);
+ break;
+ case COM_REQUEST:
+ size=sizeof(COM_RequestType);
+ break;
+ case COM_FIXUP:
+ size=sizeof(COM_FixupType);
+ break;
+ case COM_TEXT:
+ size=sizeof(COM_TextType);
+ break;
+ case COM_PAUSE:
+ size=sizeof(COM_PauseType);
+ break;
+ case COM_QUIT:
+ size=sizeof(COM_QuitType);
+ break;
+ case COM_EXIT:
+ size=sizeof(COM_ExitType);
+ break;
+ case COM_REMRID:
+ size=sizeof(COM_RemoteRidiculeType);
+ break;
+ case COM_RESPAWN:
+ size=sizeof(COM_RespawnType);
+ break;
+ case COM_UNPAUSE:
+ size=sizeof(COM_UnPauseType);
+ break;
+ case COM_SERVER:
+ size=sizeof(COM_ServerHeaderType);
+ size-=sizeof(byte);
+ break;
+ case COM_GAMEDESC:
+ size=sizeof(COM_GamePlayerType);
+ break;
+ case COM_GAMEEND:
+ size=sizeof(COM_GameEndType);
+ break;
+ case COM_GAMEPLAY:
+ size=DUMMYPACKETSIZE;
+ break;
+ case COM_GAMEACK:
+ size=sizeof(COM_GameAckType);
+ break;
+ case COM_GAMEMASTER:
+ size=sizeof(COM_GameMasterType);
+ break;
+ case COM_ENDGAME:
+ size=sizeof(COM_EndGameType);
+ break;
+ case COM_SYNCTIME:
+ size=sizeof(COM_SyncType);
+ break;
+#if (SYNCCHECK == 1)
+ case COM_SYNCCHECK:
+ size=sizeof(COM_CheckSyncType);
+ break;
+#endif
+ case COM_SOUNDANDDELTA:
+ size=sizeof(MoveType)+sizeof(COM_SoundType);
+ break;
+ default:
+ Error("Unhandled packet type in GetPacketSize type=%d",((MoveType *)pkt)->type);
+ break;
+ }
+
+ return size;
+}
+
+//****************************************************************************
+//
+// GetTypeSize ()
+//
+//****************************************************************************
+
+int GetTypeSize (int type)
+{
+ byte pkt[2];
+
+ pkt[0]=(byte)type;
+ return ( GetPacketSize(&(pkt[0])) );
+}
+
+//****************************************************************************
+//
+// GetServerPacketSize ()
+//
+//****************************************************************************
+
+int GetServerPacketSize (void * pkt)
+{
+ int i;
+ byte * ptr;
+ COM_ServerHeaderType * serverpkt;
+
+ serverpkt=(COM_ServerHeaderType *)pkt;
+ if (serverpkt->type==COM_SERVER)
+ {
+ ptr=&serverpkt->data;
+
+ for (i=0; i<serverpkt->numpackets; i++)
+ {
+ ptr+=GetPacketSize(ptr);
+ }
+ return ((byte *)ptr-(byte *)pkt);
+ }
+ else
+ return GetPacketSize(pkt);
+}
+
+//****************************************************************************
+//
+// SendPacket ()
+//
+//****************************************************************************
+
+void SendPacket (void * pkt, int dest)
+{
+ if ((networkgame==false) && (PlayerStatus[dest]!=player_ingame))
+ return;
+ if ((IsServer==true) && (dest==server) && (standalone==false)) // must be client on top of server
+ ProcessPacket(pkt,dest);
+ else if ((IsServer==false) && (dest!=server) && (standalone==false)) // We shouldn't be sending as client to anyone else
+ ComError("SendPacket:Problems\n");
+ else
+ WritePacket(pkt,GetPacketSize(pkt),dest);
+#if (DEVELOPMENT == 1)
+// ComError( "SendPacket: time=%ld dest=%ld\n",((MoveType *)pkt)->time,dest);
+#endif
+}
+
+//****************************************************************************
+//
+// ResetCurrentCommand ()
+//
+//****************************************************************************
+
+void ResetCurrentCommand ( void )
+{
+ ServerCommandStatus(oldpolltime)=cs_notarrived;
+}
+
+//****************************************************************************
+//
+// BroadcastServerPacket ()
+//
+//****************************************************************************
+
+void BroadcastServerPacket (void * pkt, int size)
+{
+ int i;
+
+
+ for (i=0; i<numplayers; i++)
+ {
+ if (PlayerStatus[i]!=player_ingame)
+ continue;
+// if ((standalone==false) && (i==consoleplayer))
+// ProcessPacket(pkt,i);
+// else
+ WritePacket((byte *)pkt,size,i);
+ }
+}
+
+
+//****************************************************************************
+//
+// ResendLocalPackets ()
+//
+//****************************************************************************
+
+void ResendLocalPackets (int time, int dest, int numpackets)
+{
+ int cmd;
+ MoveType * pkt;
+
+ cmd = CommandAddress(time);
+
+#if 0
+ if (networkgame==false)
+ {
+ int nump;
+ nump=controlupdatetime-time;
+ if (nump>numpackets)
+ numpackets=nump;
+ }
+#endif
+
+ if (controlupdatetime<=time)
+ return;
+
+ pkt = (MoveType *)LocalCommand(cmd);
+
+ if (pkt->time!=time)
+ {
+ Error( "CLIENT: Could not find packet to resend\ntime=%d packettime=%d controlupdatetime=%d\n",
+ time, pkt->time, controlupdatetime);
+ }
+ else
+ {
+ byte * tempbuf;
+ byte * tempptr;
+ byte * tempstart;
+ COM_FixupType * fixup;
+ int i;
+ int starti;
+ int size;
+ boolean done;
+
+ // allocate some space
+
+ tempbuf=SafeMalloc(MAXCOMBUFFERSIZE);
+
+ fixup=(COM_FixupType *)tempbuf;
+
+ fixup->type=COM_FIXUP;
+ tempstart=&(fixup->data);
+
+ done=false;
+ i=0;
+ while (done==false)
+ {
+ tempptr=tempstart;
+ starti=i;
+ fixup->time=( (MoveType *)LocalCommand(cmd) )->time;
+ for (; i<numpackets; i++)
+ {
+ pkt = (MoveType *)LocalCommand(cmd);
+ size=GetPacketSize(pkt);
+
+ if (((tempptr+size)-tempbuf)>MAXCOMBUFFERSIZE)
+ {
+ break;
+ }
+ memcpy(tempptr,pkt,size);
+ tempptr+=size;
+ cmd = (cmd + controldivisor) & (MAXCMDS-1);
+ }
+ fixup->numpackets=i-starti;
+ WritePacket(tempbuf,tempptr-tempbuf,dest);
+ if (i==numpackets)
+ done=true;
+ }
+
+ SafeFree(tempbuf);
+ }
+}
+
+//****************************************************************************
+//
+// ResendServerPackets ()
+//
+//****************************************************************************
+
+void ResendServerPackets (int time, int dest, int numpackets)
+{
+ int cmd;
+ COM_ServerHeaderType * serverpkt;
+
+
+ cmd = CommandAddress(time);
+
+ if (serverupdatetime<=time)
+ return;
+
+ serverpkt = (COM_ServerHeaderType *)ServerCommand(cmd);
+
+ if (serverpkt->time!=time)
+ {
+ Error( "SERVER: Could not find packet to resend\ntime=%d packettime=%d serverupdatetime=%d\n",
+ time, serverpkt->time,serverupdatetime);
+ }
+ else
+ {
+ byte * tempbuf;
+ byte * tempptr;
+ byte * tempstart;
+ COM_FixupType * fixup;
+ int i;
+ int starti;
+ int size;
+ boolean done;
+
+ // allocate some space
+
+ tempbuf=SafeMalloc(MAXCOMBUFFERSIZE);
+
+ fixup=(COM_FixupType *)tempbuf;
+
+ fixup->type=COM_FIXUP;
+ tempstart=&(fixup->data);
+
+ done=false;
+ i=0;
+ while (done==false)
+ {
+ tempptr=tempstart;
+ starti=i;
+ fixup->time=( (MoveType *)ServerCommand(cmd) )->time;
+ for (; i<numpackets; i++)
+ {
+ serverpkt = (COM_ServerHeaderType *)ServerCommand(cmd);
+ size=GetServerPacketSize(serverpkt);
+
+ if (((tempptr+size)-tempbuf)>MAXCOMBUFFERSIZE)
+ {
+ break;
+ }
+ memcpy(tempptr,serverpkt,size);
+ tempptr+=size;
+ cmd = (cmd + controldivisor) & (MAXCMDS-1);
+ }
+ fixup->numpackets=i-starti;
+ WritePacket(tempbuf,tempptr-tempbuf,dest);
+ if (i==numpackets)
+ done=true;
+ }
+
+ SafeFree(tempbuf);
+ }
+}
+
+
+//****************************************************************************
+//
+// ResendPacket (incoming packet, whoever requested it)
+//
+//****************************************************************************
+
+void ResendPacket (void * pkt, int dest)
+{
+ int time;
+ COM_RequestType * request;
+
+ if ((networkgame==false) && (PlayerStatus[dest]!=player_ingame))
+ return;
+
+ request=(COM_RequestType * )pkt;
+ time=request->time;
+
+ ComError( "RESEND request received at %d\n packet time=%d dest=%d numpackets=%d\n",
+ GetTicCount(), time, dest, request->numpackets);
+
+ if (IsServer==true)
+ {
+ if ((dest==server) && (standalone==false))
+ Error("Trying to resend packets to client on top of server\n");
+ ComError( "RESEND SERVER serverupdatetime=%d\n",serverupdatetime);
+ if (IsServerCommandReady ( time ) == true)
+ ResendServerPackets(time,dest,request->numpackets);
+ else
+ ComError( "RESEND SERVER time=%d is not ready\n",time);
+ }
+ else
+ {
+ ResendLocalPackets(time,dest,request->numpackets);
+ }
+}
+
+//****************************************************************************
+//
+// FixupPacket ()
+//
+//****************************************************************************
+
+void FixupPacket (void * pkt, int src)
+{
+ COM_FixupType * fix;
+ int i;
+ int time;
+ byte * ptr;
+
+ fix=(COM_FixupType *)pkt;
+
+ ComError( "Fixup received at %d, time=%d numpackets=%d\n", GetTicCount(), fix->time, fix->numpackets);
+#if 0
+ if (networkgame==false)
+ FixingPackets=false;
+#endif
+ time=fix->time;
+ ptr=&(fix->data);
+
+ for (i=0; i<fix->numpackets; i++,time+=controldivisor)
+ {
+ if (time == (LastCommandTime[src]+controldivisor))
+ LastCommandTime[src]=time;
+
+ if (IsServer==true)
+ {
+ if (ClientCommandStatus(src, time)!=cs_fixing)
+ {
+ ComError("Server Received fixup with no bad packet time=%d from %d\n",time,src);
+ }
+ else
+ {
+ AddSubPacket(ptr, src);
+ }
+ ptr+=GetPacketSize(ptr);
+ }
+ else
+ {
+ if (ServerCommandStatus(time)!=cs_fixing)
+ {
+ ComError("Client Received fixup with no bad packet time=%d from %d\n",time,src);
+ }
+ else
+ {
+ if (networkgame==true)
+ {
+ AddServerSubPacket( (COM_ServerHeaderType *)ptr );
+ }
+ else
+ {
+ AddModemSubPacket(ptr);
+ }
+ }
+ ptr+=GetServerPacketSize(ptr);
+ }
+ }
+}
+
+#if (SYNCCHECK == 1)
+//****************************************************************************
+//
+// CheckForSyncCheck
+//
+//****************************************************************************
+
+void CheckForSyncCheck ( void )
+{
+ int i;
+
+
+ if (modemgame==true)
+ {
+ if (oldpolltime==lastsynccheck)
+ {
+ for (i=0; i<numplayers; i++)
+ {
+ PlayerSync[i].x=PLAYER[i]->x;
+ PlayerSync[i].y=PLAYER[i]->y;
+ PlayerSync[i].z=PLAYER[i]->z;
+ PlayerSync[i].angle=PLAYER[i]->angle;
+ }
+ PlayerSync[0].randomindex=GetRNGindex();
+ PlayerSync[0].synctime=lastsynccheck;
+ SendSyncCheckPacket();
+ lastsynccheck+=CHECKSYNCTIME;
+ }
+ if (oldpolltime>lastsynccheck)
+ {
+ Error("Missed a player sync check time=%d\n",oldpolltime);
+ }
+ }
+}
+#endif
+
+//****************************************************************************
+//
+// ProcessSyncTimePacket
+//
+//****************************************************************************
+
+void ProcessSyncTimePacket (void * pkt)
+{
+ COM_SyncType * sync;
+
+ sync=(COM_SyncType *)pkt;
+ ISR_SetTime(sync->synctime);
+}
+
+#if (SYNCCHECK == 1)
+//****************************************************************************
+//
+// ProcessSyncCheckPacket
+//
+//****************************************************************************
+
+void ProcessSyncCheckPacket (void * pkt, int src)
+{
+ COM_CheckSyncType * sync;
+
+ sync=(COM_CheckSyncType *)pkt;
+// SoftError("Sync packet time=%ld\n",sync->synctime);
+ if (sync->synctime!=PlayerSync[0].synctime)
+ {
+ SoftError("Old sync packet received\n");
+ return;
+ }
+ if (sync->randomindex!=PlayerSync[0].randomindex)
+ {
+ Error("Player %d is unsynced localindex=%d remoteindex=%d\n"
+ "Unsynced Player x=%x y=%x a=%d z=%d name=%s\n",
+ src, PlayerSync[0].randomindex, sync->randomindex,
+ PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
+ PlayerSync[src].z,PLAYERSTATE[src].codename);
+ }
+ if (sync->x!=PlayerSync[src].x)
+ {
+ Error("Player %d is unsynced local x=%d remote x=%d\n"
+ "Unsynced Player x=%x y=%x a=%d z=%d name=%s\n",
+ src,PlayerSync[src].x,sync->x,
+ PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
+ PlayerSync[src].z,PLAYERSTATE[src].codename);
+ }
+ if (sync->y!=PlayerSync[src].y)
+ {
+ Error("Player %d is unsynced local y=%d remote y=%d\n"
+ "Unsynced Player x=%x y=%x a=%d z=%d name=%s\n",
+ src,PlayerSync[src].y,sync->y,
+ PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
+ PlayerSync[src].z,PLAYERSTATE[src].codename);
+ }
+ if (sync->z!=PlayerSync[src].z)
+ {
+ Error("Player %d is unsynced local z=%d remote z=%d\n"
+ "Unsynced Player x=%x y=%x a=%d z=%d name=%s\n",
+ src,PlayerSync[src].z,sync->z,
+ PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
+ PlayerSync[src].z,PLAYERSTATE[src].codename);
+ }
+ if (sync->angle!=PlayerSync[src].angle)
+ {
+ Error("Player %d is unsynced local angle=%d remote angle=%d\n"
+ "Unsynced Player x=%x y=%x a=%d z=%d name=%s\n",
+ src,PlayerSync[src].angle,sync->angle,
+ PlayerSync[src].x, PlayerSync[src].y, PlayerSync[src].angle,
+ PlayerSync[src].z,PLAYERSTATE[src].codename);
+ }
+}
+
+//****************************************************************************
+//
+// SendSyncCheckPacket
+//
+//****************************************************************************
+
+void SendSyncCheckPacket ( void )
+{
+ ((COM_CheckSyncType *)NextLocalCommand())->type=COM_SYNCCHECK;
+ ((COM_CheckSyncType *)NextLocalCommand())->synctime=PlayerSync[0].synctime;
+ ((COM_CheckSyncType *)NextLocalCommand())->x=PlayerSync[consoleplayer].x;
+ ((COM_CheckSyncType *)NextLocalCommand())->y=PlayerSync[consoleplayer].y;
+ ((COM_CheckSyncType *)NextLocalCommand())->z=PlayerSync[consoleplayer].z;
+ ((COM_CheckSyncType *)NextLocalCommand())->angle=PlayerSync[consoleplayer].angle;
+ ((COM_CheckSyncType *)NextLocalCommand())->randomindex=PlayerSync[0].randomindex;
+
+ PrepareLocalPacket();
+}
+#endif
+
+#if 0
+
+//****************************************************************************
+//
+// CheckForSyncTime
+//
+//****************************************************************************
+
+void CheckForSyncTime ( void )
+{
+ if ((modemgame==true) && (networkgame==false) && (consoleplayer==0))
+ {
+ if (controlupdatetime>=syncservertime)
+ {
+ SendSyncTimePacket();
+ syncservertime+=MODEMSYNCSERVERTIME;
+ }
+ }
+}
+#endif
+
+#if 0
+//****************************************************************************
+//
+// SendSyncTimePacket
+//
+//****************************************************************************
+
+void SendSyncTimePacket ( void )
+{
+ int i;
+ COM_SyncType sync;
+
+ return;
+
+ sync.type=COM_SYNCTIME;
+
+ if (networkgame==true)
+ {
+ for (i=0; i<numplayers; i++)
+ {
+ if ((PlayerStatus[i]!=player_ingame) || ( (i==consoleplayer) && (standalone==false) ) )
+ continue;
+ sync.synctime=GetTicCount()+GetTransitTime(i);
+ WritePacket ( &sync.type, GetPacketSize(&sync.type), i);
+ }
+ }
+ else
+ {
+ if (PlayerStatus[server]==player_ingame)
+ {
+ sync.synctime=GetTicCount()+GetTransitTime(server);
+ WritePacket ( &sync.type, GetPacketSize(&sync.type), server);
+ }
+ }
+}
+#endif
+
+//****************************************************************************
+//
+// ProcessSoundAndDeltaPacket
+//
+//****************************************************************************
+
+void ProcessSoundAndDeltaPacket (void * pkt, int src)
+{
+ MoveType * packet;
+ COM_SoundType * sndpkt;
+ byte oldtype;
+
+ packet = (MoveType *)pkt;
+
+ // Trick packet into being a normal delta packet
+
+ oldtype=packet->type;
+ packet->type=COM_DELTA;
+ AddClientPacket (pkt,src);
+ packet->type=oldtype;
+
+ // Don't process sound if it is from us
+ if (src==consoleplayer)
+ return;
+
+ sndpkt = (COM_SoundType *) (packet->Sounddata);
+
+ if (sndpkt->type==COM_SOUND_START_TRANSMISSION)
+ {
+ SD_StartIncomingSound ();
+ }
+ if (sndpkt->type==COM_SOUND_END_TRANSMISSION)
+ {
+ SD_StopIncomingSound();
+ }
+ else
+ {
+ SD_UpdateIncomingSound (&(sndpkt->data[0]), COM_SOUND_BUFFERSIZE);
+ }
+}
+//****************************************************************************
+//
+// SyncToServer
+//
+//****************************************************************************
+#define NETWORKTIMEAHEADOFSERVER (1)
+#define MODEMTIMEAHEADOFSERVER (2)
+void SyncToServer( void )
+{
+ int diff;
+
+ if ((networkgame==false) && (consoleplayer==0))
+ return;
+ if (IsServer==true)
+ return;
+// if (networkgame==true)
+// {
+// diff = (GetTicCount()-controldivisor-LastCommandTime[0])/controldivisor;
+// SoftError("diff=%ld\n",diff);
+// if (abs(diff)>1)
+// ISR_SetTime(GetTicCount()-diff);
+#if 0
+ diff = controlupdatetime-LastCommandTime[0];
+ if (diff>3)
+ {
+ ISR_SetTime(GetTicCount()-1);
+ }
+ else if (diff<-3)
+ {
+ ISR_SetTime(GetTicCount()+1);
+ }
+#endif
+// }
+// else
+// {
+ diff = (GetTicCount()-controldivisor-LastCommandTime[server])/controldivisor;
+ if (abs(diff)>0)
+ ISR_SetTime(GetTicCount()-diff);
+// }
+}
+
+//****************************************************************************
+//
+// ProcessPacket
+//
+//****************************************************************************
+
+void ProcessPacket (void * pkt, int src)
+{
+ switch (((MoveType *)pkt)->type)
+ {
+ case COM_DELTA:
+ case COM_DELTANULL:
+ case COM_TEXT:
+ case COM_PAUSE:
+ case COM_QUIT:
+ case COM_EXIT:
+ case COM_REMRID:
+ case COM_RESPAWN:
+ case COM_UNPAUSE:
+ case COM_ENDGAME:
+#if (SYNCCHECK == 1)
+ case COM_SYNCCHECK:
+#endif
+// if (FixingPackets==false)
+ AddPacket(pkt,src);
+ break;
+ case COM_SOUNDANDDELTA:
+ if (remoteridicule == false )
+ {
+ ((MoveType *)pkt)->type = COM_DELTA;
+ }
+ AddPacket(pkt,src);
+ break;
+ case COM_SERVER:
+ AddServerPacket(pkt,src);
+ break;
+
+ case COM_REQUEST:
+ ResendPacket(pkt, src);
+ break;
+
+ case COM_FIXUP:
+ FixupPacket(pkt, src);
+ break;
+
+ case COM_SYNCTIME:
+ ProcessSyncTimePacket(pkt);
+ break;
+
+ case COM_GAMEEND:
+ case COM_GAMEDESC:
+ case COM_GAMEACK:
+ case COM_GAMEMASTER:
+ if (standalone==true)
+ restartgame=true;
+ break;
+
+ case COM_START:
+ break;
+
+ default:
+ Error("ProcessPacket: Unknown packet type=%d\n",((MoveType *)pkt)->type);
+ }
+}
+
+
+//****************************************************************************
+//
+// AddServerSubPacket
+//
+//****************************************************************************
+
+void AddServerSubPacket(COM_ServerHeaderType * serverpkt)
+{
+ byte * pkt;
+ int i;
+
+ ServerCommandStatus(serverpkt->time)=cs_ready;
+
+ pkt=&serverpkt->data;
+ for (i=0; i<serverpkt->numpackets; i++)
+ {
+ AddClientPacket(pkt,i);
+ pkt+=GetPacketSize(pkt);
+ }
+}
+
+//****************************************************************************
+//
+// AddModemSubPacket
+//
+//****************************************************************************
+
+void AddModemSubPacket(void * incoming)
+{
+ MoveType * pkt;
+
+ pkt=(MoveType *)incoming;
+ ServerCommandStatus(pkt->time)=cs_ready;
+
+ AddClientPacket(incoming,server);
+}
+
+//****************************************************************************
+//
+// AddServerPacket
+//
+//****************************************************************************
+
+void AddServerPacket(void * pkt, int src)
+{
+ COM_ServerHeaderType * serverpkt;
+
+ // The server uses the client's lgts for communicating
+
+ // Last good time can be set even for the client/server combo
+
+ if (standalone==true)
+ {
+ Error("standalone should not be here\n");
+ }
+
+ if (src!=server)
+ {
+ Error("Received server packet from non-server src=%d\n",src);
+ }
+
+ serverpkt=(COM_ServerHeaderType *)pkt;
+
+// if (networkgame==false)
+// SyncToServer(serverpkt->time);
+
+ LastCommandTime[src]+=controldivisor;
+
+ if (serverpkt->time != LastCommandTime[src])
+ {
+ int numpackets;
+
+ numpackets=serverpkt->time-LastCommandTime[src];
+ if (ServerCommandStatus(LastCommandTime[src])!=cs_fixing)
+ {
+ RequestPacket ( LastCommandTime[src], src, numpackets );
+
+ ComError("AddServerPacket: Request packet time=%d lct=%d numpackets=%d\n",
+ serverpkt->time, LastCommandTime[src], numpackets
+ );
+ }
+
+ LastCommandTime[src]+=numpackets;
+ }
+
+ AddServerSubPacket( serverpkt );
+}
+
+//****************************************************************************
+//
+// AddClientPacket
+//
+//****************************************************************************
+
+void AddClientPacket (void * pkt, int src)
+{
+ int size;
+ MoveType * packet;
+
+ packet=(MoveType *)pkt;
+
+ switch (packet->type)
+ {
+ case COM_DELTA:
+ case COM_DELTANULL:
+ case COM_TEXT:
+ case COM_REMRID:
+ case COM_PAUSE:
+ case COM_QUIT:
+ case COM_EXIT:
+ case COM_RESPAWN:
+ case COM_UNPAUSE:
+#if (SYNCCHECK == 1)
+ case COM_SYNCCHECK:
+#endif
+ case COM_ENDGAME:
+ size=GetPacketSize(packet);
+ memcpy(PlayerCommand(src,CommandAddress(packet->time)),packet,size);
+ break;
+ case COM_SOUNDANDDELTA:
+ ProcessSoundAndDeltaPacket(packet, src);
+ break;
+ default:
+ Error("AddClientPacket: Unknown packet type = %d\n",packet->type);
+ }
+}
+
+//****************************************************************************
+//
+// AddSubPacket
+//
+//****************************************************************************
+
+void AddSubPacket (void * pkt, int src)
+{
+ MoveType * packet;
+
+ if (networkgame==false)
+ Error("Modem game should not be here in AddSubPacket\n");
+
+ packet = (MoveType *) pkt;
+
+ ClientCommandStatus(src, packet->time)=cs_ready;
+
+ memcpy (
+ ClientTimeCommand(src,packet->time),
+ pkt,
+ GetPacketSize(packet)
+ );
+}
+
+//****************************************************************************
+//
+// AddPacket
+//
+//****************************************************************************
+
+void AddPacket (void * pkt, int src)
+{
+ MoveType * packet;
+
+ // should only be called by server in network game
+ // in modem game we fall through the first condition
+ // all packets should be sequential
+
+ if ((IsServer==true) && (PlayerStatus[src]!=player_ingame))
+ return;
+ packet = (MoveType *) pkt;
+
+// if ((networkgame==false) && (consoleplayer!=0))
+// SyncToServer();
+
+ if (!((src==server) && (standalone==false) && (IsServer==true)))
+ {
+ LastCommandTime[src]+=controldivisor;
+
+ if (packet->time != LastCommandTime[src])
+ {
+ int numpackets;
+
+ numpackets=packet->time-LastCommandTime[src];
+ if ( ( (networkgame==false) &&
+ (ServerCommandStatus(LastCommandTime[src])!=cs_fixing)
+ )
+ ||
+ ( (networkgame==true) &&
+ (ClientCommandStatus(src,LastCommandTime[src])!=cs_fixing)
+ )
+ )
+ {
+ RequestPacket ( LastCommandTime[src], src, numpackets );
+
+ ComError("AddPacket: Request packet time=%d lct=%d numpackets=%d\n",
+ packet->time, LastCommandTime[src], numpackets
+ );
+ }
+
+ LastCommandTime[src]+=numpackets;
+ }
+ }
+
+ if (networkgame==true)
+ {
+ AddSubPacket ( packet, src );
+ }
+ else
+ {
+ AddModemSubPacket(packet);
+ }
+}
+
+
+//****************************************************************************
+//
+// RequestPacket ( int time, int dest )
+//
+//****************************************************************************
+
+void RequestPacket (int time, int dest, int numpackets)
+{
+ COM_RequestType request;
+ int i;
+
+
+#if (DEVELOPMENT == 1)
+ if (modemgame==false)
+ Error("Called Request Packet outside of modem game\n");
+#endif
+
+ request.type=COM_REQUEST;
+ request.time=time;
+ request.numpackets=numpackets/controldivisor;
+
+ if (IsServer==true)
+ {
+ if ((dest==server) && (standalone==false))
+ {
+ Error("Requesting packet from client on top of server\n");
+ }
+ if (PlayerStatus[dest]!=player_ingame)
+ return;
+ for (i=0; i<numpackets; i+=controldivisor)
+ {
+ ClientCommandStatus( dest, (time+i) ) = cs_fixing;
+ }
+ }
+ else
+ {
+ if ((networkgame==false) && (PlayerStatus[dest]!=player_ingame))
+ return;
+ for (i=0; i<numpackets; i+=controldivisor)
+ {
+ ServerCommandStatus( (time+i) ) = cs_fixing;
+ }
+ }
+// if (networkgame==false)
+// FixingPackets=true;
+
+ // send out the packet
+
+ WritePacket (&request, GetPacketSize(&request), dest);
+
+#if (DEVELOPMENT == 1)
+// ComError( "BADPKT, request sent at %ld lgt=%ld dest=%ld\n",GetTicCount(),time,dest);
+#endif
+}
+
+//****************************************************************************
+//
+// IsServerCommandReady ()
+//
+//****************************************************************************
+boolean IsServerCommandReady ( int time )
+{
+
+ if (
+ (
+ (COM_ServerHeaderType *)
+ ServerCommand(CommandAddress (time) ) )->time==time)
+ return true;
+ else
+ {
+ return false;
+ }
+}
+
+//****************************************************************************
+//
+// AreClientsReady ()
+//
+//****************************************************************************
+boolean AreClientsReady ( void )
+{
+ int i;
+ int timeindex;
+ int status;
+
+ timeindex=CommandAddress(serverupdatetime);
+
+ for (i=0; i<numplayers; i++)
+ {
+ if (PlayerStatus[i]!=player_ingame)
+ continue;
+ status=ClientCommandStatus(i, serverupdatetime);
+ if (status==cs_notarrived)
+ return false;
+ else if (status==cs_fixing)
+ {
+// RequestPacket ( serverupdatetime , i , controldivisor );
+ return false;
+ }
+ else if (((MoveType *)ClientCommand(i, timeindex))->time != serverupdatetime)
+ return false;
+ }
+ return true;
+}
+
+//****************************************************************************
+//
+// IsPlayerCommandReady ()
+//
+//****************************************************************************
+boolean IsPlayerCommandReady (int num, int time)
+{
+ MoveType * cmd;
+
+ cmd=(MoveType *)PlayerCommand(num,CommandAddress(time));
+
+ if (cmd->time==time)
+ return true;
+ else
+ return false;
+}
+
+//****************************************************************************
+//
+// ResetClientCommands ()
+//
+//****************************************************************************
+void ResetClientCommands ( int player )
+{
+ int j;
+
+ for (j=0; j<MAXCMDS; j++)
+ {
+ memset(ClientCommand(player,j),COM_DELTA,GamePacketSize());
+ }
+}
+
+//****************************************************************************
+//
+// SendFullServerPacket ()
+//
+//****************************************************************************
+void SendFullServerPacket ( void )
+{
+ int i;
+ int size;
+ byte * pkt;
+ COM_ServerHeaderType * spkt;
+ int timeindex;
+ int playerstatus[MAXPLAYERS];
+
+ timeindex=CommandAddress(serverupdatetime);
+
+ spkt=(COM_ServerHeaderType *)ServerCommand(timeindex);
+
+ pkt=&spkt->data;
+ spkt->time=serverupdatetime;
+ spkt->type=COM_SERVER;
+ spkt->numpackets=numplayers;
+
+
+ memset(playerstatus,-1,sizeof(playerstatus));
+ for (i=0; i<numplayers; i++)
+ {
+ size=GetPacketSize(ClientCommand(i,timeindex));
+ if (((MoveType *)ClientCommand(i,timeindex))->type == COM_QUIT)
+ {
+ playerstatus[i]=player_quitgame;
+ }
+ if (((MoveType *)ClientCommand(i,timeindex))->type == COM_ENDGAME)
+ {
+ playerstatus[i]=player_leftgame;
+ }
+ memcpy(pkt,
+ ClientCommand(i,timeindex),
+ size
+ );
+ pkt+=size;
+ ClientCommandNumberStatus(i,timeindex)=cs_notarrived;
+ }
+ BroadcastServerPacket((void *)spkt,(pkt-(byte *)spkt));
+ serverupdatetime+=controldivisor;
+
+ for (i=0; i<numplayers; i++)
+ {
+ if (playerstatus[i]!=-1)
+ {
+ if ((standalone==false) && (consoleplayer==i))
+ {
+ UpdateServer=false;
+ }
+ else
+ {
+ ResetClientCommands(i);
+ PlayerStatus[i]=playerstatus[i];
+ }
+ }
+ }
+}
+
+
+
+//****************************************************************************
+//
+// ProcessServer ()
+//
+//****************************************************************************
+
+void ProcessServer ( void )
+{
+ boolean done;
+ boolean exit;
+ int i;
+ int time;
+ int quittime;
+
+ if (InProcessServer==true)
+ return;
+
+ InProcessServer=true;
+
+ if (GetTicCount()<serverupdatetime)
+ goto exitProcessServer;
+
+ time=GetTicCount();
+ quittime=GetTicCount()+SERVERTIMEOUT;
+ exit=false;
+
+ while (time>=serverupdatetime)
+ {
+ int savetime;
+
+ savetime=GetTicCount()+NETWORKTIMEOUT;
+ done = false;
+ while (done == false)
+ {
+ if (standalone==true)
+ AbortCheck("GameServer aborted\n");
+
+ done = AreClientsReady ();
+
+ if ( (standalone==false) && (serverupdatetime>=(controlupdatetime-controldivisor)) && (done==false) )
+ break;
+
+ CheckForPacket ();
+
+ if (standalone==false)
+ UpdateClientControls();
+
+ if (restartgame==true)
+ break;
+ if (GetTicCount()>savetime)
+ {
+ for (i=0; i<numplayers; i++)
+ {
+ int val;
+
+ val=ClientCommandStatus(i, serverupdatetime);
+ if ((val!=cs_ready) && (PlayerStatus[i]==player_ingame))
+ {
+ SoftError("Server timeout\n");
+ RequestPacket(serverupdatetime, i, controldivisor);
+ }
+ }
+ savetime=GetTicCount()+NETWORKTIMEOUT;
+ }
+// if (GetTicCount()>quittime)
+// {
+// Error("Server aborting after %ld seconds\n",SERVERTIMEOUT/VBLCOUNTER);
+// }
+ if ((standalone==false) && (done==false))
+ {
+ exit=true;
+ done=true;
+ }
+ }
+ if (exit==true)
+ break;
+ if ( (serverupdatetime>=(controlupdatetime-controldivisor)) && (standalone==false))
+ break;
+ if (restartgame==true)
+ break;
+ SendFullServerPacket();
+#if 0
+ if (serverupdatetime>=syncservertime)
+ {
+ SendSyncTimePacket();
+ syncservertime+=NETSYNCSERVERTIME;
+ }
+#endif
+ }
+exitProcessServer:
+ InProcessServer=false;
+}
+
+
+//****************************************************************************
+//
+// SetupCheckForPacket()
+//
+//****************************************************************************
+int SetupCheckForPacket ( void )
+{
+ int retval=scfp_nodata;
+
+ if ((ReadPacket()==true) && (badpacket==0))
+ {
+ MoveType * pkt;
+
+ retval=scfp_data;
+ pkt=(MoveType *)&ROTTpacket[0];
+ if ((IsServer==true) && (standalone==true))
+ {
+ switch (pkt->type)
+ {
+ case COM_GAMEEND:
+ break;
+ case COM_GAMEDESC:
+ if (standalone==true)
+ printf("Received GameDescription from player#%ld\n",(long int)rottcom->remotenode);
+ WritePacket(&ROTTpacket[0],GetPacketSize(pkt),0); // Send to player 0
+ break;
+ case COM_GAMEACK:
+ if (standalone==true)
+ printf("Received GameAcknowledgement from player#%ld\n",(long int)rottcom->remotenode);
+ WritePacket(&ROTTpacket[0],GetPacketSize(pkt),0); // Send to player 0
+ break;
+ case COM_GAMEMASTER:
+ if (standalone==true)
+ printf("Received GameMasterPacket from player#%ld\n",(long int)rottcom->remotenode);
+ BroadcastServerPacket(&ROTTpacket[0],GetPacketSize(pkt)); // Send to all
+ break;
+ case COM_GAMEPLAY:
+ if (standalone==true)
+ printf("Received StartGamePacket from player#%ld\n",(long int)rottcom->remotenode);
+ BroadcastServerPacket(&ROTTpacket[0],GetPacketSize(pkt)); // Send to all
+ retval=scfp_done;
+ break;
+ default:
+ ComError("Server received unknown packet in Game preamble\n");
+ break;
+ }
+ }
+ else
+ {
+ switch (pkt->type)
+ {
+ case COM_GAMEPLAY:
+ retval=scfp_done;
+ break;
+ case COM_GAMEMASTER:
+ SetGameDescription(pkt);
+ retval=scfp_gameready;
+ break;
+ case COM_GAMEACK:
+ PlayersReady[((COM_GameAckType *)pkt)->player]=true;
+ break;
+ case COM_GAMEDESC:
+ GotPlayersDesc[((COM_GamePlayerType *)pkt)->player]=true;
+ SetPlayerDescription(pkt);
+ break;
+ }
+ }
+ }
+ return retval;
+}
+
+
+//****************************************************************************
+//
+// ServerLoop ()
+//
+//****************************************************************************
+void ServerLoop( void )
+{
+ boolean done;
+
+ while (1)
+ {
+ ShutdownClientControls();
+ restartgame=false;
+
+ done=false;
+ while (done==false)
+ {
+ AbortCheck("SetupGameServer aborted\n");
+
+ if (SetupCheckForPacket()==scfp_done)
+ done=true;
+ }
+ ComSetTime();
+ StartupClientControls();
+ while(1)
+ {
+ ProcessServer();
+#if (DEVELOPMENT == 1)
+ Z_CheckHeap();
+#endif
+ CalcTics();
+ if (restartgame==true)
+ break;
+ }
+ }
+}
+
+//****************************************************************************
+//
+// ProcessPlayerCommand()
+//
+//****************************************************************************
+void ProcessPlayerCommand( int player )
+{
+ MoveType * cmd;
+
+ cmd=(MoveType *)PlayerCommand(player,CommandAddress(oldpolltime));
+
+ if (cmd->type==COM_DELTA)
+ {
+ UpdatePlayerObj(player);
+ }
+ else if (cmd->type==COM_RESPAWN)
+ {
+ if (player==consoleplayer) // reset spawn state
+ respawnactive=false;
+ RespawnPlayerobj(PLAYER[player]);
+ }
+ else if (cmd->type==COM_ENDGAME)
+ {
+ playstate = ex_battledone;
+ }
+ else if (cmd->type==COM_QUIT)
+ {
+ if (player==consoleplayer)
+ QuitGame();
+ else
+ {
+ char str[50]="Player #";
+ char str2[10];
+
+ strcat(str,itoa(player+1,str2,10));
+ strcat(str,", ");
+ strcat(str,PLAYERSTATE[player].codename);
+ strcat(str," has left the game.");
+ AddMessage(str,MSG_REMOTE);
+ PlayerStatus[player]=player_quitgame;
+ }
+ }
+ else if (cmd->type==COM_EXIT)
+ {
+ QuitGame();
+ }
+ else if (cmd->type==COM_REMRID)
+ {
+ ProcessRemoteRidicule (cmd);
+ }
+ else if (cmd->type==COM_TEXT)
+ {
+ int who;
+
+ who = ( ( COM_TextType * )cmd )->towho;
+ if ( ( who == consoleplayer ) ||
+ ( who == MSG_DIRECTED_TO_ALL ) ||
+ ( ( who == MSG_DIRECTED_TO_TEAM ) &&
+ ( BATTLE_Team[ player ] == BATTLE_Team[ consoleplayer ] ) ) )
+ {
+ char string[ 50 ];
+
+ strcpy( string, "\\N9" );
+ strcat( string, PLAYERSTATE[player].codename );
+ strcat( string, ":\\NF" );
+ strcat( string, ((COM_TextType *)cmd)->string );
+ SD_PlayPitchedSound ( SD_ENDBONUS1SND, 255, 1200 );
+
+ AddMessage( string, MSG_REMOTE );
+ }
+ }
+#if (SYNCCHECK == 1)
+ else if (cmd->type==COM_SYNCCHECK)
+ {
+ ProcessSyncCheckPacket(cmd, player);
+ }
+#endif
+ else if (cmd->type==COM_PAUSE)
+ {
+ MUSIC_Pause();
+ GamePaused=true;
+ pausedstartedticcount = oldpolltime;
+ }
+ else if (cmd->type==COM_UNPAUSE)
+ {
+ GamePaused=false;
+ MUSIC_Continue ();
+ if (RefreshPause == false) // screen is blanked
+ {
+ ShutdownScreenSaver();
+ SetupScreen (true);
+ RefreshPause = true;
+ }
+ }
+}
+
+//****************************************************************************
+//
+// CheckUnPause ()
+//
+//****************************************************************************
+void CheckUnPause ( void )
+{
+ if (oldpolltime==nextupdatetime)
+ {
+ nextupdatetime=oldpolltime+controldivisor;
+ while (1)
+ {
+ if (ServerCommandStatus(oldpolltime)==cs_ready)
+ {
+ int j;
+
+ for (j=0; j<numplayers; j++)
+ {
+ if (PlayerStatus[j]==player_ingame)
+ ProcessPlayerCommand( j );
+ }
+ break;
+ }
+ else
+ {
+ UpdateClientControls();
+ }
+ }
+ }
+}
+
+
+//****************************************************************************
+//
+// ControlPlayerObj ()
+//
+//****************************************************************************
+void ControlPlayerObj (objtype * ob)
+{
+ playertype * pstate;
+ int num;
+ int savetime;
+// boolean asked;
+
+// if (GamePaused==true)
+// return;
+
+ M_LINKSTATE(ob,pstate);
+
+ // get player number
+
+ num=ob->dirchoosetime;
+
+ memcpy (pstate->buttonheld, pstate->buttonstate, sizeof(pstate->buttonstate));
+
+ if (oldpolltime==nextupdatetime)
+ {
+ if (num==numplayers-1)
+ nextupdatetime=oldpolltime+controldivisor;
+ if (networkgame==true)
+ savetime=GetTicCount()+NETWORKTIMEOUT;
+ else
+ savetime=GetTicCount()+MODEMTIMEOUT;
+
+ if (PlayerStatus[num]!=player_ingame)
+ return;
+
+ // asked=false;
+
+ // copy previous state of buttons
+
+
+ while (1)
+ {
+ if (ServerCommandStatus(oldpolltime)==cs_ready)
+ {
+ ProcessPlayerCommand (num);
+ if (demoplayback||demorecord) {
+ SoftError("x=%4x y=%4x a=%4x time=%5d\n",player->x,player->y,player->angle,oldpolltime);
+ }
+ break;
+ }
+ // else if ((ServerCommandStatus(oldpolltime)==cs_fixing) &&
+ // (networkgame==false) &&
+ // (asked==false)
+ // )
+ // {
+ // asked=true;
+ // RequestPacket(oldpolltime, server, controldivisor);
+ // }
+ else
+ {
+ UpdateClientControls();
+ }
+
+ if (GetTicCount()>savetime)
+ {
+ SoftError("Client timeout oldpolltime=%d\n",oldpolltime);
+ if (IsServer==false)
+ RequestPacket(oldpolltime, server, controldivisor);
+ if (networkgame==true)
+ savetime=GetTicCount()+NETWORKTIMEOUT;
+ else
+ savetime=GetTicCount()+MODEMTIMEOUT;
+ }
+ }
+ }
+
+ if (!(ob->flags&FL_DYING))
+ {
+ if (ob->flags&FL_PUSHED)
+ {
+ ob->flags&=~FL_PUSHED;
+#if 0
+ if (abs(ob->momentumx)>0)
+ {
+ if (abs(ob->momentumx+pstate->dmomx)>=abs(ob->momentumx))
+ {
+ ob->momentumx += pstate->dmomx;
+ ob->momentumy += pstate->dmomy;
+ }
+ }
+ else if (abs(ob->momentumy+pstate->dmomy)>=abs(ob->momentumy))
+ {
+ ob->momentumx += pstate->dmomx;
+ ob->momentumy += pstate->dmomy;
+ }
+#endif
+ if (abs(ob->momentumx+pstate->dmomx)>=abs(ob->momentumx))
+ {
+ ob->momentumx += pstate->dmomx;
+ }
+ if (abs(ob->momentumy+pstate->dmomy)>=abs(ob->momentumy))
+ {
+ ob->momentumy += pstate->dmomy;
+ }
+ }
+ else
+ {
+ ob->momentumx += pstate->dmomx;
+ ob->momentumy += pstate->dmomy;
+ }
+ }
+}
+
+//****************************************************************************
+//
+// MaxSpeedForCharacter ()
+//
+//****************************************************************************
+
+int MaxSpeedForCharacter(playertype*pstate)
+{
+ if (BATTLEMODE && (gamestate.BattleOptions.Speed == bo_fast_speed))
+ {
+ return( FASTSPEED );
+ }
+ else
+ {
+ if (pstate->buttonstate[bt_run])
+ return (characters[pstate->player].toprunspeed);
+ else
+ return (characters[pstate->player].topspeed);
+ }
+}
+
+//****************************************************************************
+//
+// UpdatePlayerObj ()
+//
+//****************************************************************************
+
+void UpdatePlayerObj ( int player )
+{
+ int i, buttonbits;
+ playertype * pstate;
+ MoveType * MoveCmd;
+
+ MoveCmd=(MoveType *)PlayerCommand(player,CommandAddress(oldpolltime));
+
+ pstate=&PLAYERSTATE[player];
+
+ buttonbits = MoveCmd->buttons;
+ for (i = 0; i < NUMTXBUTTONS; i++)
+ {
+ pstate->buttonstate[i] = buttonbits & 1;
+ buttonbits >>= 1;
+ }
+
+ pstate->dmomx = (int)(MoveCmd->momx)<<1;
+ pstate->dmomy = (int)(MoveCmd->momy)<<1;
+ pstate->angle = MoveCmd->dangle;
+ pstate->angle <<= 11;
+ pstate->topspeed=MaxSpeedForCharacter(pstate);
+
+ if (demoplayback||demorecord) {
+ SoftError(" dmx=%4x dmy=%4x da=%4x time=%5d\n",pstate->dmomx,pstate->dmomy,pstate->angle>>11,oldpolltime);
+ }
+#if 0
+#if (DEVELOPMENT == 1)
+ if ((modemgame==true) || (demoplayback==true) || (demorecord==true))
+ {
+ ComError( "player#%2ld\n",player);
+ ComError( "momx = %6ld\n", PLAYER[player]->momentumx);
+ ComError( "momy = %6ld\n", PLAYER[player]->momentumy);
+ ComError( " x = %6ld\n", PLAYER[player]->x);
+ ComError( " y = %6ld\n", PLAYER[player]->y);
+ ComError( " z = %6ld\n", PLAYER[player]->z);
+ ComError( " a = %6ld\n", PLAYER[player]->angle);
+ if (pstate->buttonstate[bt_attack])
+ ComError( "FIRING\n");
+ }
+#endif
+#endif
+}
+
+
+//****************************************************************************
+//
+// SendPlayerDescription ()
+//
+//****************************************************************************
+
+void SendPlayerDescription( void )
+{
+ byte * temp;
+ COM_GamePlayerType * desc;
+ int length;
+
+ length=sizeof(COM_GamePlayerType);
+ temp=SafeMalloc(length);
+
+ memset(temp,0,length);
+
+ desc=(COM_GamePlayerType *)temp;
+ desc->type=(byte)COM_GAMEDESC;
+ desc->player=consoleplayer;
+ desc->violence=gamestate.violence;
+ desc->Version = gamestate.Version;
+ desc->Product = gamestate.Product;
+ desc->playerdescription.character=locplayerstate->player;
+ desc->playerdescription.uniformcolor=locplayerstate->uniformcolor;
+ strcpy(&(desc->playerdescription.codename[0]),
+ &locplayerstate->codename[0]);
+
+ WritePacket(temp,length,server);
+
+ SafeFree(temp);
+}
+
+//****************************************************************************
+//
+// SendGameDescription ()
+//
+//****************************************************************************
+
+void SendGameDescription( void )
+{
+ byte * temp;
+ COM_GameMasterType * desc;
+ int length;
+ int i;
+
+ length=sizeof(COM_GameMasterType);
+ temp=SafeMalloc(length);
+
+ memset(temp,0,length);
+
+ desc=(COM_GameMasterType *)temp;
+ desc->type=(byte)COM_GAMEMASTER;
+ desc->level=gamestate.mapon;
+ desc->mapcrc=GetMapCRC (gamestate.mapon);
+ desc->mode=gamestate.battlemode;
+ desc->violence=gamestate.violence;
+ desc->Version = gamestate.Version;
+ desc->Product = gamestate.Product;
+ desc->teamplay = gamestate.teamplay;
+ memcpy( &desc->SpecialsTimes, &gamestate.SpecialsTimes, sizeof( specials ) );
+ BATTLE_GetOptions( &( desc->options ) );
+ GetMapFileName( &(desc->battlefilename[0]) );
+ desc->randomseed=GetRNGindex ( );
+ gamestate.randomseed=desc->randomseed;
+ desc->ludicrousgibs=battlegibs;
+ ludicrousgibs=battlegibs;
+// SetRNGindex ( gamestate.randomseed );
+ for (i=0; i<numplayers; i++)
+ {
+ if (gamestate.Product == ROTT_SHAREWARE)
+ PLAYERSTATE[i].player = 0;
+ desc->players[i].character =PLAYERSTATE[i].player;
+ desc->players[i].uniformcolor =PLAYERSTATE[i].uniformcolor;
+ strcpy ( &(desc->players[i].codename[0]),&(PLAYERSTATE[i].codename[0]));
+ }
+
+ if (!networkgame)
+ AssignTeams();
+
+ if (IsServer==false)
+ {
+ WritePacket(temp,length,server);
+ }
+ else
+ {
+ BroadcastServerPacket(temp,length); // Send to all
+ }
+
+ SafeFree(temp);
+}
+
+//****************************************************************************
+//
+// SetGameDescription ()
+//
+//****************************************************************************
+
+void SetGameDescription( void * pkt )
+{
+ COM_GameMasterType * desc;
+ word localcrc;
+ int i;
+
+ desc=(COM_GameMasterType *)pkt;
+ gamestate.mapon=desc->level;
+ gamestate.battlemode=desc->mode;
+ gamestate.violence=desc->violence;
+ gamestate.Version = desc->Version;
+ gamestate.Product = desc->Product;
+ gamestate.teamplay = desc->teamplay;
+ memcpy( &gamestate.SpecialsTimes, &desc->SpecialsTimes, sizeof( specials ) );
+ BATTLE_SetOptions( &( desc->options ) );
+ gamestate.randomseed=desc->randomseed;
+ SetRNGindex ( gamestate.randomseed );
+ SetBattleMapFileName( &(desc->battlefilename[0]) );
+ localcrc=GetMapCRC (gamestate.mapon);
+ ludicrousgibs=desc->ludicrousgibs;
+ if (localcrc!=desc->mapcrc)
+ Error("You have different maps on your system\n");
+ for (i=0; i<numplayers; i++)
+ {
+ PLAYERSTATE[i].player=desc->players[i].character;
+ PLAYERSTATE[i].uniformcolor=desc->players[i].uniformcolor;
+ strcpy ( &(PLAYERSTATE[i].codename[0]),
+ &(desc->players[i].codename[0])
+ );
+ }
+ AssignTeams();
+}
+
+//****************************************************************************
+//
+// SetPlayerDescription ()
+//
+//****************************************************************************
+
+void SetPlayerDescription( void * pkt )
+{
+ COM_GamePlayerType * desc;
+
+ desc=(COM_GamePlayerType *)pkt;
+ PLAYERSTATE[desc->player].player=desc->playerdescription.character;
+ PLAYERSTATE[desc->player].uniformcolor=desc->playerdescription.uniformcolor;
+ strcpy ( &(PLAYERSTATE[desc->player].codename[0]),
+ &(desc->playerdescription.codename[0])
+ );
+ if ( gamestate.Version != desc->Version )
+ {
+ Error("Player %s is using a different version of ROTT\n",PLAYERSTATE[desc->player].codename);
+// gamestate.Version = desc->Version;
+ }
+
+ if ( gamestate.violence > desc->violence )
+ {
+ gamestate.violence = desc->violence;
+ }
+
+ if ( gamestate.Product > desc->Product )
+ {
+ gamestate.Product = desc->Product;
+ }
+}
+
+//****************************************************************************
+//
+// SendGameAck ()
+//
+//****************************************************************************
+
+void SendGameAck( void )
+{
+ byte * temp;
+ int length;
+ COM_GameAckType * desc;
+
+ length=sizeof(COM_GameAckType);
+ temp=SafeMalloc(length);
+ desc=(COM_GameAckType *)temp;
+ desc->type=COM_GAMEACK;
+ desc->player=consoleplayer;
+
+ WritePacket(temp,length,server);
+
+ SafeFree(temp);
+}
+
+//****************************************************************************
+//
+// SendGameStart ()
+//
+//****************************************************************************
+
+void SendGameStart( void )
+{
+ byte * temp;
+ int length;
+
+ length=DUMMYPACKETSIZE;
+ temp=SafeMalloc(length);
+ *(temp)=(byte)COM_GAMEPLAY;
+
+ if (IsServer==false)
+ {
+ WritePacket(temp,length,server);
+ }
+ else
+ {
+ BroadcastServerPacket(temp,length); // Send to all
+ }
+
+ SafeFree(temp);
+}
+
+//****************************************************************************
+//
+// SetupGamePlayer ()
+//
+//****************************************************************************
+void SetupGamePlayer ( void )
+{
+ int savetime;
+ boolean done;
+ boolean gameready;
+
+ savetime=GetTicCount();
+
+ done=false;
+ gameready=false;
+
+ while (done==false)
+ {
+ // Setup individual player
+ AbortCheck("SetupGamePlayer aborted\n");
+
+ // send Player Description
+ if (GetTicCount() >= savetime)
+ {
+ savetime=GetTicCount()+SETUPTIME;
+ if (gameready==false)
+ SendPlayerDescription();
+ else
+ SendGameAck();
+ }
+ switch (SetupCheckForPacket())
+ {
+ case scfp_done:
+ done=true;
+ break;
+ case scfp_gameready:
+ gameready=true;
+ break;
+ }
+ }
+ savetime=GetTicCount()+(VBLCOUNTER/2);
+
+ while (GetTicCount()<savetime)
+ {
+ SetupCheckForPacket ();
+ }
+}
+
+//****************************************************************************
+//
+// AllPlayersReady ()
+//
+//****************************************************************************
+boolean AllPlayersReady ( void )
+{
+ int i;
+
+ for (i=0; i<numplayers; i++)
+ if ((PlayersReady[i]==false) && (PlayerStatus[i]==player_ingame))
+ return false;
+
+ return true;
+}
+
+//****************************************************************************
+//
+// GotAllPlayerDescriptions ()
+//
+//****************************************************************************
+boolean GotAllPlayerDescriptions ( void )
+{
+ int i;
+
+ for (i=0; i<numplayers; i++)
+ if ((GotPlayersDesc[i]==false) && (PlayerStatus[i]==player_ingame))
+ return false;
+
+ return true;
+}
+
+//****************************************************************************
+//
+// SetupGameMaster ()
+//
+//****************************************************************************
+void SetupGameMaster ( void )
+{
+ int savetime;
+ boolean done;
+
+ memset(GotPlayersDesc,false,sizeof(GotPlayersDesc));
+ GotPlayersDesc[consoleplayer]=true;
+
+ memset(PlayersReady,false,sizeof(PlayersReady));
+ PlayersReady[consoleplayer]=true;
+
+ savetime=GetTicCount();
+
+ done=false;
+
+ InitializeRNG ();
+
+ while (done==false)
+ {
+ // Setup individual player
+
+ AbortCheck("SetupGameMaster aborted\n");
+
+ // send Game Description
+ if (GetTicCount() >= savetime)
+ {
+ savetime=GetTicCount()+SETUPTIME;
+ if (GotAllPlayerDescriptions()==true)
+ SendGameDescription();
+ }
+ if (AllPlayersReady ()==true)
+ {
+ SendGameStart();
+ SendGameStart();
+ done=true;
+ }
+ SetupCheckForPacket();
+ }
+ savetime=GetTicCount()+(VBLCOUNTER/2);
+
+ while (GetTicCount()<savetime)
+ {
+ SetupCheckForPacket ();
+ }
+}
+
+
+
+
+
+
+
+
+
+
+/*
+=============================================================================
+
+ DEMO CODE
+
+=============================================================================
+*/
+//****************************************************************************
+//
+// GetDemoFilename ()
+//
+//****************************************************************************
+
+void GetDemoFilename (int demonumber, char * filename)
+{
+ strcpy(filename,DATADIR "DEMO0_0.DMO\0");
+
+ filename[4 + strlen(DATADIR)] = (char)('0' + (byte)demonumber);
+ filename[6 + strlen(DATADIR)] = (char)('0' + (byte)gamestate.violence);
+ FixFilePath(filename);
+}
+//****************************************************************************
+//
+// DemoExists ()
+//
+//****************************************************************************
+
+boolean DemoExists (int demonumber)
+{
+ char demo[20 + sizeof(DATADIR)];
+
+ GetDemoFilename (demonumber, &demo[0]);
+ if (access (demo, F_OK) == 0)
+ return true;
+ else
+ {
+ /* Saves the users violence level, only do this once, otherwise
+ we might override the saved level with one already modified by us */
+ if (predemo_violence == -1)
+ predemo_violence = gamestate.violence;
+ /* The demos distributed with rott are all for a violence level of 3 */
+ gamestate.violence = 3;
+ GetDemoFilename (demonumber, &demo[0]);
+ if (access (demo, F_OK) == 0)
+ return true;
+ else
+ return false;
+ }
+}
+
+//****************************************************************************
+//
+// SaveDemo ()
+//
+//****************************************************************************
+
+void SaveDemo (int demonumber)
+{
+ char demo[20 + sizeof(DATADIR)];
+
+ RecordDemoCmd ();
+ GetDemoFilename (demonumber, &demo[0]);
+ SaveFile (demo, demobuffer, (demoptr-demobuffer));
+ FreeDemo();
+}
+
+//****************************************************************************
+//
+// LoadDemo ()
+//
+//****************************************************************************
+
+void LoadDemo (int demonumber)
+{
+ char demo[20 + sizeof(DATADIR)];
+ int size;
+
+ GetDemoFilename (demonumber, demo);
+ if (demobuffer!=NULL)
+ FreeDemo();
+ size = LoadFile (demo, (void **)&demobuffer);
+ playstate = ex_demoplayback;
+ demoptr = demobuffer;
+ lastdemoptr = (demoptr+size);
+ locplayerstate->player=0;
+ InitializeWeapons(locplayerstate);
+ ResetPlayerstate(locplayerstate);
+ InitCharacter();
+}
+
+//****************************************************************************
+//
+// RecordDemo ()
+//
+//****************************************************************************
+
+void RecordDemo ( void )
+{
+ DemoHeaderType * DemoHeader;
+ int level;
+
+ if (demobuffer!=NULL)
+ FreeDemo();
+ godmode=0;
+ demobuffer = SafeMalloc (DEMOBUFFSIZE);
+ demoptr = demobuffer;
+ lastdemoptr = demobuffer+DEMOBUFFSIZE;
+
+ // Save off level number
+
+ DemoHeader=(DemoHeaderType *)demoptr;
+ demoptr+=sizeof(gamestate);
+ memcpy(&(DemoHeader->demostate),&gamestate,sizeof(gamestate));
+ demorecord = true;
+ locplayerstate->player=0;
+ InitializeWeapons(locplayerstate);
+ ResetPlayerstate(locplayerstate);
+ level=gamestate.mapon;
+ InitCharacter();
+ gamestate.mapon=level;
+ SoftError(">>>>>>>>>>>>Start demo record\n");
+}
+
+//****************************************************************************
+//
+// SetupDemo ()
+//
+//****************************************************************************
+
+void SetupDemo ( void )
+{
+ DemoHeaderType * DemoHeader;
+
+ demoplayback = true;
+ godmode=0;
+
+ DemoHeader=(DemoHeaderType *)demoptr;
+ demoptr+=sizeof(gamestate);
+// if (gamestate.violence!=DemoHeader->demostate.violence)
+// Error ("This demo has a different difficulty level than your current settings\n");
+ memcpy(&gamestate,&(DemoHeader->demostate),sizeof(gamestate));
+ SoftError(">>>>>>>>>>>>Start demo playback\n");
+}
+
+//****************************************************************************
+//
+// FreeDemo ()
+//
+//****************************************************************************
+
+void FreeDemo ( void )
+{
+ demoplayback = false;
+ demorecord = false;
+ SafeFree (demobuffer);
+ demobuffer=NULL;
+}
+
+//****************************************************************************
+//
+// CheckForDemoDone ()
+//
+//****************************************************************************
+
+void CheckForDemoDone ( void )
+{
+ if ((demoplayback==true) && (demoptr >= lastdemoptr))
+ {
+ FreeDemo();
+ playstate = ex_demodone;
+ }
+}
+
+//****************************************************************************
+//
+// CheckForDemoOverflowed ()
+//
+//****************************************************************************
+
+void CheckForDemoOverflowed ( void )
+{
+ if (demoptr >= (lastdemoptr-sizeof(DemoType)))
+ {
+ playstate = ex_completed; // demo is done
+ EndDemo();
+ }
+}
+
+//****************************************************************************
+//
+// RecordDemoCmd ()
+//
+//****************************************************************************
+
+void RecordDemoCmd (void)
+{
+ DemoType * dtime;
+
+ SoftError("Demo command recorded at %d\n",controlupdatetime);
+ dtime=(DemoType *)demoptr;
+ dtime->time = controlupdatetime;
+ dtime->momx = (controlbuf[0]>>1);
+ dtime->momy = (controlbuf[1]>>1);
+ dtime->dangle = controlbuf[2]>>11;
+ dtime->buttons = buttonbits;
+
+ demoptr+=sizeof(DemoType);
+
+ CheckForDemoOverflowed();
+}
+
+//****************************************************************************
+//
+// AddDemoCmd ()
+//
+//****************************************************************************
+
+void AddDemoCmd (void)
+{
+ DemoType * dtime;
+
+ //
+ // get info from demo buffer
+ //
+
+ SoftError("Demo command played at %d\n",controlupdatetime);
+ if (demoplayback==true)
+ {
+ dtime=(DemoType *)demoptr;
+ controlbuf[0]=dtime->momx<<1;
+ controlbuf[1]=dtime->momy<<1;
+ controlbuf[2]=dtime->dangle<<11;
+ buttonbits =dtime->buttons;
+ demoptr+=sizeof(DemoType);
+ }
+}
+
+//****************************************************************************
+//
+// GetNextDemoTime ()
+//
+//****************************************************************************
+
+int GetNextDemoTime (void)
+{
+ DemoType * dtime;
+
+ CheckForDemoDone();
+ dtime=(DemoType *)demoptr;
+ if (demoplayback)
+ return dtime->time;
+ else
+ return -1;
+}
+
+//****************************************************************************
+//
+// UpdateDemoPlayback ()
+//
+//****************************************************************************
+
+void UpdateDemoPlayback (int time)
+{
+ if (demoplayback)
+ {
+ if (GetNextDemoTime()==time)
+ AddDemoCmd();
+ }
+}
+
+
+
+
+
--- /dev/null
+++ b/rott/rt_net.h
@@ -1,0 +1,331 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// RT_NET.H - Network stuff
+//
+//***************************************************************************
+
+#ifndef _rt_net_public
+#define _rt_net_public
+
+#include "develop.h"
+#include "rottnet.h"
+#include "rt_actor.h"
+#include "rt_battl.h"
+#include "rt_playr.h"
+#include "rt_main.h"
+
+
+#define MAXCMDS 256
+
+#define COM_DELTA 1
+#define COM_REQUEST 2
+#define COM_FIXUP 3
+#define COM_TEXT 4
+#define COM_PAUSE 5
+#define COM_QUIT 6
+#define COM_SYNC 7
+#define COM_REMRID 8
+#define COM_RESPAWN 10
+#define COM_UNPAUSE 11
+#define COM_SERVER 12
+#define COM_START 13
+#define COM_GAMEDESC 15
+#define COM_GAMEPLAY 16
+#define COM_GAMEMASTER 17
+#define COM_GAMEACK 18
+#define COM_ENDGAME 19
+#define COM_SYNCTIME 20
+#if (SYNCCHECK==1)
+#define COM_SYNCCHECK 21
+#endif
+#define COM_SOUNDANDDELTA 22
+#define COM_EXIT 23
+#define COM_GAMEEND 24
+#define COM_DELTANULL 25
+
+#define CHECKSYNCTIME (VBLCOUNTER<<2)
+
+#define NETSYNCSERVERTIME (VBLCOUNTER)
+#define MODEMSYNCSERVERTIME (VBLCOUNTER/4)
+
+#define DUMMYPACKETSIZE 20
+
+
+#define COM_MAXTEXTSTRINGLENGTH 33
+
+// Sound defines for Remote ridicule
+
+#define COM_SOUND_START_TRANSMISSION (0xff)
+#define COM_SOUND_END_TRANSMISSION (0xfe)
+#define COM_SOUND_NORMAL_TRANSMISSION (0xfd)
+#define COM_SOUND_BUFFERSIZE 256
+
+// Demo Delta Structure
+typedef struct DemoType {
+ int time;
+ short momx;
+ short momy;
+ word dangle;
+ word buttons;
+} DemoType;
+
+// Demo Header Structure
+typedef struct DemoHeaderType {
+ gametype demostate;
+} DemoHeaderType;
+
+// Movement Queue Structure
+typedef struct MoveType {
+ byte type;
+ int time;
+ short momx;
+ short momy;
+ word dangle;
+ word buttons;
+ char Sounddata[0];
+} MoveType;
+
+typedef struct NullMoveType {
+ byte type;
+ int time;
+} NullMoveType;
+
+typedef struct {
+
+ void * Commands[MAXCMDS];
+
+} CommandType;
+
+typedef struct {
+
+ byte CommandStates[MAXCMDS];
+
+} CommandStatusType;
+
+typedef MoveType COM_SoundAndDeltaType;
+
+// uncomment for live remote ridicule
+typedef struct {
+ byte type;
+ byte data[COM_SOUND_BUFFERSIZE];
+// char data[COM_MAXTEXTSTRINGLENGTH];
+} COM_SoundType;
+
+typedef struct {
+ byte type;
+ int synctime;
+} COM_SyncType;
+
+typedef struct {
+ byte type;
+ int time;
+ int synctime;
+ int x;
+ int y;
+ int z;
+ word angle;
+ word randomindex;
+} COM_CheckSyncType;
+
+typedef struct {
+ byte type;
+ int time;
+ byte numpackets;
+ byte data;
+} COM_ServerHeaderType;
+
+typedef struct {
+ byte type;
+ int time;
+ byte numpackets;
+} COM_RequestType;
+
+typedef struct {
+ byte type;
+ int time;
+ byte towho;
+ char string[COM_MAXTEXTSTRINGLENGTH];
+} COM_TextType;
+
+#define MSG_DIRECTED_TO_ALL 255
+#define MSG_DIRECTED_TO_TEAM 254
+
+typedef struct {
+ byte type;
+ int time;
+ byte player;
+ byte num;
+ byte towho;
+} COM_RemoteRidiculeType;
+
+typedef struct {
+ byte type;
+ int time;
+ byte numpackets;
+ byte data;
+} COM_FixupType;
+
+typedef struct {
+ byte type;
+ int time;
+} COM_QuitType;
+
+typedef struct {
+ byte type;
+ int time;
+} COM_ExitType;
+
+typedef struct {
+ byte type;
+ int time;
+} COM_GameEndType;
+
+typedef struct {
+ byte character; // which character
+ byte uniformcolor; // which color
+ char codename[MAXCODENAMELENGTH]; // codename
+} COM_PlayerDescriptionType;
+
+typedef struct {
+ byte type;
+ byte player; // which player
+ byte violence;
+ byte Product;
+ unsigned Version;
+
+ COM_PlayerDescriptionType playerdescription;
+} COM_GamePlayerType;
+
+typedef struct {
+ byte type;
+ byte level;
+ word mapcrc;
+ byte violence;
+ byte Product;
+ byte mode;
+ unsigned Version;
+ boolean teamplay;
+ specials SpecialsTimes;
+ battle_type options;
+ char battlefilename[20];
+ int randomseed;
+ boolean ludicrousgibs;
+ COM_PlayerDescriptionType players[MAXPLAYERS];
+} COM_GameMasterType;
+
+typedef struct {
+ byte type;
+ byte player; // which player
+} COM_GameAckType;
+
+typedef struct {
+ byte type;
+ int time;
+} COM_EndGameType;
+
+typedef struct {
+ byte type;
+ int time;
+} COM_RespawnType;
+
+typedef struct {
+ byte type;
+ int time;
+} COM_PauseType;
+
+typedef struct {
+ byte type;
+ int time;
+} COM_UnPauseType;
+
+extern boolean demorecord,
+ demoplayback;
+extern byte *demoptr,
+ *lastdemoptr,
+ *demobuffer;
+extern boolean demodone;
+extern int predemo_violence;
+
+void ControlPlayer (void);
+void ControlRemote (objtype * ob);
+void ControlPlayerObj (objtype * ob);
+void InitializeGameCommands( void );
+void ShutdownGameCommands( void );
+void UpdateClientControls ( void );
+void StartupClientControls ( void );
+void ShutdownClientControls ( void );
+void ProcessServer ( void );
+void ServerLoop( void );
+void SendPlayerDescription( void );
+void SetGameDescription( void * pkt );
+void SendGameDescription( void );
+void SendGameAck( void );
+void SendGameStart( void );
+void SetupGamePlayer ( void );
+void SetupGameMaster ( void );
+void SetNormalHorizon (objtype * ob);
+void SaveDemo (int demonumber);
+void LoadDemo (int demonumber);
+void RecordDemo ( void );
+void SetupDemo ( void );
+void FreeDemo ( void );
+boolean DemoExists (int demonumber);
+
+void AddEndGameCommand ( void );
+void AddTextMessage ( char * message, int length, int towho );
+void AddEndGameCommand ( void );
+void AddPauseStateCommand ( int type );
+void AddRespawnCommand ( void );
+void RecordDemoCmd (void);
+void ResetCurrentCommand ( void );
+void AddRemoteRidiculeCommand ( int player, int towho, int num );
+void ProcessRemoteRidicule ( void * pkt );
+void SyncToServer( void );
+void AddQuitCommand ( void );
+void AddExitCommand ( void );
+void AddGameEndCommand ( void );
+boolean PlayerInGame ( int p );
+boolean ConsoleIsServer ( void );
+
+extern boolean IsServer;
+extern boolean standalone;
+extern boolean playerdead;
+
+extern boolean modemgame;
+extern boolean networkgame;
+extern int numplayers;
+extern int server;
+
+extern boolean GamePaused;
+extern boolean battlegibs;
+
+extern boolean remoteridicule;
+
+#if (SYNCCHECK==1)
+extern int lastsynccheck;
+extern COM_CheckSyncType PlayerSync[MAXPLAYERS];
+void CheckForSyncCheck ( void );
+#endif
+
+int GamePacketSize( void );
+
+#endif
--- /dev/null
+++ b/rott/rt_playr.c
@@ -1,0 +1,6497 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#ifdef DOS
+#include <dos.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "rt_def.h"
+#include "watcom.h"
+#include "rt_sound.h"
+#include "gmove.h"
+#include "states.h"
+#include "rt_sqrt.h"
+#include "rt_actor.h"
+#include "rt_main.h"
+#include "rt_playr.h"
+#include "isr.h"
+#include "rt_draw.h"
+#include "rt_ted.h"
+#include "rt_door.h"
+#include "rt_menu.h"
+#include "rt_view.h"
+#include "rt_com.h"
+#include "rt_in.h"
+#include "rt_util.h"
+#include "rt_game.h"
+#include "rt_rand.h"
+#include "z_zone.h"
+#include "rt_swift.h"
+#include "engine.h"
+#include "_rt_play.h"
+#include "rt_cfg.h"
+#include "rt_spbal.h"
+#include "rt_floor.h"
+#include "develop.h"
+#include "rt_msg.h"
+#include "rt_debug.h"
+#include "sprites.h"
+#include "rt_net.h"
+#include "rt_dmand.h"
+//MED
+#include "memcheck.h"
+
+
+#define FLYINGZMOM 350000
+
+
+#if (DEVELOPMENT == 1)
+#include "rt_str.h"
+#endif
+
+extern boolean usejump;
+
+
+specials CurrentSpecialsTimes =
+{
+ 60*VBLCOUNTER, // god
+ 60*VBLCOUNTER, // dog
+ 20*VBLCOUNTER, // shrooms
+ 20*VBLCOUNTER, // elasto
+ 60*VBLCOUNTER, // asbestos vest
+ 60*VBLCOUNTER, // bullet proof vest
+ GASTICS, // gas mask
+ 60*VBLCOUNTER, // mercury mode
+
+ 300*VBLCOUNTER, // god respawn
+ 60*VBLCOUNTER, // dog respawn
+ 60*VBLCOUNTER, // shrooms respawn
+ 60*VBLCOUNTER, // elasto respawn
+ 60*VBLCOUNTER, // asbestos vest respawn
+ 60*VBLCOUNTER, // bullet proof vest respawn
+ 60*VBLCOUNTER, // gas mask respawn
+ 60*VBLCOUNTER // mercury mode respawn
+};
+
+int GRAVITY = NORMAL_GRAVITY;
+
+ROTTCHARS characters[5]= {
+ {0x2100,0x4800,100,2,25}, // Taradino Cassatt
+ {0x2200,0x5200,85,3,32}, // Thi Barrett
+ {0x1f00,0x4000,150,3,20}, // Doug Wendt
+ {0x2300,0x5500,70,2,33}, // Lorelei Ni
+ {0x2000,0x4400,120,3,25}
+}; // Ian Paul Freeley
+
+static const int TD = MINACTORDIST+0x1000;
+static const int STRAFEAMOUNT = ((KEYBOARDNORMALTURNAMOUNT >> 10) + (KEYBOARDNORMALTURNAMOUNT >> 12));
+
+
+static const int GODYZANGLE = -(9*FINEANGLES/360);
+static const int DOGYZANGLE = (4*FINEANGLES/360);
+static const int SHROOMYZANGLE = (15*FINEANGLES/360);
+static const int FALLINGYZANGLE = -(15*FINEANGLES/360);
+static const int NORMALYZANGLE = 0;
+
+
+/*
+=============================================================================
+
+ GLOBAL VARIABLES
+
+=============================================================================
+*/
+
+int controlbuf[3];
+int buttonbits;
+extern _2Dpoint LASTSOUND;
+//
+// player state info
+//
+
+statobj_t *DEADPLAYER[MAXDEAD];
+int NUMDEAD;
+int lastpolltime;
+
+statobj_t *BulletHoles[MAXBULLETS];
+int BulletHoleNum;
+
+objtype *PLAYER[MAXPLAYERS],*player;
+playertype PLAYERSTATE[MAXPLAYERS],*locplayerstate;
+
+gametype gamestate;
+
+boolean godmode = false;
+
+boolean missilecam=false;
+objtype * missobj=NULL;
+// Player control variables
+
+int KX = 0;
+int KY = 0;
+int MX = 0;
+int MY = 0;
+int JX = 0;
+int JY = 0;
+int CX = 0;
+int CY = 0;
+boolean vrenabled = false;
+int VX = 0;
+int VY = 0;
+
+int oldcyberx = 0;
+int oldcybery = 0;
+int CYBERDEADRANGE = 6000;
+boolean CYBERLOOKUP,CYBERLOOKDOWN;
+
+int leftmom = 0;
+int rightmom = 0;
+int lastmom = 0;
+int first = 1;
+
+int pausedstartedticcount;
+boolean RefreshPause = true;
+
+boolean buttonpoll[NUMBUTTONS];
+
+int buttonscan[NUMBUTTONS] = {sc_Control, sc_Alt, sc_RShift, sc_Space,
+ sc_PgUp,sc_PgDn,sc_Enter,sc_Delete,
+ sc_Home,sc_End,sc_1,sc_2,sc_3,sc_4,
+ sc_CapsLock, sc_F12,
+ sc_Comma,sc_Period,sc_BackSpace,sc_A,
+ sc_UpArrow, sc_RightArrow,
+ sc_DownArrow, sc_LeftArrow,
+ sc_Tab, sc_T, sc_Z
+ };
+
+int joyxmax = 0, joyymax = 0, joyxmin = 0, joyymin = 0;
+
+int buttonmouse[6] = {bt_attack, bt_strafe, di_north,
+ bt_nobutton, bt_use, bt_nobutton
+ };
+
+int buttonjoy[8] = {bt_attack, bt_strafe, bt_run, bt_use,
+ bt_nobutton, bt_nobutton, bt_nobutton, bt_nobutton
+ };
+
+williamdidthis FREE = {84,5,0,0,9,{{done,2,1},{done,2,2},{done,2,3},
+ {done,2,4},{done,2,5},{done,2,6},{done,2,7},{done,2,8},
+ {reset,2,9}
+ }
+};
+
+williamdidthis DOGSCRATCH = {128,5,0,0,4,{{done,2,8},{at_pulltrigger,2,9},{done,2,10},
+ {reset,2,11}
+ }
+};
+
+williamdidthis DOGLICK = {128,5,0,0,4,{{done,2,4},{done,2,5},{done,2,6},
+ {reset,2,7}
+ }
+};
+
+
+williamdidthis WEAPONS[MAXWEAPONS] =
+
+{
+ {100,-1,10,0x2000l,3,{{at_pulltrigger,4,1},{done,4,2},{reset,4,0}}}, //single pistol
+ { 100,-1,10,0x2000l,6,{{at_pulltrigger,2,1},{done,2,2},{done,2,3},
+ {at_pulltrigger,2,4},{done,2,5},{reset,2,3}
+ }
+ }, // double pistol
+ {70,-1,10,0x2000l,2,{{at_pulltrigger,2,1},{reset,1,2}}}, //mp 40
+ {80,5,10,0x50000l,4,{{at_missileweapon,2,1},{done,2,2},{reset,2,3},{reset2,6,0}}}, //bazooka
+ {80,5,10,0x10000l,4,{{at_missileweapon,2,1},{done,2,2},{reset,2,3},{reset2,6,0}}}, //firebomb
+ {80,5,10,0x50000l,4,{{at_missileweapon,2,1},{done,2,2},{reset,2,3},{reset2,6,0}}}, //heatseeker
+ {80,5,10,0x10000l,4,{{at_missileweapon,2,1},{done,2,2},{reset,2,3},{reset2,6,0}}}, //drunk
+ {80,5,7,0x10000l,4,{{at_missileweapon,2,1},{done,2,2},{reset,2,2},{reset2,6,0}}}, // firewall
+ { 125,5,7,0x10000l,7,{{done,3,1},{done,3,2},{done,3,3},{done,3,4},
+ {at_missileweapon,3,5},{done,3,6},{reset,3,7}
+ }
+ }, //GODHAND
+
+#if (SHAREWARE == 0)
+ {80,5,7,0x10000l,4,{{at_missileweapon,2,1},{done,2,2},{reset,2,3},{reset2,6,0}}}, //split
+ { 80,5,7,0x10000l,9,{{done,5,1},{done,5,2},{done,5,3},{done,5,4},
+ {at_missileweapon,10,5},{done,5,4},{done,5,3}, // kes
+ {done,5,2},{reset,5,1}
+ }
+ },
+ { 200,5,7,0x10000l,6,{{done,1,1},{done,1,2},{at_pulltrigger,1,3},{at_pulltrigger,1,4},
+ {at_pulltrigger,1,5},{reset,1,6}
+ }
+ }, //BAT
+ {128,5,7,0x10000l,3,{{done,2,1},{at_pulltrigger,2,2},{reset,2,3}}}
+#endif
+};
+
+
+
+/*
+=============================================================================
+
+ LOCAL FUNCTION PROTOTYPES and VARIABLES
+
+=============================================================================
+*/
+
+void CheckPlayerSpecials(objtype * ob);
+void CheckWeaponStates(objtype * ob);
+boolean CheckSprite (statobj_t*,int *);
+void T_Tag (objtype *ob);
+void T_Player (objtype *ob);
+void T_BatBlast(objtype*ob);
+void T_Attack (objtype *ob);
+void T_Free (objtype *ob);
+void T_DogUse (objtype *ob);
+void PlayerMove(objtype * ob);
+void Thrust (objtype * ob);
+void CheckWeaponChange (objtype * ob);
+void PlayerMissileAttack(objtype* );
+void Cmd_Use(objtype*);
+//void ComError (char *error, ...);
+int FinddTopYZANGLELIMITvalue(objtype *ob);
+
+statetype s_free = {false,0,0,T_Free,0,&s_free};
+statetype s_inelevator = {false,0,420,T_Player,0,&s_player};
+
+#if (SHAREWARE == 0)
+statetype s_dogwait = {true,SERIALDOG_W11,50,T_Player,SF_DOGSTATE,&s_serialdog};
+
+statetype s_doguse = {true,SERIALDOG_W11,140,T_DogUse,SF_DOGSTATE,&s_serialdog};
+statetype s_doglick = {true,SERIALDOG_W11,0,T_DogLick,SF_DOGSTATE,&s_doglick};
+#endif
+
+statetype s_tag = {false,CASSATT_S1,20,T_Tag,0,&s_player};
+
+static SWIFT_3DStatus SWIFTStatus;
+
+//
+// curent user input
+//
+
+static int turnheldtime;
+static int turnaround = 0;
+static int turnaroundtime;
+
+//
+// Double Click variables
+//
+
+static int DoubleClickTimer[ 3 ] = { 0 };
+static byte DoubleClickCount[ 3 ] = { 0 };
+static byte DoubleClickPressed[ 3 ] = { false };
+static int JoyDblClickTimer[ 4 ] = { 0 };
+static byte JoyDblClickCount[ 4 ] = { 0 };
+static byte JoyDblClickPressed[ 4 ] = { false };
+
+
+static int PlayerRecording=-1;
+static int nettics;
+
+void Move_Player_From_Exit_To_Start(objtype *ob);
+void CheckTagGame(objtype *actor1,objtype*actor2);
+void CheckFlying(objtype*ob,playertype *pstate);
+
+/*
+===============
+=
+= LoadPlayer
+=
+===============
+*/
+void LoadPlayer ( void )
+{
+ memset (locplayerstate->buttonstate, 0, sizeof(locplayerstate->buttonstate));
+ locplayerstate->anglefrac=player->angle<<ANGLEBITS;
+ areabyplayer[player->areanumber]=true;
+ ConnectAreas();
+}
+
+
+int MaxHitpointsForCharacter(playertype*pstate)
+{
+ if (BATTLEMODE && (gamestate.BattleOptions.HitPoints != bo_character_hitpoints))
+ {
+ return( gamestate.BattleOptions.HitPoints );
+ }
+ return characters[pstate->player].hitpoints;
+}
+
+void InitializeWeapons(playertype*pstate)
+{
+
+
+#if (SHAREWARE == 0)
+ if (gamestate.SpawnEluder)
+ { pstate->new_weapon = pstate->weapon = pstate->missileweapon = wp_dog;
+ pstate->oldweapon = pstate->oldmissileweapon = wp_dog;
+ pstate->bulletweapon = -1;
+ pstate->HASBULLETWEAPON[wp_pistol] = 0;
+ pstate->HASBULLETWEAPON[wp_twopistol] = 0;
+ pstate->HASBULLETWEAPON[wp_mp40] = 0;
+ }
+ else
+#endif
+ { if (gamestate.PlayerHasGun[pstate-&PLAYERSTATE[0]])
+ { pstate->new_weapon = pstate->weapon = pstate->oldweapon =
+ pstate->bulletweapon = wp_pistol;
+ pstate->HASBULLETWEAPON[wp_pistol] = 1;
+ pstate->HASBULLETWEAPON[wp_twopistol] = 0;
+ pstate->HASBULLETWEAPON[wp_mp40] = 0;
+ pstate->missileweapon = pstate->oldmissileweapon = -1;
+ }
+ else
+ { pstate->new_weapon = pstate->weapon = pstate->oldweapon =
+ pstate->bulletweapon = -1;
+ pstate->HASBULLETWEAPON[wp_pistol] = 0;
+ pstate->HASBULLETWEAPON[wp_twopistol] = 0;
+ pstate->HASBULLETWEAPON[wp_mp40] = 0;
+ pstate->missileweapon = pstate->oldmissileweapon = -1;
+ }
+ }
+
+
+ pstate->ammo = -1;
+}
+
+void ResetPlayerstate(playertype*pstate)
+{
+
+ pstate->batblast = 0;
+ pstate->poweruptime = pstate->protectiontime = 0;
+ pstate->NETCAPTURED = 0;
+ MISCVARS->NET_IN_FLIGHT = 0;
+ pstate->weaponuptics = 0;
+ pstate->weapondowntics = 0;
+ if ((insetupgame==false) || NewGame)
+ pstate->health = MaxHitpointsForCharacter(pstate);
+ pstate->keys = 0;
+
+// Give players all the keys in battle game
+
+ if ( BATTLEMODE )
+ {
+ pstate->keys = 0x0f;
+ }
+ pstate->attackframe = pstate->attackcount =
+ pstate->weaponframe = 0;
+ if (gamestate.battlemode == battle_Tag)
+ pstate->weaponheight = TAGHANDHEIGHT;
+ else
+ pstate->weaponheight = 0;
+ pstate->heightoffset = pstate->oldheightoffset = 0;
+ if (gamestate.SpawnEluder)
+ pstate->playerheight = 40;
+ else
+ pstate->playerheight = characters[pstate->player].height;
+ pstate->falling = false;
+ memset (pstate->buttonstate, 0, sizeof(pstate->buttonstate));
+ SetPlayerHorizon(pstate,NORMALYZANGLE);
+}
+
+
+
+
+/*
+===============
+=
+= SetupPlayerobj
+=
+===============
+*/
+void SetupPlayerobj (int tilex, int tiley, int dir, objtype * ob)
+{
+ playertype *pstate;
+
+ M_LINKSTATE(ob,pstate);
+
+ ob->obclass = playerobj;
+ ob->tilex = tilex;
+ ob->tiley = tiley;
+ actorat[tilex][tiley] = ob;
+ ob->areanumber = MAPSPOT(tilex,tiley,0)-AREATILE;
+ MakeLastInArea(ob);
+ ob->x = ((long)tilex<<TILESHIFT)+TILEGLOBAL/2;
+ ob->y = ((long)tiley<<TILESHIFT)+TILEGLOBAL/2;
+ ob->z = PlatformHeight(tilex,tiley);
+ if ((ob->z == -10) || DiskAt(tilex,tiley))
+ ob->z = 0;
+
+ ob->angle = (1-dir)*ANG90;
+ ob->which = ACTOR;
+ Fix(ob->angle);
+ ob->yzangle = 0;
+
+ ob->dir = angletodir[ob->angle];
+ ob->flags = (FL_SHOOTABLE|FL_ABP|FL_BLOCK|FL_COLORED);
+ ob->drawx=ob->x;
+ ob->drawy=ob->y;
+ ob->hitpoints = pstate->health;
+ pstate->anglefrac= (ob->angle<<ANGLEBITS);
+ pstate->angle=0;
+ areabyplayer[ob->areanumber]=true;
+
+
+ if (ob == player)
+ {
+ playerdead=false; // local player dead flag
+ }
+ if (!gamestate.SpawnEluder)
+ ob->shapeoffset = pstate->player*REMOTEOFFSET;
+
+ memset (pstate->buttonstate, 0, sizeof(pstate->buttonstate));
+ if (SCREENEYE != NULL)
+ {
+ NewState(SCREENEYE,&s_megaremove);
+ SCREENEYE = NULL;
+ }
+}
+
+
+
+void SetShapeoffset(objtype*ob)
+{ playertype *pstate;
+
+ M_LINKSTATE(ob,pstate);
+ ob->shapeoffset = pstate->player*REMOTEOFFSET;
+ ob->flags |= FL_COLORED;
+ ob->flags &= ~FL_DYING;
+
+}
+
+
+/*
+===============
+=
+= RevivePlayerobj
+=
+===============
+*/
+void RevivePlayerobj (int tilex, int tiley, int dir, objtype*ob)
+{
+ playertype *pstate;
+ statetype *tstate;
+
+ M_LINKSTATE(ob,pstate);
+ tstate = ob->state;
+ RemoveFromArea(ob);
+ TurnActorIntoSprite(ob);
+ if ((LASTSTAT->z < nominalheight) && (!IsPlatform(LASTSTAT->tilex,LASTSTAT->tiley)))
+ {
+ SpawnParticles(ob,GUTS,10 + gamestate.difficulty);
+ RemoveStatic(LASTSTAT);
+ }
+ else
+ { if (DEADPLAYER[NUMDEAD])
+ RemoveStatic(DEADPLAYER[NUMDEAD]);
+ DEADPLAYER[NUMDEAD] = LASTSTAT;
+ LASTSTAT->linked_to = NUMDEAD;
+ NUMDEAD = (NUMDEAD+1)&(MAXDEAD-1);
+ }
+
+ ob->state = tstate;
+
+ SetupPlayerobj (tilex, tiley, dir, ob);
+ ConnectAreas();
+
+ ResetPlayerstate(pstate);
+ InitializeWeapons(pstate);
+ SD_PlaySoundRTP(SD_PLAYERSPAWNSND,ob->x,ob->y);
+ if (!gamestate.SpawnEluder)
+ {
+ ob->shapeoffset = 0;
+ ob->flags &= ~FL_COLORED;
+ ob->flags |= FL_DYING;
+ NewState(ob,&s_respawn1);
+ if (gamestate.battlemode == battle_Tag)
+ {
+ if (BATTLE_Team[ob->dirchoosetime] == BATTLE_It)
+
+ {
+ pstate->missileweapon = pstate->oldweapon = pstate->new_weapon =
+ pstate->oldmissileweapon = pstate->weapon = wp_godhand;
+ pstate->bulletweapon = -1;
+ ob->flags |= FL_DESIGNATED;
+ }
+ else
+ {
+ pstate->weaponheight = 0;
+ }
+ }
+ }
+#if (SHAREWARE == 0)
+ else
+ NewState(ob,&s_serialdog);
+#endif
+ if (ob==player)
+ DrawPlayScreen(false);
+ ob->momentumx = ob->momentumy = ob->momentumz = 0;
+}
+
+
+/*
+===============
+=
+= SpawnPlayerobj
+=
+===============
+*/
+void SpawnPlayerobj (int tilex, int tiley, int dir, int playerindex)
+{
+ playertype *pstate;
+
+ pstate = &PLAYERSTATE[playerindex];
+
+ GetNewActor();
+ MakeActive(new);
+
+ // Set player number
+
+ new->dirchoosetime = playerindex;
+
+ // Save off if local player
+
+ if (playerindex==consoleplayer)
+ player=new;
+
+ PLAYER[playerindex] = new;
+
+ SetupPlayerobj (tilex, tiley, dir, new);
+
+ if (!gamestate.SpawnEluder)
+ NewState(new,&s_player);
+#if (SHAREWARE == 0)
+ else
+ NewState(new,&s_serialdog);
+#endif
+
+
+}
+
+/*
+===============
+=
+= SetupBulletHoleLink
+=
+===============
+*/
+void SetupBulletHoleLink (int num, statobj_t * item)
+{
+ BulletHoles[num] = item;
+}
+
+/*
+===============
+=
+= SpawnBulletHole
+=
+===============
+*/
+void SpawnBulletHole (int x, int y, int z)
+{
+ if (M_ISDOOR(x>>16,y>>16))
+ return;
+ if (BulletHoles[MISCVARS->BulletHoleNum])
+ RemoveStatic(BulletHoles[MISCVARS->BulletHoleNum]);
+ SpawnInertStatic(x,y,z,stat_bullethole);
+ BulletHoles[MISCVARS->BulletHoleNum]=LASTSTAT;
+ LASTSTAT->linked_to=MISCVARS->BulletHoleNum;
+ MISCVARS->BulletHoleNum = (MISCVARS->BulletHoleNum+1)&(MAXBULLETS-1);
+}
+
+
+
+
+void SpawnGunSmoke(int x, int y, int z, int angle, int bullethole)
+
+{
+ int chance;
+
+ if ((x<=0) || (y<=0))
+ {
+ SoftError("SpawnGunSmoke: xy below angle=%d\n",angle);
+ return;
+ }
+
+ if ((bullethole!=0) && (z>=-32) && (z<=maxheight))
+ switch (bullethole)
+ {
+ case 1:
+ SpawnBulletHole(x-BULLETHOLEOFFSET,y,z);
+ break;
+ case 2:
+ SpawnBulletHole(x+BULLETHOLEOFFSET,y,z);
+ break;
+ case 3:
+ SpawnBulletHole(x,y-BULLETHOLEOFFSET,z);
+ break;
+ case 4:
+ SpawnBulletHole(x,y+BULLETHOLEOFFSET,z);
+ break;
+ case 5:
+ SpawnBulletHole(x,y,z);
+ break;
+ default:
+ Error("Invalid bullethole value\n");
+ break;
+ }
+
+ SpawnInertActor(x,y,z);
+
+ NewState(new,&s_gunsmoke1);
+
+ if (angle < ANGLES/4)
+ { if ((angle < (3*ANGLES/16)) && (angle > (ANGLES/16)))
+ chance = 128;
+ else
+ chance = 20;
+ }
+ else if (angle < ANGLES/2)
+ { if ((angle < (7*ANGLES/16)) && (angle > (5*ANGLES/16)))
+ chance = 128;
+ else
+ chance = 20;
+ }
+ else if (angle < 3*ANGLES/4)
+ { if ((angle < (11*ANGLES/16)) && (angle > (9*ANGLES/16)))
+ chance = 128;
+ else
+ chance = 20;
+ }
+ else
+ { if ((angle < (15*ANGLES/16)) && (angle > (13*ANGLES/16)))
+ chance = 128;
+ else
+ chance = 20;
+ }
+
+ if (RandomNumber("Wall ricochet check",0)<chance)
+ { int rand;
+
+ rand = RandomNumber("Spawn Ricochet Sound in SpawnGunSmoke",0);
+ if (rand < 80)
+ SD_PlaySoundRTP(SD_RICOCHET1SND,new->x,new->y);
+ else if (rand < 160)
+ SD_PlaySoundRTP(SD_RICOCHET2SND,new->x,new->y);
+ else
+ SD_PlaySoundRTP(SD_RICOCHET3SND,new->x,new->y);
+ }
+}
+
+void SpawnBlood(objtype * ob, int angle)
+{
+
+ SpawnInertActor(ob->x-(costable[angle]>>5),
+ ob->y+(sintable[angle]>>5),ob->z);
+
+ NewState(new,&s_bloodspurt1);
+
+ if ((new->x<=0) || (new->y<=0))
+ Error("SpawnBlood: bad x,y obj->obclass=%d\n",ob->obclass);
+}
+
+void SpawnMetalSparks(objtype * ob, int angle)
+{
+ int rand,dispx=0,dispy=0;
+
+
+ if (ob->which == ACTOR)
+ {
+ dispx = ob->momentumx;
+ dispy = ob->momentumy;
+ }
+
+ SpawnInertActor(ob->x-(costable[angle]>>3)+dispx,
+ ob->y+(sintable[angle]>>3)+dispy,ob->z);
+
+ if (GameRandomNumber("Spawn Metal Sparks",0)<128)
+ NewState(new,&s_hitmetalactor1);
+ else
+ NewState(new,&s_hitmetalwall1);
+
+ rand = RandomNumber("Spawn Ricochet Sound",0);
+ if (rand < 80)
+ SD_PlaySoundRTP(SD_RICOCHET1SND,new->x,new->y);
+ else if (rand < 160)
+ SD_PlaySoundRTP(SD_RICOCHET2SND,new->x,new->y);
+ else
+ SD_PlaySoundRTP(SD_RICOCHET3SND,new->x,new->y);
+ if ((new->x<=0) || (new->y<=0))
+ Error("SpawnMetalSparks: bad x,y obj->obclass=%d\n",ob->obclass);
+}
+
+/*
+===============
+=
+= UnTargetActor ( objtype * target )
+=
+===============
+*/
+void UnTargetActor ( objtype * target )
+{
+ int i;
+
+ for (i=0; i<numplayers; i++)
+ {
+ if (PLAYERSTATE[i].guntarget==target)
+ {
+ PLAYERSTATE[i].guntarget=NULL;
+ SetNormalHorizon(PLAYER[i]);
+ }
+ }
+}
+
+
+
+//=============================================================
+
+int GetWeaponForItem(int itemnumber)
+{
+ switch (itemnumber)
+ {
+
+
+ case stat_twopistol:
+ return wp_twopistol;
+
+ case stat_mp40:
+ return wp_mp40;
+
+ case stat_bazooka:
+ return wp_bazooka;
+
+ case stat_heatseeker:
+ return wp_heatseeker;
+
+ case stat_drunkmissile:
+ return wp_drunk;
+
+ case stat_firebomb:
+ return wp_firebomb;
+
+ case stat_firewall:
+ return wp_firewall;
+
+ case stat_godmode:
+ return wp_godhand;
+
+#if (SHAREWARE == 0)
+
+
+ case stat_splitmissile:
+ return wp_split;
+
+ case stat_kes:
+ return wp_kes;
+
+ case stat_bat:
+ return wp_bat;
+
+
+ case stat_dogmode:
+ return wp_dog;
+#endif
+ }
+ return 0;
+}
+
+
+int GetItemForWeapon(int weapon)
+{
+ switch (weapon)
+ {
+
+ case wp_twopistol:
+ return stat_twopistol;
+
+ case wp_mp40:
+ return stat_mp40;
+
+ case wp_bazooka:
+ return stat_bazooka;
+
+ case wp_heatseeker:
+ return stat_heatseeker;
+
+ case wp_drunk:
+ return stat_drunkmissile;
+
+ case wp_firebomb:
+ return stat_firebomb;
+
+ case wp_firewall:
+ return stat_firewall;
+
+ case wp_godhand:
+ return stat_godmode;
+
+#if (SHAREWARE == 0)
+
+ case wp_split:
+ return stat_splitmissile;
+
+ case wp_kes:
+ return stat_kes;
+
+ case wp_bat:
+ return stat_bat;
+
+
+ case wp_dog:
+ return stat_dogmode;
+#endif
+ }
+ return -1;
+}
+
+
+
+#define MF_SINGULAR 0x01
+
+missile_stats PlayerMissileData[13] =
+
+{
+ {0,0,0,0,0},
+ {0,0,0,0,0},
+ {0,0,0,0,0},
+
+ {&s_p_bazooka1,0x6000,p_bazookaobj,0x7000,MF_SINGULAR},
+ {&s_p_bazooka1,0x8000,p_heatseekobj,0x7000,MF_SINGULAR},
+ {&s_p_bazooka1,0x6000,p_drunkmissileobj,0x7000,0},
+ {&s_p_bazooka1,0x8000,p_firebombobj,0x7000,MF_SINGULAR},
+ {&s_p_grenade,0x4000,p_firewallobj,0x8000,0},
+ {&s_godfire1,0x3800,p_godballobj,0x8000,0},
+ {&s_p_bazooka1,0x8000,p_splitmissileobj,0x7000,MF_SINGULAR},
+#if (SHAREWARE == 0)
+ {&s_kessphere1,0xc000,p_kesobj,0x5000,MF_SINGULAR},
+#else
+ {0,0,0,0,0},
+#endif
+ {0,0,0,0,0},
+ {0,0,0,0,0}
+
+};
+
+
+void MissileAutoTarget(objtype *ob,missile_stats *mdata)
+{
+ int dx,dy,angle,mindist,currdist,magangle,saveangle,
+ xydist,dz,yzangle,oldyzangle,saveyzangle;
+ objtype *target,*temp;
+
+ mindist = 0x7fffffff;
+ target = NULL;
+ for(temp = firstactive; temp; temp=temp->nextactive)
+ {
+ if (temp == ob)
+ continue;
+ if ((!(temp->flags & FL_SHOOTABLE)) || (temp->flags & FL_DYING))
+ continue;
+ if (!CheckLine(ob,temp,SHOOT))
+ continue;
+
+ dx = temp->x-ob->x;
+ dy = ob->y-temp->y;
+ dz = ob->z-temp->z;
+ xydist = FindDistance(dx,dy);
+ yzangle = atan2_appx(xydist,dz<<10);
+
+ angle = atan2_appx(dx,dy);
+
+ magangle = abs(ob->angle - angle);
+ if (magangle > VANG180)
+ magangle = ANGLES - magangle;
+
+ if (magangle > ANGLESDIV8)
+ continue;
+
+ currdist = FindDistance(ob->x-temp->x,ob->y-temp->y);
+ if (currdist < mindist)
+ {
+ mindist = currdist;
+ target = temp;
+ saveangle = angle;
+ saveyzangle = yzangle;
+ }
+ }
+
+ if (target)
+ {
+ oldyzangle = ob->yzangle;
+ ob->yzangle = saveyzangle;
+ SpawnMissile(ob,mdata->obclass,mdata->speed,saveangle,
+ mdata->state,mdata->offset);
+ ob->yzangle = oldyzangle;
+ }
+
+ else if (ob->flags&FL_GODMODE)
+ {
+ int saveangle;
+
+ saveangle=ob->yzangle;
+ ob->yzangle -= GODYZANGLE;
+ Fix(ob->yzangle);
+ SpawnMissile(ob,mdata->obclass,mdata->speed,
+ ob->angle,mdata->state,mdata->offset);
+ ob->yzangle=saveangle;
+ }
+ else
+ SpawnMissile(ob,mdata->obclass,mdata->speed,ob->angle,
+ mdata->state,mdata->offset);
+
+}
+
+
+void PlayerMissileAttack(objtype*ob)
+
+{
+ playertype * pstate;
+ missile_stats *newmissiledata;
+ M_LINKSTATE(ob,pstate);
+
+
+ MISCVARS->madenoise = true;
+ newmissiledata = &PlayerMissileData[pstate->missileweapon];
+
+ // ready to annihilate this poor bastard
+
+ if ((newmissiledata->obclass == p_godballobj) ||
+ (newmissiledata->obclass == p_kesobj))
+ MissileAutoTarget(ob,newmissiledata);
+
+ else
+ {
+ //LT added: if autoAimMissileWeps is true (as well as autoAim), then missile weapons will be aimed similarly to bullet weapons
+ if (autoAimMissileWeps && autoAim)
+ AutoTargetHorizon(ob);
+ SpawnMissile(ob,newmissiledata->obclass,newmissiledata->speed,ob->angle,
+ newmissiledata->state,newmissiledata->offset);
+
+ if (newmissiledata->obclass == p_drunkmissileobj)
+ {
+ int i;
+
+ for(i=0; i<4; i++)
+ {
+ if (!MissileTryMove(new,new->x+new->momentumx,new->y+new->momentumy,new->z))
+ {
+ new->x = new->drawx = ob->x + (costable[new->angle]>>3);
+ new->y = new->drawy = ob->y - (sintable[new->angle]>>3);
+
+ ob->momentumx = -FixedMul(0x5000l,costable[ob->angle]);
+ ob->momentumy = FixedMul(0x5000l,sintable[ob->angle]);
+ }
+
+ SpawnMissile(ob,newmissiledata->obclass,newmissiledata->speed,ob->angle,
+ newmissiledata->state,newmissiledata->offset);
+
+
+ }
+ }
+ }
+
+
+ if (newmissiledata->flags & MF_SINGULAR)
+ PLAYER0MISSILE = new;
+
+ SD_PlaySoundRTP(BAS[new->obclass].fire,ob->x,ob->y);
+
+ // if (new->obclass == p_godballobj)
+ // new->z += 10;
+
+ new->dirchoosetime = 5;
+ if (missilecam==true)
+ missobj=new;
+ if (!MissileTryMove(new,new->x+new->momentumx,new->y+new->momentumy,new->z))
+ {
+ new->x = new->drawx = ob->x + (costable[new->angle]>>3);
+ new->y = new->drawy = ob->y - (sintable[new->angle]>>3);
+
+ ob->momentumx = -FixedMul(0x5000l,costable[ob->angle]);
+ ob->momentumy = FixedMul(0x5000l,sintable[ob->angle]);
+ }
+
+}
+
+//====================================================================
+
+
+boolean InRange (objtype *p, objtype *victim, int distance)
+{
+ int dx,dy;
+ int angle;
+ int magangle;
+
+ if (victim->which==SPRITE)
+ {
+ dx = ((statobj_t *)victim)->x - p->x;
+ dy = p->y - ((statobj_t *)victim)->y;
+ }
+ else
+ {
+ dx = victim->x - p->x;
+ dy = p->y - victim->y;
+ }
+ angle = atan2_appx (dx,dy);
+
+ magangle = abs(p->angle - angle);
+ if (magangle > VANG180)
+ magangle = ANGLES - magangle;
+ if (magangle<(75-(distance>>16)))
+ return true;
+ else
+ return false;
+}
+
+
+void DogAttack(objtype*ob)
+{
+ objtype *temp;
+ int dx,dy,dz;
+
+ SD_PlaySoundRTP(SD_DOGMODEBITE1SND+(RandomNumber("DogAttack",0)>>7),ob->x,ob->y);
+ for(temp=firstareaactor[ob->areanumber]; temp; temp=temp->nextinarea)
+ {
+
+ if (temp->obclass > b_heinrichobj)
+ continue;
+
+
+ if ((temp == ob) || (temp->obclass == roboguardobj))
+ continue;
+
+ if ((!(temp->flags & FL_SHOOTABLE)) || (temp->flags & FL_DYING))
+ continue;
+ if (temp->obclass == collectorobj)
+ continue;
+
+
+ dx = abs(temp->x - ob->x);
+ if (dx > 0xc000)
+ continue;
+
+ dy = abs(temp->y - ob->y);
+ if (dy > 0xc000)
+ continue;
+
+ dz = abs(temp->z - ob->z);
+ if (dz > (0xc000>>10))
+ continue;
+
+ DamageThing(temp,30);
+ if (gamestate.violence == vl_excessive)
+ SpawnParticles(temp,GUTS,15);
+ Collision(temp,ob,-temp->momentumx,-temp->momentumy);
+ if ((temp->obclass == playerobj) && (temp->flags & FL_DYING))
+ BATTLE_PlayerKilledPlayer(battle_kill_with_missile,ob->dirchoosetime,temp->dirchoosetime);
+
+ return;
+ }
+}
+
+
+void DogBlast(objtype*ob)
+{
+ int txl,txh,tyl,tyh,radius = 0x70000,x,y,tile;
+ objtype*temp;
+ statobj_t*tstat;
+
+ txl = ((ob->x - radius)>>TILESHIFT);
+ tyl = ((ob->y - radius)>>TILESHIFT);
+
+ txh = ((ob->x + radius)>>TILESHIFT);
+ tyh = ((ob->y + radius)>>TILESHIFT);
+
+ if (txl < 1)
+ txl = 1;
+ if (txh > MAPSIZE-1)
+ txh = MAPSIZE-1;
+ if (tyl < 1)
+ tyl = 1;
+ if (tyh > MAPSIZE-1)
+ tyh = MAPSIZE-1;
+
+ for(x=txl; x<=txh; x++)
+ for(y=tyl; y<=tyh; y++)
+ {
+ temp = (objtype*)actorat[x][y];
+
+ if (temp && (temp->which == ACTOR) && (temp->flags & FL_SHOOTABLE) &&
+ (temp != ob) && (temp->obclass < roboguardobj) &&
+ (temp->flags & FL_ABP)
+ )
+ {
+ DamageThing(temp,100);
+ if ((temp->hitpoints<=0) && (temp->obclass < roboguardobj))
+ {
+ MISCVARS->supergibflag = true;
+ temp->flags |= FL_HBM;
+ }
+ Collision(temp,ob,0,0);
+ MISCVARS->supergibflag = false;
+
+ if ((temp->obclass == playerobj) && (temp->flags & FL_DYING))
+ BATTLE_PlayerKilledPlayer(battle_kill_with_missile,ob->dirchoosetime,temp->dirchoosetime);
+
+ }
+
+ tile = tilemap[x][y];
+ if ((tile & 0x4000) && (tile & 0x8000))
+ {
+ maskedwallobj_t * mw;
+
+ mw=maskobjlist[tile&0x3ff];
+ if ((mw->flags & MW_SHOOTABLE) && (mw->flags & MW_ABP))
+ UpdateMaskedWall(tile&0x3ff);
+ }
+
+ tstat = sprites[x][y];
+ if (tstat && (tstat->flags & FL_SHOOTABLE) && (tstat->flags & FL_ABP))
+ DamageThing(tstat,50);
+ }
+}
+/*
+void DogBlast(objtype*ob)
+ {
+ int txl,txh,tyl,tyh,radius = 0x70000,x,y,tile;
+ objtype*temp;
+ statobj_t*tstat;
+
+ txl = ((ob->x - radius)>>TILESHIFT);
+ tyl = ((ob->y - radius)>>TILESHIFT);
+
+ txh = ((ob->x + radius)>>TILESHIFT);
+ tyh = ((ob->y + radius)>>TILESHIFT);
+
+ if (txl < 1)
+ txl = 1;
+ if (txh > MAPSIZE-1)
+ txh = MAPSIZE-1;
+ if (tyl < 1)
+ tyl = 1;
+ if (tyh > MAPSIZE-1)
+ tyh = MAPSIZE-1;
+
+ for(x=txl;x<=txh;x++)
+ for(y=tyl;y<=tyh;y++)
+ {
+ temp = (objtype*)actorat[x][y];
+
+ if (temp && (temp->which == ACTOR) && (temp->flags & FL_SHOOTABLE) &&
+ (temp != ob) && (temp->obclass < roboguardobj))
+ {
+ DamageThing(temp,100);
+ if ((temp->hitpoints<=0) && (temp->obclass < roboguardobj))
+ {
+ MISCVARS->supergibflag = true;
+ temp->flags |= FL_HBM;
+ }
+ Collision(temp,ob,0,0);
+ MISCVARS->supergibflag = false;
+
+ if ((temp->obclass == playerobj) && (temp->flags & FL_DYING))
+ BATTLE_PlayerKilledPlayer(battle_kill_with_missile,ob->dirchoosetime,temp->dirchoosetime);
+
+ }
+
+ tile = tilemap[x][y];
+ if ((tile & 0x4000) && (tile & 0x8000))
+ {
+ maskedwallobj_t * mw;
+
+ mw=maskobjlist[tile&0x3ff];
+ if (mw->flags & MW_SHOOTABLE)
+ UpdateMaskedWall(tile&0x3ff);
+ }
+
+ tstat = sprites[x][y];
+ if (tstat && (tstat->flags & FL_SHOOTABLE))
+ DamageThing(tstat,50);
+ }
+ }
+*/
+
+void BatBlast(objtype*ob)
+{ int angle;
+ playertype *pstate;
+
+ M_LINKSTATE(ob,pstate);
+
+ angle = ob->angle - ANGLES/8 + ((++pstate->batblast)*ANGLES/48);
+ Fix(angle);
+#if (SHAREWARE == 0)
+ SpawnMissile(ob,p_bazookaobj,0x6000,angle,&s_batblast1,0xa000);
+#endif
+
+}
+
+
+
+void BatAttack(objtype*ob)
+{ objtype *temp,*temp2;
+ objtype *grenadetarget;
+ statobj_t*tstat;
+ int dx,dy,dz,angle,momx,momy,op,magangle;
+ int tilexlow,tilexhigh;
+ int tileylow,tileyhigh;
+ int radius =0x10000;
+ int x,y;
+
+ SD_PlaySoundRTP(SD_EXCALISWINGSND,ob->x,ob->y);
+ for(temp=firstareaactor[ob->areanumber]; temp; temp=temp->nextinarea)
+ { if (temp == ob)
+ continue;
+
+ if (temp->flags & FL_DYING)
+ continue;
+
+ if ((temp->obclass != grenadeobj) &&
+ (!((temp->obclass >= grenadeobj) && (temp->obclass <= p_godballobj))) &&
+ (!(temp->flags & FL_SHOOTABLE) ||
+ (temp->obclass >= roboguardobj))
+ )
+ continue;
+
+ dx = abs(temp->x - ob->x);
+ dy = abs(temp->y - ob->y);
+ dz = abs(temp->z - ob->z);
+ if ((dx > 0x10000) || (dy > 0x10000) || (dz > 20))
+ continue;
+
+ magangle = abs(ob->angle - AngleBetween(ob,temp));
+ if (magangle > VANG180)
+ magangle = ANGLES - magangle;
+
+ if (magangle > ANGLES/8)
+ continue;
+
+
+ angle= ob->angle+ANGLES/16;
+ Fix(angle);
+
+ if ((temp->obclass >= grenadeobj) && (temp->obclass <= p_godballobj))
+ {
+ temp->angle += ANGLES/2;
+ Fix(temp->angle);
+ temp->momentumx = temp->momentumy = temp->momentumz = 0;
+ ParseMomentum(temp,temp->angle);
+ temp->whatever = ob;
+ temp->target = NULL;
+ continue;
+ }
+
+
+ else if (temp->obclass != grenadeobj)
+ { momx = FixedMul(0x3000l,costable[angle]);
+ momy = -FixedMul(0x3000l,sintable[angle]);
+ if (levelheight > 2)
+ { op = FixedMul(GRAVITY,(maxheight-100)<<16) << 1;
+ temp->momentumz = -FixedSqrtHP(op);
+ }
+ temp->flags |= FL_NOFRICTION;
+ SD_PlaySoundRTP(SD_EXCALIHITSND,ob->x,ob->y);
+ if ((gamestate.violence == vl_excessive) && (GameRandomNumber("Bat Gibs",0) < 150))
+ { temp->flags |= FL_HBM;
+ DamageThing(temp,50);
+ }
+ else
+ DamageThing(temp,10);
+ if ((temp->flags & FL_HBM) && (temp->hitpoints > 0))
+ temp->flags &= ~FL_HBM;
+ Collision(temp,ob,momx,momy);
+ if ((temp->obclass == blitzguardobj) && (temp->state == &s_blitzplead7))
+ { temp->shapeoffset += deathshapeoffset[temp->obclass];
+ temp->flags |= FL_ALTERNATE;
+ NewState(temp,&s_blitzdie3);
+ temp->momentumx = temp->momentumy = 0;
+ }
+ }
+ else // find target to hit grenade back at
+ { int rand;
+
+ rand = GameRandomNumber("bat/grenade target",0);
+ if (rand < 80)
+ { grenadetarget = (objtype*)(temp->whatever); // hit back at george
+ GetMomenta(grenadetarget,ob,&(temp->momentumx),&(temp->momentumy),&(temp->momentumz),0x3000);
+ }
+ else if (rand < 160) // hit back at first eligible
+ {
+
+ for(temp2 = firstareaactor[ob->areanumber]; temp2; temp2 = temp2->nextinarea)
+ { magangle = abs(ob->angle-AngleBetween(ob,temp2));
+ if (magangle > VANG180)
+ magangle = ANGLES - magangle;
+
+ if (magangle > ANGLES/8)
+ continue;
+ GetMomenta(temp2,ob,&(temp->momentumx),&(temp->momentumy),&(temp->momentumz),0x3000);
+ break;
+ }
+ }
+ else // hit wherever
+ { ob->angle += (rand >> 1);
+ Fix(ob->angle);
+ ob->momentumx = ob->momentumy = 0;
+ ParseMomentum(ob,ob->angle);
+ }
+
+
+ temp->temp1 = 0x70000;
+ NewState(temp,&s_grenade1);
+ }
+ break;
+ }
+
+ for(tstat=firstactivestat; tstat; tstat=tstat->statnext)
+ {
+ if (!(tstat->flags & FL_SHOOTABLE))
+ continue;
+
+ dx = abs(tstat->x - ob->x);
+ dy = abs(tstat->y - ob->y);
+ dz = abs(tstat->z - ob->z);
+
+ if ((dx > 0xc000) || (dy > 0xc000) || (dz > 20))
+ continue;
+
+ magangle = abs(ob->angle - AngleBetween(ob,(objtype*)tstat));
+ if (magangle > VANG180)
+ magangle = ANGLES - magangle;
+
+ if (magangle > ANGLES/8)
+ continue;
+
+ DamageThing(tstat,50);
+
+
+ }
+
+ tilexlow = (int)((ob->x-radius) >>TILESHIFT);
+ tileylow = (int)((ob->y-radius) >>TILESHIFT);
+
+ tilexhigh = (int)((ob->x+radius) >>TILESHIFT);
+ tileyhigh = (int)((ob->y+radius) >>TILESHIFT);
+
+ for (y=tileylow; y<=tileyhigh; y++)
+ for (x=tilexlow; x<=tilexhigh; x++)
+ { if ((tilemap[x][y]&0x8000) && (tilemap[x][y]&0x4000))
+ { maskedwallobj_t * mw;
+
+ mw=maskobjlist[tilemap[x][y]&0x3ff];
+ if (mw->flags&MW_SHOOTABLE)
+ UpdateMaskedWall(tilemap[x][y]&0x3ff);
+ }
+ }
+
+}
+
+void AutoTargetHorizon(objtype *ob)
+{
+ int dx,dy,angle,mindist,magangle,
+ xydist,dz;
+ objtype *temp;
+ playertype * pstate;
+
+ M_LINKSTATE(ob,pstate);
+
+ mindist = 0x7fffffff;
+ for(temp = firstactive; temp; temp=temp->nextactive)
+ {
+ if (temp == ob)
+ continue;
+ if ((!(temp->flags & FL_SHOOTABLE)) || (temp->flags & FL_DYING))
+ continue;
+ if (!CheckLine(ob,temp,SHOOT))
+ continue;
+
+ dx = temp->x-ob->x;
+ dy = ob->y-temp->y;
+ dz = ob->z-temp->z;//-pstate->playerheight+32;
+
+ xydist = FindDistance(dx,dy);
+ if (abs(dz<<10)>xydist)
+ continue;
+
+
+ angle = atan2_appx(dx,dy);
+
+ magangle = ob->angle - angle;
+ Fix(magangle);
+
+ if (
+ (magangle>=(ANGLESDIV8/4)) &&
+ (magangle<=(FINEANGLES-(ANGLESDIV8/4)))
+ )
+ {
+ continue;
+ }
+
+ if (xydist < mindist)
+ {
+ mindist = xydist;
+ pstate->guntarget=temp;
+ temp->flags |= FL_TARGET;
+ pstate->targettime=oldpolltime+(VBLCOUNTER);
+ }
+ }
+}
+
+void GunAttack (objtype *ob)
+{
+ playertype * pstate;
+ int damage;
+
+ M_LINKSTATE(ob,pstate);
+
+ MISCVARS->madenoise = true;
+
+ switch (pstate->weapon)
+ {
+ case wp_pistol:
+ SD_PlaySoundRTP(SD_ATKPISTOLSND,ob->x,ob->y);
+ damage=DMG_PISTOL;
+ break;
+
+ case wp_mp40:
+ SD_PlaySoundRTP(SD_ATKMP40SND,ob->x,ob->y);
+ damage=DMG_MP40;
+ break;
+
+ case wp_twopistol:
+ SD_PlaySoundRTP(SD_ATKTWOPISTOLSND,ob->x,ob->y);
+ damage=DMG_PISTOL;
+ break;
+ }
+ if(autoAim)
+ AutoTargetHorizon(ob);
+ RayShoot (ob, damage, (characters[pstate->player].accuracy+gamestate.difficulty)<<3);
+
+}
+
+
+/*
+===============
+=
+= Cmd_Fire
+=
+===============
+*/
+void Cmd_Fire (objtype*ob)
+{
+ playertype *pstate;
+
+ M_LINKSTATE(ob,pstate);
+
+// pstate->buttonheld[bt_attack] = true;
+
+ if (pstate->NETCAPTURED && (!pstate->HASKNIFE))
+ return;
+
+ if (W_CHANGE(pstate))
+ return;
+
+ pstate->attackframe = 0;
+
+ if ((ob==player) && (pstate->weapon < wp_mp40) && (!pstate->NETCAPTURED))
+ gamestate.DODEMOCRATICBONUS1 = false;
+
+ if (!pstate->NETCAPTURED)
+ {
+ if (pstate->weapon <= wp_mp40)
+ NewState(ob,&s_pgunattack1);
+#if (SHAREWARE == 0)
+ else if ((pstate->weapon == wp_bat) && (pstate->batblast >= BBTIME))
+ {
+ pstate->batblast = 0;
+ NewState(ob,&s_pbatblast);
+ }
+ else if (pstate->weapon == wp_dog)
+ NewState(ob,&s_serialdogattack);
+#endif
+ else
+ NewState(ob,&s_pmissattack1);
+
+#if (SHAREWARE == 0)
+
+ if ((pstate->weapon == wp_dog) && (!ob->momentumz))
+ ob->momentumz = -0x50000;
+#endif
+ pstate->attackcount = WEAPONS[pstate->weapon].attackinfo[0].mtics;
+ pstate->weaponframe = WEAPONS[pstate->weapon].attackinfo[0].frame;
+ }
+
+ else if (pstate->NETCAPTURED == 1)
+ {
+ NewState(player,&s_free);
+ pstate->attackcount = FREE.attackinfo[0].mtics;
+ pstate->weaponframe = FREE.attackinfo[0].frame;
+ }
+
+}
+
+void PlayNoWaySound ( void )
+{
+ if (player->flags & FL_DOGMODE)
+ SD_Play(SD_DOGMODEBITE2SND);
+ else if ((locplayerstate->player == 1) || (locplayerstate->player == 3))
+ SD_Play(SD_PLAYERTBHURTSND);
+ else
+ SD_Play(SD_NOWAYSND);
+}
+
+
+/*
+===============
+=
+= Cmd_Use
+=
+===============
+*/
+
+boolean AreJumping = false;//bna added
+int oldzval;
+int donttilt=0;
+
+
+
+void Cmd_Use (objtype*ob)
+{
+ int checkx,checky,doorn,
+ /*newtilex,newtiley,oldtilex,oldtiley,*/elevnum,
+ wallx,wally;
+// statobj_t* tempsprite=NULL;
+ objtype* tempactor= NULL;
+ doorobj_t* tempdoor=NULL;
+ pwallobj_t* temppwall=NULL;
+ wall_t* tempwall=NULL;
+ int index;
+ playertype * pstate;
+
+
+
+ M_LINKSTATE(ob,pstate);
+
+#if (SHAREWARE == 0)
+
+ if ((pstate->weapon == wp_dog) && (ob->state != &s_doguse) &&
+ (ob->state != &s_dogwait) && (!W_CHANGE(pstate))
+ )
+ {
+ pstate->attackframe = 0;
+ NewState(ob,&s_doguse);
+ pstate->attackcount = DOGSCRATCH.attackinfo[0].mtics;
+ pstate->weaponframe = DOGSCRATCH.attackinfo[0].frame;
+ ob->momentumz = -0x40000;
+ return;
+
+ }
+
+ else
+#endif
+ if ((ob->flags & FL_DESIGNATED) && (BATTLEMODE) && (gamestate.battlemode == battle_Tag))
+ {
+ NewState(ob,&s_tag);
+ //return;
+ }
+//
+// find which cardinal direction the player is facing
+//
+ if (ob->angle < FINEANGLES/8 || ob->angle > 7*FINEANGLES/8)
+ {
+ checkx = ob->tilex + 1;
+ checky = ob->tiley;
+ ob->dir = east;
+ wallx = (checkx << TILESHIFT);
+ wally = (checky << TILESHIFT) + TILEGLOBAL/2;
+ }
+ else if (ob->angle < 3*FINEANGLES/8)
+ {
+ checkx = ob->tilex;
+ checky = ob->tiley-1;
+ ob->dir = north;
+ wally = (checky << TILESHIFT) + TILEGLOBAL;
+ wallx = (checkx << TILESHIFT) + TILEGLOBAL/2;
+ }
+ else if (ob->angle < 5*FINEANGLES/8)
+ {
+ checkx = ob->tilex - 1;
+ checky = ob->tiley;
+ ob->dir = west;
+ wallx = (checkx << TILESHIFT) + TILEGLOBAL;
+ wally = (checky << TILESHIFT) + TILEGLOBAL/2;
+ }
+ else
+ {
+ checkx = ob->tilex;
+ checky = ob->tiley + 1;
+ ob->dir = south;
+ wally = (checky << TILESHIFT);
+ wallx = (checkx << TILESHIFT) + TILEGLOBAL/2;
+ }
+
+
+ if (actorat[checkx][checky])
+ {
+ tempdoor=(doorobj_t*)actorat[checkx][checky];
+ tempactor = (objtype*)actorat[checkx][checky];
+ tempwall = (wall_t*)actorat[checkx][checky];
+ }
+ doorn = tilemap[checkx][checky] & ~0x2000;
+// if (sprites[checkx][checky])
+// tempsprite = sprites[checkx][checky];
+ if (doorn == (elevatorstart + 6))
+ return;
+
+ //bna ++ jumpmode
+ //SetTextMode ( );
+ if (!BATTLEMODE) { //dont use jump in battle, spoils sync
+ if (usejump == true) {
+ if (pstate->buttonheld[bt_use]) {
+ if ((AreJumping == false)&&(ob->z > 0)&&(doorn==0)) {
+ oldzval = ob->z;
+ ob->z -= 15;
+ ob->momentumz += GRAVITY;
+ AreJumping = true;
+ donttilt=10;
+ return;
+ }
+ AreJumping = false;
+ return;
+ }
+ }
+ }
+ //bna
+
+
+ if (pstate->buttonheld[bt_use])
+ return;
+
+ if (doorn == (elevatorstart + 1))
+ {
+ tilemap[checkx][checky]++; // flip switch
+ if (MAPSPOT(ob->tilex,ob->tiley,1) == ALTELEVATORTILE);
+ // playstate = ex_secretlevel;
+ else if (ob==player)
+ playstate = ex_completed;
+ }
+
+
+ else if (doorn == (elevatorstart + 5))
+
+ {
+ elevnum = MAPSPOT(ob->tilex,ob->tiley,1) - 90;
+ tempwall->flags |= FL_S_FLIPPED;
+ OperateElevatorSwitch(ob,elevnum,checkx,checky);
+ }
+ else if (tempdoor && tempdoor->which==PWALL)
+ {
+ temppwall=(pwallobj_t *)tempdoor;
+ OperatePushWall (temppwall->num,ob->dir, ob == player );
+ }
+ else if ((doorn&0x8000) && (!(doorn&0x4000)))
+ {
+ doorobj_t* dptr = doorobjlist[doorn&0x3ff];
+ int dnum = doorn&0x3ff;
+ int lock;
+
+ OperateDoor (pstate->keys, dnum, (ob == player));
+ if (dptr->eindex != -1)
+ {
+ elevator_t*eptr;
+
+
+ lock = dptr->lock;
+ if ( lock && !( pstate->keys & ( 1 << ( lock - 1 ) ) ) )
+ {
+ if (ob==player)
+ {
+ // locked
+ switch (lock)
+ {
+ case 1:
+ AddMessage("You need the \\EGOLD key",MSG_DOOR);
+ break;
+
+ case 2:
+ AddMessage("You need the \\FSILVER key",MSG_DOOR);
+ break;
+
+ case 3:
+ AddMessage("You need the \\8IRON key",MSG_DOOR);
+ break;
+
+ case 4:
+ AddMessage("You need the \\AOSCURO key",MSG_DOOR);
+ break;
+
+ default:
+ AddMessage("This door appears to be locked",MSG_DOOR);
+ break;
+ }
+
+ SD_Play( SD_NOITEMSND );
+ }
+ return;
+ }
+
+ eptr = &ELEVATOR[dptr->eindex];
+ if (((dnum == eptr->door1) && (eptr->state == ev_rad)) ||
+ ((dnum == eptr->door2) && (eptr->state == ev_ras))
+ )
+ if (ob == player)
+ AddMessage("Elevator is on the way.",MSG_GAME);
+
+ OperateElevatorDoor(dnum);
+ }
+
+ }
+
+ else if ((tempactor) && (tempactor->which == ACTOR) &&
+ (tempactor->obclass == pillarobj) &&
+ DISTOK(ob->x,tempactor->x,TD) &&
+ DISTOK(ob->y,tempactor->y,TD) &&
+ (!(tempactor->flags & FL_DONE)) &&
+ (!MAPSPOT(tempactor->tilex,tempactor->tiley,2))
+ )
+
+ { if ((tempactor->dir == nodir) ||
+ (tempactor->dir == ob->dir))
+ { if (tempactor->dir == nodir)
+ {
+ tempactor->dir = ob->dir;
+ ParseMomentum(tempactor,dirangle8[tempactor->dir]);
+ }
+ SD_PlaySoundRTP ( SD_PUSHWALLSND, tempactor->x, tempactor->y );
+ tempactor->flags |= FL_ACTIVE;
+ tempactor->flags |= FL_FLIPPED;
+// MakeActive(tempactor);
+ tempactor->whatever = ob;
+ gamestate.secretcount++;
+ }
+
+ }
+ else if ((tempwall) && (tempwall->which == WALL) &&
+ (tempwall->flags & FL_SWITCH) )
+ {
+ tempwall->flags |= FL_S_FLIPPED;
+ if ((tempwall->flags & FL_W_INVERTED) &&
+ DISTOK(ob->x,wallx,TD) &&
+ DISTOK(ob->y,wally,TD) &&
+ DISTOK(ob->z,0,32)
+ )
+ {
+ index = touchindices[checkx][checky]-1;
+ if (!(tempwall->flags & FL_ON))
+ {
+ maskobjlist[tilemap[checkx][checky]&0x3ff]->toptexture++;
+ tempwall->flags |= FL_ON;
+ TRIGGER[index] = 1;
+ SD_PlaySoundRTP(SD_TOUCHPLATESND,ob->x,ob->y);
+ if (ob==player)
+ AddMessage("Switch turned on.",MSG_GAME);
+ }
+ else if (tempwall->flags & FL_REVERSIBLE)
+ {
+ maskobjlist[tilemap[checkx][checky]&0x3ff]->toptexture--;
+ tempwall->flags &= ~FL_ON;
+ TRIGGER[index] = 1;
+ SD_PlaySoundRTP(SD_TOUCHPLATESND,ob->x,ob->y);
+ if (ob==player)
+ AddMessage("Switch turned off.",MSG_GAME);
+ }
+
+ }
+ else if (DISTOK(ob->x,wallx,TD) &&
+ DISTOK(ob->y,wally,TD) &&
+ !(tempwall->flags & FL_W_INVERTED)
+ )
+ {
+ index = touchindices[checkx][checky]-1;
+ if (!(tempwall->flags & FL_ON))
+ {
+ tilemap[checkx][checky]++;
+ tempwall->flags |= FL_ON;
+ TRIGGER[index] = 1;
+ SD_PlaySoundRTP(SD_TOUCHPLATESND,ob->x,ob->y);
+ if (ob==player)
+ AddMessage("Switch turned on.",MSG_GAME);
+ }
+ else if (tempwall->flags & FL_REVERSIBLE)
+ {
+ tilemap[checkx][checky]--;
+ tempwall->flags &= ~FL_ON;
+ TRIGGER[index] = 1;
+ SD_PlaySoundRTP(SD_TOUCHPLATESND,ob->x,ob->y);
+ if (ob==player)
+ AddMessage("Switch turned off.",MSG_GAME);
+ }
+
+ }
+ }
+ else if ((tempwall) && (tempwall->which == WALL) && (ob==player)) {
+ PlayNoWaySound();
+ //bna ++ jumpmode
+ //SetTextMode ( );
+ if (!BATTLEMODE) { //dint use jump in battle, spoils sync
+ if (usejump == true) {
+ if (pstate->buttonheld[bt_use]) {
+ if ((AreJumping == false)&&(ob->z > 0)&&(doorn==0)) {
+ oldzval = ob->z;
+ ob->z -= 15;
+ ob->momentumz += GRAVITY;
+ AreJumping = true;
+ donttilt=10;
+ return;
+ }
+ AreJumping = false;
+ return;
+ }
+ }
+ }
+ //bna
+ }
+// else
+// SD_PlaySoundRTP (SD_NOWAYSND,ob->x,ob->y);
+// pstate->buttonheld[bt_use] = true;
+}
+
+
+/*
+=============================================================================
+
+ USER CONTROL
+
+=============================================================================
+*/
+
+
+//******************************************************************************
+//
+// PollKeyboardButtons
+//
+//******************************************************************************
+
+void PollKeyboardButtons (void)
+{
+ int i;
+
+ QueueLetterInput ();
+ IN_UpdateKeyboard();
+
+ for (i = 0; i < NUMBUTTONS; i++)
+ {
+ if (Keystate[buttonscan[i]])
+ {
+ buttonpoll[i] = true;
+ }
+ }
+}
+
+//******************************************************************************
+//
+// PollMouseButtons
+//
+//******************************************************************************
+extern boolean usemouselook;
+void PollMouseButtons (void)
+{
+ int i;
+ int buttons;
+ int mask;
+ int press;
+
+ buttons = IN_GetMouseButtons();
+
+ mask = 1;
+ for( i = 0; i < 3; i++, mask <<= 1 )
+ {
+ press = buttons & mask;
+
+ if ( press )
+ { //SetTextMode ( );
+// if ( ( buttonmouse[ i ] != bt_nobutton ) &&
+// ( DoubleClickCount[ i ] != 2 ) )
+ if ( buttonmouse[ i ] != bt_nobutton )
+ {
+ buttonpoll[ buttonmouse[ i ] ] = true;
+ //bna added
+ if ((i == 1)&&(usemouselook == true)) {
+ //if rightclick set horizon to 512 (normall)
+ playertype * pstate;
+ pstate=&PLAYERSTATE[consoleplayer];
+ pstate->horizon = 512;
+ // SetNormalHorizon(PLAYER[0]);
+ }
+ //bna added
+
+ }
+ }
+
+ // Check double-click
+ if ( buttonmouse[ i + 3 ] != bt_nobutton )
+ {
+ if ( press )
+ {
+ // Was the button pressed last tic?
+ if ( !DoubleClickPressed[ i ] )
+ {
+ // Yes, take note of it
+ DoubleClickPressed[ i ] = true;
+
+ // Is this the first click, or a really late click?
+ if ( ( DoubleClickCount[ i ] == 0 ) ||
+ ( GetTicCount() >= DoubleClickTimer[ i ] ) )
+ {
+ // Yes, now wait for a second click
+ DoubleClickTimer[ i ] = GetTicCount() + DoubleClickSpeed;
+
+ //( tics << 5 );
+ DoubleClickCount[ i ] = 1;
+ }
+ else
+ {
+ // Second click
+ buttonpoll[ buttonmouse[ i + 3 ] ] = true;
+ DoubleClickTimer[ i ] = 0;
+ DoubleClickCount[ i ] = 2;
+ }
+ }
+ else
+ {
+ // After second click, button remains pressed
+ // until user releases it
+ if ( DoubleClickCount[ i ] == 2 )
+ {
+ buttonpoll[ buttonmouse[ i + 3 ] ] = true;
+ }
+ }
+ }
+ else
+ {
+ if ( DoubleClickCount[ i ] == 2 )
+ {
+ DoubleClickCount[ i ] = 0;
+ }
+ DoubleClickPressed[ i ] = false;
+ }
+ }
+ }
+}
+
+
+//******************************************************************************
+//
+// PollJoystickButtons
+//
+//******************************************************************************
+void PollJoystickButtons
+(
+ void
+)
+
+{
+ int i;
+ int buttons;
+ int mask;
+ int num;
+ int press;
+
+ buttons = IN_JoyButtons ();
+
+ if ( joypadenabled )
+ {
+ num = 4;
+ mask = 1;
+ }
+ else
+ {
+ num = 2;
+ if ( joystickport )
+ {
+ mask = 4;
+ }
+ else
+ {
+ mask = 1;
+ }
+ }
+
+ for( i = 0; i < num; i++, mask <<= 1 )
+ {
+ press = buttons & mask;
+
+ if ( press )
+ {
+// if ( ( buttonjoy[ i ] != bt_nobutton ) &&
+// ( JoyDblClickCount[ i ] != 2 ) )
+ if ( buttonjoy[ i ] != bt_nobutton )
+ {
+ buttonpoll[ buttonjoy[ i ] ] = true;
+ }
+ }
+
+ // Check double-click
+ if ( buttonjoy[ i + 4 ] != bt_nobutton )
+ {
+ if ( press )
+ {
+ // Was the button pressed last tic?
+ if ( !JoyDblClickPressed[ i ] )
+ {
+ // Yes, take note of it
+ JoyDblClickPressed[ i ] = true;
+
+ // Is this the first click, or a really late click?
+ if ( ( JoyDblClickCount[ i ] == 0 ) ||
+ ( GetTicCount() >= JoyDblClickTimer[ i ] ) )
+ {
+ // Yes, now wait for a second click
+ JoyDblClickTimer[ i ] = GetTicCount() + DoubleClickSpeed;
+
+ //( tics << 5 );
+ JoyDblClickCount[ i ] = 1;
+ }
+ else
+ {
+ // Second click
+ buttonpoll[ buttonjoy[ i + 4 ] ] = true;
+ JoyDblClickTimer[ i ] = 0;
+ JoyDblClickCount[ i ] = 2;
+ }
+ }
+ else
+ {
+ // After second click, button remains pressed
+ // until user releases it
+ if ( JoyDblClickCount[ i ] == 2 )
+ {
+ buttonpoll[ buttonjoy[ i + 4 ] ] = true;
+ }
+ }
+ }
+ else
+ {
+ if ( JoyDblClickCount[ i ] == 2 )
+ {
+ JoyDblClickCount[ i ] = 0;
+ }
+ JoyDblClickPressed[ i ] = false;
+ }
+ }
+ }
+}
+
+
+//===========================================================================
+
+//******************************************************************************
+//
+// PollKeyboardMove
+//
+//******************************************************************************
+
+void PollKeyboardMove
+(
+ void
+)
+
+{
+ if ( ( buttonpoll[ bt_turnaround ] ) && ( turnaround == 0 ) )
+ {
+ turnaround = 1;
+ turnaroundtime = 15 + tics;
+ turnheldtime = 0;
+ }
+ if ( turnaround == 0 )
+ {
+ if ( buttonpoll[ di_east ] )
+ {
+ turnheldtime+=tics;
+ if (turnheldtime>=TURBOTURNTIME)
+ {
+ KX = -KEYBOARDNORMALTURNAMOUNT;
+ }
+ else
+ {
+ KX = -KEYBOARDPREAMBLETURNAMOUNT;
+ }
+ }
+ else if ( buttonpoll[ di_west ] )
+ {
+ turnheldtime+=tics;
+ if (turnheldtime>=TURBOTURNTIME)
+ {
+ KX = KEYBOARDNORMALTURNAMOUNT;
+ }
+ else
+ {
+ KX = KEYBOARDPREAMBLETURNAMOUNT;
+ }
+ }
+ else
+ {
+ KX = 0;
+ turnheldtime=0;
+ }
+ if ( (buttonpoll[bt_run]) &&
+ ( (turnheldtime>=TURBOTURNTIME) || (turnheldtime==0) )
+ )
+ KX = FixedMul(KX,TURBOTURNAMOUNT);
+ }
+ else
+ {
+ KX=TURNAROUNDSPEED;
+ turnaroundtime-=tics;
+ if (turnaroundtime<=0)
+ {
+ turnaround=0;
+ KX=((turnaroundtime*TURNAROUNDSPEED)>>1);
+ }
+ }
+
+ if ( buttonpoll[ di_north ] )
+ {
+ KY = -BASEMOVE;
+ }
+ else if ( buttonpoll[ di_south ] )
+ {
+ KY = BASEMOVE;
+ }
+ else
+ KY = 0;
+
+ if (buttonpoll[bt_run])
+ {
+ KY <<= 1;
+ }
+}
+
+//******************************************************************************
+//
+// PollMouseMove
+//
+//******************************************************************************
+
+//#define MOUSE_RY_SHIFT 12
+//#define MOUSE_TZ_SHIFT 3
+#define MOUSE_TZ_SENSITIVITY_SCALE 65535
+#define MOUSE_RY_SENSITIVITY_SCALE 18725*2
+//#define MOUSE_RY_INPUT_SCALE 6000
+#define MOUSE_TZ_INPUT_SCALE 20
+int mouse_ry_input_scale = 5000;
+
+int sensitivity_scalar[15] =
+{
+ 0,1,2,3,4,5,6,8,11,13,15,18,12,13,14
+};
+//#define MOUSE_RY_SCALE 65535
+//#define MOUSE_TZ_SCALE 65535
+#define MAXMOUSETURN 7000000
+
+/* use SDL mouse */
+#define USESDLMOUSE 1
+
+
+extern int inverse_mouse;
+double Y_MouseSpeed=70;
+
+void PollMouseMove (void)
+{
+ int mousexmove, mouseymove;
+ double Ys;
+//SetTextMode();
+
+ Ys=(Y_MouseSpeed/100);
+//
+
+// const long inverse_mouse = 1; //set to -1 to invert mouse
+// inverse_mouse def moved to RT_CFG.C
+
+#ifdef USESDLMOUSE
+ INL_GetMouseDelta(&mousexmove, &mouseymove);
+#else
+ PollMouse();//Uses DirectInput mouse in DInput.cpp
+ mousexmove=MX;
+ mouseymove=MY;
+#endif
+
+ if (abs(mousexmove)>abs(mouseymove))
+ mouseymove/=2;
+ else
+ mousexmove/=2;
+ MX = 0;
+ MY = 0;
+
+
+ if ((abs (mouseymove)) >= threshold)
+ { //
+ MY = MOUSE_TZ_INPUT_SCALE*mouseymove;
+ MY *= inverse_mouse;
+ if (usemouselook == true) {
+ if (MY > 0) {
+ playertype * pstate;
+ pstate=&PLAYERSTATE[consoleplayer];
+ //if (pstate->horizon > 512){
+ pstate->horizon -= Ys * (2*sensitivity_scalar[mouseadjustment]);
+ //}
+ }
+ else if (MY < 0) {
+ playertype * pstate;
+ pstate=&PLAYERSTATE[consoleplayer];
+ //SetTextMode ( );
+ pstate->horizon += Ys * (2*sensitivity_scalar[mouseadjustment]);
+ //buttonpoll[ bt_horizonup ] = true;
+ }
+ MY = 0;
+ } else {
+ // MY += FixedMul(MY,mouseadjustment*MOUSE_TZ_SENSITIVITY_SCALE);
+ if (abs(mouseymove)>200)
+ {
+ buttonpoll[bt_run]=true;
+ // buttonpoll[ bt_lookup ] = true;
+ }
+ }
+ }
+
+
+
+
+
+ if ((abs (mousexmove)) >= threshold)
+ {
+ //MX = -MOUSE_RY_INPUT_SCALE*mousexmove;
+ MX = -mouse_ry_input_scale*mousexmove;
+ MX += FixedMul(MX,sensitivity_scalar[mouseadjustment]*MOUSE_RY_SENSITIVITY_SCALE);
+ // if (abs(MX) > MAXMOUSETURN)
+ // MX = MAXMOUSETURN*SGN(MX);
+ if (usemouselook == true) {
+ if (abs(mouseymove)>10)
+ {
+ buttonpoll[bt_run]=true;
+ //buttonpoll[ bt_lookdown ] = true;
+ }
+ }
+ }
+// if (MY > 0)
+// MX -= (MX/2);
+
+// MX=0;
+// MY=0;
+
+}
+
+
+//******************************************************************************
+//
+// PollJoystickMove
+//
+//******************************************************************************
+
+void PollJoystickMove (void)
+{
+ int joyx,joyy;
+
+ INL_GetJoyDelta (joystickport, &joyx, &joyy);
+ if ( joypadenabled )
+ {
+ if (joyx >= threshold)
+ {
+ buttonpoll[ di_east ] = true;
+ }
+ if (-joyx >= threshold)
+ {
+ buttonpoll[ di_west ] = true;
+ }
+ if ( joyy >= threshold )
+ {
+ buttonpoll[ di_south ] = true;
+ }
+ if ( -joyy >= threshold )
+ {
+ buttonpoll[ di_north ] = true;
+ }
+ }
+ else
+ {
+ if ((abs (joyx)) >= threshold)
+ {
+ JX = ((-joyx)<<13)+((-joyx)<<11);
+ turnheldtime += tics;
+ }
+ else
+ JX = 0;
+
+ if ((abs (joyy)) >= threshold)
+ {
+ JY = joyy<<4;
+ }
+ else
+ JY = 0;
+ if (buttonpoll[bt_run])
+ {
+ JX <<= 1;
+ JY <<= 1;
+ }
+ }
+}
+
+//******************************************************************************
+//
+// StartVRFeedback
+//
+//******************************************************************************
+
+void StartVRFeedback (int guntype)
+{
+#ifdef DOS
+ union REGS inregs;
+ union REGS outregs;
+
+ inregs.x.eax = VR_FEEDBACK_SERVICE;
+ inregs.x.ebx = 1;
+ inregs.x.ecx = guntype;
+ int386 (0x33, &inregs, &outregs);
+#else
+ STUB_FUNCTION;
+#endif
+}
+
+//******************************************************************************
+//
+// StopVRFeedback
+//
+//******************************************************************************
+
+void StopVRFeedback (void)
+{
+#ifdef DOS
+ union REGS inregs;
+ union REGS outregs;
+
+ inregs.x.eax = VR_FEEDBACK_SERVICE;
+ inregs.x.ebx = 0;
+ int386 (0x33, &inregs, &outregs);
+#else
+ STUB_FUNCTION;
+#endif
+}
+
+//******************************************************************************
+//
+// PollVirtualReality
+//
+//******************************************************************************
+
+#define VR_BUTTON(x) ((vr_buttons>>x) & 1)
+
+void PollVirtualReality (void)
+{
+#ifdef DOS
+ union REGS inregs;
+ union REGS outregs;
+ short int mousexmove,
+ mouseymove;
+ word vr_buttons;
+
+ inregs.x.eax = VR_INPUT_SERVICE;
+
+ inregs.x.ebx = player->angle;
+ inregs.x.ecx = player->yzangle;
+
+ int386 (0x33, &inregs, &outregs);
+
+ vr_buttons = outregs.w.bx;
+
+ buttonpoll[bt_run ] |= VR_BUTTON(VR_RUNBUTTON );
+ buttonpoll[bt_strafeleft ] |= VR_BUTTON(VR_STRAFELEFTBUTTON );
+ buttonpoll[bt_straferight ] |= VR_BUTTON(VR_STRAFERIGHTBUTTON );
+ buttonpoll[bt_attack ] |= VR_BUTTON(VR_ATTACKBUTTON );
+ buttonpoll[bt_lookup ] |= VR_BUTTON(VR_LOOKUPBUTTON );
+ buttonpoll[bt_lookdown ] |= VR_BUTTON(VR_LOOKDOWNBUTTON );
+ buttonpoll[bt_swapweapon ] |= VR_BUTTON(VR_SWAPWEAPONBUTTON );
+ buttonpoll[bt_use ] |= VR_BUTTON(VR_USEBUTTON );
+ buttonpoll[bt_horizonup ] |= VR_BUTTON(VR_HORIZONUPBUTTON );
+ buttonpoll[bt_horizondown ] |= VR_BUTTON(VR_HORIZONDOWNBUTTON );
+ buttonpoll[bt_map ] |= VR_BUTTON(VR_MAPBUTTON );
+ buttonpoll[bt_pistol ] |= VR_BUTTON(VR_PISTOLBUTTON );
+ buttonpoll[bt_dualpistol ] |= VR_BUTTON(VR_DUALPISTOLBUTTON );
+ buttonpoll[bt_mp40 ] |= VR_BUTTON(VR_MP40BUTTON );
+ buttonpoll[bt_missileweapon] |= VR_BUTTON(VR_MISSILEWEAPONBUTTON);
+ buttonpoll[bt_recordsound ] |= VR_BUTTON(VR_RECORDBUTTON );
+
+ mousexmove = outregs.w.cx;
+ mouseymove = outregs.w.dx;
+
+ VX = 0;
+ VY = 0;
+
+
+ if ((abs (mouseymove)) >= threshold)
+ {
+ VY = MOUSE_TZ_INPUT_SCALE*mouseymove;
+ if (abs(mouseymove)>200)
+ {
+ buttonpoll[bt_run]=true;
+ }
+ }
+
+ if ((abs (mousexmove)) >= threshold)
+ {
+ VX = -mouse_ry_input_scale*mousexmove;
+ VX += FixedMul(MX,sensitivity_scalar[mouseadjustment]*MOUSE_RY_SENSITIVITY_SCALE);
+ if (abs(mousexmove)>10)
+ {
+ buttonpoll[bt_run]=true;
+ }
+ }
+#else
+ STUB_FUNCTION;
+#endif
+}
+
+
+//******************************************************************************
+//
+// PollMove ()
+//
+//******************************************************************************
+
+boolean aimbuttonpressed=false;
+void PollMove (void)
+{
+ int angle;
+ int x, y;
+
+
+ x = KX + MX + JX + CX + VX;
+ y = KY + MY + JY + CY + VY;
+
+ if (buttonpoll[bt_aimbutton])
+ {
+ if (y>0)
+ {
+ buttonpoll[bt_horizonup]=1;
+ y=0;
+ aimbuttonpressed=true;
+ }
+ else if (y<0)
+ {
+ buttonpoll[bt_horizondown]=1;
+ y=0;
+ aimbuttonpressed=true;
+ }
+ else if (aimbuttonpressed==false)
+ {
+ buttonpoll[bt_lookup]=1;
+ buttonpoll[bt_lookdown]=1;
+ }
+ }
+ else
+ {
+ aimbuttonpressed=false;
+ }
+
+ if (player->flags & FL_FLEET)
+ y += y>>1;
+
+ if ((locplayerstate->NETCAPTURED == 1) && (!locplayerstate->HASKNIFE))
+ {
+ if (first)
+ {
+ nettics = GetTicCount() + (VBLCOUNTER * 4);
+ first = 0;
+ }
+
+ if (x > 0)
+ {
+ rightmom += NETMOM;
+ if (lastmom!=0)
+ controlbuf[2]=x<<1;
+ lastmom=0;
+ }
+ else if (x < 0)
+ {
+ leftmom += NETMOM;
+ if (lastmom!=1)
+ controlbuf[2]=x<<1;
+ lastmom=1;
+ }
+ else
+ {
+ rightmom -= (NETMOM >> 2);
+ if (rightmom < 0)
+ rightmom = 0;
+ leftmom -= (NETMOM >> 2);
+ if (leftmom < 0)
+ leftmom = 0;
+ }
+
+ if ((GetTicCount() > nettics) && (rightmom > (NETMOM * 2)) &&
+ (leftmom > (NETMOM * 2)))
+ {
+ rightmom = 0;
+ leftmom = 0;
+ first = 1;
+ lastmom^=1;
+ locplayerstate->NETCAPTURED = 0;
+ MISCVARS->NET_IN_FLIGHT = false;
+ NewState(player, &s_player);
+ locplayerstate->weaponuptics = WEAPONS[locplayerstate->weapon].screenheight/GMOVE;
+ locplayerstate->weaponheight = locplayerstate->weaponuptics*GMOVE ;
+ }
+ }
+ else if ((buttonpoll[bt_strafe]) && (turnaround==0))
+ {
+ // strafing
+ if (x < 0)
+ {
+ angle = (player->angle - FINEANGLES/4)&(FINEANGLES-1);
+
+ x = (x>>10) + (x >> 11);
+
+ controlbuf[0] = -(FixedMul (x, costable[angle]));
+ controlbuf[1] = FixedMul (x, sintable[angle]);
+ }
+ else if (x > 0)
+ {
+ angle = (player->angle + FINEANGLES/4)&(FINEANGLES-1);
+
+ x = (x>>10) + (x >> 11);
+
+ controlbuf[0] = FixedMul (x, costable[angle]);
+ controlbuf[1] = -(FixedMul (x, sintable[angle]));
+ }
+ if (y != 0)
+ {
+ controlbuf[0] += -(FixedMul (y, viewcos));
+ controlbuf[1] += (FixedMul (y, viewsin));
+ }
+ }
+ else
+ {
+ if (y != 0)
+ {
+ controlbuf[0] = -FixedMul (y, viewcos);
+ controlbuf[1] = FixedMul (y, viewsin);
+ }
+
+ if (x != 0)
+ controlbuf[2] = x;
+ }
+
+ if (buttonpoll[bt_strafeleft])
+ {
+ angle = (player->angle - FINEANGLES/4)&(FINEANGLES-1);
+ controlbuf[0] += -(FixedMul (STRAFEAMOUNT, costable[angle]));
+ controlbuf[1] += FixedMul (STRAFEAMOUNT, sintable[angle]);
+ }
+ else if (buttonpoll[bt_straferight])
+ {
+ angle = (player->angle + FINEANGLES/4)&(FINEANGLES-1);
+ controlbuf[0] += -(FixedMul (STRAFEAMOUNT, costable[angle]));
+ controlbuf[1] += FixedMul (STRAFEAMOUNT, sintable[angle]);
+ }
+}
+
+
+//******************************************************************************
+//
+// PollCyberman ()
+//
+//******************************************************************************
+
+void PollCyberman (void)
+{
+ int i;
+ int mask;
+ int press;
+
+ SWIFT_Get3DStatus (&SWIFTStatus);
+
+ mask = 4;
+ for( i = 0; i < 3; i++, mask >>= 1 )
+ {
+ press = SWIFTStatus.buttons & mask;
+
+ if ( press )
+ {
+// if ( ( buttonmouse[ i ] != bt_nobutton ) &&
+// ( DoubleClickCount[ i ] != 2 ) )
+ if ( buttonmouse[ i ] != bt_nobutton )
+ {
+ buttonpoll[ buttonmouse[ i ] ] = true;
+ }
+ }
+
+ // Check double-click
+ if ( buttonmouse[ i + 3 ] != bt_nobutton )
+ {
+ if ( press )
+ {
+ // Was the button pressed last tic?
+ if ( !DoubleClickPressed[ i ] )
+ {
+ // Yes, take note of it
+ DoubleClickPressed[ i ] = true;
+
+ // Is this the first click, or a really late click?
+ if ( ( DoubleClickCount[ i ] == 0 ) ||
+ ( GetTicCount() >= DoubleClickTimer[ i ] ) )
+ {
+ // Yes, now wait for a second click
+ DoubleClickTimer[ i ] = GetTicCount() + DoubleClickSpeed;
+
+ //( tics << 5 );
+ DoubleClickCount[ i ] = 1;
+ }
+ else
+ {
+ // Second click
+ buttonpoll[ buttonmouse[ i + 3 ] ] = true;
+ DoubleClickTimer[ i ] = 0;
+ DoubleClickCount[ i ] = 2;
+ }
+ }
+ else
+ {
+ // After second click, button remains pressed
+ // until user releases it
+ if ( DoubleClickCount[ i ] == 2 )
+ {
+ buttonpoll[ buttonmouse[ i + 3 ] ] = true;
+ }
+ }
+ }
+ else
+ {
+ if ( DoubleClickCount[ i ] == 2 )
+ {
+ DoubleClickCount[ i ] = 0;
+ }
+ DoubleClickPressed[ i ] = false;
+ }
+ }
+ }
+
+ if (SWIFTStatus.pitch > 0)
+ CYBERLOOKUP = true;
+ else if (SWIFTStatus.pitch < 0)
+ CYBERLOOKDOWN = true;
+
+ if ((abs (SWIFTStatus.x)) > CYBERDEADRANGE)
+ {
+ CX = -(SGN (SWIFTStatus.x) * (( (abs(SWIFTStatus.x)-CYBERDEADRANGE) ) << 10));
+ turnheldtime += tics;
+ }
+ else if (SWIFTStatus.x != oldcyberx)
+ {
+ turnheldtime += tics;
+ if (SWIFTStatus.x > oldcyberx)
+ CX = -(0xB8000);
+ else
+ CX = 0xB8000;
+
+ oldcyberx = SWIFTStatus.x;
+ }
+ else
+ CX = 0;
+
+ if ((abs (SWIFTStatus.y)) > CYBERDEADRANGE)
+ {
+ CY = SWIFTStatus.y >> 2;
+ }
+ else
+ CY = 0;
+}
+
+//******************************************************************************
+//
+// PollAssassin ()
+//
+//******************************************************************************
+
+#define MAXRAMPS 5
+typedef struct
+{
+ int min;
+ int factor;
+} RampType;
+void PollAssassin (void)
+{
+ int i;
+ int mask;
+ int press;
+ int yaw;
+ int strafeAngle;
+ int acc;
+ int numramps=4;
+ RampType ramp[MAXRAMPS]= {
+ {0,280000},
+ {4,380000},
+ {10,480000},
+ {25,680000},
+// {25,( (1<<26)/80 )}
+ };
+
+ SWIFT_Get3DStatus (&SWIFTStatus);
+
+ mask = 4;
+ for( i = 0; i < 3; i++, mask >>= 1 )
+ {
+ press = SWIFTStatus.buttons & mask;
+
+ if ( press )
+ {
+// if ( ( buttonmouse[ i ] != bt_nobutton ) &&
+// ( DoubleClickCount[ i ] != 2 ) )
+ if ( buttonmouse[ i ] != bt_nobutton )
+ {
+ buttonpoll[ buttonmouse[ i ] ] = true;
+ }
+ }
+
+ // Check double-click
+ if ( buttonmouse[ i + 3 ] != bt_nobutton )
+ {
+ if ( press )
+ {
+ // Was the button pressed last tic?
+ if ( !DoubleClickPressed[ i ] )
+ {
+ // Yes, take note of it
+ DoubleClickPressed[ i ] = true;
+
+ // Is this the first click, or a really late click?
+ if ( ( DoubleClickCount[ i ] == 0 ) ||
+ ( GetTicCount() >= DoubleClickTimer[ i ] ) )
+ {
+ // Yes, now wait for a second click
+ DoubleClickTimer[ i ] = GetTicCount() + DoubleClickSpeed;
+
+ //( tics << 5 );
+ DoubleClickCount[ i ] = 1;
+ }
+ else
+ {
+ // Second click
+ buttonpoll[ buttonmouse[ i + 3 ] ] = true;
+ DoubleClickTimer[ i ] = 0;
+ DoubleClickCount[ i ] = 2;
+ }
+ }
+ else
+ {
+ // After second click, button remains pressed
+ // until user releases it
+ if ( DoubleClickCount[ i ] == 2 )
+ {
+ buttonpoll[ buttonmouse[ i + 3 ] ] = true;
+ }
+ }
+ }
+ else
+ {
+ if ( DoubleClickCount[ i ] == 2 )
+ {
+ DoubleClickCount[ i ] = 0;
+ }
+ DoubleClickPressed[ i ] = false;
+ }
+ }
+ }
+
+ buttonpoll[bt_horizonup] |= ((SWIFTStatus.buttons>>7) & 1);
+ buttonpoll[bt_horizondown] |= ((SWIFTStatus.buttons>>8) & 1);
+
+ if ( abs(SWIFTStatus.pitch) < (20<<6) )
+ {
+ SWIFTStatus.pitch = 0;
+ }
+ else
+ {
+ SWIFTStatus.pitch -= SGN(SWIFTStatus.pitch)*(20<<6);
+ }
+
+ if ( abs(SWIFTStatus.pitch) > (60<<6) )
+ {
+ buttonpoll[bt_run] = 1;
+ }
+
+ if ( abs(SWIFTStatus.roll) > (80<<6) )
+ {
+ buttonpoll[bt_run] = 1;
+ }
+
+
+ if ( abs(SWIFTStatus.roll) < (20<<6) )
+ {
+ SWIFTStatus.roll = 0;
+ }
+ else
+ {
+ SWIFTStatus.roll -= SGN(SWIFTStatus.roll)*(20<<6);
+ }
+
+ strafeAngle = (player->angle - FINEANGLES/4)&(FINEANGLES-1);
+
+ controlbuf[0] += -(FixedMulShift (SWIFTStatus.pitch, viewcos,16))+
+ FixedMulShift (-SWIFTStatus.roll, costable[strafeAngle], 16);
+
+ controlbuf[1] += FixedMulShift (SWIFTStatus.pitch, viewsin,16) -
+ FixedMulShift (-SWIFTStatus.roll, sintable[strafeAngle], 16);
+
+ yaw = abs(SWIFTStatus.yaw);
+ acc = 0;
+ for (i=0; i<numramps; i++)
+ {
+ if (yaw > ramp[i].min)
+ {
+ if (i>0)
+ {
+ acc += ramp[i].min*(ramp[i].factor-ramp[i-1].factor);
+ }
+ }
+ else
+ {
+ i++;
+ break;
+ }
+ }
+ controlbuf[2]= SWIFTStatus.yaw * ramp[i-1].factor - acc;
+}
+
+
+//******************************************************************************
+//
+// PollControls
+//
+// Gets user or demo input, call once each frame
+//
+// controlx set between -100 and 100 per tic
+// controly
+//
+//******************************************************************************
+
+
+void PollControls (void)
+{
+ int i;
+
+ if (standalone==true)
+ return;
+
+ lastpolltime=controlupdatetime;
+
+ memset (buttonpoll, 0, sizeof(buttonpoll));
+
+ controlbuf[0] = controlbuf[1] = controlbuf[2] = 0;
+ CYBERLOOKUP = CYBERLOOKDOWN = false;
+
+ if (gamestate.autorun==1)
+ buttonpoll[bt_run] = true;
+
+
+//
+// get button states
+//
+ PollKeyboardButtons ();
+
+ if (mouseenabled && !cybermanenabled)
+ PollMouseButtons ();
+
+ if (joystickenabled)
+ PollJoystickButtons ();
+
+
+//
+// get movements
+//
+ if (joystickenabled)
+ PollJoystickMove ();
+
+ if (cybermanenabled)
+ PollCyberman ();
+
+ else if (mouseenabled && MousePresent)
+ PollMouseMove ();
+
+ PollKeyboardMove ();
+
+ if (vrenabled)
+ PollVirtualReality ();
+
+ PollMove ();
+
+ if (spaceballenabled)
+ PollSpaceBall ();
+
+ else if (assassinenabled)
+ PollAssassin ();
+
+
+ buttonbits = 0;
+ if (player->flags & FL_DYING) // Player has died
+ {
+ if ((playerdead==true) &&
+ ( buttonpoll[ bt_strafe ] ||
+ buttonpoll[ bt_attack ] ||
+ buttonpoll[ bt_use ] ||
+ ((gamestate.battlemode == battle_Hunter) &&
+ (BATTLE_Team[player->dirchoosetime] == BATTLE_It)
+ )
+ )
+ )
+ {
+ AddRespawnCommand();
+ }
+ memset (buttonpoll, 0, sizeof(buttonpoll));
+ controlbuf[0] = controlbuf[1] = controlbuf[2] = 0;
+ }
+
+ if ((PausePressed==true) && (modemgame==false))
+ {
+ PausePressed=false;
+ if (GamePaused==true)
+ AddPauseStateCommand(COM_UNPAUSE);
+ else
+ {
+ AddPauseStateCommand(COM_PAUSE);
+ }
+ }
+ if (Keyboard[sc_Insert] && Keyboard[sc_X]) {
+ AddExitCommand();
+ }
+//bna section
+ if (Keyboard[sc_5]) {
+ // SetTextMode ( );
+ weaponscale += 1000;
+ //testval++;
+ }
+ if (Keyboard[sc_6]) {
+ // SetTextMode ( );
+ weaponscale -= 1000;
+ // testval--;
+ }
+//bna section end
+
+ for (i = (NUMTXBUTTONS-1); i >= 0; i--)
+ {
+ buttonbits <<= 1;
+ if (buttonpoll[i])
+ buttonbits |= 1;
+ }
+
+ UpdateClientControls();
+}
+
+
+void ResetWeapons(objtype *ob)
+{ playertype *pstate;
+
+ M_LINKSTATE(ob,pstate);
+
+ pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/GMOVE;
+ pstate->new_weapon = pstate->oldweapon;
+ pstate->missileweapon = pstate->oldmissileweapon;
+ ob->shapeoffset = pstate->oldshapeoffset;
+ pstate->attackframe = pstate->weaponframe = 0;
+
+ if ((ob==player) && SHOW_BOTTOM_STATUS_BAR() )
+ DrawBarAmmo (false);
+}
+
+
+
+
+void SaveWeapons(objtype*ob)
+{ playertype *pstate;
+
+ if ((ob->flags&FL_DOGMODE) || (ob->flags&FL_GODMODE))
+ return;
+
+//pstate = (ob==player)?(&playerstate):(&remoteplayerstate);
+ M_LINKSTATE(ob,pstate);
+
+ pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/GMOVE;
+ pstate->oldweapon = pstate->new_weapon;
+ pstate->oldmissileweapon = pstate->missileweapon;
+ pstate->oldshapeoffset = ob->shapeoffset;
+
+}
+
+/*
+void SaveWeapons(objtype*ob)
+{playertype *pstate;
+
+ if ((ob->flags&FL_DOGMODE) || (ob->flags&FL_GODMODE))
+ return;
+
+ //pstate = (ob==player)?(&playerstate):(&remoteplayerstate);
+ M_LINKSTATE(ob,pstate);
+
+ pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/GMOVE;
+ pstate->oldweapon = pstate->weapon;
+ pstate->oldmissileweapon = pstate->missileweapon;
+ pstate->oldshapeoffset = ob->shapeoffset;
+
+}
+*/
+
+
+#define GiveProtection(flag,time,sound) \
+ { \
+ if ((ob->flags & flag) || (ob->flags & FL_GODMODE) || \
+ (ob->flags & FL_DOGMODE)) \
+ return; \
+ ob->flags &= ~(FL_BPV|FL_GASMASK|FL_AV); \
+ ob->flags |= flag; \
+ SD_PlaySoundRTP(sound,ob->x, ob->y); \
+ pstate->protectiontime = time; \
+ gamestate.supercount ++; \
+ }
+
+
+
+
+boolean GivePowerup(objtype *ob,int flag,int time,int sound)
+{
+ playertype *pstate;
+
+
+ if ((ob->flags & flag) ||
+ (ob->flags & FL_GODMODE) ||
+ (ob->flags & FL_DOGMODE)
+ )
+ return false;
+
+
+ M_LINKSTATE(ob,pstate);
+
+ /*
+ if (ob->flags & FL_DOGMODE)
+ {
+ ob->temp2 = DOGMODERISE;
+ ResetWeapons(ob);
+ if (ob->state->condition & SF_DOGSTATE)
+ NewState(ob,&s_player);
+ }
+ else if (ob->flags & FL_GODMODE)
+ {
+ ob->temp2 = GODMODEFALL;
+ ResetWeapons(ob);
+ }
+ */
+ ob->flags &= ~(FL_SHROOMS|FL_FLEET|FL_ELASTO|FL_GODMODE|FL_DOGMODE);
+ ob->flags |= flag;
+ pstate->poweruptime = time;
+ pstate->soundtime = 0;
+ SD_PlaySoundRTP(sound,ob->x, ob->y);
+ gamestate.supercount ++;
+ return true;
+
+}
+
+
+
+void GiveLifePoints(objtype *ob,int points)
+{
+ SD_PlaySoundRTP(SD_GETBONUSSND,ob->x, ob->y);
+
+ UpdateTriads (ob,points);
+ if (ob==player)
+ DrawTriads (false);
+
+}
+
+
+boolean GiveBulletWeapon(objtype *ob,int bulletweapon,statobj_t*check)
+{
+ playertype *pstate;
+
+ M_LINKSTATE(ob,pstate);
+
+ if ((ob->flags & FL_DOGMODE) || (ob->flags & FL_GODMODE))
+ return false;
+
+ if (!ARMED(ob->dirchoosetime))
+ return false;
+
+ if (pstate->HASBULLETWEAPON[bulletweapon])
+ return false;
+
+ GiveWeapon(ob,bulletweapon);
+ if ( gamestate.BattleOptions.WeaponPersistence )
+ {
+ LASTSTAT->z = check->z;
+ }
+ SD_PlaySoundRTP(SD_GETWEAPONSND,ob->x, ob->y);
+ return true;
+
+}
+
+inline boolean DetermineAmmoPickup(playertype *pstate, statobj_t *check)
+{
+ if ((GetWeaponForItem(check->itemnumber) == pstate->missileweapon) &&
+ (pstate->ammo < stats[check->itemnumber].ammo))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+extern boolean enableAmmoPickups;
+boolean wasAmmoPickup = false;
+
+boolean GivePlayerMissileWeapon(objtype *ob, playertype *pstate,
+ statobj_t *check)
+{
+ if ((ob->flags & FL_DOGMODE) || (ob->flags & FL_GODMODE))
+ return false;
+
+
+ if (!ARMED(ob->dirchoosetime))
+ return false;
+
+ if ((GetWeaponForItem(check->itemnumber) == pstate->missileweapon) &&
+ (check->ammo == stats[check->itemnumber].ammo) &&
+ (pstate->ammo == stats[check->itemnumber].ammo)
+ )
+ return false;
+
+ else if ((GetWeaponForItem(check->itemnumber) == pstate->missileweapon) &&
+ (check->ammo == stats[check->itemnumber].ammo) &&
+ (pstate->ammo >= stats[check->itemnumber].ammo)
+ )
+ return false;
+
+
+
+ //LT added, this bit here handles ammo pickups if that option's enabled
+ if (enableAmmoPickups && DetermineAmmoPickup(pstate, check))
+ {
+ wasAmmoPickup = true;
+ GivePlayerAmmo(ob, check, GetWeaponForItem(check->itemnumber));
+ if ((ob==player) && SHOW_BOTTOM_STATUS_BAR() )
+ DrawBarAmmo (false);
+ SD_PlaySoundRTP(SD_GETWEAPONSND,ob->x, ob->y);
+ return true;
+ }
+
+ else if ((GetWeaponForItem(check->itemnumber) == pstate->missileweapon) &&
+ (pstate->ammo >= check->ammo) && enableAmmoPickups)
+ return false;
+
+ SD_PlaySoundRTP(SD_GETWEAPONSND,ob->x, ob->y);
+
+ GiveMissileWeapon(ob,GetWeaponForItem(check->itemnumber));
+ if (gamestate.BattleOptions.WeaponPersistence)
+ LASTSTAT->z = check->z;
+
+ gamestate.missilecount ++;
+
+ if (BATTLEMODE && (gamestate.BattleOptions.Ammo != bo_normal_shots))
+ { if (gamestate.BattleOptions.Ammo == bo_one_shot)
+ pstate->ammo = 1;
+ else
+ pstate->ammo = -1;
+ }
+ else
+ pstate->ammo = check->ammo;
+ if ((ob==player) && SHOW_BOTTOM_STATUS_BAR() )
+ DrawBarAmmo (false);
+
+ return true;
+
+}
+
+
+#define LocalBonusMessage(string) \
+ { \
+ if (ob == player) \
+ AddMessage(string,MSG_BONUS); \
+ }
+#define LocalBonus1Message(string) \
+ { \
+ if (ob == player) \
+ AddMessage(string,MSG_BONUS1); \
+ }
+
+
+/*
+=================================
+=
+= GetBonusTimeForItem
+=
+=================================
+*/
+
+int GetBonusTimeForItem(int itemnumber)
+{
+ specials *which;
+
+ if ( BATTLEMODE )
+ {
+ which = &gamestate.SpecialsTimes;
+ }
+ else
+ {
+ which = &CurrentSpecialsTimes;
+ }
+
+ switch(itemnumber)
+ {
+ case stat_godmode:
+ return which->GodModeTime;
+
+ case stat_dogmode:
+ return which->DogModeTime;
+
+ case stat_mushroom:
+ return which->ShroomsModeTime;
+
+ case stat_elastic:
+ return which->ElastoModeTime;
+
+ case stat_asbesto:
+ return which->AsbestosVestTime;
+
+ case stat_bulletproof:
+ return which->BulletProofVestTime;
+
+ case stat_gasmask:
+ return which->GasMaskTime;
+
+ case stat_fleetfeet:
+ return which->MercuryModeTime;
+ }
+
+ return -1;
+
+}
+
+
+
+
+/*
+=================================
+=
+= GetRespawnTimeForItem
+=
+=================================
+*/
+
+
+
+int GetRespawnTimeForItem(int itemnumber)
+{
+ switch(itemnumber)
+ {
+ case stat_godmode:
+ return gamestate.SpecialsTimes.GodModeRespawnTime;
+
+ case stat_dogmode:
+ return gamestate.SpecialsTimes.DogModeRespawnTime;
+
+ case stat_mushroom:
+ return gamestate.SpecialsTimes.ShroomsModeRespawnTime;
+
+ case stat_elastic:
+ return gamestate.SpecialsTimes.ElastoModeRespawnTime;
+
+ case stat_asbesto:
+ return gamestate.SpecialsTimes.AsbestosVestRespawnTime;
+
+ case stat_bulletproof:
+ return gamestate.SpecialsTimes.BulletProofVestRespawnTime;
+
+ case stat_gasmask:
+ return gamestate.SpecialsTimes.GasMaskRespawnTime;
+
+ case stat_fleetfeet:
+ return gamestate.SpecialsTimes.MercuryModeRespawnTime;
+
+ }
+
+ return gamestate.BattleOptions.RespawnTime * VBLCOUNTER;
+
+
+}
+
+
+/*
+===================
+=
+= GetBonus
+=
+===================
+*/
+void GetBonus (objtype*ob,statobj_t *check)
+{
+ int heal;
+ playertype * pstate;
+ boolean randompowerup;
+
+ M_LINKSTATE(ob,pstate);
+
+ randompowerup=false;
+
+randomlabel:
+ switch (check->itemnumber)
+ {
+
+ case stat_knifestatue:
+ SD_PlaySoundRTP(SD_GETKNIFESND,ob->x, ob->y);
+ if (ob==player)
+ locplayerstate->HASKNIFE = 1;
+ SD_PlaySoundRTP(PlayerSnds[locplayerstate->player], ob->x, ob->y);
+ LocalBonusMessage("You found a knife.");
+ break;
+ case stat_pedgoldkey:
+ LocalBonusMessage("You found the \\EGold key.");
+ goto keys;
+ case stat_pedsilverkey:
+ LocalBonusMessage("You got the \\FSilver key.");
+ goto keys;
+ case stat_pedironkey:
+ LocalBonusMessage("You got the \\8Iron key.");
+ goto keys;
+ case stat_pedcrystalkey:
+ LocalBonusMessage("You got the \\4Oscuro key.");
+keys:
+ GiveKey (check->itemnumber - stat_pedgoldkey);
+ SD_PlaySoundRTP (SD_GETKEYSND,ob->x, ob->y);
+ break;
+ case stat_monkmeal:
+ if (pstate->health == MaxHitpointsForCharacter(pstate))
+ return;
+ SD_PlaySoundRTP (SD_GETHEALTH1SND,ob->x, ob->y);
+ LocalBonusMessage("You ate some Monk Meal.");
+ HealPlayer (10,ob);
+ gamestate.healthcount ++;
+ break;
+ case stat_monkcrystal1:
+ if (pstate->health == MaxHitpointsForCharacter(pstate))
+ return;
+ SD_PlaySoundRTP (SD_GETHEALTH2SND,ob->x, ob->y);
+ LocalBonusMessage("You picked up a small Monk Crystal.");
+
+ HealPlayer (10,ob);
+ gamestate.healthcount ++;
+ break;
+ case stat_monkcrystal2:
+ if (pstate->health == MaxHitpointsForCharacter(pstate))
+ return;
+ SD_PlaySoundRTP (SD_GETHEALTH2SND,ob->x, ob->y);
+ LocalBonusMessage("You picked up a large Monk Crystal.");
+
+ HealPlayer (50,ob);
+ gamestate.healthcount ++;
+ break;
+ case stat_priestporridge:
+ if (pstate->health == MaxHitpointsForCharacter(pstate))
+ return;
+ SD_PlaySoundRTP (SD_GETHEALTH1SND,ob->x, ob->y);
+ if (check->flags & FL_ACTIVE)
+ {
+ HealPlayer (50,ob);
+ LocalBonusMessage("You ate some Priest Porridge Hot.");
+ }
+ else
+ {
+ HealPlayer (20,ob);
+
+ LocalBonusMessage("You ate some Priest Porridge.");
+ }
+ gamestate.healthcount ++;
+ break;
+
+ case stat_healingbasin:
+ if (pstate->health == MaxHitpointsForCharacter(pstate))
+ return;
+ SD_PlaySoundRTP (SD_GETHEALTH2SND,ob->x, ob->y);
+ heal = 25 + (GameRandomNumber("GetBonus",0) >> 2);
+ HealPlayer (heal,ob);
+ LocalBonusMessage("You drank from the healing basin.");
+
+ gamestate.healthcount ++;
+ gamestate.democraticcount ++;
+ break;
+
+ case stat_oneup:
+ if (abs(pstate->health - MaxHitpointsForCharacter(pstate))
+ < (MaxHitpointsForCharacter(pstate)>>2) )
+ {
+ GiveLives(1);
+ LocalBonusMessage("Extra Life!");
+ }
+ else
+ {
+ HealPlayer(MaxHitpointsForCharacter(pstate),ob);
+ LocalBonusMessage("Full Health!");
+ }
+ SD_PlaySoundRTP(SD_GET1UPSND,ob->x, ob->y);
+ break;
+ case stat_threeup:
+ if (abs(pstate->health - MaxHitpointsForCharacter(pstate))
+ < (MaxHitpointsForCharacter(pstate)>>2) )
+ {
+ GiveLives(3);
+ LocalBonusMessage("Three Extra Lives!");
+
+ }
+ else
+ {
+ HealPlayer(MaxHitpointsForCharacter(pstate),ob);
+ GiveLives(2);
+ LocalBonusMessage("Full Health AND Two Extra Lives!");
+
+ }
+ SD_PlaySoundRTP(SD_GET3UPSND,ob->x, ob->y);
+ break;
+
+ case stat_scotthead:
+ // Give Apogee's phone number as points
+ GivePoints( 2764331 );
+ LocalBonusMessage( "Whoa...Scott's Mystical Head!");
+ LocalBonus1Message( "You get 2,764,331 points!");
+ SD_PlaySoundRTP(SD_GETHEADSND,ob->x, ob->y);
+ break;
+
+ case stat_twopistol:
+ if (GiveBulletWeapon(ob,wp_twopistol,check)==false)
+ return;
+ LocalBonusMessage("You got an extra pistol.");
+
+ break;
+ case stat_mp40:
+ if (GiveBulletWeapon(ob,wp_mp40,check)==false)
+ return;
+ LocalBonusMessage("You picked up an MP40.");
+
+ break;
+
+ case stat_bazooka:
+ if (GivePlayerMissileWeapon(ob,pstate,check)==false)
+ return;
+ if (wasAmmoPickup)
+ {
+ LocalBonusMessage("You bagged more Bazooka rounds!");
+ }
+ else {
+ LocalBonusMessage("You bagged a bazooka!");
+ }
+ wasAmmoPickup = false;
+ break;
+
+ case stat_firebomb:
+ if (GivePlayerMissileWeapon(ob,pstate,check)==false)
+ return;
+ if(wasAmmoPickup)
+ {
+ LocalBonusMessage("You got more Firebomb rounds!");
+ }
+ else
+ {
+ LocalBonusMessage("You found a Firebomb!");
+ }
+ wasAmmoPickup = false;
+ break;
+
+
+ case stat_heatseeker:
+ if (GivePlayerMissileWeapon(ob,pstate,check)==false)
+ return;
+ if(wasAmmoPickup)
+ {
+ LocalBonusMessage("You got more Heatseeker rounds!");
+ }
+ else
+ {
+ LocalBonusMessage("You have a Heat-seeker!");
+ }
+ wasAmmoPickup = false;
+ break;
+
+
+ case stat_drunkmissile:
+ if (GivePlayerMissileWeapon(ob,pstate,check)==false)
+ return;
+ if (wasAmmoPickup)
+ {
+ LocalBonusMessage("You recovered more Drunk missiles!");
+ }
+ else
+ {
+ LocalBonusMessage("You recovered a Drunk Missile!");
+ }
+ wasAmmoPickup = false;
+ break;
+
+ case stat_firewall:
+ if (GivePlayerMissileWeapon(ob,pstate,check)==false)
+ return;
+ if(wasAmmoPickup)
+ {
+ LocalBonusMessage("You filched more FlameWalls!");
+ }
+ else
+ {
+ LocalBonusMessage("You filched a FlameWall!");
+ }
+ wasAmmoPickup = false;
+ break;
+
+ case stat_splitmissile:
+ if (GivePlayerMissileWeapon(ob,pstate,check)==false)
+ return;
+ if (wasAmmoPickup)
+ {
+ LocalBonusMessage("You snagged more Split Missiles!");
+ }
+ else
+ {
+ LocalBonusMessage("You snagged a Split Missile!");
+ }
+ wasAmmoPickup = false;
+ break;
+
+ case stat_kes:
+ if (GivePlayerMissileWeapon(ob,pstate,check)==false)
+ return;
+ if(wasAmmoPickup)
+ {
+ LocalBonusMessage("You got more Dark Staff rounds!");
+ }
+ else
+ {
+ LocalBonusMessage("You wield the Dark Staff!");
+ }
+ wasAmmoPickup = false;
+ break;
+
+ case stat_bat:
+ if (GivePlayerMissileWeapon(ob,pstate,check)==false)
+ return;
+ if (wasAmmoPickup) {
+ LocalBonusMessage("You got more bat blast rounds!");
+ }
+ else
+ {
+ LocalBonusMessage("You picked up the Excalibat.");
+ }
+ wasAmmoPickup = false;
+ break;
+
+
+ case stat_lifeitem1:
+ GiveLifePoints(ob,1);
+ if (timelimitenabled)
+ timelimit+=(VBLCOUNTER);
+
+ break;
+
+ case stat_lifeitem2:
+ GiveLifePoints(ob,5);
+ if (timelimitenabled)
+ timelimit+=(2*VBLCOUNTER);
+ break;
+
+ case stat_lifeitem3:
+ GiveLifePoints(ob,10);
+ if (timelimitenabled)
+ timelimit+=(5*VBLCOUNTER);
+ break;
+
+ case stat_lifeitem4:
+ GiveLifePoints(ob,25);
+ if (timelimitenabled)
+ timelimit+=(10*VBLCOUNTER);
+ break;
+
+ case stat_random:
+ switch (GameRandomNumber("GetBonus",0)>>6)
+ {
+ case 0:
+ check->itemnumber=stat_godmode;
+ break;
+ case 1:
+ check->itemnumber=stat_elastic;
+ break;
+ case 2:
+ check->itemnumber=stat_dogmode;
+ break;
+ case 3:
+ check->itemnumber=stat_mushroom;
+ break;
+ }
+ randompowerup=true;
+ LocalBonus1Message("Random powerup gives you . . .");
+ goto randomlabel;
+ break;
+
+ case stat_bulletproof:
+ GiveProtection(FL_BPV, GetBonusTimeForItem(stat_bulletproof),
+ SD_GETBVESTSND);
+ LocalBonusMessage("Bulletproof Armor!");
+
+ goto drw;
+
+ case stat_gasmask:
+ GiveProtection(FL_GASMASK, GetBonusTimeForItem(stat_gasmask),
+ SD_GETMASKSND);
+ LocalBonusMessage("You put on a Gas Mask.");
+
+ goto drw;
+
+ case stat_asbesto:
+ GiveProtection(FL_AV,GetBonusTimeForItem(stat_asbesto),
+ SD_GETAVESTSND);
+ LocalBonusMessage("Asbestos Armor! Oh so itchy!");
+
+ goto drw;
+
+ case stat_elastic:
+ if (GivePowerup(ob,FL_ELASTO,GetBonusTimeForItem(stat_elastic),
+ SD_GETELASTSND) == false)
+ return;
+ LocalBonusMessage("Elasto Mode!");
+
+ ob->flags |= FL_NOFRICTION;
+ goto drw;
+
+ case stat_fleetfeet:
+ if (GivePowerup(ob,FL_FLEET,GetBonusTimeForItem(stat_fleetfeet),
+ SD_GETFLEETSND) == false)
+ return;
+
+ LocalBonus1Message("Mercury Mode!");
+ LocalBonusMessage("Press Look Up and Down to fly.");
+
+ ob->flags &= ~FL_NOFRICTION;
+ goto drw;
+
+
+ case stat_mushroom:
+ if (GivePowerup(ob,FL_SHROOMS,GetBonusTimeForItem(stat_mushroom),
+ SD_GETSHROOMSSND) == false)
+ return;
+ LocalBonusMessage("Shrooms Mode!");
+
+ ob->flags &= ~FL_NOFRICTION;
+ gamestate.democraticcount ++;
+ goto drw;
+
+
+ case stat_godmode:
+
+ if (ob->flags & FL_GODMODE)
+ return;
+
+ if (!ARMED(ob->dirchoosetime))
+ return;
+
+ ob->flags &= ~FL_NOFRICTION;
+
+ if (ob->flags & FL_DOGMODE)
+ {
+ ob->temp2 = DOGMODERISE;
+ ResetWeapons(ob);
+ if (ob->state->condition & SF_DOGSTATE)
+ NewState(ob,&s_player);
+ }
+
+ SaveWeapons(ob);
+ SpawnNewObj(ob->tilex,ob->tiley,&s_flash1,inertobj);
+ new->flags |= FL_ABP;
+ new->x = new->drawx = ob->x;
+ new->y = new->drawy = ob->y;
+ MakeActive(new);
+ new->z = ob->z;
+
+
+ SetPlayerHorizon(pstate,GODYZANGLE);
+
+ ob->flags &= ~(FL_GODMODE|FL_SHROOMS|FL_ELASTO|FL_FLEET|FL_DOGMODE);
+ ob->flags |= FL_GODMODE;
+ ob->temp2 = GODMODERISE;
+ pstate->poweruptime = GetBonusTimeForItem(stat_godmode);
+ pstate->soundtime = 0;
+ GiveMissileWeapon(ob,wp_godhand);
+ SD_PlaySoundRTP(SD_GETGODSND,ob->x, ob->y);
+ gamestate.supercount ++;
+ LocalBonusMessage("God Mode!");
+
+ goto drw;
+
+
+#if (SHAREWARE == 0)
+ case stat_dogmode:
+ if (ob->flags & FL_DOGMODE)
+ return;
+
+ if (!ARMED(ob->dirchoosetime))
+ return;
+
+ ob->flags &= ~FL_NOFRICTION;
+
+ if (ob->flags & FL_GODMODE)
+ {
+ ob->temp2 = GODMODEFALL;
+ ResetWeapons(ob);
+ }
+
+
+ SaveWeapons(ob);
+ ob->shapeoffset = 0;
+ NewState(ob,&s_serialdog);
+
+ SpawnNewObj(ob->tilex,ob->tiley,&s_flash1,inertobj);
+ new->flags |= FL_ABP;
+ new->x = new->drawx = ob->x;
+ new->y = new->drawy = ob->y;
+ MakeActive(new);
+ new->z = ob->z;
+
+ SetPlayerHorizon(pstate,DOGYZANGLE);
+
+ ob->flags &= ~(FL_DOGMODE|FL_SHROOMS|FL_ELASTO|FL_FLEET|FL_GODMODE);
+ ob->flags |= FL_DOGMODE;
+ ob->temp2 = DOGMODEFALL;
+ pstate->poweruptime = GetBonusTimeForItem(stat_dogmode);
+ pstate->soundtime = 0;
+ GiveMissileWeapon(ob,wp_dog);
+ SD_PlaySoundRTP(SD_GETDOGSND,ob->x, ob->y);
+ gamestate.supercount ++;
+ LocalBonusMessage("Dog Mode!");
+
+ goto drw;
+#endif
+
+drw:
+
+ if (ob==player)
+ GM_DrawBonus (check->itemnumber);
+
+ break;
+
+ case stat_dipball1:
+ case stat_dipball2:
+ case stat_dipball3:
+ SD_PlaySoundRTP(SD_GETBONUSSND,ob->x, ob->y);
+ gamestate.dipballs++;
+ LocalBonusMessage("You discovered a Developer Ball!");
+
+ break;
+
+ case stat_collector:
+ if (gamestate.battlemode==battle_CaptureTheTriad)
+ { if (pstate->team == check->hitpoints)
+ return;
+ ob->flags |= FL_DESIGNATED;
+ UpdateKills = true;
+ LocalBonusMessage( "You picked up a triad! RUN!!!");
+ }
+ else
+ BATTLE_CheckGameStatus(battle_get_collector_item,ob->dirchoosetime);
+
+ SD_PlaySoundRTP(SD_GETBONUSSND,ob->x, ob->y);
+ break;
+#if (SHAREWARE == 0)
+ case stat_mine:
+ SpawnNewObj(check->tilex,check->tiley,&s_grexplosion1,inertobj);
+ new->flags |= FL_ABP;
+ new->whatever = check;
+ new->temp2 = 100;
+ MakeActive(new);
+ SD_PlaySoundRTP(SD_EXPLODESND,check->x,check->y);
+ break;
+#endif
+ default:
+ SD_PlaySoundRTP(SD_GETHEADSND,ob->x, ob->y);
+ break;
+ }
+ //StartBonusFlash ();
+ if (check->flags & FL_CHANGES)
+ {
+ switch (check->itemnumber)
+ {
+ case stat_pedgoldkey:
+ case stat_pedsilverkey:
+ case stat_pedironkey:
+ case stat_pedcrystalkey:
+ check->itemnumber = stat_emptypedestal;
+ check->shapenum = stats[stat_emptypedestal].picnum;
+ check->flags = stats[stat_emptypedestal].flags|FL_ABP;
+ check->count = 0;
+ check->numanims = 0;
+ break;
+ case stat_healingbasin:
+ check->itemnumber = stat_emptybasin;
+ check->shapenum = stats[stat_emptybasin].picnum;
+ check->flags = stats[stat_emptybasin].flags|FL_ABP;
+ check->count = 0;
+ check->numanims = 0;
+ break;
+ /*
+ case stat_tablebullets:
+ check->itemnumber = stat_emptytable;
+ check->shapenum = stats[stat_emptytable].picnum;
+ check->flags = stats[stat_emptytable].flags|FL_ABP;
+ break;
+ case stat_statuewithpole:
+ check->itemnumber = stat_armornopole;
+ check->shapenum = stats[stat_armornopole].picnum;
+ check->flags = stats[stat_armornopole].flags|FL_ABP;
+ break; */
+ case stat_pit:
+ check->shapenum ++;
+ check->flags &= ~FL_CHANGES;
+ check->flags &= ~FL_BONUS;
+ break;
+ case stat_knifestatue:
+ check->itemnumber = stat_emptystatue;
+ check->shapenum = stats[stat_emptystatue].picnum;
+ check->flags = stats[stat_emptystatue].flags|FL_ABP;
+ break;
+
+ default:
+ ;
+ }
+ }
+ else
+ { if (check == sprites[check->tilex][check->tiley])
+ {
+ statobj_t *checkstat;
+
+ checkstat = (statobj_t*)DiskAt(check->tilex,check->tiley);
+ if (checkstat && (checkstat->which == SPRITE))
+ sprites[check->tilex][check->tiley] = checkstat;
+ else
+ sprites[check->tilex][check->tiley] = NULL;
+ }
+
+ if (randompowerup==true)
+ check->itemnumber = stat_random;
+ RemoveStatic(check);
+ }
+}
+
+
+/*
+===================
+=
+= DropWeapon
+=
+===================
+*/
+
+void DropWeapon(objtype *ob)
+{ playertype *pstate;
+ int dtilex,dtiley;
+
+
+
+ M_LINKSTATE(ob,pstate);
+
+ if ((pstate->missileweapon == -1) || (pstate->missileweapon == wp_godhand)
+#if (SHAREWARE == 0)
+ || (pstate->missileweapon == wp_dog)
+#endif
+ )
+ return;
+
+ pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/3;
+ pstate->new_weapon = pstate->bulletweapon;
+
+ dtilex = ob->tilex;
+ dtiley = ob->tiley;
+
+ FindEmptyTile(&dtilex, &dtiley);
+
+
+ SpawnStatic(dtilex,dtiley,GetItemForWeapon(pstate->missileweapon),9);
+ gamestate.missiletotal ++;
+
+ LASTSTAT->ammo = pstate->ammo;
+ LASTSTAT->flags |= FL_ABP;
+ LASTSTAT->flags &= ~FL_RESPAWN;
+ MakeStatActive(LASTSTAT);
+ pstate->weaponx = ob->tilex;
+ pstate->weapony = ob->tiley;
+ pstate->ammo = -1;
+ pstate->missileweapon = -1;
+ if ((ob==player) && SHOW_BOTTOM_STATUS_BAR() )
+ DrawBarAmmo (false);
+}
+
+
+/*
+===================
+=
+= Thrust
+=
+===================
+*/
+
+void Thrust ( objtype * ob )
+{ statobj_t *tstat;
+ int dx,dy,dz,rad,index,otherteam;
+ objtype*temp;
+ playertype * pstate;
+
+ PlayerMove(ob);
+ M_LINKSTATE(ob,pstate);
+
+ if ((gamestate.battlemode == battle_CaptureTheTriad) &&
+ (ob->flags & FL_DESIGNATED) &&
+ (ob->tilex == TEAM[pstate->team].tilex) &&
+ (ob->tiley == TEAM[pstate->team].tiley))
+ { if (ob == player)
+ SD_Play(PlayerSnds[locplayerstate->player]);
+
+ if (BATTLE_CheckGameStatus(battle_captured_triad,ob->dirchoosetime)==
+ battle_no_event)
+ {
+ ob->flags &= ~FL_DESIGNATED;
+ UpdateKills = true;
+ otherteam = (pstate->team ^ 1);
+ SpawnStatic(TEAM[otherteam].tilex,TEAM[otherteam].tiley,stat_collector,9);
+ LASTSTAT->flags |= FL_COLORED;
+ LASTSTAT->hitpoints = otherteam;
+ LASTSTAT->flags |= FL_ABP;
+ MakeStatActive(LASTSTAT);
+ }
+ return;
+ }
+
+ if ((ob->tilex != pstate->weaponx) || (ob->tiley != pstate->weapony))
+ pstate->weaponx = pstate->weapony = 0;
+
+ index = touchindices[ob->tilex][ob->tiley];
+ if (index && (abs(ob->z - nominalheight) < 5))
+ { if (!TRIGGER[index-1]) {
+#if (BNACRASHPREVENT == 1)
+ if (touchplate[index-1] != 0) { // CRASH IN SHAREWARE 'ride em cowboy' BNA FIX
+ //SetTextMode ( ); qwert // DONT ALLOW BAD touchplate ( == 0 ) see rt_door.c
+#endif
+ if (touchplate[index-1]->complete)
+ SD_PlaySoundRTP(SD_BADTOUCHSND,ob->x,ob->y);
+ else {
+ SD_PlaySoundRTP(SD_TOUCHPLATESND,ob->x,ob->y);
+ if (ob == player)
+ AddMessage("Touchplate triggered.",MSG_GAME);
+ }
+#if (BNACRASHPREVENT == 1)
+ } else {
+ SD_PlaySoundRTP(SD_BADTOUCHSND,ob->x,ob->y);
+ }
+ // CRASH IN SHAREWARE 'ride em cowboy' BNA FIX
+#endif
+ }
+ TRIGGER[index-1] = 1;
+ }
+
+ tstat = sprites[ob->tilex][ob->tiley];
+ if (tstat)
+
+ { dx = abs(ob->x - tstat->x);
+ dy = abs(ob->y - tstat->y);
+ dz = abs(ob->z - tstat->z);
+ if ((dx < 0x8000) && (dy < 0x8000) && (dz<=35))
+ {
+#define OBJECT_IS_BONUS( tstat ) ( ( tstat )->flags & FL_BONUS )
+#define PLAYER_IS_SWITCHING_WEAPONS( pstate ) ( W_CHANGE( pstate ) )
+//#define IS_ATTACKING( ob ) ( ( ( ob )->state->think == T_Attack ) || ( ( ob )->state->think == T_BatBlast ) )
+#define IS_WEAPON( tstat ) ( ( tstat )->flags & FL_WEAPON )
+#define PLAYER_MAY_NOT_GET_WEAPON( pstate, ob ) ( PLAYER_IS_SWITCHING_WEAPONS( pstate ))// || IS_ATTACKING( ob ) )
+#define OK_TO_PICK_UP( tstat, pstate, ob ) ( !( IS_WEAPON( tstat ) && PLAYER_MAY_NOT_GET_WEAPON( pstate, ob ) ) )
+#define WHERE_PLAYER_DROPPED_WEAPON( ob, pstate ) ( ( ( ob )->tilex == ( pstate )->weaponx ) && ( ( ob )->tiley == ( pstate )->weapony ) )
+
+ if ( OBJECT_IS_BONUS( tstat ) &&
+ OK_TO_PICK_UP( tstat, pstate, ob ) &&
+ (!WHERE_PLAYER_DROPPED_WEAPON( ob, pstate ))
+ )
+ {
+ GetBonus(ob,tstat);
+ if (PLAYER_IS_SWITCHING_WEAPONS( pstate ))
+ { statetype *nstate;
+#if (SHAREWARE == 0)
+ if (ob->state->condition & SF_DOGSTATE)
+ nstate = &s_serialdog;
+ else
+#endif
+ nstate = &s_player;
+ pstate->attackframe = pstate->weaponframe = pstate->batblast = 0;
+ NewState(ob,nstate);
+ }
+
+
+ }
+ else if ((tstat->itemnumber == stat_pit) &&
+ (ob->temp2 != PITFALL) &&
+ (!(ob->flags & FL_FLEET))
+ )
+ { ob->temp2 = PITFALL;
+ ob->momentumx = ob->momentumy = 0;
+ //ob->momentumz = 4;
+ ob->momentumz = GRAVITY;
+
+ if (ob->whatever == NULL)
+ { ob->whatever = tstat;
+ SD_PlaySoundRTP(SD_PITTRAPSND,ob->x,ob->y);
+ tstat->shapenum = stats[tstat->itemnumber].picnum + 1;
+ MakeStatInactive(tstat);
+ //tstat->flags &= ~FL_ABP;
+ }
+ }
+ else if ((tstat->itemnumber == stat_heatgrate) &&
+ (!(ob->flags & FL_DYING)) && (!(ob->flags & FL_AV))
+ )
+ { DamageThing(ob,1);
+ Collision(ob,(objtype*)tstat,0,0);
+ M_CheckPlayerKilled(ob);
+ }
+
+
+ }
+ }
+
+//================ Check special player/actor links ======================
+
+ if (ob->whatever)
+ { temp = (objtype*)(ob->whatever);
+
+ dx = abs(ob->x - temp->x);
+ dy = abs(ob->y - temp->y);
+ dz = abs(ob->z - temp->z);
+ if (ob->flags & FL_RIDING)
+ rad = MINACTORDIST;
+ else
+ rad = 0x8000;
+
+ if ((dx >rad) || (dy > rad) || (dz > 64))
+ {
+ if ((temp->obclass == bladeobj) || (temp->obclass == diskobj))
+ { temp->whatever = NULL;
+ ob->flags &= ~FL_RIDING;
+ }
+
+ else if (ob->temp2 == COLUMNCRUSH)
+ ob->temp2 = RENORMALIZE;
+ else if (ob->z < nominalheight)
+ ob->momentumz = 40000;
+ else if (temp->which == SPRITE)
+ { tstat = (statobj_t*)(ob->whatever);
+ MakeStatActive(tstat);
+ SetNormalHorizon(ob);
+ }
+ ob->whatever = NULL;
+ }
+ }
+
+//=========================================================================
+
+
+ if (BATTLEMODE && (MAPSPOT(ob->tilex,ob->tiley,1) == EXITTILE))
+ {
+ Move_Player_From_Exit_To_Start(ob);
+ return;
+ }
+
+ if (ob==player)
+ {
+ if (MAPSPOT(ob->tilex,ob->tiley,1) == EXITTILE)
+ playstate=ex_completed;
+ else if ( ( MAPSPOT( ob->tilex, ob->tiley, 2 ) & 0xff00 ) == 0xe400 )
+ playstate = ex_secretdone;
+ else if (MAPSPOT(ob->tilex,ob->tiley,1) == SECRETEXITTILE)
+ playstate=ex_secretlevel;
+ }
+}
+
+
+
+void Move_Player_From_Exit_To_Start(objtype *ob)
+{
+ int i = 0,oldarea,newarea;
+ objtype *tplayer;
+ int travelangle,dangle;
+ playertype *pstate;
+
+ M_LINKSTATE(ob,pstate);
+
+
+ oldarea = ob->areanumber;
+ newarea = AREANUMBER(FIRST.x,FIRST.y);
+ if (oldarea != newarea)
+ {
+ RemoveFromArea(ob);
+ ob->areanumber = newarea;
+ MakeLastInArea(ob);
+ }
+
+ SetTilePosition(ob,FIRST.x,FIRST.y);
+ ob->z = PlatformHeight(ob->tilex,ob->tiley);
+ if ((ob->z == -10) || DiskAt(ob->tilex,ob->tiley))
+ ob->z = 0;
+
+ ConnectAreas();
+ travelangle = atan2_appx(ob->momentumx,ob->momentumy);
+ dangle = ob->angle - travelangle;
+
+ ob->angle = (1-FIRST.dir)*ANG90 + dangle;
+ Fix(ob->angle);
+
+ ob->dir = angletodir[ob->angle];
+ pstate->anglefrac= (ob->angle<<ANGLEBITS);
+ pstate->angle=0;
+
+
+ for(i=0; i<numplayers; i++)
+ {
+ tplayer = PLAYER[i];
+
+ if (ob == tplayer)
+ continue;
+
+ if (
+ (tplayer->tilex == FIRST.x) &&
+ (tplayer->tiley == FIRST.y) &&
+ (!(tplayer->flags & FL_DYING))
+ )
+ {
+ playertype *pstate;
+
+ M_LINKSTATE(tplayer,pstate);
+
+ pstate->health = tplayer->hitpoints = 0;
+ tplayer->flags |= FL_HBM;
+ Collision(tplayer,ob,0,0);
+ BATTLE_PlayerKilledPlayer(battle_kill_by_crushing,ob->dirchoosetime,tplayer->dirchoosetime);
+ \
+
+ }
+ }
+
+
+}
+
+
+
+void PlayerSlideMove(objtype * ob)
+{ int tryx, tryy, tryz;
+
+ tryx = ob->x + ob->momentumx;
+ tryy = ob->y + ob->momentumy;
+ tryz = ob->z + (ob->momentumz >> 16);
+
+ if (ActorTryMove(ob,ob->x,tryy,tryz))
+ {
+ if (ob->momentumx>HITWALLSPEED)
+ SD_PlaySoundRTP(SD_HITWALLSND,ob->x,ob->y);
+ ob->momentumx=0;
+ }
+ else if (ActorTryMove(ob,tryx,ob->y,tryz))
+ {
+ if (ob->momentumy>HITWALLSPEED)
+ SD_PlaySoundRTP(SD_HITWALLSND,ob->x,ob->y);
+ ob->momentumy=0;
+ }
+ else
+ {
+ if (FindDistance(ob->momentumx,ob->momentumy)>(HITWALLSPEED*3/2))
+ SD_PlaySoundRTP(SD_HITWALLSND,ob->x,ob->y);
+ ob->momentumx=0;
+ ob->momentumy=0;
+ }
+}
+
+/*
+===================
+=
+= SetNormalHorizon
+=
+===================
+*/
+
+void SetNormalHorizon (objtype * ob)
+{
+ playertype * pstate;
+
+ M_LINKSTATE(ob,pstate);
+
+ if (ob->flags&FL_DOGMODE)
+ {
+ SetPlayerHorizon(pstate,DOGYZANGLE);
+ }
+ else if (ob->flags&FL_GODMODE)
+ {
+ SetPlayerHorizon(pstate,GODYZANGLE);
+ }
+ else
+ {
+ SetPlayerHorizon(pstate,NORMALYZANGLE);
+ }
+}
+
+/*
+===================
+=
+= PlayerTiltHead
+=
+===================
+*/
+extern int iG_playerTilt;
+extern double dTopYZANGLELIMIT;
+void PlayerTiltHead (objtype * ob)
+{
+ playertype * pstate;
+ int dyz=0;
+ int yzangle;
+
+//bna++ jumpmode
+ if ((donttilt > 0)) {
+ donttilt--;
+ return;
+ }
+
+ M_LINKSTATE(ob,pstate);
+
+ yzangle=ob->yzangle+HORIZONYZOFFSET;
+ Fix(yzangle);
+
+ if (
+ (pstate->lastmomz!=ob->momentumz) &&
+ (ob->momentumz==0) &&
+ (
+ (!(ob->flags&FL_FLEET)) ||
+ (
+ (ob->flags&FL_FLEET) &&
+ (ob->z==nominalheight)
+ )
+ )
+ )
+ SetNormalHorizon(ob);
+
+ pstate->lastmomz=ob->momentumz;
+
+ if (ob->flags&FL_SHROOMS)
+ {
+ ob->yzangle = FixedMulShift(SHROOMYZANGLE,sintable[(oldpolltime<<6)&(FINEANGLES-1)],16);
+ Fix(ob->yzangle);
+ return;
+ }
+ else if (pstate->guntarget)
+ {
+ int dx,dy,dz;
+ int xydist;
+ int yzangle;
+
+ dx = ob->x - pstate->guntarget->x;
+ dy = ob->y - pstate->guntarget->y;
+ xydist = FindDistance(dx,dy)-0x8000;
+ if (ob->z==pstate->guntarget->z)
+ dz = 0;
+ else
+ {
+ dz = (ob->z-pstate->guntarget->z)<<10;
+ }
+ yzangle = atan2_appx(xydist,dz);
+
+ yzangle += HORIZONYZOFFSET;
+ Fix(yzangle);
+ SetPlayerHorizon(pstate,yzangle-HORIZONYZOFFSET);
+
+ if (oldpolltime>pstate->targettime)
+ {
+ if (pstate->guntarget)
+ pstate->guntarget->flags &= ~FL_TARGET;
+ pstate->guntarget=NULL;
+ SetNormalHorizon(ob);
+ }
+ }
+ else
+ {
+ if (pstate->buttonstate[bt_horizonup])
+ {
+ if (yzangle!=pstate->horizon)
+ {
+ SetPlayerHorizon(pstate,yzangle-HORIZONYZOFFSET);
+ }
+ else
+ {
+ SetPlayerHorizon(pstate,(pstate->horizon-HORIZONYZOFFSET+YZHORIZONSPEED));
+ }
+ }
+ else if (pstate->buttonstate[bt_horizondown])
+ {
+ if (yzangle!=pstate->horizon)
+ {
+ SetPlayerHorizon(pstate,yzangle-HORIZONYZOFFSET);
+ }
+ else
+ {
+ SetPlayerHorizon(pstate,(pstate->horizon-HORIZONYZOFFSET-YZHORIZONSPEED));
+ }
+ }
+ if (pstate->buttonstate[bt_lookup] || CYBERLOOKUP)
+ {
+ if (!(ob->flags & FL_FLEET))
+ {
+ dyz=YZTILTSPEED;
+ if (pstate->buttonstate[bt_lookdown] || CYBERLOOKDOWN)
+ {
+ dyz=0;
+ }
+
+ SetNormalHorizon(ob);
+ }
+ }
+ if (pstate->buttonstate[bt_lookdown] || CYBERLOOKDOWN)
+ {
+ if (!(ob->flags & FL_FLEET))
+ {
+ dyz=-YZTILTSPEED;
+ if (pstate->buttonstate[bt_lookup] || CYBERLOOKUP)
+ {
+ dyz=0;
+ }
+ SetNormalHorizon(ob);
+ }
+ }
+ if (!(ob->flags&FL_DOGMODE) &&
+ !(ob->flags&FL_GODMODE) &&
+ !(ob->flags&FL_FLEET) &&
+ !(ob->flags&FL_RIDING) &&
+ (ob->momentumz > (GRAVITY<<1))//(ob->momentumz>0x1000)
+ )
+ {
+ SetPlayerHorizon(pstate,FALLINGYZANGLE);
+ }
+ }
+
+
+
+ if ((yzangle!=pstate->horizon) && (dyz==0))
+ {
+ int speed;
+
+ speed=SNAPBACKSPEED;
+ if (yzangle<pstate->horizon)
+ yzangle+=speed;
+ else
+ yzangle-=speed;
+ if ((abs(yzangle-pstate->horizon))<SNAPBACKSPEED)
+ yzangle=pstate->horizon;
+ }
+//SetTextMode();
+
+ if (yzangle != 512) {
+ FinddTopYZANGLELIMITvalue(ob);
+ }
+
+
+ yzangle+=dyz;
+ if (yzangle-HORIZONYZOFFSET>YZANGLELIMIT)
+ yzangle=HORIZONYZOFFSET+YZANGLELIMIT;
+ /* else if (yzangle-HORIZONYZOFFSET<-TopYZANGLELIMIT)//bnafix
+ yzangle=HORIZONYZOFFSET-TopYZANGLELIMIT;//bnafix
+ dTopYZANGLELIMIT*/
+ else if (yzangle-HORIZONYZOFFSET<-dTopYZANGLELIMIT)//bnafix
+ yzangle=HORIZONYZOFFSET-dTopYZANGLELIMIT;//bnafix
+ ob->yzangle=yzangle-HORIZONYZOFFSET;
+ Fix(ob->yzangle);
+
+ iG_playerTilt = ob->yzangle;
+
+}
+
+//----------------------------------------------------------------------
+// bna added function
+// if a player is to close to wall, looking down max
+//,this func limit the dTopYZANGLELIMIT value when
+// facing a wall
+#define SMALLANGLE 90
+//there is small angles where didnt work
+//so we check for them to = 90/2048 = aprox, 15 degrees
+int FinddTopYZANGLELIMITvalue(objtype *ob)
+{ /*
+
+
+ checkx = ob->tilex + 1;
+ checky = ob->tiley + 1;
+ if (actorat[checkx][checky]){
+ return 0;
+ }
+ return 1;
+
+ checkx = ob->tilex ;
+ checky = ob->tiley;
+
+ // find which direction the player is facing
+ //and check if it is a wall
+
+ */
+
+ //use lowest down angle
+ dTopYZANGLELIMIT = (26*FINEANGLES/360);
+
+ if (ob->angle < 256 || ob->angle > 1792) {
+ if ((tilemap[ob->tilex + 1][ob->tiley])!=0) {
+
+ return 0;
+ }
+ //ob->dir = east;
+ } else if (ob->angle < 768) {
+ if ((tilemap[ob->tilex][ob->tiley-1])!=0) {
+ return 0;
+ }
+ } else if (ob->angle < 1280) {
+ if ((tilemap[ob->tilex-1][ob->tiley])!=0) {
+ return 0;
+ }
+ } else {
+ if ((tilemap[ob->tilex][ob->tiley+1])!=0) {
+ return 0;
+ }
+ }
+
+
+ //use middle down angle
+ dTopYZANGLELIMIT = (42*FINEANGLES/360);
+
+ if ((ob->angle > 768-SMALLANGLE)&&(ob->angle <= 768)) {
+ if ((tilemap[ob->tilex -1][ob->tiley])!=0) { //ob->tiley-1
+ return 0;
+ }
+ }
+ if ((ob->angle < 1280+SMALLANGLE)&&(ob->angle >= 1280)) {
+ if ((tilemap[ob->tilex - 1][ob->tiley])!=0) { //ob->tiley+1
+ return 0;
+ }
+ }
+ if ((ob->angle > 256)&&(ob->angle <= 256+SMALLANGLE)) {
+ if ((tilemap[ob->tilex + 1][ob->tiley])!=0) { //ob->tiley-1
+ return 0;
+ }
+ }
+ if ((ob->angle < 1792)&&(ob->angle >= 1792-SMALLANGLE)) {
+ if ((tilemap[ob->tilex + 1][ob->tiley])!=0) { //ob->tiley+1
+ return 0;
+ }
+ }
+ if ((ob->angle < 1280)&&(ob->angle >= 1280-SMALLANGLE)) {
+ if ((tilemap[ob->tilex ][ob->tiley+1])!=0) { //ob->tilex-1
+ return 0;
+ }
+ }
+ if ((ob->angle > 1792)&&(ob->angle <= 1792+SMALLANGLE)) {
+ if ((tilemap[ob->tilex ][ob->tiley+1])!=0) { //ob->tiley+1
+ return 0;
+ }
+ }
+ if ((ob->angle > 768)&&(ob->angle <= 768+SMALLANGLE)) {
+ if ((tilemap[ob->tilex][ob->tiley-1])!=0) { //ob->tiley-1
+ return 0;
+ }
+ }
+ if ((ob->angle < 256)&&(ob->angle >= 256-SMALLANGLE)) {
+ if ((tilemap[ob->tilex][ob->tiley-1])!=0) { //ob->tiley-1
+ return 0;
+ }
+ }
+
+ //use max down angle
+ dTopYZANGLELIMIT = (90*FINEANGLES/360);
+ return 1;
+}
+// bna added function end
+//----------------------------------------------------------------------
+
+
+
+
+/*
+===================
+=
+= UpdatePlayers
+=
+=================== QWERTYU
+*/
+void UpdatePlayers ( void )
+{
+ objtype * obj;
+// playertype * pstate;
+
+ for (obj = FIRSTACTOR; obj->obclass==playerobj; obj = obj->next)
+ {
+
+//ErrorDontQuit("obj->next = ",obj->next);
+#if (BNACRASHPREVENT == 1)//crashed here when oscuro and larves were all killed
+ if (obj->next == 0) {
+ return;
+ }
+#endif
+ obj->speed=FindDistance(obj->momentumx, obj->momentumy);
+// M_LINKSTATE(obj,pstate);
+// pstate->steptime-=obj->speed;
+// if (pstate->steptime<0)
+// {
+// while (pstate->steptime<0)
+// pstate->steptime+=PLAYERSTEPTIME;
+// pstate->stepwhich^=1;
+// SD_PlaySoundRTP(SD_WALK1SND+pstate->stepwhich,obj->x,obj->y);
+// }
+ }
+}
+
+
+/*
+===================
+=
+= PlayerMove
+=
+===================
+*/
+
+void PlayerMove ( objtype * ob )
+{ playertype *pstate;
+
+ M_LINKSTATE(ob,pstate);
+ if (ob->flags & FL_FLEET)
+ CheckFlying(ob,pstate);
+ ActorMovement(ob);
+ pstate->anglefrac = (pstate->anglefrac+pstate->angle)&((FINEANGLES<<ANGLEBITS)-1);
+ ob->angle = (pstate->anglefrac >> ANGLEBITS);
+ ob->dir = angletodir[ob->angle];
+ if (ob==player)
+ UpdateLightLevel(player->areanumber);
+
+ PlayerTiltHead(ob);
+
+ if (IsWindow(ob->tilex,ob->tiley))
+ {
+ if (!(ob->flags & FL_DYING))
+ {
+ pstate->health = 0;
+ pstate->falling=true;
+ if ((ob->flags & FL_GODMODE) || (ob->flags & FL_DOGMODE) ||
+ (gamestate.battlemode == battle_Eluder) || (godmode==true))
+ {
+ KillActor(ob);
+ NewState(ob,&s_remotedie1);
+ }
+ else
+ Collision(ob,(objtype*)NULL,0,0);
+ ob->flags |= FL_DYING;
+ M_CheckPlayerKilled(ob);
+ }
+ }
+}
+
+/*
+===============
+=
+= T_Tag
+=
+===============
+*/
+
+void T_Tag (objtype *ob)
+{
+ playertype *pstate;
+
+ CheckPlayerSpecials(ob);
+ //CheckWeaponStates(ob);
+ M_LINKSTATE(ob,pstate);
+ Thrust(ob);
+
+ if (ob->ticcount > 4)
+ pstate->weaponheight -= GMOVE;
+ else
+ pstate->weaponheight += GMOVE;
+
+ if ((ob->ticcount > 1) && (ob->ticcount < 8) && (!(ob->flags & FL_DIDTAG)))
+ { int i,dx,dy,magangle;
+
+ for(i=0; i<numplayers; i++)
+ { if (PLAYER[i] == ob)
+ continue;
+
+ dx = abs(PLAYER[i]->x - ob->x);
+ dy = abs(PLAYER[i]->y - ob->y);
+ if ((dx > 0xc000) || (dy > 0xc000))
+ continue;
+ magangle = abs(ob->angle - AngleBetween(ob,PLAYER[i]));
+ if (magangle > VANG180)
+ magangle = ANGLES - magangle;
+
+ if (magangle > ANGLES/8)
+ continue;
+ CheckTagGame(ob,PLAYER[i]);
+ break;
+ }
+
+ }
+
+
+//Commented out until we find if it's valid
+ /*
+ if (!ob->ticcount)
+ {if ( pstate->buttonstate[bt_use] && !pstate->buttonheld[bt_use] )
+ pstate->buttonstate[bt_use] = false;
+ if ( pstate->buttonstate[bt_attack] && !pstate->buttonheld[bt_attack])
+ pstate->buttonstate[bt_attack] = false;
+ }
+ */
+}
+
+#if (SHAREWARE == 0)
+#define GET_RESETSTATE(ob,resetstate) \
+ { \
+ if (ob->state->condition & SF_DOGSTATE) \
+ resetstate = &s_serialdog; \
+ else \
+ resetstate = &s_player; \
+ }
+#else
+#define GET_RESETSTATE(ob,resetstate) \
+ { \
+ resetstate = &s_player; \
+ }
+#endif
+
+/*
+===============
+=
+= T_Attack
+=
+===============
+*/
+
+void T_Attack (objtype *ob)
+{
+ attack_t *cur;
+
+ playertype *pstate;
+ statetype *resetstate;
+
+
+ Thrust(ob);
+ if (ob->flags & FL_DYING)
+ return;
+
+ resetstate = ob->state;
+ CheckPlayerSpecials(ob);
+ if (resetstate != ob->state)
+ {
+ return;
+ }
+
+
+ if ((ob->flags & FL_PAIN) && (!ob->ticcount))
+ ob->flags &= ~FL_PAIN;
+
+ CheckWeaponStates(ob);
+ M_LINKSTATE(ob,pstate);
+ GET_RESETSTATE(ob,resetstate);
+
+
+ if (ARMED(ob->dirchoosetime)
+ //(gamestate.battlemode != battle_Tag)
+ )
+
+ {
+ if (pstate->weapondowntics == 1) // change to up; during change, up and down
+ // are never zero at the same time
+ {
+#if (SHAREWARE == 0)
+ if (pstate->weapon == wp_kes)
+ {
+ pstate->weapondowntics = 0;
+ pstate->weaponuptics = KESTICS/(2*GMOVE);
+ }
+ else
+#endif
+ {
+ pstate->weapondowntics = 0;
+ pstate->weaponframe = pstate->attackframe = 0;
+
+ if (pstate->NETCAPTURED == -1)
+ {
+ pstate->weaponuptics = FREE.screenheight/GMOVE;
+ pstate->weaponheight = pstate->weaponuptics*GMOVE ;
+ pstate->NETCAPTURED = 1;
+ // return;
+ }
+ else if (pstate->NETCAPTURED == -2)
+ {
+ pstate->weaponuptics = WEAPONS[pstate->weapon].screenheight/GMOVE;
+ pstate->weaponheight = pstate->weaponuptics*GMOVE ;
+ pstate->NETCAPTURED = 0;
+
+ //return;
+ }
+ else
+ {
+ pstate->weaponuptics = WEAPONS[pstate->new_weapon].screenheight/GMOVE;
+ pstate->weapon = pstate->new_weapon;
+ pstate->weaponheight = pstate->weaponuptics*GMOVE ;
+ }
+ }
+ }
+ }
+ else if (gamestate.battlemode == battle_Hunter)
+ {
+ if (pstate->weapondowntics == 1)
+
+ {
+ pstate->weapondowntics = 0;
+ pstate->weaponframe = pstate->attackframe = pstate->batblast = 0;
+ pstate->weapon = pstate->new_weapon;
+ NewState(ob,resetstate);
+ return;
+ }
+ }
+
+
+
+
+#if (SHAREWARE==0)
+ if ((pstate->buttonstate[bt_use]) &&
+ (pstate->weapon != wp_dog)
+ )
+#else
+ if (pstate->buttonstate[bt_use])
+#endif
+ Cmd_Use (ob);
+
+ if (pstate->attackframe >= WEAPONS[pstate->weapon].numattacks)
+ Error("\n attackframe %d for weapon %d gt numattacks %d",
+ pstate->attackframe,pstate->weapon,
+ WEAPONS[pstate->weapon].numattacks
+ );
+
+ cur = &(WEAPONS[pstate->weapon].attackinfo[pstate->attackframe]);
+ if (! pstate->attackcount)
+ {
+ switch (cur->attack)
+ {
+ case reset:
+ if (vrenabled && (ob==player))
+ {
+ StopVRFeedback();
+ }
+ ob->flags &= ~FL_FULLLIGHT;
+ if (pstate->ammo)
+ {
+ if (BATTLEMODE && (pstate->weapon == wp_firewall))
+ break;
+ if (BATTLEMODE && (pstate->weapon == wp_firebomb))
+ break;
+ if ((pstate->buttonstate[bt_attack]) && (pstate->weapon <= wp_firewall))
+ {
+ if (pstate->weapon <= wp_mp40)
+ {
+ if (pstate->weapon == wp_twopistol)
+ pstate->attackframe -= 6;
+ else if (pstate->weapon == wp_pistol)
+ pstate->attackframe -= 3;
+ else if (pstate->weapon == wp_mp40)
+ pstate->attackframe -= 2;
+
+ if (ob->state == &s_pmissattack2)
+ NewState(ob,&s_pmissattack1);
+ else if (ob->state == &s_pgunattack2)
+ NewState(ob,&s_pgunattack1);
+
+ }
+
+ }
+ else
+ {
+ NewState(ob,resetstate);
+ pstate->attackframe = pstate->weaponframe = 0;
+ pstate->batblast = 0;
+ return;
+ }
+ }
+ else
+ {
+ NewState(ob,resetstate);
+ pstate->attackframe = pstate->weaponframe = 0;
+ pstate->new_weapon = pstate->bulletweapon;
+ pstate->batblast = 0;
+ pstate->ammo = -1;
+ pstate->missileweapon = -1;
+ pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/GMOVE;
+
+ if ((ob==player) && SHOW_BOTTOM_STATUS_BAR() )
+ DrawBarAmmo (false);
+
+ return;
+ }
+ break;
+
+ case reset2:
+ if (vrenabled && (ob==player))
+ {
+ StopVRFeedback();
+ }
+ ob->flags &= ~FL_FULLLIGHT;
+ if (pstate->buttonstate[bt_attack] && pstate->ammo)
+ {
+ pstate->attackframe -= 4;
+ if (ob->state == &s_pmissattack2)
+ NewState(ob,&s_pmissattack1);
+ else if (ob->state == &s_pgunattack2)
+ NewState(ob,&s_pgunattack1);
+ }
+ else
+ {
+ NewState(ob,resetstate);
+ pstate->attackframe = pstate->weaponframe = 0;
+ pstate->batblast = 0;
+ return;
+ }
+
+ break;
+
+
+ case at_pulltrigger:
+ if (vrenabled && (ob==player))
+ {
+ StartVRFeedback(1);
+ }
+ ob->flags |= FL_FULLLIGHT;
+
+#if (SHAREWARE == 0)
+
+ if (pstate->batblast >= BBTIME)
+ DogBlast(ob);
+
+ else if (pstate->weapon == wp_dog)
+ DogAttack(ob);
+ else if (pstate->weapon == wp_bat)
+ BatAttack (ob);
+ else
+#endif
+ GunAttack(ob);
+
+ break;
+
+ case at_missileweapon:
+ if (!pstate->ammo)
+ {
+ pstate->attackframe = pstate->weaponframe = 0;
+ pstate->batblast = 0;
+ return;
+ }
+
+ if (vrenabled && (ob==player))
+ {
+ StartVRFeedback(1);
+ }
+ ob->flags |= FL_FULLLIGHT;
+ if (ob==player)
+ SetIllumination(2);
+ PlayerMissileAttack(ob);
+
+
+ if (!(ob->flags & FL_GODMODE) && !godmode)
+ {
+ if (!BATTLEMODE || (gamestate.BattleOptions.Ammo != bo_infinite_shots))
+ pstate->ammo--;
+
+ if ((ob==player) && SHOW_BOTTOM_STATUS_BAR() )
+ DrawBarAmmo (false);
+ }
+#if (SHAREWARE == 0)
+ if (pstate->weapon == wp_kes)
+ pstate->weapondowntics = KESTICS/(2*GMOVE);
+#endif
+ break;
+
+ default:
+ ;
+ }
+
+ pstate->attackframe++;
+ cur = &(WEAPONS[pstate->weapon].attackinfo[pstate->attackframe]);
+ pstate->weaponframe = cur->frame;
+ pstate->attackcount = cur->mtics;
+
+ }
+ else
+ pstate->attackcount --;
+}
+
+/*
+===============
+=
+= T_BatBlast
+=
+===============
+*/
+
+void T_BatBlast (objtype *ob)
+{
+ attack_t *cur;
+ playertype *pstate;
+
+
+ Thrust(ob);
+ CheckPlayerSpecials(ob);
+ M_LINKSTATE(ob,pstate);
+
+
+//Commented out until we find if it's valid
+ /*
+ if (!ob->ticcount)
+ {if ( pstate->buttonstate[bt_use] && !pstate->buttonheld[bt_use] )
+ pstate->buttonstate[bt_use] = false;
+
+ if ( pstate->buttonstate[bt_attack] && !pstate->buttonheld[bt_attack])
+ pstate->buttonstate[bt_attack] = false;
+ }
+ */
+//
+// change frame and fire
+//
+
+ BatBlast(ob);
+
+
+
+ if (pstate->attackframe >= WEAPONS[pstate->weapon].numattacks)
+ Error("\n attackframe %d for weapon %d gt numattacks %d",
+ pstate->attackframe,pstate->weapon,
+ WEAPONS[pstate->weapon].numattacks
+ );
+
+
+
+ cur = &(WEAPONS[pstate->weapon].attackinfo[pstate->attackframe]);
+ if (! pstate->attackcount)
+ { if (cur->attack == reset)
+ {
+ if (!(ob->flags & FL_GODMODE) && (!godmode))
+ { pstate->ammo --;
+ if ((ob==player) && SHOW_BOTTOM_STATUS_BAR() )
+ DrawBarAmmo (false);
+ }
+
+ if (!pstate->ammo)
+ { pstate->new_weapon = pstate->bulletweapon;
+ pstate->ammo = -1;
+ pstate->missileweapon = -1;
+ pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/GMOVE;
+
+ }
+
+ NewState(ob,&s_player);
+ pstate->attackframe = pstate->weaponframe = 0;
+ pstate->batblast = 0;
+ return;
+ }
+ pstate->attackframe++;
+ pstate->weaponframe = WEAPONS[pstate->weapon].attackinfo[pstate->attackframe].frame;
+ cur = &(WEAPONS[pstate->weapon].attackinfo[pstate->attackframe]);
+ pstate->attackcount = cur->mtics;
+ }
+ else
+ pstate->attackcount --;
+
+}
+
+
+
+
+void T_Free (objtype *ob)
+{
+ attack_t *cur;
+
+
+ if (!ob->ticcount)
+ {
+
+
+//Commented out until we find if it's valid
+ /*
+ if ( locplayerstate->buttonstate[bt_use] && !locplayerstate->buttonheld[bt_use] )
+ locplayerstate->buttonstate[bt_use] = false;
+
+ if ( locplayerstate->buttonstate[bt_attack] && !locplayerstate->buttonheld[bt_attack])
+ locplayerstate->buttonstate[bt_attack] = false;
+ */
+ Thrust(ob);
+
+ }
+ CheckPlayerSpecials(ob);
+
+
+
+
+
+
+ cur = &(FREE.attackinfo[locplayerstate->attackframe]);
+
+ if (!locplayerstate->attackcount)
+ {
+ if ((locplayerstate->weaponframe > 3) && (locplayerstate->weaponframe < 8))
+ locplayerstate->NETCAPTURED ++;
+ else if (locplayerstate->weaponframe == 8)
+ {
+ locplayerstate->NETCAPTURED = -2;
+ MISCVARS->NET_IN_FLIGHT = false;
+ NewState(ob,&s_player);
+ locplayerstate->weapondowntics = FREE.screenheight/GMOVE;
+ return;
+ }
+
+ locplayerstate->attackframe++;
+ cur = &(FREE.attackinfo[locplayerstate->attackframe]);
+ locplayerstate->weaponframe = cur->frame;
+
+ locplayerstate->attackcount = cur->mtics;
+
+ }
+ else
+ locplayerstate->attackcount --;
+}
+
+
+
+void Switch_Who_Is_It_For_Tag(objtype *actor1,objtype *actor2)
+{
+ playertype *pstate;
+
+ M_LINKSTATE(actor1,pstate);
+ if (pstate->buttonstate[bt_use])
+ { playertype *pstate2;
+
+ M_LINKSTATE(actor2,pstate2);
+ pstate2->oldmissileweapon = pstate2->oldweapon = pstate2->new_weapon =
+ pstate2->missileweapon = pstate2->weapon = wp_godhand;
+ pstate2->weaponheight = 144;
+ pstate2->weaponuptics = (144 - TAGHANDHEIGHT)/GMOVE;
+ pstate2->weapondowntics = 0;
+ actor1->flags |= FL_DIDTAG;
+ actor2->flags |= FL_DESIGNATED;
+ UpdateKills = true;
+
+ actor1->flags &= ~FL_DESIGNATED;
+ BATTLE_PlayerKilledPlayer(battle_player_tagged,
+ actor1->dirchoosetime, actor2->dirchoosetime);
+ }
+
+}
+
+
+
+void CheckTagGame(objtype *actor1,objtype*actor2)
+{
+//if ((actor1->obclass != playerobj) || (actor2->obclass != playerobj))
+ //return;
+
+ if (!BATTLEMODE)
+ return;
+
+ if (gamestate.battlemode != battle_Tag)
+ return;
+
+ SD_PlaySoundRTP(SD_GETBONUSSND,actor1->x,actor1->y);
+
+ if (actor1->flags & FL_DESIGNATED)
+ Switch_Who_Is_It_For_Tag(actor1,actor2);
+ else if (actor2->flags & FL_DESIGNATED)
+ Switch_Who_Is_It_For_Tag(actor2,actor1);
+
+}
+
+
+
+
+
+
+/*
+======================
+=
+= CheckWeaponChange
+=
+= Keys 1-4 change weapons
+=
+======================
+*/
+
+void CheckWeaponChange (objtype * ob)
+{
+// int i;
+
+ playertype * pstate;
+
+
+ M_LINKSTATE(ob,pstate);
+ //pstate = (ob == player)?(&playerstate):(&remoteplayerstate);
+ if (W_CHANGE(pstate))
+ return;
+
+ if (!ARMED(ob->dirchoosetime))
+ return;
+
+ if ((ob->flags & FL_DOGMODE) || (ob->flags & FL_GODMODE))
+ return;
+
+#if (WEAPONCHEAT==1)
+ if (godmode && Keyboard[sc_Insert])
+ {
+ SD_Play(SD_SELECTWPNSND);
+
+ // FOR DEBUG only
+ /*
+ if (pstate->buttonstate[bt_run])
+ {
+ if (pstate->weapon == 0)
+ pstate->new_weapon = wp_bat;
+ else
+ pstate->new_weapon --;
+ }
+ else
+ {*/
+ if (pstate->weapon == MAXWEAPONS-1)
+ pstate->new_weapon = 0;
+ else
+ pstate->new_weapon ++;
+ //}
+ if (pstate->new_weapon <= wp_mp40)
+ { pstate->bulletweapon = pstate->new_weapon;
+ pstate->HASBULLETWEAPON[pstate->new_weapon] = 1;
+ }
+ else
+ pstate->missileweapon = pstate->new_weapon;
+
+ pstate->ammo = stats[GetItemForWeapon(pstate->missileweapon)].ammo;
+ if (pstate->ammo<1)
+ pstate->ammo=5;
+ StartWeaponChange;
+ //pstate->weapondowntics = WEAPONS[pstate->weapon].screenheight/GMOVE;
+ //if ((ob==player) && SHOW_BOTTOM_STATUS_BAR() )
+ // DrawBarAmmo (false);
+ }
+ else if (pstate->buttonstate[bt_swapweapon])
+#else
+ if (pstate->buttonstate[bt_swapweapon])
+#endif
+ {
+ if ((pstate->weapon == pstate->bulletweapon) &&
+ (pstate->missileweapon != -1))
+ { pstate->new_weapon = pstate->missileweapon;
+ StartWeaponChange;
+ }
+
+ else if (pstate->weapon != pstate->bulletweapon)
+ { pstate->new_weapon = pstate->bulletweapon;
+ StartWeaponChange;
+ }
+ }
+ else if ((pstate->buttonstate[bt_dropweapon]) &&
+ (!gamestate.BattleOptions.WeaponPersistence))
+ {
+ if (pstate->weapon==pstate->bulletweapon)
+ {
+ if ((ob==player) && (!(pstate->buttonheld[bt_dropweapon])))
+ PlayNoWaySound();
+ }
+ else
+ {
+ if (sprites[ob->tilex][ob->tiley])
+ {
+ if ((ob==player) && (!(pstate->buttonheld[bt_dropweapon])))
+ PlayNoWaySound();
+ }
+ else
+ {
+ DropWeapon(ob);
+ }
+ }
+ }
+
+
+
+ if (pstate->buttonstate[bt_pistol])
+ { if (pstate->weapon != wp_pistol)
+ { pstate->new_weapon = pstate->bulletweapon = wp_pistol;
+ StartWeaponChange;
+ }
+ }
+
+ else if (pstate->buttonstate[bt_dualpistol])
+ { if ((pstate->weapon != wp_twopistol) && pstate->HASBULLETWEAPON[wp_twopistol])
+ { pstate->new_weapon = pstate->bulletweapon = wp_twopistol;
+ StartWeaponChange;
+ }
+ }
+ else if (pstate->buttonstate[bt_mp40])
+ { if ((pstate->weapon != wp_mp40) && pstate->HASBULLETWEAPON[wp_mp40])
+ { pstate->new_weapon = pstate->bulletweapon = wp_mp40;
+ StartWeaponChange;
+ }
+ }
+ else if (pstate->buttonstate[bt_missileweapon])
+ { if ((pstate->weapon != pstate->missileweapon) && (pstate->missileweapon != -1))
+ { pstate->new_weapon = pstate->missileweapon;
+ StartWeaponChange;
+ }
+ }
+}
+
+
+void SetWhoHaveWeapons(void)
+{
+ playertype *pstate;
+ objtype *ob;
+ int i;
+
+ for ( i = 0; i < numplayers; i++ )
+ {
+ ob = PLAYER[ i ];
+ M_LINKSTATE( ob, pstate );
+
+ if ( ARMED( ob->dirchoosetime ))
+ {
+ if (pstate->weapon == -1)
+ {
+ if (( pstate->missileweapon != -1 ) && (pstate->ammo>0))
+ pstate->new_weapon = pstate->missileweapon;
+
+ else
+ {
+ if ( pstate->bulletweapon == -1 )
+ {
+ pstate->HASBULLETWEAPON[ wp_pistol ] = 1;
+ pstate->bulletweapon = wp_pistol;
+ }
+ pstate->new_weapon = pstate->bulletweapon;
+ pstate->ammo = -1;
+ }
+
+ pstate->weapon = pstate->new_weapon;
+ pstate->weapondowntics = 0;
+ pstate->weaponuptics = WEAPONS[pstate->new_weapon].screenheight/GMOVE;
+ pstate->weaponheight = pstate->weaponuptics*GMOVE ;
+ pstate->attackframe = pstate->weaponframe =
+ pstate->batblast = 0;
+ if (i == consoleplayer)
+ DrawBarAmmo(false);
+ }
+ }
+ else
+ {
+ if (ob->flags & FL_DOGMODE)
+ {
+ ob->temp2 = DOGMODERISE;
+ pstate->oldweapon = -1;
+ ResetWeapons(ob);
+ if (ob->state->condition & SF_DOGSTATE)
+ NewState(ob,&s_player);
+ }
+ else if (ob->flags & FL_GODMODE)
+ {
+ ob->temp2 = GODMODEFALL;
+ pstate->oldweapon = -1;
+ ResetWeapons(ob);
+ }
+ else
+ {
+ pstate->new_weapon = -1;
+ StartWeaponChange;
+ }
+ pstate->attackframe = pstate->weaponframe =
+ pstate->batblast = 0;
+ }
+ }
+}
+
+
+
+
+
+
+
+
+void CheckWeaponStates(objtype*ob)
+{ playertype *pstate;
+
+ M_LINKSTATE(ob,pstate);
+
+ if (gamestate.battlemode == battle_Tag)
+ { if (pstate->weapondowntics)
+ { pstate->weaponheight += GMOVE;
+ pstate->weapondowntics --;
+ if (!pstate->weapondowntics)
+ pstate->weapon = pstate->missileweapon = pstate->bulletweapon =
+ pstate->new_weapon = pstate->oldweapon = pstate->oldmissileweapon = -1;
+
+ }
+
+
+ if (pstate->weaponuptics)
+ { pstate->weaponheight -= GMOVE;
+ pstate->weaponuptics --;
+ }
+ return;
+ }
+
+ if (pstate->weapondowntics)
+ { pstate->weaponheight += GMOVE;
+#if (SHAREWARE == 0)
+ if ((pstate->weapon == wp_kes) && pstate->attackframe)
+ pstate->weaponheight += GMOVE;
+#endif
+ pstate->weapondowntics --;
+ }
+ else if (pstate->weaponuptics)
+ { pstate->weaponheight -= GMOVE;
+#if (SHAREWARE == 0)
+ if ((pstate->weapon == wp_kes) && pstate->attackframe)
+ pstate->weaponheight -= GMOVE;
+#endif
+
+ pstate->weaponuptics --;
+ }
+ else if ((pstate->weapon == pstate->new_weapon) && (!pstate->NETCAPTURED))
+ pstate->weaponheight = 0;
+
+}
+
+
+/*
+=============================
+=
+= CheckSpecialSounds
+=
+=============================
+*/
+
+#define REGDOGSTATE(ob) \
+ ((ob->state == &s_serialdog) || (ob->state == &s_serialdog2) || \
+ (ob->state == &s_serialdog3) || (ob->state == &s_serialdog4) \
+ )
+
+static int dyingvolume=255;
+void CheckSpecialSounds(objtype *ob, playertype *pstate)
+{
+ int shift;
+
+ if ((!BATTLEMODE) && (ob == player))
+ {
+ if (pstate->health < MaxHitpointsForCharacter(locplayerstate)/5)
+ {
+ pstate->healthtime ++;
+ if (pstate->healthtime > 2*VBLCOUNTER)
+ {
+ pstate->healthtime = 0;
+ SD_PlayPitchedSound ( SD_PLAYERDYINGSND, dyingvolume, 0 );
+ if (dyingvolume>80)
+ dyingvolume-=40;
+ }
+ }
+ else
+ {
+ dyingvolume=255;
+ }
+ }
+
+ if (((ob->flags & FL_GODMODE) || (ob->flags & FL_DOGMODE)) &&
+ (!W_CHANGE(pstate))
+ )
+ {
+ pstate->soundtime++;
+ if (pstate->soundtime > (2*VBLCOUNTER))
+ {
+ int rand;
+
+ rand = GameRandomNumber("player special sound",0);
+ shift = (pstate->soundtime>>5);
+ if ((rand << shift) > 3500)
+ {
+ int sound;
+
+ pstate->soundtime = 0;
+
+ rand = GameRandomNumber("player god scare",0);
+
+ if (ob->flags & FL_GODMODE)
+ {
+ sound = SD_GODMODE1SND;
+ if (rand < 160)
+ sound++;
+ if (rand < 80)
+ sound ++;
+ SD_PlaySoundRTP(sound,ob->x,ob->y);
+ }
+#if (SHAREWARE == 0)
+ else if ((!pstate->batblast) && (!ob->momentumz) &&
+ (REGDOGSTATE(ob))
+ )
+ {
+ sound = SD_DOGMODEPANTSND;
+ if (rand < 128)
+ sound += 2;
+ NewState(ob,&s_doglick);
+ pstate->attackframe = pstate->weaponframe =
+ pstate->batblast = 0;
+ SD_PlaySoundRTP(sound,ob->x,ob->y);
+ }
+#endif
+ }
+ }
+ }
+
+
+
+
+ else if (ob->flags & FL_GASMASK)
+ {
+ pstate->soundtime ++;
+
+ if (pstate->soundtime > (3*VBLCOUNTER))
+ {
+ pstate->soundtime = 0;
+ SD_PlaySoundRTP(SD_GASMASKSND,ob->x,ob->y);
+ }
+ }
+
+
+ else if (MISCVARS->GASON)
+ {
+ pstate->soundtime ++;
+ if (pstate->soundtime > (2*VBLCOUNTER))
+ {
+ int rand;
+
+ rand = GameRandomNumber("player cough sound",0);
+ shift = (pstate->soundtime>>5);
+ if ((rand << shift) > 2000)
+ {
+ pstate->soundtime = 0;
+ if ((pstate->player == 1) || (pstate->player == 3))
+ SD_PlaySoundRTP(SD_PLAYERCOUGHFSND,ob->x,ob->y);
+ else
+ SD_PlaySoundRTP(SD_PLAYERCOUGHMSND,ob->x,ob->y);
+ }
+ }
+ }
+}
+
+/*
+static int dyingvolume=255;
+void CheckSpecialSounds(objtype *ob, playertype *pstate)
+ {
+ int shift;
+
+ if ((!BATTLEMODE) && (ob == player))
+ {
+ if (pstate->health < MaxHitpointsForCharacter(locplayerstate)/5)
+ {
+ pstate->healthtime ++;
+ if (pstate->healthtime > 2*VBLCOUNTER)
+ {
+ pstate->healthtime = 0;
+ SD_PlayPitchedSound ( SD_PLAYERDYINGSND, dyingvolume, 0 );
+ if (dyingvolume>80)
+ dyingvolume-=40;
+ }
+ }
+ else
+ {
+ dyingvolume=255;
+ }
+ }
+
+ if (((ob->flags & FL_GODMODE) || (ob->flags & FL_DOGMODE)) &&
+ (!W_CHANGE(pstate))
+ )
+ {
+ pstate->soundtime++;
+ if (pstate->soundtime > (2*VBLCOUNTER))
+ {
+ int rand;
+
+ rand = GameRandomNumber("player special sound",0);
+ shift = (pstate->soundtime>>5);
+ if ((rand << shift) > 3500)
+ {
+ int sound;
+
+ pstate->soundtime = 0;
+
+ rand = GameRandomNumber("player god scare",0);
+
+ if (ob->flags & FL_GODMODE)
+ {
+ sound = SD_GODMODE1SND;
+ if (rand < 160)
+ sound++;
+ if (rand < 80)
+ sound ++;
+ SD_PlaySoundRTP(sound,ob->x,ob->y);
+ }
+#if (SHAREWARE == 0)
+ else if (!pstate->batblast)
+ {
+ sound = SD_DOGMODEPANTSND;
+ if (rand < 128)
+ sound += 2;
+ NewState(ob,&s_doglick);
+ pstate->attackframe = pstate->weaponframe =
+ pstate->batblast = 0;
+ SD_PlaySoundRTP(sound,ob->x,ob->y);
+ }
+#endif
+ }
+ }
+ }
+
+
+
+
+ else if (ob->flags & FL_GASMASK)
+ {
+ pstate->soundtime ++;
+
+ if (pstate->soundtime > (3*VBLCOUNTER))
+ {
+ pstate->soundtime = 0;
+ SD_PlaySoundRTP(SD_GASMASKSND,ob->x,ob->y);
+ }
+ }
+
+
+ else if (MISCVARS->GASON)
+ {
+ pstate->soundtime ++;
+ if (pstate->soundtime > (2*VBLCOUNTER))
+ {
+ int rand;
+
+ rand = GameRandomNumber("player cough sound",0);
+ shift = (pstate->soundtime>>5);
+ if ((rand << shift) > 2000)
+ {
+ pstate->soundtime = 0;
+ if ((pstate->player == 1) || (pstate->player == 3))
+ SD_PlaySoundRTP(SD_PLAYERCOUGHFSND,ob->x,ob->y);
+ else
+ SD_PlaySoundRTP(SD_PLAYERCOUGHMSND,ob->x,ob->y);
+ }
+ }
+ }
+ }
+
+*/
+
+
+/*
+=============================
+=
+= CheckProtectionsAndPowerups
+=
+=============================
+*/
+
+
+
+void CheckProtectionsAndPowerups(objtype *ob, playertype *pstate)
+{
+ if (pstate->poweruptime)
+ {
+ pstate->poweruptime --;
+ if (pstate->poweruptime < 0)
+ pstate->poweruptime = 0;
+ if (ob==player)
+ GM_UpdateBonus (pstate->poweruptime, true);
+ }
+ else
+ {
+ if (ob->flags & FL_ELASTO)
+ {
+ ob->flags &= ~FL_NOFRICTION;
+ if (ob==player)
+ GM_UpdateBonus (pstate->poweruptime, true);
+ SD_PlaySoundRTP(SD_LOSEMODESND,ob->x, ob->y);
+ }
+ else if (ob->flags & FL_GODMODE)
+ { ob->temp2 = GODMODEFALL;
+ if ((pstate->player == 1) || (pstate->player == 3))
+ SD_PlaySoundRTP(SD_GODWOMANSND,ob->x, ob->y);
+ else
+ SD_PlaySoundRTP(SD_GODMANSND,ob->x, ob->y);
+ ResetWeapons(ob);
+ }
+ else if (ob->flags & FL_DOGMODE)
+ { int wall;
+
+ wall = tilemap[ob->tilex][ob->tiley];
+ if ((wall & 0x4000) && (wall & 0x8000))
+ { maskedwallobj_t * mw;
+
+ mw=maskobjlist[wall&0x3ff];
+ if (mw->flags&MW_NONDOGBLOCKING)
+ return;
+ }
+
+
+ ob->temp2 = DOGMODERISE;
+ if ((pstate->player == 1) || (pstate->player == 3))
+ SD_PlaySoundRTP(SD_DOGWOMANSND,ob->x, ob->y);
+ else
+ SD_PlaySoundRTP(SD_DOGMANSND,ob->x, ob->y);
+ ResetWeapons(ob);
+ if (ob->state->condition & SF_DOGSTATE)
+ {
+ NewState(ob,&s_player);
+ pstate->attackframe = pstate->weaponframe = pstate->batblast = 0;
+ }
+ }
+ else if (ob->flags & FL_SHROOMS)
+ {
+ ResetFocalWidth ();
+ SD_PlaySoundRTP(SD_LOSEMODESND,ob->x, ob->y);
+ }
+ else if (ob->flags & FL_FLEET)
+ SD_PlaySoundRTP(SD_LOSEMODESND,ob->x, ob->y);
+
+ ob->flags &= ~(FL_SHROOMS|FL_ELASTO|FL_FLEET|FL_GODMODE|FL_DOGMODE);
+ }
+
+ if (pstate->protectiontime)
+ {
+ pstate->protectiontime --;
+ if (pstate->protectiontime <= 0)
+ {
+ SD_PlaySoundRTP(SD_LOSEMODESND,ob->x, ob->y);
+ pstate->protectiontime = 0;
+ }
+ if (ob==player)
+ GM_UpdateBonus (pstate->protectiontime, false);
+ }
+ else
+ ob->flags &= ~(FL_BPV|FL_AV|FL_GASMASK);
+
+}
+
+
+
+/*
+=============================
+=
+= CheckFlying
+=
+=============================
+*/
+
+void CheckFlying(objtype*ob,playertype *pstate)
+{
+
+
+ if (pstate->buttonstate[bt_lookup] || CYBERLOOKUP)
+ {
+ ob->momentumz = -FLYINGZMOM;
+ }
+ if (pstate->buttonstate[bt_lookdown] || CYBERLOOKDOWN)
+ {
+ ob->momentumz = FLYINGZMOM;
+ }
+
+ /*
+ if (!M_ISDOOR(((ob->x + costable[ob->angle])>>16),
+ ((ob->y - sintable[ob->angle])>>16)) &&
+ (pstate->buttonstate[bt_use]) &&
+ (!pstate->buttonheld[bt_use])
+ )
+ {
+ int op;
+ int dist;
+
+ dist=JETPACKTHRUST;
+ if (ob->z-dist<-15)
+ dist=ob->z+15;
+ if (dist>0)
+ {
+ op = FixedMul(GRAVITY,(dist<<16)) << 1;
+ ob->momentumz = -FixedSqrtHP(op);
+ SD_PlaySoundRTP(SD_FLYINGSND,ob->x,ob->y);
+ }
+ }
+ */
+}
+
+
+
+/*
+=============================
+=
+= CheckTemp2Codes
+=
+=============================
+*/
+
+
+#define IN_AIR(ob) \
+ (!((ob->z == nominalheight) || \
+ (IsPlatform(ob->tilex,ob->tiley)) || \
+ (DiskAt(ob->tilex,ob->tiley)) \
+ ) \
+ ) \
+
+
+void CheckTemp2Codes(objtype *ob,playertype *pstate)
+{
+ int pitheight;
+ int godheight;
+ int dogheight;
+ int height;
+ int oldz;
+ int destheightoffset;
+
+
+ pitheight = maxheight - 8;
+ height = ob->z + pstate->playerheight;
+ dogheight = ob->z + DOGOFFSET;
+ godheight = ob->z + GODOFFSET;
+
+ //SoftError("\nheightoffset: %d, temp2: %d",pstate->heightoffset,ob->temp2);
+
+
+ if (!((ob->temp2 == PITFALL) || (ob->temp2 == PITRISE)))
+ {
+
+ oldz = ob->z;
+ //SoftError("\n zmom %d, oldz %d, newz %d",ob->momentumz,oldz,ob->z);
+
+ if (ob->flags & FL_FLEET)
+ {
+ if (IN_AIR(ob))
+ pstate->heightoffset = FixedMulShift(0x4000,sintable[(oldpolltime<<6)&2047],28);
+
+ ob->z += ((ob->momentumz+0x8000)>>16);
+ ob->momentumz = 0;
+
+ }
+ else
+ {
+ ob->z += (ob->momentumz>>16);
+ ob->momentumz += GRAVITY;
+ }
+
+
+ if (ob->z >= nominalheight)
+ {
+ ob->z = nominalheight;
+ ob->momentumz = 0;
+ //if (platform == nominalheight)
+ //{//ob->temp2 = 0;
+ //ob->momentumz = 0;
+ if ((oldz < nominalheight) && (!(ob->flags & FL_RIDING)))
+ {
+ SD_PlaySoundRTP(SD_PLAYERLANDSND,ob->x,ob->y);
+ }
+
+ if (!(ob->flags & FL_ELASTO))
+ ob->flags &= ~FL_NOFRICTION;
+ // }
+ }
+ else if (height < 1)
+ {
+ ob->momentumz = 0;
+ ob->z = 1-pstate->playerheight;
+ }
+
+
+
+ switch (ob->temp2)
+ {
+ case RENORMALIZE:
+ pstate->heightoffset --;
+
+ if (ob->flags & FL_DOGMODE)
+ destheightoffset = DOGOFFSET-pstate->playerheight;
+ else
+ destheightoffset = 0;
+
+ if (pstate->heightoffset <= destheightoffset)
+ {
+ ob->temp2 = 0;
+ pstate->heightoffset = 0;
+ }
+ pstate->oldheightoffset = pstate->heightoffset;
+
+ break;
+
+ case COLUMNCRUSH:
+ pstate->heightoffset += 4;
+ if (pstate->heightoffset >= 30)
+ pstate->heightoffset = 30;
+
+ pstate->oldheightoffset = pstate->heightoffset;
+ break;
+
+ case GODMODERISE:
+ pstate->heightoffset --;
+ pstate->oldheightoffset = pstate->heightoffset;
+ if ((height+pstate->heightoffset) <= godheight)
+ {
+ ob->temp2 = 0;
+ pstate->poweruptime = POWERUPTICS;
+ }
+ break;
+
+
+ case GODMODEFALL:
+ pstate->heightoffset ++;
+ pstate->oldheightoffset = pstate->heightoffset;
+ SetPlayerHorizon(pstate,NORMALYZANGLE);
+ if (pstate->heightoffset >= 0)
+ {
+ ob->temp2 = 0;
+ ob->flags &= ~FL_GODMODE;
+ SetNormalHorizon(ob);
+ }
+ break;
+
+ case DOGMODERISE:
+ pstate->heightoffset --;
+ pstate->oldheightoffset = pstate->heightoffset;
+ SetPlayerHorizon(pstate,NORMALYZANGLE);
+ if (pstate->heightoffset <= 0)
+ {
+ ob->temp2 = 0;
+ ob->flags &= ~FL_DOGMODE;
+ SetNormalHorizon(ob);
+ }
+ break;
+
+
+ case DOGMODEFALL:
+ pstate->heightoffset ++;
+ pstate->oldheightoffset = pstate->heightoffset;
+ if (pstate->heightoffset >= (DOGOFFSET-pstate->playerheight))
+ {
+ ob->temp2 = 0;
+ pstate->poweruptime = POWERUPTICS;
+ }
+ break;
+
+ case STEPUP:
+ //Debug("\n\n heightoffset adjusted from %d to %d",
+ // pstate->heightoffset,pstate->heightoffset - STEPADJUST);
+ pstate->heightoffset -= STEPADJUST;
+ if (pstate->heightoffset <= pstate->oldheightoffset)
+ { ob->temp2 = 0;
+ //Debug("\n done adjusting heightoffset");
+ pstate->heightoffset = pstate->oldheightoffset;
+ }
+ break;
+
+ case STEPDOWN:
+ pstate->heightoffset += STEPADJUST;
+ if (pstate->heightoffset >= pstate->oldheightoffset)
+ { ob->temp2 = 0;
+ pstate->heightoffset = pstate->oldheightoffset;
+ }
+ break;
+
+ case 0:
+ if (!((ob->flags & FL_FLEET) ||
+ (ob->flags & FL_DOGMODE) ||
+ (ob->flags & FL_GODMODE)
+ )
+ )
+ pstate->heightoffset = 0;
+ break;
+
+ }
+
+
+ }
+
+
+ else if (ob->temp2 == PITFALL)
+ {
+ if (ob->z != pitheight)
+ {
+ ob->z += (ob->momentumz>>16);
+ ob->momentumz += GRAVITY;
+ if (ob->z >= pitheight)
+ {
+ ob->z = pitheight;
+ ob->momentumz = 0;
+ if (!(ob->flags & FL_DYING))
+ { DamageThing(ob,10);
+ Collision(ob,(objtype*)NULL,0,0);
+ M_CheckPlayerKilled(ob);
+ }
+ }
+ }
+ else if (ob->momentumx || ob->momentumy)
+ {
+ ob->temp2 = PITRISE;
+ ob->momentumz = -2;
+ }
+ }
+
+ else if (ob->temp2 == PITRISE)
+ { ob->z += ob->momentumz;
+ if (ob->z <= nominalheight)
+ { ob->z = nominalheight;
+ ob->temp2 = 0;
+ ob->momentumz = 0;
+ if (pstate->heightoffset)
+ ob->temp2 = RENORMALIZE;
+ }
+ }
+
+
+
+
+
+
+}
+
+
+
+/*
+=============================
+=
+= CheckRemoteRecording
+=
+=============================
+*/
+
+void CheckRemoteRecording(objtype *ob,playertype *pstate)
+{
+ if (networkgame==true)
+ {
+ if ( (pstate->buttonstate[bt_recordsound]) &&
+ (!pstate->buttonheld[bt_recordsound])
+ )
+ {
+ if (SD_RecordingActive()==false)
+ {
+ SD_SetRecordingActive ();
+ PlayerRecording=ob->dirchoosetime;
+ if (ob==player)
+ {
+ SD_StartRecordingSound();
+ UpdateClientControls();
+ }
+ }
+ }
+ else if ( (pstate->buttonheld[bt_recordsound]) &&
+ (!pstate->buttonstate[bt_recordsound])
+ )
+ {
+ if (SD_RecordingActive()==true)
+ {
+ if (ob->dirchoosetime==PlayerRecording)
+ {
+ if (ob==player)
+ SD_StopRecordingSound();
+ SD_ClearRecordingActive();
+ PlayerRecording=-1;
+ UpdateClientControls();
+ }
+ }
+ }
+ }
+}
+
+
+/*
+=============================
+=
+= CheckPlayerSpecials
+=
+=============================
+*/
+
+
+void CheckPlayerSpecials(objtype * ob)
+{
+ playertype * pstate;
+
+ M_LINKSTATE(ob,pstate);
+
+ // Check for recording of sound
+
+ CheckRemoteRecording(ob,pstate);
+ CheckTemp2Codes(ob,pstate);
+
+ if (ob->flags & FL_DYING)
+ return;
+
+ CheckSpecialSounds(ob,pstate);
+ CheckProtectionsAndPowerups(ob,pstate);
+}
+
+#if (SHAREWARE == 0)
+/*
+===============
+=
+= T_DogUse
+=
+===============
+*/
+
+void T_DogUse (objtype *ob)
+{
+ attack_t *cur;
+ playertype *pstate;
+ statetype *oldstate;
+
+ M_LINKSTATE(ob,pstate);
+
+ Thrust(ob);
+ oldstate = ob->state;
+ CheckPlayerSpecials(ob);
+ if (ob->state != oldstate)
+ {
+ return;
+ }
+
+
+
+
+//Commented out until we find if it's valid
+ /*
+ if (!ob->ticcount)
+ {if ( pstate->buttonstate[bt_use] && !pstate->buttonheld[bt_use] )
+ pstate->buttonstate[bt_use] = false;
+ }
+ */
+
+ if (pstate->attackframe >= DOGSCRATCH.numattacks)
+ Error("\n attackframe %d for DOGSCRATCH gt numattacks %d",
+ pstate->attackframe,DOGSCRATCH.numattacks
+ );
+
+
+
+ cur = &(DOGSCRATCH.attackinfo[pstate->attackframe]);
+ if (! pstate->attackcount)
+ { switch (cur->attack)
+ {
+ case reset:
+ {
+ NewState(ob,&s_dogwait);
+ pstate->attackframe = pstate->weaponframe = pstate->batblast = 0;
+ return;
+ }
+ break;
+ case at_pulltrigger:
+ pstate->buttonheld[bt_use]=false;
+ Cmd_Use(ob);
+ break;
+ default:
+ break;
+ }
+ pstate->attackframe++;
+ cur = &(DOGSCRATCH.attackinfo[pstate->attackframe]);
+ pstate->weaponframe = cur->frame;
+ pstate->attackcount = cur->mtics;
+
+ }
+ else
+ pstate->attackcount --;
+
+
+
+}
+
+/*
+===============
+=
+= T_DogLick
+=
+===============
+*/
+
+
+
+void T_DogLick (objtype *ob)
+{
+ attack_t *cur;
+ playertype *pstate;
+ statetype *oldstate;
+
+ M_LINKSTATE(ob,pstate);
+
+ Thrust(ob);
+ oldstate = ob->state;
+ CheckPlayerSpecials(ob);
+ if (ob->state != oldstate)
+ {
+ return;
+ }
+
+
+
+//Commented out until we find if it's valid
+ /*
+ if (!ob->ticcount)
+ {if ( pstate->buttonstate[bt_use] && !pstate->buttonheld[bt_use] )
+ pstate->buttonstate[bt_use] = false;
+ }
+ */
+
+
+ if (pstate->attackframe >= DOGLICK.numattacks)
+ Error("\n attackframe %d for DOGLICK gt numattacks %d",
+ pstate->attackframe,DOGLICK.numattacks
+ );
+
+
+ cur = &(DOGLICK.attackinfo[pstate->attackframe]);
+ if (! pstate->attackcount)
+ { if (cur->attack == reset)
+ {
+ NewState(ob,&s_serialdog);
+ pstate->attackframe = pstate->weaponframe = 0;
+ return;
+ }
+ pstate->attackframe++;
+ cur = &(DOGLICK.attackinfo[pstate->attackframe]);
+ pstate->weaponframe = cur->frame;
+ pstate->attackcount = cur->mtics;
+
+ }
+ else
+ pstate->attackcount --;
+
+// if ( playerstate.buttonstate[bt_attack] && (!playerstate.buttonheld[bt_attack]) && (!W_CHANGE))
+ // Cmd_Fire (ob);
+
+
+}
+
+#endif
+
+void T_DeadWait(objtype*ob)
+{
+ playertype *pstate;
+
+ M_LINKSTATE(ob,pstate);
+ if ((ob->flags & FL_DESIGNATED) && (gamestate.battlemode == battle_CaptureTheTriad))
+ { int otherteam = (pstate->team ^ 1);
+
+ ob->flags &= ~FL_DESIGNATED;
+ UpdateKills = true;
+ SpawnStatic(TEAM[otherteam].tilex,TEAM[otherteam].tiley,stat_collector,9);
+ LASTSTAT->flags |= FL_COLORED;
+ LASTSTAT->hitpoints = otherteam;
+ LASTSTAT->flags |= FL_ABP;
+ MakeStatActive(LASTSTAT);
+
+ }
+ //ob->momentumx=0;
+ //ob->momentumy=0;
+
+ if (pstate->heightoffset<36)
+ { pstate->heightoffset++;
+ pstate->oldheightoffset = pstate->heightoffset;
+ }
+
+ if (ob==player)
+ {
+ UpdateLightLevel(player->areanumber);
+ if ((pstate->falling==true) || (ob->momentumz==0))
+ {
+ if (BATTLEMODE)
+ playerdead=true;
+ else
+ playstate = ex_died;
+ }
+ }
+ /*
+ if (BATTLEMODE)
+ {
+ objtype * killer=(objtype *)ob->target;
+
+ dx = killer->x - ob->x;
+ dy = ob->y - killer->y;
+
+ if (dx && dy)
+ ob->angle = atan2_appx (dx,dy);
+ }
+ */
+ //CheckPlayerSpecials(ob);
+}
+
+/*
+===============
+=
+= T_Player
+=
+===============
+*/
+
+void T_Player (objtype *ob)
+{
+ playertype *pstate;
+ statetype *oldstate;
+
+#if (SHAREWARE == 0)
+ int eluder;
+#endif
+
+ M_LINKSTATE(ob,pstate);
+
+
+
+#if (SHAREWARE == 0)
+ eluder = ((pstate->weapon == wp_dog) && gamestate.SpawnEluder);
+#endif
+
+ oldstate = ob->state;
+
+ if (ob->flags&FL_DYING)
+ {
+
+ CheckPlayerSpecials(ob);
+ PlayerMove(ob);
+ if (
+ (pstate->falling==true) ||
+ (
+ (!ob->momentumx) &&
+ (!ob->momentumy) &&
+ (!ob->momentumz) &&
+ (!ob->state->tictime)
+ )
+ )
+ {
+ KillActor(ob);
+ if (ob->state == &s_remoteguts12)
+ NewState(ob,&s_gutwait);
+ else
+ NewState(ob,&s_deadwait);
+ }
+ return;
+ }
+
+ Thrust(ob);
+ if (ob->flags & FL_DYING)
+ return;
+
+ oldstate = ob->state;
+ CheckPlayerSpecials(ob);
+ if (ob->state != oldstate)
+ {
+ if (ob->flags & FL_DYING)
+ return;
+ }
+
+ if (!(ob->flags & FL_PAIN))
+ { if (!(ob->state->condition & SF_DOGSTATE))
+ { if ((ob->momentumx || ob->momentumy) && (ob->state->condition != SF_DOWN))
+ NewState(ob,&s_remotemove1);
+ else if (NOMOM && (ob->state != &s_player))
+ NewState(ob,&s_player);
+ }
+ else if (NOMOM
+#if (SHAREWARE == 0)
+
+ && (ob->state != &s_dogwait)
+#endif
+
+ )
+
+ NewState(ob,ob->state);
+
+ }
+ else if (!ob->ticcount)
+ { if (!(ob->state->condition & SF_DOGSTATE))
+ NewState(ob,&s_player);
+
+ ob->flags &= ~FL_PAIN;
+
+ }
+
+ if (ob->flags & FL_DIDTAG)
+ { ob->flags &= ~FL_DIDTAG;
+ pstate->weapondowntics = (144 - TAGHANDHEIGHT)/GMOVE;
+ }
+
+
+ CheckWeaponStates(ob);
+
+
+ if (ARMED(ob->dirchoosetime)
+ //(gamestate.battlemode != battle_Tag)
+ )
+ {
+ if (pstate->weapondowntics == 1) // change to up; during change, up and down
+ // are never zero at the same time
+ {
+ pstate->weapondowntics = 0;
+ pstate->weaponframe = pstate->attackframe = 0;
+
+ if (pstate->NETCAPTURED == -1)
+ {
+ pstate->weaponuptics = FREE.screenheight/GMOVE;
+ pstate->weaponheight = pstate->weaponuptics*GMOVE ;
+ pstate->NETCAPTURED = 1;
+ // return;
+ }
+ else if (pstate->NETCAPTURED == -2)
+ {
+ pstate->weaponuptics = WEAPONS[pstate->weapon].screenheight/GMOVE;
+ pstate->weaponheight = pstate->weaponuptics*GMOVE ;
+ pstate->NETCAPTURED = 0;
+
+ //return;
+ }
+ else
+ {
+ pstate->weaponuptics = WEAPONS[pstate->new_weapon].screenheight/GMOVE;
+ pstate->weapon = pstate->new_weapon;
+
+ pstate->weaponheight = pstate->weaponuptics*GMOVE ;
+ }
+ }
+
+ else
+ CheckWeaponChange (ob);
+ }
+
+ else if (gamestate.battlemode == battle_Hunter)
+ {
+ if (pstate->weapondowntics == 1)
+
+ {
+ pstate->weapondowntics = 0;
+ pstate->weaponframe = pstate->attackframe = pstate->batblast = 0;
+ pstate->weapon = pstate->new_weapon;
+ }
+ }
+
+// if ( pstate->buttonstate[bt_use] && (!W_CHANGE(pstate)) )
+
+ if ( pstate->buttonstate[bt_use] )
+ Cmd_Use (ob);
+
+
+ if (W_CHANGE(pstate))
+ return;
+
+
+
+
+ if ((!ARMED(ob->dirchoosetime))
+#if (SHAREWARE == 0)
+ && (pstate->weapon != wp_dog)
+#endif
+ )
+ return;
+
+ if (pstate->buttonstate[bt_attack])
+ {
+#if (SHAREWARE == 0)
+
+ if (eluder)
+ Cmd_Fire(ob);
+
+ else if ((pstate->weapon == wp_bat) ||
+ (pstate->weapon == wp_dog)
+ )
+ {
+ int oldblast=pstate->batblast;
+
+ pstate->batblast ++;
+
+ if (pstate->weapon==wp_bat)
+ {
+ if (pstate->batblast == 20)
+ SD_PlaySoundRTP(SD_EXCALIBUILDSND,ob->x,ob->y);
+ }
+ else
+ {
+ if ((pstate->batblast>>4)!=(oldblast>>4))
+ {
+ int handle;
+
+ handle=SD_PlaySoundRTP(SD_DOGMODEPREPBLASTSND,ob->x,ob->y);
+ SD_SetSoundPitch(handle,-(BBTIME<<3)+(pstate->batblast<<3));
+ }
+ }
+ if (pstate->batblast < BBTIME)
+ return;
+
+ if (pstate->weapon == wp_bat)
+ SD_PlaySoundRTP(SD_EXCALIBLASTSND,ob->x,ob->y);
+ else
+ SD_PlaySoundRTP(SD_DOGMODEBLASTSND,ob->x,ob->y);
+ }
+
+ if ((pstate->weapon != wp_split) || (!pstate->buttonheld[bt_attack]))
+#endif
+ // if (!pstate->buttonheld[bt_attack])
+//#endif
+ {
+
+#if (SHAREWARE == 0)
+
+ if (pstate->weapon == wp_kes)
+ SD_PlaySoundRTP(SD_GRAVBUILDSND,ob->x,ob->y);
+#endif
+
+ Cmd_Fire (ob);
+ }
+ }
+
+#if (SHAREWARE == 0)
+
+ else if (
+ ((pstate->weapon == wp_bat) ||
+ ((pstate->weapon == wp_dog) && (!eluder))
+ ) &&
+ (pstate->buttonheld[bt_attack])
+ )
+ {
+ if (pstate->weapon == wp_bat)
+ SD_StopSound(SD_EXCALIBUILDSND);
+ pstate->batblast = 0;
+ Cmd_Fire(ob);
+ }
+#endif
+
+}
+
+
+
--- /dev/null
+++ b/rott/rt_playr.h
@@ -1,0 +1,295 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// RT_PLAYR.C - Player movement and stuff
+//
+//***************************************************************************
+
+#ifndef _rt_playr_public
+#define _rt_playr_public
+
+#include "rt_actor.h"
+#include "rt_stat.h"
+#include "states.h"
+#include "rottnet.h"
+#include "rt_battl.h"
+#include "develop.h"
+
+
+
+extern int mouse_ry_input_scale;
+
+#define LOW_GRAVITY 10000
+#define NORMAL_GRAVITY 30000
+#define HIGH_GRAVITY 250000
+#define TAGHANDHEIGHT 40
+
+#define MAXDEAD 32
+#define MAXBULLETS 64
+
+#define MAXCODENAMELENGTH 9
+
+#define ARMED(x) ( \
+ (gamestate.PlayerHasGun[x]) || \
+ (!BATTLEMODE) \
+ )
+
+
+typedef struct
+{
+ statetype *state;
+ int speed;
+ classtype obclass;
+ int offset;
+ int flags;
+
+} missile_stats;
+
+extern missile_stats PlayerMissileData[13];
+
+extern int GetWeaponForItem(int itemnumber);
+extern int GetItemForWeapon(int weapon);
+
+
+typedef enum
+{ reset,
+ reset2,
+ done,
+ at_knife,
+ at_pulltrigger,
+ at_automatic,
+ at_dryheaving,
+ at_missileweapon
+} attack_action;
+
+
+typedef struct atkinf
+{
+ attack_action attack;
+ char mtics,frame; // attack is 1 for gun, 2 for knife, 3 for machine guns,
+ // 4 for chaingun (orig. game)
+} attack_t;
+
+typedef struct weaptype
+{ const int screenheight;
+ int startammo;
+ int base_damage;
+ int impulse;
+ int numattacks;
+ attack_t attackinfo[14];
+} williamdidthis;
+
+//
+// Interactive input status of device, returned by SWIFT_Get3DStatus
+//
+typedef struct {
+ short x;
+ short y;
+ short z;
+ short pitch;
+ short roll;
+ short yaw;
+ short buttons;
+} SWIFT_3DStatus;
+
+
+//
+// Static data about device, returned by SWIFT_GetStaticDeviceInfo
+//
+typedef struct
+{
+ unsigned char deviceType;
+ unsigned char majorVersion;
+ unsigned char minorVersion;
+ unsigned char coordDescriptor[6];
+ unsigned char reserved[1];
+} SWIFT_StaticData;
+
+typedef struct
+{
+ int lives;
+ int health;
+ int triads;
+ signed char ammo;
+ short poweruptime;
+ short protectiontime;
+ int new_weapon;
+ int keys;
+ int weapon;
+ int missileweapon;
+ int bulletweapon;
+ signed char HASBULLETWEAPON[3];
+ int attackframe,attackcount,weaponframe;
+ byte player;
+ int topspeed;
+ int dmomx;
+ int dmomy;
+ int angle;
+ int anglefrac;
+ boolean buttonheld[NUMBUTTONS];
+ boolean buttonstate[NUMBUTTONS];
+ int horizon;
+ int lastmomz;
+ signed short playerheight;
+ signed short heightoffset;
+ signed short weaponheight;
+ byte weaponx,weapony;
+ word batblast;
+ signed char NETCAPTURED;
+ signed char HASKNIFE;
+ int oldweapon, oldmissileweapon;
+ signed short weapondowntics,weaponuptics;
+ int soundtime;
+ int healthtime;
+ objtype* guntarget;
+ int targettime;
+// int steptime;
+// int stepwhich;
+ boolean falling;
+ int oldshapeoffset;
+ int uniformcolor;
+ char codename[MAXCODENAMELENGTH];
+ int oldheightoffset;
+ int team;
+} playertype;
+
+
+typedef struct
+{ int topspeed;
+ int toprunspeed;
+ int hitpoints;
+ int accuracy;
+ int height;
+} ROTTCHARS;
+
+
+#define M_LINKSTATE(x,y) \
+{ y = &PLAYERSTATE[x->dirchoosetime];\
+}
+
+
+extern williamdidthis DOGSCRATCH;
+extern int GRAVITY;
+extern int controlupdatetime;
+extern int controlupdatestarted;
+extern statobj_t *DEADPLAYER[MAXDEAD];
+extern int NUMDEAD;
+extern objtype *PLAYER[MAXPLAYERS];
+extern objtype *player;
+extern playertype PLAYERSTATE[MAXPLAYERS],*locplayerstate;
+
+extern ROTTCHARS characters[5];
+
+extern williamdidthis FREE;
+extern statetype s_player;
+extern williamdidthis WEAPONS[MAXWEAPONS];
+extern boolean cybermanenabled;
+extern boolean spaceballenabled;
+extern boolean SpaceBallPresent;
+extern boolean CybermanPresent;
+extern boolean mouseenabled;
+extern boolean joystickenabled;
+extern boolean joypadenabled;
+extern boolean joystickprogressive;
+extern int joystickport;
+extern int joyxmax, joyymax, joyxmin, joyymin;
+extern int buttonscan[NUMBUTTONS];
+extern int buttonmouse[6];
+extern int buttonjoy[8];
+extern boolean buttonpoll[NUMBUTTONS];
+extern boolean godmode;
+extern boolean missilecam;
+extern objtype * missobj;
+extern int lastpolltime;
+
+extern int controlbuf[3];
+extern int buttonbits;
+
+extern int pausedstartedticcount;
+extern boolean RefreshPause;
+
+
+void PlayNoWaySound(void);
+int GetBonusTimeForItem(int);
+int GetRespawnTimeForItem(int);
+int GetItemForWeapon(int);
+void SetWhoHaveWeapons(void);
+int MaxHitpointsForCharacter(playertype*);
+void RespawnPlayerobj(objtype*);
+void RevivePlayerobj(int,int,int,objtype*);
+void OperateElevatorSwitch(objtype*,int,int,int);
+void ResetPlayerstate(playertype*);
+void InitializeWeapons(playertype*);
+void DropWeapon(objtype*ob);
+void PollKeyboardButtons (void);
+void PollMouseButtons (void);
+void PollJoystickButtons (void);
+void PollKeyboardMove (void);
+void PollCyberman (void);
+void PollMouseMove (void);
+void PollJoystickMove (void);
+void PollControls (void);
+void AddDemoCmd (void);
+void AddRemoteCmd (void);
+void PlayerSlideMove(objtype * ob);
+void SpawnSmoke(objtype*);
+void GetBonus(objtype*,statobj_t*);
+void SpawnPlayerobj(int,int,int,int);
+void ClipPlayer(void);
+void PlayerMove ( objtype * ob );
+void Cmd_Use(objtype*);
+void Cmd_Fire (objtype*ob);
+void SpawnGunSmoke(int x, int y, int z, int angle, int bullethole);
+void SpawnBlood(objtype * ob, int angle);
+void SpawnMetalSparks(objtype * ob, int angle);
+void CheckPlayerSpecials(objtype * ob);
+void LoadPlayer ( void );
+void PlayerTiltHead (objtype * ob);
+boolean InRange (objtype *p, objtype *victim, int distance);
+void CheckUnPause ( void );
+void UpdatePlayers ( void );
+void UnTargetActor ( objtype * target );
+
+
+enum
+{ RENORMALIZE = 1,
+ PITFALL,
+ PITRISE,
+ COLUMNCRUSH,
+ GODMODERISE,
+ GODMODEFALL,
+ DOGMODEFALL,
+ DOGMODERISE,
+ STEPUP,
+ STEPDOWN
+};
+
+extern void ResetWeapons(objtype *);
+extern void SaveWeapons(objtype*);
+
+extern int whichpath;
+extern statobj_t *BulletHoles[MAXBULLETS];
+
+extern boolean vrenabled;
+
+void SetupBulletHoleLink (int num, statobj_t * item);
+
+#endif
--- /dev/null
+++ b/rott/rt_rand.c
@@ -1,0 +1,147 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "rt_def.h"
+#include "_rt_rand.h"
+#include "rt_rand.h"
+#include "develop.h"
+#include "rt_util.h"
+#include <time.h>
+
+#if (DEVELOPMENT == 1)
+#include "rt_main.h"
+#endif
+//MED
+#include "memcheck.h"
+
+//****************************************************************************
+//
+// GLOBALS
+//
+//****************************************************************************
+
+static int rndindex;
+static int sndindex = 0;
+
+
+//****************************************************************************
+//
+// GetRandomSeed ()
+//
+//****************************************************************************
+
+int GetRandomSeed ( void )
+{
+ return ( time (NULL) % (SIZE_OF_RANDOM_TABLE) );
+}
+
+//****************************************************************************
+//
+// InitializeRNG ()
+//
+//****************************************************************************
+
+void InitializeRNG ( void )
+{
+ SetRNGindex(GetRandomSeed());
+ sndindex=GetRandomSeed();
+}
+
+//****************************************************************************
+//
+// SetRNGindex ()
+//
+//****************************************************************************
+
+void SetRNGindex ( int i )
+{
+ rndindex=i;
+//#if (DEVELOPMENT == 1)
+ SoftError("RNG index set at %d\n",i);
+//#endif
+}
+
+//****************************************************************************
+//
+// GetRNGindex ()
+//
+//****************************************************************************
+
+int GetRNGindex ( void )
+{
+ return rndindex;
+}
+
+
+#if (RANDOMTEST==1)
+//****************************************************************************
+//
+// int GameRNG ( char * string, int val )
+//
+//****************************************************************************
+int GameRNG ( char * string, int val )
+{
+ rndindex = (rndindex+1)&(SIZE_OF_RANDOM_TABLE-1);
+ SoftError("RNG - num=%3d called from=%s val=%d\n",RandomTable[rndindex],string,val);
+ return RandomTable[rndindex];
+}
+#else
+//****************************************************************************
+//
+// int GameRNG (void)
+//
+//****************************************************************************
+int GameRNG ( void )
+{
+ rndindex = (rndindex+1)&(SIZE_OF_RANDOM_TABLE-1);
+
+ return RandomTable[rndindex];
+}
+#endif
+
+
+
+#if (RANDOMTEST==1)
+//****************************************************************************
+//
+// int RNG ( char * string, int val )
+//
+//****************************************************************************
+
+int RNG ( char * string, int val )
+{
+ sndindex = (sndindex+1)&(SIZE_OF_RANDOM_TABLE-1);
+// SoftError("SRNG - num=%3ld called from=%s val=%ld\n",RandomTable[sndindex],string,val);
+ return RandomTable[sndindex];
+}
+#else
+//****************************************************************************
+//
+// int RNG (void)
+//
+//****************************************************************************
+
+int RNG( void )
+{
+ sndindex = (sndindex+1)&(SIZE_OF_RANDOM_TABLE-1);
+
+ return RandomTable[sndindex];
+}
+#endif
+
--- /dev/null
+++ b/rott/rt_rand.h
@@ -1,0 +1,51 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_rand_public
+#define _rt_rand_public
+
+#include "develop.h"
+
+void InitializeRNG ( void );
+int GetRandomSeed ( void );
+
+
+#if RANDOMTEST
+
+int GameRNG ( char * string, int val );
+#define GameRandomNumber(string,val) GameRNG(string, val)
+
+int RNG ( char * string, int val );
+#define RandomNumber(string,val) RNG(string, val)
+
+#else
+
+int GameRNG ( void );
+#define GameRandomNumber(string,val) GameRNG()
+
+int RNG ( void );
+#define RandomNumber(string,val) RNG()
+
+#endif
+
+
+
+void SetRNGindex ( int i );
+int GetRNGindex ( void );
+#endif
--- /dev/null
+++ b/rott/rt_sc_a.h
@@ -1,0 +1,41 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// RT_SC_A.ASM - Low level DrawColumn for masked post
+//
+//***************************************************************************
+
+#ifndef _rt_sc_a_public
+#define _rt_sc_a_public
+
+void R_DrawColumn (byte * buf);
+void R_DrawSolidColumn (int color, byte * buf);
+void R_TransColumn (byte * buf);
+void R_DrawClippedColumn (byte * buf);
+
+#if defined(__WATCOMC__)
+#pragma aux R_DrawColumn parm [EDI] modify exact [eax ebx ecx edx esi edi]
+#pragma aux R_DrawSolidColumn parm [EBX] [EDI] modify exact [eax ecx edi]
+#pragma aux R_TransColumn parm [EDI] modify exact [eax ebx esi edi]
+#pragma aux R_DrawClippedColumn parm [EDI] modify exact [eax ebx ecx edx esi edi]
+#endif
+
+#endif
--- /dev/null
+++ b/rott/rt_scale.c
@@ -1,0 +1,1463 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "rt_def.h"
+#include "watcom.h"
+#include <stdio.h>
+#include <string.h>
+
+#ifdef DOS
+#include <malloc.h>
+#include <dos.h>
+#include <conio.h>
+#endif
+
+#include "modexlib.h"
+#include "rt_util.h"
+#include "rt_draw.h"
+#include "rt_scale.h"
+#include "_rt_scal.h"
+#include "rt_sc_a.h"
+#include "engine.h"
+#include "w_wad.h"
+#include "z_zone.h"
+#include "lumpy.h"
+#include "rt_main.h"
+#include "rt_ted.h"
+#include "rt_vid.h"
+#include "rt_view.h"
+#include "rt_playr.h"
+//MED
+#include "memcheck.h"
+
+/*
+=============================================================================
+
+ GLOBALS
+
+=============================================================================
+*/
+
+// Draw Column vars
+
+int dc_texturemid;
+int dc_iscale;
+int dc_invscale;
+int sprtopoffset;
+int dc_yl;
+int dc_yh;
+//byte * dc_firstsource;
+byte * dc_source;
+int centeryclipped;
+int transparentlevel=0;
+
+/*
+==========================
+=
+= SetPlayerLightLevel
+=
+==========================
+*/
+
+void SetPlayerLightLevel (void)
+{
+ int i;
+ int lv;
+ int intercept;
+ int height;
+
+ whereami=23;
+ if (MISCVARS->GASON==1)
+ {
+ shadingtable=greenmap+(MISCVARS->gasindex<<8);
+ return;
+ }
+
+ if (fulllight || fog)
+ {
+ shadingtable=colormap+(1<<12);
+ return;
+ }
+
+ height=PLAYERHEIGHT;
+
+ if (player->angle < FINEANGLES/8 || player->angle > 7*FINEANGLES/8)
+ intercept=(player->x>>11)&0x1c;
+ else if (player->angle < 3*FINEANGLES/8)
+ intercept=(player->y>>11)&0x1c;
+ else if (player->angle < 5*FINEANGLES/8)
+ intercept=(player->x>>11)&0x1c;
+ else
+ intercept=(player->y>>11)&0x1c;
+
+ if (lightsource)
+ {
+ lv=(((LightSourceAt(player->x>>16,player->y>>16)>>intercept)&0xf)>>1);
+ i=maxshade-(height>>normalshade)-lv;
+ if (i<minshade) i=minshade;
+ shadingtable=colormap+(i<<8);
+ }
+ else
+ {
+ i=maxshade-(height>>normalshade);
+ if (i<minshade) i=minshade;
+ shadingtable=colormap+(i<<8);
+ }
+}
+
+
+
+/*
+==========================
+=
+= SetLightLevel
+=
+==========================
+*/
+
+void SetLightLevel (int height)
+{
+ int i;
+
+ whereami=24;
+ if (MISCVARS->GASON==1)
+ {
+ shadingtable=greenmap+(MISCVARS->gasindex<<8);
+ return;
+ }
+
+ if (fulllight)
+ {
+ shadingtable=colormap+(1<<12);
+ return;
+ }
+ if (fog)
+ {
+ i=((height*200/iGLOBAL_SCREENHEIGHT)>>normalshade)+minshade;
+ if (i>maxshade) i=maxshade;
+ shadingtable=colormap+(i<<8);
+ }
+ else
+ {
+ i=maxshade-(height>>normalshade);
+ if (i<minshade) i=minshade;
+ shadingtable=colormap+(i<<8);
+ }
+}
+
+/*
+==========================
+=
+= ScaleTransparentPost
+=
+==========================
+*/
+void ScaleTransparentPost (byte * src, byte * buf, int level)
+{
+ int offset;
+ int length;
+ int topscreen;
+ int bottomscreen;
+ byte * oldlevel;
+ byte * seelevel;
+#if (DEVELOPMENT == 1)
+ boolean found=false;
+ int i;
+#endif
+
+ whereami=25;
+#if (DEVELOPMENT == 1)
+ if ((shadingtable>=colormap) && (shadingtable<=(colormap+(31*256))))
+ {
+ found=true;
+ }
+ else if ((shadingtable>=redmap) && (shadingtable<=(redmap+(31*256))))
+ {
+ found=true;
+ }
+ else
+ {
+ for (i=0; i<MAXPLAYERCOLORS; i++)
+ {
+ if ((shadingtable>=playermaps[i]) || (shadingtable<=(playermaps[i]+(31*256))))
+ found=true;
+ }
+ }
+ if (found==false)
+ {
+ Error ("Shadingtable out of range\n");
+ }
+ if ((level<0) || (level>=64))
+ {
+ Error ("translucent level out of range\n");
+ }
+#endif
+
+ seelevel=colormap+(((level+64)>>2)<<8);
+ oldlevel=shadingtable;
+ offset=*(src++);
+ for (; offset!=255;)
+ {
+ length=*(src++);
+ topscreen = sprtopoffset + (dc_invscale*offset);
+ bottomscreen = topscreen + (dc_invscale*length);
+ dc_yl = (topscreen+SFRACUNIT)>>SFRACBITS;
+ dc_yh = ((bottomscreen-1)>>SFRACBITS);
+ if (dc_yh >= viewheight)
+ dc_yh = viewheight-1;
+ if (dc_yl < 0)
+ dc_yl = 0;
+ if ((*src)==254)
+ {
+ shadingtable=seelevel;
+ if (dc_yl <= dc_yh)
+ R_TransColumn (buf);
+ src++;
+ offset=*(src++);
+ shadingtable=oldlevel;
+ }
+ else
+ {
+ if (dc_yl <= dc_yh)
+ {
+ dc_source=src-offset;
+ R_DrawColumn (buf);
+ }
+ src+=length;
+ offset=*(src++);
+ }
+ }
+
+ whereami=-2;
+}
+
+
+void ScaleMaskedPost (byte * src, byte * buf)
+{
+ int offset;
+ int length;
+ int topscreen;
+ int bottomscreen;
+
+ whereami=26;
+ offset=*(src++);
+ for (; offset!=255;)
+ {
+ length=*(src++);
+ topscreen = sprtopoffset + (dc_invscale*offset);
+ bottomscreen = topscreen + (dc_invscale*length);
+ dc_yl = (topscreen+SFRACUNIT)>>SFRACBITS;
+ dc_yh = ((bottomscreen-1)>>SFRACBITS);
+ if (dc_yh >= viewheight)
+ dc_yh = viewheight-1;
+ if (dc_yl < 0)
+ dc_yl = 0;
+ if (dc_yl <= dc_yh)
+ {
+ dc_source=src-offset;
+ R_DrawColumn (buf);
+#if (DEVELOPMENT == 1)
+// if (dc_firstsource<src)
+// SoftError("dc_firstsource=%p src=%p\n",dc_firstsource,src);
+#endif
+ }
+ src+=length;
+ offset=*(src++);
+ }
+}
+
+void ScaleClippedPost (byte * src, byte * buf)
+{
+ int offset;
+ int length;
+ int topscreen;
+ int bottomscreen;
+
+ whereami=27;
+ offset=*(src++);
+ for (; offset!=255;)
+ {
+ length=*(src++);
+ topscreen = sprtopoffset + (dc_invscale*offset);
+ bottomscreen = topscreen + (dc_invscale*length);
+ dc_yl = (topscreen+SFRACUNIT-1)>>SFRACBITS;
+ dc_yh = ((bottomscreen-1)>>SFRACBITS);
+ if (dc_yh >= viewheight)
+ dc_yh = viewheight-1;
+ if (dc_yl < 0)
+ dc_yl = 0;
+ if (dc_yl <= dc_yh)
+ {
+ dc_source=src-offset;
+ R_DrawClippedColumn (buf);
+ }
+ src+=length;
+ offset=*(src++);
+ }
+}
+
+void ScaleSolidMaskedPost (int color, byte * src, byte * buf)
+{
+ int offset;
+ int length;
+ int topscreen;
+ int bottomscreen;
+
+ whereami=28;
+ offset=*(src++);
+ for (; offset!=255;)
+ {
+ length=*(src++);
+ topscreen = sprtopoffset + (dc_invscale*offset);
+ bottomscreen = topscreen + (dc_invscale*length);
+ dc_yl = (topscreen+SFRACUNIT)>>SFRACBITS;
+ dc_yh = ((bottomscreen-1)>>SFRACBITS);
+ if (dc_yh >= viewheight)
+ dc_yh = viewheight-1;
+ if (dc_yl < 0)
+ dc_yl = 0;
+ if (dc_yl <= dc_yh)
+ {
+ dc_source=src-offset;
+ R_DrawSolidColumn (color, buf);
+ }
+ src+=length;
+ offset=*(src++);
+ }
+
+}
+
+
+void ScaleTransparentClippedPost (byte * src, byte * buf, int level)
+{
+ int offset;
+ int length;
+ int topscreen;
+ int bottomscreen;
+ byte * oldlevel;
+ byte * seelevel;
+
+ whereami=29;
+
+ seelevel=colormap+(((level+64)>>2)<<8);
+ oldlevel=shadingtable;
+ offset=*(src++);
+ for (; offset!=255;)
+ {
+ length=*(src++);
+ topscreen = sprtopoffset + (dc_invscale*offset);
+ bottomscreen = topscreen + (dc_invscale*length);
+ dc_yl = (topscreen+SFRACUNIT)>>SFRACBITS;
+ dc_yh = ((bottomscreen-1)>>SFRACBITS);
+ if (dc_yh >= viewheight)
+ dc_yh = viewheight-1;
+ if (dc_yl < 0)
+ dc_yl = 0;
+ if ((*src)==254)
+ {
+ shadingtable=seelevel;
+ if (dc_yl <= dc_yh)
+ R_TransColumn (buf);
+ src++;
+ offset=*(src++);
+ shadingtable=oldlevel;
+ }
+ else
+ {
+ if (dc_yl <= dc_yh)
+ {
+ dc_source=src-offset;
+ R_DrawClippedColumn (buf);
+ }
+ src+=length;
+ offset=*(src++);
+ }
+ }
+
+}
+
+
+void ScaleMaskedWidePost (byte * src, byte * buf, int x, int width)
+{
+#ifdef DOS
+ int ofs;
+ int msk;
+
+ whereami=30;
+ buf+=x>>2;
+ ofs=((x&3)<<3)+(x&3)+width-1;
+ VGAMAPMASK(*((byte *)mapmasks1+ofs));
+ ScaleMaskedPost(src,buf);
+ msk=(byte)*((byte *)mapmasks2+ofs);
+ if (msk==0)
+ return;
+ buf++;
+ VGAMAPMASK(msk);
+ ScaleMaskedPost(src,buf);
+ msk=(byte)*((byte *)mapmasks3+ofs);
+ if (msk==0)
+ return;
+ buf++;
+ VGAMAPMASK(msk);
+ ScaleMaskedPost(src,buf);
+#else
+ buf += x;
+
+ while (width--) {
+ ScaleMaskedPost(src,buf);
+ buf++;
+ }
+#endif
+}
+
+void ScaleClippedWidePost (byte * src, byte * buf, int x, int width)
+{
+#ifdef DOS
+ int ofs;
+ int msk;
+
+ whereami=31;
+ buf+=x>>2;
+ ofs=((x&3)<<3)+(x&3)+width-1;
+ VGAMAPMASK(*((byte *)mapmasks1+ofs));
+ ScaleClippedPost(src,buf);
+ msk=(byte)*((byte *)mapmasks2+ofs);
+ if (msk==0)
+ return;
+ buf++;
+ VGAMAPMASK(msk);
+ ScaleClippedPost(src,buf);
+ msk=(byte)*((byte *)mapmasks3+ofs);
+ if (msk==0)
+ return;
+ buf++;
+ VGAMAPMASK(msk);
+ ScaleClippedPost(src,buf);
+#else
+ buf += x;
+
+ while (width--) {
+ ScaleClippedPost(src,buf);
+ buf++;
+ }
+#endif
+}
+
+
+/*
+=======================
+=
+= ScaleShape
+=
+=======================
+*/
+
+void ScaleShape (visobj_t * sprite)
+{
+ byte *shape;
+ int frac;
+ patch_t *p;
+ int x1,x2;
+ int tx;
+ int size;
+ int plane;
+
+ whereami=32;
+ shape=W_CacheLumpNum(sprite->shapenum,PU_CACHE, Cvt_patch_t, 1);
+ p=(patch_t *)shape;
+ size=p->origsize>>7;
+// sprite->viewheight<<=1;
+ dc_invscale=sprite->viewheight<<((10-HEIGHTFRACTION)-size);
+ tx=-p->leftoffset;
+ sprite->viewx=(sprite->viewx<<SFRACBITS)-(sprite->viewheight<<(SFRACBITS-HEIGHTFRACTION-1))+(SFRACUNIT>>1);
+//
+// calculate edges of the shape
+//
+ x1 = (sprite->viewx+(tx*dc_invscale))>>SFRACBITS;
+ if (x1 >= viewwidth)
+ {
+ return; // off the right side
+ }
+ tx+=p->width;
+ x2 = ((sprite->viewx+(tx*dc_invscale)) >>SFRACBITS) - 1 ;
+ if (x2 < 0)
+ {
+ return; // off the left side
+ }
+
+// dc_iscale=(1<<(16+6+HEIGHTFRACTION+size))/sprite->viewheight;
+ dc_iscale=0xffffffffu/(unsigned)dc_invscale;
+ dc_texturemid=(((sprite->h1<<size) + p->topoffset)<<SFRACBITS);//+(SFRACUNIT>>1);
+ sprtopoffset=centeryfrac - FixedMul(dc_texturemid,dc_invscale);
+ shadingtable=sprite->colormap;
+
+ if (x1<0)
+ {
+ frac=dc_iscale*(-x1);
+ x1=0;
+ }
+ else
+ frac=0;
+ x2 = x2 >= viewwidth ? viewwidth-1 : x2;
+
+ if (sprite->viewheight>((1<<(HEIGHTFRACTION+6))<<size))
+ {
+ int texturecolumn;
+ int lastcolumn;
+ int startx;
+ int width;
+
+ width=1;
+ startx=0;
+ lastcolumn=-1;
+ for (; x1<=x2 ; x1++, frac += dc_iscale)
+ {
+ if (posts[x1].wallheight>sprite->viewheight)
+ {
+ if (lastcolumn>=0)
+ {
+ ScaleMaskedWidePost(((p->collumnofs[lastcolumn])+shape),(byte *)bufferofs,startx,width);
+ width=1;
+ lastcolumn=-1;
+ }
+ continue;
+ }
+ texturecolumn = frac>>SFRACBITS;
+ if ((texturecolumn==lastcolumn)&&(width<9))
+ {
+ width++;
+ continue;
+ }
+ else
+ {
+ if (lastcolumn>=0)
+ {
+ ScaleMaskedWidePost(((p->collumnofs[lastcolumn])+shape),(byte *)bufferofs,startx,width);
+ width=1;
+ startx=x1;
+ lastcolumn=texturecolumn;
+ }
+ else
+ {
+ startx=x1;
+ lastcolumn=texturecolumn;
+ }
+ }
+ }
+ if (lastcolumn!=-1)
+ ScaleMaskedWidePost(((p->collumnofs[lastcolumn])+shape),(byte *)bufferofs,startx,width);
+ }
+ else
+ {
+ byte * b;
+ int startfrac;
+ int startx;
+
+ startx=x1;
+ startfrac=frac;
+ if (doublestep>1)
+ {
+#ifdef DOS
+ for (plane=startx; plane<startx+4; plane+=2,startfrac+=(dc_iscale<<1))
+#endif
+ {
+ frac=startfrac;
+// VGAWRITEMAP(plane&3);
+#ifdef DOS
+ for (x1=plane; x1<=x2; x1+=4, frac += (dc_iscale<<2))
+#else
+ for (x1=startx; x1<=x2; x1+=2, frac += (dc_iscale<<1))
+#endif
+ {
+ if (
+ (posts[x1].wallheight>sprite->viewheight) &&
+ (posts[x1+1].wallheight>sprite->viewheight)
+ )
+ continue;
+ if (x1==viewwidth-1)
+ ScaleMaskedWidePost(((p->collumnofs[frac>>SFRACBITS])+shape),(byte *)bufferofs,x1,1);
+ else
+ ScaleMaskedWidePost(((p->collumnofs[frac>>SFRACBITS])+shape),(byte *)bufferofs,x1,2);
+ }
+ }
+ }
+ else
+ {
+#ifdef DOS
+ for (plane=startx; plane<startx+4; plane++,startfrac+=dc_iscale)
+#endif
+ {
+ frac=startfrac;
+
+#ifdef DOS
+ b=(byte *)bufferofs+(plane>>2);
+ VGAWRITEMAP(plane&3);
+#else
+ b=(byte *)bufferofs+startx;
+#endif
+
+#ifdef DOS
+ for (x1=plane; x1<=x2; x1+=4, frac += (dc_iscale<<2),b++)
+#else
+ for (x1=startx; x1<=x2; x1++, frac += dc_iscale,b++)
+#endif
+ {
+ if (posts[x1].wallheight>sprite->viewheight)
+ continue;
+ ScaleMaskedPost(((p->collumnofs[frac>>SFRACBITS])+shape),b);
+ }
+ }
+ }
+ }
+}
+
+
+/*
+=======================
+=
+= ScaleTranparentShape
+=
+=======================
+*/
+
+void ScaleTransparentShape (visobj_t * sprite)
+{
+ byte *shape;
+ int frac;
+ transpatch_t *p;
+ int x1,x2;
+ int tx;
+ int size;
+ byte * b;
+ int startfrac;
+ int startx;
+ int plane;
+
+ whereami=33;
+ shape=W_CacheLumpNum(sprite->shapenum,PU_CACHE, Cvt_transpatch_t, 1);
+ p=(transpatch_t *)shape;
+ size=p->origsize>>7;
+ dc_invscale=sprite->viewheight<<((10-HEIGHTFRACTION)-size);
+ tx=-p->leftoffset;
+ sprite->viewx=(sprite->viewx<<SFRACBITS)-(sprite->viewheight<<(SFRACBITS-HEIGHTFRACTION-1));
+//
+// calculate edges of the shape
+//
+ x1 = (sprite->viewx+(tx*dc_invscale))>>SFRACBITS;
+ if (x1 >= viewwidth)
+ {
+ return; // off the right side
+ }
+ tx+=p->width;
+ x2 = ((sprite->viewx+(tx*dc_invscale)) >>SFRACBITS) - 1 ;
+ if (x2 < 0)
+ {
+ return; // off the left side
+ }
+
+// dc_iscale=(1<<(16+6+HEIGHTFRACTION+size))/sprite->viewheight;
+ dc_iscale=0xffffffffu/(unsigned)dc_invscale;
+ dc_texturemid=(((sprite->h1<<size)+p->topoffset)<<SFRACBITS);//+(SFRACUNIT>>1);
+ sprtopoffset=centeryfrac - FixedMul(dc_texturemid,dc_invscale);
+ shadingtable=sprite->colormap;
+
+ if (x1<0)
+ {
+ frac=dc_iscale*(-x1);
+ x1=0;
+ }
+ else
+ frac=0;
+ x2 = x2 >= viewwidth ? viewwidth-1 : x2;
+
+#if 0
+ for (; x1<=x2 ; x1++, frac += dc_iscale)
+ {
+ if (posts[x1].wallheight>sprite->viewheight)
+ continue;
+ VGAWRITEMAP(x1&3);
+ VGAREADMAP(x1&3);
+ ScaleTransparentPost(((p->collumnofs[frac>>SFRACBITS])+shape),(byte *)bufferofs+(x1>>2),sprite->h2);
+ }
+#endif
+ startx=x1;
+ startfrac=frac;
+
+#ifdef DOS
+ for (plane=startx; plane<startx+4; plane++,startfrac+=dc_iscale)
+#endif
+
+ {
+ frac=startfrac;
+
+#ifdef DOS
+ b=(byte *)bufferofs+(plane>>2);
+ VGAWRITEMAP(plane&3);
+ VGAREADMAP(plane&3);
+#else
+ b=(byte *)bufferofs+startx;
+#endif
+
+#ifdef DOS
+ for (x1=plane; x1<=x2; x1+=4, frac += (dc_iscale<<2),b++)
+#else
+ for (x1=startx; x1<=x2; x1++, frac += dc_iscale,b++)
+#endif
+ {
+ if (posts[x1].wallheight>sprite->viewheight)
+ continue;
+ ScaleTransparentPost(((p->collumnofs[frac>>SFRACBITS])+shape),b,sprite->h2);
+ }
+ }
+}
+
+/*
+=======================
+=
+= ScaleSolidShape
+=
+=======================
+*/
+
+void ScaleSolidShape (visobj_t * sprite)
+{
+ byte *shape;
+ int frac;
+ patch_t *p;
+ int x1,x2;
+ int tx;
+ int size;
+ int plane;
+ byte * b;
+ int startfrac;
+ int startx;
+
+ whereami=34;
+ shape=W_CacheLumpNum(sprite->shapenum,PU_CACHE, Cvt_patch_t, 1);
+ p=(patch_t *)shape;
+ size=p->origsize>>7;
+ dc_invscale=sprite->viewheight<<((10-HEIGHTFRACTION)-size);
+ tx=-p->leftoffset;
+ sprite->viewx=(sprite->viewx<<SFRACBITS)-(sprite->viewheight<<(SFRACBITS-HEIGHTFRACTION-1))+(SFRACUNIT>>1);
+//
+// calculate edges of the shape
+//
+ x1 = (sprite->viewx+(tx*dc_invscale))>>SFRACBITS;
+ if (x1 >= viewwidth)
+ {
+ return; // off the right side
+ }
+ tx+=p->width;
+ x2 = ((sprite->viewx+(tx*dc_invscale)) >>SFRACBITS) - 1 ;
+ if (x2 < 0)
+ {
+ return; // off the left side
+ }
+
+// dc_iscale=(1<<(16+6+HEIGHTFRACTION+size))/sprite->viewheight;
+ dc_iscale=0xffffffffu/(unsigned)dc_invscale;
+ dc_texturemid=(((sprite->h1<<size)+p->topoffset)<<SFRACBITS);//+(SFRACUNIT>>1);
+ sprtopoffset=centeryfrac - FixedMul(dc_texturemid,dc_invscale);
+ shadingtable=sprite->colormap;
+
+ if (x1<0)
+ {
+ frac=dc_iscale*(-x1);
+ x1=0;
+ }
+ else
+ frac=0;
+ x2 = x2 >= viewwidth ? viewwidth-1 : x2;
+
+ startx=x1;
+ startfrac=frac;
+
+#ifdef DOS
+ for (plane=startx; plane<startx+4; plane++,startfrac+=dc_iscale)
+#endif
+
+ {
+ frac=startfrac;
+
+#ifdef DOS
+ b=(byte *)bufferofs+(plane>>2);
+ VGAWRITEMAP(plane&3);
+#else
+ b=(byte *)bufferofs+startx;
+#endif
+
+#ifdef DOS
+ for (x1=plane; x1<=x2; x1+=4, frac += (dc_iscale<<2),b++)
+#else
+ for (x1=startx; x1<=x2; x1++, frac += dc_iscale,b++)
+#endif
+ {
+ if (posts[x1].wallheight>sprite->viewheight)
+ continue;
+ ScaleSolidMaskedPost(sprite->h2,((p->collumnofs[frac>>SFRACBITS])+shape),b);
+ }
+ }
+}
+
+
+/*
+=======================
+=
+= ScaleWeapon
+=
+=======================
+*/
+
+void ScaleWeapon (int xoff, int y, int shapenum)
+{
+ byte *shape;
+ int frac;
+ int h;
+ patch_t *p;
+ int x1,x2;
+ int tx;
+ int xcent;
+ byte * b;
+ int startfrac;
+ int startx;
+ int plane;
+
+ whereami=35;
+ SetPlayerLightLevel();
+ shape=W_CacheLumpNum(shapenum,PU_CACHE, Cvt_patch_t, 1);
+ p=(patch_t *)shape;
+ h=((p->origsize*weaponscale)>>17);
+ centeryclipped=(viewheight-h)+FixedMul(y,weaponscale);
+ xcent=centerx+FixedMul(xoff,weaponscale);
+ dc_invscale=(h<<17)/p->origsize;
+
+ tx=-p->leftoffset;
+ xcent=(xcent<<SFRACBITS)-(h<<SFRACBITS);
+//
+// calculate edges of the shape
+//
+ x1 = (xcent+(tx*dc_invscale))>>SFRACBITS;
+ if (x1 >= viewwidth)
+ return; // off the right side
+ tx+=p->width;
+ x2 = ((xcent+(tx*dc_invscale)) >>SFRACBITS) - 1 ;
+ if (x2 < 0)
+ return; // off the left side
+
+ dc_iscale=0xffffffffu/(unsigned)dc_invscale;
+ dc_texturemid=(((p->origsize>>1)+p->topoffset)<<SFRACBITS)+(SFRACUNIT>>2);
+ sprtopoffset=(centeryclipped<<16) - FixedMul(dc_texturemid,dc_invscale);
+
+//
+// store information in a vissprite
+//
+ if (x1<0)
+ {
+ frac=dc_iscale*(-x1);
+ x1=0;
+ }
+ else
+ frac=0;
+
+ x2 = x2 >= viewwidth ? viewwidth-1 : x2;
+
+ startx=x1;
+ startfrac=frac;
+
+#ifdef DOS
+ for (plane=startx; plane<startx+4; plane++,startfrac+=dc_iscale)
+#endif
+ {
+ frac=startfrac;
+#ifdef DOS
+ b=(byte *)bufferofs+(plane>>2);
+#else
+ b=(byte *)bufferofs+startx;
+#endif
+ VGAWRITEMAP(plane&3);
+#ifdef DOS
+ for (x1=plane; x1<=x2 ; x1+=4, frac += dc_iscale<<2,b++)
+#else
+ for (x1=startx; x1<=x2 ; x1++, frac += dc_iscale,b++)
+#endif
+ ScaleClippedPost(((p->collumnofs[frac>>SFRACBITS])+shape),b);
+ }
+}
+
+
+
+
+/*
+=======================
+=
+= DrawUnScaledSprite
+=
+=======================
+*/
+
+void DrawUnScaledSprite (int x, int y, int shapenum, int shade)
+{
+ byte *shape;
+ int frac;
+ patch_t *p;
+ int x1,x2;
+ int tx;
+ int xcent;
+ byte * b;
+ int startfrac;
+ int startx;
+ int plane;
+
+ whereami=36;
+ shadingtable=colormap+(shade<<8);
+ centeryclipped=y;
+ xcent=x;
+ shape=W_CacheLumpNum(shapenum,PU_CACHE, Cvt_patch_t, 1);
+ p=(patch_t *)shape;
+ dc_invscale=0x10000;
+
+ tx=-p->leftoffset;
+ xcent-=p->origsize>>1;
+//
+// calculate edges of the shape
+//
+ x1 = xcent+tx;
+ if (x1 >= viewwidth)
+ return; // off the right side
+ tx+=p->width;
+ x2 = xcent+tx - 1;
+ if (x2 < 0)
+ return; // off the left side
+
+ dc_iscale=0x10000;
+ dc_texturemid=(((p->height>>1)+p->topoffset)<<SFRACBITS);//+(SFRACUNIT>>1);
+ sprtopoffset=(centeryclipped<<16) - dc_texturemid;
+
+//
+// store information in a vissprite
+//
+ if (x1<0)
+ {
+ frac=dc_iscale*(-x1);
+ x1=0;
+ }
+ else
+ frac = 0;
+
+ x2 = x2 >= viewwidth ? viewwidth-1 : x2;
+
+ startx=x1;
+ startfrac=frac;
+
+#ifdef DOS
+ for (plane=startx; plane<startx+4; plane++,startfrac+=dc_iscale)
+#endif
+
+ {
+ frac=startfrac;
+
+#ifdef DOS
+ b=(byte *)bufferofs+(plane>>2);
+ VGAWRITEMAP(plane&3);
+#else
+ b=(byte *)bufferofs+startx;
+#endif
+
+#ifdef DOS
+ for (x1=plane; x1<=x2 ; x1+=4, frac += dc_iscale<<2,b++)
+#else
+ for (x1=startx; x1<=x2 ; x1++, frac += dc_iscale,b++)
+#endif
+ ScaleClippedPost(((p->collumnofs[frac>>SFRACBITS])+shape),b);
+ }
+}
+
+
+/*
+=======================
+=
+= DrawScreenSprite
+=
+=======================
+*/
+
+void DrawScreenSprite (int x, int y, int shapenum)
+{
+ whereami=37;
+ ScaleWeapon (x-160, y-200, shapenum);
+}
+
+/*
+=======================
+=
+= DrawPositionedScaledSprite
+=
+=======================
+*/
+
+void DrawPositionedScaledSprite (int x, int y, int shapenum, int height, int type)
+{
+ byte *shape;
+ int frac;
+ patch_t *p;
+ transpatch_t *tp;
+ int x1,x2;
+ int tx;
+ int xcent;
+ byte * b;
+ int startfrac;
+ int startx;
+ int plane;
+ int size;
+
+ whereami=38;
+ shadingtable=colormap+(1<<12);
+ centeryclipped=y;
+ xcent=x;
+ shape=W_CacheLumpNum(shapenum,PU_CACHE, Cvt_patch_t, 1); // was transpatch, fixed
+ p=(patch_t *)shape;
+ tp=(transpatch_t *)shape;
+
+ size=p->origsize>>7;
+ dc_invscale=height<<(10-size);
+
+ tx=-p->leftoffset;
+ xcent=(xcent<<SFRACBITS)-(height<<(SFRACBITS-1));
+
+//
+// calculate edges of the shape
+//
+ x1 = (xcent+(tx*dc_invscale))>>SFRACBITS;
+ if (x1 >= viewwidth)
+ return; // off the right side
+ tx+=p->width;
+ x2 = ((xcent+(tx*dc_invscale)) >>SFRACBITS) - 1 ;
+ if (x2 < 0)
+ return; // off the left side
+
+ dc_iscale=0xffffffffu/(unsigned)dc_invscale;
+// dc_iscale=(1<<(16+6+size))/height;
+ dc_texturemid=(((32<<size)+p->topoffset)<<SFRACBITS)+(SFRACUNIT>>1);
+ sprtopoffset=(centeryclipped<<16) - FixedMul(dc_texturemid,dc_invscale);
+
+//
+// store information in a vissprite
+//
+ if (x1<0)
+ {
+ frac=dc_iscale*(-x1);
+ x1=0;
+ }
+ else
+ frac=0;
+
+ x2 = x2 >= viewwidth ? viewwidth-1 : x2;
+
+ startx=x1;
+ startfrac=frac;
+
+#ifdef DOS
+ for (plane=startx; plane<startx+4; plane++,startfrac+=dc_iscale)
+#endif
+
+ {
+ frac=startfrac;
+
+#ifdef DOS
+ b=(byte *)bufferofs+(plane>>2);
+ VGAWRITEMAP(plane&3);
+ VGAREADMAP(plane&3);
+#else
+ b=(byte *)bufferofs+startx;
+#endif
+
+#ifdef DOS
+ for (x1=plane; x1<=x2 ; x1+=4, frac += dc_iscale<<2,b++)
+#else
+ for (x1=startx; x1<=x2 ; x1++, frac += dc_iscale,b++)
+#endif
+ if (type==0)
+ ScaleClippedPost(((p->collumnofs[frac>>SFRACBITS])+shape),b);
+ else
+ ScaleTransparentClippedPost(((tp->collumnofs[frac>>SFRACBITS])+shape),b,transparentlevel);
+ }
+}
+
+
+/*
+=================
+=
+= DrawScreenSizedSprite
+=
+=================
+*/
+extern int G_gmasklump;
+void DrawScreenSizedSprite (int lump)
+{
+ //draws gasmask among other things zxcv
+ byte *shape,*src;
+ int frac;
+ patch_t *p;
+ int x1,x2;
+ int tx;
+// int plane;
+ byte * b;
+ int startfrac;
+
+ int offset;
+ int length;
+ int topscreen;
+ int bottomscreen;
+ byte *cnt,*Ycnt;
+
+ // SetTextMode ( );
+ whereami=39;
+ shadingtable=colormap+(1<<12);
+ shape=W_CacheLumpNum(lump,PU_CACHE, Cvt_patch_t, 1);
+ p=(patch_t *)shape;
+ dc_invscale=(viewwidth<<16)/p->origsize;
+ tx=-p->leftoffset;
+ centeryclipped=viewheight>>1;
+ //centeryclipped=(viewheight>>1)+43;
+//
+// calculate edges of the shape
+//
+ x1 = (tx*dc_invscale)>>SFRACBITS;
+ if (x1 >= viewwidth)
+ {
+ return; // off the right side
+ }
+ tx+=p->width;
+ x2 = ((tx*dc_invscale) >>SFRACBITS) - 1 ;
+ if (x2 < 0)
+ {
+ return; // off the left side
+ }
+
+ dc_iscale=0xffffffffu/(unsigned)dc_invscale;
+ dc_texturemid=(((p->origsize>>1) + p->topoffset)<<SFRACBITS)+(SFRACUNIT>>1);
+ sprtopoffset=(centeryclipped<<16) - FixedMul(dc_texturemid,dc_invscale);
+
+ x2 = (viewwidth-1);
+
+ startfrac=0;
+
+ {
+ frac=startfrac;
+ b=(byte *)bufferofs;
+
+ ///////////// BNA PATCH //////////////////////////////////////////////////////////
+ //gmasklump=W_GetNumForName("p_gmask"); //=783
+ //perhaps I should have painted the mask in a seperate buffer
+ //and streched it and copyet it back, but that would demand
+ //a new buffer (size=800x600) and slowed the game down so ?
+
+ // if its the gasmask, paint black patches at hires
+ if ((lump == G_gmasklump)&&(iGLOBAL_SCREENWIDTH>320)) {
+ src = ((p->collumnofs[frac>>SFRACBITS])+shape);
+ offset=*(src++);
+ length=*(src++);
+ topscreen = sprtopoffset + (dc_invscale*offset);
+ bottomscreen = topscreen + (dc_invscale*length);
+ dc_yl = (topscreen+SFRACUNIT-1)>>SFRACBITS;//=41 viewheight=584
+ dc_yh = ((bottomscreen-1)>>SFRACBITS);//=540 viewwidth =800
+ //paint upper black patch in gasmask
+ for (cnt=b; cnt<b+viewwidth; cnt++) {
+ for (Ycnt=cnt; Ycnt<cnt+(dc_yl*iGLOBAL_SCREENWIDTH); Ycnt+=iGLOBAL_SCREENWIDTH) {
+ *Ycnt = 36;
+ }
+ }
+ //paint lower black patch in gasmask
+ for (cnt=b+(dc_yh*iGLOBAL_SCREENWIDTH); cnt<b+(dc_yh*iGLOBAL_SCREENWIDTH)+viewwidth; cnt++) {
+ for (Ycnt=cnt; Ycnt<b+(viewheight*iGLOBAL_SCREENWIDTH); Ycnt+=iGLOBAL_SCREENWIDTH) {
+ *Ycnt = 36;
+ }
+ }
+ }
+ ///////////////////////////////////////////////////////////////////////////////////
+ for (x1=0; x1<=x2; x1++, frac += dc_iscale,b++)
+
+ {
+ ScaleClippedPost(((p->collumnofs[frac>>SFRACBITS])+shape),b);
+ }
+ }
+}
+
+#if 0
+byte *shape;
+int frac;
+patch_t *p;
+int x1,x2;
+int tx;
+int xdc_invscale;
+int xdc_iscale;
+byte * buf;
+byte * b;
+int plane;
+int startx,startfrac;
+
+whereami=39;
+SetPlayerLightLevel();
+buf=(byte *)bufferofs;
+shape=W_CacheLumpNum(lump,PU_CACHE);
+p=(patch_t *)shape;
+dc_invscale=(viewheight<<16)/200;
+xdc_invscale=(viewwidth<<16)/320;
+
+tx=-p->leftoffset;
+centeryclipped=viewheight>>1;
+//
+// calculate edges of the shape
+//
+x1 = (tx*xdc_invscale)>>SFRACBITS;
+if (x1 >= viewwidth)
+ return; // off the right side
+tx+=p->width;
+x2 = ((tx*xdc_invscale)>>SFRACBITS) - 1 ;
+if (x2 < 0)
+ return; // off the left side
+
+dc_iscale=(200*65536)/viewheight;
+xdc_iscale=(320*65536)/viewwidth;
+dc_texturemid=(((p->height>>1)+p->topoffset)<<SFRACBITS)+(SFRACUNIT>>1);
+sprtopoffset=(centeryclipped<<16) - FixedMul(dc_texturemid,dc_invscale);
+
+//
+// store information in a vissprite
+//
+if (x1<0)
+{
+ frac=xdc_iscale*(-x1);
+ x1=0;
+}
+else
+ frac=0;
+x2 = x2 >= viewwidth ? viewwidth-1 : x2;
+
+startx=x1;
+startfrac=frac;
+for (plane=startx; plane<startx+4; plane++,startfrac+=xdc_iscale)
+{
+ frac=startfrac;
+ b=(byte *)bufferofs+(plane>>2);
+ VGAWRITEMAP(plane&3);
+ for (x1=plane; x1<=x2 ; x1+=4, frac += xdc_iscale<<2,b++)
+ ScaleClippedPost(((p->collumnofs[frac>>SFRACBITS])+shape),b);
+}
+}
+#endif
+
+
+
+//******************************************************************************
+//
+// DrawNormalPost
+//
+//******************************************************************************
+
+void DrawNormalPost (byte * src, byte * buf)
+{
+ int offset;
+ int length;
+ int s;
+
+ whereami=40;
+
+ while (1)
+ {
+ offset=*(src++);
+ if (offset==0xff)
+ return;
+ else
+ {
+ length=*(src++);
+ for (s=0; s<length; s++) {
+ // Spaced out a little for tracking a bug. Should be equivalent.
+ byte *saddr = src+s;
+ byte *daddr = buf + ylookup[offset + s];
+ byte val = *saddr;
+ *daddr = val;
+// *(buf+ylookup[offset+s])=*(src+s);
+ }
+ src+=length;
+ }
+ }
+}
+
+
+
+//******************************************************************************
+//
+// DrawNormalSprite
+//
+//******************************************************************************
+
+void DrawNormalSprite (int x, int y, int shapenum)
+{
+ byte *buffer;
+ int cnt;
+ byte *shape;
+ patch_t *p;
+ int plane;
+ byte * b;
+ int startx;
+
+ whereami=41;
+
+ shape = W_CacheLumpNum (shapenum, PU_CACHE, Cvt_patch_t, 1);
+ p = (patch_t *)shape;
+
+ if (((x-p->leftoffset)<0) || ((x-p->leftoffset+p->width)>iGLOBAL_SCREENWIDTH))
+ Error ("DrawNormalSprite: x is out of range x=%d\n",x-p->leftoffset+p->width);
+ if (((y-p->topoffset)<0) || ((y-p->topoffset+p->height)>iGLOBAL_SCREENHEIGHT))
+ Error ("DrawNormalSprite: y is out of range y=%d\n",y-p->topoffset+p->height);
+
+ startx=x-p->leftoffset;
+ buffer = (byte*)bufferofs+ylookup[y-p->topoffset];
+
+#ifdef DOS
+ for (plane=startx; plane<startx+4; plane++)
+#endif
+ {
+#ifdef DOS
+ b=buffer+(plane>>2);
+ VGAWRITEMAP(plane&3);
+#else
+ b=buffer+startx;
+#endif
+
+#ifdef DOS
+ for (cnt = plane-startx; cnt < p->width; cnt+=4,b++)
+#else
+ for (cnt = 0; cnt < p->width; cnt++,b++)
+#endif
+ DrawNormalPost ((byte *)(p->collumnofs[cnt]+shape), b);
+ }
+}
+
+#ifndef DOS
+
+void R_DrawColumn (byte * buf)
+{
+ // This is *NOT* 100% correct - DDOI
+ int count;
+ int frac, fracstep;
+ byte *dest;
+
+ count = dc_yh - dc_yl + 1;
+ if (count < 0) return;
+
+ dest = buf + ylookup[dc_yl];
+
+ fracstep = dc_iscale;
+ frac = dc_texturemid + (dc_yl-centery)*fracstep;
+
+ while (count--) {
+ //*dest = test++;
+ *dest = shadingtable[dc_source[(frac>>SFRACBITS)]];
+ dest += iGLOBAL_SCREENWIDTH;
+ frac += fracstep;
+ }
+}
+
+void R_TransColumn (byte * buf)
+{
+ int count;
+ byte *dest;
+
+ count = dc_yh - dc_yl + 1;
+ if (count < 0) return;
+
+ dest = buf + ylookup[dc_yl];
+
+ while (count--)
+ {
+ *dest = shadingtable[*dest];
+ dest += iGLOBAL_SCREENWIDTH;
+ }
+}
+
+void R_DrawWallColumn (byte * buf)
+{
+ // This is *NOT* 100% correct - DDOI
+ int count;
+ int frac, fracstep;
+ byte *dest;
+
+ count = dc_yh - dc_yl;
+ if (count < 0) return;
+
+ dest = buf + ylookup[dc_yl];
+
+ fracstep = dc_iscale;
+ frac = dc_texturemid + (dc_yl-centery)*fracstep;
+ frac <<= 10;
+ fracstep <<= 10;
+
+ while (count--) {
+ //*dest = 6;
+ *dest = shadingtable[dc_source[(((unsigned)frac)>>26)]];
+ dest += iGLOBAL_SCREENWIDTH;
+ frac += fracstep;
+ }
+}
+
+void R_DrawClippedColumn (byte * buf)
+{
+ // This is *NOT* 100% correct - DDOI zxcv
+ int count;
+ int frac, fracstep;
+ byte *dest;
+// byte *b;int y;
+
+ count = dc_yh - dc_yl + 1;
+ if (count < 0) return;
+
+ dest = buf + ylookup[dc_yl];
+
+
+ fracstep = dc_iscale;
+ frac = dc_texturemid + (dc_yl-centeryclipped)*fracstep;
+
+ while (count--) {
+ *dest = shadingtable[dc_source[(((unsigned)frac)>>SFRACBITS)]];
+ dest += iGLOBAL_SCREENWIDTH;
+ frac += fracstep;
+ }
+}
+
+void R_DrawSolidColumn (int color, byte * buf)
+{
+ int count;
+ int frac, fracstep;
+ byte *dest;
+
+ count = dc_yh - dc_yl + 1;
+ if (count < 0) return;
+
+ dest = buf + ylookup[dc_yl];
+
+ while (count--)
+ {
+ *dest = (byte)color;
+ dest += iGLOBAL_SCREENWIDTH;
+ }
+}
+
+#endif
--- /dev/null
+++ b/rott/rt_scale.h
@@ -1,0 +1,53 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// RT_SCALE.H - Scale-o-rama
+//
+//***************************************************************************
+#ifndef _rt_scale_public
+#define _rt_scale_public
+
+#include "rt_draw.h"
+
+extern int dc_texturemid;
+extern int dc_iscale;
+extern int dc_invscale;
+extern int centeryclipped;
+extern int sprtopoffset;
+extern int dc_yl;
+extern int dc_yh;
+extern byte * dc_source;
+extern int transparentlevel;
+
+void ScaleShape (visobj_t * vis);
+void ScaleWeapon (int xcent, int yoffset, int shapenum);
+void DrawScreenSprite (int x, int y, int shapenum);
+void SetLightLevel (int height);
+void ScaleMaskedPost (byte * src, byte * buf);
+void DrawScreenSizedSprite (int lump);
+void ScaleTransparentPost (byte * src, byte * buf, int level);
+void ScaleTransparentShape (visobj_t * sprite);
+void ScaleSolidShape (visobj_t * sprite);
+void DrawUnScaledSprite (int x, int y, int shapenum, int shade);
+void DrawPositionedScaledSprite (int x, int y, int shapenum, int height, int type);
+void DrawNormalSprite (int x, int y, int shapenum);
+
+#endif
--- /dev/null
+++ b/rott/rt_sound.c
@@ -1,0 +1,1548 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "rt_def.h"
+#include "rt_sound.h"
+#include "_rt_soun.h"
+#include "fx_man.h"
+#include "music.h"
+#include "z_zone.h"
+#include "w_wad.h"
+#include "rt_main.h"
+#include "rt_ted.h"
+#include "rt_menu.h"
+#include "rt_playr.h"
+#include "rt_util.h"
+#include "rt_rand.h"
+#include "watcom.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+#if PLATFORM_DOS
+#include <mem.h>
+#include <io.h>
+#elif PLATFORM_UNIX
+#include <unistd.h>
+#endif
+
+#include "rt_cfg.h"
+#include "isr.h"
+#include "develop.h"
+#include "rt_net.h"
+
+#include "rt_str.h"
+
+#if (SHAREWARE==0)
+#include "snd_reg.h"
+#else
+#include "snd_shar.h"
+#endif
+//MED
+#include "memcheck.h"
+
+// Local Variables
+
+static int soundstart;
+static int soundtype;
+int SD_Started=false;
+static boolean PositionStored=false;
+static int NumBadSounds=0;
+static int remotestart;
+static boolean SoundsRemapped = false;
+
+#ifdef DOS
+int musicnums[ 11 ] = {
+ -1, UltraSound, SoundBlaster, SoundMan16, ProAudioSpectrum,
+ Awe32, SoundScape, WaveBlaster, GenMidi, SoundCanvas, Adlib
+};
+
+int fxnums[ 11 ] = {
+ -1, UltraSound, SoundBlaster, SoundMan16, ProAudioSpectrum,
+ Awe32, SoundScape, Adlib, SoundSource, TandySoundSource, PC
+};
+#else
+int musicnums[ 11 ] = {
+ -1, -1, -1, -1, -1, -1, SoundScape, -1, -1, -1, -1
+};
+
+int fxnums[ 11 ] = {
+ -1, -1, -1, -1, -1, -1, SoundScape, -1, -1, -1, -1
+};
+#endif
+
+#if 0
+void MU_SetupGUSInitFile( void );
+#endif
+
+int MUSIC_GetPosition( void ) {
+ songposition pos;
+
+ MUSIC_GetSongPosition( &pos );
+ return pos.milliseconds;
+}
+
+void MUSIC_SetPosition( int time ) {
+ MUSIC_SetSongTime( ( unsigned long )time );
+}
+
+
+//***************************************************************************
+//
+// SoundNumber
+//
+//***************************************************************************
+
+int SoundNumber ( int x )
+{
+ if ((x>=SD_REMOTEM1SND) && (x<=SD_REMOTEM10SND))
+ return remotestart + x - SD_REMOTEM1SND;
+// sounds[x].snds[soundtype]+remotestart;
+ else
+ return sounds[x].snds[soundtype]+soundstart;
+}
+
+
+//***************************************************************************
+//
+// SD_MakeCacheable - Make a sound that has just finished playing cacheable again
+//
+//***************************************************************************
+void SD_MakeCacheable( unsigned long sndnum )
+{
+ if (sndnum == (unsigned long) -1)
+ {
+ return;
+ }
+
+ if (sndnum>=MAXSOUNDS)
+ {
+ SoftError ("Illegal sound value in SD_MakeCacheable value=%ld\n",sndnum);
+ return;
+ }
+ sounds[sndnum].count--;
+ if (sounds[sndnum].count>0)
+ return;
+ else
+ W_CacheLumpNum(SoundNumber(sndnum),PU_CACHE, CvtNull, 1);
+}
+
+#if 0
+//***************************************************************************
+//
+// SD_PrintActive
+//
+//***************************************************************************
+void SD_PrintActive ( void )
+{
+ int i;
+
+ myprintf("Active Sounds\n");
+ for (i=0; i<MAXSOUNDS; i++)
+ {
+ if (sounds[i].count>0)
+ {
+ myprintf("sound active #%ld\n",i);
+ }
+ }
+}
+#endif
+
+//***************************************************************************
+//
+// SD_SetupFXCard - Initialize sound Tables and start up sound card
+//
+//***************************************************************************
+
+int SD_SetupFXCard ( int * numvoices, int * numbits, int * numchannels)
+{
+ fx_device device;
+ int status;
+ int card;
+
+ if (SD_Started==true)
+ SD_Shutdown();
+
+ if ( ( FXMode < 0 ) || ( FXMode >= 11 ) )
+ {
+ return( 0 );
+ }
+
+ card = fxnums[ FXMode ];
+ if (card==-1) // Check if it is off
+ return (0);
+#ifdef DOS
+ if ( ( card == SoundBlaster ) || ( card == Awe32 ) )
+ {
+ extern fx_blaster_config SBSettings;
+
+ status = FX_SetupSoundBlaster( SBSettings, numvoices,
+ numbits, numchannels );
+ }
+ else
+ {
+#endif
+ status=FX_SetupCard( card, &device );
+ if ( status == FX_Ok )
+ {
+ *numvoices=device.MaxVoices;
+ *numbits=device.MaxSampleBits;
+ *numchannels=device.MaxChannels;
+ }
+#ifdef DOS
+ }
+#endif
+
+ return (status);
+}
+
+//***************************************************************************
+//
+// SD_Startup - Initialize sound Tables and start up sound card
+//
+//***************************************************************************
+
+int SD_Startup ( boolean bombonerror )
+{
+ int status;
+ int card;
+ int voices;
+ int channels;
+ int bits;
+ int i;
+ extern boolean IS8250;
+
+ if (SD_Started==true)
+ SD_Shutdown();
+
+ if ( ( FXMode < 0 ) || ( FXMode >= 11 ) )
+ {
+ return( 0 );
+ }
+ card = fxnums[ FXMode ];
+ if (card==-1) // Check if it is off
+ return (0);
+
+ switch (card)
+ {
+#ifdef DOS
+ case UltraSound:
+ case SoundBlaster:
+ case SoundMan16:
+ case ProAudioSpectrum:
+ case Awe32:
+ case SoundSource:
+ case TandySoundSource:
+#endif
+ case SoundScape:
+ soundstart=W_GetNumForName("digistrt")+1;
+ soundtype=fx_digital;
+ break;
+#ifdef DOS
+ case Adlib:
+ soundstart=W_GetNumForName("adstart")+1;
+ soundtype=fx_muse;
+ break;
+ case PC:
+ soundstart=W_GetNumForName("pcstart")+1;
+ soundtype=fx_muse;
+ break;
+#endif
+ default:
+ Error("FX: Unsupported Card number %d",FXMode);
+ break;
+ }
+
+ if ( soundtype == fx_digital )
+ {
+ if ( SoundsRemapped == false )
+ {
+ for( i = 0; i < SD_LASTSOUND; i++ )
+ {
+ int snd;
+
+ snd = sounds[ i ].snds[ fx_digital ];
+ if ( snd >= 0)
+ {
+ sounds[ i ].snds[ fx_digital ] = W_GetNumForName(
+ W_GetNameForNum( snd + soundstart ) );
+ }
+ }
+ SoundsRemapped = true;
+ }
+ soundstart = 0;
+ }
+
+ voices = NumVoices;
+ channels = NumChannels;
+ bits = NumBits;
+
+ if ( IS8250 )
+ {
+ voices = max( voices, 4 );
+ channels = 1;
+ bits = 8;
+ }
+
+#ifdef DOS
+ status=FX_Init( card, voices, channels, bits, 11000 );
+#else
+ status=FX_Init( card, voices, channels, bits, 11025 );
+#endif
+
+ if (status != FX_Ok)
+ {
+ if (bombonerror)
+ {
+ DeleteSoundFile ();
+ Error( "%s\n", FX_ErrorString( status ) );
+ }
+
+ return (status);
+ }
+
+ if (stereoreversed == true)
+ {
+ FX_SetReverseStereo(!FX_GetReverseStereo());
+ }
+
+ FX_SetCallBack( SD_MakeCacheable );
+
+ remotestart=W_GetNumForName("remostrt")+1;
+
+ SD_Started=true;
+
+ FX_SetVolume (FXvolume);
+
+ return (0);
+}
+
+//***************************************************************************
+//
+// SD_SoundOkay - checks to see if the sound is okay
+//
+//***************************************************************************
+
+boolean SD_SoundOkay ( int sndnum )
+{
+ if (SD_Started==false)
+ return false;
+
+ if (sndnum>=MAXSOUNDS)
+ Error ("Illegal sound number, sound number = %d\n",sndnum);
+
+ if (SoundOffset(sndnum)==-1)
+ return false;
+
+ if ( ( sounds[ sndnum ].flags & SD_PLAYONCE ) &&
+ ( SD_SoundActive( sounds[ sndnum ].prevhandle ) ) )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//***************************************************************************
+//
+// SD_PlayIt - Play a pre-setup sound
+//
+//***************************************************************************
+
+int SD_PlayIt ( int sndnum, int angle, int distance, int pitch )
+{
+ int voice;
+ byte * snd;
+
+#if (DEVELOPMENT == 1)
+#if (SOUNDTEST == 1)
+ SoftError("SOUND =%d \n",sndnum);
+#endif
+#endif
+
+ if (!(sounds[sndnum].flags & SD_WRITE))
+ {
+ if (sounds[sndnum].count)
+ {
+ if (distance<=sounds[sndnum].prevdistance)
+ FX_StopSound(sounds[sndnum].prevhandle);
+ else
+ return 0;
+ }
+ }
+
+ if ( !FX_VoiceAvailable( sounds[sndnum].priority ) )
+ {
+ return( 0 );
+ }
+
+ sounds[sndnum].count++;
+
+ snd=W_CacheLumpNum(SoundNumber(sndnum),PU_STATIC, CvtNull, 1);
+
+ if ( *snd == 'C' )
+ {
+ voice = FX_PlayVOC3D( snd, pitch, angle, distance,
+ sounds[sndnum].priority, (unsigned long) sndnum );
+ }
+ else
+ {
+ voice = FX_PlayWAV3D( snd, pitch, angle, distance,
+ sounds[sndnum].priority, (unsigned long) sndnum );
+ }
+
+ if ( voice < FX_Ok )
+ {
+#if (DEVELOPMENT == 1)
+ /*
+ if (MV_ErrorCode == MV_InvalidVOCFile)
+ {
+ Error("SD_PlayIt: Invalid VOC File snd=%p sndnum=%ld lump=%ld\n",snd,sndnum,SoundNumber(sndnum));
+ }
+ */
+ NumBadSounds++;
+ SoftError("SD_PlayIt: Error/Warning %s\n",FX_ErrorString( FX_Error ));
+ SoftError("BadSoundNumber %ld time %ld\n",NumBadSounds,GetTicCount());
+#endif
+ SD_MakeCacheable( sndnum );
+
+ return 0;
+ }
+
+ NumBadSounds=0;
+
+ if (!(sounds[sndnum].flags & SD_WRITE))
+ {
+ sounds[sndnum].prevhandle=voice;
+ sounds[sndnum].prevdistance=distance;
+ }
+ return voice;
+}
+
+
+//***************************************************************************
+//
+// SD_Play - Play a sample
+//
+//***************************************************************************
+
+int SD_Play ( int sndnum )
+{
+ int voice;
+ int pitch;
+
+ if ( SD_SoundOkay ( sndnum ) == false )
+ return 0;
+
+ pitch = 0;
+
+ if ( !( sounds[ sndnum ].flags & SD_PITCHSHIFTOFF ) )
+ {
+ pitch = PitchOffset();
+ }
+
+ voice = SD_PlayIt ( sndnum, 0, 0, pitch );
+
+ return voice;
+
+}
+
+//***************************************************************************
+//
+// SD_Play3D - Play a positioned sample
+//
+//***************************************************************************
+
+int SD_Play3D ( int sndnum, int angle, int distance )
+{
+ int voice;
+ int pitch;
+
+ if ( SD_SoundOkay ( sndnum ) == false )
+ return 0;
+
+ pitch = 0;
+ if ( !( sounds[ sndnum ].flags & SD_PITCHSHIFTOFF ) )
+ {
+ pitch = PitchOffset();
+ }
+
+ voice = SD_PlayIt ( sndnum, angle, distance, pitch );
+
+ return voice;
+
+}
+
+//***************************************************************************
+//
+// SD_PlayPositionedSound - Play a positioned sample
+//
+//***************************************************************************
+
+int SD_PlayPositionedSound ( int sndnum, int px, int py, int x, int y )
+{
+ int voice;
+ int angle;
+ int distance;
+ int dx;
+ int dy;
+ int pitch;
+
+ if ( SD_SoundOkay ( sndnum ) == false )
+ return 0;
+
+ dx=(x-px);
+ dy=(py-y);
+
+ distance=FindDistance(dx,dy) >> SD_DISTANCESHIFT;
+
+ if (distance>255)
+ return 0;
+
+ if (distance!=0)
+ {
+ angle = ( atan2_appx(dx,dy) & (FINEANGLES-1) ) >> 6;
+ }
+ else
+ {
+ angle=0;
+ }
+
+ pitch = 0;
+
+ if ( !( sounds[ sndnum ].flags & SD_PITCHSHIFTOFF ) )
+ {
+ pitch = PitchOffset();
+ }
+
+ voice = SD_PlayIt ( sndnum, angle, distance, pitch );
+
+ return voice;
+
+}
+
+//***************************************************************************
+//
+// SD_PlaySoundRTP - Play a positioned sample relative to the player
+//
+//***************************************************************************
+
+int SD_PlaySoundRTP ( int sndnum, int x, int y )
+{
+ int voice;
+ int angle;
+ int distance;
+ int dx;
+ int dy;
+ int pitch;
+
+
+ if ( SD_SoundOkay ( sndnum ) == false )
+ return 0;
+
+ dx=(x-player->x);
+ dy=(player->y-y);
+
+ distance=FindDistance(dx,dy) >> SD_DISTANCESHIFT;
+
+ if (distance>255)
+ return 0;
+
+ if (distance!=0)
+ {
+ angle = ( (player->angle - atan2_appx(dx,dy)) & (FINEANGLES-1) ) >> 6;
+ }
+ else
+ {
+ angle=0;
+ }
+
+ pitch = 0;
+
+ if ( !( sounds[ sndnum ].flags & SD_PITCHSHIFTOFF ) )
+ {
+ pitch = PitchOffset();
+ }
+
+ voice = SD_PlayIt ( sndnum, angle, distance, pitch );
+
+ return voice;
+}
+
+//***************************************************************************
+//
+// SD_PlayPitchedSound - Play a pitched sample
+//
+//***************************************************************************
+
+int SD_PlayPitchedSound ( int sndnum, int volume, int pitch )
+{
+ int voice;
+ int distance;
+
+ if ( SD_SoundOkay ( sndnum ) == false )
+ return 0;
+
+ distance = 255 - volume;
+
+ voice = SD_PlayIt ( sndnum, 0, distance, pitch );
+
+ return voice;
+}
+
+//***************************************************************************
+//
+// SD_SetSoundPitch - sets the pitch of a sound
+//
+//***************************************************************************
+
+void SD_SetSoundPitch ( int sndnum, int pitch )
+{
+ int status;
+
+ if (SD_Started==false)
+ return;
+
+ if (!FX_SoundActive(sndnum))
+ return;
+
+ status=FX_SetPitch( sndnum, pitch );
+ if (status != FX_Ok)
+ {
+#if (DEVELOPMENT == 1)
+ SoftError("SD_SetSoundPitch : %s\n",FX_ErrorString( status ));
+#endif
+ }
+}
+
+//***************************************************************************
+//
+// SD_PanRTP Sound - pan a positioned sample relative to the player
+//
+//***************************************************************************
+
+void SD_PanRTP ( int handle, int x, int y )
+{
+ int angle;
+ int distance;
+ int dx;
+ int dy;
+ int status;
+
+ if (SD_Started==false)
+ return;
+
+ if (!FX_SoundActive(handle))
+ return;
+
+ dx=(x-player->x);
+ dy=(player->y-y);
+
+ distance=FindDistance(dx,dy) >> SD_DISTANCESHIFT;
+
+ if (distance>255)
+ return;
+
+ if (distance!=0)
+ {
+ angle = ( (player->angle - atan2_appx(dx,dy)) & (FINEANGLES-1) ) >> 6;
+ }
+ else
+ {
+ angle = 0;
+ }
+
+ status = FX_Pan3D ( handle, angle, distance );
+
+ if (status != FX_Ok)
+ {
+#if (DEVELOPMENT == 1)
+ SoftError("SD_PanPositionedSound: %s\n",FX_ErrorString( status ));
+#endif
+ }
+}
+
+//***************************************************************************
+//
+// SD_SetPan - set the pan of a sample
+//
+//***************************************************************************
+
+void SD_SetPan ( int handle, int vol, int left, int right )
+{
+ int status;
+
+ if (SD_Started==false)
+ return;
+
+ if (!FX_SoundActive(handle))
+ return;
+
+ status=FX_SetPan( handle, vol, left, right );
+
+ if (status != FX_Ok)
+ {
+#if (DEVELOPMENT == 1)
+ SoftError("SD_SetPan: %s\n",FX_ErrorString( status ));
+#endif
+ }
+}
+
+//***************************************************************************
+//
+// SD_PanPositioned Sound - pan a positioned sample
+//
+//***************************************************************************
+
+void SD_PanPositionedSound ( int handle, int px, int py, int x, int y )
+{
+ int angle;
+ int distance;
+ int dx;
+ int dy;
+ int status;
+
+ if (SD_Started==false)
+ return;
+
+ if (!FX_SoundActive(handle))
+ return;
+
+ dx=(x-px);
+ dy=(py-y);
+
+ distance=FindDistance(dx,dy) >> SD_DISTANCESHIFT;
+
+ if (distance>255)
+ return;
+
+ if (distance!=0)
+ {
+ angle = ( atan2_appx(dx,dy) & (FINEANGLES-1) ) >> 6;
+ }
+ else
+ {
+ angle = 0;
+ }
+
+ status=FX_Pan3D( handle, angle, distance );
+
+ if (status != FX_Ok)
+ {
+#if (DEVELOPMENT == 1)
+ SoftError("SD_PanPositionedSound: %s\n",FX_ErrorString( status ));
+#endif
+ }
+}
+
+
+//***************************************************************************
+//
+// SD_StopSound - Stop the current sound from playing
+//
+//***************************************************************************
+
+void SD_StopSound ( int handle )
+{
+ int status;
+
+ if (SD_Started==false)
+ return;
+
+ status=FX_StopSound( handle);
+
+ if (status != FX_Ok)
+ {
+#if (DEVELOPMENT == 1)
+ SoftError("SD_StopSound: %s\n",FX_ErrorString( status ));
+#endif
+ }
+}
+
+//***************************************************************************
+//
+// SD_StopAllSounds - Stop All the sounds currently playing
+//
+//***************************************************************************
+
+void SD_StopAllSounds ( void )
+{
+ int status;
+
+ if (SD_Started==false)
+ return;
+
+ status=FX_StopAllSounds();
+
+ if (status != FX_Ok)
+ {
+#if (DEVELOPMENT == 1)
+ SoftError("SD_StopAllSounds: %s\n",FX_ErrorString( status ));
+#endif
+ }
+}
+
+//***************************************************************************
+//
+// SD_SoundActive - See if a sound is active
+//
+//***************************************************************************
+
+int SD_SoundActive ( int handle )
+{
+ if (SD_Started==false)
+ {
+ return false;
+ }
+ else
+ {
+ return (FX_SoundActive(handle));
+ }
+}
+
+//***************************************************************************
+//
+// SD_WaitSound - wait until a sound has finished
+//
+//***************************************************************************
+void SD_WaitSound ( int handle )
+{
+ int time;
+
+ IN_ClearKeysDown();
+
+ while (FX_SoundActive(handle)!=0)
+ {
+ time=GetTicCount()+1;
+ while (time>GetTicCount()) {}
+ if ((LastScan) || IN_GetMouseButtons())
+ break;
+ }
+}
+
+
+//***************************************************************************
+//
+// SD_Shutdown - Shutdown the sound system
+//
+//***************************************************************************
+
+void SD_Shutdown (void)
+{
+ if (SD_Started==false)
+ return;
+
+ FX_Shutdown();
+ SD_Started=false;
+}
+
+
+//***************************************************************************
+//
+// SD_PreCacheSound - PreCache sound
+//
+//***************************************************************************
+
+void SD_PreCacheSound ( int num )
+{
+ if ( SD_SoundOkay ( num ) == false )
+ return;
+
+ PreCacheLump(SoundNumber(num),PU_CACHESOUNDS+sounds[num].priority,cache_other);
+}
+
+//***************************************************************************
+//
+// SD_PreCacheSoundGroup - PreCache sound group
+//
+//***************************************************************************
+
+void SD_PreCacheSoundGroup ( int lo, int hi )
+{
+ int i;
+
+ if (SD_Started==false)
+ return;
+
+ for (i=lo; i<=hi; i++)
+ SD_PreCacheSound(i);
+}
+
+
+#if (SHAREWARE == 1)
+#define MAXSONGS 18
+static song_t rottsongs[MAXSONGS] = {
+ { loop_no, song_apogee,"FANFARE2","Apogee Fanfare"},
+ { loop_yes, song_title,"RISE", "Rise"},
+ { loop_yes, song_menu,"MMMENU", "MMMenu"},
+ { loop_yes, song_christmas,"DEADLY", "Deadly Gentlemen"},
+ { loop_yes, song_elevator,"GOINGUP", "Going up?"},
+ { loop_yes, song_endlevel,"HOWDIDO", "How'd I do?"},
+ { loop_yes, song_secretmenu,"FISHPOLK","Fish Polka"},
+ { loop_yes, song_gameover,"YOUSUCK", "You Suck"},
+ { loop_yes, song_youwin,"WATZNEXT","Watz Next?"},
+ { loop_no, song_gason,"GAZZ!", "Gazz!"},
+ { loop_yes, song_level,"FASTWAY", "Goin' Down The Fast Way"},
+ { loop_yes, song_level,"MISTACHE","Mist Ache"},
+ { loop_yes, song_level,"OWW", "Oww!!!"},
+ { loop_yes, song_level,"SMOKE", "Smoke And Mirrors"},
+ { loop_yes, song_level,"SPRAY", "Spray"},
+ { loop_yes, song_level,"RUNLIKE", "Run Like Smeg"},
+ { loop_yes, song_level,"SMOOTH", "Havana Smooth"},
+ { loop_yes, song_level,"CHANT", "Chant"},
+};
+#else
+#define MAXSONGS 34
+static song_t rottsongs[MAXSONGS] = {
+ { loop_no, song_apogee,"FANFARE2","Apogee Fanfare"},
+ { loop_yes, song_title,"RISE", "Rise"},
+ { loop_yes, song_menu,"MMMENU", "MMMenu"},
+ { loop_yes, song_christmas,"DEADLY", "Deadly Gentlemen"},
+ { loop_yes, song_elevator,"GOINGUP", "Going up?"},
+ { loop_yes, song_secretmenu,"FISHPOLK","Fish Polka"},
+ { loop_yes, song_endlevel,"HOWDIDO", "How'd I do?"},
+ { loop_yes, song_gameover,"YOUSUCK", "You Suck"},
+ { loop_yes, song_cinematic2,"WATZNEXT","Watz Next?"},
+ { loop_no, song_gason,"GAZZ!", "Gazz!"},
+ { loop_yes, song_level,"FASTWAY", "Goin' Down The Fast Way"},
+ { loop_yes, song_level,"MISTACHE","Mist Ache"},
+ { loop_yes, song_level,"OWW", "Oww!!!"},
+ { loop_yes, song_level,"SMOKE", "Smoke And Mirrors"},
+ { loop_yes, song_level,"SPRAY", "Spray"},
+ { loop_yes, song_level,"RUNLIKE", "Run Like Smeg"},
+ { loop_yes, song_level,"SMOOTH", "Havana Smooth"},
+ { loop_yes, song_level,"CHANT", "Chant"},
+ { loop_yes, song_level,"MEDIEV1A","Funeral of Queen Mary"},
+ { loop_yes, song_level,"TASKFORC","Task Force"},
+ { loop_yes, song_level,"KISSOFF", "KISS Off"},
+ { loop_yes, song_level,"RADAGIO", "Adagio For Strings"},
+ { loop_yes, song_level,"SHARDS", "Shards"},
+ { loop_yes, song_level,"STAIRS", "I Choose the Stairs"},
+ { loop_yes, song_level,"SUCKTHIS","Suck This"},
+ { loop_yes, song_level,"EXCALIBR","Excalibur"},
+ { loop_yes, song_level,"CCCOOL", "CCCool"},
+ { loop_yes, song_level,"WORK_DAY","Work Day"},
+ { loop_yes, song_level,"WHERIZIT","Where Iz It?"},
+ { loop_no, song_bossdie,"BOSSBLOW", "Boss Blow"},
+ { loop_yes, song_bosssee,"HELLERO", "Hellero"},
+ { loop_yes, song_cinematic1,"EVINRUDE","Evin Rude"},
+ { loop_yes, song_youwin,"VICTORY", "Victory!"},
+ { loop_yes, song_dogend,"HERE_BOY","Here Boy"}
+};
+#endif
+
+static byte * currentsong;
+static int MU_Started=false;
+static int lastsongnumber=-1;
+int storedposition=0;
+
+//****************************************************************************
+//
+// MU_JukeBoxMenu()
+//
+//****************************************************************************
+
+void MU_PlayJukeBoxSong
+(
+ int which
+)
+
+{
+ if ( ( MusicMode > 0 ) && ( MU_Started == true ) )
+ {
+ SetMenuHeader( rottsongs[ which ].songname );
+ MU_PlaySong( which );
+ }
+}
+
+
+//****************************************************************************
+//
+// MU_JukeBoxMenu()
+//
+//****************************************************************************
+
+void MU_JukeBoxRedraw
+(
+ void
+)
+
+{
+ if ( ( MusicMode > 0 ) && ( MU_Started == true ) )
+ {
+ SetMenuHeader( rottsongs[ lastsongnumber ].songname );
+ }
+}
+
+
+//****************************************************************************
+//
+// MU_JukeBoxMenu()
+//
+//****************************************************************************
+
+void MU_JukeBoxMenu
+(
+ void
+)
+
+{
+ char *SongNames[ MAXSONGS ];
+ int i;
+
+ for( i = 0; i < MAXSONGS; i++ )
+ {
+ SongNames[ i ] = rottsongs[ i ].songname;
+ }
+
+ HandleMultiPageCustomMenu( SongNames, MAXSONGS, lastsongnumber,
+ "Jukebox", MU_PlayJukeBoxSong, MU_JukeBoxRedraw, false );
+
+ if ( rottsongs[ lastsongnumber ].loopflag == loop_no )
+ {
+ MU_StartSong(song_level);
+ }
+}
+
+//***************************************************************************
+//
+// MusicStarted - see if the music is started
+//
+//***************************************************************************
+boolean MusicStarted( void )
+{
+ return MU_Started;
+}
+
+//***************************************************************************
+//
+// MU_Startup - Initialize music stuff
+//
+//***************************************************************************
+
+int MU_Startup ( boolean bombonerror )
+{
+ int status;
+ int card;
+
+ if (MU_Started==true)
+ {
+ MU_StopSong();
+ MU_Shutdown();
+ }
+ if ( ( MusicMode < 0 ) || ( MusicMode >= 11 ) )
+ {
+ return( 0 );
+ }
+ card = musicnums[ MusicMode ];
+ if (card==-1) // Check if it is off
+ return (0);
+
+#ifdef DOS
+ if ( ( card == SoundBlaster ) || ( card == Awe32 ) || ( card == WaveBlaster ) )
+ {
+ if ( SD_Started == false )
+ {
+ extern fx_blaster_config SBSettings;
+ int numvoices;
+ int numbits;
+ int numchannels;
+
+ FX_SetupSoundBlaster( SBSettings, &numvoices,
+ &numbits, &numchannels );
+ }
+ }
+
+ if (card== UltraSound)
+ {
+ MU_SetupGUSInitFile();
+ }
+
+ status=MUSIC_Init( card, MidiAddress );
+#else
+ /* Not DOS, no address config needed */
+ status=MUSIC_Init( card, 0 );
+#endif
+
+
+ if (status != MUSIC_Ok) {
+ if (bombonerror)
+ {
+ DeleteSoundFile ();
+ Error( "%s\n", MUSIC_ErrorString( status ) );
+ }
+ else
+ return (status);
+ }
+
+ currentsong=0;
+
+ MU_Started=true;
+
+ MU_SetVolume (MUvolume);
+
+ return (0);
+}
+
+//***************************************************************************
+//
+// MU_Shutdown - Shutdown the music system
+//
+//***************************************************************************
+
+void MU_Shutdown (void)
+{
+ if (MU_Started==false)
+ return;
+ MUSIC_Shutdown();
+ MU_Started=false;
+}
+
+#ifdef DOS
+//***************************************************************************
+//
+// MU_SetupGUSInitFile - initialize GUS stuff
+//
+//***************************************************************************
+
+void MU_SetupGUSInitFile( void )
+{
+ char filename[ 128 ];
+
+ GetPathFromEnvironment( filename, ApogeePath, GUSMIDIINIFILE );
+ if (access (filename, F_OK) != 0)
+ {
+ int lump;
+
+ lump=W_GetNumForName("gusmidi");
+
+ SaveFile (filename, W_CacheLumpNum(lump,PU_CACHE, CvtNull, 1), W_LumpLength(lump));
+ }
+}
+
+#endif
+
+//***************************************************************************
+//
+// MU_GetNumForType - returns number of song in rottsongs of specific type
+//
+//***************************************************************************
+int MU_GetNumForType ( int type )
+{
+ int i;
+
+ for (i=0; i<MAXSONGS; i++)
+ {
+ if (rottsongs[i].songtype == type)
+ return i;
+ }
+ Error("MU_GetNumForType: could not find song type in list\n");
+ return -1;
+}
+
+
+//***************************************************************************
+//
+// MU_PlaySong - Play a specific song number
+//
+//***************************************************************************
+
+void MU_PlaySong ( int num )
+{
+ int lump;
+ int size;
+
+ if (MU_Started==false)
+ return;
+
+ if (num<0)
+ return;
+
+ if (num>=MAXSONGS)
+ Error("Song number out of range\n");
+
+ MU_StopSong();
+
+ lastsongnumber=num;
+
+ lump = W_GetNumForName(rottsongs[num].lumpname);
+ size = W_LumpLength(lump);
+
+ currentsong=W_CacheLumpNum(lump,PU_STATIC, CvtNull, 1);
+
+#ifdef PLATFORM_DOS
+ if (rottsongs[num].loopflag == loop_yes)
+ MUSIC_PlaySong(currentsong,size,MUSIC_LoopSong);
+ else
+ MUSIC_PlaySong(currentsong,size,MUSIC_PlayOnce);
+#else
+ if (rottsongs[num].loopflag == loop_yes)
+ MUSIC_PlaySongROTT(currentsong,size,MUSIC_LoopSong);
+ else
+ MUSIC_PlaySongROTT(currentsong,size,MUSIC_PlayOnce);
+#endif
+
+ MU_SetVolume (MUvolume);
+}
+
+//***************************************************************************
+//
+// MU_StopSong - Play a specific song number
+//
+//***************************************************************************
+
+void MU_StopSong ( void )
+{
+ if (MU_Started==false)
+ return;
+
+ MUSIC_StopSong ();
+ if (currentsong)
+ {
+ W_CacheLumpName(rottsongs[lastsongnumber].lumpname,PU_CACHE, CvtNull, 1);
+ currentsong=0;
+ }
+}
+
+//***************************************************************************
+//
+// MU_GetSongNumber - get current song number
+//
+//***************************************************************************
+
+int MU_GetSongNumber ( void )
+{
+ return lastsongnumber;
+}
+
+
+//***************************************************************************
+//
+// MU_FadeToSong - Fade to a specific song in a certain time
+//
+//***************************************************************************
+
+void MU_FadeToSong ( int num, int time )
+{
+ int t;
+
+ if (MU_Started==false)
+ return;
+
+ MU_FadeOut(time>>1);
+
+ while (MU_FadeActive())
+ {
+ t=GetTicCount();
+ while (GetTicCount()==t) {}
+ }
+
+ MU_FadeIn (num,time>>1);
+}
+
+//***************************************************************************
+//
+// MU_FadeIn - Fade in
+//
+//***************************************************************************
+
+void MU_FadeIn ( int num, int time )
+{
+ if (MU_Started==false)
+ return;
+
+ MUSIC_SetVolume(0);
+ MU_PlaySong ( num );
+ MUSIC_FadeVolume (MUvolume, time);
+}
+
+//***************************************************************************
+//
+// MU_FadeOut - Fade out
+//
+//***************************************************************************
+
+void MU_FadeOut ( int time )
+{
+ if (MU_Started==false)
+ return;
+ if (!MUSIC_SongPlaying())
+ {
+#if (DEVELOPMENT == 1)
+ SoftError("Called FadeOut with no song playing\n");
+#endif
+ return;
+ }
+ MUSIC_FadeVolume(0,time);
+}
+
+
+//***************************************************************************
+//
+// MU_StartSong - Start a context sensitive song
+//
+//***************************************************************************
+
+void MU_StartSong ( int songtype )
+{
+ int songnum;
+
+ if (MU_Started==false)
+ return;
+
+ MU_StopSong();
+
+ songnum = MU_GetNumForType ( songtype );
+ switch (songtype)
+ {
+ case song_level:
+ if (IsChristmas())
+ {
+ songnum = MU_GetNumForType ( song_christmas );
+ }
+ else
+ {
+ songnum += GetSongForLevel ();
+ }
+ break;
+ }
+ MU_PlaySong (songnum);
+}
+
+//***************************************************************************
+//
+// MU_StoreSongPostition - Save off Song Position
+//
+//***************************************************************************
+
+void MU_StoreSongPosition ( void )
+{
+ if (MU_Started==false)
+ return;
+ PositionStored=true;
+ storedposition=MUSIC_GetPosition();
+}
+
+//***************************************************************************
+//
+// MU_RestoreSongPostition - Save off Song Position
+//
+//***************************************************************************
+
+void MU_RestoreSongPosition ( void )
+{
+ if (MU_Started==false)
+ return;
+ if (PositionStored==false)
+ return;
+ PositionStored=false;
+
+ MUSIC_SetPosition(storedposition);
+}
+
+//***************************************************************************
+//
+// MU_GetStoredPostition - Get Stored song Position
+//
+//***************************************************************************
+
+int MU_GetStoredPosition ( void )
+{
+ if (PositionStored)
+ return storedposition;
+ else
+ return -1;
+}
+
+//***************************************************************************
+//
+// MU_SetStoredPostition - Get Stored song Position
+//
+//***************************************************************************
+
+void MU_SetStoredPosition ( int position )
+{
+ if (MU_Started==false)
+ return;
+ if (position==-1)
+ return;
+ PositionStored=true;
+ storedposition=position;
+}
+
+
+
+//***************************************************************************
+//
+// MU_GetSongPostition - Get Song Position
+//
+//***************************************************************************
+
+int MU_GetSongPosition ( void )
+{
+ if (MU_Started==false)
+ return 0;
+ return MUSIC_GetPosition();
+}
+
+//***************************************************************************
+//
+// MU_SetSongPostition - Set Song Position
+//
+//***************************************************************************
+
+void MU_SetSongPosition ( int position )
+{
+ if (MU_Started==false)
+ return;
+ MUSIC_SetPosition(position);
+}
+
+//***************************************************************************
+//
+// MU_SaveMusic
+//
+//***************************************************************************
+
+void MU_SaveMusic (byte ** buf, int * size)
+{
+ int unitsize;
+ byte *ptr;
+ int vsize;
+ int i;
+
+ //
+ // Size
+ //
+
+ unitsize=0;
+
+ unitsize+=sizeof(i);
+ unitsize+=sizeof(i);
+ unitsize+=sizeof(i);
+
+
+ *size = unitsize;
+ *buf = (byte *) SafeMalloc (*size);
+
+ ptr = *buf;
+
+ i=MU_GetSongNumber();
+ if (rottsongs[i].songtype == song_menu)
+ {
+ i = MU_GetNumForType ( song_level );
+ if (IsChristmas())
+ {
+ i = MU_GetNumForType ( song_christmas );
+ }
+ else
+ {
+ i += GetSongForLevel ();
+ }
+ vsize=sizeof(i);
+ memcpy(ptr,&i,vsize);
+ ptr+=vsize;
+
+ i=MU_GetStoredPosition();
+ vsize=sizeof(i);
+ memcpy(ptr,&i,vsize);
+ ptr+=vsize;
+
+ i=-1;
+ vsize=sizeof(i);
+ memcpy(ptr,&i,vsize);
+ ptr+=vsize;
+ }
+ else
+ {
+ vsize=sizeof(i);
+ memcpy(ptr,&i,vsize);
+ ptr+=vsize;
+
+ i=MU_GetSongPosition();
+ vsize=sizeof(i);
+ memcpy(ptr,&i,vsize);
+ ptr+=vsize;
+
+ i=MU_GetStoredPosition();
+ vsize=sizeof(i);
+ memcpy(ptr,&i,vsize);
+ ptr+=vsize;
+ }
+}
+
+
+//***************************************************************************
+//
+// MU_LoadMusic
+//
+//***************************************************************************
+
+void MU_LoadMusic (byte * buf, int size)
+{
+ int unitsize;
+ byte *ptr;
+ int i;
+ int songnumber;
+ boolean differentsong=false;
+ int vsize;
+
+ //
+ // Size
+ //
+
+ unitsize=0;
+
+ unitsize+=sizeof(i);
+ unitsize+=sizeof(i);
+ unitsize+=sizeof(i);
+
+ if (size!=unitsize)
+ Error("LoadMusic: Different number of parameters\n");
+
+ ptr = buf;
+
+ vsize=sizeof(songnumber);
+ memcpy(&songnumber,ptr,vsize);
+ ptr+=vsize;
+ if (MU_GetSongNumber () != songnumber)
+ {
+ MU_PlaySong(songnumber);
+ differentsong=true;
+ }
+
+ vsize=sizeof(i);
+ memcpy(&i,ptr,vsize);
+ ptr+=vsize;
+ if (differentsong==true)
+ {
+ MU_SetSongPosition(i);
+ }
+
+ vsize=sizeof(i);
+ memcpy(&i,ptr,vsize);
+ ptr+=vsize;
+ MU_SetStoredPosition(i);
+
+ // Check if game was saved with NOSOUND
+
+ if (MU_GetSongNumber () != songnumber)
+ {
+ MU_StartSong ( song_level );
+ }
+}
--- /dev/null
+++ b/rott/rt_sound.h
@@ -1,0 +1,689 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_sound_public
+#define _rt_sound_public
+
+#include "music.h"
+#include "develop.h"
+
+typedef enum {
+
+// MENU SOUNDS
+
+ SD_MENUFLIP,
+ SD_ESCPRESSEDSND,
+ SD_MOVECURSORSND,
+ SD_SELECTSND,
+ SD_WARNINGBOXSND,
+ SD_INFOBOXSND,
+ SD_QUESTIONBOXSND,
+ SD_NOPESND,
+ SD_QUIT1SND,
+ SD_QUIT2SND,
+ SD_QUIT3SND,
+ SD_QUIT4SND,
+ SD_QUIT5SND,
+ SD_QUIT6SND,
+ SD_QUIT7SND,
+
+
+// GAME SOUNDS
+
+ SD_LEVELSTARTSND,
+ SD_LEVELDONESND,
+ SD_GAMEOVERSND,
+
+// LEVEL END SCREEN
+
+ SD_ENDBONUS1SND,
+ SD_NOBONUSSND,
+ SD_PERCENT100SND,
+
+// PLAYER SOUNDS
+
+ SD_HITWALLSND,
+ SD_SELECTWPNSND,
+ SD_NOWAYSND,
+ SD_DONOTHINGSND,
+ SD_NOITEMSND,
+ SD_PLAYERDYINGSND,
+
+ SD_PLAYERTCDEATHSND,
+ SD_PLAYERTBDEATHSND,
+ SD_PLAYERDWDEATHSND,
+ SD_PLAYERLNDEATHSND,
+ SD_PLAYERIPFDEATHSND,
+ SD_PLAYERTCHURTSND,
+ SD_PLAYERTBHURTSND,
+ SD_PLAYERDWHURTSND,
+ SD_PLAYERLNHURTSND,
+ SD_PLAYERIPFHURTSND,
+ SD_PLAYERTCSND,
+ SD_PLAYERTBSND,
+ SD_PLAYERDWSND,
+ SD_PLAYERLNSND,
+ SD_PLAYERIPFSND,
+// SD_WALK1SND,
+// SD_WALK2SND,
+ SD_PLAYERBURNEDSND,
+ SD_PLAYERLANDSND,
+ SD_PLAYERCOUGHMSND,
+ SD_PLAYERCOUGHFSND,
+ SD_NETWIGGLESND,
+ SD_NETFALLSND,
+
+// PLAYER WEAPONS
+
+ SD_ATKPISTOLSND,
+ SD_ATKTWOPISTOLSND,
+ SD_ATKMP40SND,
+ SD_RICOCHET1SND,
+ SD_RICOCHET2SND,
+ SD_RICOCHET3SND,
+ SD_BAZOOKAFIRESND,
+ SD_FIREBOMBFIRESND,
+ SD_HEATSEEKFIRESND,
+ SD_DRUNKFIRESND,
+ SD_FLAMEWALLFIRESND,
+ SD_FLAMEWALLSND,
+ SD_SPLITFIRESND,
+ SD_SPLITSND,
+ SD_GRAVBUILDSND,
+ SD_GRAVFIRESND,
+ SD_GRAVSND,
+ SD_GRAVHITSND,
+ SD_FIREHITSND,
+ SD_MISSILEFLYSND,
+ SD_MISSILEHITSND,
+ SD_EXCALIBOUNCESND,
+ SD_EXCALISWINGSND,
+ SD_EXCALIHITSND,
+ SD_EXCALIBUILDSND,
+ SD_EXCALIBLASTSND,
+ SD_GODMODEFIRESND,
+ SD_GODMODE1SND,
+ SD_GODMODE2SND,
+ SD_GODMODE3SND,
+ SD_LOSEMODESND,
+ SD_DOGMODEPANTSND,
+ SD_DOGMODEBITE1SND,
+ SD_DOGMODEBITE2SND,
+ SD_DOGMODELICKSND,
+ SD_DOGMODEBLASTSND,
+ SD_DOGMODEPREPBLASTSND,
+ SD_DOGMANSND,
+ SD_DOGWOMANSND,
+ SD_GODMANSND,
+ SD_GODWOMANSND,
+ SD_FLYINGSND,
+
+// PLAYER-CAUSED SOUNDS
+
+ SD_GLASSBREAKSND,
+ SD_ITEMBLOWSND,
+ SD_BONUSBARRELSND,
+ SD_TOUCHPLATESND,
+ SD_BADTOUCHSND,
+ SD_EXPLODEFLOORSND,
+ SD_EXPLODESND,
+ SD_GASSTARTSND,
+ SD_GASHISSSND,
+ SD_GASENDSND,
+ SD_GASMASKSND,
+
+// GET ITEM SOUNDS
+
+ SD_GETKEYSND,
+ SD_GETBONUSSND,
+ SD_GETHEALTH1SND,
+ SD_GETHEALTH2SND,
+ SD_COOKHEALTHSND,
+
+ SD_GETWEAPONSND,
+ SD_GETKNIFESND,
+ SD_GETGODSND,
+ SD_GETDOGSND,
+ SD_GETFLEETSND,
+ SD_GETELASTSND,
+ SD_GETSHROOMSSND,
+ SD_GETBVESTSND,
+ SD_GETAVESTSND,
+ SD_GETMASKSND,
+ SD_GETBATSND,
+ SD_GETHEADSND,
+
+ SD_GET1UPSND,
+ SD_GET3UPSND,
+ SD_RESPAWNSND,
+ SD_PLAYERSPAWNSND,
+
+// ACTOR SOUNDS
+
+ SD_LOWGUARD1SEESND,
+ SD_LOWGUARD1ASEESND,
+ SD_LOWGUARD1SEE3SND,
+ SD_LOWGUARD2SEESND,
+ SD_LOWGUARD2ASEESND,
+ SD_LOWGUARD2SEE3SND,
+ SD_LOWGUARDFIRESND,
+ SD_LOWGUARDOUCHSND,
+ SD_LOWGUARD1DIESND,
+ SD_LOWGUARD2DIESND,
+ SD_SNEAKYSPRINGMSND,
+ SD_SNEAKYSPRINGFSND,
+
+ SD_HIGHGUARD1SEESND,
+ SD_HIGHGUARD2SEESND,
+ SD_HIGHGUARDFIRESND,
+ SD_HIGHGUARDOUCHSND,
+ SD_HIGHGUARDDIESND,
+
+ SD_OVERP1SEESND,
+ SD_OVERP2SEESND,
+ SD_OVERPFIRESND,
+ SD_OVERPNETSND,
+ SD_OVERPOUCHSND,
+ SD_OVERPDIESND,
+
+ SD_STRIKE1SEESND,
+ SD_STRIKE2SEESND,
+ SD_STRIKEFIRESND,
+ SD_STRIKEROLLSND,
+ SD_STRIKEOUCHSND,
+ SD_STRIKEDIESND,
+
+ SD_BLITZ1SEESND,
+ SD_BLITZ2SEESND,
+ SD_BLITZFIRESND,
+ SD_BLITZSTEALSND,
+ SD_BLITZOUCHSND,
+ SD_BLITZDIESND,
+ SD_BLITZPLEADSND,
+ SD_BLITZPLEAD1SND,
+ SD_BLITZPLEAD2SND,
+
+ SD_ENFORCERSEESND,
+ SD_ENFORCERFIRESND,
+ SD_ENFORCERTHROWSND,
+ SD_ENFORCEROUCHSND,
+ SD_ENFORCERDIESND,
+
+ SD_MONKSEESND,
+ SD_MONKGRABSND,
+ SD_MONKOUCHSND,
+ SD_MONKDIESND,
+
+ SD_FIREMONKSEESND,
+ SD_FIREMONKFIRESND,
+ SD_FIREMONKOUCHSND,
+ SD_FIREMONKDIESND,
+
+ SD_ROBOTSEESND,
+ SD_ROBOTFIRESND,
+ SD_ROBOTDIESND,
+ SD_ROBOTMOVESND,
+
+ SD_BALLISTIKRAFTSEESND,
+ SD_BALLISTIKRAFTFIRESND,
+
+ SD_DARIANSEESND,
+ SD_DARIANFIRESND,
+ SD_DARIANGONNAUSESND,
+ SD_DARIANUSESND,
+ SD_DARIANHIDESND,
+ SD_DARIANDIESND,
+ SD_DARIANSAY1,
+ SD_DARIANSAY2,
+ SD_DARIANSAY3,
+
+ SD_KRISTSEESND,
+ SD_KRISTFIRESND,
+ SD_KRISTMOTORSND,
+ SD_KRISTTURNSND,
+ SD_KRISTDROPSND,
+ SD_KRISTMINEBEEPSND,
+ SD_KRISTMINEHITSND,
+ SD_KRISTDIESND,
+ SD_KRISTSAY1,
+ SD_KRISTSAY2,
+ SD_KRISTSAY3,
+
+ SD_NMESEESND,
+ SD_NMEREADYSND,
+ SD_NMEFIRE1SND,
+ SD_NMEAPARTSND,
+ SD_NMEUFOSND,
+ SD_NMEDIESND,
+
+ SD_DARKMONKSEESND,
+ SD_DARKMONKFIRE1SND,
+ SD_DARKMONKFIRE2SND,
+ SD_DARKMONKFIRE3SND,
+ SD_DARKMONKFIRE4SND,
+ SD_DARKMONKRECHARGESND,
+ SD_DARKMONKFLOATSND,
+ SD_DARKMONKDIESND,
+ SD_DARKMONKSAY1,
+ SD_DARKMONKSAY2,
+ SD_DARKMONKSAY3,
+
+ SD_SNAKESEESND,
+ SD_SNAKEREADYSND,
+ SD_SNAKECHARGESND,
+ SD_SNAKEOUCHSND,
+ SD_SNAKEDIESND,
+ SD_SNAKESPITSND,
+ SD_SNAKESAY1,
+ SD_SNAKESAY2,
+ SD_SNAKESAY3,
+
+ SD_EMPLACEMENTSEESND,
+ SD_EMPLACEMENTFIRESND,
+ SD_BIGEMPLACEFIRESND,
+
+
+// ENVIRONMENT SOUNDS
+
+ SD_OPENDOORSND,
+ SD_CLOSEDOORSND,
+ SD_DOORHITSND,
+ SD_FIRECHUTESND,
+ SD_FIREBALLSND,
+ SD_FIREBALLHITSND,
+ SD_BLADESPINSND,
+ SD_PUSHWALLSND,
+ SD_PUSHWALLHITSND,
+ SD_GOWALLSND,
+ SD_TURBOWALLSND,
+ SD_BOULDERHITSND,
+ SD_BOULDERROLLSND,
+ SD_BOULDERFALLSND,
+ SD_PITTRAPSND,
+ SD_FIREJETSND,
+ SD_ACTORSQUISHSND,
+ SD_ACTORBURNEDSND,
+ SD_ACTORSKELETONSND,
+
+ SD_SPEARSTABSND,
+ SD_CYLINDERMOVESND,
+ SD_ELEVATORONSND,
+ SD_ELEVATORENDSND,
+
+ SD_SPRINGBOARDSND,
+ SD_LIGHTNINGSND,
+ SD_WINDSND,
+ SD_WATERSND,
+ SD_BODYLANDSND,
+ SD_GIBSPLASHSND,
+ SD_ACTORLANDSND,
+
+// SECRET SOUNDS
+
+ SD_DOPEFISHSND,
+ SD_YOUSUCKSND,
+
+ SD_SILLYMOVESND,
+ SD_SOUNDSELECTSND,
+ SD_SOUNDESCSND,
+
+// REMOTE SOUNDS (shift number row)
+
+ SD_REMOTEM1SND,
+ SD_REMOTEM2SND,
+ SD_REMOTEM3SND,
+ SD_REMOTEM4SND,
+ SD_REMOTEM5SND,
+ SD_REMOTEM6SND,
+ SD_REMOTEM7SND,
+ SD_REMOTEM8SND,
+ SD_REMOTEM9SND,
+ SD_REMOTEM10SND,
+
+ SD_LASTSOUND,
+
+ MAXSOUNDS
+
+} game_sounds;
+
+
+typedef enum
+{
+// REMOTE SOUNDS (shift number row)
+
+ D_REMOTEM1SND,
+ D_REMOTEM2SND,
+ D_REMOTEM3SND,
+ D_REMOTEM4SND,
+ D_REMOTEM5SND,
+ D_REMOTEM6SND,
+ D_REMOTEM7SND,
+ D_REMOTEM8SND,
+ D_REMOTEM9SND,
+ D_REMOTEM10SND,
+} remotesounds;
+
+typedef enum {
+ MUSE_MENUFLIPSND, // 0
+ MUSE_ESCPRESSEDSND, // 1
+ MUSE_MOVECURSORSND, // 2
+ MUSE_SELECTSND, // 3
+ MUSE_WARNINGBOXSND, // 4
+ MUSE_INFOBOXSND, // 5
+ MUSE_QUESTIONBOXSND, // 6
+ MUSE_NOPESND, // 7
+ MUSE_LEVELSTARTSND, // 8
+ MUSE_LEVELENDSND, // 9
+ MUSE_GAMEOVERSND, // 10
+ MUSE_ENDBONUS1SND, // 11
+ MUSE_ENDBONUS2SND, // 12
+ MUSE_NOBONUSSND, // 13
+ MUSE_PERCENT100SND, // 14
+ MUSE_HITWALLSND, // 15
+ MUSE_SELECTWPNSND, // 16
+ MUSE_NOWAYSND, // 17
+ MUSE_DONOTHINGSND, // 18
+ MUSE_NOITEMSND, // 19
+ MUSE_PLAYERDYINGSND, // 20
+ MUSE_PLAYERDEATHSND, // 21
+ MUSE_PLAYERHURTSND, // 22
+ MUSE_PLAYERYESSND, // 23
+ MUSE_WALK1SND, // 24
+ MUSE_WALK2SND, // 25
+ MUSE_PLAYERLANDSND, // 26
+ MUSE_NETFALLSND, // 27
+ MUSE_ATKKNIFESND, // 28
+ MUSE_ATKPISTOLSND, // 29
+ MUSE_ATKMP40SND, // 30
+ MUSE_RICOCHETSND, // 31
+ MUSE_MISSILEFIRESND, // 32
+ MUSE_FLAMEWALLSND, // 33
+ MUSE_MISSILEHITSND, // 34
+ MUSE_WEAPONBUILDSND, // 35
+ MUSE_STABBERSND, // 36
+ MUSE_ENERGYFIRESND, // 37
+ MUSE_GAINMODESND, // 38
+ MUSE_LOSEMODESND, // 39
+ MUSE_DOGLICKSND, // 40
+ MUSE_DOGBITESND, // 41
+ MUSE_GLASSBREAKSND, // 42
+ MUSE_EXPLOSIONSND, // 43
+ MUSE_TOUCHPLATESND, // 44
+ MUSE_BADTOUCHSND, // 45
+ MUSE_SWITCHSND, // 46
+ MUSE_GETKEYSND, // 47
+ MUSE_GETBONUSSND, // 48
+ MUSE_GETHEALTHSND, // 49
+ MUSE_GETWEAPONSND, // 50
+ MUSE_GETMWEAPONSND, // 51
+ MUSE_GETPOWERUPSND, // 52
+ MUSE_GETPOWERDOWNSND, // 53
+ MUSE_GETARMORSND, // 54
+ MUSE_GETWEIRDSND, // 55
+ MUSE_GETLIFESND, // 56
+ MUSE_ACTORSEESND, // 57
+ MUSE_ACTORFIRESND, // 58
+ MUSE_ACTOROUCHSND, // 59
+ MUSE_ACTORDIESND, // 60
+ MUSE_ACTORTHROWSND, // 61
+ MUSE_ACTORROLLSND, // 62
+ MUSE_ACTORDOITSND, // 63
+ MUSE_ACTORUSESND, // 64
+ MUSE_BOSSSEESND, // 65
+ MUSE_BOSSOUCHSND, // 66
+ MUSE_BOSSDIESND, // 67
+ MUSE_BOSSDOSND, // 68
+ MUSE_BOSSBEEPSND, // 69
+ MUSE_BOSSHEYSND, // 70
+ MUSE_BOSSFIRESND, // 71
+ MUSE_BOSSWARNSND, // 72
+ MUSE_BOSSFIRE2SND, // 73
+ MUSE_EMPFIRESND, // 74
+ MUSE_OPENDOORSND, // 75
+ MUSE_CLOSEDOORSND, // 76
+ MUSE_SPINBLADESND, // 77
+ MUSE_PUSHWALLSND, // 78
+ MUSE_BOULDERSND, // 79
+ MUSE_PITTRAPSND, // 80
+ MUSE_FIREJETSND, // 81
+ MUSE_ACTORSQUISHSND, // 82
+ MUSE_CYLINDERHITSND, // 83
+ MUSE_ELEVATORSND, // 84
+ MUSE_SPRINGBOARDSND, // 85
+ MUSE_LASTSOUND=-1
+} musesounds;
+
+#define NUMCARDS 6
+
+typedef enum {
+ fx_digital,
+ fx_muse
+} fxtypes;
+
+typedef enum {
+ ASS_UltraSound,
+ ASS_SoundBlaster,
+ ASS_SoundMan16,
+ ASS_PAS,
+ ASS_AWE32,
+ ASS_SoundScape,
+ ASS_WaveBlaster,
+ ASS_Adlib,
+ ASS_GeneralMidi,
+ ASS_SoundCanvas,
+ ASS_SoundSource,
+ ASS_TandySoundSource,
+ ASS_PCSpeaker,
+ ASS_Off
+} ASSTypes;
+
+
+extern int SD_Started;
+
+int SD_SetupFXCard ( int * numvoices, int * numbits, int * numchannels);
+int SD_Startup ( boolean bombonerror );
+int SD_Play ( int sndnum );
+void SD_Shutdown (void);
+
+int SD_PlayPositionedSound ( int sndnum, int px, int py, int x, int y );
+int SD_PlaySoundRTP ( int sndnum, int x, int y );
+void SD_PanPositionedSound ( int handle, int px, int py, int x, int y );
+void SD_PanRTP ( int handle, int x, int y );
+void SD_SetPan ( int handle, int vol, int left, int right );
+int SD_Play3D ( int sndnum, int angle, int distance );
+int SD_PlayPitchedSound ( int sndnum, int volume, int pitch );
+void SD_SetSoundPitch ( int sndnum, int pitch );
+boolean SD_SoundOkay ( int sndnum );
+
+//***************************************************************************
+//
+// SD_WaitSound - wait until a sound has finished
+//
+//***************************************************************************
+void SD_WaitSound ( int handle );
+
+//***************************************************************************
+//
+// SD_StopSound
+//
+//***************************************************************************
+void SD_StopSound ( int handle );
+
+//***************************************************************************
+//
+// SD_SoundActive
+//
+//***************************************************************************
+int SD_SoundActive ( int handle );
+
+//***************************************************************************
+//
+// SD_StopAllSounds
+//
+//***************************************************************************
+void SD_StopAllSounds ( void );
+
+
+typedef enum {
+ song_gason,
+ song_bosssee,
+ song_bossdie,
+ song_endlevel,
+ song_dogend,
+ song_title,
+ song_apogee,
+ song_youwin,
+ song_level,
+ song_elevator,
+ song_secretmenu,
+ song_cinematic1,
+ song_cinematic2,
+ song_cinematic3,
+ song_gameover,
+ song_christmas,
+ song_snakechase,
+ song_menu
+} songtypes;
+
+
+
+void MU_Shutdown ( void );
+int MU_Startup ( boolean bombonerror );
+void MU_PlaySong ( int num );
+void MU_StopSong ( void );
+
+//***************************************************************************
+//
+// MU_Continue
+//
+//***************************************************************************
+#define MU_Continue() MUSIC_Continue()
+
+//***************************************************************************
+//
+// MU_Pause
+//
+//***************************************************************************
+#define MU_Pause() MUSIC_Pause()
+
+//***************************************************************************
+//
+// MU_GetVolume
+//
+//***************************************************************************
+#define MU_GetVolume() MUSIC_GetVolume()
+
+//***************************************************************************
+//
+// MU_SetVolume
+//
+//***************************************************************************
+#define MU_SetVolume(x) MUSIC_SetVolume(x)
+
+//***************************************************************************
+//
+// MU_SongPlaying
+//
+//***************************************************************************
+#define MU_SongPlaying() MUSIC_SongPlaying()
+
+//***************************************************************************
+//
+// MU_FadeVolume
+//
+//***************************************************************************
+#define MU_FadeVolume(v,m) MUSIC_FadeVolume(v,m)
+
+//***************************************************************************
+//
+// MU_FadeActive
+//
+//***************************************************************************
+#define MU_FadeActive() MUSIC_FadeActive()
+
+//***************************************************************************
+//
+// MU_StopFade
+//
+//***************************************************************************
+#define MU_StopFade() MUSIC_StopFade()
+
+
+//***************************************************************************
+//
+// MU_FadeIn
+//
+//***************************************************************************
+void MU_FadeIn ( int num, int time );
+
+//***************************************************************************
+//
+// MU_FadeOut
+//
+//***************************************************************************
+void MU_FadeOut ( int time );
+
+//***************************************************************************
+//
+// MU_FadeToSong
+//
+//***************************************************************************
+void MU_FadeToSong ( int num, int time );
+
+//***************************************************************************
+//
+// SD_PreCacheSoundGroup
+//
+//***************************************************************************
+void SD_PreCacheSoundGroup ( int lo, int hi );
+
+//***************************************************************************
+//
+// SD_PreCacheSound
+//
+//***************************************************************************
+
+void SD_PreCacheSound ( int num );
+
+void MU_StartSong ( int songtype );
+
+void MU_JukeBoxMenu( void );
+
+void MU_StoreSongPosition ( void );
+
+void MU_RestoreSongPosition ( void );
+
+int MU_GetSongPosition ( void );
+
+void MU_SetSongPosition ( int position );
+
+int MU_GetSongNumber ( void );
+
+int MU_GetNumForType ( int songtype );
+
+int MU_GetStoredPosition ( void );
+
+void MU_SetStoredPosition ( int position );
+
+void MU_LoadMusic (byte * buf, int size);
+
+void MU_SaveMusic (byte ** buf, int * size);
+
+boolean MusicStarted( void );
+#endif
--- /dev/null
+++ b/rott/rt_spbal.c
@@ -1,0 +1,507 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "rt_def.h"
+#include "watcom.h"
+#include "splib.h"
+#include "rt_draw.h"
+#include "rt_playr.h"
+#include "isr.h"
+#include <stdlib.h>
+#include "rt_spbal.h"
+#include "_rt_spba.h"
+#include "sbconfig.h"
+#include "rt_main.h"
+#include "rt_map.h"
+
+#include "rt_debug.h"
+#include "rt_game.h"
+#include "rt_str.h"
+#include "rt_vid.h"
+#include "rt_playr.h"
+#include "rt_actor.h"
+#include "rt_main.h"
+#include "rt_util.h"
+#include "rt_draw.h"
+#include "rt_in.h"
+#include "z_zone.h"
+#include "rt_ted.h"
+#include "rt_view.h"
+#include "develop.h"
+#include "version.h"
+#include "scriplib.h"
+#include <stdlib.h>
+
+#ifdef DOS
+#include <conio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <dos.h>
+#include <mem.h>
+#endif
+//MED
+#include "memcheck.h"
+
+#ifdef DOS
+/* This file and associated .h files and Spaceball libraries:
+ Copyright 1995 Spacetec IMC Corporation
+*/
+//static char c[]="Copyright 1995 Spacetec IMC Corporation";
+
+
+#define MSGN(x) (((x)>0)?1:-1)
+#define MABS(x) ((x<0)?(-x):(x))
+
+#define FF(n) FLOAT_TO_FIXED(n)
+
+#define MAX_WARPS 1 // maximum number of ranges in all warps in defaultWarps
+static WarpRange defaultWarps[][MAX_WARPS]= {
+ {{ 0, 511, FF(0.00013)}}, // Tx
+ {{ 0, 511, FF(0.0075 )}}, // Ty
+ {{ 0, 511, FF(0.0005 )}}, // Tz
+ {{150, 511, FF(0.0075 )}}, // Rx
+ {{ 0, 511, FF(0.15 )}} // Ry
+};
+
+#undef FF
+
+
+static WarpRecord defaultRecords[]= {
+ {"Tx", defaultWarps[0], 1},
+ {"Ty", defaultWarps[1], 1},
+ {"Tz", defaultWarps[2], 1},
+ {"Rx", defaultWarps[3], 1},
+ {"Ry", defaultWarps[4], 1},
+};
+
+WarpRecord *WarpTx, *WarpTy, *WarpTz, *WarpRx, *WarpRy;
+
+static char *SpaceBallConfigName = "spwrott.cfg";
+static char *ApogeePath = "APOGEECD";
+
+#define TURBO_LIMIT 1000000
+static int turbo_increment = 500000,
+ turbo_count = 0,
+ turboFire = false;
+
+
+// sbbuttons mask: 00FE DCBA
+
+#define BUTTON_A 0x01
+#define BUTTON_B 0x02
+#define BUTTON_C 0x04
+#define BUTTON_D 0x08
+#define BUTTON_E 0x10
+#define BUTTON_F 0x20
+
+// All possible button assignment masks (with defaults)
+static
+short turboFireMask = BUTTON_A,
+ attackMask = BUTTON_B,
+ useMask = BUTTON_C,
+ mapMask = 0,
+ swapWeaponMask = BUTTON_D,
+ singleAxisMask = 0,
+ planarMask = 0,
+ aimMask = BUTTON_E,
+ pauseMask = BUTTON_F;
+
+// Array exists just to make sure two tasks are not assigned to same button
+static short *masks[6]= {&turboFireMask, &attackMask, &useMask,
+ &swapWeaponMask, &aimMask, &pauseMask
+ };
+
+
+
+//******************************************************************************
+//
+// ShiftTowardZero ()
+//
+//******************************************************************************
+
+static short
+ShiftTowardZero(short n, short amount)
+{
+ if (MABS(n) >= amount)
+ return n-((n>0)?amount:-amount);
+ else
+ return 0;
+}
+
+
+//******************************************************************************
+//
+// SPW_SingleAxisFilter
+//
+// Zeroes all but the largest (in absolute value) element in a RawPacket
+//
+// returns: nothing
+//
+//******************************************************************************
+
+static void
+SPW_SingleAxisFilter(SpwRawData *p)
+{
+ short *array = &(p->tx), // hope the data are in contigous locations
+ *largest = array,
+ newabs, large, array_length = 6;
+
+ large = MABS( *array );
+ while (--array_length > 0) {
+ ++array;
+ newabs = MABS(*array);
+ if (newabs > large) {
+ *largest = 0;
+ large = newabs;
+ largest = array;
+ } else
+ *array = 0;
+ }
+
+} /* end of SPW_SingleAxisFilter */
+
+
+
+//******************************************************************************
+//
+// HandleSpaceBallMotion ()
+//
+//******************************************************************************
+
+static void HandleSpaceBallMotion (SpwRawData * npacket, int controlbuf[])
+{
+
+ int strafeAngle;
+ short tx, ty, tz, rx, ry;
+ long sbtx, sbty, sbtz, sbrx, sbry;
+ static short ButtonState;
+
+ // If they are really cranking on it, limit them to one axis at a time
+ if ((MABS(npacket->tx) > 450) ||
+ (MABS(npacket->ty) > 450) ||
+ (MABS(npacket->tz) > 450) ||
+ (MABS(npacket->rx) > 450) ||
+ (MABS(npacket->ry) > 450)) SPW_SingleAxisFilter(npacket);
+
+ // Don't want to lose the low end that the sb null_region calc is losing
+ tx=ShiftTowardZero(npacket->tx,30); // range now approximately +/- 0-480
+ ty=ShiftTowardZero(npacket->ty,30); // range now approximately +/- 0-480
+ tz=ShiftTowardZero(npacket->tz,50); // range now approximately +/- 0-460
+ rx=ShiftTowardZero(npacket->rx,60); // range now approximately +/- 0-450
+ ry=ShiftTowardZero(npacket->ry,60); // range now approximately +/- 0-450
+
+ sbtx = SbFxConfigWarp( WarpTx, tx );
+ sbty = SbFxConfigWarp( WarpTy, ty );
+ sbtz = SbFxConfigWarp( WarpTz, tz );
+ sbrx = SbFxConfigWarp( WarpRx, rx );
+ sbry = SbFxConfigWarp( WarpRy, ry );
+
+ strafeAngle = (player->angle - FINEANGLES/4)&(FINEANGLES-1);
+
+ // check for turboFire
+ if (turboFire)
+ {
+ if (MABS(turbo_count) > TURBO_LIMIT)
+ turbo_increment *= -1;
+ turbo_count += turbo_increment;
+ sbry += turbo_increment;
+ }
+
+ controlbuf[0] += -(FixedMul (sbtz, viewcos))+
+ FixedMul (sbtx, costable[strafeAngle]);
+
+ controlbuf[1] += FixedMul (sbtz, viewsin) -
+ FixedMul (sbtx, sintable[strafeAngle]);
+
+ controlbuf[2] += sbry;
+
+
+
+ // Handle looking up and down ^ flying
+
+ ButtonState=npacket->buttons.cur;
+
+ // should the user be running?
+ buttonpoll[bt_run] = true; //((MABS(tx)+MABS(tz)+MABS(ry)) > 320) ? true : false ;
+
+
+ // TY does flying if the user has acquired the ability to fly.
+ // Currently this is ^'ed with looking up and down
+ if (player->flags & FL_FLEET)
+ {
+ if (sbty != 0)
+ {
+ if (sbty > 0)
+ buttonpoll[bt_lookup ] = true;
+ else
+ buttonpoll[bt_lookdown] = true;
+ }
+ }
+ else // Lookup/down || aim up/down ?
+ {
+ if ( sbrx != 0 )
+ {
+ if (sbrx > 0)
+ {
+ if (ButtonState & aimMask)
+ buttonpoll[bt_horizonup] = true;
+ else
+ buttonpoll[bt_lookup] = true;
+ }
+ else
+ {
+ if (ButtonState & aimMask)
+ buttonpoll[bt_horizondown] = true;
+ else
+ buttonpoll[bt_lookdown] = true;
+ }
+ }
+ }
+
+
+}
+
+//******************************************************************************
+//
+// PollSpaceBall ()
+//
+//******************************************************************************
+
+void PollSpaceBall (void)
+{
+ SpwRawData rawpacket;
+ short buttonsChanged;
+ static short buttonState=0;
+ static int reusePacketNTimes=0;
+ static SpwRawData lastPacket;
+
+ memset(&rawpacket,0,sizeof(rawpacket));
+ if (SpwSimpleGet(0,&rawpacket))
+ {
+ lastPacket=rawpacket;
+ reusePacketNTimes=6;
+ }
+ else if (reusePacketNTimes > 0)
+ {
+ rawpacket=lastPacket;
+ --reusePacketNTimes;
+ }
+ else if (buttonState) // did not get a packet but a button is down
+ rawpacket.buttons.cur=lastPacket.buttons.cur;
+ else
+ return;
+
+
+ buttonsChanged=buttonState ^ rawpacket.buttons.cur;
+ buttonState=rawpacket.buttons.cur;
+
+ buttonpoll[bt_attack] = (turboFire = (buttonState & turboFireMask) ? true : false );
+
+ if (buttonState & mapMask) DoMap(player->tilex,player->tiley);
+ if (buttonState & useMask) buttonpoll[bt_use] = true;
+ if (buttonState & attackMask) buttonpoll[bt_attack] = true;
+ if (buttonState & swapWeaponMask) buttonpoll[bt_swapweapon] = true;
+ if (buttonState & singleAxisMask) SPW_SingleAxisFilter(&rawpacket);
+ if (buttonState & planarMask) rawpacket.ty=rawpacket.rz=rawpacket.rx=0;
+ if (buttonState & pauseMask) PausePressed=true;
+ if (!PausePressed) HandleSpaceBallMotion(&rawpacket,controlbuf);
+}
+
+
+//******************************************************************************
+//
+// OpenSpaceBall ()
+//
+//******************************************************************************
+
+void OpenSpaceBall (void)
+{
+ int btn;
+ char filename[ 128 ];
+
+ if (SpwSimpleOpen(0))
+ {
+ SpwRawData sp;
+
+ SpaceBallPresent = true;
+ printf("Test the Spaceball by moving the ball and/or pressing buttons.\n");
+ printf("Exit test by pressing any keyboard key...\n");
+ while(!kbhit())
+ {
+
+ if (SpwSimpleGet(0,&sp))
+ printf("\r# tx: %4d ty: %4d tz: %4d # rx: %4d ry: %4d rz: %4d # b: %1c-%1c-%1c-%1c-%1c-%1c",
+ sp.tx, sp.ty, sp.tz,
+ sp.rx, sp.ry, sp.rz,
+ sp.buttons.cur & 1 ? 'A':' ', sp.buttons.cur & 2 ? 'B':' ',
+ sp.buttons.cur & 4 ? 'C':' ', sp.buttons.cur & 8 ? 'D':' ',
+ sp.buttons.cur & 16 ? 'E':' ', sp.buttons.cur & 32 ? 'F':' ');
+ }
+
+ // Check for configuration file, set defaults if none
+
+ GetPathFromEnvironment( filename, ApogeePath, SpaceBallConfigName );
+
+ SbConfigParse(filename);
+
+ // Check for warp records
+ WarpTx = SbConfigGetWarpRange("Tx");
+ WarpTy = SbConfigGetWarpRange("Ty");
+ WarpTz = SbConfigGetWarpRange("Tz");
+ WarpRx = SbConfigGetWarpRange("Rx");
+ WarpRy = SbConfigGetWarpRange("Ry");
+
+ if(!WarpTx) WarpTx = &defaultRecords[0];
+ if(!WarpTy) WarpTy = &defaultRecords[1];
+ if(!WarpTz) WarpTz = &defaultRecords[2];
+ if(!WarpRx) WarpRx = &defaultRecords[3];
+ if(!WarpRy) WarpRy = &defaultRecords[4];
+
+ // Check for button assignments
+ if((btn=SbConfigGetButtonNumber("TURBO_FIRE"))!=-1)
+ {
+ if (masks[btn])
+ *(masks[btn]) = 0; // zero out mask previously assigned to button
+ masks[btn]= &turboFireMask;
+ turboFireMask=(short)(1<<btn);
+ }
+
+ if((btn=SbConfigGetButtonNumber("ATTACK"))!=-1)
+ {
+ if (masks[btn])
+ *masks[btn] = 0; // zero out mask previously assigned to button
+ masks[btn]= &attackMask;
+ attackMask=(short)(1<<btn);
+ }
+
+ if((btn=SbConfigGetButtonNumber("USE"))!=-1)
+ {
+ if (masks[btn])
+ *masks[btn] = 0; // zero out mask previously assigned to button
+ masks[btn]= &useMask;
+ useMask=(short)(1<<btn);
+ }
+
+ if((btn=SbConfigGetButtonNumber("MAP"))!=-1)
+ {
+ if (masks[btn])
+ *masks[btn] = 0; // zero out mask previously assigned to button
+ masks[btn]= &mapMask;
+ mapMask=(short)(1<<btn);
+ }
+
+ if((btn=SbConfigGetButtonNumber("SWAP_WEAPON"))!=-1)
+ {
+ if (masks[btn])
+ *masks[btn] = 0; // zero out mask previously assigned to button
+ masks[btn]= &swapWeaponMask;
+ swapWeaponMask=(short)(1<<btn);
+ }
+
+ if((btn=SbConfigGetButtonNumber("SINGLE_AXIS_FILTER"))!=-1)
+ {
+ if (masks[btn])
+ *masks[btn] = 0; // zero out mask previously assigned to button
+ masks[btn]= &singleAxisMask;
+ singleAxisMask=(short)(1<<btn);
+ }
+
+ if((btn=SbConfigGetButtonNumber("PLANAR_FILTER"))!=-1)
+ {
+ if (masks[btn])
+ *masks[btn] = 0; // zero out mask previously assigned to button
+ masks[btn]= &planarMask;
+ planarMask=(short)(1<<btn);
+ }
+
+ if((btn=SbConfigGetButtonNumber("AIM"))!=-1)
+ {
+ if (masks[btn])
+ *masks[btn] = 0; // zero out mask previously assigned to button
+ masks[btn]= &aimMask;
+ aimMask=(short)(1<<btn);
+ }
+
+ if((btn=SbConfigGetButtonNumber("PAUSE"))!=-1)
+ {
+ if (masks[btn])
+ *masks[btn] = 0; // zero out mask previously assigned to button
+ masks[btn]= &pauseMask;
+ pauseMask=(short)(1<<btn);
+ }
+ }
+ else
+ {
+ SpaceBallPresent = false;
+ }
+}
+
+//******************************************************************************
+//
+// CloseSpaceBall ()
+//
+//******************************************************************************
+
+void CloseSpaceBall (void)
+{
+ if (SpaceBallPresent)
+ {
+ SpwSimpleClose(0);
+ }
+}
+
+//******************************************************************************
+//
+// GetSpaceBallButtons ()
+//
+//******************************************************************************
+
+unsigned GetSpaceBallButtons (void)
+{
+ SpwRawData sp;
+
+ return ((SpwSimpleGet(0,&sp) & SPW_BUTTON_DOWN));
+}
+
+#else
+
+/* This isn't of much use in Linux. */
+
+void PollSpaceBall (void)
+{
+ STUB_FUNCTION;
+}
+
+void OpenSpaceBall (void)
+{
+ STUB_FUNCTION;
+}
+
+void CloseSpaceBall (void)
+{
+}
+
+unsigned GetSpaceBallButtons (void)
+{
+ STUB_FUNCTION;
+
+ return 0;
+}
+
+#endif
--- /dev/null
+++ b/rott/rt_spbal.h
@@ -1,0 +1,34 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// RT_spbal.h - SpaceBall stuff
+//
+//***************************************************************************
+
+#ifndef _rt_spbal_public
+#define _rt_spbal_public
+
+
+unsigned GetSpaceBallButtons (void);
+void OpenSpaceBall (void);
+void CloseSpaceBall (void);
+void PollSpaceBall (void);
+#endif
--- /dev/null
+++ b/rott/rt_sqrt.c
@@ -1,0 +1,82 @@
+#include "rt_def.h"
+
+#include "rt_sqrt.h"
+
+/*
+ C version of fixed-point Square Root functions
+ */
+
+long FixedSqrtLP(long n) // Low Precision (8.8)
+{
+ /*
+ Not used, so unimplemented.
+ If it matters, just copy the first half of the HP version,
+ and multiply the answer by 256.
+ */
+ STUB_FUNCTION;
+
+ return 0;
+}
+
+long FixedSqrtHP(long n) // High Precision (8.16)
+{
+ /* This is more or less a direct C transliteration of the asm code.
+ I've replaced right shifting with division, since right shifting
+ signed values is undefined in ANSI C (though it usually works).
+ ROTT does not use this routine heavily. */
+ unsigned long root, mask, val;
+ signed long d;
+
+ root = 0;
+ mask = 0x40000000;
+ val = (unsigned long)n;
+hp1:
+ d = val;
+ d -= mask;
+ if (d < 0)
+ goto hp2;
+ d -= root;
+ if (d < 0)
+ goto hp2;
+
+ val = d;
+ root /= 2;
+ root |= mask;
+ mask /= 4;
+ if (mask != 0)
+ goto hp1;
+ else
+ goto hp5;
+hp2:
+ root /= 2;
+ mask /= 4;
+ if (mask != 0)
+ goto hp1;
+
+hp5:
+ mask = 0x00004000;
+ root <<= 16;
+ val <<= 16;
+hp3:
+ /* use add here to properly emulate the asm - SBF */
+ if ((root+mask) > val)
+ goto hp4;
+
+ val -= (root+mask);
+
+ root /= 2;
+ root |= mask;
+ mask /= 4;
+ if (mask != 0)
+ goto hp3;
+ else
+ goto hp6;
+hp4:
+ root /= 2;
+ mask /= 4;
+ if (mask != 0)
+ goto hp3;
+hp6:
+
+ return (long)root;
+}
--- /dev/null
+++ b/rott/rt_sqrt.h
@@ -1,0 +1,109 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_sqrt_public
+#define _rt_sqrt_public
+
+/*
+FUNCTION:
+ Fixed32 FixedSqrtHP(Fixed32 n);
+DESCRIPTION:
+ This does a high-precision square root of a Fixed32. It has
+ 8.16 bit accuracy. For more speed use FixedSqrtLP().
+
+
+FUNCTION:
+ Fixed32 FixedSqrtLP(Fixed32 n);
+DESCRIPTION:
+ This does a low-precision square root of a Fixed32. It has
+ 8.8 bit accuracy. For more accuracy use FixedSqrtHP().
+*/
+
+
+
+long FixedSqrtLP(long n); // Low Precision (8.8)
+long FixedSqrtHP(long n); // High Precision (8.16)
+
+#ifdef __WATCOMC__
+#pragma aux FixedSqrtLP = \
+ " xor eax, eax" \
+ " mov ebx, 40000000h" \
+ "sqrtLP1: mov edx, ecx" \
+ " sub edx, ebx" \
+ " jl sqrtLP2" \
+ " sub edx, eax" \
+ " jl sqrtLP2" \
+ " mov ecx,edx" \
+ " shr eax, 1" \
+ " or eax, ebx" \
+ " shr ebx, 2" \
+ " jnz sqrtLP1" \
+ " shl eax, 8" \
+ " jmp sqrtLP3" \
+ "sqrtLP2: shr eax, 1" \
+ " shr ebx, 2" \
+ " jnz sqrtLP1" \
+ " shl eax, 8" \
+ "sqrtLP3: nop" \
+ parm caller [ecx] \
+ value [eax] \
+ modify [eax ebx ecx edx];
+
+
+#pragma aux FixedSqrtHP = \
+ " xor eax, eax" \
+ " mov ebx, 40000000h" \
+ "sqrtHP1: mov edx, ecx" \
+ " sub edx, ebx" \
+ " jb sqrtHP2" \
+ " sub edx, eax" \
+ " jb sqrtHP2" \
+ " mov ecx,edx" \
+ " shr eax, 1" \
+ " or eax, ebx" \
+ " shr ebx, 2" \
+ " jnz sqrtHP1" \
+ " jz sqrtHP5" \
+ "sqrtHP2: shr eax, 1" \
+ " shr ebx, 2" \
+ " jnz sqrtHP1" \
+ "sqrtHP5: mov ebx, 00004000h" \
+ " shl eax, 16" \
+ " shl ecx, 16" \
+ "sqrtHP3: mov edx, ecx" \
+ " sub edx, ebx" \
+ " jb sqrtHP4" \
+ " sub edx, eax" \
+ " jb sqrtHP4" \
+ " mov ecx, edx" \
+ " shr eax, 1" \
+ " or eax, ebx" \
+ " shr ebx, 2" \
+ " jnz sqrtHP3" \
+ " jmp sqrtHP6" \
+ "sqrtHP4: shr eax, 1" \
+ " shr ebx, 2" \
+ " jnz sqrtHP3" \
+ "sqrtHP6: nop" \
+ parm caller [ecx] \
+ value [eax] \
+ modify [eax ebx ecx edx];
+#endif
+
+#endif
--- /dev/null
+++ b/rott/rt_stat.c
@@ -1,0 +1,1940 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "rt_def.h"
+
+#ifdef DOS
+#include <malloc.h>
+#include <dos.h>
+#endif
+
+#include <string.h>
+#include "sprites.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "rt_stat.h"
+#include "z_zone.h"
+#include "lumpy.h"
+#include "rt_util.h"
+#include "rt_draw.h"
+#include "rt_ted.h"
+#include "rt_door.h"
+#include "rt_main.h"
+#include "w_wad.h"
+#include "rt_main.h"
+#include "rt_rand.h"
+#include "rt_menu.h"
+#include "rt_sound.h"
+#include "_rt_stat.h"
+#include "rt_net.h"
+#include "rt_view.h"
+#include "isr.h"
+//MED
+#include "memcheck.h"
+
+
+
+/*
+=============================================================================
+
+Global Variables GLOBAL VARIABLES
+
+=============================================================================
+*/
+
+statobj_t *firstactivestat,*lastactivestat;
+statobj_t *firstemptystat,*lastemptystat;
+
+wall_t switches[MAXSWITCHES],*lastswitch;
+respawn_t *firstrespawn,*lastrespawn;
+statobj_t *FIRSTSTAT,*LASTSTAT,*sprites[MAPSIZE][MAPSIZE];
+animwall_t animwalls[MAXANIMWALLS];
+
+dirtype opposite[9] =
+{west,southwest,south,southeast,east,northeast,north,northwest,nodir};
+
+
+
+
+
+
+statinfo stats[NUMSTATS] =
+{
+ {0,SPR0_YLIGHT, stat_ylight,FL_LIGHT|FL_SHOOTABLE,0,0,2,0,0},
+ {0,SPR1_RLIGHT, stat_rlight,FL_LIGHT|FL_SHOOTABLE,0,0,2,0,0},
+ {0,SPR2_GLIGHT, stat_glight,FL_LIGHT|FL_SHOOTABLE,0,0,2,0,0},
+ {0,SPR3_BLIGHT, stat_blight,FL_LIGHT|FL_SHOOTABLE,0,0,2,0,0},
+ {0,SPR4_CHAND, stat_chandelier,FL_LIGHT|FL_SHOOTABLE,0,0,2,0,0},
+ {0,SPR5_LAMPOFF, stat_lamp,FL_LIGHT|FL_BLOCK|FL_SHOOTABLE,0,0,2,0,0},
+ {0,SPR73_GKEY1, stat_pedgoldkey,FL_COLORED|FL_BONUS|FL_CHANGES|FL_BLOCK|FL_ACTIVE,2,16,pc_orange,0,0},
+ {0,SPR73_GKEY1,stat_pedsilverkey,FL_COLORED|FL_BONUS|FL_CHANGES|FL_BLOCK|FL_ACTIVE,2,16,pc_gray,0,0},
+ {0,SPR73_GKEY1, stat_pedironkey,FL_COLORED|FL_BONUS|FL_CHANGES|FL_BLOCK|FL_ACTIVE,2,16,pc_olive,0,0},
+ {0,SPR73_GKEY1,stat_pedcrystalkey,FL_COLORED|FL_BONUS|FL_CHANGES|FL_BLOCK|FL_ACTIVE,2,16,pc_red,0,0},
+ {0,SPR6_GIBS1, stat_gibs1,0,0,0,0,0,0},
+ {0,SPR7_GIBS2, stat_gibs2,0,0,0,0,0,0},
+ {0,SPR8_GIBS3, stat_gibs3,0,0,0,0,0,0},
+ {0,SPR9_MONKMEAL, stat_monkmeal,FL_BONUS|FL_RESPAWN,0,0,0,0,0},
+ {0,PORRIDGE1, stat_priestporridge,FL_BONUS|FL_RESPAWN,2,6,0,0,0},
+ {0,MONKCRYSTAL11,stat_monkcrystal1,FL_BONUS|FL_ACTIVE|FL_RESPAWN,2,6,0,0,0},
+ {0,MONKCRYSTAL21,stat_monkcrystal2,FL_BONUS|FL_ACTIVE|FL_RESPAWN,2,7,0,0,0},
+ {0,ONEUP01,stat_oneup,FL_BONUS|FL_ACTIVE|FL_FULLLIGHT,2,8,0,0,0},
+ {0,THREEUP01,stat_threeup,FL_BONUS|FL_ACTIVE|FL_FULLLIGHT,2,8,0,0,0},
+ {0,TORCH1,stat_altbrazier1,FL_HEAT|FL_BLOCK|FL_ACTIVE|FL_LIGHT|FL_SHOOTABLE,2,15,2,0,0},
+ {0,SPR_ABRAZIER2,stat_altbrazier2,FL_HEAT|FL_BLOCK|FL_LIGHT|FL_SHOOTABLE,0,0,2,0,0},
+ {0,FBASIN1,stat_healingbasin,FL_BONUS|FL_CHANGES|FL_ACTIVE|FL_BLOCK,2,3,0,0,0},
+ {20,EBASIN,stat_emptybasin,FL_BLOCK|FL_SHOOTABLE,0,0,0,0,0},
+ {0,BAT1,stat_bat,FL_BONUS|FL_ACTIVE|FL_RESPAWN|FL_WEAPON,1,16,0,0,10},
+ {0,KNIFE_STATUE1,stat_knifestatue,FL_BONUS|FL_CHANGES|FL_BLOCK,0,0,0,0,0},
+ {0,SPR_TWOPIST,stat_twopistol,FL_BONUS|FL_RESPAWN|FL_WEAPON,0,0,0,0,5},
+ {0,SPR_MP40,stat_mp40,FL_BONUS|FL_RESPAWN|FL_WEAPON,0,0,0,0,5},
+ {0,SPR_BAZOOKA,stat_bazooka,FL_BONUS|FL_RESPAWN|FL_WEAPON,0,0,0,0,10},
+ {0,SPR_FIREBOMB,stat_firebomb,FL_BONUS|FL_RESPAWN|FL_WEAPON,0,0,0,0,5},
+ {0,SPR_HEATSEEK,stat_heatseeker,FL_BONUS|FL_RESPAWN|FL_WEAPON,0,0,0,0,7},
+ {0,SPR_DRUNK,stat_drunkmissile,FL_BONUS|FL_RESPAWN|FL_WEAPON,0,0,0,0,7},
+ {0,SPR_FIREWALL,stat_firewall,FL_BONUS|FL_RESPAWN|FL_WEAPON,0,0,0,0,5},
+ {0,SPR_SPLIT,stat_splitmissile,FL_BONUS|FL_RESPAWN|FL_WEAPON,0,0,0,0,7},
+ {0,SPR_KES,stat_kes,FL_BONUS|FL_RESPAWN|FL_WEAPON,0,0,0,0,7},
+ {0,LIFEITEMA01,stat_lifeitem1,FL_BONUS|FL_ACTIVE|FL_SHOOTABLE|FL_FULLLIGHT,2,8, 2,0,0},
+ {0,LIFEITEMB01,stat_lifeitem2,FL_BONUS|FL_ACTIVE|FL_SHOOTABLE|FL_FULLLIGHT,2,8, 2,0,0},
+ {0,LIFEITEMD01,stat_lifeitem3,FL_BONUS|FL_ACTIVE|FL_SHOOTABLE|FL_FULLLIGHT,2,8, 2,0,0},
+ {0,LIFEITEMC01,stat_lifeitem4,FL_BONUS|FL_ACTIVE|FL_SHOOTABLE|FL_FULLLIGHT,2,15, 2,0,0},
+ {24,SPR32_EXPLOS,stat_tntcrate,FL_SHOOTABLE|FL_BLOCK|FL_WOODEN,0,0,3,10,0},
+ {12,SPR33_CBARREL,stat_bonusbarrel,FL_METALLIC|FL_SHOOTABLE|FL_BLOCK,0,0,3,10,0},
+ {0,TORCH1,stat_torch,FL_BLOCK|FL_LIGHT|FL_ACTIVE|FL_HEAT|FL_SHOOTABLE,2,15,2,0,0},
+ {30,FFLAME1,stat_floorfire,FL_HEAT|FL_BLOCK|FL_LIGHT|FL_ACTIVE|FL_SHOOTABLE,2,7,30,0,0},
+ {0,DIP11,stat_dipball1,FL_BONUS|FL_FULLLIGHT,0,0,0,0,0},
+ {0,DIP21,stat_dipball2,FL_BONUS|FL_FULLLIGHT,0,0,0,0,0},
+ {0,DIP31,stat_dipball3,FL_BONUS|FL_FULLLIGHT,0,0,0,0,0},
+ {0,SPR34_TOUCH1,stat_touch1,0|FL_TRANSLUCENT|FL_FADING,0,0,0,0,0},
+ {0,SPR35_TOUCH2,stat_touch2,0|FL_TRANSLUCENT|FL_FADING,0,0,0,0,0},
+ {0,SPR36_TOUCH3,stat_touch3,0|FL_TRANSLUCENT|FL_FADING,0,0,0,0,0},
+ {0,SPR37_TOUCH4,stat_touch4,0|FL_TRANSLUCENT|FL_FADING,0,0,0,0,0},
+ {20,SPR62_ETOUCH1,stat_dariantouch,FL_METALLIC|FL_BANDF|FL_SHOOTABLE|FL_BLOCK,10,3,50,0,0},
+ {0,SCOTHEAD1, stat_scotthead,FL_BONUS|FL_ACTIVE|FL_FULLLIGHT,4,7,0,0,0},
+ {0,SPR38_GARBAGE1,stat_garb1,0,0,0,0,0,0},
+ {0,SPR39_GARBAGE2,stat_garb2,0,0,0,0,0,0},
+ {0,SPR40_GARBAGE3,stat_garb3,0,0,0,0,0,0},
+ {0,SPR41_SHIT,stat_shit,0,0,0,0,0,0},
+ {0,SPR42_GRATE,stat_grate,0,0,0,0,0,0},
+ {0,SPR43_MSHARDS,stat_metalshards,0,0,0,0,0,0},
+ {20,SPR44_PEDESTAL,stat_emptypedestal,FL_BLOCK|FL_SHOOTABLE|FL_WOODEN,0,0,60,0,0},
+ {20,SPR45_ETABLE,stat_emptytable,FL_BLOCK|FL_SHOOTABLE|FL_WOODEN,0,0,100,0,0},
+ {16,SPR46_STOOL,stat_stool,FL_BLOCK|FL_SHOOTABLE|FL_WOODEN,0,0,25,0,0},
+ {0,SPR_PUSHCOLUMN1,stat_bcolumn,FL_BLOCK|FL_HEIGHTFLIPPABLE,0,0,0,0,0},
+ {0,SPR_PUSHCOLUMN1,stat_gcolumn,FL_BLOCK|FL_HEIGHTFLIPPABLE,0,0,0,0,0},
+ {0,SPR_PUSHCOLUMN1,stat_icolumn,FL_BLOCK|FL_HEIGHTFLIPPABLE,0,0,0,0,0},
+ {20,SPR50_TREE,stat_tree,FL_SHOOTABLE|FL_BLOCK,0,0,0,0,0},
+ {20,SPR51_PLANT,stat_plant,FL_SHOOTABLE|FL_BLOCK,0,0,0,0,0},
+ {20,BLUEVASE,stat_urn,FL_SHOOTABLE|FL_BLOCK,0,0,0,0,0},
+ {0,SPR54_HAY,stat_haystack,FL_SHOOTABLE|FL_BLOCK,0,0,20,0,0},
+ {12,SPR55_IBARREL,stat_ironbarrel,FL_METALLIC|FL_BLOCK|FL_SHOOTABLE,0,0,50,0,0},
+ {0,HGRATE1,stat_heatgrate,FL_LIGHT|FL_ACTIVE,2,4,0,5,0},
+ {-10,STNPOLE1,stat_standardpole,FL_SHOOTABLE|FL_BLOCK,0,0,25,0,0},
+ {0,PREPIT,stat_pit,FL_CHANGES,0,0,0,0,0},
+ {0,GODPOWERUP1,stat_godmode,FL_WEAPON|FL_BONUS|FL_ACTIVE|FL_RESPAWN|FL_FULLLIGHT,2,8,0,0,0},
+ {0,DOGPOWERUP1,stat_dogmode,FL_WEAPON|FL_BONUS|FL_ACTIVE|FL_RESPAWN|FL_FULLLIGHT,2,8,0,0,0},
+ {0,FLEETFEETPOWERUP1,stat_fleetfeet,FL_BONUS|FL_ACTIVE|FL_RESPAWN|FL_FULLLIGHT,2,8,0,0,0},
+ {0,ELASTICPOWERUP1, stat_elastic, FL_BONUS|FL_ACTIVE|FL_RESPAWN|FL_FULLLIGHT,2,8,0,0,0},
+ {0,MUSHROOMPOWERUP1, stat_mushroom, FL_BONUS|FL_ACTIVE|FL_RESPAWN|FL_FULLLIGHT,2,8,0,0,0},
+ {0,GASMASKPOWERUP, stat_gasmask, FL_BONUS|FL_RESPAWN,0,0,0,0,0},
+ {0,BULLETPROOFPOWERUP, stat_bulletproof, FL_BONUS|FL_RESPAWN,0,0,0,0,0},
+ {0,ASBESTOSPOWERUP, stat_asbesto, FL_BONUS|FL_RESPAWN,0,0,0,0,0},
+ {0,RANDOMPOWERUP1, stat_random, FL_BONUS|FL_ACTIVE|FL_RESPAWN,2,8,0,0,0},
+ {0,RUBBLE1, stat_rubble, FL_ACTIVE,2,10,0,0,0},
+ {0,WOODFRAG1, stat_woodfrag, FL_ACTIVE,2,14,0,0,0},
+ {0,ROBOGRDDIE1, stat_metalfrag, FL_ACTIVE,2,10,0,0,0},
+ {0,EMPTY_STATUE1,stat_emptystatue,FL_BLOCK|FL_SHOOTABLE,0,0,50,0,0},
+ {16,TOMLARVA1,stat_tomlarva,FL_ACTIVE|FL_SHOOTABLE|FL_BLOCK,2,4,150,0,0},
+ {0,BULLETHOLE,stat_bullethole,FL_TRANSLUCENT,0,0,0,0,0},
+//MED
+#if (SHAREWARE == 1)
+ {0,COLLECTOR1,stat_collector,FL_ACTIVE|FL_BONUS,2,8,-1,0,0},
+#else
+ {0,DOPE1,stat_collector,FL_ACTIVE|FL_BONUS,2,8,-1,0,0},
+#endif
+ {0,SPR_MINE1,stat_mine,FL_BONUS|FL_SHOOTABLE|FL_RESPAWN,0,0,10,0,0},
+ {0,MISSMOKE1,stat_missmoke,FL_ACTIVE,6,4,0,0,0},
+ {0,PLATFORM1,stat_disk,FL_BLOCK|FL_HEIGHTFLIPPABLE,0,0,0,0,0},
+ {-1,0,0,0,0,0,0,0,0}
+};
+
+
+dirtype diagonal[9][9] =
+{
+ /* east */ {nodir,nodir,northeast,nodir,nodir,nodir,southeast,nodir,nodir},
+ {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
+ /* north */ {northeast,nodir,nodir,nodir,northwest,nodir,nodir,nodir,nodir},
+ {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
+ /* west */ {nodir,nodir,northwest,nodir,nodir,nodir,southwest,nodir,nodir},
+ {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
+ /* south */ {southeast,nodir,nodir,nodir,southwest,nodir,nodir,nodir,nodir},
+ {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir},
+ {nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir,nodir}
+};
+
+/*
+=============================================================================
+
+Local Variables GLOBAL VARIABLES
+
+=============================================================================
+*/
+static awallinfo_t animwallsinfo[MAXANIMWALLS] =
+{ {3,4,"FPLACE1\0"}, //lava wall
+ {3,6,"ANIMY1\0"}, //anim red
+ {3,6,"ANIMR1\0"}, //anim yellow
+ {40,4,"ANIMFAC1\0"}, //anim face
+ {3,4,"ANIMONE1\0"}, //anim one
+ {3,4,"ANIMTWO1\0"}, //anim two
+ {3,4,"ANIMTHR1\0"}, //anim three
+ {3,4,"ANIMFOR1\0"}, //anim four
+ {3,6,"ANIMGW1\0"}, //anim grey water
+ {3,6,"ANIMYOU1\0"}, //anim you do not belong
+ {3,6,"ANIMBW1\0"}, //anim brown water
+ {3,6,"ANIMBP1\0"}, //anim brown piston
+ {3,6,"ANIMCHN1\0"}, //anim chain
+ {3,6,"ANIMFW1\0"}, //anim firewall
+ {3,6,"ANIMLAT1\0"}, //anim little blips
+ {3,6,"ANIMST1\0"}, //anim light streams left
+ {3,6,"ANIMRP1\0"}
+};//anim light streams right
+
+int statcount;
+
+void AddRespawnStatic(respawn_t*stat);
+void DoLights (int tilex, int tiley);
+
+void AddToFreeStaticList(statobj_t*stat)
+{ if (!firstemptystat)
+ firstemptystat = stat;
+ else
+ { stat->statprev = lastemptystat;
+ lastemptystat->statnext = stat;
+ }
+ lastemptystat = stat;
+
+}
+
+
+void RemoveFromFreeStaticList(statobj_t*stat)
+{
+ if (stat == lastemptystat)
+ lastemptystat = stat->statprev;
+ else
+ stat->statnext->statprev = stat->statprev;
+
+ if (stat == firstemptystat)
+ firstemptystat = stat->statnext;
+ else
+ stat->statprev->statnext = stat->statnext;
+
+ stat->statprev = NULL;
+ stat->statnext = NULL;
+
+}
+
+
+
+
+/*
+===============
+=
+= MakeStatActive
+=
+===============
+*/
+
+void MakeStatActive(statobj_t*x)
+{ if (!firstactivestat)
+ firstactivestat = x;
+ else
+ { x->prevactive = lastactivestat;
+ lastactivestat->nextactive = x;
+ }
+ lastactivestat = x;
+}
+
+
+/*
+===============
+=
+= MakeStatInactive
+=
+===============
+*/
+
+void MakeStatInactive(statobj_t*stat)
+{
+ if (stat == lastactivestat)
+ lastactivestat = stat->prevactive;
+ else
+ stat->nextactive->prevactive = stat->prevactive;
+
+ if (stat == firstactivestat)
+ firstactivestat = stat->nextactive;
+ else
+ stat->prevactive->nextactive = stat->nextactive;
+
+ stat->prevactive = NULL;
+ stat->nextactive = NULL;
+
+}
+/*
+===============
+=
+= AddStatic
+=
+===============
+*/
+
+void AddStatic(statobj_t *stat)
+{ if (FIRSTSTAT)
+ { stat->statprev = LASTSTAT;
+ LASTSTAT->statnext = stat;
+ }
+ else
+ FIRSTSTAT = stat;
+ LASTSTAT = stat;
+}
+
+
+
+void RemoveStatic(statobj_t*stat)
+{
+ if (stat->flags & FL_ABP) //remove from active list
+ MakeStatInactive(stat);
+
+ if (stat == LASTSTAT) // remove from master list
+ LASTSTAT = stat->statprev;
+ else
+ stat->statnext->statprev = stat->statprev;
+
+ if (stat == FIRSTSTAT)
+ FIRSTSTAT = stat->statnext;
+ else
+ stat->statprev->statnext = stat->statnext;
+
+ stat->statprev = NULL;
+ stat->statnext = NULL;
+
+ if (stat->flags & FL_WEAPON)
+ MISCVARS->NUMWEAPONS --;
+
+ if ((stat->flags & FL_RESPAWN) &&
+ gamestate.BattleOptions.RespawnItems &&
+ (!((stat->flags & FL_WEAPON ) &&
+ (gamestate.BattleOptions.WeaponPersistence)
+ )
+ )
+ )
+ {
+ respawn_t*temp;
+ // if ( !( (stat->flags & FL_WEAPON) &&
+ // (MISCVARS->NUMWEAPONS >= (numplayers+10))
+ // )
+ // )
+ {
+ temp = (respawn_t*)Z_LevelMalloc(sizeof(respawn_t),PU_LEVELSTRUCT,NULL);
+
+ memset (temp,0,sizeof(*temp));
+ temp->ticcount = GetRespawnTimeForItem(stat->itemnumber);
+ temp->tilex = stat->tilex;
+ temp->tiley = stat->tiley;
+ temp->itemnumber = stat->itemnumber;
+ temp->spawnz = stat->z;
+ temp->linked_to = stat->linked_to;
+ //SoftError("\nrespawn obj created for stattype %d with z = %d",stat->itemnumber,temp->spawnz);
+ AddRespawnStatic(temp);
+ }
+ }
+ //Z_Free(stat);
+ AddToFreeStaticList(stat);
+
+ //Add_To_Delete_Array(stat);
+ statcount --;
+}
+
+
+void RemoveRespawnStatic(respawn_t*stat)
+{
+ if (stat == lastrespawn)
+ lastrespawn = stat->prev;
+ else
+ stat->next->prev = stat->prev;
+
+ if (stat == firstrespawn)
+ firstrespawn = stat->next;
+ else
+ stat->prev->next = stat->next;
+
+ stat->prev = NULL;
+ stat->next = NULL;
+ Z_Free(stat);
+}
+
+
+void TurnOffLight(int tilex,int tiley)
+{
+ DoLights(tilex,tiley);
+ LightsInArea[MAPSPOT(tilex,tiley,0)-AREATILE]--;
+
+}
+
+
+void ActivateLight(long light)
+{ statobj_t*tstat;
+
+ tstat = (statobj_t*)light;
+
+ tstat->shapenum ++;
+ tstat->flags |= FL_LIGHTON;
+ TurnOnLight(tstat->tilex,tstat->tiley);
+
+}
+
+
+void DeactivateLight(long light)
+{ statobj_t*tstat;
+
+ tstat = (statobj_t*)light;
+
+ tstat->shapenum --;
+ tstat->flags &= ~(FL_LIGHTON);
+ TurnOffLight(tstat->tilex,tstat->tiley);
+
+}
+
+void TurnOnLight(int i,int j)
+{
+
+ LightsInArea[MAPSPOT(i,j,0)-AREATILE]++;
+
+ if (lightsource==0)
+ return;
+
+ if ((!(tilemap[i+1][j])) && (!(tilemap[i-1][j])))
+ {
+ SetLight(i,j,0xcdeffedc);
+ SetLight(i+1,j,0x135789ab);
+ SetLight(i-1,j,0xba987351);
+ SetLight(i,j+1,0xcdeffedc);
+ SetLight(i,j-1,0xcdeffedc);
+ SetLight(i-1,j-1,0xba987351);
+ SetLight(i+1,j+1,0xba987351);
+ SetLight(i+1,j-1,0x135789ab);
+ SetLight(i-1,j+1,0x135789ab);
+ }
+ else if ((!(tilemap[i][j+1])) && (!(tilemap[i][j-1])))
+ {
+ SetLight(i,j,0xcdeffedc);
+ SetLight(i+1,j,0xcdeffedc);
+ SetLight(i-1,j,0xcdeffedc);
+ SetLight(i,j+1,0x135789ab);
+ SetLight(i,j-1,0xba987531);
+ SetLight(i-1,j-1,0x135789ab);
+ SetLight(i+1,j-1,0xba987531);
+ SetLight(i+1,j+1,0x135789ab);
+ SetLight(i-1,j+1,0xba987531);
+ }
+ // |
+ //__|
+ else if ((tilemap[i][j+1]) && (tilemap[i+1][j]))
+ {
+ SetLight(i,j,0xcdeffedc);
+ SetLight(i+1,j,0xcdeffedc);
+ SetLight(i-1,j,0xcdeffedc);
+ SetLight(i,j+1,0xcdeffedc);
+ SetLight(i,j-1,0xcdeffedc);
+ SetLight(i-1,j-1,0xba987351);
+ SetLight(i+1,j-1,0xba987351);
+ SetLight(i+1,j+1,0xba987351);
+ SetLight(i-1,j+1,0x135789ab);
+ }
+ //|
+ //|_
+ else if ((tilemap[i][j+1]) && (tilemap[i-1][j]))
+ {
+ SetLight(i,j,0xcdeffedc);
+ SetLight(i+1,j,0xcdeffedc);
+ SetLight(i-1,j,0xcdeffedc);
+ SetLight(i,j+1,0xcdeffedc);
+ SetLight(i,j-1,0xcdeffedc);
+ SetLight(i-1,j-1,0x135789ab);
+ SetLight(i+1,j-1,0xba987531);
+ SetLight(i+1,j+1,0xba987531);
+ SetLight(i-1,j+1,0xba987531);
+ }
+ //_
+ // |
+ else if ((tilemap[i][j-1]) && (tilemap[i+1][j]))
+ {
+ SetLight(i,j,0xcdeffedc);
+ SetLight(i+1,j,0xcdeffedc);
+ SetLight(i-1,j,0xcdeffedc);
+ SetLight(i,j+1,0xcdeffedc);
+ SetLight(i,j-1,0xcdeffedc);
+ SetLight(i-1,j-1,0xba987531);
+ SetLight(i+1,j-1,0x135789ab);
+ SetLight(i+1,j+1,0x135789ab);
+ SetLight(i-1,j+1,0xba987531);
+ }
+ //__
+ //|
+ else if ((tilemap[i][j-1]) && (tilemap[i-1][j]))
+ {
+ SetLight(i,j,0xcdeffedc);
+ SetLight(i+1,j,0xcdeffedc);
+ SetLight(i-1,j,0xcdeffedc);
+ SetLight(i,j+1,0xcdeffedc);
+ SetLight(i,j-1,0xcdeffedc);
+ SetLight(i-1,j-1,0x135789ab);
+ SetLight(i+1,j-1,0x135789ab);
+ SetLight(i+1,j+1,0xba987531);
+ SetLight(i-1,j+1,0xba987531);
+ }
+ else if (tilemap[i][j])
+ {
+ SetLight(i,j,0x58bffb85);
+ }
+ else
+ {
+ SetLight(i,j,0xcdeffedc);
+ SetLight(i+1,j,0xba987654);
+ SetLight(i-1,j,0x456789ab);
+ SetLight(i,j+1,0xba987654);
+ SetLight(i,j-1,0x456789ab);
+ SetLight(i-1,j+1,0x33322211);
+ SetLight(i+1,j+1,0x33322211);
+ SetLight(i+1,j-1,0x11222333);
+ SetLight(i-1,j-1,0x11222333);
+ }
+
+
+}
+
+
+
+
+/*===============
+=
+= AddRespawnStatic
+=
+===============
+*/
+
+void AddRespawnStatic(respawn_t*stat)
+{
+ if (firstrespawn)
+ { stat->prev = lastrespawn;
+ lastrespawn->next = stat;
+ }
+ else
+ firstrespawn = stat;
+ lastrespawn = stat;
+}
+
+
+/*
+===============
+=
+= InitStaticList
+=
+===============
+*/
+
+void InitStaticList (void)
+{
+ FIRSTSTAT = NULL;
+ LASTSTAT = NULL;
+ lastactivestat = NULL;
+ firstactivestat = NULL;
+ firstrespawn = NULL;
+ lastrespawn = NULL;
+ lastemptystat = NULL;
+ firstemptystat = NULL;
+
+ memset(&BulletHoles[0],0,sizeof(BulletHoles));
+ MISCVARS->BulletHoleNum = 0;
+
+
+ memset(sprites,0,sizeof(sprites));
+ if (loadedgame==false)
+ {
+ memset(switches,0,sizeof(switches));
+ lastswitch = &switches[0];
+ }
+ statcount = 0;
+
+}
+
+
+/*
+===============
+=
+= InitAnimatedWallList
+=
+===============
+*/
+
+void InitAnimatedWallList(void)
+{
+ int i;
+
+ for (i=0; i<MAXANIMWALLS; i++)
+ animwalls[i].active=0;
+}
+
+/*
+===============
+=
+= SetupAnimatedWall
+=
+===============
+*/
+
+void SetupAnimatedWall(int which)
+{
+ animwall_t * aw;
+ int i;
+ int texture;
+
+ aw = &animwalls[which];
+
+ aw->active=1;
+ aw->ticcount=animwallsinfo[which].tictime;
+ aw->count = 1;
+
+ texture=W_GetNumForName(animwallsinfo[which].firstlump);
+
+ aw->basetexture=texture;
+ aw->texture=texture;
+
+ if (DoPanicMapping()==true)
+ {
+ PreCacheLump(aw->basetexture,PU_CACHEWALLS,cache_pic_t);
+ }
+ else
+ {
+ for (i=aw->basetexture; i<aw->basetexture+animwallsinfo[which].numanims; i++)
+ PreCacheLump(i,PU_CACHEWALLS,cache_pic_t);
+ }
+}
+
+
+/*
+===============
+=
+= SaveStatics
+=
+===============
+*/
+
+void SaveStatics (byte **buffer, int * size)
+{ statobj_t * temp;
+ saved_stat_type dummy;
+ byte * tptr;
+ int count;
+
+ if (statcount==0)
+ {
+ *size=0;
+ *buffer=SafeMalloc(16);
+ return;
+ }
+ *size = statcount*sizeof(saved_stat_type);
+ *buffer = (byte *)SafeMalloc(*size);
+ tptr = *buffer;
+
+ for(count=0,temp=FIRSTSTAT; temp; temp=temp->statnext)
+ { dummy.x = temp->x;
+ dummy.y = temp->y;
+ dummy.z = temp->z;
+ dummy.flags = temp->flags;
+ dummy.ticcount = temp->ticcount;
+ dummy.hitpoints = temp->hitpoints;
+ dummy.shapenum = temp->shapenum;
+ dummy.ammo = temp->ammo;
+ dummy.count = temp->count;
+ dummy.numanims = temp->numanims;
+ dummy.itemnumber = temp->itemnumber;
+ dummy.areanumber = temp->areanumber;
+ temp->whichstat = count;
+ dummy.whichstat = count++;
+ dummy.linked_to = temp->linked_to;
+
+ memcpy(tptr,&(dummy.x),sizeof(saved_stat_type));
+ tptr += sizeof(saved_stat_type);
+
+ }
+
+}
+
+/*
+===============
+=
+= DoLights
+=
+===============
+*/
+
+void DoLights (int tilex, int tiley)
+{
+ if (lightsource==0)
+ return;
+ if (TurnOffLight0 (tilex, tiley))
+ LightSourceAt(tilex,tiley) = 0;
+
+ if (TurnOffLight1 (tilex, tiley, -1, -1))
+ LightSourceAt(tilex-1,tiley-1) = 0;
+
+ if (TurnOffLight2 (tilex, tiley, -1))
+ LightSourceAt(tilex,tiley-1) = 0;
+
+ if (TurnOffLight1 (tilex, tiley, 1, -1))
+ LightSourceAt(tilex+1,tiley-1) = 0;
+
+ if (TurnOffLight3 (tilex, tiley, 1))
+ LightSourceAt(tilex+1,tiley) = 0;
+
+ if (TurnOffLight1 (tilex, tiley, 1, 1))
+ LightSourceAt(tilex+1,tiley+1) = 0;
+
+ if (TurnOffLight2 (tilex, tiley, 1))
+ LightSourceAt(tilex,tiley+1) = 0;
+
+ if (TurnOffLight1 (tilex, tiley, -1, 1))
+ LightSourceAt(tilex-1,tiley+1) = 0;
+
+ if (TurnOffLight3 (tilex, tiley, -1))
+ LightSourceAt(tilex-1,tiley) = 0;
+}
+
+
+/*
+===============
+=
+= TurnOffLight0
+=
+===============
+*/
+
+boolean TurnOffLight0 (int tilex, int tiley)
+{
+ if ( IsLight(tilex-1,tiley ) ||
+ IsLight(tilex-1,tiley-1) ||
+ IsLight(tilex,tiley-1) ||
+ IsLight(tilex+1,tiley-1) ||
+ IsLight(tilex+1,tiley ) ||
+ IsLight(tilex+1,tiley+1) ||
+ IsLight(tilex,tiley+1) ||
+ IsLight(tilex-1,tiley+1) )
+ return (false);
+ else
+ return (true);
+}
+
+/*
+===============
+=
+= TurnOffLight1
+=
+===============
+*/
+
+boolean TurnOffLight1 (int tilex, int tiley, int i, int j)
+{
+ int tempi = 2*i;
+ int tempy = 2*j;
+
+ if ( IsLight(tilex+i,tiley ) ||
+ IsLight(tilex+i,tiley+j) ||
+ IsLight(tilex,tiley+j) ||
+ IsLight(tilex,tiley+tempy) ||
+ IsLight(tilex+i,tiley+tempy) ||
+ IsLight(tilex+tempi,tiley+tempy) ||
+ IsLight(tilex+tempi,tiley+j) ||
+ IsLight(tilex+tempi,tiley))
+ return (false);
+ else
+ return (true);
+}
+
+
+/*
+===============
+=
+= TurnOffLight2
+=
+===============
+*/
+
+boolean TurnOffLight2 (int tilex, int tiley, int j)
+{
+ int tempy = 2*j;
+
+ if ( IsLight(tilex-1,tiley ) ||
+ IsLight(tilex-1,tiley+j) ||
+ IsLight(tilex-1,tiley+tempy) ||
+ IsLight(tilex,tiley+j) ||
+ IsLight(tilex,tiley+tempy) ||
+ IsLight(tilex+1,tiley) ||
+ IsLight(tilex+1,tiley+j) ||
+ IsLight(tilex+1,tiley+tempy))
+ return (false);
+ else
+ return (true);
+}
+
+
+/*
+===============
+=
+= TurnOffLight3
+=
+===============
+*/
+
+boolean TurnOffLight3 (int tilex, int tiley, int i)
+{
+ int tempx = 2*i;
+
+ if ( IsLight(tilex,tiley-1) ||
+ IsLight(tilex+1,tiley-1) ||
+ IsLight(tilex+tempx,tiley-1) ||
+ IsLight(tilex+i,tiley) ||
+ IsLight(tilex+tempx,tiley) ||
+ IsLight(tilex,tiley+1) ||
+ IsLight(tilex+i,tiley+1) ||
+ IsLight(tilex+tempx,tiley+1))
+ return (false);
+ else
+ return (true);
+}
+
+
+
+
+/*
+======================
+=
+= PreCacheStaticFrames
+=
+======================
+*/
+
+
+
+
+void PreCacheStaticFrames(statobj_t*temp)
+{
+ int z,start,stop;
+ int female=0,black=0;
+
+ if (temp->itemnumber != stat_bullethole &&
+ ((temp->itemnumber < stat_touch1) || (temp->itemnumber > stat_touch4)))
+ PreCacheLump(temp->shapenum+shapestart,PU_CACHESPRITES,cache_patch_t);
+ else
+ PreCacheLump(temp->shapenum+shapestart,PU_CACHESPRITES,cache_transpatch_t);
+ for (z=0; z<temp->numanims; z++)
+ PreCacheLump(temp->shapenum+shapestart+z,PU_CACHESPRITES,cache_patch_t);
+
+ if (temp->flags & FL_ROTATING)
+ {
+ for (z=1; z<8; z++)
+ PreCacheLump(temp->shapenum+shapestart+z,PU_CACHESPRITES,cache_patch_t);
+ }
+
+ if (temp->flags & FL_WOODEN)
+ {
+ start = W_GetNumForName("WFRAG1");
+ stop = W_GetNumForName("WFRAG14");
+ PreCacheGroup(start,stop,cache_patch_t);
+ }
+
+ if (temp->flags & FL_METALLIC)
+ {
+ PreCacheLump(W_GetNumForName("MSHARDS"),PU_CACHESPRITES,cache_patch_t);
+ start = W_GetNumForName("ROBODIE1");
+ stop = W_GetNumForName("ROBODEAD");
+ PreCacheGroup(start,stop,cache_patch_t);
+ }
+
+ female = ((locplayerstate->player == 1) || (locplayerstate->player == 3));
+ black = (locplayerstate->player == 2);
+
+ if (female)
+ {
+ start = W_GetNumForName("FPIST11");
+ stop = W_GetNumForName("FPIST13");
+ }
+ else if (black)
+ {
+ start = W_GetNumForName("BMPIST1");
+ stop = W_GetNumForName("BMPIST3");
+ }
+ else
+ {
+ start = W_GetNumForName("MPIST11");
+ stop = W_GetNumForName("MPIST13");
+ }
+
+ PreCacheGroup(start,stop,cache_patch_t);
+
+ switch (temp->itemnumber)
+ {
+
+ case stat_pedgoldkey:
+ case stat_pedsilverkey:
+ case stat_pedironkey:
+ case stat_pedcrystalkey:
+ PreCacheLump(W_GetNumForName("PEDESTA"),PU_CACHESPRITES,cache_patch_t);
+ break;
+
+ case stat_bat:
+ start = W_GetNumForName("EXBAT1");
+ stop = W_GetNumForName("EXBAT7");
+ PreCacheGroup(start,stop,cache_patch_t);
+ break;
+ case stat_knifestatue:
+ start = W_GetNumForName("KNIFE1");
+ stop = W_GetNumForName("KNIFE10");
+ PreCacheGroup(start,stop,cache_patch_t);
+ break;
+ case stat_twopistol:
+ if (female)
+ {
+ start = W_GetNumForName("RFPIST1");
+ stop = W_GetNumForName("LFPIST3");
+ }
+ else if (black)
+ {
+ start = W_GetNumForName("RBMPIST1");
+ stop = W_GetNumForName("LBMPIST3");
+ }
+ else
+ {
+ start = W_GetNumForName("RMPIST1");
+ stop = W_GetNumForName("LMPIST3");
+ }
+ PreCacheGroup(start,stop,cache_patch_t);
+ break;
+ case stat_mp40:
+ start = W_GetNumForName("MP401");
+ stop = W_GetNumForName("MP403");
+ PreCacheGroup(start,stop,cache_patch_t);
+ break;
+ case stat_bazooka:
+ start = W_GetNumForName("BAZOOKA1");
+ stop = W_GetNumForName("BAZOOKA4");
+ PreCacheGroup(start,stop,cache_patch_t);
+ break;
+ case stat_firebomb:
+ start = W_GetNumForName("FBOMB1");
+ stop = W_GetNumForName("FBOMB4");
+ PreCacheGroup(start,stop,cache_patch_t);
+ break;
+ case stat_heatseeker:
+ start = W_GetNumForName("HSEEK1");
+ stop = W_GetNumForName("HSEEK4");
+ PreCacheGroup(start,stop,cache_patch_t);
+ break;
+ case stat_drunkmissile:
+ start = W_GetNumForName("DRUNK1");
+ stop = W_GetNumForName("DRUNK4");
+ PreCacheGroup(start,stop,cache_patch_t);
+ break;
+ case stat_firewall:
+ start = W_GetNumForName("FIREW1");
+ stop = W_GetNumForName("FIREW3");
+ PreCacheGroup(start,stop,cache_patch_t);
+ break;
+ case stat_splitmissile:
+ start = W_GetNumForName("SPLIT1");
+ stop = W_GetNumForName("SPLIT4");
+ PreCacheGroup(start,stop,cache_patch_t);
+ break;
+ case stat_kes:
+ start = W_GetNumForName("KES1");
+ stop = W_GetNumForName("KES6");
+ PreCacheGroup(start,stop,cache_patch_t);
+ break;
+ case stat_godmode:
+ start = W_GetNumForName("GODHAND1");
+ stop = W_GetNumForName("GODHAND8");
+ PreCacheGroup(start,stop,cache_patch_t);
+
+ PreCacheGroup(W_GetNumForName("VAPO1"),
+ W_GetNumForName("LITSOUL"),
+ cache_patch_t);
+
+ PreCacheGroup(W_GetNumForName("GODFIRE1"),
+ W_GetNumForName("GODFIRE4"),
+ cache_patch_t);
+
+ break;
+ case stat_dogmode:
+ start = W_GetNumForName("DOGNOSE1");
+ stop = W_GetNumForName("DOGPAW4");
+ PreCacheGroup(start,stop,cache_patch_t);
+ break;
+
+ default:
+ ;
+ }
+
+
+
+}
+
+
+
+/*
+===============
+=
+= LoadStatics
+=
+===============
+*/
+
+
+
+
+void LoadStatics( byte * buffer, int size)
+{ saved_stat_type dummy;
+ int stcount,i;
+ statobj_t*temp;
+
+ stcount = size/sizeof(saved_stat_type);
+ InitStaticList();
+
+ for(i=0; i<stcount; i++)
+ {
+ temp = (statobj_t*)Z_LevelMalloc(sizeof(statobj_t),PU_LEVELSTRUCT,NULL);
+ if (!temp)
+ Error("LoadStatics: Failed on allocation of static %d of %d",i,stcount);
+ memset(temp,0,sizeof(*temp));
+ memcpy(&(dummy.x),buffer,sizeof(saved_stat_type));
+ temp->whichstat = statcount++;
+ temp->x = dummy.x;
+ temp->y = dummy.y;
+ temp->z = dummy.z;
+ temp->flags = dummy.flags;
+ temp->ticcount = dummy.ticcount;
+ temp->hitpoints = dummy.hitpoints;
+ temp->shapenum = dummy.shapenum;
+ temp->ammo = dummy.ammo;
+ temp->count = dummy.count;
+ temp->numanims = dummy.numanims;
+ temp->itemnumber = dummy.itemnumber;
+ temp->areanumber = dummy.areanumber;
+ temp->linked_to = dummy.linked_to;
+
+ temp->which = SPRITE;
+ temp->tilex = temp->x >> TILESHIFT;
+ temp->tiley = temp->y >> TILESHIFT;
+ temp->flags &= ~FL_ABP;
+ temp->visspot = &spotvis[temp->tilex][temp->tiley];
+
+ if ((temp->itemnumber >= stat_touch1) &&
+ (temp->itemnumber <= stat_touch4))
+ { touchindices[temp->tilex][temp->tiley] = lasttouch + 1;
+ lasttouch ++;
+ SD_PreCacheSoundGroup(SD_TOUCHPLATESND,SD_BADTOUCHSND);
+ }
+
+ AddStatic(temp);
+ if (temp->shapenum != -1)
+ {
+ if (temp->itemnumber == stat_bullethole)
+ {
+ SetupBulletHoleLink(temp->linked_to,temp);
+ }
+
+ else if (temp->flags & FL_DEADBODY)
+ {
+ if ( actorat[temp->tilex][temp->tiley] == NULL )
+ actorat[temp->tilex][temp->tiley] = temp;
+ }
+
+ else if (!(temp->flags & FL_NONMARK))
+ {
+ sprites[temp->tilex][temp->tiley] = temp;
+ }
+
+ PreCacheStaticFrames(temp);
+
+
+ }
+ PreCacheStaticSounds(temp->itemnumber);
+
+ buffer += sizeof(saved_stat_type);
+ }
+}
+
+
+void Set_NewZ_to_MapValue(fixed *newz,int zoffset,const char*errorstr,int tilex,int tiley)
+{
+ int zf,z;
+
+ zoffset&=0xff;
+ z=zoffset>>4;
+ zf=zoffset&0xf;
+ if (z==0xf)
+ *newz = nominalheight+64-(zf<<2);
+ else
+ {
+ if (z>levelheight)
+ Error ("You specified a height of %x for the %s at tilex=%d tiley=%d when\n the level is only %d high\n",
+ zoffset,errorstr,tilex,tiley,levelheight);
+ else
+ *newz = nominalheight-(z<<6)-(zf<<2);
+ }
+
+}
+
+
+
+/*
+===============
+=
+= SpawnStatic
+=
+===============
+*/
+
+
+int BaseMarkerZ;//bna++
+
+void SpawnStatic (int tilex, int tiley, int mtype, int zoffset)
+{ statobj_t * temp;
+ boolean onetimer;
+
+
+
+#if (SHAREWARE == 1)
+ switch(mtype)
+ {
+ case stat_rlight:
+ case stat_glight:
+ case stat_ylight:
+ case stat_chandelier:
+ mtype = stat_blight;
+ break;
+
+ case stat_garb1:
+ case stat_garb2:
+ case stat_garb3:
+ case stat_shit:
+ mtype = stat_metalshards;
+ break;
+
+ case stat_lamp:
+ mtype = stat_altbrazier2;
+ break;
+
+ }
+#endif
+
+
+
+ if ( BATTLEMODE )
+ {
+ if ( !gamestate.BattleOptions.SpawnWeapons )
+ {
+ if ( stats[ mtype ].flags & FL_WEAPON )
+ {
+ return;
+ }
+ }
+
+ if (mtype == stat_pit)
+ return;
+
+ // Change lifeitems and extra lives to health
+ switch( mtype )
+ {
+ case stat_lifeitem1 :
+ case stat_lifeitem2 :
+ mtype = stat_monkcrystal1;
+ break;
+
+ case stat_lifeitem3 :
+ case stat_lifeitem4 :
+ case stat_oneup :
+ case stat_threeup :
+ mtype = stat_monkcrystal2;
+ break;
+ }
+
+ switch( mtype )
+ {
+ case stat_monkmeal :
+ case stat_priestporridge :
+ case stat_monkcrystal1 :
+ case stat_monkcrystal2 :
+ case stat_healingbasin :
+ if ( ( gamestate.Product != ROTT_SHAREWARE ) &&
+ ( gamestate.BattleOptions.SpawnMines ) &&
+ ( !IsPlatform( tilex, tiley ) &&
+ ( ( zoffset & 0xff00 ) != 0xb000 ) ) &&
+ ( zoffset == -1 ) )
+ {
+ mtype = stat_mine;
+ }
+ else if ( !gamestate.BattleOptions.SpawnHealth )
+ {
+ return;
+ }
+ break;
+ }
+ }
+
+ if (!firstemptystat)
+ { temp = (statobj_t*)Z_LevelMalloc(sizeof(statobj_t),PU_LEVELSTRUCT,NULL);
+ //SoftError("\nMalloc-ing actor");
+ //if (insetupgame)
+ // SoftError("in setup");
+ }
+
+ else
+ { temp = lastemptystat;
+ //SoftError("\nfree actor available");
+ RemoveFromFreeStaticList(lastemptystat);
+ }
+
+// Standard pole hack
+
+ if ((zoffset>=14) && (zoffset<=17))
+ zoffset=-1;
+
+ if (temp)
+ { memset(temp,0,sizeof(*temp));
+ temp->shapenum = stats[mtype].picnum;
+ temp->whichstat = statcount ++;
+ temp->tilex = tilex;
+ temp->tiley = tiley;
+ temp->x = ((long)tilex << TILESHIFT) + 0x8000;
+ temp->y = ((long)tiley << TILESHIFT) + 0x8000;
+ temp->areanumber = MAPSPOT(tilex,tiley,0)-AREATILE;
+ temp->linked_to = -1;
+ if ((temp->areanumber<=0) || (temp->areanumber>NUMAREAS))
+ Error ("Sprite at x=%d y=%d type=%d has an illegal areanumber\n",tilex,tiley,mtype);
+ if ( mtype == stat_mine )
+ {
+ temp->z = nominalheight;
+ }
+ else if (zoffset!=-1)
+ {
+ if ((zoffset&0xff00)==0xb000)
+ Set_NewZ_to_MapValue(&(temp->z),zoffset,"static",tilex,tiley);
+ else if (IsPlatform(tilex,tiley))
+ temp->z = PlatformHeight(tilex,tiley);
+ else if (zoffset==11)
+ temp->z=-65;
+ else if (zoffset==12)
+ temp->z=-66;
+ else
+ temp->z = nominalheight;
+ // Error ("You didn't specify a valid height over the sprite at tilex=%ld tiley=%ld\n",tilex,tiley);
+ }
+ else if (mtype>stat_chandelier)
+ temp->z = nominalheight;
+
+ temp->visspot = &spotvis[tilex][tiley];
+ temp->which = SPRITE;
+ temp->ticcount = stats[mtype].tictime;
+ temp->hitpoints = stats[mtype].hitpoints;
+ temp->itemnumber = stats[mtype].type;
+ temp->flags = stats[mtype].flags;
+ temp->ammo = stats[mtype].ammo;
+ temp->numanims = stats[mtype].numanims;
+
+
+
+
+ if (temp->flags & FL_BONUS)
+ switch (stats[mtype].type)
+ {
+ case stat_lifeitem1:
+ case stat_lifeitem2:
+ case stat_lifeitem3:
+ case stat_lifeitem4:
+ gamestate.treasuretotal++;
+ break;
+ default:
+ ;
+ }
+
+
+
+
+ AddStatic(temp);
+
+ onetimer = ((mtype == stat_rubble) || (mtype == stat_woodfrag) ||
+ (mtype == stat_metalfrag) || (mtype == stat_missmoke)
+ );
+
+ if (DoPanicMapping())
+ {
+ if (temp->numanims && (!onetimer))
+ {
+ temp->flags &= ~FL_ACTIVE;
+ temp->numanims = 0;
+ GameRandomNumber("SpawnStatic",mtype);
+ }
+ }
+
+ else
+ {
+ if (temp->numanims)
+ {
+ if (!onetimer)
+ temp->count = (int)(((int)GameRandomNumber("SpawnStatic",mtype) % stats[mtype].numanims) + 1);
+ else
+ temp->count = 0;
+ }
+ else if (temp->itemnumber == stat_standardpole)
+ {
+ if (MAPSPOT(temp->tilex,temp->tiley,2))
+ temp->count = 2*(MAPSPOT(temp->tilex,temp->tiley,2)-14);
+ else
+ temp->count = 0;
+ }
+
+ if ((temp->itemnumber == stat_knifestatue) ||
+ (temp->itemnumber == stat_emptystatue) ||
+ (temp->itemnumber == stat_standardpole))
+ temp->flags|=FL_ROTATING;
+ }
+
+
+
+
+ if (mtype != stat_missmoke)
+ sprites[tilex][tiley] = temp;
+ else
+ temp->flags |= FL_NONMARK;
+
+
+//================ check special junk ==================================//
+
+ if (temp->itemnumber == stat_dariantouch)
+ { _2Dpoint *tdptr;
+
+ tdptr = &(MISCVARS->ETOUCH[MISCVARS->nexttouch]);
+
+ tdptr->x = tilex;
+ tdptr->y = tiley;
+ sprites[tilex][tiley]->linked_to = MISCVARS->nexttouch;
+ MISCVARS->nexttouch ++;
+ }
+ else if ((temp->itemnumber >= stat_touch1) &&
+ (temp->itemnumber <= stat_touch4))
+ { touchindices[tilex][tiley] = lasttouch + 1;
+ SD_PreCacheSoundGroup(SD_TOUCHPLATESND,SD_BADTOUCHSND);
+ lasttouch ++;
+ }
+
+//=====================================================================//
+ //bna added
+ // BaseMarkerZ used to adjust height in s_basemarker1
+ // in SpawnNewObj(i,j,&s_basemarker1,inertobj);
+ BaseMarkerZ=temp->z;//bna++ BaseMarkerZ = spawnz;
+
+ PreCacheStaticFrames(temp);
+
+ PreCacheStaticSounds(temp->itemnumber);
+
+ if (temp->flags & FL_WEAPON)
+ MISCVARS->NUMWEAPONS ++;
+ }
+ else
+ Error("Z_LevelMalloc failed in SpawnStatic!");
+
+}
+
+/*
+===============
+=
+= SpawnInertStatic
+=
+===============
+*/
+
+void SpawnInertStatic (int x, int y, int z, int mtype)
+{ statobj_t * temp;
+
+
+
+
+ if (!firstemptystat)
+ { temp = (statobj_t*)Z_LevelMalloc(sizeof(statobj_t),PU_LEVELSTRUCT,NULL);
+ //SoftError("\nMalloc-ing actor");
+ //if (insetupgame)
+ // SoftError("in setup");
+ }
+
+ else
+ { temp = lastemptystat;
+ //SoftError("\nfree actor available");
+ RemoveFromFreeStaticList(lastemptystat);
+ }
+
+ if (temp)
+ { memset(temp,0,sizeof(*temp));
+ temp->shapenum = stats[mtype].picnum;
+
+ temp->whichstat = statcount ++;
+ temp->tilex = x>>16;
+ temp->tiley = y>>16;
+ temp->x = x;
+ temp->y = y;
+ temp->areanumber = MAPSPOT(temp->tilex,temp->tiley,0)-AREATILE;
+ temp->linked_to = -1;
+ if ((temp->areanumber<=0) || (temp->areanumber>NUMAREAS))
+ {
+ int tilex=temp->tilex;
+ int tiley=temp->tiley;
+
+ FindEmptyTile(&tilex,&tiley);
+ temp->areanumber = MAPSPOT(tilex,tiley,0)-AREATILE;
+ }
+ temp->z=z;
+ temp->visspot = &spotvis[temp->tilex][temp->tiley];
+ temp->which = SPRITE;
+ temp->ticcount = stats[mtype].tictime;
+ temp->hitpoints = stats[mtype].hitpoints;
+ temp->itemnumber = stats[mtype].type;
+ temp->flags = (stats[mtype].flags|FL_ABP|FL_NONMARK);
+ if (fog)
+ { temp->shapenum++;
+ temp->flags &= ~FL_TRANSLUCENT;
+ }
+
+ temp->ammo = stats[mtype].ammo;
+ temp->numanims = stats[mtype].numanims;
+ AddStatic(temp);
+ MakeStatActive(temp);
+ }
+ else
+ Error("Z_LevelMalloc failed in SpawnStatic!");
+
+}
+
+/*
+===============
+=
+= SpawnSolidStatic
+=
+===============
+*/
+
+void SpawnSolidStatic (statobj_t * temp)
+{
+ if (temp->flags & FL_ACTIVE)
+ temp->flags &= ~FL_ACTIVE;
+ temp->hitpoints = INITIALFIRECOLOR;
+ temp->flags = FL_SOLIDCOLOR|FL_SEEN|FL_ABP;
+ if ((gamestate.BattleOptions.RespawnItems) &&
+ (temp->itemnumber == stat_tntcrate)
+ )
+ temp->flags |= FL_RESPAWN;
+
+ temp->ticcount = SOLIDCOLORTICTIME;
+}
+
+
+/*
+======================
+=
+= PreCacheStaticSounds
+=
+======================
+*/
+
+
+
+void PreCacheStaticSounds (int itemnumber)
+{
+
+ if (stats[itemnumber].flags & FL_SHOOTABLE)
+ SD_PreCacheSound(SD_ITEMBLOWSND);
+
+
+ switch(itemnumber)
+
+ {
+ case stat_pit:
+ SD_PreCacheSound(SD_PITTRAPSND);
+ break;
+
+ case stat_bonusbarrel:
+ SD_PreCacheSound(SD_BONUSBARRELSND);
+ break;
+
+ case stat_knifestatue:
+ SD_PreCacheSound(SD_GETKNIFESND);
+ break;
+ case stat_gibs1:
+ case stat_gibs2:
+ case stat_gibs3:
+ SD_PreCacheSound (SD_ACTORSQUISHSND);
+ break;
+ case stat_pedgoldkey:
+ case stat_pedsilverkey:
+ case stat_pedironkey:
+ case stat_pedcrystalkey:
+ SD_PreCacheSound (SD_GETKEYSND);
+
+ break;
+ case stat_monkmeal:
+ SD_PreCacheSound (SD_GETHEALTH1SND);
+ break;
+ case stat_monkcrystal1:
+ SD_PreCacheSound (SD_GETHEALTH2SND);
+ break;
+ case stat_monkcrystal2:
+ SD_PreCacheSound (SD_GETHEALTH2SND);
+ break;
+ case stat_priestporridge:
+ SD_PreCacheSound (SD_GETHEALTH1SND);
+ SD_PreCacheSound(SD_COOKHEALTHSND);
+
+ break;
+
+ case stat_healingbasin:
+ SD_PreCacheSound (SD_GETHEALTH2SND);
+ break;
+
+ case stat_oneup:
+ SD_PreCacheSound(SD_GET1UPSND);
+ break;
+ case stat_threeup:
+ SD_PreCacheSound(SD_GET3UPSND);
+ break;
+
+ case stat_scotthead:
+ SD_PreCacheSound(SD_GETHEADSND);
+ break;
+
+ case stat_twopistol:
+ case stat_mp40:
+ case stat_bazooka:
+ case stat_firebomb:
+ case stat_heatseeker:
+ case stat_drunkmissile:
+ case stat_firewall:
+ case stat_splitmissile:
+ case stat_kes:
+ SD_PreCacheSound(SD_GETWEAPONSND);
+ break;
+
+ case stat_bat:
+ SD_PreCacheSound(SD_GETBATSND);
+ break;
+
+ case stat_lifeitem1:
+ case stat_lifeitem2:
+ case stat_lifeitem3:
+ case stat_lifeitem4:
+ SD_PreCacheSound(SD_GETBONUSSND);
+ break;
+
+
+ case stat_random:
+ SD_PreCacheSound(SD_GETGODSND);
+ SD_PreCacheSound(SD_GETDOGSND);
+ SD_PreCacheSound(SD_GETELASTSND);
+ SD_PreCacheSound(SD_GETSHROOMSSND);
+ SD_PreCacheSound(SD_LOSEMODESND);
+
+ break;
+ case stat_bulletproof:
+ SD_PreCacheSound(SD_GETBVESTSND);
+ SD_PreCacheSound(SD_LOSEMODESND);
+ break;
+
+ case stat_gasmask:
+ SD_PreCacheSound(SD_GETMASKSND);
+ SD_PreCacheSound(SD_LOSEMODESND);
+ break;
+
+ case stat_asbesto:
+ SD_PreCacheSound(SD_GETAVESTSND);
+ SD_PreCacheSound(SD_LOSEMODESND);
+ break;
+
+ case stat_elastic:
+ SD_PreCacheSound(SD_GETELASTSND);
+ SD_PreCacheSound(SD_LOSEMODESND);
+ break;
+
+ case stat_fleetfeet:
+ SD_PreCacheSound(SD_GETFLEETSND);
+ SD_PreCacheSound(SD_LOSEMODESND);
+ break;
+
+ case stat_godmode:
+ SD_PreCacheSound(SD_GETGODSND);
+ SD_PreCacheSound(SD_GODMODE1SND);
+
+ break;
+
+ case stat_dogmode:
+ SD_PreCacheSound(SD_GETDOGSND);
+ break;
+
+ case stat_mushroom:
+ SD_PreCacheSound(SD_GETSHROOMSSND);
+ SD_PreCacheSound(SD_LOSEMODESND);
+
+ break;
+
+ case stat_dipball1:
+ case stat_dipball2:
+ case stat_dipball3:
+ SD_PreCacheSound(SD_GETBONUSSND);
+ break;
+
+ default:
+ SD_PreCacheSound(SD_GETBONUSSND);
+ break;
+ }
+
+}
+
+
+
+
+
+/*
+===============
+=
+= SaveSwitches
+=
+===============
+*/
+
+void SaveSwitches(byte ** buffer, int * size)
+{ int numswitches,i;
+ byte * tptr;
+
+ numswitches = lastswitch-&switches[0];
+ if (numswitches==0)
+ {
+ *size=0;
+ *buffer=SafeMalloc(16);
+ return;
+ }
+ *size = numswitches*sizeof(wall_t);
+
+ *buffer = (byte *)SafeMalloc(*size);
+ tptr = *buffer;
+
+ for(i=0; i<numswitches; i++)
+ { memcpy(tptr,&switches[i],sizeof(wall_t));
+ tptr += sizeof(wall_t);
+ }
+
+}
+
+
+/*
+===============
+=
+= LoadSwitches
+=
+===============
+*/
+
+void LoadSwitches (byte * buffer, int size)
+{ int numswitches,i,tilex,tiley;
+
+ numswitches = size/sizeof(wall_t);
+
+ for(i=0; i<numswitches; i++)
+ { memcpy(&switches[i],buffer,sizeof(wall_t));
+ tilex = switches[i].tilex;
+ tiley = switches[i].tiley;
+ actorat[tilex][tiley]=&switches[i];
+ if (MAPSPOT(tilex,tiley,0) == 79) // On by default
+ {
+ if (!(switches[i].flags & FL_ON))
+ tilemap[tilex][tiley]--;
+ }
+ else if (switches[i].flags & FL_W_INVERTED) // Hi masked wall
+ {
+ maskedwallobj_t * lastmaskobj;
+
+ lastmaskobj=maskobjlist[tilemap[tilex][tiley]&0x3ff];
+ if (switches[i].flags & FL_ON)
+ lastmaskobj->toptexture++;
+ }
+ else if (switches[i].flags & FL_ON)
+ tilemap[tilex][tiley]++;
+ buffer += sizeof(wall_t);
+ touchindices[tilex][tiley] = lasttouch + 1;
+ lasttouch ++;
+ }
+ lastswitch=&switches[numswitches];
+
+}
+
+
+
+/*
+===============
+=
+= SpawnSwitchThingy
+=
+===============
+*/
+
+void SpawnSwitchThingy(int tilex, int tiley)
+{
+ lastswitch->flags |= FL_SWITCH;
+ lastswitch->which = WALL;
+ lastswitch->tilex = tilex;
+ lastswitch->tiley = tiley;
+ touchindices[tilex][tiley] = lasttouch + 1;
+ lasttouch ++;
+ actorat[tilex][tiley] = lastswitch;
+ lastswitch ++;
+
+}
+
+/*
+===============
+=
+= AnimateWalls
+=
+===============
+*/
+
+void AnimateWalls(void)
+{
+ int i;
+ animwall_t * aw;
+
+ if (DoPanicMapping()==true)
+ return;
+
+ for(i=0; i<MAXANIMWALLS; i++)
+ {
+ aw=&animwalls[i];
+ if (aw->active==0)
+ continue;
+ if (aw->ticcount <= 0)
+ {
+ if (aw->count < animwallsinfo[i].numanims)
+ {
+ aw->texture = aw->basetexture + aw->count;
+ aw->count++;
+ }
+ else
+ {
+ aw->texture = aw->basetexture;
+ aw->count = 1;
+ }
+
+ while (aw->ticcount<=0)
+ aw->ticcount+=animwallsinfo[i].tictime;
+ }
+ else
+ aw->ticcount -= tics;
+ }
+}
+
+
+#define M_ResetSprites(x) \
+ { if ((index == stat_dariantouch) && (!x->count))\
+ {x->shapenum = stats[index].picnum; \
+ x->count = 1; \
+ x->ticcount = stats[index].tictime; \
+ x->flags &= ~FL_BACKWARDS; \
+ x->flags &= ~FL_ACTIVE; \
+ } \
+ }
+
+
+
+
+void CheckCriticalStatics(void)
+{ respawn_t *rtemp,*ddt;
+ int i,stilex,stiley;
+ statobj_t*temp,*stat;
+
+ for(rtemp = firstrespawn; rtemp;)
+ { rtemp->ticcount --;
+ ddt = rtemp->next;
+
+ if (rtemp->ticcount <=0)
+ { int stype;
+
+ stilex = rtemp->tilex;
+ stiley = rtemp->tiley;
+
+ // if another weapon is there, nuke it
+ if (sprites[stilex][stiley])
+ { RemoveStatic(sprites[stilex][stiley]);
+ sprites[stilex][stiley] = NULL;
+ }
+
+ if (rtemp->itemnumber == stat_tntcrate)
+ {
+ RemoveStatic((statobj_t*)(rtemp->linked_to));
+ stype = stat_tntcrate;
+ }
+ else
+ {
+ for(i=0; i<NUMSTATS; i++)
+ {
+ if (rtemp->itemnumber == stats[i].type)
+ {
+ stype = i;
+ break;
+ }
+ }
+
+ }
+
+ SpawnStatic(stilex,stiley,stype,-1);
+ LASTSTAT->z = rtemp->spawnz;
+ LASTSTAT->flags |= FL_ABP;
+ MakeStatActive(LASTSTAT);
+ SpawnNewObj(stilex,stiley,&s_itemspawn1,inertobj);
+ SD_PlaySoundRTP(SD_RESPAWNSND,new->x,new->y);
+ new->flags |= FL_ABP;
+ MakeActive(new);
+ new->z = LASTSTAT->z;
+ RemoveRespawnStatic(rtemp);
+ }
+
+ rtemp = ddt;
+ }
+
+ for (temp = firstactivestat ; temp; )
+ { stat = temp->nextactive;
+
+ if (temp->flags & FL_SOLIDCOLOR)
+ { temp->ticcount--;
+ if (temp->ticcount<=0)
+ { temp->hitpoints+=SOLIDCOLORINCREMENT;
+ if (temp->hitpoints>MAXFIRECOLOR)
+ RemoveStatic(temp);
+ else
+ temp->ticcount = SOLIDCOLORTICTIME;
+ }
+ }
+ temp = stat;
+ }
+
+
+}
+
+
+
+/*
+===============
+=
+= DoSprites
+=
+===============
+*/
+
+void DoSprites(void)
+{ int index,i;
+ statobj_t *temp,*tempnext;
+
+
+#if (0)
+ Debug("\n");
+#endif
+ i=0;
+ for(temp = firstactivestat; temp;)
+ { tempnext = temp->nextactive;
+
+#if (0)
+ Debug("\nid: %d, shapenum: %d, numanims: %d",i++,temp->shapenum,temp->numanims);
+#endif
+
+ if ((temp->shapenum != NOTHING) && (temp->flags & FL_ACTIVE))
+ { index = temp->itemnumber;
+ temp->ticcount -= tics;
+ while (temp->ticcount <= 0)
+ { if (temp->count < temp->numanims)
+ { temp->shapenum = stats[index].picnum + temp->count;
+ if (index == stat_missmoke)
+ { RemoveStatic(temp);
+ break;
+ }
+
+ if (((index == stat_rubble) && (temp->count == 9)) ||
+ ((index == stat_woodfrag) && (temp->count == 13)) ||
+ ((index == stat_metalfrag) && (temp->count == 9)))
+ { temp->flags &= ~FL_ACTIVE;
+ break;
+ }
+
+ if (temp->flags & FL_BACKWARDS)
+ { temp->count--;
+ M_ResetSprites(temp);
+ }
+ else
+ temp->count ++;
+ }
+ else if (!(temp->flags & FL_BANDF))
+ { temp->shapenum = stats[index].picnum;
+ temp->count=1;
+ }
+ else
+ { temp->flags |= FL_BACKWARDS;
+ temp->count --;
+ }
+ temp->ticcount += stats[index].tictime;
+ }
+ }
+ temp = tempnext;
+
+ }
+
+}
+
+void SpawnStaticDamage(statobj_t * stat, int angle)
+{
+ GetNewActor ();
+ MakeActive(new);
+ NewState(new,&s_gunsmoke1);
+
+ new->obclass = inertobj;
+ new->which = ACTOR;
+ new->x = (stat->x)-(costable[angle]>>4);
+ new->y = (stat->y)+(sintable[angle]>>4);
+ new->z = (stat->z)+stats[stat->itemnumber].heightoffset;
+ new->drawx = new->x;
+ new->drawy = new->y;
+ new->tilex = (new->x >> TILESHIFT);
+ new->tiley = (new->y >> TILESHIFT);
+ new->dir = 0;
+ new->speed = 0;
+ new->flags = (FL_NEVERMARK|FL_ABP);
+ if ((new->x<=0) || (new->y<=0))
+ Error("SpawnStaticDamage: bad x,y itemnumber=%d\n",stat->itemnumber);
+}
--- /dev/null
+++ b/rott/rt_stat.h
@@ -1,0 +1,238 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// RT_STAT.C (static object functions)
+//
+//***************************************************************************
+#ifndef _rt_stat_public
+#define _rt_stat_public
+
+#include "rt_ted.h"
+
+#define MAXSWITCHES 64
+#define MAXANIMWALLS 17
+#define NUMSTATS 91
+
+typedef enum {
+ stat_ylight,
+ stat_rlight,
+ stat_glight,
+ stat_blight,
+ stat_chandelier,
+ stat_lamp,
+ stat_pedgoldkey,
+ stat_pedsilverkey,
+ stat_pedironkey,
+ stat_pedcrystalkey,
+ stat_gibs1,
+ stat_gibs2,
+ stat_gibs3,
+ stat_monkmeal,
+ stat_priestporridge,
+ stat_monkcrystal1,
+ stat_monkcrystal2,
+ stat_oneup,
+ stat_threeup,
+ stat_altbrazier1,
+ stat_altbrazier2,
+ stat_healingbasin,
+ stat_emptybasin,
+ stat_bat,
+ stat_knifestatue,
+ stat_twopistol,
+ stat_mp40,
+ stat_bazooka,
+ stat_firebomb,
+ stat_heatseeker,
+ stat_drunkmissile,
+ stat_firewall,
+ stat_splitmissile,
+ stat_kes,
+ stat_lifeitem1,
+ stat_lifeitem2,
+ stat_lifeitem3,
+ stat_lifeitem4,
+ stat_tntcrate,
+ stat_bonusbarrel,
+ stat_torch,
+ stat_floorfire,
+ stat_dipball1,
+ stat_dipball2,
+ stat_dipball3,
+ stat_touch1,
+ stat_touch2,
+ stat_touch3,
+ stat_touch4,
+ stat_dariantouch,
+ stat_scotthead,
+ stat_garb1,
+ stat_garb2,
+ stat_garb3,
+ stat_shit,
+ stat_grate,
+ stat_metalshards,
+ stat_emptypedestal,
+ stat_emptytable,
+ stat_stool,
+ stat_bcolumn,
+ stat_gcolumn,
+ stat_icolumn,
+ stat_tree,
+ stat_plant,
+ stat_urn,
+ stat_haystack,
+ stat_ironbarrel,
+ stat_heatgrate,
+ stat_standardpole,
+ stat_pit,
+ stat_godmode,
+ stat_dogmode,
+ stat_fleetfeet,
+ stat_elastic,
+ stat_mushroom,
+ stat_gasmask,
+ stat_bulletproof,
+ stat_asbesto,
+ stat_random,
+ stat_rubble,
+ stat_woodfrag,
+ stat_metalfrag,
+ stat_emptystatue,
+ stat_tomlarva,
+ stat_bullethole,
+ stat_collector,
+ stat_mine,
+ stat_missmoke,
+ stat_disk,
+ stat_badstatic
+} stat_t;
+
+typedef struct awall
+{
+ byte active;
+ byte count;
+ signed char ticcount;
+ int texture;
+ int basetexture;
+} animwall_t;
+
+typedef struct statstruct
+{
+ thingtype which;
+ byte tilex,tiley;
+ fixed x,y,z;
+ int shapenum;
+ unsigned flags;
+ signed char ticcount;
+ signed char ammo;
+ byte *visspot;
+ signed char count;
+ byte numanims;
+ stat_t itemnumber;
+ short int hitpoints;
+ short int whichstat;
+ short int areanumber;
+
+ long linked_to;
+ struct statstruct *statnext;
+ struct statstruct *statprev;
+ struct statstruct *nextactive;
+ struct statstruct *prevactive;
+
+} statobj_t;
+
+typedef struct respstruct
+{
+ byte tilex,tiley;
+ int ticcount;
+ stat_t itemnumber;
+ int spawnz;
+ struct respstruct *next;
+ struct respstruct *prev;
+ long linked_to;
+} respawn_t;
+
+
+typedef struct
+{
+ short heightoffset;
+ int picnum;
+ stat_t type;
+ unsigned flags;
+ byte tictime;
+ byte numanims;
+ byte hitpoints;
+ byte damage;
+ signed char ammo;
+} statinfo;
+
+extern statobj_t *lastactivestat,*firstactivestat;
+extern statobj_t *firstemptystat,*lastemptystat;
+extern int spritestart;
+extern wall_t switches[MAXSWITCHES],*lastswitch;
+
+extern respawn_t *firstrespawn,*lastrespawn;
+extern statobj_t *FIRSTSTAT,*LASTSTAT,*sprites[MAPSIZE][MAPSIZE];
+extern statinfo stats[NUMSTATS];
+extern dirtype diagonal[9][9];
+extern dirtype opposite[9];
+
+extern int statcount;
+
+extern int animwallstart;
+extern animwall_t animwalls[MAXANIMWALLS];
+
+
+void Set_NewZ_to_MapValue(fixed*,int,const char*,int,int);
+void RemoveFromFreeStaticList(statobj_t*);
+void CheckCriticalStatics(void);
+void ActivateLight(long);
+void DeactivateLight(long);
+void TurnOnLight(int,int);
+void TurnOffLight(int,int);
+void MakeStatActive(statobj_t*);
+void MakeStatInactive(statobj_t*);
+void AddStatic(statobj_t *);
+void RemoveStatic(statobj_t *);
+
+
+void SpawnSwitchThingy(int,int);
+void InitStaticList (void);
+void InitAnimatedWallList(void);
+void SetupAnimatedWall(int which);
+void SpawnStatic (int tilex, int tiley, int mtype, int zoffset);
+void SpawnSolidStatic (statobj_t * temp);
+void AnimateWalls(void);
+void DoSprites(void);
+
+void SaveAnimWalls(byte ** buf, int * size);
+void SaveStatics(byte ** buf, int * size);
+
+void LoadAnimWalls(byte * buf, int size);
+void LoadStatics(byte * buf, int size);
+
+void SaveSwitches(byte ** buf, int * size);
+void LoadSwitches(byte * buf, int size);
+
+void SpawnInertStatic (int x, int y, int z, int mtype);
+void SpawnStaticDamage(statobj_t * stat, int angle);
+
+#endif
--- /dev/null
+++ b/rott/rt_state.c
@@ -1,0 +1,2031 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "rt_def.h"
+#include "sprites.h"
+#include "states.h" //HEADER FILE FOR rt_state.c
+#include "rt_actor.h"
+#include "develop.h"
+#define SPRINGDELAY 3
+//MED
+#include "memcheck.h"
+
+
+extern void T_ReallyDead(objtype*ob);
+extern void T_PlayDead(objtype*ob);
+extern void T_Xylophone(objtype*ob);
+extern void T_BloodFall(objtype*ob);
+extern void SetShapeoffset(objtype*ob);
+extern void RespawnPlayerobj(objtype*ob);
+extern void T_ElevDisk(objtype*ob);
+extern void T_Plead(objtype*ob);
+extern void T_Blood(objtype*ob);
+extern void T_Convert(objtype*ob);
+extern void T_SlideDownScreen(objtype*ob);
+extern void T_End(objtype*ob);
+extern void T_Reset(objtype*ob);
+extern void T_CollectorWander(objtype*ob);
+extern void T_CollectorFindDoor(objtype*ob);
+extern void T_AutoPath(objtype*);
+extern void T_AutoRealign(objtype*);
+extern void T_AutoShootAlign(objtype*);
+extern void T_NME_SpinFire(objtype*);
+extern void MissileMovement(objtype*);
+extern void T_BatBlast(objtype*);
+extern void T_DeadWait(objtype*);
+extern void ActorMovement(objtype*);
+extern void T_Spring(objtype*);
+extern void T_SnakeFinale(objtype*);
+extern void T_Special(objtype*);
+extern void T_NME_Explode(objtype*);
+extern void T_Guts(objtype*);
+extern void T_Player(objtype*);
+extern void T_ParticleGenerate(objtype*);
+extern void T_Particle(objtype*);
+extern void T_SpawnSoul(objtype*);
+extern void T_NME_WindUp(objtype*);
+extern void T_NME_Attack(objtype*);
+extern void T_Saucer(objtype*);
+extern void T_NMErocket(objtype*);
+extern void T_NME_SpinAttack(objtype*);
+extern void T_NME_HeadShoot(objtype*);
+extern void T_CrushUp(objtype*);
+extern void T_CrushDown(objtype*);
+extern void T_HeinrichChase(objtype*);
+extern void T_KristLeft(objtype*);
+extern void T_KristRight(objtype*);
+extern void T_KristCheckFire(objtype*);
+extern void T_BoulderSpawn(objtype*);
+extern void T_BoulderDrop(objtype*);
+extern void T_BoulderMove(objtype*);
+extern void T_DarkmonkChase(objtype*);
+extern void T_DarkSnakeChase(objtype*);
+extern void T_DarkSnakeSpawn(objtype*);
+extern void A_DmonkAttack(objtype*);
+extern void T_GenericMove(objtype*);
+extern void T_Count(objtype*);
+extern void T_Spears(objtype*);
+extern void T_EsauSpears(objtype*);
+extern void T_Spring(objtype*);
+extern void T_4WayGunStand(objtype*);
+extern void A_GunShoot(objtype*);
+extern void A_4WayGunShoot(objtype*);
+extern void T_Attack(objtype*);
+extern void T_SnakePath(objtype*);
+extern void T_SnakeFindPath(objtype*);
+extern void T_DarkmonkLandAndFire(objtype*ob);
+extern void T_DarkmonkCharge(objtype*ob);
+extern void T_DarkmonkReact(objtype*ob);
+extern void T_BossExplosions(objtype*ob);
+
+
+/*
+=============================================================================
+
+ LOW GUARD (includes sneaky)
+
+=============================================================================
+*/
+
+
+statetype s_lowgrdstand = {true,SPR_LOWGRD_S1,0,T_Stand,0,&s_lowgrdstand};
+
+
+statetype s_lowgrdpath4 = {true,SPR_LOWGRD_W41,12,T_Path,0,&s_lowgrdpath1};
+statetype s_lowgrdpath3 = {true,SPR_LOWGRD_W31,12,T_Path,SF_CLOSE,&s_lowgrdpath4};
+statetype s_lowgrdpath2 = {true,SPR_LOWGRD_W21,12,T_Path,0,&s_lowgrdpath3};
+statetype s_lowgrdpath1 = {true,SPR_LOWGRD_W11,12,T_Path,SF_CLOSE,&s_lowgrdpath2};
+
+statetype s_lowgrdcollide = {false,SPR_LOWGRD_PAIN1,0,T_Collide,0,&s_lowgrdcollide};
+statetype s_lowgrdcollide2 = {false,SPR_LOWGRD_PAIN2,0,T_Collide,0,&s_lowgrdcollide2};
+
+
+//statetype s_lowgrduse2 = {true,SPR_LOWGRD_USE21,5,T_Use,0,&s_lowgrdpath1};
+//statetype s_lowgrduse1 = {true,SPR_LOWGRD_USE11,5,T_Use,0,&s_lowgrduse2};
+
+statetype s_lowgrdshoot4 = {false,SPR_LOWGRD_SHOOT4,8,ActorMovement,0,&s_lowgrdchase1};
+statetype s_lowgrdshoot3 = {false,SPR_LOWGRD_SHOOT3,5,A_Shoot,0,&s_lowgrdshoot4};
+statetype s_lowgrdshoot2 = {false,SPR_LOWGRD_SHOOT2,20,ActorMovement,0,&s_lowgrdshoot3};
+statetype s_lowgrdshoot1 = {false,SPR_LOWGRD_SHOOT1,6,ActorMovement,0,&s_lowgrdshoot2};
+
+statetype s_lowgrdchase4 = {true,SPR_LOWGRD_W41,12,T_Chase,0,&s_lowgrdchase1};
+statetype s_lowgrdchase3 = {true,SPR_LOWGRD_W31,12,T_Chase,SF_CLOSE,&s_lowgrdchase4};
+statetype s_lowgrdchase2 = {true,SPR_LOWGRD_W21,12,T_Chase,0,&s_lowgrdchase3};
+statetype s_lowgrdchase1 = {true,SPR_LOWGRD_W11,12,T_Chase,SF_CLOSE,&s_lowgrdchase2};
+
+
+
+statetype s_lowgrddead = {false,SPR_LOWGRD_DEAD,0,T_Collide,0,&s_lowgrddead};
+
+statetype s_lowgrddie4 = {false,SPR_LOWGRD_DIE4,8,T_Collide,0,&s_lowgrddead};
+statetype s_lowgrddie3 = {false,SPR_LOWGRD_DIE3,8,T_Collide,0,&s_lowgrddie4};
+statetype s_lowgrddie2 = {false,SPR_LOWGRD_DIE2,8,T_Collide,0,&s_lowgrddie3};
+statetype s_lowgrddie1 = {false,SPR_LOWGRD_DIE1,15,T_Collide,0,&s_lowgrddie2};
+
+//LT added
+
+
+statetype s_lowgrddie1rev = {false, SPR_LOWGRD_DIE1,8,T_Collide,0,&s_lowgrdstand};
+statetype s_lowgrddie2rev = {false, SPR_LOWGRD_DIE2,8,T_Collide,0,&s_lowgrddie1rev};
+statetype s_lowgrddie3rev = {false, SPR_LOWGRD_DIE3,8,T_Collide,0,&s_lowgrddie2rev};
+statetype s_lowgrddie4rev = {false, SPR_LOWGRD_DIE4,8,T_Collide,0,&s_lowgrddie3rev};
+statetype s_lowgrddeadrev = {false,SPR_LOWGRD_DEAD,0,T_Collide,0,&s_lowgrddie4rev};
+
+
+
+statetype s_lowgrdcrushed2 = {false,SPR_LOWGRD_DIE3,2,NULL,0,&s_lowgrddead};
+statetype s_lowgrdcrushed1 = {false,SPR_LOWGRD_DIE1,2,NULL,0,&s_lowgrdcrushed2};
+
+/************** Sneaky stuff *******************************************/
+
+statetype s_sneakydown = {false,SPR_SNEAKY_DEAD,0,T_Stand,0,&s_sneakydown};
+statetype s_sneakyrise4 = {false,SPR_RISE4,6,ActorMovement,0,&s_lowgrdchase1};
+statetype s_sneakyrise3 = {false,SPR_RISE3,6,ActorMovement,0,&s_sneakyrise4};
+statetype s_sneakyrise2 = {false,SPR_RISE2,6,ActorMovement,0,&s_sneakyrise3};
+statetype s_sneakyrise1 = {false,SPR_RISE1,6,ActorMovement,0,&s_sneakyrise2};
+
+
+/*
+=============================================================================
+
+ HIGH GUARD
+
+=============================================================================
+*/
+
+
+
+statetype s_highgrdstand = {true,SPR_HIGHGRD_S1,0,T_Stand,0,&s_highgrdstand};
+
+
+statetype s_highgrdpath4 = {true,SPR_HIGHGRD_W41,12,T_Path,0,&s_highgrdpath1};
+statetype s_highgrdpath3 = {true,SPR_HIGHGRD_W31,12,T_Path,SF_CLOSE,&s_highgrdpath4};
+statetype s_highgrdpath2 = {true,SPR_HIGHGRD_W21,12,T_Path,0,&s_highgrdpath3};
+statetype s_highgrdpath1 = {true,SPR_HIGHGRD_W11,12,T_Path,SF_CLOSE,&s_highgrdpath2};
+
+
+//statetype s_highgrdpain1 = {2,SPR_HIGHGRD_PAIN1,10,T_Collide,0,&s_highgrdchase1};
+//statetype s_highgrdpain2 = {2,SPR_HIGHGRD_PAIN2,10,T_Collide,0,&s_highgrdchase1};
+
+
+statetype s_highgrdcollide = {false,SPR_HIGHGRD_PAIN1,0,T_Collide,0,&s_highgrdcollide};
+statetype s_highgrdcollide2 = {false,SPR_HIGHGRD_PAIN2,0,T_Collide,0,&s_highgrdcollide2};
+
+
+//statetype s_highgrduse2 = {true,SPR_HIGHGRD_USE21,10,T_Use,0,&s_highgrdpath1};
+//statetype s_highgrduse1 = {true,SPR_HIGHGRD_USE11,10,T_Use,0,&s_highgrduse2};
+
+
+statetype s_highgrdshoot4 = {false,SPR_HIGHGRD_SHOOT4,3,A_Repeat,0,&s_highgrdshoot3};
+statetype s_highgrdshoot3 = {false,SPR_HIGHGRD_SHOOT3,5,A_Shoot,0,&s_highgrdshoot4};
+statetype s_highgrdshoot2 = {false,SPR_HIGHGRD_SHOOT2,6,ActorMovement,0,&s_highgrdshoot3};
+statetype s_highgrdshoot1 = {false,SPR_HIGHGRD_SHOOT1,6,ActorMovement,0,&s_highgrdshoot2};
+
+
+statetype s_highgrdchase4 = {true,SPR_HIGHGRD_W41,12,T_Chase,0,&s_highgrdchase1};
+statetype s_highgrdchase3 = {true,SPR_HIGHGRD_W31,12,T_Chase,SF_CLOSE,&s_highgrdchase4};
+statetype s_highgrdchase2 = {true,SPR_HIGHGRD_W21,12,T_Chase,0,&s_highgrdchase3};
+statetype s_highgrdchase1 = {true,SPR_HIGHGRD_W11,12,T_Chase,SF_CLOSE,&s_highgrdchase2};
+
+
+statetype s_highgrddead = {false,SPR_HIGHGRD_DEAD,0,T_Collide,0,&s_highgrddead};
+statetype s_highgrddie5 = {false,SPR_HIGHGRD_DIE5,0,T_Collide,0,&s_highgrddead};
+statetype s_highgrddie4 = {false,SPR_HIGHGRD_DIE4,8,T_Collide,0,&s_highgrddie5};
+statetype s_highgrddie3 = {false,SPR_HIGHGRD_DIE3,8,T_Collide,0,&s_highgrddie4};
+statetype s_highgrddie2 = {false,SPR_HIGHGRD_DIE2,8,T_Collide,0,&s_highgrddie3};
+statetype s_highgrddie1 = {false,SPR_HIGHGRD_DIE1,8,T_Collide,0,&s_highgrddie2};
+
+statetype s_highgrddie1rev = {false,SPR_HIGHGRD_DIE1,8,T_Collide,0,&s_highgrdstand};
+statetype s_highgrddie2rev = {false,SPR_HIGHGRD_DIE2,8,T_Collide,0,&s_highgrddie1rev};
+statetype s_highgrddie3rev = {false,SPR_HIGHGRD_DIE3,8,T_Collide,0,&s_highgrddie2rev};
+statetype s_highgrddie4rev = {false,SPR_HIGHGRD_DIE4,8,T_Collide,0,&s_highgrddie3rev};
+statetype s_highgrddie5rev = {false,SPR_HIGHGRD_DIE5,0,T_Collide,0,&s_highgrddie4rev};
+
+statetype s_highgrdcrushed2 = {false,SPR_HIGHGRD_DIE3,2,NULL,0,&s_highgrddead};
+statetype s_highgrdcrushed1 = {false,SPR_HIGHGRD_DIE1,2,NULL,0,&s_highgrdcrushed2};
+
+/*
+===========================================================================
+
+ STRIKEGUARD
+
+===========================================================================
+*/
+
+
+statetype s_strikestand = {true,SPR_STRIKE_S1,0,T_Stand,0,&s_strikestand};
+
+
+statetype s_strikepath4 = {true,SPR_STRIKE_W41,12,T_Path,0,&s_strikepath1};
+statetype s_strikepath3 = {true,SPR_STRIKE_W31,12,T_Path,SF_CLOSE,&s_strikepath4};
+statetype s_strikepath2 = {true,SPR_STRIKE_W21,12,T_Path,0,&s_strikepath3};
+statetype s_strikepath1 = {true,SPR_STRIKE_W11,12,T_Path,SF_CLOSE,&s_strikepath2};
+
+statetype s_strikecollide = {false,SPR_STRIKE_PAIN1,0,T_Collide,0,&s_strikecollide};
+statetype s_strikecollide2 = {false,SPR_STRIKE_PAIN2,0,T_Collide,0,&s_strikecollide2};
+
+statetype s_strikeshoot4 = {false,SPR_STRIKE_SHOOT4,6,ActorMovement,0,&s_strikechase1};
+statetype s_strikeshoot3 = {false,SPR_STRIKE_SHOOT3,6,ActorMovement,0,&s_strikeshoot4};
+statetype s_strikeshoot2 = {false,SPR_STRIKE_SHOOT2,5,A_Shoot,0,&s_strikeshoot3};
+statetype s_strikeshoot1 = {false,SPR_STRIKE_SHOOT1,20,ActorMovement,0,&s_strikeshoot2};
+
+
+//statetype s_strikeuse2 = {true,SPR_STRIKE_USE21,10,T_Use,0,&s_strikechase1};
+//statetype s_strikeuse1 = {true,SPR_STRIKE_USE11,10,NULL,0,&s_strikeuse2};
+
+statetype s_strikewait = {true,SPR_STRIKE_S1,35,NULL,0,&s_strikechase1};
+
+statetype s_strikerollright6 = {false,SPR_STRIKE_LROLL6,8,T_Roll,0,&s_strikeshoot1};
+statetype s_strikerollright5 = {false,SPR_STRIKE_LROLL5,8,T_Roll,0,&s_strikerollright6};
+statetype s_strikerollright4 = {false,SPR_STRIKE_LROLL4,7,T_Reset,0,&s_strikerollright5};
+statetype s_strikerollright3 = {false,SPR_STRIKE_LROLL3,7,T_Roll,0,&s_strikerollright4};
+statetype s_strikerollright2 = {false,SPR_STRIKE_LROLL2,7,T_Roll,0,&s_strikerollright3};
+statetype s_strikerollright1 = {false,SPR_STRIKE_LROLL1,5,T_Roll,0,&s_strikerollright2};
+
+
+
+statetype s_strikerollleft6 = {false,SPR_STRIKE_RROLL6,8,T_Roll,0,&s_strikeshoot1};
+statetype s_strikerollleft5 = {false,SPR_STRIKE_RROLL5,8,T_Roll,0,&s_strikerollleft6};
+statetype s_strikerollleft4 = {false,SPR_STRIKE_RROLL4,7,T_Reset,0,&s_strikerollleft5};
+statetype s_strikerollleft3 = {false,SPR_STRIKE_RROLL3,7,T_Roll,0,&s_strikerollleft4};
+statetype s_strikerollleft2 = {false,SPR_STRIKE_RROLL2,7,T_Roll,0,&s_strikerollleft3};
+statetype s_strikerollleft1 = {false,SPR_STRIKE_RROLL1,5,T_Roll,0,&s_strikerollleft2};
+
+
+statetype s_strikechase4 = {true,SPR_STRIKE_W41,12,T_Chase,0,&s_strikechase1};
+statetype s_strikechase3 = {true,SPR_STRIKE_W31,12,T_Chase,SF_CLOSE,&s_strikechase4};
+statetype s_strikechase2 = {true,SPR_STRIKE_W21,12,T_Chase,0,&s_strikechase3};
+statetype s_strikechase1 = {true,SPR_STRIKE_W11,12,T_Chase,SF_CLOSE,&s_strikechase2};
+
+
+statetype s_strikedead3 = {false,SPR_STRIKE_DEAD3,0,T_Collide,0,&s_strikedead3};
+statetype s_strikedead2 = {false,SPR_STRIKE_DEAD2,0,T_Collide,0,&s_strikedead3};
+statetype s_strikedead = {false,SPR_STRIKE_DEAD1,7,T_Collide,0,&s_strikedead2};
+statetype s_strikedie4 = {false,SPR_STRIKE_DIE4,7,T_Collide,0,&s_strikedead};
+statetype s_strikedie3 = {false,SPR_STRIKE_DIE3,7,T_Collide,0,&s_strikedie4};
+statetype s_strikedie2 = {false,SPR_STRIKE_DIE2,7,T_Collide,0,&s_strikedie3};
+statetype s_strikedie1 = {false,SPR_STRIKE_DIE1,7,T_Collide,0,&s_strikedie2};
+
+
+statetype s_strikedie1rev = {false,SPR_STRIKE_DIE1,7,T_Collide,0,&s_strikestand};
+statetype s_strikedie2rev = {false,SPR_STRIKE_DIE2,7,T_Collide,0,&s_strikedie1rev};
+statetype s_strikedie3rev = {false,SPR_STRIKE_DIE3,7,T_Collide,0,&s_strikedie2rev};
+statetype s_strikedie4rev = {false,SPR_STRIKE_DIE4,7,T_Collide,0,&s_strikedie3rev};
+
+statetype s_strikecrushed2 = {false,SPR_STRIKE_DIE3,2,NULL,0,&s_strikedead};
+statetype s_strikecrushed1 = {false,SPR_STRIKE_DIE1,2,NULL,0,&s_strikecrushed2};
+
+/*
+============================================================================
+
+ LIGHTNING GUARD
+
+============================================================================
+*/
+
+statetype s_blitzstand = {true,SPR_BLITZ_S1,0,T_Stand,0,&s_blitzstand};
+
+statetype s_blitzpath4 = {true,SPR_BLITZ_W41,12,T_Path,0,&s_blitzpath1};
+statetype s_blitzpath3 = {true,SPR_BLITZ_W31,12,T_Path,SF_CLOSE,&s_blitzpath4};
+statetype s_blitzpath2 = {true,SPR_BLITZ_W21,12,T_Path,0,&s_blitzpath3};
+statetype s_blitzpath1 = {true,SPR_BLITZ_W11,12,T_Path,SF_CLOSE,&s_blitzpath2};
+
+
+
+statetype s_blitzcollide = {false,SPR_BLITZ_PAIN1,0,T_Collide,0,&s_blitzcollide};
+statetype s_blitzcollide2 = {false,SPR_BLITZ_PAIN2,0,T_Collide,0,&s_blitzcollide2};
+
+statetype s_blitzshoot4 = {false,SPR_BLITZ_SHOOT4,10,ActorMovement,0,&s_blitzchase1};
+statetype s_blitzshoot3 = {false,SPR_BLITZ_SHOOT3,10,ActorMovement,0,&s_blitzshoot4};
+statetype s_blitzshoot2 = {false,SPR_BLITZ_SHOOT2,5,A_Shoot,0,&s_blitzshoot3};
+statetype s_blitzshoot1 = {false,SPR_BLITZ_SHOOT1,10,ActorMovement,0,&s_blitzshoot2};
+
+statetype s_blitzrise4 = {false,SPR_BLITZ_RISE4,8,ActorMovement,0,&s_blitzchase1};
+statetype s_blitzrise3 = {false,SPR_BLITZ_RISE3,8,ActorMovement,0,&s_blitzrise4};
+statetype s_blitzrise2 = {false,SPR_BLITZ_RISE2,8,ActorMovement,0,&s_blitzrise3};
+statetype s_blitzrise1 = {false,SPR_BLITZ_RISE1,8,ActorMovement,0,&s_blitzrise2};
+
+statetype s_blitzuse = {true,SPR_BLITZ_USE,10,T_Use,0,&s_blitzpath1};
+
+
+statetype s_blitzsteal2 = {true,SPR_BLITZ_STEAL2,20,A_Steal,0,&s_blitzchase1};
+statetype s_blitzsteal1 = {true,SPR_BLITZ_STEAL1,20,ActorMovement,0,&s_blitzsteal2};
+
+statetype s_blitzchase4 = {true,SPR_BLITZ_W41,12,T_Chase,0,&s_blitzchase1};
+statetype s_blitzchase3 = {true,SPR_BLITZ_W31,12,T_Chase,SF_CLOSE,&s_blitzchase4};
+statetype s_blitzchase2 = {true,SPR_BLITZ_W21,12,T_Chase,0,&s_blitzchase3};
+statetype s_blitzchase1 = {true,SPR_BLITZ_W11,12,T_Chase,SF_CLOSE,&s_blitzchase2};
+
+
+statetype s_blitzdead2 = {false,SPR_BLITZ_DEAD2,0,T_Collide,0,&s_blitzdead2};
+statetype s_blitzdead = {false,SPR_BLITZ_DEAD1,0,T_Collide,0,&s_blitzdead2};
+statetype s_blitzdie4 = {false,SPR_BLITZ_DIE4,7,T_Collide,0,&s_blitzdead};
+statetype s_blitzdie3 = {false,SPR_BLITZ_DIE3,7,T_Collide,0,&s_blitzdie4};
+statetype s_blitzdie2 = {false,SPR_BLITZ_DIE2,7,T_Collide,0,&s_blitzdie3};
+statetype s_blitzdie1 = {false,SPR_BLITZ_DIE1,7,T_Collide,0,&s_blitzdie2};
+
+statetype s_blitzdie1rev = {false,SPR_BLITZ_DIE1,7,T_Collide,0,&s_blitzstand};
+statetype s_blitzdie2rev = {false,SPR_BLITZ_DIE2,7,T_Collide,0,&s_blitzdie1rev};
+statetype s_blitzdie3rev = {false,SPR_BLITZ_DIE3,7,T_Collide,0,&s_blitzdie2rev};
+statetype s_blitzdie4rev = {false,SPR_BLITZ_DIE4,7,T_Collide,0,&s_blitzdie3rev};
+
+statetype s_blitzstruggledead = {false,SPR_BLITZ_RISE2,0,T_Collide,0,&s_blitzstruggledead};
+statetype s_blitzstruggledie1 = {false,SPR_BLITZ_RISE2,20,T_ReallyDead,0,&s_blitzstruggledead};
+
+
+statetype s_blitzfakedead = {false,SPR_BLITZ_DEAD2,0,T_PlayDead,SF_FAKING,&s_blitzfakedead};
+statetype s_blitzfakedie3 = {false,SPR_BLITZ_DEAD1,5,ActorMovement,0,&s_blitzfakedead};
+statetype s_blitzfakedie2 = {false,SPR_BLITZ_DIE4,5,ActorMovement,0,&s_blitzfakedie3};
+statetype s_blitzfakedie1 = {false,SPR_BLITZ_DIE3,5,ActorMovement,0,&s_blitzfakedie2};
+
+
+statetype s_blitzcrushed2 = {false,SPR_BLITZ_DIE3,2,NULL,0,&s_blitzdead};
+statetype s_blitzcrushed1 = {false,SPR_BLITZ_DIE1,2,NULL,0,&s_blitzcrushed2};
+
+statetype s_blitzplead11 = {false,SPR_BLITZ_PLEAD11,0,T_Collide,0,&s_blitzplead11};
+statetype s_blitzplead10 = {false,SPR_BLITZ_PLEAD10,6,NULL,0,&s_blitzplead11};
+statetype s_blitzplead9 = {false,SPR_BLITZ_PLEAD9,6,NULL,0,&s_blitzplead10};
+statetype s_blitzplead8 = {false,SPR_BLITZ_PLEAD8,6,NULL,0,&s_blitzplead9};
+statetype s_blitzplead7 = {false,SPR_BLITZ_PLEAD7,6,NULL,0,&s_blitzplead8};
+
+
+
+
+statetype s_blitzaplead4 = {false,SPR_BLITZ_PLEAD4,5,T_Plead,SF_DOWN,&s_blitzplead3};
+statetype s_blitzaplead5 = {false,SPR_BLITZ_PLEAD5,5,T_Plead,SF_DOWN,&s_blitzaplead4};
+
+statetype s_blitzplead6 = {false,SPR_BLITZ_PLEAD6,5,T_Plead,SF_DOWN,&s_blitzaplead5};
+statetype s_blitzplead5 = {false,SPR_BLITZ_PLEAD5,5,T_Plead,SF_DOWN,&s_blitzplead6};
+statetype s_blitzplead4 = {false,SPR_BLITZ_PLEAD4,5,T_Plead,SF_DOWN,&s_blitzplead5};
+statetype s_blitzplead3 = {false,SPR_BLITZ_PLEAD3,5,T_Plead,SF_DOWN,&s_blitzplead4};
+statetype s_blitzplead2 = {false,SPR_BLITZ_PLEAD2,6,ActorMovement,0,&s_blitzplead3};
+statetype s_blitzplead1 = {false,SPR_BLITZ_PLEAD1,6,ActorMovement,0,&s_blitzplead2};
+
+
+
+/*
+============================================================================
+
+ TRIAD ENFORCERS
+
+============================================================================
+*/
+
+
+statetype s_enforcerstand = {true,SPR_ENFORCER_S1,0,T_Stand,0,&s_enforcerstand};
+
+
+statetype s_enforcerpath4 = {true,SPR_ENFORCER_W41,12,T_Path,0,&s_enforcerpath1};
+statetype s_enforcerpath3 = {true,SPR_ENFORCER_W31,12,T_Path,SF_CLOSE,&s_enforcerpath4};
+statetype s_enforcerpath2 = {true,SPR_ENFORCER_W21,12,T_Path,0,&s_enforcerpath3};
+statetype s_enforcerpath1 = {true,SPR_ENFORCER_W11,12,T_Path,SF_CLOSE,&s_enforcerpath2};
+
+
+statetype s_enforcerchase4 = {true,SPR_ENFORCER_W41,12,T_Chase,0,&s_enforcerchase1};
+statetype s_enforcerchase3 = {true,SPR_ENFORCER_W31,12,T_Chase,SF_CLOSE,&s_enforcerchase4};
+statetype s_enforcerchase2 = {true,SPR_ENFORCER_W21,12,T_Chase,0,&s_enforcerchase3};
+statetype s_enforcerchase1 = {true,SPR_ENFORCER_W11,12,T_Chase,SF_CLOSE,&s_enforcerchase2};
+
+statetype s_enforcercollide = {false,SPR_ENFORCER_PAIN1,0,T_Collide,0,&s_enforcercollide};
+statetype s_enforcercollide2 = {false,SPR_ENFORCER_PAIN2,0,T_Collide,0,&s_enforcercollide2};
+
+
+//statetype s_enforceruse2 = {true,SPR_ENFORCER_USE21,10,T_Use,0,&s_enforcerchase1};
+//statetype s_enforceruse1 = {true,SPR_ENFORCER_USE11,10,T_Use,0,&s_enforceruse2};
+
+statetype s_enforcershoot4 = {false,SPR_ENFORCER_SHOOT4,6,A_Repeat,0,&s_enforcershoot3};
+statetype s_enforcershoot3 = {false,SPR_ENFORCER_SHOOT3,6,A_Shoot,0,&s_enforcershoot4};
+statetype s_enforcershoot2 = {false,SPR_ENFORCER_SHOOT2,6,ActorMovement,0,&s_enforcershoot3};
+statetype s_enforcershoot1 = {false,SPR_ENFORCER_SHOOT1,6,ActorMovement,0,&s_enforcershoot2};
+
+
+statetype s_enforcerthrow8 = {false,SPR_ENFORCER_THROW8,10,ActorMovement,0,&s_enforcerchase1};
+statetype s_enforcerthrow7 = {false,SPR_ENFORCER_THROW7,10,ActorMovement,0,&s_enforcerthrow8};
+statetype s_enforcerthrow6 = {false,SPR_ENFORCER_THROW6,10,ActorMovement,0,&s_enforcerthrow7};
+statetype s_enforcerthrow5 = {false,SPR_ENFORCER_THROW5,10,A_MissileWeapon,0,&s_enforcerthrow6};
+statetype s_enforcerthrow4 = {false,SPR_ENFORCER_THROW4,10,ActorMovement,0,&s_enforcerthrow5};
+statetype s_enforcerthrow3 = {false,SPR_ENFORCER_THROW3,10,ActorMovement,0,&s_enforcerthrow4};
+statetype s_enforcerthrow2 = {false,SPR_ENFORCER_THROW2,10,ActorMovement,0,&s_enforcerthrow3};
+statetype s_enforcerthrow1 = {false,SPR_ENFORCER_THROW1,10,ActorMovement,0,&s_enforcerthrow2};
+
+
+
+statetype s_grenade10 = {false,SPR_ENFORCER_GR10,2,T_Projectile,0,&s_grenade1};
+statetype s_grenade9 = {false,SPR_ENFORCER_GR9,2,T_Projectile,0,&s_grenade10};
+statetype s_grenade8 = {false,SPR_ENFORCER_GR8,2,T_Projectile,0,&s_grenade9};
+statetype s_grenade7 = {false,SPR_ENFORCER_GR7,2,T_Projectile,0,&s_grenade8};
+statetype s_grenade6 = {false,SPR_ENFORCER_GR6,2,T_Projectile,0,&s_grenade7};
+statetype s_grenade5 = {false,SPR_ENFORCER_GR5,2,T_Projectile,0,&s_grenade6};
+statetype s_grenade4 = {false,SPR_ENFORCER_GR4,2,T_Projectile,0,&s_grenade5};
+statetype s_grenade3 = {false,SPR_ENFORCER_GR3,2,T_Projectile,0,&s_grenade4};
+statetype s_grenade2 = {false,SPR_ENFORCER_GR2,2,T_Projectile,0,&s_grenade3};
+statetype s_grenade1 = {false,SPR_ENFORCER_GR1,2,T_Projectile,0,&s_grenade2};
+
+statetype s_grenade_fall6 = {false,SPR_ENFORCER_FALL6,6,T_Projectile,0,&s_grenade_fall6};
+statetype s_grenade_fall5 = {false,SPR_ENFORCER_FALL5,6,T_Projectile,0,&s_grenade_fall6};
+statetype s_grenade_fall4 = {false,SPR_ENFORCER_FALL4,6,T_Projectile,0,&s_grenade_fall5};
+statetype s_grenade_fall3 = {false,SPR_ENFORCER_FALL3,6,T_Projectile,0,&s_grenade_fall4};
+statetype s_grenade_fall2 = {false,SPR_ENFORCER_FALL1,6,T_Projectile,0,&s_grenade_fall3};
+statetype s_grenade_fall1 = {false,SPR_ENFORCER_FALL1,6,T_Projectile,0,&s_grenade_fall2};
+
+statetype s_grenadehit3 = {false,SPR_GRENADE_HIT3,5,NULL,0,NULL};
+statetype s_grenadehit2 = {false,SPR_GRENADE_HIT2,5,NULL,0,&s_grenadehit3};
+statetype s_grenadehit1 = {false,SPR_GRENADE_HIT1,5,NULL,0,&s_grenadehit2};
+
+
+statetype s_enforcerdead = {false,SPR_ENFORCER_DEAD,0,T_Collide,0,&s_enforcerdead};
+statetype s_enforcerdie4 = {false,SPR_ENFORCER_DIE4,7,T_Collide,0,&s_enforcerdead};
+statetype s_enforcerdie3 = {false,SPR_ENFORCER_DIE3,7,T_Collide,0,&s_enforcerdie4};
+statetype s_enforcerdie2 = {false,SPR_ENFORCER_DIE2,7,T_Collide,0,&s_enforcerdie3};
+statetype s_enforcerdie1 = {false,SPR_ENFORCER_DIE1,7,T_Collide,0,&s_enforcerdie2};
+
+statetype s_enforcerdie1rev = {false,SPR_ENFORCER_DIE1,7,T_Collide,0,&s_enforcerstand};
+statetype s_enforcerdie2rev = {false,SPR_ENFORCER_DIE2,7,T_Collide,0,&s_enforcerdie1rev};
+statetype s_enforcerdie3rev = {false,SPR_ENFORCER_DIE3,7,T_Collide,0,&s_enforcerdie2rev};
+statetype s_enforcerdie4rev = {false,SPR_ENFORCER_DIE4,7,T_Collide,0,&s_enforcerdie3rev};
+
+
+statetype s_enforcercrushed2 = {false,SPR_ENFORCER_DIE3,2,NULL,0,&s_enforcerdead};
+statetype s_enforcercrushed1 = {false,SPR_ENFORCER_DIE1,2,NULL,0,&s_enforcercrushed2};
+
+/*
+============================================================================
+
+ ROBOT GUARD
+
+============================================================================
+*/
+
+
+
+statetype s_robogrdstand = {16,SPR_ROBOGRD_S11,0,T_Stand,0,&s_robogrdstand};
+
+statetype s_robogrdpath1 = {16,SPR_ROBOGRD_S11,20,T_AutoPath,0,&s_robogrdpath1};
+
+statetype s_robowait = {16,SPR_ROBOGRD_S11,0,NULL,0,&s_robowait};
+statetype s_roborealign = {16,SPR_ROBOGRD_S11,0,T_AutoRealign,0,&s_roborealign};
+statetype s_roboalign = {16,SPR_ROBOGRD_S11,0,T_AutoShootAlign,0,&s_roboalign};
+
+statetype s_robogrdshoot1 = {false,SPR_ROBOGRD_S11,35,A_MissileWeapon,0,&s_roborealign};
+
+statetype s_robogrdshuriken4 = {false,SPR_ROBOGRD_SHURIKEN4,4,T_Projectile,0,&s_robogrdshuriken1};
+statetype s_robogrdshuriken3 = {false,SPR_ROBOGRD_SHURIKEN3,4,T_Projectile,0,&s_robogrdshuriken4};
+statetype s_robogrdshuriken2 = {false,SPR_ROBOGRD_SHURIKEN2,4,T_Projectile,0,&s_robogrdshuriken3};
+statetype s_robogrdshuriken1 = {false,SPR_ROBOGRD_SHURIKEN1,4,T_Projectile,0,&s_robogrdshuriken2};
+
+statetype s_shurikenhit3 = {false,SPR_SHURIKEN_HIT3,5,NULL,0,NULL};
+statetype s_shurikenhit2 = {false,SPR_SHURIKEN_HIT2,5,NULL,0,&s_shurikenhit3};
+statetype s_shurikenhit1 = {false,SPR_SHURIKEN_HIT1,5,NULL,0,&s_shurikenhit2};
+
+statetype s_robogrdcollide = {16,SPR_ROBOGRD_S11,0,T_Collide,0,&s_robogrdcollide};
+statetype s_robogrdcollide2 = {16,SPR_ROBOGRD_S11,0,T_Collide,0,&s_robogrdcollide2};
+
+//statetype s_robogrdchase1 = {16,SPR_ROBOGRD_S11,10,T_RoboChase,0,&s_robogrdchase1};
+
+statetype s_robogrddead = {false,ROBOGRDDEAD,0,T_Collide,0,&s_robogrddead};
+statetype s_robogrddie9 = {false,ROBOGRDDIE9,3,T_Collide,0,&s_robogrddead};
+statetype s_robogrddie8 = {false,ROBOGRDDIE8,3,T_Collide,0,&s_robogrddie9};
+statetype s_robogrddie7 = {false,ROBOGRDDIE7,3,T_Collide,0,&s_robogrddie8};
+statetype s_robogrddie6 = {false,ROBOGRDDIE6,3,T_Collide,0,&s_robogrddie7};
+statetype s_robogrddie5 = {false,ROBOGRDDIE5,3,T_Collide,0,&s_robogrddie6};
+statetype s_robogrddie4 = {false,ROBOGRDDIE4,3,T_Collide,0,&s_robogrddie5};
+statetype s_robogrddie3 = {false,ROBOGRDDIE3,3,T_Collide,0,&s_robogrddie4};
+statetype s_robogrddie2 = {false,ROBOGRDDIE2,3,T_Collide,0,&s_robogrddie3};
+statetype s_robogrddie1 = {false,ROBOGRDDIE1,3,T_Collide,0,&s_robogrddie2};
+
+
+statetype s_bstar4 = {false,SPR_BSTAR4,1,T_Projectile,0,&s_bstar1};
+statetype s_bstar3 = {false,SPR_BSTAR3,1,T_Projectile,0,&s_bstar4};
+statetype s_bstar2 = {false,SPR_BSTAR2,1,T_Projectile,0,&s_bstar3};
+statetype s_bstar1 = {false,SPR_BSTAR1,1,T_Projectile,0,&s_bstar2};
+
+
+
+/*
+==========================================================================
+=
+= Explosions
+=
+==========================================================================
+*/
+
+statetype s_altexplosion10 = {false,SPR_EXPLOSION19,3,NULL,0,NULL};
+statetype s_altexplosion9 = {false,SPR_EXPLOSION17,3,NULL,0,&s_altexplosion10};
+statetype s_altexplosion8 = {false,SPR_EXPLOSION15,3,NULL,0,&s_altexplosion9};
+statetype s_altexplosion7 = {false,SPR_EXPLOSION13,3,NULL,0,&s_altexplosion8};
+statetype s_altexplosion6 = {false,SPR_EXPLOSION11,3,NULL,0,&s_altexplosion7};
+statetype s_altexplosion5 = {false,SPR_EXPLOSION9,3,NULL,0,&s_altexplosion6};
+statetype s_altexplosion4 = {false,SPR_EXPLOSION7,3,NULL,0,&s_altexplosion5};
+statetype s_altexplosion3 = {false,SPR_EXPLOSION5,3,NULL,0,&s_altexplosion4};
+statetype s_altexplosion2 = {false,SPR_EXPLOSION3,3,T_Explosion,0,&s_altexplosion3};
+statetype s_altexplosion1 = {false,SPR_EXPLOSION1,3,NULL,0,&s_altexplosion2};
+
+
+
+
+
+statetype s_explosion20 = {false,SPR_EXPLOSION20,2,NULL,0,NULL};
+statetype s_explosion19 = {false,SPR_EXPLOSION19,2,NULL,0,&s_explosion20};
+statetype s_explosion18 = {false,SPR_EXPLOSION18,2,NULL,0,&s_explosion19};
+statetype s_explosion17 = {false,SPR_EXPLOSION17,2,NULL,0,&s_explosion18};
+statetype s_explosion16 = {false,SPR_EXPLOSION16,2,NULL,0,&s_explosion17};
+statetype s_explosion15 = {false,SPR_EXPLOSION15,2,NULL,0,&s_explosion16};
+statetype s_explosion14 = {false,SPR_EXPLOSION14,2,NULL,0,&s_explosion15};
+statetype s_explosion13 = {false,SPR_EXPLOSION13,2,NULL,0,&s_explosion14};
+statetype s_explosion12 = {false,SPR_EXPLOSION12,2,NULL,0,&s_explosion13};
+statetype s_explosion11 = {false,SPR_EXPLOSION11,2,NULL,0,&s_explosion12};
+statetype s_explosion10 = {false,SPR_EXPLOSION10,2,NULL,0,&s_explosion11};
+statetype s_explosion9 = {false,SPR_EXPLOSION9,2,NULL,0,&s_explosion10};
+statetype s_explosion8 = {false,SPR_EXPLOSION8,2,NULL,0,&s_explosion9};
+statetype s_explosion7 = {false,SPR_EXPLOSION7,2,NULL,0,&s_explosion8};
+statetype s_explosion6 = {false,SPR_EXPLOSION6,2,NULL,0,&s_explosion7};
+statetype s_explosion5 = {false,SPR_EXPLOSION5,2,NULL,0,&s_explosion6};
+statetype s_explosion4 = {false,SPR_EXPLOSION4,2,NULL,0,&s_explosion5};
+statetype s_explosion3 = {false,SPR_EXPLOSION3,2,T_Explosion,0,&s_explosion4};
+statetype s_explosion2 = {false,SPR_EXPLOSION2,2,NULL,0,&s_explosion3};
+statetype s_explosion1 = {false,SPR_EXPLOSION1,2,NULL,0,&s_explosion2};
+
+
+
+statetype s_grexplosion20 = {false,SPR_GROUNDEXPL20,2,T_Special,0,NULL};
+statetype s_grexplosion19 = {false,SPR_GROUNDEXPL19,2,NULL,0,&s_grexplosion20};
+statetype s_grexplosion18 = {false,SPR_GROUNDEXPL18,2,NULL,0,&s_grexplosion19};
+statetype s_grexplosion17 = {false,SPR_GROUNDEXPL17,2,NULL,0,&s_grexplosion18};
+statetype s_grexplosion16 = {false,SPR_GROUNDEXPL16,2,NULL,0,&s_grexplosion17};
+statetype s_grexplosion15 = {false,SPR_GROUNDEXPL15,2,NULL,0,&s_grexplosion16};
+statetype s_grexplosion14 = {false,SPR_GROUNDEXPL14,2,NULL,0,&s_grexplosion15};
+statetype s_grexplosion13 = {false,SPR_GROUNDEXPL13,2,NULL,0,&s_grexplosion14};
+statetype s_grexplosion12 = {false,SPR_GROUNDEXPL12,2,NULL,0,&s_grexplosion13};
+statetype s_grexplosion11 = {false,SPR_GROUNDEXPL11,2,NULL,0,&s_grexplosion12};
+statetype s_grexplosion10 = {false,SPR_GROUNDEXPL10,2,NULL,0,&s_grexplosion11};
+statetype s_grexplosion9 = {false,SPR_GROUNDEXPL9,2,NULL,0,&s_grexplosion10};
+statetype s_grexplosion8 = {false,SPR_GROUNDEXPL8,2,NULL,0,&s_grexplosion9};
+statetype s_grexplosion7 = {false,SPR_GROUNDEXPL7,2,NULL,0,&s_grexplosion8};
+statetype s_grexplosion6 = {false,SPR_GROUNDEXPL6,2,NULL,0,&s_grexplosion7};
+statetype s_grexplosion5 = {false,SPR_GROUNDEXPL5,2,NULL,0,&s_grexplosion6};
+statetype s_grexplosion4 = {false,SPR_GROUNDEXPL4,2,NULL,0,&s_grexplosion5};
+statetype s_grexplosion3 = {false,SPR_GROUNDEXPL3,2,T_Explosion,0,&s_grexplosion4};
+statetype s_grexplosion2 = {false,SPR_GROUNDEXPL2,2,NULL,0,&s_grexplosion3};
+statetype s_grexplosion1 = {false,SPR_GROUNDEXPL1,2,NULL,0,&s_grexplosion2};
+
+
+
+statetype s_staticexplosion25 = {false,SPR_STATICEXPL25,2,NULL,0,NULL};
+statetype s_staticexplosion24 = {false,SPR_STATICEXPL24,2,NULL,0,&s_staticexplosion25};
+statetype s_staticexplosion23 = {false,SPR_STATICEXPL23,2,NULL,0,&s_staticexplosion24};
+statetype s_staticexplosion22 = {false,SPR_STATICEXPL22,2,NULL,0,&s_staticexplosion23};
+statetype s_staticexplosion21 = {false,SPR_STATICEXPL21,2,NULL,0,&s_staticexplosion22};
+statetype s_staticexplosion20 = {false,SPR_STATICEXPL20,2,NULL,0,&s_staticexplosion21};
+statetype s_staticexplosion19 = {false,SPR_STATICEXPL19,2,NULL,0,&s_staticexplosion20};
+statetype s_staticexplosion18 = {false,SPR_STATICEXPL18,2,NULL,0,&s_staticexplosion19};
+statetype s_staticexplosion17 = {false,SPR_STATICEXPL17,2,NULL,0,&s_staticexplosion18};
+statetype s_staticexplosion16 = {false,SPR_STATICEXPL16,2,NULL,0,&s_staticexplosion17};
+statetype s_staticexplosion15 = {false,SPR_STATICEXPL15,2,NULL,0,&s_staticexplosion16};
+statetype s_staticexplosion14 = {false,SPR_STATICEXPL14,2,NULL,0,&s_staticexplosion15};
+statetype s_staticexplosion13 = {false,SPR_STATICEXPL13,2,NULL,0,&s_staticexplosion14};
+statetype s_staticexplosion12 = {false,SPR_STATICEXPL12,2,NULL,0,&s_staticexplosion13};
+statetype s_staticexplosion11 = {false,SPR_STATICEXPL11,2,NULL,0,&s_staticexplosion12};
+statetype s_staticexplosion10 = {false,SPR_STATICEXPL10,2,NULL,0,&s_staticexplosion11};
+statetype s_staticexplosion9 = {false,SPR_STATICEXPL9,2,NULL,0,&s_staticexplosion10};
+statetype s_staticexplosion8 = {false,SPR_STATICEXPL8,2,NULL,0,&s_staticexplosion9};
+statetype s_staticexplosion7 = {false,SPR_STATICEXPL7,2,NULL,0,&s_staticexplosion8};
+statetype s_staticexplosion6 = {false,SPR_STATICEXPL6,2,NULL,0,&s_staticexplosion7};
+statetype s_staticexplosion5 = {false,SPR_STATICEXPL5,2,NULL,0,&s_staticexplosion6};
+statetype s_staticexplosion4 = {false,SPR_STATICEXPL4,2,NULL,0,&s_staticexplosion5};
+statetype s_staticexplosion3 = {false,SPR_STATICEXPL3,2,T_Explosion,0,&s_staticexplosion4};
+statetype s_staticexplosion2 = {false,SPR_STATICEXPL2,2,NULL,0,&s_staticexplosion3};
+statetype s_staticexplosion1 = {false,SPR_STATICEXPL1,2,NULL,0,&s_staticexplosion2};
+
+
+
+statetype s_upblade16 = {false,UBLADE8,1,T_Path,0,&s_upblade1};
+statetype s_upblade15 = {false,UBLADE7,2,T_Path,0,&s_upblade16};
+statetype s_upblade14 = {false,UBLADE6,1,T_Path,0,&s_upblade15};
+statetype s_upblade13 = {false,UBLADE5,2,T_Path,0,&s_upblade14};
+statetype s_upblade12 = {false,UBLADE4,1,T_Path,0,&s_upblade13};
+statetype s_upblade11 = {false,UBLADE3,2,T_Path,0,&s_upblade12};
+statetype s_upblade10 = {false,UBLADE2,1,T_Path,0,&s_upblade11};
+statetype s_upblade9 = {false,UBLADE9,2,T_Path,0,&s_upblade10};
+statetype s_upblade8 = {false,UBLADE8,1,T_Path,0,&s_upblade9};
+statetype s_upblade7 = {false,UBLADE7,2,T_Path,0,&s_upblade8};
+statetype s_upblade6 = {false,UBLADE6,1,T_Path,0,&s_upblade7};
+statetype s_upblade5 = {false,UBLADE5,2,T_Path,0,&s_upblade6};
+statetype s_upblade4 = {false,UBLADE4,1,T_Path,0,&s_upblade5};
+statetype s_upblade3 = {false,UBLADE3,2,T_Path,0,&s_upblade4};
+statetype s_upblade2 = {false,UBLADE2,1,T_Path,0,&s_upblade3};
+statetype s_upblade1 = {false,UBLADE1,2,T_Path,SF_SOUND,&s_upblade2};
+
+
+statetype s_firejetup23 = {false,FIREJETUP23,3,T_Path,SF_CRUSH,&s_firejetup1};
+statetype s_firejetup22 = {false,FIREJETUP22,3,T_Path,SF_CRUSH,&s_firejetup23};
+statetype s_firejetup21 = {false,FIREJETUP21,3,T_Path,0,&s_firejetup22};
+statetype s_firejetup20 = {false,FIREJETUP20,3,T_Path,0,&s_firejetup21};
+statetype s_firejetup19 = {false,FIREJETUP19,3,T_Path,0,&s_firejetup20};
+statetype s_firejetup18 = {false,FIREJETUP18,3,T_Path,0,&s_firejetup19};
+statetype s_firejetup17 = {false,FIREJETUP17,3,T_Path,0,&s_firejetup18};
+statetype s_firejetup16 = {false,FIREJETUP16,3,T_Path,SF_CRUSH,&s_firejetup17};
+statetype s_firejetup15 = {false,FIREJETUP15,3,T_Path,SF_CRUSH,&s_firejetup16};
+statetype s_firejetup14 = {false,FIREJETUP14,3,T_Path,SF_CRUSH,&s_firejetup15};
+statetype s_firejetup13 = {false,FIREJETUP13,3,T_Path,0,&s_firejetup14};
+statetype s_firejetup12 = {false,FIREJETUP12,3,T_Path,0,&s_firejetup13};
+statetype s_firejetup11 = {false,FIREJETUP11,3,T_Path,0,&s_firejetup12};
+statetype s_firejetup10 = {false,FIREJETUP10,3,T_Path,0,&s_firejetup11};
+statetype s_firejetup9 = {false,FIREJETUP9,3,T_Path,0,&s_firejetup10};
+statetype s_firejetup8 = {false,FIREJETUP8,3,T_Path,SF_CRUSH,&s_firejetup9};
+statetype s_firejetup7 = {false,FIREJETUP7,3,T_Path,SF_CRUSH,&s_firejetup8};
+statetype s_firejetup6 = {false,FIREJETUP6,3,T_Path,SF_CRUSH,&s_firejetup7};
+statetype s_firejetup5 = {false,FIREJETUP5,3,T_Path,0,&s_firejetup6};
+statetype s_firejetup4 = {false,FIREJETUP4,3,T_Path,0,&s_firejetup5};
+statetype s_firejetup3 = {false,FIREJETUP3,3,T_Path,0,&s_firejetup4};
+statetype s_firejetup2 = {false,FIREJETUP2,3,T_Path,0,&s_firejetup3};
+statetype s_firejetup1 = {false,FIREJETUP1,70,T_Path,SF_SOUND,&s_firejetup2};
+
+
+
+statetype s_columndownup6 = {false,CRUSHDOWN7,5,NULL,0,&s_columndowndown1};
+statetype s_columndownup5 = {false,CRUSHDOWN6,5,NULL,0,&s_columndownup6};
+statetype s_columndownup4 = {false,CRUSHDOWN5,5,NULL,SF_BLOCK,&s_columndownup5};
+statetype s_columndownup3 = {false,CRUSHDOWN4,5,NULL,SF_BLOCK,&s_columndownup4};
+statetype s_columndownup2 = {false,CRUSHDOWN3,5,NULL,SF_BLOCK,&s_columndownup3};
+statetype s_columndownup1 = {false,CRUSHDOWN2,5,NULL,SF_BLOCK,&s_columndownup2};
+
+
+statetype s_columndowndown8 = {false,CRUSHDOWN1,5,T_CrushDown,SF_CRUSH|SF_DOWN|SF_BLOCK,&s_columndownup1};
+statetype s_columndowndown7 = {false,CRUSHDOWN2,5,T_CrushDown,SF_CRUSH|SF_DOWN|SF_BLOCK,&s_columndowndown8};
+statetype s_columndowndown6 = {false,CRUSHDOWN3,5,T_CrushDown,SF_DOWN|SF_BLOCK,&s_columndowndown7};
+statetype s_columndowndown5 = {false,CRUSHDOWN4,5,T_CrushDown,SF_DOWN|SF_BLOCK,&s_columndowndown6};
+statetype s_columndowndown4 = {false,CRUSHDOWN5,5,T_CrushDown,SF_DOWN,&s_columndowndown5};
+statetype s_columndowndown3 = {false,CRUSHDOWN6,5,T_CrushDown,SF_DOWN,&s_columndowndown4};
+statetype s_columndowndown2 = {false,CRUSHDOWN7,5,T_CrushDown,SF_DOWN,&s_columndowndown3};
+statetype s_columndowndown1 = {false,CRUSHDOWN8,30,T_CrushDown,SF_DOWN|SF_SOUND,&s_columndowndown2};
+
+
+statetype s_spearup16 = {false,SPEARUP16,2,T_Spears,SF_CRUSH,&s_spearup1};
+statetype s_spearup15 = {false,SPEARUP15,2,T_Spears,SF_CRUSH,&s_spearup16};
+statetype s_spearup14 = {false,SPEARUP14,2,T_Spears,SF_CRUSH,&s_spearup15};
+statetype s_spearup13 = {false,SPEARUP13,2,T_Spears,SF_CRUSH,&s_spearup14};
+statetype s_spearup12 = {false,SPEARUP12,2,T_Spears,SF_CRUSH,&s_spearup13};
+statetype s_spearup11 = {false,SPEARUP11,2,T_Spears,SF_CRUSH,&s_spearup12};
+statetype s_spearup10 = {false,SPEARUP10,2,T_Spears,SF_CRUSH,&s_spearup11};
+statetype s_spearup9 = {false,SPEARUP9,2,T_Spears,SF_DOWN,&s_spearup10};
+
+statetype s_spearup8 = {false,SPEARUP8,35,T_Spears,SF_DOWN|SF_SOUND,&s_spearup9};
+statetype s_spearup7 = {false,SPEARUP7,2,T_Spears,SF_DOWN,&s_spearup8};
+statetype s_spearup6 = {false,SPEARUP6,2,T_Spears,SF_CRUSH,&s_spearup7};
+statetype s_spearup5 = {false,SPEARUP5,2,T_Spears,SF_CRUSH,&s_spearup6};
+statetype s_spearup4 = {false,SPEARUP4,2,T_Spears,SF_CRUSH,&s_spearup5};
+statetype s_spearup3 = {false,SPEARUP3,2,T_Spears,SF_CRUSH,&s_spearup4};
+statetype s_spearup2 = {false,SPEARUP2,2,T_Spears,SF_CRUSH,&s_spearup3};
+statetype s_spearup1 = {false,SPEARUP1,2,T_Spears,SF_CRUSH,&s_spearup2};
+
+
+statetype s_dust = {false,NOTHING,0,NULL,0,&s_dust};
+
+
+
+statetype s_gas2 = {false,SPR42_GRATE,5,T_Count,0,&s_gas2};
+statetype s_gas1 = {false,SPR42_GRATE,0,NULL,0,&s_gas1};
+
+
+//================== player stuff =======================================/
+
+statetype s_p_bazooka1 = {16,SPR_BJMISS11,3,T_Projectile,0,&s_p_bazooka1};
+
+statetype s_p_grenade = {16,SPR_BJMISS11,3,T_Projectile,0,&s_p_grenade};
+
+/*
+statetype s_p_misssmoke4 = {false,MISSSMOKE4,7,NULL,0,NULL};
+statetype s_p_misssmoke3 = {false,MISSSMOKE3,7,NULL,0,&s_p_misssmoke4};
+statetype s_p_misssmoke2 = {false,MISSSMOKE2,7,NULL,0,&s_p_misssmoke3};
+statetype s_p_misssmoke1 = {false,MISSSMOKE1,3,NULL,0,&s_p_misssmoke2};
+*/
+
+
+statetype s_basemarker8 = {false,FLASH8,3,NULL,0,&s_basemarker1};
+statetype s_basemarker7 = {false,FLASH7,3,NULL,0,&s_basemarker8};
+statetype s_basemarker6 = {false,FLASH6,3,NULL,0,&s_basemarker7};
+statetype s_basemarker5 = {false,FLASH5,3,NULL,0,&s_basemarker6};
+statetype s_basemarker4 = {false,FLASH4,3,NULL,0,&s_basemarker5};
+statetype s_basemarker3 = {false,FLASH3,3,NULL,0,&s_basemarker4};
+statetype s_basemarker2 = {false,FLASH2,3,NULL,0,&s_basemarker3};
+statetype s_basemarker1 = {false,FLASH1,3,NULL,0,&s_basemarker2};
+
+
+
+statetype s_flash8 = {false,FLASH8,3,NULL,0,NULL};
+statetype s_flash7 = {false,FLASH7,3,NULL,0,&s_flash8};
+statetype s_flash6 = {false,FLASH6,3,NULL,0,&s_flash7};
+statetype s_flash5 = {false,FLASH5,3,NULL,0,&s_flash6};
+statetype s_flash4 = {false,FLASH4,3,NULL,0,&s_flash5};
+statetype s_flash3 = {false,FLASH3,3,NULL,0,&s_flash4};
+statetype s_flash2 = {false,FLASH2,3,NULL,0,&s_flash3};
+statetype s_flash1 = {false,FLASH1,3,NULL,0,&s_flash2};
+
+statetype s_gunsmoke8 = {false,GUNSMOKE8,3,NULL,0,NULL};
+statetype s_gunsmoke7 = {false,GUNSMOKE7,3,NULL,0,&s_gunsmoke8};
+statetype s_gunsmoke6 = {false,GUNSMOKE6,3,NULL,0,&s_gunsmoke7};
+statetype s_gunsmoke5 = {false,GUNSMOKE5,3,NULL,0,&s_gunsmoke6};
+statetype s_gunsmoke4 = {false,GUNSMOKE4,3,NULL,0,&s_gunsmoke5};
+statetype s_gunsmoke3 = {false,GUNSMOKE3,3,NULL,0,&s_gunsmoke4};
+statetype s_gunsmoke2 = {false,GUNSMOKE2,3,NULL,0,&s_gunsmoke3};
+statetype s_gunsmoke1 = {false,GUNSMOKE1,2,NULL,0,&s_gunsmoke2};
+
+statetype s_bloodspurt8 = {false,BLOODSPURT8,7,NULL,0,NULL};
+statetype s_bloodspurt7 = {false,BLOODSPURT7,7,NULL,0,&s_bloodspurt8};
+statetype s_bloodspurt6 = {false,BLOODSPURT6,7,NULL,0,&s_bloodspurt7};
+statetype s_bloodspurt5 = {false,BLOODSPURT5,7,NULL,0,&s_bloodspurt6};
+statetype s_bloodspurt4 = {false,BLOODSPURT4,7,NULL,0,&s_bloodspurt5};
+statetype s_bloodspurt3 = {false,BLOODSPURT3,7,NULL,0,&s_bloodspurt4};
+statetype s_bloodspurt2 = {false,BLOODSPURT2,7,NULL,0,&s_bloodspurt3};
+statetype s_bloodspurt1 = {false,BLOODSPURT1,5,NULL,0,&s_bloodspurt2};
+
+statetype s_hitmetalwall4 = {false,HITMETALWALL4,7,NULL,0,NULL};
+statetype s_hitmetalwall3 = {false,HITMETALWALL3,7,NULL,0,&s_hitmetalwall4};
+statetype s_hitmetalwall2 = {false,HITMETALWALL2,7,NULL,0,&s_hitmetalwall3};
+statetype s_hitmetalwall1 = {false,HITMETALWALL1,5,NULL,0,&s_hitmetalwall2};
+
+statetype s_hitmetalactor4 = {false,HITMETALACTOR4,7,NULL,0,NULL};
+statetype s_hitmetalactor3 = {false,HITMETALACTOR3,7,NULL,0,&s_hitmetalactor4};
+statetype s_hitmetalactor2 = {false,HITMETALACTOR2,7,NULL,0,&s_hitmetalactor3};
+statetype s_hitmetalactor1 = {false,HITMETALACTOR1,5,NULL,0,&s_hitmetalactor2};
+
+
+
+statetype s_fireunit15 = {false,FIREW15,3,T_Firethink,0,&s_fireunit1};
+statetype s_fireunit14 = {false,FIREW14,3,T_Firethink,0,&s_fireunit15};
+statetype s_fireunit13 = {false,FIREW13,3,T_Firethink,0,&s_fireunit14};
+statetype s_fireunit12 = {false,FIREW12,3,T_Firethink,0,&s_fireunit13};
+statetype s_fireunit11 = {false,FIREW11,3,T_Firethink,0,&s_fireunit12};
+statetype s_fireunit10 = {false,FIREW10,3,T_Firethink,0,&s_fireunit11};
+statetype s_fireunit9 = {false,FIREW9,3,T_Firethink,0,&s_fireunit10};
+statetype s_fireunit8 = {false,FIREW8,3,T_Firethink,0,&s_fireunit9};
+statetype s_fireunit7 = {false,FIREW7,3,T_Firethink,0,&s_fireunit8};
+statetype s_fireunit6 = {false,FIREW6,3,T_Firethink,0,&s_fireunit7};
+statetype s_fireunit5 = {false,FIREW5,3,T_Firethink,0,&s_fireunit6};
+statetype s_fireunit4 = {false,FIREW4,3,T_Firethink,0,&s_fireunit5};
+statetype s_fireunit3 = {false,FIREW3,3,T_Firethink,0,&s_fireunit4};
+statetype s_fireunit2 = {false,FIREW2,3,T_Firethink,0,&s_fireunit3};
+statetype s_fireunit1 = {false,FIREW1,3,T_Firethink,0,&s_fireunit2};
+
+
+
+statetype s_skeleton48 = {false,SKELETON48,0,T_Convert,0,&s_skeleton48};
+statetype s_skeleton47 = {false,SKELETON47,2,NULL,0,&s_skeleton48};
+statetype s_skeleton46 = {false,SKELETON46,2,NULL,0,&s_skeleton47};
+statetype s_skeleton45 = {false,SKELETON45,2,NULL,0,&s_skeleton46};
+statetype s_skeleton44 = {false,SKELETON44,2,NULL,0,&s_skeleton45};
+statetype s_skeleton43 = {false,SKELETON43,2,NULL,0,&s_skeleton44};
+statetype s_skeleton42 = {false,SKELETON42,2,NULL,0,&s_skeleton43};
+statetype s_skeleton41 = {false,SKELETON41,2,T_Xylophone,0,&s_skeleton42};
+statetype s_skeleton40 = {false,SKELETON40,2,NULL,0,&s_skeleton41};
+statetype s_skeleton39 = {false,SKELETON39,2,NULL,0,&s_skeleton40};
+statetype s_skeleton38 = {false,SKELETON38,2,NULL,0,&s_skeleton39};
+statetype s_skeleton37 = {false,SKELETON37,2,NULL,0,&s_skeleton38};
+statetype s_skeleton36 = {false,SKELETON36,2,NULL,0,&s_skeleton37};
+statetype s_skeleton35 = {false,SKELETON35,2,NULL,0,&s_skeleton36};
+statetype s_skeleton34 = {false,SKELETON34,2,NULL,0,&s_skeleton35};
+statetype s_skeleton33 = {false,SKELETON33,2,NULL,0,&s_skeleton34};
+statetype s_skeleton32 = {false,SKELETON32,2,NULL,0,&s_skeleton33};
+statetype s_skeleton31 = {false,SKELETON31,2,NULL,0,&s_skeleton32};
+statetype s_skeleton30 = {false,SKELETON30,2,NULL,0,&s_skeleton31};
+statetype s_skeleton29 = {false,SKELETON29,2,NULL,0,&s_skeleton30};
+statetype s_skeleton28 = {false,SKELETON28,2,NULL,0,&s_skeleton29};
+statetype s_skeleton27 = {false,SKELETON27,2,NULL,0,&s_skeleton28};
+statetype s_skeleton26 = {false,SKELETON26,2,NULL,0,&s_skeleton27};
+statetype s_skeleton25 = {false,SKELETON25,2,NULL,0,&s_skeleton26};
+statetype s_skeleton24 = {false,SKELETON24,2,NULL,0,&s_skeleton25};
+statetype s_skeleton23 = {false,SKELETON23,2,NULL,0,&s_skeleton24};
+statetype s_skeleton22 = {false,SKELETON22,2,NULL,0,&s_skeleton23};
+statetype s_skeleton21 = {false,SKELETON21,2,NULL,0,&s_skeleton22};
+statetype s_skeleton20 = {false,SKELETON20,2,NULL,0,&s_skeleton21};
+statetype s_skeleton19 = {false,SKELETON19,2,NULL,0,&s_skeleton20};
+statetype s_skeleton18 = {false,SKELETON18,2,NULL,0,&s_skeleton19};
+statetype s_skeleton17 = {false,SKELETON17,2,NULL,0,&s_skeleton18};
+statetype s_skeleton16 = {false,SKELETON16,2,NULL,0,&s_skeleton17};
+statetype s_skeleton15 = {false,SKELETON15,2,NULL,0,&s_skeleton16};
+statetype s_skeleton14 = {false,SKELETON14,2,NULL,0,&s_skeleton15};
+statetype s_skeleton13 = {false,SKELETON13,2,NULL,0,&s_skeleton14};
+statetype s_skeleton12 = {false,SKELETON12,2,NULL,0,&s_skeleton13};
+statetype s_skeleton11 = {false,SKELETON11,2,NULL,0,&s_skeleton12};
+statetype s_skeleton10 = {false,SKELETON10,2,NULL,0,&s_skeleton11};
+statetype s_skeleton9 = {false,SKELETON9,2,NULL,0,&s_skeleton10};
+statetype s_skeleton8 = {false,SKELETON8,2,NULL,0,&s_skeleton9};
+statetype s_skeleton7 = {false,SKELETON7,2,NULL,0,&s_skeleton8};
+statetype s_skeleton6 = {false,SKELETON6,2,NULL,0,&s_skeleton7};
+statetype s_skeleton5 = {false,SKELETON5,2,NULL,0,&s_skeleton6};
+statetype s_skeleton4 = {false,SKELETON4,2,NULL,0,&s_skeleton5};
+statetype s_skeleton3 = {false,SKELETON3,2,NULL,0,&s_skeleton4};
+statetype s_skeleton2 = {false,SKELETON2,2,NULL,0,&s_skeleton3};
+statetype s_skeleton1 = {false,SKELETON1,2,NULL,0,&s_skeleton2};
+
+
+
+statetype s_spring9 = {false,SPRING9,4,T_Spring,SF_DOWN,&s_spring1};
+statetype s_spring8 = {false,SPRING8,4,NULL,0,&s_spring9};
+statetype s_spring7 = {false,SPRING7,4,NULL,0,&s_spring8};
+statetype s_spring6 = {false,SPRING6,4,NULL,0,&s_spring7};
+statetype s_spring5 = {false,SPRING5,4,NULL,0,&s_spring6};
+statetype s_spring4 = {false,SPRING4,15,NULL,SF_UP,&s_spring5};
+statetype s_spring3 = {false,SPRING3,1,NULL,SF_UP,&s_spring4};
+statetype s_spring2 = {false,SPRING2,1,NULL,SF_UP,&s_spring3};
+statetype s_spring1 = {false,SPRING1,0,NULL,SF_UP,&s_spring1};
+
+
+statetype s_autospring9 = {false,SPRING9,4,NULL,0,&s_autospring1};
+statetype s_autospring8 = {false,SPRING8,4,NULL,0,&s_autospring9};
+statetype s_autospring7 = {false,SPRING7,4,NULL,0,&s_autospring8};
+statetype s_autospring6 = {false,SPRING6,4,NULL,0,&s_autospring7};
+statetype s_autospring5 = {false,SPRING5,4,NULL,0,&s_autospring6};
+statetype s_autospring4 = {false,SPRING4,15,NULL,SF_UP,&s_autospring5};
+statetype s_autospring3 = {false,SPRING3,1,T_Spring,SF_UP,&s_autospring4};
+statetype s_autospring2 = {false,SPRING2,1,T_Spring,SF_UP,&s_autospring3};
+statetype s_autospring1 = {false,SPRING1,70*SPRINGDELAY,NULL,0,&s_autospring2};
+
+//====================== remote player ==============================//
+
+statetype s_itemspawn8 = {false,ITEMSPAWN8,6,NULL,0,NULL};
+statetype s_itemspawn7 = {false,ITEMSPAWN7,6,NULL,0,&s_itemspawn8};
+statetype s_itemspawn6 = {false,ITEMSPAWN6,6,NULL,0,&s_itemspawn7};
+statetype s_itemspawn5 = {false,ITEMSPAWN5,6,NULL,0,&s_itemspawn6};
+statetype s_itemspawn4 = {false,ITEMSPAWN4,6,NULL,0,&s_itemspawn5};
+statetype s_itemspawn3 = {false,ITEMSPAWN3,6,NULL,0,&s_itemspawn4};
+statetype s_itemspawn2 = {false,ITEMSPAWN2,6,NULL,0,&s_itemspawn3};
+statetype s_itemspawn1 = {false,ITEMSPAWN1,6,NULL,0,&s_itemspawn2};
+
+
+statetype s_player = {true,CASSATT_S1,0,T_Player,0,&s_player};
+
+statetype s_pgunattack2 = {true,CASSATT_SHOOT11,0,T_Attack,0,&s_pgunattack2};
+statetype s_pgunattack1 = {true,CASSATT_SHOOT21,5,T_Attack,0,&s_pgunattack2};
+
+statetype s_pmissattack2 = {true,CASSATTM_SHOOT11,0,T_Attack,0,&s_pmissattack2};
+statetype s_pmissattack1 = {true,CASSATTM_SHOOT21,5,T_Attack,0,&s_pmissattack2};
+
+statetype s_pbatblast = {true,CASSATT_SHOOT21,0,T_BatBlast,0,&s_pbatblast};
+
+
+
+
+statetype s_remotemove4 = {true,CASSATT_W41,5,T_Player,SF_DOWN,&s_remotemove1};
+statetype s_remotemove3 = {true,CASSATT_W31,5,T_Player,SF_DOWN,&s_remotemove4};
+statetype s_remotemove2 = {true,CASSATT_W21,5,T_Player,SF_DOWN,&s_remotemove3};
+statetype s_remotemove1 = {true,CASSATT_W11,5,T_Player,SF_DOWN,&s_remotemove2};
+
+statetype s_remoteinelev = {true,CASSATT_S1,700,T_Player,0,&s_remoteinelev};
+
+statetype s_remotedead = {false,CASSATT_VDEAD,0,T_Player,0,&s_remotedead};
+
+
+
+statetype s_remotedie6 = {false,CASSATT_VDIE6,3,T_Player,0,&s_remotedead};
+statetype s_remotedie5 = {false,CASSATT_VDIE5,3,T_Player,0,&s_remotedie6};
+statetype s_remotedie4 = {false,CASSATT_VDIE4,3,T_Player,0,&s_remotedie5};
+statetype s_remotedie3 = {false,CASSATT_VDIE3,3,T_Player,0,&s_remotedie4};
+statetype s_remotedie2 = {false,CASSATT_VDIE2,3,T_Player,0,&s_remotedie3};
+statetype s_remotedie1 = {false,CASSATT_VDIE1,3,T_Player,0,&s_remotedie2};
+
+
+statetype s_voidwait = {false,NOTHING,0,T_DeadWait,0,&s_voidwait};
+statetype s_ashwait = {false,SKELETON48,0,T_DeadWait,0,&s_ashwait};
+statetype s_deadwait = {false,CASSATT_VDEAD,0,T_DeadWait,0,&s_deadwait};
+statetype s_gutwait = {false,GUTS12,0,T_DeadWait,0,&s_gutwait};
+statetype s_remoteguts12 = {false,GUTS12,0,T_Player,0,&s_remoteguts12};
+statetype s_remoteguts11 = {false,GUTS11,3,T_Player,0,&s_remoteguts12};
+statetype s_remoteguts10 = {false,GUTS10,3,T_Player,0,&s_remoteguts11};
+statetype s_remoteguts9 = {false,GUTS9,3,T_Player,0,&s_remoteguts10};
+statetype s_remoteguts8 = {false,GUTS8,3,T_Player,0,&s_remoteguts9};
+statetype s_remoteguts7 = {false,GUTS7,3,T_Player,0,&s_remoteguts8};
+statetype s_remoteguts6 = {false,GUTS6,3,T_Player,0,&s_remoteguts7};
+statetype s_remoteguts5 = {false,GUTS5,3,T_Player,0,&s_remoteguts6};
+statetype s_remoteguts4 = {false,GUTS4,3,T_Player,0,&s_remoteguts5};
+statetype s_remoteguts3 = {false,GUTS3,3,T_Player,0,&s_remoteguts4};
+statetype s_remoteguts2 = {false,GUTS2,3,T_Player,0,&s_remoteguts3};
+statetype s_remoteguts1 = {false,GUTS1,3,T_Player,0,&s_remoteguts2};
+
+//========================================================================//
+
+statetype s_godfire4 = {false,GODFIRE4,3,T_Projectile,0,&s_godfire1};
+statetype s_godfire3 = {false,GODFIRE3,3,T_Projectile,0,&s_godfire4};
+statetype s_godfire2 = {false,GODFIRE2,3,T_Projectile,0,&s_godfire3};
+statetype s_godfire1 = {false,GODFIRE1,3,T_Projectile,0,&s_godfire2};
+
+
+
+
+statetype s_guts12 = {false,GUTS12,0,T_Collide,SF_GUTS,&s_guts12};
+statetype s_guts11 = {false,GUTS11,3,T_Collide,SF_GUTS,&s_guts12};
+statetype s_guts10 = {false,GUTS10,3,T_Collide,SF_GUTS,&s_guts11};
+statetype s_guts9 = {false,GUTS9,3,T_Collide,SF_GUTS,&s_guts10};
+statetype s_guts8 = {false,GUTS8,3,T_Collide,SF_GUTS,&s_guts9};
+statetype s_guts7 = {false,GUTS7,3,T_Collide,SF_GUTS,&s_guts8};
+statetype s_guts6 = {false,GUTS6,3,T_Collide,SF_GUTS,&s_guts7};
+statetype s_guts5 = {false,GUTS5,3,T_Collide,SF_GUTS,&s_guts6};
+statetype s_guts4 = {false,GUTS4,3,T_Collide,SF_GUTS,&s_guts5};
+statetype s_guts3 = {false,GUTS3,3,T_Collide,SF_GUTS,&s_guts4};
+statetype s_guts2 = {false,GUTS2,3,T_Collide,SF_GUTS,&s_guts3};
+statetype s_guts1 = {false,GUTS1,3,T_Collide,SF_GUTS,&s_guts2};
+
+//MED
+#if (SHAREWARE == 1) || (DOPEFISH == 0)
+statetype s_collectorwander8 = {false,COLLECTOR15,0,T_CollectorWander,0,&s_collectorwander1};
+statetype s_collectorwander7 = {false,COLLECTOR13,1,T_CollectorWander,0,&s_collectorwander8};
+statetype s_collectorwander6 = {false,COLLECTOR11,0,T_CollectorWander,0,&s_collectorwander7};
+statetype s_collectorwander5 = {false,COLLECTOR9,1,T_CollectorWander,0,&s_collectorwander6};
+statetype s_collectorwander4 = {false,COLLECTOR7,0,T_CollectorWander,0,&s_collectorwander5};
+statetype s_collectorwander3 = {false,COLLECTOR5,1,T_CollectorWander,0,&s_collectorwander4};
+statetype s_collectorwander2 = {false,COLLECTOR3,0,T_CollectorWander,0,&s_collectorwander3};
+statetype s_collectorwander1 = {false,COLLECTOR1,1,T_CollectorWander,0,&s_collectorwander2};
+#else
+
+statetype s_collectorwander8 = {false,DOPE8,2,T_CollectorWander,0,&s_collectorwander1};
+statetype s_collectorwander7 = {false,DOPE7,2,T_CollectorWander,0,&s_collectorwander8};
+statetype s_collectorwander6 = {false,DOPE6,2,T_CollectorWander,0,&s_collectorwander7};
+statetype s_collectorwander5 = {false,DOPE5,2,T_CollectorWander,0,&s_collectorwander6};
+statetype s_collectorwander4 = {false,DOPE4,2,T_CollectorWander,0,&s_collectorwander5};
+statetype s_collectorwander3 = {false,DOPE3,2,T_CollectorWander,0,&s_collectorwander4};
+statetype s_collectorwander2 = {false,DOPE2,2,T_CollectorWander,0,&s_collectorwander3};
+statetype s_collectorwander1 = {false,DOPE1,2,T_CollectorWander,0,&s_collectorwander2};
+#endif
+
+
+//MED
+#if (SHAREWARE == 1) || (DOPEFISH == 0)
+statetype s_collectorfdoor8 = {false,COLLECTOR15,0,T_CollectorFindDoor,0,&s_collectorfdoor1};
+statetype s_collectorfdoor7 = {false,COLLECTOR13,1,T_CollectorFindDoor,0,&s_collectorfdoor8};
+statetype s_collectorfdoor6 = {false,COLLECTOR11,0,T_CollectorFindDoor,0,&s_collectorfdoor7};
+statetype s_collectorfdoor5 = {false,COLLECTOR9,1,T_CollectorFindDoor,0,&s_collectorfdoor6};
+statetype s_collectorfdoor4 = {false,COLLECTOR7,0,T_CollectorFindDoor,0,&s_collectorfdoor5};
+statetype s_collectorfdoor3 = {false,COLLECTOR5,1,T_CollectorFindDoor,0,&s_collectorfdoor4};
+statetype s_collectorfdoor2 = {false,COLLECTOR3,0,T_CollectorFindDoor,0,&s_collectorfdoor3};
+statetype s_collectorfdoor1 = {false,COLLECTOR1,1,T_CollectorFindDoor,0,&s_collectorfdoor2};
+#else
+
+statetype s_collectorfdoor8 = {false,DOPE8,2,T_CollectorFindDoor,0,&s_collectorfdoor1};
+statetype s_collectorfdoor7 = {false,DOPE7,2,T_CollectorFindDoor,0,&s_collectorfdoor8};
+statetype s_collectorfdoor6 = {false,DOPE6,2,T_CollectorFindDoor,0,&s_collectorfdoor7};
+statetype s_collectorfdoor5 = {false,DOPE5,2,T_CollectorFindDoor,0,&s_collectorfdoor6};
+statetype s_collectorfdoor4 = {false,DOPE4,2,T_CollectorFindDoor,0,&s_collectorfdoor5};
+statetype s_collectorfdoor3 = {false,DOPE3,2,T_CollectorFindDoor,0,&s_collectorfdoor4};
+statetype s_collectorfdoor2 = {false,DOPE2,2,T_CollectorFindDoor,0,&s_collectorfdoor3};
+statetype s_collectorfdoor1 = {false,DOPE1,2,T_CollectorFindDoor,0,&s_collectorfdoor2};
+
+#endif
+
+statetype s_timekeeper = {false,NOTHING,140,T_End,0,NULL};
+
+statetype s_wind = {false,-1,10,T_Wind,0,&s_wind};
+
+
+statetype s_deadblood8 = {false,NOTHING,0,T_Blood,0,&s_deadblood8};
+statetype s_deadblood7 = {false,DEADBLOOD7,5,NULL,0,&s_deadblood8};
+statetype s_deadblood6 = {false,DEADBLOOD6,5,NULL,0,&s_deadblood7};
+statetype s_deadblood5 = {false,DEADBLOOD5,5,NULL,0,&s_deadblood6};
+statetype s_deadblood4 = {false,DEADBLOOD4,5,NULL,0,&s_deadblood5};
+statetype s_deadblood3 = {false,DEADBLOOD3,5,NULL,0,&s_deadblood4};
+statetype s_deadblood2 = {false,DEADBLOOD2,5,NULL,0,&s_deadblood3};
+statetype s_deadblood1 = {false,DEADBLOOD1,5,NULL,0,&s_deadblood2};
+
+/*
+statetype s_rain7 = {false,RAINDROP6,0,NULL,0,NULL};
+statetype s_rain6 = {false,RAINDROP5,3,NULL,0,&s_rain7};
+statetype s_rain5 = {false,RAINDROP4,0,NULL,0,&s_rain6};
+statetype s_rain4 = {false,RAINDROP3,3,NULL,0,&s_rain5};
+statetype s_rain3 = {false,RAINDROP2,0,NULL,0,&s_rain4};
+statetype s_rain2 = {false,RAINDROP1,0,T_RainFall,0,&s_rain2};
+statetype s_rain1 = {false,NOTHING,50,T_RainSpawn,0,&s_rain1};
+
+statetype s_rainmaster = {false,NOTHING,0,T_RainMaster,0,&s_rainmaster};
+*/
+
+statetype s_pathdisk = {false,PLATFORM1,0,T_Path,0,&s_pathdisk};
+statetype s_elevdisk = {false,PLATFORM1,0,T_ElevDisk,0,&s_elevdisk};
+
+statetype s_diskmaster = {false,NOTHING,0,T_ElevDisk,0,&s_diskmaster};
+
+
+
+statetype s_blooddrip4 = {false,WALLGIB4,3,T_BloodFall,0,&s_blooddrip1};
+statetype s_blooddrip3 = {false,WALLGIB3,3,T_BloodFall,0,&s_blooddrip4};
+statetype s_blooddrip2 = {false,WALLGIB2,3,T_BloodFall,0,&s_blooddrip3};
+statetype s_blooddrip1 = {false,WALLGIB1,3,T_BloodFall,0,&s_blooddrip2};
+
+
+
+//==================== Push column =====================================//
+
+
+statetype s_pushcolumn1 = {false,SPR_PUSHCOLUMN1,6,T_MoveColumn,0,&s_pushcolumn1};
+statetype s_pushcolumn2 = {false,SPR_PUSHCOLUMN1,6,T_MoveColumn,0,&s_pushcolumn2};
+statetype s_pushcolumn3 = {false,SPR_PUSHCOLUMN1,6,T_MoveColumn,0,&s_pushcolumn3};
+
+
+//=================== Wall Fire =======================================/
+
+statetype s_wallfireball = {false,NOTHING,50,A_Wallfire,0,&s_wallfireball};
+
+statetype s_crossfire2 = {true,SPR_CROSSFIRE31,6,T_Projectile,0,&s_crossfire1};
+statetype s_crossfire1 = {true,SPR_CROSSFIRE11,6,T_Projectile,0,&s_crossfire2};
+
+statetype s_crossdone5 = {false,SPR_CREXP5,6,NULL,0,NULL};
+statetype s_crossdone4 = {false,SPR_CREXP4,6,NULL,0,&s_crossdone5};
+statetype s_crossdone3 = {false,SPR_CREXP3,6,NULL,0,&s_crossdone4};
+statetype s_crossdone2 = {false,SPR_CREXP2,6,NULL,0,&s_crossdone3};
+statetype s_crossdone1 = {false,SPR_CREXP1,6,NULL,0,&s_crossdone2};
+
+
+
+//=============== gib/related states ===========================================//
+
+
+statetype s_bossdeath = {false,NOTHING,140,T_BossDied,0,NULL};
+
+statetype s_megaremove = {false,NOTHING,0,NULL,0,NULL};
+statetype s_megaexplosions = {false,NOTHING,0,T_BossExplosions,0,&s_megaexplosions};
+statetype s_superparticles = {false,NOTHING,0,T_ParticleGenerate,0,&s_superparticles};
+
+
+statetype s_gibsdone8 = {false,PARTICLE12,2,NULL,0,NULL};
+statetype s_gibsdone7 = {false,PARTICLE11,2,NULL,0,&s_gibsdone8};
+//MED
+statetype s_gibsdone6 = {false,PARTICLE10,2,NULL,0,&s_gibsdone7};
+statetype s_gibsdone5 = {false,PARTICLE09,2,NULL,0,&s_gibsdone6};
+statetype s_gibsdone4 = {false,PARTICLE08,2,NULL,0,&s_gibsdone5};
+statetype s_gibsdone3 = {false,PARTICLE07,2,NULL,0,&s_gibsdone4};
+statetype s_gibsdone2 = {false,PARTICLE06,2,NULL,0,&s_gibsdone3};
+statetype s_gibsdone1 = {false,PARTICLE05,2,NULL,0,&s_gibsdone2};
+
+statetype s_gibs4 = {false,PARTICLE04,2,T_Particle,0,&s_gibs1};
+statetype s_gibs3 = {false,PARTICLE03,2,T_Particle,0,&s_gibs4};
+statetype s_gibs2 = {false,PARTICLE02,2,T_Particle,0,&s_gibs3};
+statetype s_gibs1 = {false,PARTICLE01,2,T_Particle,0,&s_gibs2};
+
+
+
+//statetype s_head = {false,DEADHEAD,4200,NULL,0,&s_gibsdone2};
+
+statetype s_eye3 = {false,NOTHING,7,T_SlideDownScreen,SF_EYE3,&s_eye1};
+statetype s_eye2 = {false,NOTHING,7,T_SlideDownScreen,SF_EYE2,&s_eye3};
+statetype s_eye1 = {false,NOTHING,7,T_SlideDownScreen,SF_EYE1,&s_eye2};
+
+statetype s_littlesoul = {false,LITTLESOUL,0,MissileMovement,0,&s_littlesoul};
+statetype s_bigsoul = {false,BIGSOUL,0,MissileMovement,0,&s_bigsoul};
+
+
+statetype s_vaporized8 = {false,VAPORIZED8,0,T_Convert,0,NULL};
+statetype s_vaporized7 = {false,VAPORIZED7,3,NULL,0,&s_vaporized8};
+statetype s_vaporized6 = {false,VAPORIZED6,3,NULL,0,&s_vaporized7};
+statetype s_vaporized5 = {false,VAPORIZED5,3,NULL,0,&s_vaporized6};
+statetype s_vaporized4 = {false,VAPORIZED4,3,NULL,0,&s_vaporized5};
+statetype s_vaporized3 = {false,VAPORIZED3,3,NULL,0,&s_vaporized4};
+statetype s_vaporized2 = {false,VAPORIZED2,3,NULL,0,&s_vaporized3};
+statetype s_vaporized1 = {false,VAPORIZED1,3,NULL,0,&s_vaporized2};
+
+statetype s_respawn8 = {false,VAPORIZED1,0,SetShapeoffset,0,&s_player};
+statetype s_respawn7 = {false,VAPORIZED2,3,NULL,0,&s_respawn8};
+statetype s_respawn6 = {false,VAPORIZED3,3,NULL,0,&s_respawn7};
+statetype s_respawn5 = {false,VAPORIZED4,3,NULL,0,&s_respawn6};
+statetype s_respawn4 = {false,VAPORIZED5,3,NULL,0,&s_respawn5};
+statetype s_respawn3 = {false,VAPORIZED6,3,NULL,0,&s_respawn4};
+statetype s_respawn2 = {false,VAPORIZED7,3,NULL,0,&s_respawn3};
+statetype s_respawn1 = {false,VAPORIZED8,3,NULL,0,&s_respawn2};
+
+
+
+#if (SHAREWARE == 0)
+
+
+//========================= NON-SHAREWARE STATES ============================
+
+
+statetype s_scottwander7 = {false,SCOTHEAD7,4,T_CollectorWander,0,&s_scottwander1};
+statetype s_scottwander6 = {false,SCOTHEAD6,4,T_CollectorWander,0,&s_scottwander7};
+statetype s_scottwander5 = {false,SCOTHEAD5,4,T_CollectorWander,0,&s_scottwander6};
+statetype s_scottwander4 = {false,SCOTHEAD4,4,T_CollectorWander,0,&s_scottwander5};
+statetype s_scottwander3 = {false,SCOTHEAD3,4,T_CollectorWander,0,&s_scottwander4};
+statetype s_scottwander2 = {false,SCOTHEAD2,4,T_CollectorWander,0,&s_scottwander3};
+statetype s_scottwander1 = {false,SCOTHEAD1,4,T_CollectorWander,0,&s_scottwander2};
+
+statetype s_scottwanderdoor7 = {false,SCOTHEAD7,4,T_CollectorWander,0,&s_scottwanderdoor1};
+statetype s_scottwanderdoor6 = {false,SCOTHEAD6,4,T_CollectorWander,0,&s_scottwanderdoor7};
+statetype s_scottwanderdoor5 = {false,SCOTHEAD5,4,T_CollectorWander,0,&s_scottwanderdoor6};
+statetype s_scottwanderdoor4 = {false,SCOTHEAD4,4,T_CollectorWander,0,&s_scottwanderdoor5};
+statetype s_scottwanderdoor3 = {false,SCOTHEAD3,4,T_CollectorWander,0,&s_scottwanderdoor4};
+statetype s_scottwanderdoor2 = {false,SCOTHEAD2,4,T_CollectorWander,0,&s_scottwanderdoor3};
+statetype s_scottwanderdoor1 = {false,SCOTHEAD1,4,T_CollectorWander,0,&s_scottwanderdoor2};
+
+
+
+/*
+===========================================================================
+
+ OVERPATROLS (op)
+ ,
+===========================================================================
+*/
+
+statetype s_opstand = {true,SPR_OP_S1,0,T_Stand,0,&s_opstand};
+
+statetype s_oppath4 = {true,SPR_OP_W41,10,T_Path,0,&s_oppath1};
+statetype s_oppath3 = {true,SPR_OP_W31,10,T_Path,SF_CLOSE,&s_oppath4};
+statetype s_oppath2 = {true,SPR_OP_W21,10,T_Path,0,&s_oppath3};
+statetype s_oppath1 = {true,SPR_OP_W11,10,T_Path,SF_CLOSE,&s_oppath2};
+
+
+statetype s_opcollide = {false,SPR_OP_PAIN1,0,T_Collide,0,&s_opcollide};
+statetype s_opcollide2 = {false,SPR_OP_PAIN2,0,T_Collide,0,&s_opcollide2};
+
+
+//statetype s_opuse2 = {true,SPR_OP_USE21,10,T_Use,0,&s_oppath1};
+//statetype s_opuse1 = {true,SPR_OP_USE11,10,T_Use,0,&s_opuse2};
+
+
+statetype s_opshoot4 = {false,SPR_OP_SHOOT4,10,ActorMovement,0,&s_opchase1};
+statetype s_opshoot3 = {false,SPR_OP_SHOOT3,10,ActorMovement,0,&s_opshoot4};
+statetype s_opshoot2 = {false,SPR_OP_SHOOT2,20,A_Shoot,0,&s_opshoot3};
+statetype s_opshoot1 = {false,SPR_OP_SHOOT1,6,ActorMovement,0,&s_opshoot2};
+
+
+
+statetype s_opbolo5 = {false,SPR_OP_BOLOSHOOT5,6,ActorMovement,0,&s_opchase1};
+statetype s_opbolo4 = {false,SPR_OP_BOLOSHOOT4,6,ActorMovement,0,&s_opbolo5};
+statetype s_opbolo3 = {false,SPR_OP_BOLOSHOOT3,20,A_MissileWeapon,0,&s_opbolo4};
+statetype s_opbolo2 = {false,SPR_OP_BOLOSHOOT2,6,ActorMovement,0,&s_opbolo3};
+statetype s_opbolo1 = {false,SPR_OP_BOLOSHOOT1,6,ActorMovement,0,&s_opbolo2};
+
+
+statetype s_bolocast4 = {false,SPR_BOLO4,6,T_Projectile,0,&s_bolocast4};
+statetype s_bolocast3 = {false,SPR_BOLO3,6,T_Projectile,0,&s_bolocast4};
+statetype s_bolocast2 = {false,SPR_BOLO2,6,T_Projectile,0,&s_bolocast3};
+statetype s_bolocast1 = {false,SPR_BOLO1,6,T_Projectile,0,&s_bolocast2};
+
+
+statetype s_opchase4 = {true,SPR_OP_W41,6,T_Chase,0,&s_opchase1};
+statetype s_opchase3 = {true,SPR_OP_W31,6,T_Chase,SF_CLOSE,&s_opchase4};
+statetype s_opchase2 = {true,SPR_OP_W21,6,T_Chase,0,&s_opchase3};
+statetype s_opchase1 = {true,SPR_OP_W11,6,T_Chase,SF_CLOSE,&s_opchase2};
+
+
+statetype s_opdead = {false,SPR_OP_ALTDEAD,0,T_Collide,0,&s_opdead};
+statetype s_opdie5 = {false,SPR_OP_ALTDIE5,5,T_Collide,0,&s_opdead};
+statetype s_opdie4 = {false,SPR_OP_ALTDIE4,5,T_Collide,0,&s_opdie5};
+statetype s_opdie3 = {false,SPR_OP_ALTDIE3,5,T_Collide,0,&s_opdie4};
+statetype s_opdie2 = {false,SPR_OP_ALTDIE2,5,T_Collide,0,&s_opdie3};
+statetype s_opdie1 = {false,SPR_OP_ALTDIE1,5,T_Collide,0,&s_opdie2};
+
+statetype s_opdie1rev = {false,SPR_OP_ALTDIE1,5,T_Collide,0,&s_opstand};
+statetype s_opdie2rev = {false,SPR_OP_ALTDIE2,5,T_Collide,0,&s_opdie1rev};
+statetype s_opdie3rev = {false,SPR_OP_ALTDIE3,5,T_Collide,0,&s_opdie2rev};
+statetype s_opdie4rev = {false,SPR_OP_ALTDIE4,5,T_Collide,0,&s_opdie3rev};
+statetype s_opdie5rev = {false,SPR_OP_ALTDIE5,5,T_Collide,0,&s_opdie4rev};
+
+
+statetype s_opcrushed2 = {false,SPR_OP_DIE3,2,NULL,0,&s_opdead};
+statetype s_opcrushed1 = {false,SPR_OP_DIE1,2,NULL,0,&s_opcrushed2};
+
+
+
+/*
+============================================================================
+
+ DEATH MONKS
+
+============================================================================
+*/
+
+
+statetype s_dmonkstand = {true,SPR_MONK_S1,0,T_Stand,0,&s_dmonkstand};
+
+statetype s_dmonkpath4 = {true,SPR_MONK_W41,10,T_Path,0,&s_dmonkpath1};
+statetype s_dmonkpath3 = {true,SPR_MONK_W31,10,T_Path,SF_CLOSE,&s_dmonkpath4};
+statetype s_dmonkpath2 = {true,SPR_MONK_W21,10,T_Path,0,&s_dmonkpath3};
+statetype s_dmonkpath1 = {true,SPR_MONK_W11,10,T_Path,SF_CLOSE,&s_dmonkpath2};
+
+
+statetype s_dmonkcollide = {false,SPR_MONK_PAIN1,0,T_Collide,0,&s_dmonkcollide};
+statetype s_dmonkcollide2 = {false,SPR_MONK_PAIN2,0,T_Collide,0,&s_dmonkcollide2};
+
+
+statetype s_dmonkshoot6 = {false,SPR_MONK_DRAIN6,20,ActorMovement,0,&s_dmonkchase1};
+statetype s_dmonkshoot5 = {false,SPR_MONK_DRAIN5,20,ActorMovement,0,&s_dmonkshoot6};
+statetype s_dmonkshoot4 = {false,SPR_MONK_DRAIN4,20,ActorMovement,0,&s_dmonkshoot3};
+statetype s_dmonkshoot3 = {false,SPR_MONK_DRAIN3,20,A_Drain,0,&s_dmonkshoot4};
+statetype s_dmonkshoot2 = {false,SPR_MONK_DRAIN2,20,ActorMovement,0,&s_dmonkshoot3};
+statetype s_dmonkshoot1 = {false,SPR_MONK_DRAIN1,20,A_Drain,0,&s_dmonkshoot2};
+
+statetype s_dmonkchase4 = {true,SPR_MONK_W41,6,T_Chase,0,&s_dmonkchase1};
+statetype s_dmonkchase3 = {true,SPR_MONK_W31,6,T_Chase,SF_CLOSE,&s_dmonkchase4};
+statetype s_dmonkchase2 = {true,SPR_MONK_W21,6,T_Chase,0,&s_dmonkchase3};
+statetype s_dmonkchase1 = {true,SPR_MONK_W11,6,T_Chase,SF_CLOSE,&s_dmonkchase2};
+
+statetype s_dmonkdead = {false,SPR_MONK_DEAD,0,T_Collide,0,&s_dmonkdead};
+statetype s_dmonkdie4 = {false,SPR_MONK_DIE4,5,T_Collide,0,&s_dmonkdead};
+statetype s_dmonkdie3 = {false,SPR_MONK_DIE3,5,T_Collide,0,&s_dmonkdie4};
+statetype s_dmonkdie2 = {false,SPR_MONK_DIE2,5,T_Collide,0,&s_dmonkdie3};
+statetype s_dmonkdie1 = {false,SPR_MONK_DIE1,5,T_Collide,0,&s_dmonkdie2};
+
+statetype s_dmonkdie1rev = {false,SPR_MONK_DIE1,5,T_Collide,0, &s_dmonkstand};
+statetype s_dmonkdie2rev = {false,SPR_MONK_DIE2,5,T_Collide,0,&s_dmonkdie1rev};
+statetype s_dmonkdie3rev = {false,SPR_MONK_DIE3,5,T_Collide,0,&s_dmonkdie2rev};
+statetype s_dmonkdie4rev = {false,SPR_MONK_DIE4,5,T_Collide,0,&s_dmonkdie3rev};
+
+statetype s_dmonkcrushed2 = {false,SPR_MONK_DIE3,2,NULL,0,&s_dmonkdead};
+statetype s_dmonkcrushed1 = {false,SPR_MONK_DIE1,2,NULL,0,&s_dmonkcrushed2};
+
+/*
+============================================================================
+
+ DEATH FIRE MONKS
+
+============================================================================
+*/
+
+statetype s_firemonkstand = {true,SPR_FIREMONK_S1,0,T_Stand,0,&s_firemonkstand};
+
+statetype s_firemonkpath4 = {true,SPR_FIREMONK_W41,10,T_Path,0,&s_firemonkpath1};
+statetype s_firemonkpath3 = {true,SPR_FIREMONK_W31,10,T_Path,SF_CLOSE,&s_firemonkpath4};
+statetype s_firemonkpath2 = {true,SPR_FIREMONK_W21,10,T_Path,0,&s_firemonkpath3};
+statetype s_firemonkpath1 = {true,SPR_FIREMONK_W11,10,T_Path,SF_CLOSE,&s_firemonkpath2};
+
+
+statetype s_firemonkcollide = {false,SPR_FIREMONK_PAIN1,0,T_Collide,0,&s_firemonkcollide};
+statetype s_firemonkcollide2 = {false,SPR_FIREMONK_PAIN2,0,T_Collide,0,&s_firemonkcollide2};
+
+statetype s_firemonkcast7 = {false,SPR_FIREMONK_CAST7,6,ActorMovement,0,&s_firemonkchase1};
+statetype s_firemonkcast6 = {false,SPR_FIREMONK_CAST6,40,A_MissileWeapon,0,&s_firemonkcast7};
+statetype s_firemonkcast5 = {false,SPR_FIREMONK_CAST5,6,ActorMovement,0,&s_firemonkcast6};
+statetype s_firemonkcast4 = {false,SPR_FIREMONK_CAST4,6,ActorMovement,0,&s_firemonkcast5};
+statetype s_firemonkcast3 = {false,SPR_FIREMONK_CAST3,6,ActorMovement,0,&s_firemonkcast4};
+statetype s_firemonkcast2 = {false,SPR_FIREMONK_CAST2,6,ActorMovement,0,&s_firemonkcast3};
+statetype s_firemonkcast1 = {false,SPR_FIREMONK_CAST1,6,ActorMovement,0,&s_firemonkcast2};
+
+statetype s_monkfire4 = {false,MONKFIRE4,3,T_Projectile,0,&s_monkfire1};
+statetype s_monkfire3 = {false,MONKFIRE3,3,T_Projectile,0,&s_monkfire4};
+statetype s_monkfire2 = {false,MONKFIRE2,3,T_Projectile,0,&s_monkfire3};
+statetype s_monkfire1 = {false,MONKFIRE1,3,T_Projectile,0,&s_monkfire2};
+
+
+statetype s_fireballhit3 = {false,SPR_FIREBALL_HIT3,5,NULL,0,NULL};
+statetype s_fireballhit2 = {false,SPR_FIREBALL_HIT2,5,NULL,0,&s_fireballhit3};
+statetype s_fireballhit1 = {false,SPR_FIREBALL_HIT1,5,NULL,0,&s_fireballhit2};
+
+statetype s_firemonkchase4 = {true,SPR_FIREMONK_W41,6,T_Chase,0,&s_firemonkchase1};
+statetype s_firemonkchase3 = {true,SPR_FIREMONK_W31,6,T_Chase,SF_CLOSE,&s_firemonkchase4};
+statetype s_firemonkchase2 = {true,SPR_FIREMONK_W21,6,T_Chase,0,&s_firemonkchase3};
+statetype s_firemonkchase1 = {true,SPR_FIREMONK_W11,6,T_Chase,SF_CLOSE,&s_firemonkchase2};
+
+
+statetype s_firemonkdead7 = {false,SPR_FIREMONK_DEAD7,0,T_Collide,0,&s_firemonkdead7};
+statetype s_firemonkdead6 = {false,SPR_FIREMONK_DEAD6,5,T_Collide,0,&s_firemonkdead7};
+statetype s_firemonkdead5 = {false,SPR_FIREMONK_DEAD5,5,T_Collide,0,&s_firemonkdead6};
+statetype s_firemonkdead4 = {false,SPR_FIREMONK_DEAD4,5,T_Collide,0,&s_firemonkdead5};
+statetype s_firemonkdead3 = {false,SPR_FIREMONK_DEAD3,5,T_Collide,0,&s_firemonkdead4};
+statetype s_firemonkdead2 = {false,SPR_FIREMONK_DEAD2,5,T_Collide,0,&s_firemonkdead3};
+statetype s_firemonkdead = {false,SPR_FIREMONK_DEAD1,5,T_Collide,0,&s_firemonkdead2};
+statetype s_firemonkdie4 = {false,SPR_FIREMONK_DIE3,5,T_Collide,0,&s_firemonkdead};
+statetype s_firemonkdie3 = {false,SPR_FIREMONK_DIE3,5,T_Collide,0,&s_firemonkdie4};
+statetype s_firemonkdie2 = {false,SPR_FIREMONK_DIE2,5,T_Collide,0,&s_firemonkdie3};
+statetype s_firemonkdie1 = {false,SPR_FIREMONK_DIE1,5,T_Collide,0,&s_firemonkdie2};
+
+
+statetype s_firemonkdie1rev = {false,SPR_FIREMONK_DIE1,5,T_Collide,0,&s_firemonkstand};
+statetype s_firemonkdie2rev = {false,SPR_FIREMONK_DIE2,5,T_Collide,0,&s_firemonkdie1rev};
+statetype s_firemonkdie3rev = {false,SPR_FIREMONK_DIE3,5,T_Collide,0,&s_firemonkdie2rev};
+statetype s_firemonkdie4rev = {false,SPR_FIREMONK_DIE3,5,T_Collide,0,&s_firemonkdie3rev};
+
+
+statetype s_firemonkcrushed2 = {false,SPR_FIREMONK_DIE3,2,NULL,0,&s_firemonkdead};
+statetype s_firemonkcrushed1 = {false,SPR_FIREMONK_DIE1,2,NULL,0,&s_firemonkcrushed2};
+
+/*===========================================================================
+
+ INSANE WALL DUDE
+
+============================================================================*/
+
+
+statetype s_wallstand = {16,BCRAFT01,0,T_Stand,0,&s_wallstand};
+
+statetype s_wallpath = {16,BCRAFT01,20,T_AutoPath,0,&s_wallpath};
+
+statetype s_wallshoot = {16,BCRAFT01,15,A_MissileWeapon,0,&s_wallshoot};
+
+statetype s_wallalign = {16,BCRAFT01,0,T_AutoShootAlign,0,&s_wallalign};
+statetype s_wallwait = {16,BCRAFT01,0,NULL,0,&s_wallwait};
+statetype s_wallrestore = {16,BCRAFT01,0,T_AutoRealign,0,&s_wallrestore};
+
+
+
+statetype s_wallcollide = {16,BCRAFT01,0,T_Collide,0,&s_wallcollide};
+
+
+/*
+===========================================================================
+
+ ESAU GUDERIAN
+
+===========================================================================
+*/
+
+
+
+
+statetype s_darianstand = {true,SPR_DARIAN_S1,0,T_Stand,0,&s_darianstand};
+
+statetype s_darianchase4 = {true,SPR_DARIAN_W41,8,T_EsauChase,0,&s_darianchase1};
+statetype s_darianchase3 = {true,SPR_DARIAN_W31,8,T_EsauChase,SF_CLOSE,&s_darianchase4};
+statetype s_darianchase2 = {true,SPR_DARIAN_W21,8,T_EsauChase,0,&s_darianchase3};
+statetype s_darianchase1 = {true,SPR_DARIAN_W11,8,T_EsauChase,SF_CLOSE,&s_darianchase2};
+
+
+statetype s_darianrise8 = {false,SPR_DARIAN_SINK1,3,NULL,0,&s_darianwait};
+statetype s_darianrise7 = {false,SPR_DARIAN_SINK2,3,NULL,0,&s_darianrise8};
+statetype s_darianrise6 = {false,SPR_DARIAN_SINK3,3,NULL,0,&s_darianrise7};
+statetype s_darianrise5 = {false,SPR_DARIAN_SINK4,3,NULL,0,&s_darianrise6};
+statetype s_darianrise4 = {false,SPR_DARIAN_SINK5,3,NULL,0,&s_darianrise5};
+statetype s_darianrise3 = {false,SPR_DARIAN_SINK6,3,NULL,0,&s_darianrise4};
+statetype s_darianrise2 = {false,SPR_DARIAN_SINK7,3,NULL,0,&s_darianrise3};
+statetype s_darianrise1 = {false,SPR_DARIAN_SINK8,3,NULL,0,&s_darianrise2};
+
+
+statetype s_dariansink9 = {false,NOTHING,110,T_EsauRise,0,&s_darianrise1};
+statetype s_dariansink8 = {false,SPR_DARIAN_SINK8,3,NULL,0,&s_dariansink9};
+statetype s_dariansink7 = {false,SPR_DARIAN_SINK7,3,NULL,0,&s_dariansink8};
+statetype s_dariansink6 = {false,SPR_DARIAN_SINK6,3,NULL,0,&s_dariansink7};
+statetype s_dariansink5 = {false,SPR_DARIAN_SINK5,3,NULL,0,&s_dariansink6};
+statetype s_dariansink4 = {false,SPR_DARIAN_SINK4,3,NULL,0,&s_dariansink5};
+statetype s_dariansink3 = {false,SPR_DARIAN_SINK3,3,NULL,0,&s_dariansink4};
+statetype s_dariansink2 = {false,SPR_DARIAN_SINK2,3,NULL,0,&s_dariansink3};
+statetype s_dariansink1 = {false,SPR_DARIAN_SINK1,3,NULL,0,&s_dariansink2};
+
+
+statetype s_dariancollide = {false,SPR_DARIAN_PAIN1,0,T_Collide,0,&s_dariancollide};
+statetype s_dariancollide2 = {false,SPR_DARIAN_PAIN2,0,T_Collide,0,&s_dariancollide2};
+
+
+statetype s_darianshoot4 = {false,SPR_DARIAN_SHOOT4,10,NULL,0,&s_darianchase1};
+statetype s_darianshoot3 = {false,SPR_DARIAN_SHOOT3,10,NULL,0,&s_darianshoot4};
+statetype s_darianshoot2 = {false,SPR_DARIAN_SHOOT2,20,A_MissileWeapon,0,&s_darianshoot3};
+statetype s_darianshoot1 = {false,SPR_DARIAN_SHOOT1,10,NULL,0,&s_darianshoot2};
+
+statetype s_dariandefend3 = {false,SPR_DARIAN_SHOOT3,10,NULL,0,&s_darianwait};
+statetype s_dariandefend2 = {false,SPR_DARIAN_SHOOT2,20,A_MissileWeapon,0,&s_dariandefend3};
+statetype s_dariandefend1 = {false,SPR_DARIAN_SHOOT1,10,NULL,0,&s_dariandefend2};
+
+
+statetype s_darianuse4 = {true,SPR_DARIAN_USE11,10,NULL,0,&s_darianspears};
+statetype s_darianuse3 = {true,SPR_DARIAN_USE21,10,T_Use,0,&s_darianuse4};
+statetype s_darianuse2 = {true,SPR_DARIAN_USE11,30,NULL,0,&s_darianuse3};
+statetype s_darianuse1 = {true,SPR_DARIAN_S1,40,NULL,0,&s_darianuse2};
+
+statetype s_darianwait = {false,SPR_DARIAN_SHOOT1,0,T_EsauWait,0,&s_darianwait};
+
+statetype s_darianspears = {true,SPR_DARIAN_S1,280,NULL,0,&s_darianchase1};
+
+
+statetype s_dspear16 = {false,SPEARDOWN7,2,T_Spears,SF_DOWN,NULL};
+statetype s_dspear15 = {false,SPEARDOWN6,2,T_Spears,SF_CRUSH,&s_dspear16};
+statetype s_dspear14 = {false,SPEARDOWN5,2,T_Spears,SF_CRUSH,&s_dspear15};
+statetype s_dspear13 = {false,SPEARDOWN4,2,T_Spears,SF_CRUSH,&s_dspear14};
+statetype s_dspear12 = {false,SPEARDOWN3,2,T_Spears,SF_CRUSH,&s_dspear13};
+statetype s_dspear11 = {false,SPEARDOWN2,2,T_Spears,SF_CRUSH,&s_dspear12};
+statetype s_dspear10 = {false,SPEARDOWN1,2,T_Spears,SF_CRUSH,&s_dspear11};
+statetype s_dspear9 = {false,SPEARDOWN16,2,T_Spears,SF_CRUSH,&s_dspear10};
+statetype s_dspear8 = {false,SPEARDOWN15,2,T_Spears,SF_CRUSH,&s_dspear9};
+statetype s_dspear7 = {false,SPEARDOWN14,2,T_Spears,SF_CRUSH,&s_dspear8};
+statetype s_dspear6 = {false,SPEARDOWN13,2,T_Spears,SF_CRUSH,&s_dspear7};
+statetype s_dspear5 = {false,SPEARDOWN12,2,T_Spears,SF_CRUSH,&s_dspear6};
+statetype s_dspear4 = {false,SPEARDOWN11,2,T_Spears,SF_CRUSH,&s_dspear5};
+statetype s_dspear3 = {false,SPEARDOWN10,2,T_Spears,SF_CRUSH,&s_dspear4};
+statetype s_dspear2 = {false,SPEARDOWN9,2,T_Spears,SF_DOWN,&s_dspear3};
+statetype s_dspear1 = {false,SPEARDOWN8,2,T_Spears,SF_DOWN,&s_dspear2};
+
+
+statetype s_dariandead2 = {false,SPR_DARIAN_DEAD,0,T_BossDied,0,&s_dariandead2};
+statetype s_dariandead1 = {false,SPR_DARIAN_DEAD,140,NULL,0,&s_dariandead2};
+statetype s_dariandead = {false,SPR_DARIAN_DEAD,0,NULL,0,&s_dariandead1};
+
+statetype s_dariandie10 = {false,SPR_DARIAN_DIE10,5,NULL,0,&s_dariandead};
+statetype s_dariandie9 = {false,SPR_DARIAN_DIE9,5,NULL,0,&s_dariandie10};
+statetype s_dariandie8 = {false,SPR_DARIAN_DIE8,5,NULL,0,&s_dariandie9};
+statetype s_dariandie7 = {false,SPR_DARIAN_DIE7,5,NULL,0,&s_dariandie8};
+statetype s_dariandie6 = {false,SPR_DARIAN_DIE6,5,T_Guts,0,&s_dariandie7};
+statetype s_dariandie5 = {false,SPR_DARIAN_DIE5,5,NULL,0,&s_dariandie6};
+statetype s_dariandie4 = {false,SPR_DARIAN_DIE4,5,NULL,0,&s_dariandie5};
+statetype s_dariandie3 = {false,SPR_DARIAN_DIE3,5,NULL,0,&s_dariandie4};
+statetype s_dariandie2 = {false,SPR_DARIAN_DIE2,5,NULL,0,&s_dariandie3};
+statetype s_dariandie1 = {false,SPR_DARIAN_DIE1,70,T_Collide,0,&s_dariandie2};
+
+
+
+/*
+===========================================================================
+
+ HEINRICH KRIST
+
+===========================================================================
+*/
+
+
+statetype s_heinrichstand = {true,SPR_KRIST_S1,0,T_Stand,0,&s_heinrichstand};
+
+statetype s_heinrichchase = {true,SPR_KRIST_FOR1,10,T_HeinrichChase,0,&s_heinrichchase};
+
+
+statetype s_kristleft = {true,SPR_KRIST_LEFT1,10,T_KristLeft,0,&s_kristleft};
+
+statetype s_kristright = {true,SPR_KRIST_RIGHT1,10,T_KristRight,0,&s_kristright};
+
+statetype s_heinrichshoot11 = {false,SPR_KRIST_SHOOT11,8,NULL,0,&s_heinrichchase};
+statetype s_heinrichshoot10 = {false,SPR_KRIST_SHOOT10,8,NULL,0,&s_heinrichshoot11};
+statetype s_heinrichshoot9 = {false,SPR_KRIST_SHOOT9,8,A_HeinrichShoot,0,&s_heinrichshoot10};
+statetype s_heinrichshoot8 = {false,SPR_KRIST_SHOOT8,8,NULL,0,&s_heinrichshoot9};
+statetype s_heinrichshoot7 = {false,SPR_KRIST_SHOOT7,8,T_KristCheckFire,0,&s_heinrichshoot8};
+statetype s_heinrichshoot6 = {false,SPR_KRIST_SHOOT6,8,NULL,0,&s_heinrichshoot7};
+statetype s_heinrichshoot5 = {false,SPR_KRIST_SHOOT5,8,NULL,0,&s_heinrichshoot6};
+statetype s_heinrichshoot4 = {false,SPR_KRIST_SHOOT4,8,A_HeinrichShoot,0,&s_heinrichshoot5};
+statetype s_heinrichshoot3 = {false,SPR_KRIST_SHOOT3,8,NULL,0,&s_heinrichshoot4};
+statetype s_heinrichshoot2 = {false,SPR_KRIST_SHOOT2,8,NULL,0,&s_heinrichshoot3};
+statetype s_heinrichshoot1 = {false,SPR_KRIST_SHOOT1,8,T_KristCheckFire,0,&s_heinrichshoot2};
+
+statetype s_missile1 = {16,SPR_BJMISS11,6,T_Projectile,0,&s_missile1};
+
+
+statetype s_missilehit3 = {false,SPR_MISSILEHIT3,6,NULL,0,NULL};
+statetype s_missilehit2 = {false,SPR_MISSILEHIT2,6,NULL,0,&s_missilehit3};
+statetype s_missilehit1 = {false,SPR_MISSILEHIT1,6,NULL,0,&s_missilehit2};
+
+statetype s_mine4 = {false,SPR_MINE4,3,T_Projectile,0,&s_mine1};
+statetype s_mine3 = {false,SPR_MINE3,3,T_Projectile,0,&s_mine4};
+statetype s_mine2 = {false,SPR_MINE2,3,T_Projectile,0,&s_mine3};
+statetype s_mine1 = {false,SPR_MINE1,3,T_Projectile,0,&s_mine2};
+
+statetype s_heinrichdefend = {true,SPR_KRIST_MINERIGHT1,35,T_Heinrich_Defend,0,&s_heinrichdefend};
+
+
+statetype s_heinrichooc = {true,SPR_KRIST_DEAD1,0,T_Heinrich_Out_of_Control,0,&s_heinrichooc};
+
+statetype s_heinrichdead = {false,SPR_KRIST_DEAD1,35,T_Collide,0,&s_heinrichooc};
+
+statetype s_heinrichdie2 = {false,SPR_KRIST_DIE2,35,T_Collide,0,&s_heinrichdead};
+statetype s_heinrichdie1 = {false,SPR_KRIST_DIE1,35,T_Collide,0,&s_heinrichdie2};
+
+statetype s_heindead2 = {false,-1,0,T_BossDied,0,NULL};
+statetype s_heindead1 = {false, -1, 140,NULL,0,&s_heindead2};
+statetype s_heinexp13 = {false,SPR_EXPLOSION13,2,NULL,0,&s_heindead1};
+statetype s_heinexp12 = {false,SPR_EXPLOSION12,2,NULL,0,&s_heinexp13};
+statetype s_heinexp11 = {false,SPR_EXPLOSION11,2,NULL,0,&s_heinexp12};
+statetype s_heinexp10 = {false,SPR_EXPLOSION10,2,NULL,0,&s_heinexp11};
+statetype s_heinexp9 = {false,SPR_EXPLOSION9,2,NULL,0,&s_heinexp10};
+statetype s_heinexp8 = {false,SPR_EXPLOSION8,2,NULL,0,&s_heinexp9};
+statetype s_heinexp7 = {false,SPR_EXPLOSION7,2,NULL,0,&s_heinexp8};
+statetype s_heinexp6 = {false,SPR_EXPLOSION6,2,NULL,0,&s_heinexp7};
+statetype s_heinexp5 = {false,SPR_EXPLOSION5,2,NULL,0,&s_heinexp6};
+statetype s_heinexp4 = {false,SPR_EXPLOSION4,2,NULL,0,&s_heinexp5};
+statetype s_heinexp3 = {false,SPR_EXPLOSION3,2,T_Explosion,0,&s_heinexp4};
+statetype s_heinexp2 = {false,SPR_EXPLOSION2,2,NULL,0,&s_heinexp3};
+statetype s_heinexp1 = {false,SPR_EXPLOSION1,0,NULL,0,&s_heinexp2};
+
+
+/*
+===========================================================================
+
+ DARK MONK (TOM)
+
+===========================================================================
+*/
+
+
+statetype s_darkmonkstand = {true,TOMS1,0,T_Stand,0,&s_darkmonkstand};
+
+statetype s_darkmonkland = {true,TOMFLY11,6,NULL,0,&s_darkmonkstand};
+
+
+statetype s_darkmonkchase2 = {true,TOMFLY21,10,T_DarkmonkChase,0,&s_darkmonkchase2};
+statetype s_darkmonkchase1 = {true,TOMFLY11,3,T_DarkmonkChase,0,&s_darkmonkchase2};
+
+statetype s_dmlandandfire = {true,TOMFLY11,0,T_DarkmonkLandAndFire,0,&s_dmlandandfire};
+
+statetype s_darkmonkcover3 = {false,TAWAKEN1,1,NULL,0,&s_darkmonkawaken1};
+statetype s_darkmonkcover2 = {false,TAWAKEN2,1,NULL,0,&s_darkmonkcover3};
+statetype s_darkmonkcover1 = {false,TAWAKEN3,1,NULL,0,&s_darkmonkcover2};
+
+
+statetype s_darkmonkawaken5 = {false,TAWAKEN5,3,NULL,0,&s_darkmonkchase1};
+statetype s_darkmonkawaken4 = {false,TAWAKEN4,3,NULL,0,&s_darkmonkawaken5};
+statetype s_darkmonkawaken3 = {false,TAWAKEN3,3,NULL,0,&s_darkmonkawaken4};
+statetype s_darkmonkawaken2 = {false,TAWAKEN2,3,NULL,0,&s_darkmonkawaken3};
+statetype s_darkmonkawaken1 = {false,TAWAKEN1,3,NULL,0,&s_darkmonkawaken2};
+
+
+statetype s_darkmonklightning11 = {false,TOMLG11,3,NULL,0,&s_darkmonkchase1};
+statetype s_darkmonklightning10 = {false,TOMLG10,3,NULL,0,&s_darkmonklightning11};
+statetype s_darkmonklightning9 = {false,TOMLG9,70,A_DmonkAttack,0,&s_darkmonklightning10};
+statetype s_darkmonklightning8 = {false,TOMLG8,3,NULL,0,&s_darkmonklightning9};
+statetype s_darkmonklightning7 = {false,TOMLG7,3,NULL,0,&s_darkmonklightning8};
+statetype s_darkmonklightning6 = {false,TOMLG6,3,NULL,0,&s_darkmonklightning7};
+statetype s_darkmonklightning5 = {false,TOMLG5,3,NULL,0,&s_darkmonklightning6};
+statetype s_darkmonklightning4 = {false,TOMLG4,3,NULL,0,&s_darkmonklightning5};
+statetype s_darkmonklightning3 = {false,TOMLG3,3,NULL,0,&s_darkmonklightning4};
+statetype s_darkmonklightning2 = {false,TOMLG2,3,NULL,0,&s_darkmonklightning3};
+statetype s_darkmonklightning1 = {false,TOMLG1,3,NULL,0,&s_darkmonklightning2};
+
+statetype s_darkmonkfspark6 = {false,TOMFS6,3,NULL,0,&s_darkmonkchase1};
+statetype s_darkmonkfspark5 = {false,TOMFS5,70,A_DmonkAttack,0,&s_darkmonkfspark6};
+statetype s_darkmonkfspark4 = {false,TOMFS4,3,NULL,0,&s_darkmonkfspark5};
+statetype s_darkmonkfspark3 = {false,TOMFS3,3,NULL,0,&s_darkmonkfspark4};
+statetype s_darkmonkfspark2 = {false,TOMFS2,3,NULL,0,&s_darkmonkfspark3};
+statetype s_darkmonkfspark1 = {false,TOMFS1,3,NULL,0,&s_darkmonkfspark2};
+
+
+statetype s_darkmonkbreathe8 = {false,TOMBR8,3,NULL,0,&s_darkmonkchase1};
+statetype s_darkmonkbreathe7 = {false,TOMBR7,3,NULL,0,&s_darkmonkbreathe8};
+statetype s_darkmonkbreathe6 = {false,TOMBR6,70,A_DmonkAttack,0,&s_darkmonkbreathe7};
+statetype s_darkmonkbreathe5 = {false,TOMBR5,3,NULL,0,&s_darkmonkbreathe6};
+statetype s_darkmonkbreathe4 = {false,TOMBR4,3,NULL,0,&s_darkmonkbreathe5};
+statetype s_darkmonkbreathe3 = {false,TOMBR3,3,NULL,0,&s_darkmonkbreathe4};
+statetype s_darkmonkbreathe2 = {false,TOMBR2,3,NULL,0,&s_darkmonkbreathe3};
+statetype s_darkmonkbreathe1 = {false,TOMBR1,70,NULL,0,&s_darkmonkbreathe2};
+
+statetype s_darkmonksummon3 = {false,TOMBR1,3,NULL,0,&s_darkmonkchase1};
+statetype s_darkmonksummon2 = {false,TOMBR3,3,NULL,0,&s_darkmonksummon3};
+statetype s_darkmonksummon1 = {false,TOMBR2,3,NULL,0,&s_darkmonksummon2};
+
+statetype s_snakepath = {true,TOMHEAD1,0,T_SnakePath,0,&s_snakepath};
+statetype s_snakefindpath = {true,TOMHEAD1,0,T_SnakeFindPath,0,&s_snakefindpath};
+
+statetype s_darkmonkhead = {true,TOMHEAD1,0,T_DarkSnakeChase,0,&s_darkmonkhead};
+statetype s_darkmonksnakelink = {true,TOMHEAD1,0,T_GenericMove,0,&s_darkmonksnakelink};
+
+
+statetype s_darkmonkhspawn = {false,NOTHING,78,T_DarkSnakeSpawn,0,NULL};
+statetype s_darkmonkfastspawn = {false,NOTHING,35,T_DarkSnakeSpawn,0,NULL};
+
+statetype s_darkmonkheaddead = {false,THDIE2,0,NULL,0,&s_darkmonkheaddead};
+statetype s_darkmonkheaddie1 = {false,THDIE1,1400,T_SnakeFinale,0,&s_snakefireworks1};
+
+statetype s_snakefireworks2 = {false,THDIE2,10,T_SnakeFinale,0,&s_snakefireworks1};
+statetype s_snakefireworks1 = {false,THDIE1,10,T_SnakeFinale,0,&s_snakefireworks2};
+
+statetype s_darkmonkhball9 = {false,THBALL9,5,NULL,0,&s_darkmonkchase1};
+statetype s_darkmonkhball8 = {false,THBALL8,5,NULL,0,&s_darkmonkhball9};
+statetype s_darkmonkhball7 = {false,THBALL7,5,A_DmonkAttack,0,&s_darkmonkhball8};
+statetype s_darkmonkhball6 = {false,THBALL6,5,NULL,0,&s_darkmonkhball7};
+statetype s_darkmonkhball5 = {false,THBALL5,5,NULL,0,&s_darkmonkhball6};
+statetype s_darkmonkhball4 = {false,THBALL4,5,NULL,0,&s_darkmonkhball5};
+statetype s_darkmonkhball3 = {false,THBALL3,5,NULL,0,&s_darkmonkhball4};
+statetype s_darkmonkhball2 = {false,THBALL2,5,NULL,0,&s_darkmonkhball3};
+statetype s_darkmonkhball1 = {false,THBALL1,70,NULL,0,&s_darkmonkhball2};
+
+statetype s_darkmonkabsorb9 = {false,THBALL9,3,NULL,0,&s_darkmonksphere1};
+statetype s_darkmonkabsorb8 = {false,THBALL8,3,NULL,0,&s_darkmonkabsorb9};
+statetype s_darkmonkabsorb7 = {false,THBALL7,3,NULL,0,&s_darkmonkabsorb8};
+statetype s_darkmonkabsorb6 = {false,THBALL6,3,NULL,0,&s_darkmonkabsorb7};
+statetype s_darkmonkabsorb5 = {false,THBALL5,3,NULL,0,&s_darkmonkabsorb6};
+statetype s_darkmonkabsorb4 = {false,THBALL4,3,NULL,0,&s_darkmonkabsorb5};
+statetype s_darkmonkabsorb3 = {false,THBALL3,3,NULL,0,&s_darkmonkabsorb4};
+statetype s_darkmonkabsorb2 = {false,THBALL2,3,NULL,0,&s_darkmonkabsorb3};
+statetype s_darkmonkabsorb1 = {false,THBALL1,3,NULL,0,&s_darkmonkabsorb2};
+
+
+statetype s_darkmonksphere10 = {false,TSPHERE10,4,NULL,0,&s_darkmonkchase1};
+statetype s_darkmonksphere9 = {false,TSPHERE9,4,NULL,0,&s_darkmonksphere10};
+statetype s_darkmonksphere8 = {false,TSPHERE8,4,A_DmonkAttack,0,&s_darkmonksphere9};
+statetype s_darkmonksphere7 = {false,TSPHERE7,4,NULL,0,&s_darkmonksphere8};
+statetype s_darkmonksphere6 = {false,TSPHERE6,4,NULL,0,&s_darkmonksphere7};
+statetype s_darkmonksphere5 = {false,TSPHERE5,4,NULL,0,&s_darkmonksphere6};
+statetype s_darkmonksphere4 = {false,TSPHERE4,4,NULL,0,&s_darkmonksphere5};
+statetype s_darkmonksphere3 = {false,TSPHERE3,4,NULL,0,&s_darkmonksphere4};
+statetype s_darkmonksphere2 = {false,TSPHERE2,4,NULL,0,&s_darkmonksphere3};
+statetype s_darkmonksphere1 = {false,TSPHERE1,4,NULL,0,&s_darkmonksphere2};
+
+statetype s_dmgreenthing10 = {false,TSPHERE10,4,NULL,0,&s_darkmonkchase1};
+statetype s_dmgreenthing9 = {false,TSPHERE9,4,NULL,0,&s_dmgreenthing10};
+statetype s_dmgreenthing8 = {false,TSPHERE8,4,A_DmonkAttack,0,&s_dmgreenthing9};
+statetype s_dmgreenthing7 = {false,TSPHERE7,4,NULL,0,&s_dmgreenthing8};
+statetype s_dmgreenthing6 = {false,TSPHERE6,4,NULL,0,&s_dmgreenthing7};
+statetype s_dmgreenthing5 = {false,TSPHERE5,4,NULL,0,&s_dmgreenthing6};
+statetype s_dmgreenthing4 = {false,TSPHERE4,4,NULL,0,&s_dmgreenthing5};
+statetype s_dmgreenthing3 = {false,TSPHERE3,4,NULL,0,&s_dmgreenthing4};
+statetype s_dmgreenthing2 = {false,TSPHERE2,4,NULL,0,&s_dmgreenthing3};
+statetype s_dmgreenthing1 = {false,TSPHERE1,4,NULL,0,&s_dmgreenthing2};
+
+
+statetype s_energysphere4 = {false,TOMSPHERE4,4,T_Projectile,0,&s_energysphere1};
+statetype s_energysphere3 = {false,TOMSPHERE3,4,T_Projectile,0,&s_energysphere4};
+statetype s_energysphere2 = {false,TOMSPHERE2,4,T_Projectile,0,&s_energysphere3};
+statetype s_energysphere1 = {false,TOMSPHERE1,4,T_Projectile,0,&s_energysphere2};
+
+
+statetype s_lightning = {true,TOMLIGHTNING1,0,T_Projectile,0,&s_lightning};
+
+
+statetype s_handball2 = {false,TOMHANDBALL2,3,T_Projectile,0,&s_handball1};
+statetype s_handball1 = {false,TOMHANDBALL1,3,T_Projectile,0,&s_handball2};
+
+statetype s_faceball2 = {false,TOMFACEBALL2,3,T_Projectile,0,&s_faceball1};
+statetype s_faceball1 = {false,TOMFACEBALL1,3,T_Projectile,0,&s_faceball2};
+
+statetype s_floorspark4 = {false,TOMFLOORSPARK4,3,T_Projectile,0,&s_floorspark1};
+statetype s_floorspark3 = {false,TOMFLOORSPARK3,3,T_Projectile,0,&s_floorspark4};
+statetype s_floorspark2 = {false,TOMFLOORSPARK2,3,T_Projectile,0,&s_floorspark3};
+statetype s_floorspark1 = {false,TOMFLOORSPARK1,3,T_Projectile,0,&s_floorspark2};
+
+
+
+statetype s_darkmonkreact = {true,TOMFLY11,0,T_DarkmonkReact,0,&s_darkmonkreact};
+
+statetype s_darkmonkbball9 = {false,TBBALL9,4,NULL,0,&s_darkmonkchase1};
+statetype s_darkmonkbball8 = {false,TBBALL8,4,NULL,0,&s_darkmonkbball9};
+statetype s_darkmonkbball7 = {false,TBBALL7,4,A_DmonkAttack,0,&s_darkmonkbball8};
+statetype s_darkmonkbball6 = {false,TBBALL6,4,NULL,0,&s_darkmonkbball7};
+statetype s_darkmonkbball5 = {false,TBBALL5,4,NULL,0,&s_darkmonkbball6};
+statetype s_darkmonkbball4 = {false,TBBALL4,4,NULL,0,&s_darkmonkbball5};
+statetype s_darkmonkbball3 = {false,TBBALL3,4,NULL,0,&s_darkmonkbball4};
+statetype s_darkmonkbball2 = {false,TBBALL2,4,NULL,0,&s_darkmonkbball3};
+statetype s_darkmonkbball1 = {false,TBBALL1,70,NULL,0,&s_darkmonkbball2};
+
+
+statetype s_darkmonkcharge10 = {false,TSCAREB3,140,T_DarkmonkCharge,0,&s_darkmonkchase1};
+statetype s_darkmonkcharge9 = {false,TAWAKEN5,3,NULL,0,&s_darkmonkcharge10};
+statetype s_darkmonkcharge8 = {false,TAWAKEN4,3,NULL,0,&s_darkmonkcharge9};
+statetype s_darkmonkcharge7 = {false,TAWAKEN3,3,NULL,0,&s_darkmonkcharge8};
+statetype s_darkmonkcharge6 = {false,TAWAKEN2,3,NULL,0,&s_darkmonkcharge7};
+statetype s_darkmonkcharge5 = {false,TAWAKEN1,3,NULL,0,&s_darkmonkcharge6};
+statetype s_darkmonkcharge4 = {false,TAWAKEN2,3,NULL,0,&s_darkmonkcharge5};
+statetype s_darkmonkcharge3 = {false,TAWAKEN3,3,NULL,0,&s_darkmonkcharge4};
+statetype s_darkmonkcharge2 = {false,TAWAKEN4,3,NULL,0,&s_darkmonkcharge3};
+statetype s_darkmonkcharge1 = {false,TAWAKEN5,3,NULL,0,&s_darkmonkcharge2};
+
+
+statetype s_darkmonkscare5 = {false,TSCAREB5,3,NULL,0,&s_darkmonkcharge1};
+statetype s_darkmonkscare4 = {false,TSCAREB4,3,NULL,0,&s_darkmonkscare5};
+statetype s_darkmonkscare3 = {false,TSCAREB3,3,NULL,0,&s_darkmonkscare4};
+statetype s_darkmonkscare2 = {false,TSCAREB2,3,NULL,0,&s_darkmonkscare3};
+statetype s_darkmonkscare1 = {false,TSCAREB1,3,NULL,0,&s_darkmonkscare2};
+
+statetype s_darkmonkdead = {false,TOMDIE8,0,T_Collide,0,&s_darkmonkdead};
+statetype s_darkmonkdie7 = {false,TOMDIE7,3,T_Collide,0,&s_darkmonkdead};
+statetype s_darkmonkdie6 = {false,TOMDIE6,3,T_Collide,0,&s_darkmonkdie7};
+statetype s_darkmonkdie5 = {false,TOMDIE5,3,T_Collide,0,&s_darkmonkdie6};
+statetype s_darkmonkdie4 = {false,TOMDIE4,3,T_Collide,0,&s_darkmonkdie5};
+statetype s_darkmonkdie3 = {false,TOMDIE3,3,T_Collide,0,&s_darkmonkdie4};
+statetype s_darkmonkdie2 = {false,TOMDIE2,3,T_Collide,0,&s_darkmonkdie3};
+statetype s_darkmonkdie1 = {false,TOMDIE1,3,T_Collide,0,&s_darkmonkdie2};
+
+
+
+statetype s_darkmonkredhead = {true,TOMRH1,50,T_DarkSnakeChase,0,&s_darkmonkhead};
+statetype s_darkmonkredlink = {true,TOMRH1,50,T_GenericMove,0,&s_darkmonksnakelink};
+
+statetype s_redheadhit = {false,THDIE1,35,T_DarkSnakeChase,0,&s_darkmonkhead};
+statetype s_redlinkhit = {false,THDIE1,35,T_GenericMove,0,&s_darkmonksnakelink};
+
+
+statetype s_spithit4 = {false,SPITHIT4,3,NULL,0,NULL};
+statetype s_spithit3 = {false,SPITHIT3,3,NULL,0,&s_spithit4};
+statetype s_spithit2 = {false,SPITHIT2,3,NULL,0,&s_spithit3};
+statetype s_spithit1 = {false,SPITHIT1,3,NULL,0,&s_spithit2};
+
+statetype s_spit4 = {false,TOMSPIT4,3,T_Projectile,0,&s_spit1};
+statetype s_spit3 = {false,TOMSPIT3,3,T_Projectile,0,&s_spit4};
+statetype s_spit2 = {false,TOMSPIT2,3,T_Projectile,0,&s_spit3};
+statetype s_spit1 = {false,TOMSPIT1,3,T_Projectile,0,&s_spit2};
+
+statetype s_snakefire2 = {true,TOMHEAD1,1,T_DarkSnakeChase,SF_DOWN|SF_UP,&s_darkmonkhead};
+statetype s_snakefire1 = {false,TPREPARE,30,T_DarkSnakeChase,SF_DOWN,&s_snakefire2};
+
+statetype s_dexplosion22 = {false,-1,0,T_BossDied,0,NULL};
+statetype s_dexplosion21 = {false, -1, 240,NULL,0,&s_dexplosion22};
+statetype s_dexplosion20 = {false,SPR_EXPLOSION20,2,NULL,0,&s_dexplosion21};
+statetype s_dexplosion19 = {false,SPR_EXPLOSION19,2,NULL,0,&s_dexplosion20};
+statetype s_dexplosion18 = {false,SPR_EXPLOSION18,2,NULL,0,&s_dexplosion19};
+statetype s_dexplosion17 = {false,SPR_EXPLOSION17,2,NULL,0,&s_dexplosion18};
+statetype s_dexplosion16 = {false,SPR_EXPLOSION16,2,NULL,0,&s_dexplosion17};
+statetype s_dexplosion15 = {false,SPR_EXPLOSION15,2,NULL,0,&s_dexplosion16};
+statetype s_dexplosion14 = {false,SPR_EXPLOSION14,2,NULL,0,&s_dexplosion15};
+statetype s_dexplosion13 = {false,SPR_EXPLOSION13,2,NULL,0,&s_dexplosion14};
+statetype s_dexplosion12 = {false,SPR_EXPLOSION12,2,NULL,0,&s_dexplosion13};
+statetype s_dexplosion11 = {false,SPR_EXPLOSION11,2,NULL,0,&s_dexplosion12};
+statetype s_dexplosion10 = {false,SPR_EXPLOSION10,2,NULL,0,&s_dexplosion11};
+statetype s_dexplosion9 = {false,SPR_EXPLOSION9,2,NULL,0,&s_dexplosion10};
+statetype s_dexplosion8 = {false,SPR_EXPLOSION8,2,NULL,0,&s_dexplosion9};
+statetype s_dexplosion7 = {false,SPR_EXPLOSION7,2,NULL,0,&s_dexplosion8};
+statetype s_dexplosion6 = {false,SPR_EXPLOSION6,2,NULL,0,&s_dexplosion7};
+statetype s_dexplosion5 = {false,SPR_EXPLOSION5,2,NULL,0,&s_dexplosion6};
+statetype s_dexplosion4 = {false,SPR_EXPLOSION4,2,NULL,0,&s_dexplosion5};
+statetype s_dexplosion3 = {false,SPR_EXPLOSION3,2,T_Explosion,0,&s_dexplosion4};
+statetype s_dexplosion2 = {false,SPR_EXPLOSION2,2,NULL,0,&s_dexplosion3};
+statetype s_dexplosion1 = {false,SPR_EXPLOSION1,2,NULL,0,&s_dexplosion2};
+
+
+/*
+===========================================================================
+
+ OROBOT
+
+===========================================================================
+*/
+
+statetype s_NMEdeathbuildup = {16,NMEBODY1_01,210,T_NME_Explode,0,NULL};
+statetype s_NMEheadexplosion = {16,NMEHEAD1_01,140,T_Special,0,&s_grexplosion1};
+
+statetype s_NMEstand = {16,NMEBODY1_01,0,T_Stand,0,&s_NMEstand};
+statetype s_NMEhead1 = {16,NMEHEAD1_01,0,NULL,0,&s_NMEhead1};
+statetype s_NMEhead2 = {16,NMEHEAD2_01,0,NULL,0,&s_NMEhead2};
+statetype s_NMEchase = {16,NMEBODY1_01,20,T_OrobotChase,0,&s_NMEchase};
+statetype s_NMEwheels1 = {16,NMEWHEEL1_01,0,NULL,0,&s_NMEwheels1};
+statetype s_NMEwheels2 = {16,NMEWHEEL2_01,0,NULL,0,&s_NMEwheels2};
+statetype s_NMEwheels3 = {16,NMEWHEEL3_01,0,NULL,0,&s_NMEwheels3};
+statetype s_NMEwheels4 = {16,NMEWHEEL4_01,0,NULL,0,&s_NMEwheels4};
+statetype s_NMEwheels5 = {16,NMEWHEEL5_01,0,NULL,0,&s_NMEwheels5};
+
+statetype s_shootinghead = {16,NMEHEAD1_01,140,T_NME_HeadShoot,0,&s_shootinghead};
+
+statetype s_NMEspinattack = {16,NMEBODY1_01,70,T_NME_SpinAttack,0,&s_NMEchase};
+statetype s_NMEwheelspin = {16,NMEWHEEL1_01,70,NULL,0,&s_NMEwheels2};
+
+statetype s_NMEminiball4 = {false,NMEMINIBALL_04,4,T_Projectile,0,&s_NMEminiball1};
+statetype s_NMEminiball3 = {false,NMEMINIBALL_03,4,T_Projectile,0,&s_NMEminiball4};
+statetype s_NMEminiball2 = {false,NMEMINIBALL_02,4,T_Projectile,0,&s_NMEminiball3};
+statetype s_NMEminiball1 = {false,NMEMINIBALL_01,4,T_Projectile,0,&s_NMEminiball2};
+
+statetype s_NMEsaucer4 = {false,NMESAUCER_04,6,T_Saucer,0,&s_NMEsaucer1};
+statetype s_NMEsaucer3 = {false,NMESAUCER_03,6,T_Saucer,0,&s_NMEsaucer4};
+statetype s_NMEsaucer2 = {false,NMESAUCER_02,6,T_Saucer,0,&s_NMEsaucer3};
+statetype s_NMEsaucer1 = {false,NMESAUCER_01,6,T_Saucer,SF_SOUND,&s_NMEsaucer2};
+
+statetype s_NMEdie = {16,NMEBODY1_01,0,T_Collide,0,&s_NMEdie};
+
+
+statetype s_NMEspinfire = {16,NMEBODY1_01,0,T_NME_SpinFire,0,&s_NMEspinfire};
+statetype s_NMEattack = {16,NMEBODY1_01,0,T_NME_Attack,0,&s_NMEattack};
+statetype s_NMEhead1rl = {16,NMEROCKET_01,0,NULL,0,&s_NMEhead1rl};
+statetype s_NMEhead2rl = {16,NMEROCKET2_01,0,NULL,0,&s_NMEhead2rl};
+
+statetype s_NMEwindup = {16,NMEBODY1_01,0,T_NME_WindUp,0,&s_NMEwindup};
+
+statetype s_NMEwheels120 = {16,NMEWHEEL1_01,0,NULL,0,&s_NMEwheels120};
+
+statetype s_NMEwrotleft3 = {16,NMEWHEEL4_01,10,NULL,0,&s_NMEwrotleft3};
+statetype s_NMEwrotleft2 = {16,NMEWHEEL3_01,10,NULL,0,&s_NMEwrotleft3};
+statetype s_NMEwrotleft1 = {16,NMEWHEEL2_01,10,NULL,0,&s_NMEwrotleft2};
+
+statetype s_NMEwrotright3 = {16,NMEWHEEL4_01,10,NULL,0,&s_NMEwrotleft3};
+statetype s_NMEwrotright2 = {16,NMEWHEEL5_01,10,NULL,0,&s_NMEwrotleft3};
+statetype s_NMEwrotright1 = {16,NMEWHEEL2_01,10,NULL,0,&s_NMEwrotleft2};
+
+statetype s_oshuriken4 = {false,SPR_OSHUR4,1,T_Projectile,0,&s_oshuriken1};
+statetype s_oshuriken3 = {false,SPR_OSHUR3,1,T_Projectile,0,&s_oshuriken4};
+statetype s_oshuriken2 = {false,SPR_OSHUR2,1,T_Projectile,0,&s_oshuriken3};
+statetype s_oshuriken1 = {false,SPR_OSHUR1,1,T_Projectile,0,&s_oshuriken2};
+
+statetype s_oshurikenhit3 = {false,SPR_OSHURHIT3,3,NULL,0,NULL};
+statetype s_oshurikenhit2 = {false,SPR_OSHURHIT2,3,NULL,0,&s_oshurikenhit3};
+statetype s_oshurikenhit1 = {false,SPR_OSHURHIT1,3,NULL,0,&s_oshurikenhit2};
+
+statetype s_speardown16 = {false,SPEARDOWN16,2,T_Spears,SF_CRUSH,&s_speardown1};
+statetype s_speardown15 = {false,SPEARDOWN15,2,T_Spears,SF_CRUSH,&s_speardown16};
+statetype s_speardown14 = {false,SPEARDOWN14,2,T_Spears,SF_CRUSH,&s_speardown15};
+statetype s_speardown13 = {false,SPEARDOWN13,2,T_Spears,SF_CRUSH,&s_speardown14};
+statetype s_speardown12 = {false,SPEARDOWN12,2,T_Spears,SF_CRUSH,&s_speardown13};
+statetype s_speardown11 = {false,SPEARDOWN11,2,T_Spears,SF_CRUSH,&s_speardown12};
+statetype s_speardown10 = {false,SPEARDOWN10,2,T_Spears,SF_CRUSH,&s_speardown11};
+statetype s_speardown9 = {false,SPEARDOWN9,2,T_Spears,SF_DOWN,&s_speardown10};
+
+statetype s_speardown8 = {false,SPEARDOWN8,35,T_Spears,SF_DOWN|SF_SOUND,&s_speardown9};
+statetype s_speardown7 = {false,SPEARDOWN7,2,T_Spears,SF_DOWN,&s_speardown8};
+statetype s_speardown6 = {false,SPEARDOWN6,2,T_Spears,SF_CRUSH,&s_speardown7};
+statetype s_speardown5 = {false,SPEARDOWN5,2,T_Spears,SF_CRUSH,&s_speardown6};
+statetype s_speardown4 = {false,SPEARDOWN4,2,T_Spears,SF_CRUSH,&s_speardown5};
+statetype s_speardown3 = {false,SPEARDOWN3,2,T_Spears,SF_CRUSH,&s_speardown4};
+statetype s_speardown2 = {false,SPEARDOWN2,2,T_Spears,SF_CRUSH,&s_speardown3};
+statetype s_speardown1 = {false,SPEARDOWN1,2,T_Spears,SF_CRUSH,&s_speardown2};
+
+
+
+statetype s_downblade16 = {false,DBLADE8,1,T_Path,0,&s_downblade1};
+statetype s_downblade15 = {false,DBLADE7,2,T_Path,0,&s_downblade16};
+statetype s_downblade14 = {false,DBLADE6,1,T_Path,0,&s_downblade15};
+statetype s_downblade13 = {false,DBLADE5,2,T_Path,0,&s_downblade14};
+statetype s_downblade12 = {false,DBLADE4,1,T_Path,0,&s_downblade13};
+statetype s_downblade11 = {false,DBLADE3,2,T_Path,0,&s_downblade12};
+statetype s_downblade10 = {false,DBLADE2,1,T_Path,0,&s_downblade11};
+statetype s_downblade9 = {false,DBLADE9,2,T_Path,0,&s_downblade10};
+statetype s_downblade8 = {false,DBLADE8,1,T_Path,0,&s_downblade9};
+statetype s_downblade7 = {false,DBLADE7,2,T_Path,0,&s_downblade8};
+statetype s_downblade6 = {false,DBLADE6,1,T_Path,0,&s_downblade7};
+statetype s_downblade5 = {false,DBLADE5,2,T_Path,0,&s_downblade6};
+statetype s_downblade4 = {false,DBLADE4,1,T_Path,0,&s_downblade5};
+statetype s_downblade3 = {false,DBLADE3,2,T_Path,0,&s_downblade4};
+statetype s_downblade2 = {false,DBLADE2,1,T_Path,0,&s_downblade3};
+statetype s_downblade1 = {false,DBLADE1,2,T_Path,SF_SOUND,&s_downblade2};
+
+
+statetype s_firejetdown23 = {false,FIREJETDOWN23,3,T_Path,SF_CRUSH,&s_firejetdown1};
+statetype s_firejetdown22 = {false,FIREJETDOWN22,3,T_Path,SF_CRUSH,&s_firejetdown23};
+statetype s_firejetdown21 = {false,FIREJETDOWN21,3,T_Path,0,&s_firejetdown22};
+statetype s_firejetdown20 = {false,FIREJETDOWN20,3,T_Path,0,&s_firejetdown21};
+statetype s_firejetdown19 = {false,FIREJETDOWN19,3,T_Path,0,&s_firejetdown20};
+statetype s_firejetdown18 = {false,FIREJETDOWN18,3,T_Path,0,&s_firejetdown19};
+statetype s_firejetdown17 = {false,FIREJETDOWN17,3,T_Path,0,&s_firejetdown18};
+statetype s_firejetdown16 = {false,FIREJETDOWN16,3,T_Path,SF_CRUSH,&s_firejetdown17};
+statetype s_firejetdown15 = {false,FIREJETDOWN15,3,T_Path,SF_CRUSH,&s_firejetdown16};
+statetype s_firejetdown14 = {false,FIREJETDOWN14,3,T_Path,SF_CRUSH,&s_firejetdown15};
+statetype s_firejetdown13 = {false,FIREJETDOWN13,3,T_Path,0,&s_firejetdown14};
+statetype s_firejetdown12 = {false,FIREJETDOWN12,3,T_Path,0,&s_firejetdown13};
+statetype s_firejetdown11 = {false,FIREJETDOWN11,3,T_Path,0,&s_firejetdown12};
+statetype s_firejetdown10 = {false,FIREJETDOWN10,3,T_Path,0,&s_firejetdown11};
+statetype s_firejetdown9 = {false,FIREJETDOWN9,3,T_Path,0,&s_firejetdown10};
+statetype s_firejetdown8 = {false,FIREJETDOWN8,3,T_Path,SF_CRUSH,&s_firejetdown9};
+statetype s_firejetdown7 = {false,FIREJETDOWN7,3,T_Path,SF_CRUSH,&s_firejetdown8};
+statetype s_firejetdown6 = {false,FIREJETDOWN6,3,T_Path,SF_CRUSH,&s_firejetdown7};
+statetype s_firejetdown5 = {false,FIREJETDOWN5,3,T_Path,0,&s_firejetdown6};
+statetype s_firejetdown4 = {false,FIREJETDOWN4,3,T_Path,0,&s_firejetdown5};
+statetype s_firejetdown3 = {false,FIREJETDOWN3,3,T_Path,0,&s_firejetdown4};
+statetype s_firejetdown2 = {false,FIREJETDOWN2,3,T_Path,0,&s_firejetdown3};
+statetype s_firejetdown1 = {false,FIREJETDOWN1,70,T_Path,SF_SOUND,&s_firejetdown2};
+
+
+
+statetype s_columnupdown6 = {false,CRUSHUP7,5,T_CrushUp,SF_DOWN,&s_columnupup1};
+statetype s_columnupdown5 = {false,CRUSHUP6,2,T_CrushUp,SF_DOWN,&s_columnupdown6};
+statetype s_columnupdown4 = {false,CRUSHUP5,5,T_CrushUp,SF_DOWN|SF_BLOCK,&s_columnupdown5};
+statetype s_columnupdown3 = {false,CRUSHUP4,5,T_CrushUp,SF_DOWN|SF_BLOCK,&s_columnupdown4};
+statetype s_columnupdown2 = {false,CRUSHUP3,5,T_CrushUp,SF_DOWN|SF_BLOCK,&s_columnupdown3};
+statetype s_columnupdown1 = {false,CRUSHUP2,2,T_CrushUp,SF_DOWN|SF_BLOCK,&s_columnupdown2};
+
+
+statetype s_columnupup8 = {false,CRUSHUP1,5,T_CrushUp,SF_CRUSH|SF_BLOCK,&s_columnupdown1};
+statetype s_columnupup7 = {false,CRUSHUP2,2,T_CrushUp,SF_CRUSH|SF_UP|SF_BLOCK,&s_columnupup8};
+statetype s_columnupup6 = {false,CRUSHUP3,5,T_CrushUp,SF_UP|SF_BLOCK,&s_columnupup7};
+statetype s_columnupup5 = {false,CRUSHUP4,5,T_CrushUp,SF_UP|SF_BLOCK,&s_columnupup6};
+statetype s_columnupup4 = {false,CRUSHUP5,5,T_CrushUp,SF_UP,&s_columnupup5};
+statetype s_columnupup3 = {false,CRUSHUP6,2,T_CrushUp,SF_UP,&s_columnupup4};
+statetype s_columnupup2 = {false,CRUSHUP7,5,T_CrushUp,SF_UP,&s_columnupup3};
+statetype s_columnupup1 = {false,CRUSHUP8,30,T_CrushUp,SF_SOUND,&s_columnupup2};
+
+
+
+statetype s_spinupblade16 = {false,SPINUBLADE_16,2,T_Path,SF_DOWN,&s_spinupblade1};
+statetype s_spinupblade15 = {false,SPINUBLADE_15,2,T_Path,0,&s_spinupblade16};
+statetype s_spinupblade14 = {false,SPINUBLADE_14,2,T_Path,0,&s_spinupblade15};
+statetype s_spinupblade13 = {false,SPINUBLADE_13,2,T_Path,0,&s_spinupblade14};
+statetype s_spinupblade12 = {false,SPINUBLADE_12,2,T_Path,0,&s_spinupblade13};
+statetype s_spinupblade11 = {false,SPINUBLADE_11,2,T_Path,0,&s_spinupblade12};
+statetype s_spinupblade10 = {false,SPINUBLADE_10,2,T_Path,0,&s_spinupblade11};
+statetype s_spinupblade9 = {false,SPINUBLADE_09,2,T_Path,0,&s_spinupblade10};
+
+statetype s_spinupblade8 = {false,SPINUBLADE_08,2,T_Path,0,&s_spinupblade9};
+statetype s_spinupblade7 = {false,SPINUBLADE_07,2,T_Path,0,&s_spinupblade8};
+statetype s_spinupblade6 = {false,SPINUBLADE_06,2,T_Path,0,&s_spinupblade7};
+statetype s_spinupblade5 = {false,SPINUBLADE_05,2,T_Path,0,&s_spinupblade6};
+statetype s_spinupblade4 = {false,SPINUBLADE_04,2,T_Path,0,&s_spinupblade5};
+statetype s_spinupblade3 = {false,SPINUBLADE_03,2,T_Path,0,&s_spinupblade4};
+statetype s_spinupblade2 = {false,SPINUBLADE_02,2,T_Path,0,&s_spinupblade3};
+statetype s_spinupblade1 = {false,SPINUBLADE_01,35,T_Path,SF_UP|SF_SOUND,&s_spinupblade2};
+
+
+statetype s_spindownblade16 = {false,SPINDBLADE_16,2,T_Path,SF_DOWN,&s_spindownblade1};
+statetype s_spindownblade15 = {false,SPINDBLADE_15,2,T_Path,0,&s_spindownblade16};
+statetype s_spindownblade14 = {false,SPINDBLADE_14,2,T_Path,0,&s_spindownblade15};
+statetype s_spindownblade13 = {false,SPINDBLADE_13,2,T_Path,0,&s_spindownblade14};
+statetype s_spindownblade12 = {false,SPINDBLADE_12,2,T_Path,0,&s_spindownblade13};
+statetype s_spindownblade11 = {false,SPINDBLADE_11,2,T_Path,0,&s_spindownblade12};
+statetype s_spindownblade10 = {false,SPINDBLADE_10,2,T_Path,0,&s_spindownblade11};
+statetype s_spindownblade9 = {false,SPINDBLADE_09,2,T_Path,0,&s_spindownblade10};
+
+statetype s_spindownblade8 = {false,SPINDBLADE_08,2,T_Path,0,&s_spindownblade9};
+statetype s_spindownblade7 = {false,SPINDBLADE_07,2,T_Path,0,&s_spindownblade8};
+statetype s_spindownblade6 = {false,SPINDBLADE_06,2,T_Path,0,&s_spindownblade7};
+statetype s_spindownblade5 = {false,SPINDBLADE_05,2,T_Path,0,&s_spindownblade6};
+statetype s_spindownblade4 = {false,SPINDBLADE_04,2,T_Path,0,&s_spindownblade5};
+statetype s_spindownblade3 = {false,SPINDBLADE_03,2,T_Path,0,&s_spindownblade4};
+statetype s_spindownblade2 = {false,SPINDBLADE_02,2,T_Path,0,&s_spindownblade3};
+statetype s_spindownblade1 = {false,SPINDBLADE_01,35,T_Path,SF_UP|SF_SOUND,&s_spindownblade2};
+
+
+statetype s_bouldersink9 = {false,BSINK9,2,NULL,0,NULL};
+statetype s_bouldersink8 = {false,BSINK8,2,NULL,0,&s_bouldersink9};
+statetype s_bouldersink7 = {false,BSINK7,2,NULL,0,&s_bouldersink8};
+statetype s_bouldersink6 = {false,BSINK6,2,NULL,0,&s_bouldersink7};
+statetype s_bouldersink5 = {false,BSINK5,2,NULL,0,&s_bouldersink6};
+statetype s_bouldersink4 = {false,BSINK4,2,NULL,0,&s_bouldersink5};
+statetype s_bouldersink3 = {false,BSINK3,2,NULL,0,&s_bouldersink4};
+statetype s_bouldersink2 = {false,BSINK2,2,NULL,0,&s_bouldersink3};
+statetype s_bouldersink1 = {false,BSINK1,2,NULL,0,&s_bouldersink2};
+
+
+statetype s_boulderroll8 = {false,BOULDER41,3,T_BoulderMove,0,&s_boulderroll1};
+statetype s_boulderroll7 = {false,BOULDER31,3,T_BoulderMove,0,&s_boulderroll8};
+statetype s_boulderroll6 = {false,BOULDER21,3,T_BoulderMove,0,&s_boulderroll7};
+statetype s_boulderroll5 = {false,BOULDER11,3,T_BoulderMove,0,&s_boulderroll6};
+statetype s_boulderroll4 = {false,BOULDER41,3,T_BoulderMove,0,&s_boulderroll5};
+statetype s_boulderroll3 = {false,BOULDER31,3,T_BoulderMove,0,&s_boulderroll4};
+statetype s_boulderroll2 = {false,BOULDER21,3,T_BoulderMove,0,&s_boulderroll3};
+statetype s_boulderroll1 = {false,BOULDER11,3,T_BoulderMove,SF_SOUND,&s_boulderroll2};
+
+
+
+
+statetype s_boulderdrop12 = {false,BOULDER11,0,T_BoulderDrop,0,&s_boulderdrop12};
+statetype s_boulderdrop11 = {false,BDROP11,1,T_BoulderDrop,0,&s_boulderdrop12};
+statetype s_boulderdrop10 = {false,BDROP10,1,T_BoulderDrop,0,&s_boulderdrop11};
+statetype s_boulderdrop9 = {false,BDROP9,2,T_BoulderDrop,0,&s_boulderdrop10};
+statetype s_boulderdrop8 = {false,BDROP8,1,T_BoulderDrop,0,&s_boulderdrop9};
+statetype s_boulderdrop7 = {false,BDROP7,1,T_BoulderDrop,0,&s_boulderdrop8};
+statetype s_boulderdrop6 = {false,BDROP6,2,T_BoulderDrop,0,&s_boulderdrop7};
+statetype s_boulderdrop5 = {false,BDROP5,3,T_BoulderDrop,0,&s_boulderdrop6};
+statetype s_boulderdrop4 = {false,BDROP4,4,T_BoulderDrop,0,&s_boulderdrop5};
+statetype s_boulderdrop3 = {false,BDROP3,5,T_BoulderDrop,SF_SOUND,&s_boulderdrop4};
+statetype s_boulderdrop2 = {false,BDROP2,6,NULL,0,&s_boulderdrop3};
+statetype s_boulderdrop1 = {false,BDROP1,6,NULL,0,&s_boulderdrop2};
+
+statetype s_boulderspawn = {false,NOTHING,70,T_BoulderSpawn,0,&s_boulderspawn};
+
+
+
+/*==========================================================================
+
+ GUN STUFF
+
+============================================================================*/
+
+statetype s_gunfire2 = {true,GUNRISE51,5,A_GunShoot,0,&s_gunfire1};
+statetype s_gunfire1 = {true,GUNFIRE1,5,A_GunShoot,0,&s_gunfire2};
+
+statetype s_gunstand = {true,GUNRISE11,0,T_GunStand,0,&s_gunstand};
+
+statetype s_gunraise4 = {true,GUNRISE51,2,NULL,0,&s_gunfire1};
+statetype s_gunraise3 = {true,GUNRISE41,2,NULL,0,&s_gunraise4};
+statetype s_gunraise2 = {true,GUNRISE31,2,NULL,0,&s_gunraise3};
+statetype s_gunraise1 = {true,GUNRISE21,2,NULL,0,&s_gunraise2};
+
+statetype s_gunlower3 = {true,GUNRISE21,2,NULL,0,&s_gunstand};
+statetype s_gunlower2 = {true,GUNRISE31,2,NULL,0,&s_gunlower3};
+statetype s_gunlower1 = {true,GUNRISE41,2,NULL,0,&s_gunlower2};
+
+
+statetype s_gundead = {false,GUNDEAD2,0,T_Collide,0,&s_gundead};
+statetype s_gundie1 = {false,GUNDEAD1,5,NULL,0,&s_gundead};
+
+
+
+//======================================================================//
+
+statetype s_4waygunfire1 = {true,FOURWAYFIRE01,5,A_4WayGunShoot,0,&s_4waygunfire2};
+statetype s_4waygunfire2 = {true,FOURWAY01,5,NULL,0,&s_4waygunfire1};
+
+statetype s_4waygun = {true,FOURWAY01,0,T_4WayGunStand,0,&s_4waygun};
+
+
+
+
+statetype s_kessphere8 = {false,KESSPHERE8,2,T_Projectile,0,&s_kessphere1};
+statetype s_kessphere7 = {false,KESSPHERE7,2,T_Projectile,0,&s_kessphere8};
+statetype s_kessphere6 = {false,KESSPHERE6,2,T_Projectile,0,&s_kessphere7};
+statetype s_kessphere5 = {false,KESSPHERE5,2,T_Projectile,0,&s_kessphere6};
+statetype s_kessphere4 = {false,KESSPHERE4,2,T_Projectile,0,&s_kessphere5};
+statetype s_kessphere3 = {false,KESSPHERE3,2,T_Projectile,0,&s_kessphere4};
+statetype s_kessphere2 = {false,KESSPHERE2,2,T_Projectile,0,&s_kessphere3};
+statetype s_kessphere1 = {false,KESSPHERE1,2,T_Projectile,0,&s_kessphere2};
+
+
+statetype s_slop4 = {false,TOMSPIT4,3,T_Particle,0,&s_slop1};
+statetype s_slop3 = {false,TOMSPIT3,3,T_Particle,0,&s_slop4};
+statetype s_slop2 = {false,TOMSPIT2,3,T_Particle,0,&s_slop3};
+statetype s_slop1 = {false,TOMSPIT1,3,T_Particle,0,&s_slop2};
+
+
+statetype s_batblast4 = {false,BATBLAST4,3,T_Projectile,SF_BAT,&s_batblast1};
+statetype s_batblast3 = {false,BATBLAST3,3,T_Projectile,SF_BAT,&s_batblast4};
+statetype s_batblast2 = {false,BATBLAST2,3,T_Projectile,SF_BAT,&s_batblast3};
+statetype s_batblast1 = {false,BATBLAST1,3,T_Projectile,SF_BAT,&s_batblast2};
+
+
+statetype s_serialdog4 = {true,SERIALDOG_W41,5,T_Player,SF_DOGSTATE,&s_serialdog};
+statetype s_serialdog3 = {true,SERIALDOG_W31,5,T_Player,SF_DOGSTATE,&s_serialdog4};
+statetype s_serialdog2 = {true,SERIALDOG_W21,5,T_Player,SF_DOGSTATE,&s_serialdog3};
+statetype s_serialdog = {true,SERIALDOG_W11,5,T_Player,SF_DOGSTATE,&s_serialdog2};
+statetype s_serialdogattack = {true,SERIALDOG_ATTACK1,0,T_Attack,SF_DOGSTATE,&s_serialdogattack };
+
+
+#endif
+
+
+#include "rt_table.h"
--- /dev/null
+++ b/rott/rt_str.c
@@ -1,0 +1,2055 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//******************************************************************************
+//
+// RT_STR.C
+// Contains the menu stuff!
+//
+//******************************************************************************
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <string.h>
+#include <ctype.h>
+#include "rt_def.h"
+#include "rt_menu.h"
+#include "rt_util.h"
+#include "rt_vid.h"
+#include "rt_build.h"
+#include "lumpy.h"
+#include "rt_str.h"
+#include "_rt_str.h"
+#include "isr.h"
+#include "rt_in.h"
+#include "rt_menu.h"
+#include "rt_view.h"
+#include "w_wad.h"
+#include "z_zone.h"
+#include "modexlib.h"
+#include "rt_main.h"
+#include "rt_msg.h"
+#include "rt_playr.h"
+#include "rt_sound.h"
+#include "myprint.h"
+//MED
+#include "memcheck.h"
+
+
+//******************************************************************************
+//
+// GLOBALS
+//
+//******************************************************************************
+
+int fontcolor;
+
+//******************************************************************************
+//
+// LOCALS
+//
+//******************************************************************************
+
+static int BKw;
+static int BKh;
+
+static char strbuf[MaxString];
+
+//******************************************************************************
+//
+// VW_DrawClippedString ()
+//
+// Draws a string at x, y to bufferofs
+//
+//******************************************************************************
+
+void VW_DrawClippedString (int x, int y, const char *string)
+{
+ int width,height,ht;
+ byte *source;
+ int ch;
+ int oy;
+
+ ht = CurrentFont->height;
+
+ oy=y;
+
+ while ((ch = (unsigned char)*string++)!=0)
+ {
+ ch -= 31;
+ width = CurrentFont->width[ch];
+ source = ((byte *)CurrentFont)+CurrentFont->charofs[ch];
+ while (width--)
+ {
+ if ((x>=0) && (x<iGLOBAL_SCREENWIDTH))
+ {
+ y=oy;
+ VGAWRITEMAP(x&3);
+ height = ht;
+ while (height--)
+ {
+ if ((y>=0) && (y<iGLOBAL_SCREENHEIGHT))
+ {
+ if (*source>0)
+#ifdef DOS
+ *((byte *)(bufferofs+ylookup[y]+(x>>2))) = *source;
+#else
+ *((byte *)(bufferofs+ylookup[y]+x)) = *source;
+#endif
+ }
+ source++;
+ y++;
+ }
+ }
+ x++;
+ }
+ }
+}
+
+//******************************************************************************
+//
+// US_ClippedPrint() - Prints a string in bufferofs. Newlines are supported.
+//
+//******************************************************************************
+
+void US_ClippedPrint (int x, int y, const char *string)
+{
+ char c,
+ *se;
+ char *s;
+ int startx;
+
+ strcpy(strbuf, string);
+ s = strbuf;
+
+ startx=x;
+ while (*s)
+ {
+ se = s;
+ while ((c = *se) && (c != '\n'))
+ se++;
+ *se = '\0';
+
+ VW_DrawClippedString ( x, y, s);
+
+ s = se;
+ if (c)
+ {
+ *se = c;
+ s++;
+ y += CurrentFont->height;
+ }
+ }
+}
+
+
+//******************************************************************************
+//
+// VW_DrawPropString ()
+//
+// Draws a string at px, py to bufferofs
+//
+//******************************************************************************
+
+void VW_DrawPropString (const char *string)
+{
+#ifdef DOS
+ byte pix;
+ int width,step,height,ht;
+ byte *source, *dest, *origdest;
+ int ch,mask;
+
+
+ ht = CurrentFont->height;
+ dest = origdest = (byte *)(bufferofs+ylookup[py]+(px>>2));
+
+
+ mask = 1<<(px&3);
+
+
+ while ((ch = *string++)!=0)
+ {
+ ch -= 31;
+ width = step = CurrentFont->width[ch];
+ source = ((byte *)CurrentFont)+CurrentFont->charofs[ch];
+ while (width--)
+ {
+ VGAMAPMASK(mask);
+
+ height = ht;
+ while (height--)
+ {
+ pix = *source;
+ if (pix)
+ *dest = pix;
+
+ source++;
+ dest += linewidth;
+ }
+
+ px++;
+ mask <<= 1;
+ if (mask == 16)
+ {
+ mask = 1;
+ origdest++;
+ }
+ dest = origdest;
+ }
+ }
+ bufferheight = ht;
+ bufferwidth = ((dest+1)-origdest)*4;
+#else
+ byte pix;
+ int width,step,height,ht;
+ byte *source, *dest, *origdest;
+ int ch,mask;
+
+ ht = CurrentFont->height;
+ dest = origdest = (byte *)(bufferofs+ylookup[py]+px);
+
+ while ((ch = (unsigned char)*string++)!=0)
+ {
+ ch -= 31;
+ width = step = CurrentFont->width[ch];
+ source = ((byte *)CurrentFont)+CurrentFont->charofs[ch];
+ while (width--)
+ {
+ height = ht;
+ while (height--)
+ {
+ pix = *source;
+ if (pix)
+ *dest = pix;
+
+ source++;
+ dest += linewidth;
+ }
+
+ px++;
+ origdest++;
+ dest = origdest;
+ }
+ }
+ bufferheight = ht;
+ bufferwidth = ((dest+1)-origdest);
+#endif
+}
+
+
+
+//******************************************************************************
+//
+// VWB_DrawPropString ()
+//
+// Calls VW_DrawPropString then updates the mark block.
+//
+//******************************************************************************
+
+void VWB_DrawPropString (const char *string)
+{
+ int x;
+ x = px;
+ VW_DrawPropString (string);
+ VW_MarkUpdateBlock (x, py, px-1, py+bufferheight-1);
+}
+
+
+
+//******************************************************************************
+//
+// VW_DrawIPropString ()
+//
+// Draws a string at px, py to bufferofs
+//
+//******************************************************************************
+
+void VW_DrawIPropString (const char *string)
+{
+ byte pix;
+ int width,step,height,ht;
+ byte *source, *dest, *origdest;
+ int ch,mask;
+
+
+ ht = CurrentFont->height;
+#ifdef DOS
+ dest = origdest = (byte *)(bufferofs+ylookup[py]+(px>>2));
+#else
+ dest = origdest = (byte *)(bufferofs+ylookup[py]+px);
+#endif
+
+
+ mask = 1<<(px&3);
+
+
+ while ((ch = (unsigned char)*string++)!=0)
+ {
+ ch -= 31;
+ width = step = CurrentFont->width[ch];
+ source = ((byte *)CurrentFont)+CurrentFont->charofs[ch];
+ while (width--)
+ {
+ VGAMAPMASK(mask);
+
+ height = ht;
+ while (height--)
+ {
+ pix = *source;
+ if (pix)
+ *dest = pix;
+
+ source++;
+ dest += linewidth;
+ }
+
+ px++;
+#ifdef DOS
+ mask <<= 1;
+ if (mask == 16)
+ {
+ mask = 1;
+ origdest++;
+ }
+#else
+ origdest++;
+#endif
+ dest = origdest;
+ }
+ }
+ bufferheight = ht;
+#ifdef DOS
+ bufferwidth = ((dest+1)-origdest)*4;
+#else
+ bufferwidth = ((dest+1)-origdest);
+#endif
+
+}
+
+
+
+//******************************************************************************
+//
+// VWB_DrawIPropString ()
+//
+// Calls VW_DrawIPropString then updates the mark block.
+//
+//******************************************************************************
+
+void VWB_DrawIPropString (const char *string)
+{
+ int x;
+ x = px;
+ VW_DrawIPropString (string);
+ VW_MarkUpdateBlock (x, py, px-1, py+bufferheight-1);
+}
+
+
+
+//******************************************************************************
+//
+// VWL_MeasureString ()
+//
+//******************************************************************************
+
+void VWL_MeasureString (const char *s, int *width, int *height, const font_t *font)
+{
+ *height = font->height;
+
+ for (*width = 0; *s; s++)
+ *width += font->width[(*((byte *)s))-31]; // proportional width
+}
+
+//******************************************************************************
+//
+// VWL_MeasureIntensityString ()
+//
+//******************************************************************************
+
+void VWL_MeasureIntensityString (const char *s, int *width, int *height, const cfont_t *font)
+{
+ *height = font->height;
+
+ for (*width = 0; *s; s++)
+ *width += font->width[(*((byte *)s))-31]; // proportional width
+}
+
+//******************************************************************************
+//
+// VW_MeasureIntensityPropString ()
+//
+//******************************************************************************
+
+void VW_MeasureIntensityPropString (const char *string, int *width, int *height)
+{
+ VWL_MeasureIntensityString (string, width, height, IFont);
+}
+
+//******************************************************************************
+//
+// VW_MeasurePropString ()
+//
+//******************************************************************************
+
+void VW_MeasurePropString (const char *string, int *width, int *height)
+{
+ VWL_MeasureString (string, width, height, CurrentFont);
+}
+
+
+//******************************************************************************
+//
+// US_MeasureStr ()
+//
+//******************************************************************************
+
+void US_MeasureStr (int *width, int *height, const char * s, ...)
+{
+ char c,
+ *se,
+ *ss;
+ int w,h;
+ va_list strptr;
+ char buf[300];
+
+ *width = 0;
+ *height = 0;
+
+ memset (&buf[0], 0, sizeof (buf));
+ va_start (strptr, s);
+ vsprintf (&buf[0], s, strptr);
+ va_end (strptr);
+
+ ss = &buf[0];
+
+ while (*ss)
+ {
+ se = ss;
+ while ((c = *se) && (c != '\n'))
+ se++;
+ *se = '\0';
+
+ VWL_MeasureString (ss, &w, &h, CurrentFont);
+
+ *height += h;
+
+ if (w > *width)
+ *width = w;
+
+ ss = se;
+ if (c)
+ {
+ *se = c;
+ ss++;
+ }
+ }
+}
+
+
+//******************************************************************************
+//
+// US_SetPrintRoutines() - Sets the routines used to measure and print
+// from within the User Mgr. Primarily provided to allow switching
+// between masked and non-masked fonts
+//
+//******************************************************************************
+
+void US_SetPrintRoutines (void (*measure)(const char *, int *, int *, font_t *),
+ void (*print)(const char *))
+{
+ USL_MeasureString = measure;
+ USL_DrawString = print;
+}
+
+
+//******************************************************************************
+//
+// US_Print() - Prints a string in the current window. Newlines are
+// supported.
+//
+//******************************************************************************
+
+void US_Print (const char *string)
+{
+ char c,
+ *se,
+ *s;
+ int w,h;
+
+ strcpy(strbuf, string);
+ s = strbuf;
+
+ while (*s)
+ {
+ se = s;
+ while ((c = *se) && (c != '\n'))
+ se++;
+ *se = '\0';
+
+ USL_MeasureString (s, &w, &h, CurrentFont);
+ px = PrintX;
+ py = PrintY;
+ USL_DrawString (s);
+
+ s = se;
+ if (c)
+ {
+ *se = c;
+ s++;
+
+ PrintX = WindowX;
+ PrintY += h;
+ }
+ else
+ PrintX += w;
+ }
+}
+
+//******************************************************************************
+//
+// US_BufPrint() - Prints a string in bufferofs. Newlines are supported.
+//
+//******************************************************************************
+
+void US_BufPrint (const char *string)
+{
+ char c,
+ *se,
+ *s;
+ int startx;
+
+ strcpy(strbuf, string);
+ s = strbuf;
+
+ startx=PrintX;
+ while (*s)
+ {
+ se = s;
+ while ((c = *se) && (c != '\n'))
+ se++;
+ *se = '\0';
+
+ px = PrintX;
+ py = PrintY;
+ USL_DrawString (s);
+
+ PrintY = py;
+ PrintX = px;
+
+ s = se;
+ if (c)
+ {
+ *se = c;
+ s++;
+ PrintY += CurrentFont->height;
+ PrintX = startx;
+ }
+ }
+}
+
+
+//******************************************************************************
+//
+// US_PrintUnsigned () - Prints an unsigned long int
+//
+//******************************************************************************
+
+void US_PrintUnsigned (unsigned long int n)
+{
+ char buffer[32];
+
+ US_Print (ultoa (n, buffer, 10));
+}
+
+//******************************************************************************
+//
+// US_PrintSigned() - Prints a signed long
+//
+//******************************************************************************
+
+void US_PrintSigned (long int n)
+{
+ char buffer[32];
+
+ US_Print (ltoa (n, buffer, 10));
+}
+
+//******************************************************************************
+//
+// USL_PrintInCenter() - Prints a string in the center of the given rect
+//
+//******************************************************************************
+
+void USL_PrintInCenter (const char *s, Rect r)
+{
+ int w,h,
+ rw,rh;
+
+ USL_MeasureString (s,&w,&h, CurrentFont);
+ rw = r.lr.x - r.ul.x;
+ rh = r.lr.y - r.ul.y;
+
+ px = r.ul.x + ((rw - w) / 2);
+ py = r.ul.y + ((rh - h) / 2);
+ USL_DrawString (s);
+}
+
+//******************************************************************************
+//
+// US_PrintCentered() - Prints a string centered in the current window.
+//
+//******************************************************************************
+
+void US_PrintCentered (const char *s)
+{
+ Rect r;
+
+ r.ul.x = WindowX;
+ r.ul.y = WindowY;
+ r.lr.x = r.ul.x + WindowW;
+ r.lr.y = r.ul.y + WindowH;
+
+ USL_PrintInCenter (s, r);
+}
+
+//******************************************************************************
+//
+// US_CPrintLine() - Prints a string centered on the current line and
+// advances to the next line. Newlines are not supported.
+//
+//******************************************************************************
+
+void US_CPrintLine (const char *s)
+{
+ int w, h;
+
+ USL_MeasureString (s, &w, &h, CurrentFont);
+
+ if (w > WindowW)
+ Error("US_CPrintLine() - String exceeds width");
+
+ px = WindowX + ((WindowW - w) / 2);
+ py = PrintY;
+ USL_DrawString (s);
+ PrintY += h;
+}
+
+//******************************************************************************
+//
+// US_CPrint() - Prints a string in the current window. Newlines are
+// supported.
+//
+//******************************************************************************
+
+void US_CPrint (const char *string)
+{
+ char c,
+ *se,
+ *s;
+
+ strcpy(strbuf, string);
+ s = strbuf;
+
+ while (*s)
+ {
+ se = s;
+ while ((c = *se) && (c != '\n'))
+ se++;
+ *se = '\0';
+
+ US_CPrintLine (s);
+
+ s = se;
+ if (c)
+ {
+ *se = c;
+ s++;
+ }
+ }
+}
+
+
+
+//
+//
+// Text Input routines
+//
+//
+//
+
+
+
+//******************************************************************************
+//
+// USL_XORICursor() - XORs the I-bar text cursor. Used by US_LineInput()
+//
+//******************************************************************************
+
+static void USL_XORICursor (int x, int y, const char *s, int cursor, int color)
+{
+ static boolean status; // VGA doesn't XOR...
+ char buf[MaxString];
+
+ int w,h;
+ int oldx = px;
+ int oldy = py;
+
+ strcpy (buf,s);
+ buf[cursor] = '\0';
+ USL_MeasureString (buf, &w, &h, CurrentFont);
+
+
+ if (status^=1)
+ {
+ px = x + w;
+ py = y;
+ if (color)
+ USL_DrawString ("\x80");
+ else
+ DrawMenuBufPropString (px, py, "\x80");
+ }
+ else
+ {
+ if (color)
+ {
+ VWB_Bar (px, py, BKw, BKh, color);
+ USL_DrawString (s);
+ }
+ else
+ {
+ EraseMenuBufRegion (px, py, BKw, BKh);
+// EraseMenuBufRegion (px, py+1, BKw, BKh-2);
+ DrawMenuBufPropString (px, py, s);
+ }
+ }
+ px = oldx;
+ py = oldy;
+}
+
+
+
+
+
+
+//******************************************************************************
+//
+// US_LineInput() - Gets a line of user input at (x,y), the string defaults
+// to whatever is pointed at by def. Input is restricted to maxchars
+// chars or maxwidth pixels wide. If the user hits escape (and escok is
+// true), nothing is copied into buf, and false is returned. If the
+// user hits return, the current string is copied into buf, and true is
+// returned
+//
+///******************************************************************************
+
+extern byte * IN_GetScanName (ScanCode scan);
+
+boolean US_LineInput (int x, int y, char *buf, const char *def, boolean escok,
+ int maxchars, int maxwidth, int color)
+{
+ boolean redraw,
+ cursorvis,
+ cursormoved,
+ done,
+ result;
+ char s[MaxString],
+ olds[MaxString];
+ int i,
+ cursor,
+ w,h,
+ len;
+
+ int lasttime;
+
+
+ int lastkey;
+ int cursorwidth;
+
+ cursorwidth = CurrentFont->width[80-31];
+
+ memset (s, 0, MaxString);
+ memset (olds, 0, MaxString);
+ IN_ClearKeyboardQueue ();
+
+ BKw = maxwidth;
+ BKh = CurrentFont->height;
+
+
+ if (def)
+ strcpy (s, def);
+ else
+ *s = '\0';
+
+ *olds = '\0';
+
+ cursor = strlen (s);
+ cursormoved = redraw = true;
+ cursorvis = done = false;
+
+ lasttime = GetTicCount();
+
+
+ lastkey = getASCII ();
+
+ while (!done)
+ {
+// if (GameEscaped==true)
+// PauseLoop ();
+
+ IN_PumpEvents();
+
+ if (cursorvis)
+ USL_XORICursor (x, y, s, cursor, color);
+
+ LastScan = IN_InputUpdateKeyboard ();
+ if (Keyboard[sc_LShift] || Keyboard[sc_RShift])
+ lastkey = ShiftNames[LastScan];
+ else
+ lastkey = ASCIINames[LastScan];
+
+
+ switch (LastScan)
+ {
+ case sc_LeftArrow:
+
+ if (cursor)
+ {
+ cursor--;
+ cursormoved = true;
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ }
+ lastkey = key_None;
+ Keyboard[sc_LeftArrow] = 0;
+ break;
+
+ case sc_RightArrow:
+
+ if (s[cursor])
+ {
+ cursor++;
+ cursormoved = true;
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ }
+ lastkey = key_None;
+ Keyboard[sc_RightArrow] = 0;
+ break;
+
+ case sc_Home:
+
+ if ( cursor )
+ {
+ cursor = 0;
+ cursormoved = true;
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ }
+ Keyboard[sc_Home] = 0;
+ lastkey = key_None;
+ break;
+
+ case sc_End:
+
+ if ( cursor != (int)strlen (s) )
+ {
+ cursor = strlen (s);
+ cursormoved = true;
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ }
+ lastkey = key_None;
+ Keyboard[sc_End] = 0;
+ break;
+
+
+ case sc_Return:
+ strcpy (buf,s);
+ done = true;
+ result = true;
+ lastkey = key_None;
+ MN_PlayMenuSnd (SD_SELECTSND);
+ break;
+
+ case sc_Escape:
+ if (escok)
+ {
+ done = true;
+ result = false;
+ MN_PlayMenuSnd (SD_ESCPRESSEDSND);
+ }
+ lastkey = key_None;
+ break;
+
+ case sc_BackSpace:
+
+ if (cursor)
+ {
+ strcpy (s + cursor - 1,s + cursor);
+ cursor--;
+ redraw = true;
+ cursormoved = true;
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ }
+ lastkey = key_None;
+ Keyboard[sc_BackSpace] = 0;
+ IN_ClearKeyboardQueue ();
+ break;
+
+ case sc_Delete:
+
+ if (s[cursor])
+ {
+ strcpy (s + cursor,s + cursor + 1);
+ redraw = true;
+ cursormoved = true;
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ }
+ lastkey = key_None;
+ Keyboard[sc_Delete] = 0;
+ IN_ClearKeyboardQueue ();
+ break;
+
+ case 0x4c: // Keypad 5
+ case sc_UpArrow:
+ case sc_DownArrow:
+ case sc_PgUp:
+ case sc_PgDn:
+ case sc_Insert:
+ lastkey = key_None;
+ break;
+ }
+
+// if (GameEscaped==true)
+// PauseLoop ();
+
+ if (lastkey)
+ {
+ len = strlen (s);
+ USL_MeasureString (s, &w, &h, CurrentFont);
+
+ if
+ (
+ isprint(lastkey)
+ && (len < MaxString - 1)
+ && ((!maxchars) || (len < maxchars))
+ && ((!maxwidth) || ((w+2) < (maxwidth-cursorwidth-2)))
+ )
+ {
+ int ls;
+ int rs;
+
+ for (i = len + 1; i > cursor; i--)
+ s[i] = s[i - 1];
+ s[cursor++] = lastkey;
+ redraw = true;
+
+ ls = Keyboard[sc_LShift];
+ rs = Keyboard[sc_RShift];
+ memset ((void*)Keyboard, 0, 127*sizeof(int)); // Clear printable keys
+ Keyboard[sc_LShift] = ls;
+ Keyboard[sc_RShift] = rs;
+
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ }
+ }
+
+// if (GameEscaped==true)
+// PauseLoop ();
+
+ if (redraw)
+ {
+ if (color)
+ VWB_Bar (x, y, BKw, BKh, color);
+ else
+ EraseMenuBufRegion (x, y, BKw, BKh);
+
+ strcpy (olds, s);
+
+ px = x;
+ py = y;
+ if (color)
+ USL_DrawString (s);
+ else
+ DrawMenuBufPropString (px, py, s);
+ px = x;
+ py = y;
+
+ redraw = false;
+ }
+
+ if (cursormoved)
+ {
+ cursorvis = false;
+ lasttime = GetTicCount() - VBLCOUNTER;
+
+ cursormoved = false;
+ }
+ if (GetTicCount() - lasttime > VBLCOUNTER / 2)
+ {
+ lasttime = GetTicCount();
+
+ cursorvis ^= true;
+ }
+ if (cursorvis)
+ USL_XORICursor (x, y, s, cursor, color);
+
+// if (GameEscaped==true)
+// PauseLoop ();
+
+ if (color)
+ VW_UpdateScreen ();
+ else
+ RefreshMenuBuf (0);
+ }
+
+ if (cursorvis)
+ USL_XORICursor (x, y, s, cursor, color);
+
+ if (!result)
+ {
+ px = x;
+ py = y;
+ if (color)
+ USL_DrawString (olds);
+ else
+ DrawMenuBufPropString (px, py, olds);
+ }
+
+// if (GameEscaped==true)
+// PauseLoop ();
+
+ if (color)
+ VW_UpdateScreen ();
+ else
+ RefreshMenuBuf (0);
+
+ IN_ClearKeyboardQueue ();
+ return (result);
+}
+
+
+//******************************************************************************
+//
+// US_lineinput() - Gets a line of user input at (x,y), the string defaults
+// to whatever is pointed at by def. Input is restricted to maxchars
+// chars or maxwidth pixels wide. If the user hits escape (and escok is
+// true), nothing is copied into buf, and false is returned. If the
+// user hits return, the current string is copied into buf, and true is
+// returned - PASSWORD INPUT
+//
+///******************************************************************************
+
+boolean US_lineinput (int x, int y, char *buf, const char *def, boolean escok,
+ int maxchars, int maxwidth, int color)
+{
+ boolean redraw,
+ cursorvis,
+ cursormoved,
+ done,
+ result;
+ char s[MaxString],
+ xx[MaxString],
+ olds[MaxString];
+ int i,
+ cursor,
+ w,h,
+ len;
+
+ int lasttime;
+
+
+ int lastkey;
+ int cursorwidth;
+
+ cursorwidth = CurrentFont->width[80-31];
+
+ memset (s, 0, MaxString);
+ memset (xx, 0, MaxString);
+ memset (olds, 0, MaxString);
+ IN_ClearKeyboardQueue ();
+
+ BKw = maxwidth;
+ BKh = CurrentFont->height;
+
+
+ if (def)
+ strcpy (s, def);
+ else
+ *s = '\0';
+
+ *olds = '\0';
+
+ cursor = strlen (s);
+ cursormoved = redraw = true;
+ cursorvis = done = false;
+
+ lasttime = GetTicCount();
+
+
+ lastkey = getASCII ();
+
+ while (!done)
+ {
+// if (GameEscaped == true)
+// PauseLoop ();
+
+ IN_PumpEvents();
+
+ if (cursorvis)
+ USL_XORICursor (x, y, xx, cursor, color);
+
+ LastScan = IN_InputUpdateKeyboard ();
+ if (Keyboard[sc_LShift] || Keyboard[sc_RShift])
+ lastkey = ShiftNames[LastScan];
+ else
+ lastkey = ASCIINames[LastScan];
+
+
+ switch (LastScan)
+ {
+ case sc_LeftArrow:
+
+ if (cursor)
+ {
+ cursor--;
+ cursormoved = true;
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ }
+ lastkey = key_None;
+ Keyboard[sc_LeftArrow] = 0;
+ break;
+
+ case sc_RightArrow:
+
+ if (s[cursor])
+ {
+ cursor++;
+ cursormoved = true;
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ }
+ lastkey = key_None;
+ Keyboard[sc_RightArrow] = 0;
+ break;
+
+ case sc_Home:
+
+ if ( cursor != 0 )
+ {
+ cursor = 0;
+ cursormoved = true;
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ }
+ Keyboard[sc_Home] = 0;
+ lastkey = key_None;
+ break;
+
+ case sc_End:
+
+ if ( cursor != (int)strlen( s ) )
+ {
+ cursor = strlen (s);
+ cursormoved = true;
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ }
+ lastkey = key_None;
+ Keyboard[sc_End] = 0;
+ break;
+
+ case sc_Return:
+ strcpy (buf,s);
+ done = true;
+ result = true;
+ lastkey = key_None;
+ MN_PlayMenuSnd (SD_SELECTSND);
+ break;
+
+ case sc_Escape:
+ if (escok)
+ {
+ done = true;
+ result = false;
+ MN_PlayMenuSnd (SD_ESCPRESSEDSND);
+ }
+ lastkey = key_None;
+ break;
+
+ case sc_BackSpace:
+
+ if (cursor)
+ {
+ strcpy (s + cursor - 1,s + cursor);
+ strcpy (xx + cursor - 1,xx + cursor);
+ cursor--;
+ redraw = true;
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ cursormoved = true;
+ }
+ lastkey = key_None;
+ Keyboard[sc_BackSpace] = 0;
+ IN_ClearKeyboardQueue ();
+ break;
+
+ case sc_Delete:
+
+ if (s[cursor])
+ {
+ strcpy (s + cursor,s + cursor + 1);
+ strcpy (xx + cursor,xx + cursor + 1);
+ redraw = true;
+ cursormoved = true;
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ }
+ lastkey = key_None;
+ Keyboard[sc_Delete] = 0;
+ IN_ClearKeyboardQueue ();
+ break;
+
+ case 0x4c: // Keypad 5
+ case sc_UpArrow:
+ case sc_DownArrow:
+ case sc_PgUp:
+ case sc_PgDn:
+ case sc_Insert:
+ lastkey = key_None;
+ break;
+ }
+
+// if (GameEscaped==true)
+// PauseLoop ();
+
+ if (lastkey)
+ {
+ len = strlen (s);
+ USL_MeasureString (xx, &w, &h, CurrentFont);
+
+ if
+ (
+ isprint(lastkey)
+ && (len < MaxString - 1)
+ && ((!maxchars) || (len < maxchars))
+ && ((!maxwidth) || ((w+2) < (maxwidth-cursorwidth-2)))
+ )
+ {
+ int ls;
+ int rs;
+
+ for (i = len + 1; i > cursor; i--)
+ s[i] = s[i - 1];
+ s[cursor] = lastkey;
+ xx[cursor++] = '*';
+ redraw = true;
+
+ ls = Keyboard[sc_LShift];
+ rs = Keyboard[sc_RShift];
+ memset ((void*)Keyboard, 0, 127*sizeof(int)); // Clear printable keys
+ Keyboard[sc_LShift] = ls;
+ Keyboard[sc_RShift] = rs;
+ MN_PlayMenuSnd (SD_MOVECURSORSND);
+ }
+ }
+
+// if (GameEscaped==true)
+// PauseLoop ();
+
+ if (redraw)
+ {
+ if (color)
+ VWB_Bar (x, y, BKw, BKh, color);
+ else
+ EraseMenuBufRegion (x, y, BKw, BKh);
+
+ strcpy (olds, s);
+
+ px = x;
+ py = y;
+ if (color)
+ USL_DrawString (xx);
+ else
+ DrawMenuBufPropString (px, py, xx);
+ px = x;
+ py = y;
+
+ redraw = false;
+ }
+
+ if (cursormoved)
+ {
+ cursorvis = false;
+ lasttime = GetTicCount() - VBLCOUNTER;
+
+ cursormoved = false;
+ }
+ if (GetTicCount() - lasttime > VBLCOUNTER / 2)
+ {
+ lasttime = GetTicCount();
+
+ cursorvis ^= true;
+ }
+ if (cursorvis)
+ USL_XORICursor (x, y, xx, cursor, color);
+
+ if (color)
+ VW_UpdateScreen ();
+ else
+ RefreshMenuBuf (0);
+ }
+
+ if (cursorvis)
+ USL_XORICursor (x, y, xx, cursor, color);
+
+ if (!result)
+ {
+ px = x;
+ py = y;
+ if (color)
+ USL_DrawString (xx);
+ else
+ DrawMenuBufPropString (px, py, xx);
+ }
+
+// if (GameEscaped==true)
+// PauseLoop ();
+
+ if (color)
+ VW_UpdateScreen ();
+ else
+ RefreshMenuBuf (0);
+
+ IN_ClearKeyboardQueue ();
+ return (result);
+}
+
+
+
+//******************************************************************************
+//******************************************************************************
+//
+// WINDOWING ROUTINES
+//
+//******************************************************************************
+//******************************************************************************
+
+
+//******************************************************************************
+//
+// US_ClearWindow() - Clears the current window to white and homes the
+// cursor
+//
+//******************************************************************************
+
+void US_ClearWindow (void)
+{
+ VWB_Bar (WindowX, WindowY, WindowW, WindowH, 13);
+ PrintX = WindowX;
+ PrintY = WindowY;
+}
+
+
+
+
+//******************************************************************************
+//
+// US_DrawWindow() - Draws a frame and sets the current window parms
+//
+//******************************************************************************
+
+void US_DrawWindow (int x, int y, int w, int h)
+{
+ int i,
+ sx,
+ sy,
+ sw,
+ sh;
+ byte * shape;
+
+ pic_t *Win1;
+ pic_t *Win2;
+ pic_t *Win3;
+ pic_t *Win4;
+ pic_t *Win5;
+ pic_t *Win6;
+ pic_t *Win7;
+ pic_t *Win8;
+ pic_t *Win9;
+
+ // Cache in windowing shapes
+ shape = W_CacheLumpNum (W_GetNumForName ("window1"), PU_CACHE, Cvt_pic_t, 1);
+ Win1 = (pic_t *) shape;
+ shape = W_CacheLumpNum (W_GetNumForName ("window2"), PU_CACHE, Cvt_pic_t, 1);
+ Win2 = (pic_t *) shape;
+ shape = W_CacheLumpNum (W_GetNumForName ("window3"), PU_CACHE, Cvt_pic_t, 1);
+ Win3 = (pic_t *) shape;
+ shape = W_CacheLumpNum (W_GetNumForName ("window4"), PU_CACHE, Cvt_pic_t, 1);
+ Win4 = (pic_t *) shape;
+ shape = W_CacheLumpNum (W_GetNumForName ("window5"), PU_CACHE, Cvt_pic_t, 1);
+ Win5 = (pic_t *) shape;
+ shape = W_CacheLumpNum (W_GetNumForName ("window6"), PU_CACHE, Cvt_pic_t, 1);
+ Win6 = (pic_t *) shape;
+ shape = W_CacheLumpNum (W_GetNumForName ("window7"), PU_CACHE, Cvt_pic_t, 1);
+ Win7 = (pic_t *) shape;
+ shape = W_CacheLumpNum (W_GetNumForName ("window8"), PU_CACHE, Cvt_pic_t, 1);
+ Win8 = (pic_t *) shape;
+ shape = W_CacheLumpNum (W_GetNumForName ("window9"), PU_CACHE, Cvt_pic_t, 1);
+ Win9 = (pic_t *) shape;
+
+ WindowX = x * 8;
+ WindowY = y * 8;
+ WindowW = w * 8;
+ WindowH = h * 8;
+
+ PrintX = WindowX;
+ PrintY = WindowY;
+
+ sx = (x - 1) * 8;
+ sy = (y - 1) * 8;
+ sw = (w + 1) * 8;
+ sh = (h + 1) * 8;
+
+ US_ClearWindow ();
+
+
+ VWB_DrawPic (sx, sy, Win1);
+
+ VWB_DrawPic (sx, sy + sh, Win7);
+
+ for (i = sx + 8; i <= sx + sw - 8; i += 8)
+ {
+ VWB_DrawPic (i, sy, Win2);
+ VWB_DrawPic (i, sy + sh, Win8);
+ }
+
+ VWB_DrawPic (i, sy, Win3);
+ VWB_DrawPic (i, sy + sh, Win9);
+
+ for (i = sy + 8; i <= sy + sh - 8; i += 8)
+ {
+ VWB_DrawPic (sx, i, Win4);
+ VWB_DrawPic (sx + sw, i, Win6);
+ }
+}
+
+
+
+//******************************************************************************
+//
+// US_CenterWindow() - Generates a window of a given width & height in the
+// middle of the screen
+//
+//******************************************************************************
+
+void US_CenterWindow (int w, int h)
+{
+ //HDG US_DrawWindow (((MaxX / 8) - w) / 2, ((MaxY / 8) - h) / 2, w, h);
+ US_DrawWindow (((iGLOBAL_SCREENWIDTH / 8) - w) / 2,((iGLOBAL_SCREENHEIGHT / 8) - h) / 2, w, h);
+}
+
+
+
+//==============================================================================
+//
+// Intensity Font stuff
+//
+// TEXT FORMATTING COMMANDS - (Use EGA colors ONLY!)
+// -------------------------------------------------
+// /<hex digit> - Change the following word to <hex digit> color
+// ` - Highlights the following word with lighter color of fontcolor
+// /N<hex digit> - Change the fontcolor to a certain color
+//
+//==============================================================================
+
+//******************************************************************************
+//
+// GetIntensityColor ()
+//
+//******************************************************************************
+
+byte GetIntensityColor (byte pix)
+{
+ if ((fontcolor<0) || (fontcolor>255))
+ Error("Intensity Color out of range\n");
+ return ((byte) intensitytable[(pix<<8)+fontcolor]);
+}
+
+
+//******************************************************************************
+//
+// DrawIntensityChar ()
+//
+// Draws an intensity character at px, py
+//
+//******************************************************************************
+
+void DrawIntensityChar ( char ch )
+{
+
+ byte pix;
+ int px1,py1;
+ int width,w1;
+ int height,h1;
+ int ht;
+ byte *source,*src1;
+ byte *dest;
+ byte *origdest,*orgdst1;
+ int mask;
+
+ px1 = px;
+ py1 = py;
+
+ ht = IFont->height;
+
+ origdest = ( byte * )( bufferofs + ylookup[ py ] + px );
+
+ dest = origdest;
+
+ ch -= 31;
+ width = IFont->width[ (unsigned char)ch ];
+ source = ( ( byte * )IFont ) + IFont->charofs[ (unsigned char)ch ];
+
+ mask = 1 << ( px & 3 );
+
+ if ((iGLOBAL_SCREENWIDTH <= 320)||(StretchScreen == true)) {
+ while( width-- )
+ {
+ VGAMAPMASK( mask );
+
+ height = ht;
+ while( height-- )
+ {
+ pix = *source;
+ if ( pix != 0xFE )
+ {
+ *dest = GetIntensityColor( pix );
+ }
+
+ source++;
+ dest += linewidth;
+ }
+
+ px++;
+ origdest++;
+ dest = origdest;
+ }
+ } else { //strech letter in x any direction
+ w1 = width;
+ h1 = ht;
+ orgdst1 = origdest;
+ src1 = source;
+ while( width-- )
+ {
+ VGAMAPMASK( mask );
+
+ height = ht;
+ while( height-- )
+ {
+ pix = *source;
+ if ( pix != 0xFE )
+ {
+ *dest = GetIntensityColor( pix );
+ *(dest+iGLOBAL_SCREENWIDTH) = GetIntensityColor( pix );
+
+ *(dest+1) = GetIntensityColor( pix );
+ *(dest+1+iGLOBAL_SCREENWIDTH) = GetIntensityColor( pix );
+ }
+
+ source++;
+ dest += linewidth*2;
+ }
+
+ px++;
+ px++;
+ origdest++;
+ origdest++;
+ dest = origdest;
+ }
+
+ }
+
+}
+
+
+//******************************************************************************
+//
+// GetColor ()
+//
+//******************************************************************************
+
+int GetColor (int num)
+{
+ int returnval;
+
+ if ((num >= '0') && (num <= '9'))
+ returnval = egacolor[num - '0'];
+ else if ((num >= 'A') && (num <= 'F'))
+ returnval = egacolor[((num - 'A') + 10)];
+
+ return (returnval);
+}
+
+//******************************************************************************
+//
+// DrawIString ()
+//
+//******************************************************************************
+
+static int oldfontcolor = 0;
+static boolean highlight = false;
+
+void DrawIString (unsigned short int x, unsigned short int y, const char *string, int flags)
+{
+ char ch;
+ char temp;
+
+ px = x;
+ py = y;
+
+ while ((ch = *string++) != 0)
+ {
+ if ( !PERMANENT_MSG( flags ) )
+ {
+ // Highlighting is done only for 1 word - if we get a "space"
+ // and highlight is on ...., reset variables.
+ //
+ if ((ch == ' ') && (highlight == true))
+ {
+ highlight = false;
+ fontcolor = oldfontcolor;
+ DrawIntensityChar (ch);
+ }
+ else
+ // '\\' is color change to a specific EGA color (ie. egacolor)
+ //
+ if (ch == '\\')
+ {
+ temp = *string++;
+ temp = toupper (temp);
+
+ // Force fontcolor to a specific color egacolor[ RED ];
+ if (temp == 'N')
+ {
+ temp = *string++;
+ fontcolor = GetColor (temp);
+ oldfontcolor = fontcolor;
+ }
+ //bna added
+ else if (temp == 'X')
+ {
+ temp = *string;
+ fontcolor = egacolor[ RED ];
+ oldfontcolor = fontcolor;
+ }
+ else if (temp == 'Y')
+ {
+ temp = *string;
+ fontcolor = egacolor[ YELLOW ];
+ oldfontcolor = fontcolor;
+ }
+ else if (temp == 'Z')
+ {
+ temp = *string;
+ fontcolor = egacolor[ GREEN ];
+ oldfontcolor = fontcolor;
+ }
+ //bna added end
+ // Restore fontcolor to a previous color
+ else if (temp == 'O')
+ {
+ fontcolor = oldfontcolor;
+ }
+ else
+ {
+ oldfontcolor = fontcolor; // save off old font color
+ highlight = true; // set highlight
+ fontcolor = GetColor (temp);
+ }
+ }
+ else
+ // '`' is highlight the current fontcolor
+ //
+ if (ch == '`')
+ {
+ oldfontcolor = fontcolor; // save off old font color
+ highlight = true; // set highlight
+ if (fontcolor < 8) // only highlight the
+ fontcolor = fontcolor-10; // lower colors
+ }
+ else
+ DrawIntensityChar (ch);
+ }
+ else
+ DrawIntensityChar (ch);
+ }
+
+ if (highlight == true)
+ {
+ highlight = false;
+ fontcolor = oldfontcolor;
+ }
+}
+
+
+//******************************************************************************
+//
+// DrawIntensityString ()
+//
+//******************************************************************************
+
+void DrawIntensityString (unsigned short int x, unsigned short int y, const char *string, int color)
+{
+ char ch;
+
+ px = x;
+ py = y;
+
+ fontcolor=color;
+
+ while ((ch = *string++) != 0)
+ {
+ DrawIntensityChar (ch);
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+static unsigned short disp_offset = 160 * 24;
+
+void DrawRottText
+(
+ int x,
+ int y,
+ int ch,
+ int foreground,
+ int background
+)
+
+{
+ char *vid;
+
+ vid = ( char * )( 0xb0000 );
+ vid += y * 160;
+ vid += x * 2;
+
+ if ( ch != NONE )
+ {
+ *vid = ch;
+ }
+ vid++;
+ *vid = ( ( background & 0x0f ) << 4 ) | ( foreground & 0x0f );
+}
+
+void TextBox
+(
+ int x1,
+ int y1,
+ int x2,
+ int y2,
+ int ch,
+ int foreground,
+ int background
+)
+
+{
+ int x;
+ int y;
+
+ for( x = x1; x <= x2; x++ )
+ {
+ for( y = y1; y <= y2; y++ )
+ {
+ DrawRottText( x, y, ch, foreground, background );
+ }
+ }
+}
+
+void TextFrame
+(
+ int x1,
+ int y1,
+ int x2,
+ int y2,
+ int type,
+ int foreground,
+ int background
+)
+
+{
+ int x;
+ int y;
+
+ if ( type == 0 )
+ {
+ for( x = x1 + 1; x < x2; x++ )
+ {
+ DrawRottText( x, y1, type, foreground, background );
+ DrawRottText( x, y2, type, foreground, background );
+ }
+ for( y = y1 + 1; y < y2; y++ )
+ {
+ DrawRottText( x1, y, type, foreground, background );
+ DrawRottText( x2, y, type, foreground, background );
+ }
+ }
+ if ( type == SINGLE_FRAME )
+ {
+ DrawRottText( x1, y1, '�', foreground, background );
+ DrawRottText( x2, y1, '�', foreground, background );
+ DrawRottText( x1, y2, '�', foreground, background );
+ DrawRottText( x2, y2, '�', foreground, background );
+ for( x = x1 + 1; x < x2; x++ )
+ {
+ DrawRottText( x, y1, '�', foreground, background );
+ DrawRottText( x, y2, '�', foreground, background );
+ }
+ for( y = y1 + 1; y < y2; y++ )
+ {
+ DrawRottText( x1, y, '�', foreground, background );
+ DrawRottText( x2, y, '�', foreground, background );
+ }
+ }
+ if ( type == DOUBLE_FRAME )
+ {
+ DrawRottText( x1, y1, '�', foreground, background );
+ DrawRottText( x2, y1, '�', foreground, background );
+ DrawRottText( x1, y2, '�', foreground, background );
+ DrawRottText( x2, y2, '�', foreground, background );
+ for( x = x1 + 1; x < x2; x++ )
+ {
+ DrawRottText( x, y1, '�', foreground, background );
+ DrawRottText( x, y2, '�', foreground, background );
+ }
+ for( y = y1 + 1; y < y2; y++ )
+ {
+ DrawRottText( x1, y, '�', foreground, background );
+ DrawRottText( x2, y, '�', foreground, background );
+ }
+ }
+}
+
+void mysetxy
+(
+ int x,
+ int y
+)
+
+{
+ disp_offset = ( x * 2 ) + ( y * 160 );
+}
+
+void myputch
+(
+ char ch
+)
+
+{
+ int j;
+ char *disp_start = (char *)( 0xb0000 );
+
+ if ( disp_offset >= 160 * 24 )
+ {
+ for ( j = 160; j < 160 * 24; j += 2 )
+ {
+ *( disp_start + j - 160 ) = *( disp_start + j );
+ }
+
+ disp_offset = 160 * 23;
+
+ for ( j = disp_offset; j < ( 160 * 24 ); j += 2 )
+ {
+ *( disp_start + j ) = ' ';
+ }
+ }
+
+ if ( ch >= 32 )
+ {
+ *( disp_start + disp_offset ) = ch;
+ disp_offset = disp_offset + 2;
+ }
+
+ if ( ch == '\r' )
+ {
+ disp_offset = disp_offset / 160;
+ disp_offset = disp_offset * 160;
+ }
+
+ if ( ch == '\n' )
+ {
+ disp_offset = disp_offset + 160;
+ if ( disp_offset < 160 * 24 )
+ {
+ for ( j = disp_offset; j < ( ( ( disp_offset / 160 ) + 1 ) *
+ 160 ); j += 2 )
+ {
+ *( disp_start + j ) = ' ';
+ }
+ }
+ }
+}
+
+int printstring
+(
+ char *string
+)
+
+{
+ int count;
+ char *ptr;
+
+ ptr = string;
+ count = 0;
+
+ while ( *ptr )
+ {
+ myputch( *ptr );
+ count++;
+ ptr++;
+ }
+
+ return( count );
+}
+
+
+int printnum
+(
+ int number
+)
+
+{
+ char string[ 100 ];
+ int count;
+
+ itoa( number, string, 10 );
+ count = printstring( string );
+
+ return( count );
+}
+
+int printunsigned
+(
+ unsigned long number,
+ int radix
+)
+
+{
+ char string[ 100 ];
+ int count;
+
+ ultoa( number, string, radix );
+ count = printstring( string );
+
+ return( count );
+}
+
+int myprintf
+(
+ char *fmt,
+ ...
+)
+
+{
+ va_list argptr;
+ int count;
+ char *ptr;
+ if (MONOPRESENT==false)
+ {
+ Debug("%s", fmt);
+ return 0;
+ }
+ va_start( argptr, fmt );
+ ptr = fmt;
+ count = 0;
+
+ while( *ptr != 0 )
+ {
+ if ( *ptr == '%' )
+ {
+ ptr++;
+ switch( *ptr )
+ {
+ case 0 :
+ return( EOF );
+ break;
+ case 'l' :
+ count += printnum( va_arg( argptr, int ) );
+ ptr++;
+ break;
+ case 'd' :
+ count += printnum( va_arg( argptr, int ) );
+ break;
+ case 's' :
+ count += printstring( va_arg( argptr, char * ) );
+ break;
+ case 'u' :
+ count += printunsigned( va_arg( argptr, int ), 10 );
+ break;
+ case 'x' :
+ case 'X' :
+ count += printunsigned( va_arg( argptr, int ), 16 );
+ break;
+ }
+ ptr++;
+ }
+ else
+ {
+ myputch( *ptr );
+ count++;
+ ptr++;
+ }
+ }
+
+ va_end( argptr );
+
+ return( count );
+}
--- /dev/null
+++ b/rott/rt_str.h
@@ -1,0 +1,125 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// Public header for RT_STR.C.
+//
+//***************************************************************************
+
+#ifndef _rt_str_public
+#define _rt_str_public
+
+#include "lumpy.h"
+
+
+//***************************************************************************
+//
+// GLOBALS
+//
+//***************************************************************************
+
+extern int fontcolor;
+
+
+//***************************************************************************
+//
+// TYPEDEFS
+//
+//***************************************************************************
+
+typedef struct
+{
+ int x,y;
+} Point;
+
+typedef struct
+{
+ int x, y,
+ w, h,
+ px, py;
+} WindowRec; // Record used to save & restore screen windows
+
+typedef struct
+{
+ Point ul,lr;
+} Rect;
+
+
+//***************************************************************************
+//
+// PROTOTYPES
+//
+//***************************************************************************
+
+//
+// String rtns
+//
+
+void VW_DrawClippedString (int x, int y, const char *string);
+void US_ClippedPrint (int x, int y, const char *s);
+
+void VWB_DrawPropString (const char *string);
+void VW_MeasurePropString (const char *string, int *width, int *height);
+
+void US_MeasureStr (int *width, int *height, const char * s, ...) __attribute__((format(printf,3,4)));
+
+void VW_DrawPropString (const char *string);
+
+void US_SetPrintRoutines (void (*measure)(const char *, int *, int *, font_t *),
+ void (*print)(const char *));
+void US_Print (const char *s);
+void US_BufPrint (const char *s);
+void US_PrintUnsigned (unsigned long int n);
+void US_PrintSigned (long int n);
+void USL_PrintInCenter (const char *s, Rect r);
+void US_PrintCentered (const char *s);
+void US_CPrintLine (const char *s);
+void US_CPrint (const char *s);
+
+
+//
+// Input rtns
+//
+
+boolean US_LineInput (int x, int y, char *buf, const char *def, boolean escok,
+ int maxchars, int maxwidth, int color);
+boolean US_lineinput (int x, int y, char *buf, const char *def, boolean escok,
+ int maxchars, int maxwidth, int color);
+int CalibrateJoystick(void);
+
+//
+// Window rtns
+//
+
+void US_DrawWindow (int x, int y, int w, int h);
+void US_CenterWindow (int w, int h);
+
+//
+// Intensity font rtns
+//
+
+void DrawIString (unsigned short int x, unsigned short int y, const char *string, int flags);
+void DrawIntensityString (unsigned short int x, unsigned short int y, const char *string, int color);
+void VW_MeasureIntensityPropString (const char *string, int *width, int *height);
+byte GetIntensityColor (byte pix);
+
+#include "myprint.h"
+
+#endif
--- /dev/null
+++ b/rott/rt_swift.c
@@ -1,0 +1,429 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//****************************************************************************
+//
+// RT_SWIFT.C
+//
+// SWIFT services module - for CYBERMAN use in ROTT.
+//
+//****************************************************************************
+
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef DOS
+#include <dos.h>
+#endif
+
+#include "rt_def.h"
+#include "rt_swift.h"
+#include "_rt_swft.h"
+//MED
+#include "memcheck.h"
+
+
+#ifdef DOS
+
+//****************************************************************************
+//
+// SWIFT_Initialize ()
+//
+// Test for presence of SWIFT extensions and SWIFT device.
+// Returns 1 (TRUE) if SWIFT features are available, 0 otherwise.
+// Remember to call SWIFT_Terminate() if SWIFT_Initialize succeeds!
+//
+//****************************************************************************
+
+int SWIFT_Initialize (void)
+{
+ SWIFT_StaticData sdBuf;
+ int fSwift = 0;
+
+ if (fActive) // SWIFT extensions already active
+ {
+#ifdef DEGUB
+ SoftError( "SWIFT_Initialize: Already active.\n");
+ SoftError( "SWIFT_Initialize: returns TRUE\n");
+#endif
+ return (1);
+ }
+
+ nAttached = SWIFT_DEV_NONE;
+
+
+ if (_dos_getvect(0x33) == NULL) // No mouse driver loaded
+ {
+#ifdef DBUG
+ SoftError( "SWIFT_Initialize: No mouse driver loaded.\n");
+ SoftError( "SWIFT_Initialize: returns FALSE\n");
+#endif
+ return (0);
+ }
+
+
+ // Reset the mouse and driver
+ AX (regs) = 0;
+ int386( 0x33, ®s, ®s);
+
+ if (AX (regs) == 0)
+ { // no mouse
+#ifdef DBUG
+ SoftError( "SWIFT_Initialize: No pointing device attached.\n");
+ SoftError( "SWIFT_Initialize: returns FALSE\n");
+#endif
+ return (0);
+ }
+
+#ifdef DBUG
+ AX (regs) = 36; // Get Mouse Information
+ BX (regs) = 0xffff;
+ CX (regs) = 0xffff;
+ DX (regs) = 0xffff;
+ int386 (0x33, ®s, ®s);
+ SoftError( "SWIFT_Initialize: driver version %d.%02d\n", regs.h.bh, regs.h.bl);
+ SoftError( "SWIFT_Initialize: %s mouse using IRQ %d\n",
+ (regs.h.ch==1) ? "bus" :
+ (regs.h.ch==2) ? "serial" :
+ (regs.h.ch==3) ? "inport" :
+ (regs.h.ch==4) ? "PS/2" :
+ "unknown", regs.h.cl);
+#endif
+
+
+ // allocate a DOS real-mode buffer
+ pdosmem = allocDOS(DOSMEMSIZE, &segment, &selector);
+ if (!pdosmem)
+ {
+#ifdef DBUG
+ SoftError( "SWIFT_Initialize: DOS Alloc failed!\n");
+ SoftError( "SWIFT_Initialize: returns FALSE\n");
+#endif
+ return (0);
+ }
+
+//
+// SWIFT device supported and attached
+//
+ if (SWIFT_GetStaticDeviceInfo (&sdBuf))
+ fSwift = 1;
+
+
+ if (!fSwift)
+ { // SWIFT functions not present
+#ifdef DBUG
+ SoftError( "SWIFT_Initialize: no SWIFT support in mouse driver.\n");
+#endif
+ }
+ else if (sdBuf.deviceType == SWIFT_DEV_NONE)
+ {
+#ifdef DBUG
+ SoftError( "SWIFT_Initialize: no SWIFT device connected.\n");
+#endif
+ }
+ else
+ {
+ nAttached = sdBuf.deviceType;
+#ifdef DBUG
+ SoftError( "SWIFT_Initialize: ");
+
+ switch (nAttached)
+ {
+ case SWIFT_DEV_CYBERMAN:
+ SoftError( "CyberMan %d.%02d connected.\n",
+ sdBuf.majorVersion, sdBuf.minorVersion);
+ break;
+
+ default:
+ SoftError( "Unknown SWIFT device (type %d) connected.\n",
+ nAttached);
+ break;
+ }
+#endif
+ fActive = 1;
+ }
+
+ if (!fActive)
+ { // activation of SWIFT module failed for some reason
+ if (pdosmem)
+ { // if DOS buffer was allocated, free it
+ freeDOS(selector);
+ pdosmem = 0;
+ }
+ }
+
+#ifdef DBUG
+ SoftError( "SWIFT_Initialize: returns %s.\n", (fActive ? "TRUE" : "FALSE"));
+#endif
+ return fActive;
+}
+
+
+
+//****************************************************************************
+//
+// SWIFT_Terminate ()
+//
+// Free resources required for SWIFT support. If SWIFT_Initialize has
+// not been called, or returned FALSE, this function does nothing.
+// SWIFT_Terminate should always be called at some time after a call to
+// SWIFT_Initialize has returned TRUE.
+//
+//****************************************************************************
+
+void SWIFT_Terminate (void)
+{
+#ifdef DBUG
+ SoftError( "SWIFT_Terminate called.\n");
+#endif
+
+ if (fActive)
+ {
+ // free DOS buffer
+ if (pdosmem)
+ {
+ freeDOS(selector);
+ pdosmem = 0;
+ }
+
+ fActive = 0;
+ }
+}
+
+
+//****************************************************************************
+//
+// SWIFT_GetAttachedDevice ()
+//
+// Returns the device-type code for the attached SWIFT device, if any.
+//
+//****************************************************************************
+
+int SWIFT_GetAttachedDevice (void)
+{
+ return (nAttached);
+}
+
+
+
+//****************************************************************************
+//
+// SWIFT_GetStaticDeviceInfo ()
+//
+// Reads static device data.
+//
+//****************************************************************************
+
+int SWIFT_GetStaticDeviceInfo (SWIFT_StaticData far *psd)
+{
+ memset (&RMI, 0, sizeof (RMI));
+ RMI.ax = 0x53C1; // SWIFT: Get Static Device Data
+ RMI.es = segment; // DOS buffer real-mode segment
+ RMI.dx = 0; // " " " " offset
+ MouseInt (&RMI); // get data into DOS buffer
+
+ *psd = *(SWIFT_StaticData *)pdosmem; // then copy into caller's buffer
+ return (RMI.ax == 1); // return success
+}
+
+
+
+//****************************************************************************
+//
+// SWIFT_Get3DStatus ()
+//
+// Read the current input state of the device.
+//
+//****************************************************************************
+
+
+void SWIFT_Get3DStatus (SWIFT_3DStatus far *pstat)
+{
+#ifdef DBUG
+ if (!fActive)
+ {
+ SoftError( "SWIFT_Get3DStatus: SWIFT module not active!\n");
+ }
+#endif
+
+ memset (&RMI, 0, sizeof (RMI));
+ RMI.ax = 0x5301;
+ RMI.es = segment;
+ RMI.dx = 0;
+ MouseInt(&RMI);
+ *pstat = *(SWIFT_3DStatus *)pdosmem;
+}
+
+
+
+
+//****************************************************************************
+//
+// SWIFT_TactileFeedback ()
+//
+// Generates tactile feedback to user.
+// d = duration of tactile burst, in milliseconds.
+// on = motor on-time per cycle, in milliseconds.
+// off = motor off-time per cycle, in milliseconds.
+//
+//****************************************************************************
+
+void SWIFT_TactileFeedback (int d, int on, int off)
+{
+ // Use DPMI call 300h to issue mouse interrupt
+ memset (&RMI, 0, sizeof(RMI));
+ RMI.ax = 0x5330; // SWIFT: Get Position & Buttons
+ RMI.bx = (on / 5) << 8 + (off / 5);
+ RMI.cx = d / 40;
+ MouseInt (&RMI);
+
+#ifdef DBUG
+ SoftError( "SWIFT_TactileFeedback (dur=%d ms, on=%d ms, off=%d ms)\n",
+ d / 40 * 40, on/5*5, off/5*5);
+#endif
+}
+
+
+
+//****************************************************************************
+//
+// SWIFT_GetDynamicDeviceData ()
+//
+// Returns Dynamic Device Data word - see SDD_* above
+//
+//****************************************************************************
+
+unsigned SWIFT_GetDynamicDeviceData (void)
+{
+ memset (&RMI, 0, sizeof(RMI));
+ RMI.ax = 0x53C2; // SWIFT: Get Dynamic Device Data
+ MouseInt (&RMI);
+ return ((unsigned)RMI.ax);
+}
+
+
+//****************************************************************************
+//
+// MouseInt ()
+//
+// Generate a call to the mouse driver (interrupt 33h) in real mode,
+// using the DPMI function 'Simulate Real-Mode Interrupt'.
+//
+//****************************************************************************
+
+void MouseInt (struct rminfo *prmi)
+{
+ memset (&sregs, 0, sizeof (sregs));
+ AX (regs) = 0x0300; // DPMI: simulate interrupt
+ BX (regs) = MOUSE_INT;
+ CX (regs) = 0;
+ DI (regs) = FP_OFF (prmi);
+ sregs.es = FP_SEG (prmi);
+ int386x( DPMI_INT, ®s, ®s, &sregs );
+}
+
+
+//****************************************************************************
+//
+// freeDOS ()
+//
+// Release real-mode DOS memory block via DPMI
+//
+//****************************************************************************
+
+void freeDOS (short sel)
+{
+ AX(regs) = 0x0101; // DPMI free DOS memory
+ DX(regs) = sel;
+
+ int386( DPMI_INT, ®s, ®s);
+}
+
+
+//****************************************************************************
+//
+// allocDOS ()
+//
+// Allocate a real-mode DOS memory block via DPMI
+//
+//****************************************************************************
+
+void far *allocDOS (unsigned nbytes, short *pseg, short *psel)
+{
+ unsigned npara = (nbytes + 15) / 16;
+ void far *pprot;
+ pprot = NULL;
+ *pseg = 0; // assume will fail
+ *psel = 0;
+
+ // DPMI call 100h allocates DOS memory
+ segread (&sregs);
+ AX (regs) = 0x0100; // DPMI: Allocate DOS Memory
+ BX (regs) = npara; // number of paragraphs to alloc
+ int386( DPMI_INT, ®s, ®s);
+
+ if (regs.w.cflag == 0)
+ {
+ *pseg = AX (regs); // the real-mode segment
+ *psel = DX (regs); // equivalent protected-mode selector
+ // pprot is the protected mode address of the same allocated block.
+ // The Rational extender maps the 1 MB physical DOS memory into
+ // the bottom of our virtual address space.
+ pprot = (void far *) ((unsigned)*pseg << 4);
+ }
+ return pprot;
+}
+
+#else
+
+/* This isn't of much use in Linux. */
+
+int SWIFT_Initialize (void)
+{
+ STUB_FUNCTION;
+
+ return 0;
+}
+
+void SWIFT_Terminate (void)
+{
+ STUB_FUNCTION;
+}
+
+void SWIFT_Get3DStatus (SWIFT_3DStatus far *pstat)
+{
+ STUB_FUNCTION;
+}
+
+void SWIFT_TactileFeedback (int d, int on, int off)
+{
+ STUB_FUNCTION;
+}
+
+unsigned SWIFT_GetDynamicDeviceData (void)
+{
+ STUB_FUNCTION;
+
+ return 0;
+}
+
+#endif
--- /dev/null
+++ b/rott/rt_swift.h
@@ -1,0 +1,81 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_swift_public
+#define _rt_swift_public
+
+//***************************************************************************
+//
+// Public header for RT_SWIFT.C.
+//
+//***************************************************************************
+
+#include "rt_playr.h"
+
+//***************************************************************************
+//
+// PROTOTYPES
+//
+//***************************************************************************
+
+int SWIFT_Initialize (void);
+//
+// Test for presence of SWIFT extensions and SWIFT device
+// Returns 1 (TRUE) if SWIFT features are available, 0 otherwise.
+// Remember to call SWIFT_Terminate() if SWIFT_Initialize succeeds!
+//
+
+void SWIFT_Terminate (void);
+//
+// Free resources required for SWIFT support. If SWIFT_Initialize has
+// not been called, or returned FALSE, this function does nothing.
+// SWIFT_Terminate should always be called at some time after a call to
+// SWIFT_Initialize has returned TRUE.
+//
+
+int SWIFT_GetAttachedDevice (void);
+//
+// Returns the device-type code for the attached SWIFT device, if any.
+//
+
+int SWIFT_GetStaticDeviceInfo (SWIFT_StaticData far *psd);
+//
+// Reads static device data.
+//
+
+void SWIFT_Get3DStatus (SWIFT_3DStatus far *pstat);
+//
+// Read the current input state of the device.
+//
+
+void SWIFT_TactileFeedback (int d, int on, int off);
+//
+// Generates tactile feedback to user.
+// d = duration of tactile burst, in milliseconds.
+// on = motor on-time per cycle, in milliseconds.
+// off = motor off-time per cycle, in milliseconds.
+//
+
+unsigned SWIFT_GetDynamicDeviceData (void);
+//
+// Returns Dynamic Device Data word - see SDD_* above
+//
+
+
+#endif
--- /dev/null
+++ b/rott/rt_table.h
@@ -1,0 +1,1331 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_table_public
+#define _rt_table_public
+
+#include "states.h"
+
+statetype * statetable[MAXSTATES]=
+{
+ &s_lowgrdstand ,
+ &s_lowgrdpath4 ,
+ &s_lowgrdpath3 ,
+ &s_lowgrdpath2 ,
+ &s_lowgrdpath1 ,
+ &s_lowgrdcollide,
+ &s_lowgrdcollide2,
+ &s_lowgrdshoot4 ,
+ &s_lowgrdshoot3 ,
+ &s_lowgrdshoot2 ,
+ &s_lowgrdshoot1 ,
+ &s_lowgrdchase4 ,
+ &s_lowgrdchase3 ,
+ &s_lowgrdchase2 ,
+ &s_lowgrdchase1 ,
+ &s_lowgrddead ,
+ &s_lowgrddie4 ,
+ &s_lowgrddie3 ,
+ &s_lowgrddie2 ,
+ &s_lowgrddie1 ,
+ &s_lowgrdcrushed2 ,
+ &s_lowgrdcrushed1 ,
+ &s_sneakydown,
+ &s_sneakyrise4,
+ &s_sneakyrise3,
+ &s_sneakyrise2,
+ &s_sneakyrise1,
+ &s_highgrdstand ,
+ &s_highgrdpath4 ,
+ &s_highgrdpath3 ,
+ &s_highgrdpath2 ,
+ &s_highgrdpath1 ,
+ &s_highgrdcollide,
+ &s_highgrdcollide2,
+ &s_highgrdshoot4,
+ &s_highgrdshoot3,
+ &s_highgrdshoot2 ,
+ &s_highgrdshoot1 ,
+ &s_highgrdchase4 ,
+ &s_highgrdchase3 ,
+ &s_highgrdchase2 ,
+ &s_highgrdchase1 ,
+ &s_highgrddead ,
+ &s_highgrddie5 ,
+ &s_highgrddie4 ,
+ &s_highgrddie3 ,
+ &s_highgrddie2 ,
+ &s_highgrddie1 ,
+ &s_highgrdcrushed2 ,
+ &s_highgrdcrushed1 ,
+ &s_strikestand ,
+ &s_strikepath4 ,
+ &s_strikepath3 ,
+ &s_strikepath2 ,
+ &s_strikepath1 ,
+ &s_strikecollide,
+ &s_strikecollide2,
+ &s_strikeshoot4 ,
+ &s_strikeshoot3 ,
+ &s_strikeshoot2 ,
+ &s_strikeshoot1 ,
+ &s_strikewait,
+ &s_strikerollright6,
+ &s_strikerollright5,
+ &s_strikerollright4,
+ &s_strikerollright3,
+ &s_strikerollright2,
+ &s_strikerollright1,
+ &s_strikerollleft6,
+ &s_strikerollleft5,
+ &s_strikerollleft4,
+ &s_strikerollleft3,
+ &s_strikerollleft2,
+ &s_strikerollleft1,
+ &s_strikechase4 ,
+ &s_strikechase3 ,
+ &s_strikechase2 ,
+ &s_strikechase1 ,
+ &s_strikedead3 ,
+ &s_strikedead2 ,
+ &s_strikedead ,
+ &s_strikedie4 ,
+ &s_strikedie3 ,
+ &s_strikedie2 ,
+ &s_strikedie1 ,
+ &s_strikecrushed2 ,
+ &s_strikecrushed1 ,
+ &s_blitzstand,
+ &s_blitzpath4,
+ &s_blitzpath3,
+ &s_blitzpath2,
+ &s_blitzpath1,
+ &s_blitzcollide,
+ &s_blitzcollide2,
+ &s_blitzshoot4,
+ &s_blitzshoot3,
+ &s_blitzshoot2,
+ &s_blitzshoot1,
+ &s_blitzrise4,
+ &s_blitzrise3,
+ &s_blitzrise2,
+ &s_blitzrise1,
+ &s_blitzuse,
+ &s_blitzsteal2,
+ &s_blitzsteal1,
+ &s_blitzchase4 ,
+ &s_blitzchase3 ,
+ &s_blitzchase2 ,
+ &s_blitzchase1 ,
+ &s_blitzdead2 ,
+ &s_blitzdead ,
+ &s_blitzdie4 ,
+ &s_blitzdie3 ,
+ &s_blitzdie2 ,
+ &s_blitzdie1 ,
+ &s_blitzcrushed2 ,
+ &s_blitzcrushed1 ,
+ &s_blitzplead1,
+ &s_blitzplead2,
+ &s_blitzplead3,
+ &s_blitzplead4,
+ &s_blitzplead5,
+ &s_blitzplead6,
+ &s_blitzplead7,
+ &s_blitzplead8,
+ &s_blitzplead9,
+ &s_blitzplead10,
+ &s_blitzplead11,
+ &s_blitzaplead5,
+ &s_blitzaplead4,
+ &s_blitzfakedead,
+ &s_blitzfakedie3,
+ &s_blitzfakedie2,
+ &s_blitzfakedie1,
+ &s_blitzstruggledie1,
+ &s_blitzstruggledead,
+ &s_enforcerstand,
+ &s_enforcerpath4 ,
+ &s_enforcerpath3 ,
+ &s_enforcerpath2 ,
+ &s_enforcerpath1 ,
+ &s_enforcerchase4 ,
+ &s_enforcerchase3 ,
+ &s_enforcerchase2 ,
+ &s_enforcerchase1 ,
+ &s_enforcercollide,
+ &s_enforcercollide2,
+ &s_enforcershoot4,
+ &s_enforcershoot3,
+ &s_enforcershoot2,
+ &s_enforcershoot1,
+ &s_enforcerthrow8,
+ &s_enforcerthrow7,
+ &s_enforcerthrow6,
+ &s_enforcerthrow5,
+ &s_enforcerthrow4,
+ &s_enforcerthrow3,
+ &s_enforcerthrow2,
+ &s_enforcerthrow1,
+ &s_grenade10,
+ &s_grenade9,
+ &s_grenade8,
+ &s_grenade7,
+ &s_grenade6,
+ &s_grenade5,
+ &s_grenade4,
+ &s_grenade3,
+ &s_grenade2,
+ &s_grenade1,
+ &s_grenade_fall6,
+ &s_grenade_fall5,
+ &s_grenade_fall4,
+ &s_grenade_fall3,
+ &s_grenade_fall2,
+ &s_grenade_fall1,
+ &s_grenadehit3,
+ &s_grenadehit2,
+ &s_grenadehit1,
+ &s_enforcerdead ,
+ &s_enforcerdie4 ,
+ &s_enforcerdie3 ,
+ &s_enforcerdie2 ,
+ &s_enforcerdie1 ,
+ &s_enforcercrushed2 ,
+ &s_enforcercrushed1 ,
+
+
+ &s_robogrdstand ,
+ &s_robogrdpath1 ,
+ &s_robogrdshoot1 ,
+ &s_robogrdshuriken4 ,
+ &s_robogrdshuriken3 ,
+ &s_robogrdshuriken2 ,
+ &s_robogrdshuriken1 ,
+ &s_shurikenhit3,
+ &s_shurikenhit2,
+ &s_shurikenhit1,
+ &s_robogrdcollide,
+ &s_robogrdcollide2,
+ &s_robogrddead ,
+ &s_robogrddie9 ,
+ &s_robogrddie8 ,
+ &s_robogrddie7 ,
+ &s_robogrddie6 ,
+ &s_robogrddie5 ,
+ &s_robogrddie4 ,
+ &s_robogrddie3 ,
+ &s_robogrddie2 ,
+ &s_robogrddie1 ,
+ &s_roboalign,
+ &s_roborealign,
+ &s_robowait,
+
+ &s_altexplosion10,
+ &s_altexplosion9,
+ &s_altexplosion8,
+ &s_altexplosion7,
+ &s_altexplosion6,
+ &s_altexplosion5,
+ &s_altexplosion4,
+ &s_altexplosion3,
+ &s_altexplosion2,
+ &s_altexplosion1,
+
+
+ &s_explosion20,
+ &s_explosion19,
+ &s_explosion18,
+ &s_explosion17,
+ &s_explosion16,
+ &s_explosion15,
+ &s_explosion14,
+ &s_explosion13,
+ &s_explosion12,
+ &s_explosion11,
+ &s_explosion10,
+ &s_explosion9,
+ &s_explosion8,
+ &s_explosion7,
+ &s_explosion6,
+ &s_explosion5,
+ &s_explosion4,
+ &s_explosion3,
+ &s_explosion2,
+ &s_explosion1,
+ &s_grexplosion20,
+ &s_grexplosion19,
+ &s_grexplosion18,
+ &s_grexplosion17,
+ &s_grexplosion16,
+ &s_grexplosion15,
+ &s_grexplosion14,
+ &s_grexplosion13,
+ &s_grexplosion12,
+ &s_grexplosion11,
+ &s_grexplosion10,
+ &s_grexplosion9,
+ &s_grexplosion8,
+ &s_grexplosion7,
+ &s_grexplosion6,
+ &s_grexplosion5,
+ &s_grexplosion4,
+ &s_grexplosion3,
+ &s_grexplosion2,
+ &s_grexplosion1,
+
+ &s_staticexplosion25,
+ &s_staticexplosion24,
+ &s_staticexplosion23,
+ &s_staticexplosion22,
+ &s_staticexplosion21,
+ &s_staticexplosion20,
+ &s_staticexplosion19,
+ &s_staticexplosion18,
+ &s_staticexplosion17,
+ &s_staticexplosion16,
+ &s_staticexplosion15,
+ &s_staticexplosion14,
+ &s_staticexplosion13,
+ &s_staticexplosion12,
+ &s_staticexplosion11,
+ &s_staticexplosion10,
+ &s_staticexplosion9,
+ &s_staticexplosion8,
+ &s_staticexplosion7,
+ &s_staticexplosion6,
+ &s_staticexplosion5,
+ &s_staticexplosion4,
+ &s_staticexplosion3,
+ &s_staticexplosion2,
+ &s_staticexplosion1,
+
+
+ &s_upblade16,
+ &s_upblade15,
+ &s_upblade14,
+ &s_upblade13,
+ &s_upblade12,
+ &s_upblade11,
+ &s_upblade10,
+ &s_upblade9,
+ &s_upblade8,
+ &s_upblade7,
+ &s_upblade6,
+ &s_upblade5,
+ &s_upblade4,
+ &s_upblade3,
+ &s_upblade2,
+ &s_upblade1,
+
+
+ &s_firejetup23,
+ &s_firejetup22,
+ &s_firejetup21,
+ &s_firejetup20,
+ &s_firejetup19,
+ &s_firejetup18,
+ &s_firejetup17,
+ &s_firejetup16,
+ &s_firejetup15,
+ &s_firejetup14,
+ &s_firejetup13,
+ &s_firejetup12,
+ &s_firejetup11,
+ &s_firejetup10,
+ &s_firejetup9,
+ &s_firejetup8,
+ &s_firejetup7,
+ &s_firejetup6,
+ &s_firejetup5,
+ &s_firejetup4,
+ &s_firejetup3,
+ &s_firejetup2,
+ &s_firejetup1,
+
+
+ &s_columndownup6,
+ &s_columndownup5,
+ &s_columndownup4,
+ &s_columndownup3,
+ &s_columndownup2,
+ &s_columndownup1,
+ &s_columndowndown8,
+ &s_columndowndown7,
+ &s_columndowndown6,
+ &s_columndowndown5,
+ &s_columndowndown4,
+ &s_columndowndown3,
+ &s_columndowndown2,
+ &s_columndowndown1,
+
+
+ &s_spearup16,
+ &s_spearup15,
+ &s_spearup14,
+ &s_spearup13,
+ &s_spearup12,
+ &s_spearup11,
+ &s_spearup10,
+ &s_spearup9,
+ &s_spearup8,
+ &s_spearup7,
+ &s_spearup6,
+ &s_spearup5,
+ &s_spearup4,
+ &s_spearup3,
+ &s_spearup2,
+ &s_spearup1,
+
+ &s_pushcolumn1,
+ &s_pushcolumn2,
+ &s_pushcolumn3,
+ &s_wallfireball,
+ &s_crossfire2,
+ &s_crossfire1,
+ &s_crossdone5,
+ &s_crossdone4,
+ &s_crossdone3,
+ &s_crossdone2,
+ &s_crossdone1,
+ &s_dust,
+ &s_gas2,
+ &s_gas1,
+ &s_p_bazooka1,
+ &s_p_grenade,
+ &s_gunsmoke8,
+ &s_gunsmoke7,
+ &s_gunsmoke6,
+ &s_gunsmoke5,
+ &s_gunsmoke4,
+ &s_gunsmoke3,
+ &s_gunsmoke2,
+ &s_gunsmoke1,
+ &s_bloodspurt8,
+ &s_bloodspurt7,
+ &s_bloodspurt6,
+ &s_bloodspurt5,
+ &s_bloodspurt4,
+ &s_bloodspurt3,
+ &s_bloodspurt2,
+ &s_bloodspurt1,
+ &s_hitmetalwall4,
+ &s_hitmetalwall3,
+ &s_hitmetalwall2,
+ &s_hitmetalwall1,
+ &s_hitmetalactor4,
+ &s_hitmetalactor3,
+ &s_hitmetalactor2,
+ &s_hitmetalactor1,
+ &s_fireunit15,
+ &s_fireunit14,
+ &s_fireunit13,
+ &s_fireunit12,
+ &s_fireunit11,
+ &s_fireunit10,
+ &s_fireunit9,
+ &s_fireunit8,
+ &s_fireunit7,
+ &s_fireunit6,
+ &s_fireunit5,
+ &s_fireunit4,
+ &s_fireunit3,
+ &s_fireunit2,
+ &s_fireunit1,
+ &s_skeleton48,
+ &s_skeleton47,
+ &s_skeleton46,
+ &s_skeleton45,
+ &s_skeleton44,
+ &s_skeleton43,
+ &s_skeleton42,
+ &s_skeleton41,
+ &s_skeleton40,
+ &s_skeleton39,
+ &s_skeleton38,
+ &s_skeleton37,
+ &s_skeleton36,
+ &s_skeleton35,
+ &s_skeleton34,
+ &s_skeleton33,
+ &s_skeleton32,
+ &s_skeleton31,
+ &s_skeleton30,
+ &s_skeleton29,
+ &s_skeleton28,
+ &s_skeleton27,
+ &s_skeleton26,
+ &s_skeleton25,
+ &s_skeleton24,
+ &s_skeleton23,
+ &s_skeleton22,
+ &s_skeleton21,
+ &s_skeleton20,
+ &s_skeleton19,
+ &s_skeleton18,
+ &s_skeleton17,
+ &s_skeleton16,
+ &s_skeleton15,
+ &s_skeleton14,
+ &s_skeleton13,
+ &s_skeleton12,
+ &s_skeleton11,
+ &s_skeleton10,
+ &s_skeleton9,
+ &s_skeleton8,
+ &s_skeleton7,
+ &s_skeleton6,
+ &s_skeleton5,
+ &s_skeleton4,
+ &s_skeleton3,
+ &s_skeleton2,
+ &s_skeleton1,
+ &s_spring9,
+ &s_spring8,
+ &s_spring7,
+ &s_spring6,
+ &s_spring5,
+ &s_spring4,
+ &s_spring3,
+ &s_spring2,
+ &s_spring1,
+ &s_pgunattack1,
+ &s_pmissattack1,
+ &s_pgunattack2,
+ &s_pmissattack2,
+ &s_pbatblast,
+ &s_remotemove4,
+ &s_remotemove3,
+ &s_remotemove2,
+ &s_remotemove1,
+ &s_remoteinelev,
+ &s_remotedead,
+ &s_remotedie5,
+ &s_remotedie4,
+ &s_remotedie3,
+ &s_remotedie2,
+ &s_remotedie1,
+ &s_godfire4,
+ &s_godfire3,
+ &s_godfire2,
+ &s_godfire1,
+ &s_guts12,
+ &s_guts11,
+ &s_guts10,
+ &s_guts9,
+ &s_guts8,
+ &s_guts7,
+ &s_guts6,
+ &s_guts5,
+ &s_guts4,
+ &s_guts3,
+ &s_guts2,
+ &s_guts1,
+ &s_player,
+ &s_free,
+ &s_megaexplosions,
+ &s_bossdeath,
+ &s_superparticles,
+ &s_littlesoul,
+ &s_bigsoul,
+ &s_vaporized8,
+ &s_vaporized7,
+ &s_vaporized6,
+ &s_vaporized5,
+ &s_vaporized4,
+ &s_vaporized3,
+ &s_vaporized2,
+ &s_vaporized1,
+
+ &s_autospring1,
+ &s_autospring2,
+ &s_autospring3,
+ &s_autospring4,
+ &s_autospring5,
+ &s_autospring6,
+ &s_autospring7,
+ &s_autospring8,
+ &s_autospring9,
+
+
+ &s_gibsdone8,
+ &s_gibsdone7,
+ &s_gibsdone6,
+ &s_gibsdone5,
+ &s_gibsdone4,
+ &s_gibsdone3,
+ &s_gibsdone2,
+ &s_gibsdone1,
+ &s_gibs4,
+ &s_gibs3,
+ &s_gibs2,
+ &s_gibs1,
+
+
+
+ &s_collectorwander8,
+ &s_collectorwander7,
+ &s_collectorwander6,
+ &s_collectorwander5,
+ &s_collectorwander4,
+ &s_collectorwander3,
+ &s_collectorwander2,
+ &s_collectorwander1,
+ &s_collectorfdoor8,
+ &s_collectorfdoor7,
+ &s_collectorfdoor6,
+ &s_collectorfdoor5,
+ &s_collectorfdoor4,
+ &s_collectorfdoor3,
+ &s_collectorfdoor2,
+ &s_collectorfdoor1,
+ &s_tag,
+ &s_wind,
+ &s_timekeeper,
+ &s_remoteguts1,
+ &s_remoteguts2,
+ &s_remoteguts3,
+ &s_remoteguts4,
+ &s_remoteguts5,
+ &s_remoteguts6,
+ &s_remoteguts7,
+ &s_remoteguts8,
+ &s_remoteguts9,
+ &s_remoteguts10,
+ &s_remoteguts11,
+ &s_remoteguts12,
+ &s_voidwait,
+ &s_ashwait,
+ &s_deadwait,
+ &s_gutwait,
+ &s_eye1,
+ &s_eye2,
+ &s_eye3,
+ &s_itemspawn1,
+ &s_itemspawn2,
+ &s_itemspawn3,
+ &s_itemspawn4,
+ &s_itemspawn5,
+ &s_itemspawn6,
+ &s_itemspawn7,
+ &s_itemspawn8,
+ &s_deadblood1,
+ &s_deadblood2,
+ &s_deadblood3,
+ &s_deadblood4,
+ &s_deadblood5,
+ &s_deadblood6,
+ &s_deadblood7,
+ &s_deadblood8,
+ &s_flash1,
+ &s_flash2,
+ &s_flash3,
+ &s_flash4,
+ &s_flash5,
+ &s_flash6,
+ &s_flash7,
+ &s_flash8,
+ &s_basemarker1,
+ &s_basemarker2,
+ &s_basemarker3,
+ &s_basemarker4,
+ &s_basemarker5,
+ &s_basemarker6,
+ &s_basemarker7,
+ &s_basemarker8,
+ &s_pathdisk,
+ &s_elevdisk,
+ &s_megaremove,
+ /*&s_rain7,
+ &s_rain6,
+ &s_rain5,
+ &s_rain4,
+ &s_rain3,
+ &s_rain2,
+ &s_rain1,
+ &s_rainmaster,*/
+ &s_respawn8,
+ &s_respawn7,
+ &s_respawn6,
+ &s_respawn5,
+ &s_respawn4,
+ &s_respawn3,
+ &s_respawn2,
+ &s_respawn1,
+ &s_blooddrip1,
+ &s_blooddrip2,
+ &s_blooddrip3,
+ &s_blooddrip4,
+ &s_diskmaster,
+ &s_bstar4,
+ &s_bstar3,
+ &s_bstar2,
+ &s_bstar1,
+
+
+
+#if (SHAREWARE == 0)
+ &s_scottwander7,
+ &s_scottwander6,
+ &s_scottwander5,
+ &s_scottwander4,
+ &s_scottwander3,
+ &s_scottwander2,
+ &s_scottwander1,
+ &s_scottwanderdoor7,
+ &s_scottwanderdoor6,
+ &s_scottwanderdoor5,
+ &s_scottwanderdoor4,
+ &s_scottwanderdoor3,
+ &s_scottwanderdoor2,
+ &s_scottwanderdoor1,
+
+
+ &s_opstand,
+ &s_oppath4 ,
+ &s_oppath3 ,
+ &s_oppath2 ,
+ &s_oppath1 ,
+ &s_opcollide,
+ &s_opcollide2,
+ &s_opshoot4 ,
+ &s_opshoot3 ,
+ &s_opshoot2 ,
+ &s_opshoot1 ,
+ &s_opbolo5,
+ &s_opbolo4,
+ &s_opbolo3,
+ &s_opbolo2,
+ &s_opbolo1,
+ &s_bolocast4,
+ &s_bolocast3,
+ &s_bolocast2,
+ &s_bolocast1,
+ &s_opchase4 ,
+ &s_opchase3 ,
+ &s_opchase2 ,
+ &s_opchase1 ,
+ &s_opdead ,
+ &s_opdie5 ,
+ &s_opdie4 ,
+ &s_opdie3 ,
+ &s_opdie2 ,
+ &s_opdie1 ,
+ &s_opcrushed2 ,
+ &s_opcrushed1 ,
+
+
+
+ &s_dmonkstand,
+ &s_dmonkpath4 ,
+ &s_dmonkpath3 ,
+ &s_dmonkpath2 ,
+ &s_dmonkpath1 ,
+ &s_dmonkcollide,
+ &s_dmonkcollide2,
+ &s_dmonkshoot6,
+ &s_dmonkshoot5,
+ &s_dmonkshoot4,
+ &s_dmonkshoot3,
+ &s_dmonkshoot2,
+ &s_dmonkshoot1,
+ &s_dmonkchase4 ,
+ &s_dmonkchase3 ,
+ &s_dmonkchase2 ,
+ &s_dmonkchase1 ,
+ &s_dmonkdead ,
+ &s_dmonkdie4 ,
+ &s_dmonkdie3 ,
+ &s_dmonkdie2 ,
+ &s_dmonkdie1 ,
+ &s_dmonkcrushed2 ,
+ &s_dmonkcrushed1 ,
+ &s_firemonkstand ,
+ &s_firemonkpath4 ,
+ &s_firemonkpath3 ,
+ &s_firemonkpath2 ,
+ &s_firemonkpath1 ,
+ &s_firemonkcollide,
+ &s_firemonkcollide2,
+ &s_firemonkcast7,
+ &s_firemonkcast6,
+ &s_firemonkcast5,
+ &s_firemonkcast4,
+ &s_firemonkcast3,
+ &s_firemonkcast2,
+ &s_firemonkcast1,
+ &s_monkfire4,
+ &s_monkfire3,
+ &s_monkfire2,
+ &s_monkfire1,
+ &s_fireballhit3,
+ &s_fireballhit2,
+ &s_fireballhit1,
+ &s_firemonkchase4 ,
+ &s_firemonkchase3 ,
+ &s_firemonkchase2 ,
+ &s_firemonkchase1 ,
+ &s_firemonkdead7 ,
+ &s_firemonkdead6 ,
+ &s_firemonkdead5 ,
+ &s_firemonkdead4 ,
+ &s_firemonkdead3 ,
+ &s_firemonkdead2 ,
+ &s_firemonkdead ,
+ &s_firemonkdie4 ,
+ &s_firemonkdie3 ,
+ &s_firemonkdie2 ,
+ &s_firemonkdie1 ,
+ &s_firemonkcrushed2 ,
+ &s_firemonkcrushed1 ,
+
+
+ &s_wallstand,
+ &s_wallpath,
+ &s_wallshoot,
+ &s_wallcollide,
+ &s_wallalign,
+ &s_wallrestore,
+ &s_wallwait,
+
+
+
+
+ &s_darianstand,
+ &s_darianchase4 ,
+ &s_darianchase3 ,
+ &s_darianchase2 ,
+ &s_darianchase1 ,
+ &s_darianrise8,
+ &s_darianrise7,
+ &s_darianrise6,
+ &s_darianrise5,
+ &s_darianrise4,
+ &s_darianrise3,
+ &s_darianrise2,
+ &s_darianrise1,
+ &s_dariansink9,
+ &s_dariansink8,
+ &s_dariansink7,
+ &s_dariansink6,
+ &s_dariansink5,
+ &s_dariansink4,
+ &s_dariansink3,
+ &s_dariansink2,
+ &s_dariansink1,
+ &s_dariancollide,
+ &s_dariancollide2,
+ &s_darianshoot4,
+ &s_darianshoot3,
+ &s_darianshoot2,
+ &s_darianshoot1,
+ &s_dariandefend3,
+ &s_dariandefend2,
+ &s_dariandefend1,
+ &s_darianuse4,
+ &s_darianuse3,
+ &s_darianuse2,
+ &s_darianuse1,
+ &s_darianwait,
+ &s_darianspears,
+ &s_dspear16,
+ &s_dspear15,
+ &s_dspear14,
+ &s_dspear13,
+ &s_dspear12,
+ &s_dspear11,
+ &s_dspear10,
+ &s_dspear9,
+ &s_dspear8,
+ &s_dspear7,
+ &s_dspear6,
+ &s_dspear5,
+ &s_dspear4,
+ &s_dspear3,
+ &s_dspear2,
+ &s_dspear1,
+ &s_dariandead2 ,
+ &s_dariandead1 ,
+ &s_dariandead ,
+ &s_dariandie10,
+ &s_dariandie9 ,
+ &s_dariandie8 ,
+ &s_dariandie7 ,
+ &s_dariandie6 ,
+ &s_dariandie5 ,
+ &s_dariandie4 ,
+ &s_dariandie3 ,
+ &s_dariandie2 ,
+ &s_dariandie1 ,
+ &s_heinrichstand ,
+ &s_heinrichchase ,
+ &s_kristleft,
+ &s_kristright,
+ &s_heinrichshoot11,
+ &s_heinrichshoot10,
+ &s_heinrichshoot9,
+ &s_heinrichshoot8,
+ &s_heinrichshoot7,
+ &s_heinrichshoot6,
+ &s_heinrichshoot5,
+ &s_heinrichshoot4,
+ &s_heinrichshoot3,
+ &s_heinrichshoot2,
+ &s_heinrichshoot1,
+ &s_missile1,
+ &s_missilehit3,
+ &s_missilehit2,
+ &s_missilehit1,
+ &s_mine4,
+ &s_mine3,
+ &s_mine2,
+ &s_mine1,
+ &s_heinrichdefend,
+ &s_heinrichooc,
+ &s_heinrichdead ,
+ &s_heinrichdie2 ,
+ &s_heinrichdie1 ,
+ &s_heindead2,
+ &s_heindead1,
+ &s_heinexp13,
+ &s_heinexp12,
+ &s_heinexp11,
+ &s_heinexp10,
+ &s_heinexp9,
+ &s_heinexp8,
+ &s_heinexp7,
+ &s_heinexp6,
+ &s_heinexp5,
+ &s_heinexp4,
+ &s_heinexp3,
+ &s_heinexp2,
+ &s_heinexp1,
+ &s_darkmonkstand ,
+ &s_darkmonkland ,
+ &s_darkmonkchase2 ,
+ &s_darkmonkchase1 ,
+ &s_dmlandandfire,
+ &s_darkmonkcover3 ,
+ &s_darkmonkcover2 ,
+ &s_darkmonkcover1 ,
+ &s_darkmonkawaken5 ,
+ &s_darkmonkawaken4 ,
+ &s_darkmonkawaken3 ,
+ &s_darkmonkawaken2 ,
+ &s_darkmonkawaken1 ,
+ &s_darkmonklightning11 ,
+ &s_darkmonklightning10 ,
+ &s_darkmonklightning9 ,
+ &s_darkmonklightning8 ,
+ &s_darkmonklightning7 ,
+ &s_darkmonklightning6 ,
+ &s_darkmonklightning5 ,
+ &s_darkmonklightning4 ,
+ &s_darkmonklightning3 ,
+ &s_darkmonklightning2 ,
+ &s_darkmonklightning1 ,
+ &s_darkmonkfspark6 ,
+ &s_darkmonkfspark5 ,
+ &s_darkmonkfspark4 ,
+ &s_darkmonkfspark3 ,
+ &s_darkmonkfspark2 ,
+ &s_darkmonkfspark1 ,
+ &s_darkmonkbreathe8 ,
+ &s_darkmonkbreathe7 ,
+ &s_darkmonkbreathe6 ,
+ &s_darkmonkbreathe5 ,
+ &s_darkmonkbreathe4 ,
+ &s_darkmonkbreathe3 ,
+ &s_darkmonkbreathe2 ,
+ &s_darkmonkbreathe1 ,
+ &s_darkmonksummon3 ,
+ &s_darkmonksummon2 ,
+ &s_darkmonksummon1 ,
+ &s_snakepath,
+ &s_snakefindpath,
+ &s_darkmonkhead ,
+ &s_darkmonksnakelink ,
+ &s_darkmonkhspawn,
+ &s_darkmonkfastspawn,
+ &s_darkmonkheaddead ,
+ &s_darkmonkheaddie1 ,
+ &s_darkmonkhball9 ,
+ &s_darkmonkhball8 ,
+ &s_darkmonkhball7,
+ &s_darkmonkhball6 ,
+ &s_darkmonkhball5 ,
+ &s_darkmonkhball4 ,
+ &s_darkmonkhball3 ,
+ &s_darkmonkhball2,
+ &s_darkmonkhball1,
+ &s_darkmonkabsorb9 ,
+ &s_darkmonkabsorb8 ,
+ &s_darkmonkabsorb7,
+ &s_darkmonkabsorb6 ,
+ &s_darkmonkabsorb5 ,
+ &s_darkmonkabsorb4 ,
+ &s_darkmonkabsorb3 ,
+ &s_darkmonkabsorb2,
+ &s_darkmonkabsorb1,
+ &s_darkmonksphere10,
+ &s_darkmonksphere9,
+ &s_darkmonksphere8,
+ &s_darkmonksphere7,
+ &s_darkmonksphere6,
+ &s_darkmonksphere5,
+ &s_darkmonksphere4,
+ &s_darkmonksphere3,
+ &s_darkmonksphere2,
+ &s_darkmonksphere1,
+ &s_dmgreenthing10,
+ &s_dmgreenthing9,
+ &s_dmgreenthing8,
+ &s_dmgreenthing7,
+ &s_dmgreenthing6,
+ &s_dmgreenthing5,
+ &s_dmgreenthing4,
+ &s_dmgreenthing3,
+ &s_dmgreenthing2,
+ &s_dmgreenthing1,
+ &s_energysphere4,
+ &s_energysphere3,
+ &s_energysphere2,
+ &s_energysphere1,
+ &s_lightning,
+ &s_handball2,
+ &s_handball1,
+ &s_faceball2,
+ &s_faceball1,
+ &s_floorspark4,
+ &s_floorspark3,
+ &s_floorspark2,
+ &s_floorspark1,
+ &s_darkmonkreact,
+ &s_darkmonkbball9 ,
+ &s_darkmonkbball8 ,
+ &s_darkmonkbball7,
+ &s_darkmonkbball6 ,
+ &s_darkmonkbball5 ,
+ &s_darkmonkbball4 ,
+ &s_darkmonkbball3 ,
+ &s_darkmonkbball2,
+ &s_darkmonkbball1,
+ &s_darkmonkcharge10,
+ &s_darkmonkcharge9 ,
+ &s_darkmonkcharge8 ,
+ &s_darkmonkcharge7 ,
+ &s_darkmonkcharge6 ,
+ &s_darkmonkcharge5 ,
+ &s_darkmonkcharge4 ,
+ &s_darkmonkcharge3 ,
+ &s_darkmonkcharge2 ,
+ &s_darkmonkcharge1 ,
+ &s_darkmonkscare5 ,
+ &s_darkmonkscare4 ,
+ &s_darkmonkscare3 ,
+ &s_darkmonkscare2,
+ &s_darkmonkscare1,
+ &s_darkmonkdead,
+ &s_darkmonkdie7,
+ &s_darkmonkdie6,
+ &s_darkmonkdie5,
+ &s_darkmonkdie4,
+ &s_darkmonkdie3,
+ &s_darkmonkdie2,
+ &s_darkmonkdie1,
+ &s_darkmonkredhead,
+ &s_darkmonkredlink,
+ &s_redheadhit,
+ &s_redlinkhit,
+ &s_spithit4,
+ &s_spithit3,
+ &s_spithit2,
+ &s_spithit1,
+ &s_spit4,
+ &s_spit3,
+ &s_spit2,
+ &s_spit1,
+ &s_snakefire2,
+ &s_snakefire1,
+ &s_snakefireworks1,
+ &s_snakefireworks2,
+
+ &s_dexplosion22,
+ &s_dexplosion21,
+ &s_dexplosion20,
+ &s_dexplosion19,
+ &s_dexplosion18,
+ &s_dexplosion17,
+ &s_dexplosion16,
+ &s_dexplosion15,
+ &s_dexplosion14,
+ &s_dexplosion13,
+ &s_dexplosion12,
+ &s_dexplosion11,
+ &s_dexplosion10,
+ &s_dexplosion9,
+ &s_dexplosion8,
+ &s_dexplosion7,
+ &s_dexplosion6,
+ &s_dexplosion5,
+ &s_dexplosion4,
+ &s_dexplosion3,
+ &s_dexplosion2,
+ &s_dexplosion1,
+ &s_NMEhead1,
+ &s_NMEhead2,
+ &s_NMEchase,
+ &s_NMEwheels1,
+ &s_NMEwheels2,
+ &s_NMEwheels3,
+ &s_NMEwheels4,
+ &s_NMEwheels5,
+ &s_NMEspinattack,
+ &s_NMEwheelspin,
+ &s_NMEminiball4,
+ &s_NMEminiball3,
+ &s_NMEminiball2,
+ &s_NMEminiball1,
+ &s_NMEsaucer4,
+ &s_NMEsaucer3,
+ &s_NMEsaucer2,
+ &s_NMEsaucer1,
+ &s_NMEdie,
+ &s_NMEattack,
+ &s_NMEhead1rl,
+ &s_NMEhead2rl,
+ &s_NMEwindup,
+ &s_NMEwheels120,
+ &s_NMEwrotleft3,
+ &s_NMEwrotleft2,
+ &s_NMEwrotleft1,
+ &s_NMEwrotright3,
+ &s_NMEwrotright2,
+ &s_NMEwrotright1,
+ &s_NMEdeathbuildup,
+ &s_NMEheadexplosion,
+ &s_NMEstand,
+ &s_NMEspinfire,
+ &s_oshuriken4,
+ &s_oshuriken3,
+ &s_oshuriken2,
+ &s_oshuriken1,
+ &s_oshurikenhit3,
+ &s_oshurikenhit2,
+ &s_oshurikenhit1,
+ &s_shootinghead,
+
+
+ &s_speardown16,
+ &s_speardown15,
+ &s_speardown14,
+ &s_speardown13,
+ &s_speardown12,
+ &s_speardown11,
+ &s_speardown10,
+ &s_speardown9,
+ &s_speardown8,
+ &s_speardown7,
+ &s_speardown6,
+ &s_speardown5,
+ &s_speardown4,
+ &s_speardown3,
+ &s_speardown2,
+ &s_speardown1,
+
+
+ &s_downblade16,
+ &s_downblade15,
+ &s_downblade14,
+ &s_downblade13,
+ &s_downblade12,
+ &s_downblade11,
+ &s_downblade10,
+ &s_downblade9,
+ &s_downblade8,
+ &s_downblade7,
+ &s_downblade6,
+ &s_downblade5,
+ &s_downblade4,
+ &s_downblade3,
+ &s_downblade2,
+ &s_downblade1,
+
+ &s_firejetdown23,
+ &s_firejetdown22,
+ &s_firejetdown21,
+ &s_firejetdown20,
+ &s_firejetdown19,
+ &s_firejetdown18,
+ &s_firejetdown17,
+ &s_firejetdown16,
+ &s_firejetdown15,
+ &s_firejetdown14,
+ &s_firejetdown13,
+ &s_firejetdown12,
+ &s_firejetdown11,
+ &s_firejetdown10,
+ &s_firejetdown9,
+ &s_firejetdown8,
+ &s_firejetdown7,
+ &s_firejetdown6,
+ &s_firejetdown5,
+ &s_firejetdown4,
+ &s_firejetdown3,
+ &s_firejetdown2,
+ &s_firejetdown1,
+
+ &s_columnupdown6,
+ &s_columnupdown5,
+ &s_columnupdown4,
+ &s_columnupdown3,
+ &s_columnupdown2,
+ &s_columnupdown1,
+ &s_columnupup8,
+ &s_columnupup7,
+ &s_columnupup6,
+ &s_columnupup5,
+ &s_columnupup4,
+ &s_columnupup3,
+ &s_columnupup2,
+ &s_columnupup1,
+
+
+ &s_spinupblade16,
+ &s_spinupblade15,
+ &s_spinupblade14,
+ &s_spinupblade13,
+ &s_spinupblade12,
+ &s_spinupblade11,
+ &s_spinupblade10,
+ &s_spinupblade9,
+ &s_spinupblade8,
+ &s_spinupblade7,
+ &s_spinupblade6,
+ &s_spinupblade5,
+ &s_spinupblade4,
+ &s_spinupblade3,
+ &s_spinupblade2,
+ &s_spinupblade1,
+
+
+ &s_spindownblade16,
+ &s_spindownblade15,
+ &s_spindownblade14,
+ &s_spindownblade13,
+ &s_spindownblade12,
+ &s_spindownblade11,
+ &s_spindownblade10,
+ &s_spindownblade9,
+ &s_spindownblade8,
+ &s_spindownblade7,
+ &s_spindownblade6,
+ &s_spindownblade5,
+ &s_spindownblade4,
+ &s_spindownblade3,
+ &s_spindownblade2,
+ &s_spindownblade1,
+
+
+ &s_bouldersink9,
+ &s_bouldersink8,
+ &s_bouldersink7,
+ &s_bouldersink6,
+ &s_bouldersink5,
+ &s_bouldersink4,
+ &s_bouldersink3,
+ &s_bouldersink2,
+ &s_bouldersink1,
+ &s_boulderroll8,
+ &s_boulderroll7,
+ &s_boulderroll6,
+ &s_boulderroll5,
+ &s_boulderroll4,
+ &s_boulderroll3,
+ &s_boulderroll2,
+ &s_boulderroll1,
+ &s_boulderdrop12,
+ &s_boulderdrop11,
+ &s_boulderdrop10,
+ &s_boulderdrop9,
+ &s_boulderdrop8,
+ &s_boulderdrop7,
+ &s_boulderdrop6,
+ &s_boulderdrop5,
+ &s_boulderdrop4,
+ &s_boulderdrop3,
+ &s_boulderdrop2,
+ &s_boulderdrop1,
+ &s_boulderspawn,
+
+
+ &s_gunfire2,
+ &s_gunfire1,
+ &s_gunstand,
+ &s_gunraise4,
+ &s_gunraise3,
+ &s_gunraise2,
+ &s_gunraise1,
+ &s_gunlower3,
+ &s_gunlower2,
+ &s_gunlower1,
+ &s_gundead,
+ &s_gundie1,
+ &s_4waygunfire1,
+ &s_4waygunfire2,
+ &s_4waygun,
+
+
+
+ &s_kessphere8,
+ &s_kessphere7,
+ &s_kessphere6,
+ &s_kessphere5,
+ &s_kessphere4,
+ &s_kessphere3,
+ &s_kessphere2,
+ &s_kessphere1,
+
+
+ &s_slop1,
+ &s_slop2,
+ &s_slop3,
+ &s_slop4,
+
+ &s_batblast1,
+ &s_batblast2,
+ &s_batblast3,
+ &s_batblast4,
+
+ &s_serialdog4,
+ &s_serialdog3,
+ &s_serialdog2,
+ &s_serialdog,
+ &s_serialdogattack,
+ &s_doguse,
+ &s_doglick,
+ &s_dogwait,
+
+
+
+
+#endif //SHAREWARE
+
+};
+#endif
--- /dev/null
+++ b/rott/rt_ted.c
@@ -1,0 +1,7089 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// make sure word alignment is OFF!
+
+#include "rt_def.h"
+#include "rt_sound.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#ifdef DOS
+#include <io.h>
+#include <conio.h>
+#include <dos.h>
+#else
+#include <errno.h>
+#endif
+
+#include "states.h"
+#include "watcom.h"
+#include "rt_ted.h"
+#include "_rt_ted.h"
+#include "w_wad.h"
+#include "z_zone.h"
+#include "rt_util.h"
+#include "lumpy.h"
+#include "rt_vid.h"
+#include "rt_actor.h"
+#include "rt_stat.h"
+#include "rt_menu.h"
+#include "rt_draw.h"
+#include "rt_com.h"
+#include "rt_main.h"
+#include "rt_door.h"
+#include "rt_playr.h"
+#include "rt_view.h"
+#include "rt_str.h"
+#include "isr.h"
+#include "rt_floor.h"
+#include "rt_game.h"
+#include "rt_rand.h"
+#include "rt_cfg.h"
+#include "develop.h"
+#include "modexlib.h"
+#include "engine.h"
+#include "rt_debug.h"
+#include "rt_scale.h"
+#include "rt_net.h"
+//MED
+#include "memcheck.h"
+
+
+
+
+//========================================
+// GLOBAL VARIABLES
+//========================================
+
+extern boolean UseBaseMarker;
+
+teamtype TEAM[MAXPLAYERS];
+int numareatiles[NUMAREAS+1];
+int shapestart,shapestop;
+_2dvec SPAWNLOC[MAXSPAWNLOCATIONS],FIRST,SECOND;
+int NUMSPAWNLOCATIONS,numteams=0;
+wall_t walls[MAXWALLTILES];
+str_clock Clocks[MAXCLOCKS];
+int numclocks;
+int LightsInArea[NUMAREAS+1];
+
+int maxheight;
+int nominalheight;
+int elevatorstart;
+int gunsstart;
+int fog;
+int lightsource;
+int SNAKELEVEL;
+int whichpath;
+
+word *mapplanes[3];
+int mapwidth;
+int mapheight;
+int lastlevelloaded=-1;
+
+boolean insetupgame;
+boolean ISRTL = false;
+
+unsigned MapSpecials = 0;
+
+char LevelName[80];
+
+//========================================
+// LOCAL VARIABLES
+//========================================
+
+static cachetype * cachelist;
+static word cacheindex;
+static boolean CachingStarted=false;
+static char * ROTTMAPS = STANDARDGAMELEVELS;
+char * BATTMAPS;
+
+static char NormalWeaponTiles[ 10 ] =
+{
+ 46, 48, 49, 50, 51, 52, 53, 54, 55, 56
+};
+static char SharewareWeaponTiles[ 7 ] =
+{
+ 48, 49, 50, 51, 52, 53, 54
+};
+
+static char CacheStrings[MAXSILLYSTRINGS][80]=
+{
+ {"Ready yourself\nfor destruction!\0\0"},
+ {"Here comes the enemy!\0\0"},
+ {"Hope you wrote\nyour will!\0\0"},
+ {"Did you bring your\nextra bullets?\0\0"},
+ {"Try not to bleed\non the rug.\0\0"},
+ {"Let's see...bandages,\ntape, splints,...\0\0"},
+ {"Couldn't we just\ntalk this over?\0\0"},
+ {"Cache as cache can...\0\0"},
+ {"You are smart.\nMake us strong.\0\0"},
+ {"Bleh!\0\0"},
+ {"I am as far\nabove you...\0\0"},
+ {"Just keep thinkin':\nBut it's loadin' COOL\nstuff...\0\0"},
+ {"Guess which line\nwill win!\0\0"},
+ {"Oh, no. Not again.\0\0"},
+ {"Wait! I'm not ready!\nToo late.\0\0"},
+ {"Hope this doesn't\ncrash.\0\0"},
+ {"Have a sandwich.\0\0"},
+ {"Smoke 'em if\nya got 'em...and\nif ya like cancer.\0\0"},
+ {"Ummmmm...\0\0"},
+ {"Bang! Bang! Bang!\nFreeze!\0\0"},
+ {"You have the right\nto...DIE.\0\0"},
+ {"Insert funny phrase\nhere.\0\0"},
+ {"Blood, bullets,\nnicely decorated\nhallways.\0\0"},
+ {"You are to be killed,\nnot hurt.\0\0"},
+ {"It's time for you to\ngo down the stairs!\0\0"},
+ {"This game, like,\nrules and stuff.\0\0"},
+ {"We get money for this!\nHa ha ha ha!\0\0"},
+ {"Let's not start any\nreligious wars...\0\0"},
+ {"I don't wanna start\nno ting...\0\0"},
+ {"Ah, another sacrifice!\0\0"},
+ {"If you were dead,\nyou'd be the\nsame thing.\0\0"},
+ {"This Game isn't\nhuman; it can't\nbe reasoned with!\0\0"}
+};
+
+void SetupGameLevel (void);
+void ScanInfoPlane(void);
+
+void DrawPreCache( void );
+void InitializePlayerstates(void);
+void SetupSnakePath(void);
+void SetupRandomActors(void);
+void SetupActors(void);
+void SetupStatics(void);
+void LoftSprites( void );
+int GetLumpForTile(int tile);
+
+//========================================
+
+/*
+======================
+=
+= SortPreCache
+= Sort the Precache for cachelevel precedence using a HEAPSORT
+=
+======================
+*/
+#define SGN(x) ((x>0) ? (1) : ((x==0) ? (0) : (-1)))
+
+/*--------------------------------------------------------------------------*/
+int CompareTags(s1p,s2p) cachetype *s1p,*s2p;
+{
+// Sort according to lump
+ if (DoPanicMapping()==true)
+ return SGN(s1p->cachelevel-s2p->cachelevel);
+// Sort according to cachelevel
+ else
+ return SGN(s1p->lump-s2p->lump);
+}
+
+void SwitchCacheEntries(s1p,s2p) cachetype *s1p,*s2p;
+{
+ cachetype temp;
+
+ temp=*s1p;
+ *s1p=*s2p;
+ *s2p=temp;
+}
+
+
+
+void SortPreCache( void )
+{
+ hsort((char *)cachelist,cacheindex,sizeof(cachetype),&CompareTags,&SwitchCacheEntries);
+}
+
+//========================================
+
+
+/*
+======================
+=
+= SetupPreCache
+= Setup the cache for pre-cacheing
+=
+======================
+*/
+void SetupPreCache( void )
+{
+
+ CachingStarted=true;
+ cacheindex=0;
+ cachelist=(cachetype *)SafeMalloc(MAXPRECACHE*(sizeof(cachetype)));
+ DrawPreCache();
+}
+
+
+/*
+======================
+=
+= ShutdownPreCache
+= Setup the cache for pre-cacheing
+=
+======================
+*/
+void ShutdownPreCache( void )
+{
+
+ CachingStarted=false;
+ SafeFree((byte *)cachelist);
+}
+
+
+/*
+======================
+=
+= PreCacheLump
+= precache the lump and check to see if it is already tagged
+=
+======================
+*/
+void PreCacheLump( int lump, int level, int type ) // added type
+{
+ int i;
+
+ if (CachingStarted==false)
+ return;
+ if (!W_LumpLength(lump))
+ {
+#if (PRECACHETEST == 1)
+ SoftError("Tried to precache a label, lump = %ld tag=%ld maskednum=%ld\n",lump, level, maskednum);
+#endif
+ return;
+ }
+ for (i=1; i<cacheindex; i++)
+ if (cachelist[i].lump==lump)
+ return;
+ cachelist[cacheindex].lump=lump;
+ cachelist[cacheindex].cachelevel=level;
+ cachelist[cacheindex++].type=type;
+ if (cacheindex==MAXPRECACHE)
+ Error("MaxPreCache reached\n");
+}
+
+
+
+/*
+======================
+=
+= PreCacheGroup
+= precache the lump and check to see if it is already tagged
+=
+======================
+*/
+void PreCacheGroup( int start, int end, int type ) // added type
+{
+ int i;
+ int j;
+ int k;
+ int found;
+
+ if (CachingStarted==false)
+ return;
+ k=cacheindex;
+ for (j=start; j<=end; j++)
+ {
+ if (!W_LumpLength(j))
+ {
+#if (PRECACHETEST == 1)
+ SoftError("Tried to precache a label, lump = %ld\n",j);
+#endif
+ continue;
+ }
+ found=0;
+ for (i=1; i<k; i++)
+ if (cachelist[i].lump==j)
+ {
+ found=1;
+ break;
+ }
+ if (found==0)
+ {
+ cachelist[cacheindex].lump=j;
+ cachelist[cacheindex].cachelevel=PU_CACHEACTORS;
+ cachelist[cacheindex++].type=type;
+
+ if (cacheindex==MAXPRECACHE)
+ Error("MaxPreCache reached\n");
+ }
+ }
+
+}
+
+
+/*
+======================
+=
+= PreCachePlayers
+= precache the lump and check to see if it is already tagged
+=
+======================
+*/
+void PreCachePlayers(void )
+{
+ int start;
+ int end;
+ int i;
+ playertype*pstate;
+
+ for(i=0; i<numplayers; i++)
+ { if (i!=consoleplayer) // don't cache consoleplayer
+ { pstate = &PLAYERSTATE[i];
+ start=W_GetNumForName("CASSHO11")+(pstate->player*REMOTEOFFSET);
+ end =W_GetNumForName("CASWDEAD")+(pstate->player*REMOTEOFFSET);
+ PreCacheGroup(start,end,cache_patch_t);
+ }
+ }
+}
+
+
+
+
+void PreCachePlayerSound(void)
+{
+ switch (locplayerstate->player)
+ {
+ case 0:
+ SD_PreCacheSound(SD_PLAYERTCSND);
+
+ break;
+ case 1:
+ SD_PreCacheSound(SD_PLAYERTBSND);
+
+ break;
+ case 2:
+ SD_PreCacheSound(SD_PLAYERDWSND);
+
+ break;
+ case 3:
+ SD_PreCacheSound(SD_PLAYERLNSND);
+
+ break;
+ case 4:
+ SD_PreCacheSound(SD_PLAYERIPFSND);
+ break;
+ }
+}
+
+
+#define IS_ALTERNATE_ACTOR(ob) \
+ ((ob->shapeoffset - deathshapeoffset[ob->obclass]) > 0)\
+
+/*
+======================
+=
+= PreCacheActor
+= precache the lump and check to see if it is already tagged
+=
+======================
+*/
+void PreCacheActor( int actor, int which )
+{
+ int start;
+ int end;
+
+ switch (actor)
+ {
+ case lowguardobj:
+ if (IS_ALTERNATE_ACTOR(new))
+ {
+ start = SD_LOWGUARD2SEESND;
+ end = SD_LOWGUARD2SEE3SND;
+ SD_PreCacheSoundGroup(start,end);
+
+ start = SD_LOWGUARD2DIESND;
+ end = SD_LOWGUARD2DIESND;
+ SD_PreCacheSoundGroup(start,end);
+
+ start = SD_LOWGUARDFIRESND;
+ end = SD_SNEAKYSPRINGFSND;
+ SD_PreCacheSoundGroup(start,end);
+
+ start=W_GetNumForName("MARSHOO1");
+ end =W_GetNumForName("MNGRISE4");
+ //end =W_GetNumForName("MARUSE28");
+ }
+
+ else
+ { start = SD_LOWGUARD1SEESND;
+ end = SD_LOWGUARD1SEE3SND;
+ SD_PreCacheSoundGroup(start,end);
+
+ start = SD_LOWGUARD1DIESND;
+ end = SD_LOWGUARD1DIESND;
+ SD_PreCacheSoundGroup(start,end);
+
+ start = SD_LOWGUARDFIRESND;
+ end = SD_SNEAKYSPRINGFSND;
+ SD_PreCacheSoundGroup(start,end);
+
+ start=W_GetNumForName("LWGSHOO1");
+ end = W_GetNumForName("SNGRISE4");
+ //end =W_GetNumForName("LOWUSE28");
+ }
+
+ break;
+ case highguardobj:
+
+ start = SD_HIGHGUARD1SEESND;
+ end = SD_HIGHGUARDDIESND;
+ SD_PreCacheSoundGroup(start,end);
+
+ if (IS_ALTERNATE_ACTOR(new))
+ {
+ start=W_GetNumForName("HIGSHOO1");
+ end =W_GetNumForName("HIGWDEAD");
+ //end =W_GetNumForName("HIHUSE28");
+ }
+ else
+ {
+ start=W_GetNumForName("HG2SHOO1");
+ end =W_GetNumForName("HG2WDEAD");
+ //end =W_GetNumForName("H2HUSE28");
+ }
+ break;
+
+ case overpatrolobj:
+
+ start=W_GetNumForName("OBBOLO1");
+ end =W_GetNumForName("OBBOLO4");
+ PreCacheGroup(start,end,cache_patch_t);
+ start=W_GetNumForName("NET1");
+ end =W_GetNumForName("NET4");
+ PreCacheGroup(start,end,cache_patch_t);
+
+ start = SD_OVERP1SEESND;
+ end = SD_OVERPDIESND;
+ SD_PreCacheSoundGroup(start,end);
+ SD_PreCacheSoundGroup(SD_NETWIGGLESND,SD_NETFALLSND);
+
+ if (IS_ALTERNATE_ACTOR(new))
+ {
+ start=W_GetNumForName("PATSHOO1");
+ end =W_GetNumForName("PATDEAD");
+
+ //end =W_GetNumForName("OBPUSE28");
+ }
+
+ else
+ {
+ start=W_GetNumForName("OBPSHOO1");
+ end =W_GetNumForName("OBPDEAD");
+
+ //end =W_GetNumForName("PATUSE28");
+ }
+
+ break;
+ case strikeguardobj:
+
+
+ start = SD_STRIKE1SEESND;
+ end = SD_STRIKEDIESND;
+ SD_PreCacheSoundGroup(start,end);
+
+ if (IS_ALTERNATE_ACTOR(new))
+ {
+ start=W_GetNumForName("XYGSHOO1");
+ end =W_GetNumForName("XYLROLL6");
+ //end =W_GetNumForName("XYUSE28");
+ }
+
+ else
+ {
+ start=W_GetNumForName("ANGSHOO1");
+ end =W_GetNumForName("ANLROLL6");
+ //end =W_GetNumForName("ANUSE28");
+ }
+
+ break;
+
+ case blitzguardobj:
+
+ start = SD_BLITZ1SEESND;
+ end = SD_BLITZDIESND;
+ SD_PreCacheSoundGroup(start,end);
+
+ if (IS_ALTERNATE_ACTOR(new))
+ {
+ start=W_GetNumForName("WIGSHOO1");
+ end =W_GetNumForName("WIHUSE28");
+ }
+
+ else
+ {
+ start=W_GetNumForName("LIGSHOO1");
+ end =W_GetNumForName("LIPEAD11");
+ }
+
+ break;
+
+ case triadenforcerobj:
+
+ start = SD_ENFORCERSEESND;
+ end = SD_ENFORCERDIESND;
+ SD_PreCacheSoundGroup(start,end);
+
+ start=W_GetNumForName("TEGREN1");
+ end =W_GetNumForName("TGRENF6");
+ PreCacheGroup(start,end,cache_patch_t);
+ start=W_GetNumForName("TRISHOO1");
+ end =W_GetNumForName("TRIWDEAD");
+ //end =W_GetNumForName("TRIUSE28");
+ break;
+ case deathmonkobj:
+
+
+ start = SD_MONKSEESND;
+ end = SD_MONKDIESND;
+ SD_PreCacheSoundGroup(start,end);
+
+ start=W_GetNumForName("MONKDR1");
+ end =W_GetNumForName("MONDEAD");
+ //end =W_GetNumForName("MONUSE28");
+ break;
+
+
+ case dfiremonkobj:
+
+ start = SD_FIREMONKSEESND;
+ end = SD_FIREMONKDIESND;
+ SD_PreCacheSoundGroup(start,end);
+
+ start = W_GetNumForName("MONFIRE1");
+ end = W_GetNumForName("MONFIRE4");
+ PreCacheGroup(start,end,cache_patch_t);
+
+
+ if (IS_ALTERNATE_ACTOR(new))
+ {
+ start=W_GetNumForName("MRKKSH1");
+ end =W_GetNumForName("MRKDEAD7");
+ }
+
+ else
+ {
+ start=W_GetNumForName("ALLKSH1");
+ end =W_GetNumForName("ALLDEAD7");
+ }
+
+ break;
+
+ case roboguardobj:
+
+ start = SD_ROBOTSEESND;
+ end = SD_ROBOTDIESND;
+ SD_PreCacheSoundGroup(start,end);
+ start=W_GetNumForName("ROBOGRD1");
+ end =W_GetNumForName("ROBGRD16");
+ break;
+
+ case b_darianobj:
+
+ PreCachePlayerSound();
+
+ start = SD_DARIANSEESND;
+ end = SD_DARIANSAY3;
+ SD_PreCacheSoundGroup(start,end);
+
+
+ start=W_GetNumForName("DARSHOO1");
+ end =W_GetNumForName("DARUSE28");
+ break;
+
+
+ case b_heinrichobj:
+
+ PreCachePlayerSound();
+
+ start = SD_KRISTSEESND;
+ end = SD_KRISTSAY3;
+ SD_PreCacheSoundGroup(start,end);
+
+ start=W_GetNumForName("MINE1");
+ end =W_GetNumForName("MINE4");
+ PreCacheGroup(start,end,cache_patch_t);
+ start=W_GetNumForName("HSIT1");
+ end =W_GetNumForName("HDOPE8");
+ break;
+
+ case b_darkmonkobj:
+
+ start = SD_DARKMONKSEESND;
+ end = SD_DARKMONKSAY3;
+ SD_PreCacheSoundGroup(start,end);
+
+ start=W_GetNumForName("LIGNING1");
+ end =W_GetNumForName("FSPARK4");
+ PreCacheGroup(start,end,cache_patch_t);
+ start=W_GetNumForName("TOMS1");
+ end =W_GetNumForName("TOHRH8");
+ break;
+
+ case b_darksnakeobj:
+
+ PreCachePlayerSound();
+
+ start = SD_SNAKESEESND;
+ end = SD_SNAKESAY3;
+ SD_PreCacheSoundGroup(start,end);
+
+ start=W_GetNumForName("TOMRH1");
+ end =W_GetNumForName("TOHRH8");
+ case b_robobossobj:
+
+ PreCachePlayerSound();
+
+ start = SD_NMESEESND;
+ end = SD_NMESEESND;
+ SD_PreCacheSoundGroup(start,end);
+
+ start=W_GetNumForName("RHEAD101");
+ end =W_GetNumForName("NMESAUC4");
+ break;
+ case patrolgunobj:
+
+ start = SD_EMPLACEMENTSEESND;
+ end = SD_BIGEMPLACEFIRESND;
+ SD_PreCacheSoundGroup(start,end);
+
+
+ start=W_GetNumForName("GUNEMP1");
+ end =W_GetNumForName("GUNEMPF8");
+ PreCacheGroup(start,end,cache_patch_t);
+ start=W_GetNumForName("GRISE11");
+ end =W_GetNumForName("GDEAD2");
+ break;
+
+ case wallopobj:
+ start=W_GetNumForName("BSTAR1");
+ end =W_GetNumForName("BSTAR4");
+ PreCacheGroup(start,end,cache_patch_t);
+ start=W_GetNumForName("BCRAFT1");
+ end =W_GetNumForName("BCRAFT16");
+ break;
+
+ case wallfireobj:
+
+ SD_PreCacheSound(SD_FIRECHUTESND);
+ SD_PreCacheSound(SD_FIREBALLSND);
+ SD_PreCacheSound(SD_FIREBALLHITSND);
+
+ start = W_GetNumForName("CRFIRE11");
+ end = W_GetNumForName("CREXP5");
+
+ case pillarobj:
+
+ start=W_GetNumForName("PUSHCOL1");
+ end =W_GetNumForName("PSHCOL1A");
+ //end =W_GetNumForName("PUSHCOL3");
+ break;
+
+ case firejetobj:
+
+ SD_PreCacheSound(SD_FIREJETSND);
+
+ if (which)
+ {
+ start=W_GetNumForName("FJUP0");
+ end =W_GetNumForName("FJUP22");
+ }
+#if (SHAREWARE == 0)
+ else
+ {
+ start=W_GetNumForName("FJDOWN0");
+ end =W_GetNumForName("FJDOWN22");
+ }
+#endif
+
+ break;
+
+ case bladeobj:
+
+ SD_PreCacheSound(SD_BLADESPINSND);
+
+
+#if (SHAREWARE == 0)
+
+
+ if (which&2)
+ {
+ if (which&1)
+ {
+ start=W_GetNumForName("SPSTUP1");
+ end =W_GetNumForName("SPSTUP16");
+ }
+ else
+ {
+ start=W_GetNumForName("SPSTDN1");
+ end =W_GetNumForName("SPSTDN16");
+ }
+ }
+ else
+ {
+ if (which&1)
+ {
+ start=W_GetNumForName("UBLADE1");
+ end =W_GetNumForName("UBLADE9");
+ }
+ else
+ {
+ start=W_GetNumForName("DBLADE1");
+ end =W_GetNumForName("DBLADE9");
+ }
+ }
+#else
+ start=W_GetNumForName("UBLADE1");
+ end =W_GetNumForName("UBLADE9");
+#endif
+
+ break;
+ case crushcolobj:
+
+ SD_PreCacheSound(SD_CYLINDERMOVESND);
+ if (which)
+ {
+ start=W_GetNumForName("CRDOWN1");
+ end =W_GetNumForName("CRDOWN8");
+ }
+#if (SHAREWARE == 0)
+ else
+ {
+ start=W_GetNumForName("CRUP1");
+ end =W_GetNumForName("CRUP8");
+ }
+#endif
+ break;
+
+ case boulderobj:
+ start=W_GetNumForName("BOL11");
+ end =W_GetNumForName("BSINK9");
+ SD_PreCacheSound(SD_BOULDERHITSND);
+ SD_PreCacheSound(SD_BOULDERROLLSND);
+ SD_PreCacheSound(SD_BOULDERFALLSND);
+
+ break;
+
+ case spearobj:
+ SD_PreCacheSound(SD_SPEARSTABSND);
+
+ if (which)
+ {
+ start=W_GetNumForName("SPEARUP1");
+ end =W_GetNumForName("SPERUP16");
+ }
+#if (SHAREWARE == 0)
+ else
+ {
+ start=W_GetNumForName("SPEARDN1");
+ end =W_GetNumForName("SPERDN16");
+ }
+#endif
+
+ break;
+
+ case gasgrateobj:
+
+ start = SD_GASSTARTSND;
+ end = SD_GASMASKSND;
+ SD_PreCacheSoundGroup(start,end);
+ if ((locplayerstate->player == 1) || (locplayerstate->player == 3))
+ SD_PreCacheSound(SD_PLAYERCOUGHFSND);
+ else
+ SD_PreCacheSound(SD_PLAYERCOUGHMSND);
+ start=-1;
+ end=-1;
+ break;
+
+ case springobj:
+
+ SD_PreCacheSound(SD_SPRINGBOARDSND);
+
+ start=W_GetNumForName("SPRING1");
+ end =W_GetNumForName("SPRING9");
+ break;
+ default:
+ return;
+ break;
+ }
+ if ((start>=0) && (end>=0))
+ PreCacheGroup(start,end,cache_patch_t);
+}
+
+
+
+/*
+======================
+=
+= MiscPreCache
+= precache the lump and check to see if it is already tagged
+=
+======================
+*/
+void MiscPreCache( void )
+{
+ int start;
+ int end;
+
+ //essential sounds
+
+ SD_PreCacheSoundGroup(SD_HITWALLSND,SD_PLAYERDWHURTSND);
+ SD_PreCacheSoundGroup(SD_RICOCHET1SND,SD_RICOCHET3SND);
+ SD_PreCacheSound(SD_ATKPISTOLSND);
+ SD_PreCacheSoundGroup(SD_PLAYERBURNEDSND,SD_PLAYERLANDSND);
+ SD_PreCacheSoundGroup(SD_EXPLODEFLOORSND,SD_EXPLODESND);
+
+ if (lightning==true)
+ SD_PreCacheSound(SD_LIGHTNINGSND);
+
+ SD_PreCacheSound(SD_BODYLANDSND);
+ SD_PreCacheSound(SD_GIBSPLASHSND);
+ SD_PreCacheSound(SD_ACTORLANDSND);
+ SD_PreCacheSound(SD_ACTORSQUISHSND);
+
+
+ // cache in bullet hole graphics
+ start=W_GetNumForName("BULLETHO");
+ end=W_GetNumForName("ALTBHO");
+ PreCacheGroup(start,end,cache_transpatch_t);
+
+
+ // cache in explosions
+
+ if (DoPanicMapping()==true)
+ {
+ start=W_GetNumForName("EXPLOS1");
+ end =W_GetNumForName("EXPLOS20");
+ PreCacheGroup(start,end,cache_patch_t);
+ }
+ else
+ {
+ start=W_GetNumForName("EXPLOS1");
+ end =W_GetNumForName("GREXP25");
+ PreCacheGroup(start,end,cache_patch_t);
+ }
+
+ // cache in misc player sprites
+ start=W_GetNumForName("BLOODS1");
+ end =W_GetNumForName("PLATFRM5");
+ PreCacheGroup(start,end,cache_patch_t);
+
+ // cache in missile smoke
+ start=W_GetNumForName("MISSMO11");
+ end =W_GetNumForName("MISSMO14");
+ PreCacheGroup(start,end,cache_patch_t);
+
+#if (DEVELOPMENT == 1)
+ // cache in all weapon sounds
+ SD_PreCacheSoundGroup(SD_ATKPISTOLSND,SD_LOSEMODESND);
+
+ // cache in misc player weapons
+#if (SHAREWARE == 0)
+ start=W_GetNumForName("KNIFE1");
+ end =W_GetNumForName("DOGPAW4");
+ PreCacheGroup(start,end,cache_patch_t);
+ // cache in kinetic sphere
+ start=W_GetNumForName("KSPHERE1");
+ end =W_GetNumForName("KSPHERE4");
+ PreCacheGroup(start,end,cache_patch_t);
+
+#else
+ start=W_GetNumForName("MPIST11");
+ end =W_GetNumForName("GODHAND8");
+ PreCacheGroup(start,end,cache_patch_t);
+#endif
+
+
+ // cache in god mode stuff
+
+ PreCacheGroup(W_GetNumForName("VAPO1"),
+ W_GetNumForName("LITSOUL"),
+ cache_patch_t);
+
+ PreCacheGroup(W_GetNumForName("GODFIRE1"),
+ W_GetNumForName("GODFIRE4"),
+ cache_patch_t);
+
+
+#endif
+ // cache in player's gun
+
+ // cache in rubble
+ start=W_GetNumForName("RUBBLE1");
+ end =W_GetNumForName("RUBBLE10");
+ PreCacheGroup(start,end,cache_patch_t);
+
+ // cache in guts
+ start=W_GetNumForName("GUTS1");
+ end =W_GetNumForName("GUTS12");
+ PreCacheGroup(start,end,cache_patch_t);
+
+ // cache in player missile
+ start=W_GetNumForName("BJMISS1");
+ end =W_GetNumForName("BJMISS16");
+ PreCacheGroup(start,end,cache_patch_t);
+
+ if (gamestate.violence >= vl_high)
+ { // cache in all gibs
+ if (DoPanicMapping()==true)
+ {
+ start = W_GetNumForName("ORGAN1");
+ end = W_GetNumForName("ORGAN12");
+ }
+ else
+ {
+ start = W_GetNumForName("PART1");
+ end = W_GetNumForName("GEYE3");
+ }
+ PreCacheGroup(start,end,cache_patch_t);
+ }
+}
+
+
+/*
+========================
+=
+= IsChristmas
+=
+========================
+*/
+
+boolean IsChristmas(void)
+{
+ struct dosdate_t date;
+
+ _dos_getdate(&date);
+
+ if (((date.day == 24) || (date.day == 25)) && //Christmas
+ (date.month == 12)
+ )
+ return true;
+
+ return false;
+
+}
+
+
+/*
+========================
+=
+= CheckHolidays
+=
+========================
+*/
+
+void CheckHolidays(void)
+{
+ struct dosdate_t date;
+
+ _dos_getdate(&date);
+
+
+ if (IsChristmas())
+ DrawNormalSprite(0,0,W_GetNumForName("santahat"));
+
+ else if ((date.month == 5) && (date.day == 5)) // Cinco de Mayo
+ DrawNormalSprite(0,0,W_GetNumForName("sombrero"));
+
+ else if ((date.month == 7) && (date.day == 4)) // 4th of July
+ DrawNormalSprite(0,0,W_GetNumForName("amflag"));
+
+ else if ((date.month == 10) && (date.day == 31)) // Halloween
+ DrawNormalSprite(0,0,W_GetNumForName("witchhat"));
+
+ else if ((date.month == 4) && (date.dayofweek == 0)) //Easter
+ {
+ int i;
+
+ for(i=15; i<=21; i++)
+ {
+ if (date.day == i)
+ DrawNormalSprite(0,0,W_GetNumForName("esterhat"));
+ }
+ }
+}
+
+
+/*
+======================
+=
+= DrawPreCache
+=
+======================
+*/
+extern boolean dopefish;
+void DrawPreCache( void )
+{
+ if (loadedgame==false)
+ {
+ char temp[80];
+ int width, height, num;
+ char buf[30];
+
+ if ( BATTLEMODE )
+ {
+ VL_DrawPostPic (W_GetNumForName("trilogo"));
+ VWB_TBar ( 30, 23, 260, 82 );
+ ShowBattleOptions( false, 56, 26 );
+
+ DrawPlayers ();
+ }
+ else
+ {
+ pic_t * pic;
+ pic=(pic_t *)W_CacheLumpName("mmbk",PU_CACHE, Cvt_pic_t, 1);
+ VWB_DrawPic (0, 0, pic);
+
+ CheckHolidays();
+ }
+
+ DrawNormalSprite (PRECACHEBARX, PRECACHEBARY, W_GetNumForName ("cachebar"));
+
+ CurrentFont=smallfont;
+
+ PrintY = PRECACHEESTRINGY;
+ PrintX = PRECACHEESTRINGX;
+
+ memset (&buf[0], 0, sizeof (buf));
+
+ if ( !BATTLEMODE )
+ {
+ memcpy (&buf[0], "EPISODE ", 8);
+ itoa (gamestate.episode,&buf[8],10);
+ }
+ else
+ memcpy (&buf[0], "COMM-BAT", 8);
+
+ US_MeasureStr (&width, &height, "%s", &buf[0]);
+ VWB_TBar (PrintX-2, PrintY-2, width+4, height+4);
+ US_BufPrint (&buf[0]);
+
+
+ PrintY = PRECACHEASTRINGY;
+
+ memset (&buf[0], 0, sizeof (buf));
+ memcpy (&buf[0], "AREA ", 5);
+
+ if ( !BATTLEMODE )
+ {
+ itoa( GetLevel( gamestate.episode, gamestate.mapon ),
+ &buf[ 5 ], 10 );
+ }
+ else
+ {
+ itoa( gamestate.mapon + 1, &buf[ 5 ], 10 );
+ }
+ US_MeasureStr (&width, &height, "%s", &buf[0]);
+ PrintX = (300-width);
+ VWB_TBar (PrintX-2, PrintY-2, width+4, height+4);
+ US_BufPrint (&buf[0]);
+
+
+ PrintY = PRECACHESTRINGY;
+
+ num = (RandomNumber ("PreCacheString", 0)) % MAXSILLYSTRINGS;
+
+ if ((dopefish==true) || (tedlevel == true))
+ strcpy (temp, &(CacheStrings[num][0]));
+ else
+ strcpy (temp, &(LevelName[0]));
+
+ US_MeasureStr (&width, &height, "%s", &temp[0]);
+
+ PrintX = (320-width) >> 1;
+ PrintY = PRECACHESTRINGY;
+ VWB_TBar (PrintX-2, PrintY-2, width+4, height+4);
+
+ US_BufPrint (&temp[0]);
+
+ VW_UpdateScreen();
+
+ MenuFadeIn ();
+ }
+}
+
+#define CACHETICDELAY (6)
+/*
+======================
+=
+= PreCache
+= precache all the lumps for the level
+=
+======================
+*/
+void PreCache( void )
+{
+ int i;
+ int total;
+ byte * dummy;
+ int maxheapsize;
+ int newheap;
+
+ int currentmem;
+ int currentcache;
+ int lastmem=0;
+ int lastcache=0;
+ int ticdelay;
+ byte *tempbuf;
+
+ double Gs;
+ Gs = (iGLOBAL_SCREENWIDTH*100/320);
+ Gs = Gs / 100;
+
+//SetTextMode ( );
+
+ /*
+ #define PRECACHEBARX 28
+ #define PRECACHEBARY 178
+
+ #define PRECACHELED1X 9
+ #define PRECACHELED1Y 8
+
+ #define PRECACHELED2X 9
+ #define PRECACHELED2Y 12
+ */
+
+ if (CachingStarted==false)
+ {
+ if (loadedgame==false)
+ {
+ ClearGraphicsScreen();
+ MenuFadeIn ();
+ }
+ return;
+ }
+
+ MiscPreCache();
+
+ SortPreCache();
+
+ if (loadedgame==false)
+ {
+ maxheapsize=Z_HeapSize();
+ total=0;
+
+ tempbuf=bufferofs;
+ bufferofs=page1start; // fixed, was displayofs
+ ticdelay=CACHETICDELAY;
+ for (i=1; i<cacheindex; i++)
+ {
+ dummy=W_CacheLumpNum(cachelist[i].lump,cachelist[i].cachelevel, CvtForType(cachelist[i].type), 1);
+ total+=W_LumpLength(cachelist[i].lump);
+ newheap=Z_UsedHeap();
+ currentmem=(newheap*MAXLEDS)/maxheapsize;
+ while (lastmem<=currentmem)
+ { //SetTextMode ( );
+ if ( iGLOBAL_SCREENWIDTH == 320) {
+ DrawNormalSprite (PRECACHEBARX+PRECACHELED1X+(lastmem<<2),
+ PRECACHEBARY+PRECACHELED1Y,
+ W_GetNumForName ("led1"));//led1 progressbar
+ } else if ( iGLOBAL_SCREENWIDTH == 640) {
+ DrawNormalSprite (72+(Gs*(lastmem<<2)),446,W_GetNumForName ("led1"));//led1 progressbar
+ DrawNormalSprite (72+(Gs*(lastmem<<2)),446+3,W_GetNumForName ("led1"));//led1 progressbar
+ DrawNormalSprite (72+3+(Gs*(lastmem<<2)),446,W_GetNumForName ("led1"));//led1 progressbar
+ DrawNormalSprite (72+3+(Gs*(lastmem<<2)),446+3,W_GetNumForName ("led1"));//led1 progressbar
+ } else if ( iGLOBAL_SCREENWIDTH == 800) {
+ DrawNormalSprite (91+(Gs*(lastmem<<2)),559,W_GetNumForName ("led1"));//led1 progressbar
+ DrawNormalSprite (91+(Gs*(lastmem<<2)),559+3,W_GetNumForName ("led1"));//led1 progressbar
+ DrawNormalSprite (91+3+(Gs*(lastmem<<2)),559,W_GetNumForName ("led1"));//led1 progressbar
+ DrawNormalSprite (91+3+(Gs*(lastmem<<2)),559+3,W_GetNumForName ("led1"));//led1 progressbar
+ }
+
+ lastmem++;
+ VW_UpdateScreen (); // was missing, fixed
+ }
+ currentcache=(i*MAXLEDS)/(cacheindex+1);
+ while (lastcache<=currentcache)
+ {
+
+ if ( iGLOBAL_SCREENWIDTH == 320) {
+ DrawNormalSprite (PRECACHEBARX+PRECACHELED2X+(lastcache<<2),
+ PRECACHEBARY+PRECACHELED2Y,
+ W_GetNumForName ("led2"));//led2 progressbar
+ } else if ( iGLOBAL_SCREENWIDTH == 640) {
+ DrawNormalSprite (72+(Gs*(lastcache<<2)),458,W_GetNumForName ("led2"));//led2 progressbar
+ DrawNormalSprite (72+(Gs*(lastcache<<2)),458+3,W_GetNumForName ("led2"));//led2 progressbar
+ DrawNormalSprite (72+3+(Gs*(lastcache<<2)),458,W_GetNumForName ("led2"));//led2 progressbar
+ DrawNormalSprite (72+3+(Gs*(lastcache<<2)),458+3,W_GetNumForName ("led2"));//led2 progressbar
+
+ } else if ( iGLOBAL_SCREENWIDTH == 800) {
+ DrawNormalSprite (91+(Gs*(lastcache<<2)),573,W_GetNumForName ("led2"));//led2 progressbar
+ DrawNormalSprite (91+(Gs*(lastcache<<2)),573+3,W_GetNumForName ("led2"));//led2 progressbar
+ DrawNormalSprite (91+3+(Gs*(lastcache<<2)),573,W_GetNumForName ("led2"));//led2 progressbar
+ DrawNormalSprite (91+3+(Gs*(lastcache<<2)),573+3,W_GetNumForName ("led2"));//led2 progressbar
+ }
+ DisableScreenStretch();//bna++
+ VW_UpdateScreen ();//bna++
+ lastcache++;
+ ticdelay--;
+ if (ticdelay==0)
+ {
+ extern boolean dopefish;
+
+ if ( dopefish==true )
+ {
+ SD_PlayPitchedSound ( SD_DOPEFISHSND, 255, 0 );
+ }
+ ticdelay=CACHETICDELAY;
+ }
+ VW_UpdateScreen (); // was missing, fixed
+ }
+ }
+ DisableScreenStretch();//bna++
+ VW_UpdateScreen ();//bna++
+ //I_Delay(200);
+ bufferofs=tempbuf;
+ ShutdownPreCache ();
+
+ if ( BATTLEMODE )
+ {
+ int width,height;
+ char buf[30];//byte * shape;
+ double WHratio = 16200/200;
+ WHratio = WHratio/100;
+/// iGLOBAL_SCREENWIDTH = 640;
+// iGLOBAL_SCREENHEIGHT = 480;
+ DisableScreenStretch();
+
+ // Cache in fonts
+// shape = W_CacheLumpNum (W_GetNumForName ("newfnt1"), PU_STATIC, Cvt_font_t, 1);
+// bigfont = (font_t *)shape;
+ CurrentFont = newfont1;//smallfont;
+
+ strcpy( buf, "Press Any Key" );
+ US_MeasureStr (&width, &height, "%s", &buf[ 0 ] );
+ PrintX = (iGLOBAL_SCREENWIDTH-(width)) / 2;
+ PrintY = WHratio*iGLOBAL_SCREENHEIGHT;//162;
+ //VWB_TBar (PrintX-2, PrintY-2, width+4, height+4);
+ US_BufPrint (&buf[0]);
+
+ VW_UpdateScreen();
+
+ IN_StartAck();
+ while (!IN_CheckAck ())
+ ;
+ }
+// EnableScreenStretch();
+#if (DEVELOPMENT == 1)
+ tempbuf=bufferofs;
+ bufferofs=displayofs;
+ CurrentFont = smallfont;
+ US_CenterWindow(30,6);
+ PrintY+=6;
+ US_Print("Max Heap Size:");
+ US_PrintUnsigned(maxheapsize);
+ US_Print("\n");
+ US_Print("Used Heap Size:");
+ US_PrintUnsigned(newheap);
+ US_Print("\n");
+ US_Print("Percentage Used:");
+ US_PrintUnsigned(newheap*100/maxheapsize);
+ US_Print("\n");
+ US_Print("TotalPrecached:");
+ US_PrintUnsigned(total);
+ bufferofs=tempbuf;
+ I_Delay (40);
+#endif
+#if (PRECACHETEST == 1)
+ SoftError("Max Heap Size: %ld\n",maxheapsize);
+ SoftError("Used Heap Size: %ld\n",newheap);
+ SoftError("TotalPrecached: %ld\n",total);
+#endif
+ }
+ else
+ {
+ for (i=1; i<cacheindex; i++)
+ {
+ dummy=W_CacheLumpNum(cachelist[i].lump,cachelist[i].cachelevel, CvtForType(cachelist[i].type), 1);
+ DoLoadGameAction ();
+ }
+ ShutdownPreCache ();
+ }
+ if (CheckParm("LEVELSIZE")!=0)
+ {
+ OpenMapDebug();
+
+ MapDebug("Map Number %d\n",gamestate.mapon);
+ MapDebug("sizeoflevel=%d\n",Z_UsedLevelHeap());
+ }
+#if (PRECACHETEST == 1)
+ SoftError("<<<<<<<<<<<<<<<<<<<<<<<Precaching done\n");
+#endif
+}
+
+
+
+/*
+======================
+=
+= CA_RLEWexpand
+= length is EXPANDED length
+=
+======================
+*/
+
+void CA_RLEWexpand (word *source, word *dest,long length, unsigned rlewtag)
+{
+ word value,count,i;
+ word *end;
+
+ end = dest + length;
+ //
+ // expand it
+ //
+ do
+ {
+ value = IntelShort(*source++);
+ if (value != rlewtag)
+ //
+ // uncompressed
+ //
+ *dest++=value;
+ else
+ {
+ //
+ // compressed string
+ //
+ count = IntelShort(*source++);
+ value = IntelShort(*source++);
+ for (i=1; i<=count; i++)
+ *dest++ = value;
+ }
+ } while (dest<end);
+}
+
+/*
+======================
+=
+= CheckRTLVersion
+=
+======================
+*/
+
+void CheckRTLVersion
+(
+ char *filename
+)
+
+{
+ int filehandle;
+ char RTLSignature[ 4 ];
+ unsigned int RTLVersion;
+
+ filehandle = SafeOpenRead( filename );
+
+ //
+ // Load RTL signature
+ //
+ SafeRead( filehandle, RTLSignature, sizeof( RTLSignature ) );
+
+ if ( ( strcmp( RTLSignature, COMMBAT_SIGNATURE ) != 0 ) &&
+ ( strcmp( RTLSignature, NORMAL_SIGNATURE ) != 0 ) )
+ {
+ Error( "The file '%s' is not a valid level file.", filename );
+ }
+
+ //
+ // Check the version number
+ //
+ SafeRead( filehandle, &RTLVersion, sizeof( RTLVersion ) );
+ SwapIntelLong(&RTLVersion);
+ if ( RTLVersion > RTL_VERSION )
+ {
+ Error(
+ "The file '%s' is a version %d.%d %s file.\n"
+ "The highest this version of ROTT can load is %d.%d.", filename,
+ RTLVersion >> 8, RTLVersion & 0xff, RTLSignature,
+ RTL_VERSION >> 8, RTL_VERSION & 0xff );
+ }
+
+ close( filehandle );
+}
+
+
+/*
+======================
+=
+= ReadROTTMap
+=
+======================
+*/
+
+void ReadROTTMap
+(
+ char *filename,
+ int mapnum
+)
+
+{
+ RTLMAP RTLMap;
+ int filehandle;
+ long pos;
+ long compressed;
+ long expanded;
+ int plane;
+ byte *buffer;
+
+ CheckRTLVersion( filename );
+ filehandle = SafeOpenRead( filename );
+
+ //
+ // Load map header
+ //
+ lseek( filehandle, RTL_HEADER_OFFSET + mapnum * sizeof( RTLMap ),
+ SEEK_SET );
+ SafeRead( filehandle, &RTLMap, sizeof( RTLMap ) );
+
+ SwapIntelLong((int *)&RTLMap.used);
+ SwapIntelLong((int *)&RTLMap.CRC);
+ SwapIntelLong((int *)&RTLMap.RLEWtag);
+ SwapIntelLong((int *)&RTLMap.MapSpecials);
+ SwapIntelLongArray((int *)&RTLMap.planestart, NUMPLANES);
+ SwapIntelLongArray((int *)&RTLMap.planelength, NUMPLANES);
+
+ if ( !RTLMap.used )
+ {
+ Error( "ReadROTTMap: Tried to load a non existent map!" );
+ }
+
+#if ( SHAREWARE == 1 )
+ if ( RTLMap.RLEWtag == REGISTERED_TAG )
+ {
+ Error( "Can't use maps from the registered game in shareware version." );
+ }
+
+ if ( RTLMap.RLEWtag != SHAREWARE_TAG )
+ {
+ Error( "Can't use modified maps in shareware version." );
+ }
+#endif
+
+ mapwidth = 128;
+ mapheight = 128;
+
+ // Get special map flags
+ MapSpecials = RTLMap.MapSpecials;
+
+ //
+ // load the planes in
+ //
+ expanded = mapwidth * mapheight * 2;
+
+ for( plane = 0; plane <= 2; plane++ )
+ {
+ pos = RTLMap.planestart[ plane ];
+ compressed = RTLMap.planelength[ plane ];
+ buffer = SafeMalloc( compressed );
+ lseek( filehandle, pos, SEEK_SET );
+ SafeRead( filehandle, buffer, compressed );
+
+ mapplanes[ plane ] = Z_Malloc( expanded, PU_LEVEL, &mapplanes[ plane ] );
+
+ //
+ // unRLEW, skipping expanded length
+ //
+#if ( SHAREWARE == 1 )
+ CA_RLEWexpand( ( word * )buffer, ( word * )mapplanes[ plane ],
+ expanded >> 1, SHAREWARE_TAG );
+#else
+ CA_RLEWexpand( ( word * )buffer, ( word * )mapplanes[ plane ],
+ expanded >> 1, RTLMap.RLEWtag );
+#endif
+
+ SafeFree( buffer );
+ }
+ close(filehandle);
+
+ //
+ // get map name
+ //
+ strcpy( LevelName, RTLMap.Name );
+}
+
+
+
+/*
+======================
+=
+= GetNextMap
+=
+======================
+*/
+int GetNextMap ( int tilex, int tiley )
+{
+ word next;
+ word icon;
+ boolean done;
+
+ next = MAPSPOT( tilex, tiley, 2 );
+ icon = MAPSPOT( tilex, tiley, 1 );
+ done=false;
+ if ( ( ( icon != EXITTILE ) && ( icon != SECRETEXITTILE ) ) ||
+ ( ( ( next&0xff00 ) != 0xe200 ) && ( ( next&0xff00 ) != 0xe400 ) ) )
+ {
+ int i,j;
+
+ for ( j = 0; j < mapheight; j++ )
+ {
+ for ( i = 0; i < mapwidth; i++ )
+ {
+ icon = MAPSPOT( i, j, 1 );
+ next = MAPSPOT( i, j, 2 );
+ if ( ( ( icon == EXITTILE ) || ( icon == SECRETEXITTILE ) ) &&
+ ( ( ( next&0xff00 ) == 0xe200 ) ||
+ ( ( next&0xff00 ) == 0xe400 ) ) )
+ {
+ done=true;
+ break;
+ }
+ }
+
+ if ( done == true )
+ {
+ break;
+ }
+ }
+
+ if ( !done )
+ {
+ Error( "GetNextMap : No exit tile on map %d.", gamestate.mapon );
+ }
+ }
+ if ( ( ( next & 0xff00 ) != 0xe200 ) &&
+ ( ( next & 0xff00 ) != 0xe400 ) )
+ {
+ // Should this be DEVELOPMENT only?
+ Error( "GetNextMap : Illegal destination map %xh at exit "
+ "tile on map %d.", next, gamestate.mapon );
+ }
+
+ if ( next == 0xe2ff )
+ {
+ return -1;
+ }
+
+ return ( next & 0xff );
+}
+
+/*
+======================
+=
+= GetMapFileInfo
+=
+======================
+*/
+void GetMapFileInfo
+(
+ mapfileinfo_t *mapinfo,
+ char *filename
+)
+
+{
+ RTLMAP RTLMap[ 100 ];
+ int filehandle;
+ int i;
+ int nummaps;
+
+ CheckRTLVersion( filename );
+
+ filehandle = SafeOpenRead( filename );
+
+ //
+ // Load map header
+ //
+ lseek( filehandle, RTL_HEADER_OFFSET, SEEK_SET );
+ SafeRead( filehandle, &RTLMap, sizeof( RTLMap ) );
+ close( filehandle );
+
+ nummaps = 0;
+ for( i = 0; i < 100; i++ )
+ {
+ if ( !RTLMap[ i ].used )
+ {
+ continue;
+ }
+
+ mapinfo->maps[ nummaps ].number = i;
+
+ strcpy( mapinfo->maps[ nummaps ].mapname, RTLMap[ i ].Name );
+
+ nummaps++;
+ }
+
+ mapinfo->nummaps = nummaps;
+}
+
+/*
+======================
+=
+= GetMapFileName
+=
+======================
+*/
+void GetMapFileName ( char * filename )
+{
+ if ( ( BATTLEMODE ) && (BattleLevels.avail == true) )
+ {
+ strcpy(filename,BattleLevels.file);
+ }
+ else if (GameLevels.avail == true)
+ {
+ strcpy(filename,GameLevels.file);
+ }
+ else if ( BATTLEMODE )
+ {
+ strcpy(filename,BATTMAPS);
+ }
+ else
+ {
+ strcpy(filename,ROTTMAPS);
+ }
+}
+
+/*
+======================
+=
+= SetBattleMapFileName
+=
+======================
+*/
+void SetBattleMapFileName ( char * filename )
+{
+ BattleLevels.avail = true;
+ BattleLevels.file = strdup(filename);
+}
+
+/*
+======================
+=
+= GetMapCRC
+=
+======================
+*/
+word GetMapCRC
+(
+ int num
+)
+
+{
+ int filehandle;
+ char filename[ 80 ];
+ RTLMAP RTLMap;
+
+ GetMapFileName( &filename[ 0 ] );
+ CheckRTLVersion( filename );
+ filehandle = SafeOpenRead( filename );
+
+ //
+ // Load map header
+ //
+ lseek( filehandle, RTL_HEADER_OFFSET + num * sizeof( RTLMap ), SEEK_SET );
+ SafeRead( filehandle, &RTLMap, sizeof( RTLMap ) );
+
+ close( filehandle );
+
+ return( RTLMap.CRC );
+}
+
+
+/*
+======================
+=
+= GetAlternateMapInfo
+=
+======================
+*/
+
+void GetAlternateMapInfo (mapfileinfo_t * mapinfo, AlternateInformation *info)
+{
+ if (UL_ChangeDirectory (info->path) == false)
+ Error ("ERROR : Can't change to alternate directory %s!\n", info->path);
+
+ GetMapFileInfo (mapinfo, info->file);
+
+ UL_ChangeDirectory (&CWD[0]);
+}
+
+/*
+======================
+=
+= GetMapInfo
+=
+======================
+*/
+void GetMapInfo
+(
+ mapfileinfo_t *mapinfo
+)
+
+{
+ if ( ( BATTLEMODE ) && ( BattleLevels.avail == true ) )
+ {
+ GetAlternateMapInfo( mapinfo, &BattleLevels );
+ }
+ else if ( GameLevels.avail == true )
+ {
+ GetAlternateMapInfo( mapinfo, &GameLevels );
+ }
+ else if ( BATTLEMODE )
+ {
+ GetMapFileInfo( mapinfo, BATTMAPS );
+ }
+ else
+ {
+ GetMapFileInfo( mapinfo, ROTTMAPS );
+ }
+}
+
+/*
+======================
+=
+= LoadTedMap
+=
+======================
+*/
+void LoadTedMap
+(
+ const char *extension,
+ int mapnum
+)
+
+{
+ long pos;
+ long compressed;
+ long expanded;
+ int plane;
+ int i;
+ int maphandle;
+ byte *buffer;
+ maptype mapheader;
+ char name[ 200 ];
+ mapfiletype *tinf;
+
+ //
+ // load maphead.ext (offsets and tileinfo for map file)
+ //
+ strcpy( name, "maphead." );
+ strcat( name, extension );
+ LoadFile( name, ( void * )&tinf );
+
+ // fix structure alignment
+ tinf = ( void * )( ( word * )tinf - 1 );
+
+ for( i = 0 ; i < 100 ; i++ )
+ {
+ tinf->headeroffsets[ i ] = IntelLong( tinf->headeroffsets[ i ] );
+ }
+
+ //
+ // open the data file
+ //
+ strcpy( name, "maptemp." );
+ strcat( name, extension );
+ maphandle = SafeOpenRead( name );
+
+ //
+ // load map header
+ //
+ pos = tinf->headeroffsets[ mapnum ];
+
+ // $FFFFFFFF start is a sparse map
+ if ( pos < 0 )
+ {
+ Error( "LoadTedMap : Tried to load a non existent map!" );
+ }
+
+ lseek( maphandle, pos, SEEK_SET );
+ SafeRead( maphandle, &mapheader, sizeof( maptype ) );
+
+ for( i = 0 ; i < 3; i++ )
+ {
+ mapheader.planestart[ i ] = IntelLong( mapheader.planestart[ i ] );
+ mapheader.planelength[ i ] = IntelShort( mapheader.planelength[ i ] );
+ }
+
+ mapheader.width = IntelShort( mapheader.width );
+ mapheader.height = IntelShort( mapheader.height );
+
+ mapwidth = mapheader.width;
+ mapheight = mapheader.height;
+
+ // Set special map flags
+ MapSpecials = 0;
+
+ //
+ // load the planes in
+ //
+ expanded = mapheader.width * mapheader.height * 2;
+
+ for( plane = 0; plane <= 2; plane++ )
+ {
+ pos = mapheader.planestart[ plane ];
+ lseek( maphandle, pos, SEEK_SET );
+
+ compressed = mapheader.planelength[ plane ];
+ buffer = SafeMalloc( compressed );
+ SafeRead( maphandle, buffer, compressed );
+
+ mapplanes[ plane ] = Z_Malloc( expanded, PU_LEVEL, &mapplanes[ plane ] );
+
+ //
+ // unRLEW, skipping expanded length
+ //
+ CA_RLEWexpand( ( word * )( buffer + 2 ), ( word * )mapplanes[ plane ],
+ expanded >> 1, 0xabcd );
+
+ SafeFree( buffer );
+ }
+
+ // fix structure alignment
+ tinf = ( void * )( ( word * )tinf + 1 );
+
+ SafeFree( tinf );
+
+ if ( close( maphandle ) )
+ {
+ Error( "Error closing Ted file Error #%d", errno );
+ }
+}
+
+
+/*
+======================
+=
+= LoadAlternateMap
+=
+======================
+*/
+
+void LoadAlternateMap (AlternateInformation *info, int mapnum)
+{
+ if (UL_ChangeDirectory (info->path) == false)
+ Error ("ERROR : Can't change to alternate directory %s!\n",info->path);
+
+ ReadROTTMap (info->file, mapnum);
+
+ UL_ChangeDirectory (&CWD[0]);
+}
+
+/*
+======================
+=
+= LoadROTTMap
+=
+======================
+*/
+void LoadROTTMap
+(
+ int mapnum
+)
+
+{
+ if ( tedlevel == true )
+ {
+ LoadTedMap( "rot", mapnum );
+ }
+ else if ( ( BATTLEMODE ) && ( BattleLevels.avail == true ) )
+ {
+ LoadAlternateMap( &BattleLevels, mapnum );
+ }
+ else if ( GameLevels.avail == true )
+ {
+ LoadAlternateMap( &GameLevels, mapnum );
+ }
+ else if ( BATTLEMODE )
+ {
+ ReadROTTMap( BATTMAPS, mapnum );
+ }
+ else
+ {
+ ReadROTTMap( ROTTMAPS, mapnum );
+ }
+}
+
+
+void CountAreaTiles(void)
+{ int i,j,areanumber;
+ word*map,tile;
+
+ memset(numareatiles,0,sizeof(numareatiles));
+ map = mapplanes[0];
+
+ for(i=0; i<MAPSIZE; i++)
+ for(j=0; j<MAPSIZE; j++)
+ { tile = *map++;
+
+ areanumber = tile - AREATILE;
+ if ((areanumber >= 0) && (areanumber <= NUMAREAS))
+ numareatiles[areanumber] ++;
+ }
+
+}
+
+
+
+#define InitWall(lump,index,newx,newy) \
+ { \
+ PreCacheLump(lump,PU_CACHEWALLS,cache_pic_t); \
+ if (W_LumpLength(lump) == 0) \
+ Error("%s being used in shareware at %d %d",\
+ W_GetNameForNum(lump),newx,newy); \
+ actorat[newx][newy]= &walls[index]; \
+ tempwall = (wall_t*)actorat[newx][newy]; \
+ tempwall->which = WALL; \
+ tempwall->tile = index; \
+ } \
+
+
+/*
+==================
+=
+= SetupWalls
+=
+==================
+*/
+void SetupWalls( void )
+{
+ int i,j,lump,index;
+ word *map,tile;
+ wall_t * tempwall;
+
+
+ for (i=0; i<MAXWALLTILES; i++)
+ memset(&walls[i],0,sizeof(wall_t));
+
+ map = mapplanes[0];
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ if ((i>=0) && (i<=3) && (j==0))
+ {
+ map++;
+ continue;
+ }
+ if ((loadedgame == false) && (MAPSPOT(i,j,2) == 0xeeee))
+ { _2Dpoint *tdptr;
+
+ tdptr = &(MISCVARS->EPOP[MISCVARS->nextpop]);
+ tdptr->x = i;
+ tdptr->y = j;
+ MISCVARS->nextpop ++;
+ MISCVARS->popsleft ++;
+ }
+ tile= *map++;
+
+ if ((tile > 89) ||
+ ((tile > 32) && (tile < 36)) ||
+ (tile == 44) ||
+ (tile == 45) ||
+ (tile == 0)
+ )
+ {
+ tilemap[i][j] = 0;
+ continue;
+ }
+
+ if (tile <= 32)
+ {
+ index = tile;
+#if 0
+ if (tile==12)
+ {
+ if (MAPSPOT(i,j,2)==0)
+ MAPSPOT(i,j,2)=21;
+ }
+#endif
+ }
+ else
+ index = tile-3;
+
+ if ((tile > 75) && (tile <= 79))
+ {
+ lump = tilemap[i][j] = GetLumpForTile(tile);
+ PreCacheLump(lump,PU_CACHEWALLS,cache_pic_t);
+ PreCacheLump(elevatorstart+5,PU_CACHEWALLS,cache_pic_t);
+ PreCacheLump(elevatorstart+6,PU_CACHEWALLS,cache_pic_t);
+ PreCacheLump(elevatorstart+7,PU_CACHEWALLS,cache_pic_t);
+ tilemap[i][j]|=0x2000;
+ if (MAPSPOT(i,j,2)==0)
+ MAPSPOT(i,j,2)=21;
+ }
+ else if ((tile >= 47) && (tile <= 48))
+ {
+ lump = tilemap[i][j] = GetLumpForTile(tile);
+ InitWall(lump,index,i,j);
+ tilemap[i][j]|=0x2000;
+ if (MAPSPOT(i,j,2)==0)
+ MAPSPOT(i,j,2)=21;
+ }
+ else
+ {
+ lump = tilemap[i][j] = GetLumpForTile(tile);
+ InitWall(lump,index,i,j);
+ if (MAPSPOT(i,j,2))
+ tilemap[i][j]|=0x2000;
+ }
+ }
+ }
+}
+
+
+/*
+===============
+=
+= GetNearestAreaNumber
+=
+===============
+*/
+word GetNearestAreaNumber ( int tilex, int tiley )
+{
+ int up,dn,lt,rt;
+ int tile;
+
+ tile=MAPSPOT(tilex,tiley,0)-AREATILE;
+
+ if ((tile<=NUMAREAS) && (tile>0))
+ return (tile+AREATILE);
+
+ up=MAPSPOT(tilex,tiley-1,0)-AREATILE;
+ dn=MAPSPOT(tilex,tiley+1,0)-AREATILE;
+ lt=MAPSPOT(tilex-1,tiley,0)-AREATILE;
+ rt=MAPSPOT(tilex+1,tiley,0)-AREATILE;
+
+ up = ((up>0) && (up<=NUMAREAS));
+ dn = ((dn>0) && (dn<=NUMAREAS));
+ lt = ((lt>0) && (lt<=NUMAREAS));
+ rt = ((rt>0) && (rt<=NUMAREAS));
+
+ if (rt)
+ return (MAPSPOT(tilex+1,tiley,0) + AREATILE);
+ else if (lt)
+ return (MAPSPOT(tilex-1,tiley,0) + AREATILE);
+ else if (up)
+ return (MAPSPOT(tilex,tiley-1,0) + AREATILE);
+ else if (dn)
+ return (MAPSPOT(tilex,tiley+1,0) + AREATILE);
+// else
+// Error("GetNearestAreaNumber: Couldn't fix up area at x=%ld y=%ld\n",tilex,tiley);
+ return (NUMAREAS+AREATILE-1);
+}
+
+/*
+===============
+=
+= SetupWindows
+=
+===============
+*/
+void SetupWindows ( void )
+{
+ int i,j;
+ boolean skythere;
+
+ skythere = SkyExists();
+
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ if ((i>=0) && (i<=3) && (j==0))
+ continue;
+ if (IsWindow(i,j))
+ {
+ actorat[i][j]=0;
+ if (skythere==true)
+ {
+ tilemap[i][j]|=0x2000;
+ }
+ else
+ {
+ MAPSPOT(i,j,2)=0;
+ }
+ MAPSPOT(i,j,0)=(word)(GetNearestAreaNumber(i,j));
+ }
+ }
+ }
+
+}
+
+
+/*
+==================
+=
+= GetWallIndex
+=
+==================
+*/
+
+int GetWallIndex( int texture )
+{
+ int wallstart;
+ int exitstart;
+
+ wallstart=W_GetNumForName("WALLSTRT");
+ exitstart=W_GetNumForName("EXITSTRT");
+ elevatorstart = W_GetNumForName("ELEVSTRT");
+
+ if (texture&0x1000)
+ {
+ texture&=~0x1000;
+ if (texture==0)
+ return 41;
+ else if (texture==1)
+ return 90;
+ else if (texture==2)
+ return 91;
+ else if (texture==3)
+ return 42;
+ else if (texture==4)
+ return 92;
+ else if (texture==5)
+ return 93;
+ else if (texture==6)
+ return 94;
+ else if (texture==7)
+ return 95;
+ else if (texture==8)
+ return 96;
+ else if (texture==9)
+ return 97;
+ else if (texture==10)
+ return 98;
+ else if (texture==11)
+ return 99;
+ else if (texture==12)
+ return 100;
+ else if (texture==13)
+ return 101;
+ else if (texture==14)
+ return 102;
+ else if (texture==15)
+ return 103;
+ else if (texture==16)
+ return 104;
+ }
+ else if (texture > elevatorstart)
+ return (texture - elevatorstart + 68);
+// else if (texture > specialstart)
+// return (texture - specialstart + 41);
+ else if (texture > exitstart)
+ return (texture - exitstart + 43);
+ else
+ {
+ if (texture>wallstart+63)
+ return (texture - (wallstart + 63) + 76 );
+ else if (texture>wallstart+40)
+ return (texture - (wallstart + 40) + 45 );
+ else
+ return (texture - wallstart);
+ }
+ return 0x8000;
+}
+
+/*
+==================
+=
+= SetupAnimatedWalls
+=
+==================
+*/
+void SetupAnimatedWalls( void )
+{
+ int i,j;
+ word *map,tile;
+ wall_t * tempwall;
+
+ InitAnimatedWallList();
+ map = mapplanes[0];
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ if ((i>=0) && (i<=3) && (j==0))
+ {
+ map++;
+ continue;
+ }
+ tile= *map++;
+ if (tile == 44)
+ {
+ actorat[i][j]= &walls[tile-3];
+ tempwall = (wall_t*)actorat[i][j];
+ tempwall->which = WALL;
+ tempwall->tile = tile-3;
+ tempwall->flags = FL_W_DAMAGE;
+ SetupAnimatedWall(0);
+ tilemap[i][j]=0;
+ tilemap[i][j]|=0x1000;
+ }
+ else if (tile == 45)
+ {
+ actorat[i][j]= &walls[tile-3];
+ tempwall = (wall_t*)actorat[i][j];
+ tempwall->which = WALL;
+ tempwall->tile = tile-3;
+ SetupAnimatedWall(3);
+ tilemap[i][j]=3;
+ tilemap[i][j]|=0x1000;
+ }
+ else if ((tile >= 106) && (tile <= 107))
+ {
+ actorat[i][j]= &walls[tile-16];
+ tempwall = (wall_t*)actorat[i][j];
+ tempwall->which = WALL;
+ tempwall->tile = tile-16;
+ SetupAnimatedWall(tile-105);
+ tilemap[i][j]=tile-105;
+ tilemap[i][j]|=0x1000;
+ }
+ else if ((tile >= 224) && (tile <= 233))
+ {
+ actorat[i][j]= &walls[tile-224+92];
+ tempwall = (wall_t*)actorat[i][j];
+ tempwall->which = WALL;
+ tempwall->tile = tile-224+94;
+ if (tile==233)
+ tempwall->flags = FL_W_DAMAGE;
+ SetupAnimatedWall(tile-224+4);
+ tilemap[i][j]=tile-224+4;
+ tilemap[i][j]|=0x1000;
+ }
+ else if ((tile >= 242) && (tile <= 244))
+ {
+ actorat[i][j]= &walls[tile-242+102];
+ tempwall = (wall_t*)actorat[i][j];
+ tempwall->which = WALL;
+ tempwall->tile = tile-242+102;
+ SetupAnimatedWall(tile-242+14);
+ tilemap[i][j]=tile-242+14;
+ tilemap[i][j]|=0x1000;
+ }
+ }
+ }
+}
+
+
+/*
+==================
+=
+= SetupSwitches
+=
+==================
+*/
+
+void SetupSwitches( void )
+{
+ int i,j;
+ word *map,tile;
+
+ map = mapplanes[0];
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ if ((i>=0) && (i<=3) && (j==0))
+ {
+ map++;
+ continue;
+ }
+ tile= *map++;
+ if ((tile >= 76) && (tile <= 79))
+ {
+ if (tile == 79)
+ lastswitch->flags |= FL_ON;
+ SpawnSwitchThingy(i,j);
+ }
+ else if ((tile == 157) || (tile == 175)) // hi masked switches
+ {
+ lastswitch->flags |= FL_W_INVERTED;
+ lastswitch->flags |= FL_REVERSIBLE;
+ if (tile==175)
+ lastswitch->flags |= FL_ON;
+ SpawnSwitchThingy(i,j);
+ }
+ }
+ }
+}
+
+
+
+void RespawnPlayerobj(objtype *ob)
+{ int rand,numchecked=0;
+ int oldsetupgame,nx,ny,ndir;
+ playertype *pstate;
+
+ M_LINKSTATE(ob,pstate);
+
+ if (gamestate.battlemode != battle_CaptureTheTriad)
+ {
+ rand = (GameRandomNumber("playerobj respawn",0) % NUMSPAWNLOCATIONS);
+
+ while(numchecked < NUMSPAWNLOCATIONS)
+ {
+ if (!actorat[SPAWNLOC[rand].x][SPAWNLOC[rand].y])
+ { RevivePlayerobj(SPAWNLOC[rand].x,SPAWNLOC[rand].y,SPAWNLOC[rand].dir,ob);
+ return;
+ }
+ numchecked ++;
+ rand = (rand + 1) % NUMSPAWNLOCATIONS;
+ }
+#if (DEVELOPMENT == 1)
+ SoftError("\nno spawn locations available, using FindEmptyTile");
+#endif
+ nx = SPAWNLOC[rand].x;
+ ny = SPAWNLOC[rand].y;
+ ndir = SPAWNLOC[rand].dir;
+ }
+ else
+ { nx = TEAM[pstate->team].tilex;
+ ny = TEAM[pstate->team].tiley;
+ ndir = TEAM[pstate->team].dir;
+ }
+
+ oldsetupgame = insetupgame;
+ insetupgame = true;
+ FindEmptyTile(&nx,&ny);
+ insetupgame = oldsetupgame;
+ RevivePlayerobj(nx,ny,ndir,ob);
+
+
+}
+
+#define SetupSpecificFlagTeamAt(whichteam, spawnlocindex) \
+{int newx,newy; \
+ \
+ newx = SPAWNLOC[spawnlocindex].x; \
+ newy = SPAWNLOC[spawnlocindex].y; \
+ TEAM[whichteam].tilex = newx; \
+ TEAM[whichteam].tiley = newy; \
+ TEAM[whichteam].dir = SPAWNLOC[spawnlocindex].x; \
+ SpawnStatic(newx,newy,stat_collector,9); \
+ SpawnNewObj(newx,newy,&s_basemarker1,inertobj); \
+ LASTACTOR->z = LASTSTAT->z; \
+ LASTSTAT->flags |= FL_COLORED; \
+ LASTSTAT->hitpoints = whichteam; \
+ locspawned[spawnlocindex]=1; \
+ for(j=0;j<numplayers;j++) \
+ {if (PLAYERSTATE[j].uniformcolor != \
+ TEAM[whichteam].uniformcolor) \
+ continue; \
+ \
+ ntilex = newx; \
+ ntiley = newy; \
+ FindEmptyTile(&ntilex,&ntiley); \
+ SpawnPlayerobj(ntilex,ntiley,dir,j); \
+ } \
+} \
+
+
+/*
+=============
+=
+= AssignTeams called from SetGameDescription in rt_net.c
+=
+=============
+*/
+
+void AssignTeams(void)
+{ int i,color;
+ int teamforcolor[MAXPLAYERCOLORS];
+
+ numteams = 0;
+ if (!gamestate.teamplay)
+ return;
+
+ memset(teamforcolor,-1,sizeof(teamforcolor));
+ memset(TEAM,0,sizeof(TEAM));
+
+ for(i=0; i<numplayers; i++)
+ { color = PLAYERSTATE[i].uniformcolor;
+ if (teamforcolor[color] == -1)
+ { TEAM[numteams].uniformcolor = color;
+
+ TEAM[numteams].nummembers ++;
+ teamforcolor[color] = numteams;
+ numteams++;
+ if ((gamestate.battlemode == battle_CaptureTheTriad) &&
+ (numteams > 2))
+ Error("players selected more colors(%d) than Capture the Triad allows",numteams);
+ }
+ else
+ TEAM[teamforcolor[color]].nummembers ++;
+
+ PLAYERSTATE[i].team = teamforcolor[color];
+
+ }
+
+}
+
+
+
+/*
+=============
+=
+= SetupTeams
+=
+=============
+*/
+
+
+void SetupTeams(void)
+{
+
+ int i,j,rand,sx,sy,ntilex,ntiley,dir,
+ maxdist,currdist,spawnindex,cnt;
+ int locspawned[MAXSPAWNLOCATIONS] = {0};
+
+ if (gamestate.battlemode == battle_CaptureTheTriad)
+ { rand = (GameRandomNumber("net player spawn",0) % NUMSPAWNLOCATIONS);
+
+ for(i=0; i<NUMSPAWNLOCATIONS; i++)
+ { sx = SPAWNLOC[rand].x;
+ sy = SPAWNLOC[rand].y;
+ dir = SPAWNLOC[rand].dir;
+
+ if (CheckTile(sx,sy) && (!IsPlatform(sx,sy)) &&
+ (Number_of_Empty_Tiles_In_Area_Around(sx,sy) > TEAM[0].nummembers)
+ )
+ { SetupSpecificFlagTeamAt(0,rand);
+ break;
+ }
+
+ rand = (rand + 1)%NUMSPAWNLOCATIONS;
+ }
+
+ if (i == NUMSPAWNLOCATIONS)
+ Error("No spawn location available for team 0, capture the flag");
+
+ maxdist = 0x80000000;
+ for(i=0; i<NUMSPAWNLOCATIONS; i++)
+ { if (locspawned[i])
+ continue;
+
+ sx = SPAWNLOC[i].x;
+ sy = SPAWNLOC[i].y;
+ dir = SPAWNLOC[i].dir;
+
+ if ((Number_of_Empty_Tiles_In_Area_Around(sx,sy) < TEAM[1].nummembers)
+ || (!CheckTile(sx,sy) || IsPlatform(sx,sy))
+ )
+ continue;
+
+ currdist = FindDistance(sx-TEAM[0].tilex,sy-TEAM[0].tiley);
+ if (currdist > maxdist)
+ { maxdist = currdist;
+ spawnindex = i;
+ }
+ }
+
+ SetupSpecificFlagTeamAt(1,spawnindex);
+ }
+ else
+ {
+ int badcount = 0,teamindex;
+
+ if (numteams > NUMSPAWNLOCATIONS)
+ Error("More teams than spawn locations !");
+ //cnt =0;
+ //for(rand = 0;rand < NUMSPAWNLOCATIONS;rand++)
+ for(cnt=0; cnt<numteams;)
+ {
+ rand = (GameRandomNumber("team spawn",0) % NUMSPAWNLOCATIONS);
+
+ if (locspawned[rand])
+ continue;
+
+
+ sx = SPAWNLOC[rand].x;
+ sy = SPAWNLOC[rand].y;
+ dir = SPAWNLOC[rand].dir;
+
+ if (Number_of_Empty_Tiles_In_Area_Around(sx,sy) < TEAM[cnt].nummembers)
+ {
+ badcount ++;
+ if (badcount == (NUMSPAWNLOCATIONS - cnt))
+ Error("\n%s team cannot spawn in this level",colorname[TEAM[cnt].uniformcolor]);
+ continue;
+ }
+
+ badcount = 0;
+ //Debug("\n\nSpawn Location %d",rand);
+ //Debug("\n-----------------");
+ TEAM[cnt].tilex = sx;
+ TEAM[cnt].tiley = sy;
+ TEAM[cnt].dir = dir;
+ locspawned[rand]=1;
+ cnt++;
+
+ }
+
+ for(j=0; j<numplayers; j++)
+ {
+ teamindex = PLAYERSTATE[j].team;
+
+ sx = TEAM[teamindex].tilex;
+ sy = TEAM[teamindex].tiley;
+ dir = TEAM[teamindex].dir;
+
+ FindEmptyTile(&sx,&sy);
+
+ //Debug("\n x: %3d, y: %3d",sx,sy);
+ SpawnPlayerobj(sx,sy,dir,j);
+ }
+
+
+ }
+
+
+
+
+//numplayers = 1;
+//Error("Okay");
+#if ((DEVELOPMENT == 1))
+#if (TEAMTEST == 1)
+
+ Debug("Team Spawn Location\n");
+ Debug("-------------------\n");
+ for(i=0; i<numteams; i++)
+ Debug("%d %3d,%3d\n",i,TEAM[i].tilex,TEAM[i].tiley);
+
+
+ Debug("Player Team Location\n");
+ Debug("------ ---- --------\n");
+ for(i=0; i<numplayers; i++)
+ Debug(" %d %d %3d,%3d\n",i,PLAYERSTATE[i].team,PLAYER[i]->tilex,PLAYER[i]->tiley);
+
+// Error("done");
+#endif
+#endif
+
+}
+
+
+/*
+==================
+=
+= SetupPlayers
+=
+==================
+*/
+
+void SetupPlayers( void )
+{
+ int i,j;
+ word *map,tile;
+
+ //START in icon plane = 10
+
+ map = mapplanes[1];
+ for(j=0; j<mapheight; j++)
+ for(i=0; i<mapwidth; i++)
+ {
+ tile = *map++;
+ switch (tile)
+ {
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ FIRST.x = i;
+ FIRST.y = j;
+ FIRST.dir = tile-19;
+ SPAWNLOC[NUMSPAWNLOCATIONS].x = i;
+ SPAWNLOC[NUMSPAWNLOCATIONS].y = j;
+ SPAWNLOC[NUMSPAWNLOCATIONS].dir = tile-19;
+ if (NUMSPAWNLOCATIONS<MAXSPAWNLOCATIONS)
+ NUMSPAWNLOCATIONS ++;
+ break;
+
+ case 274:
+ case 275:
+ case 276:
+ case 277:
+ SPAWNLOC[NUMSPAWNLOCATIONS].x = i;
+ SPAWNLOC[NUMSPAWNLOCATIONS].y = j;
+ SPAWNLOC[NUMSPAWNLOCATIONS].dir = tile-274;
+ if (NUMSPAWNLOCATIONS<MAXSPAWNLOCATIONS)
+ NUMSPAWNLOCATIONS ++;
+ break;
+ }
+
+ }
+
+ if ( NUMSPAWNLOCATIONS <= 0 )
+ {
+ Error( "No spawn locations found on map." );
+ }
+
+ /*modemgame=true;
+ gamestate.teamplay = true;
+ PLAYERSTATE[0].uniformcolor = 2;
+ PLAYERSTATE[1].uniformcolor = 2;
+ numplayers = 2;
+ AssignTeams();*/
+
+ if (!BATTLEMODE)
+ {
+ if (tedlevel)
+ {
+ if ((tedx==0) || (tedy == 0))
+ SpawnPlayerobj (FIRST.x, FIRST.y, FIRST.dir,0);
+ else
+ SpawnPlayerobj(tedx,tedy,FIRST.dir,0);
+ }
+ else
+ SpawnPlayerobj(FIRST.x,FIRST.y,FIRST.dir,0);
+ }
+
+ else if (gamestate.teamplay == true)
+ SetupTeams();
+
+ else
+ {
+ int rand,cnt,locspawned[MAXSPAWNLOCATIONS]= {0};
+ int locsleft;
+
+ locsleft=NUMSPAWNLOCATIONS;
+ for(cnt=0; cnt<numplayers;)
+ { rand = (GameRandomNumber("net player spawn",0) % NUMSPAWNLOCATIONS);
+ if (locsleft==0)
+ {
+ int x,y;
+
+ x=SPAWNLOC[rand].x;
+ y=SPAWNLOC[rand].y;
+ FindEmptyTile(&x,&y);
+ SpawnPlayerobj(x,y,SPAWNLOC[rand].dir,cnt);
+ cnt++;
+ }
+ else if (!locspawned[rand])
+ { SpawnPlayerobj(SPAWNLOC[rand].x,SPAWNLOC[rand].y,SPAWNLOC[rand].dir,cnt);
+ locspawned[rand]=1;
+ locsleft--;
+ cnt++;
+ }
+ }
+ }
+
+ if (gamestate.battlemode == battle_Tag)
+ { int i;
+ playertype *pstate;
+
+ BATTLE_It = GameRandomNumber("tag choose",0) % numplayers;
+
+ PLAYER[BATTLE_It]->flags |= FL_DESIGNATED;
+ for(i=0; i<numplayers; i++)
+ { M_LINKSTATE(PLAYER[i],pstate);
+
+ if (i == BATTLE_It)
+ { pstate->missileweapon = pstate->oldweapon = pstate->new_weapon =
+ pstate->oldmissileweapon = pstate->weapon = wp_godhand;
+ pstate->bulletweapon = -1;
+ }
+ else
+ { pstate->missileweapon = pstate->oldweapon = pstate->new_weapon =
+ pstate->oldmissileweapon = pstate->bulletweapon = pstate->weapon = -1;
+ }
+ }
+ }
+
+ PreCachePlayers();
+}
+
+
+
+/*
+==================
+=
+= SetupMaskedWalls
+=
+==================
+*/
+
+void SetupMaskedWalls( void )
+{
+ int i,j;
+ word *map,tile;
+
+ map = mapplanes[0];
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ tile = *map++;
+ if ((tile >= 158) && (tile <= 160)) // Multi glassed walls
+ {
+ SpawnMaskedWall(i,j,mw_multi1+(tile-158),MW_MULTI|MW_BLOCKING|MW_BLOCKINGCHANGES|MW_SHOOTABLE);
+ }
+ else if ((tile >= 176) && (tile <= 178)) // Multi shot out glassed walls
+ {
+ SpawnMaskedWall(i,j,mw_multi1+(tile-176),MW_BOTTOMPASSABLE);
+ }
+ else if ((tile >= 162) && (tile <= 171))
+ {
+ switch (tile)
+ {
+ case 162:
+ SpawnMaskedWall(i,j,mw_normal1,MW_SHOOTABLE|MW_BLOCKING);
+ break;
+ case 163:
+ SpawnMaskedWall(i,j,mw_normal1,MW_BLOCKING);
+ break;
+ case 164:
+ SpawnMaskedWall(i,j,mw_normal2,MW_SHOOTABLE|MW_BLOCKING);
+ break;
+ case 165:
+ SpawnMaskedWall(i,j,mw_normal2,MW_BLOCKING);
+ break;
+ case 166:
+ SpawnMaskedWall(i,j,mw_normal3,MW_SHOOTABLE|MW_BLOCKING);
+ break;
+ case 167:
+ SpawnMaskedWall(i,j,mw_normal3,MW_BLOCKING);
+ break;
+ case 168:
+ SpawnMaskedWall(i,j,mw_singlepane,MW_SHOOTABLE|MW_BLOCKINGCHANGES|MW_BLOCKING);
+ break;
+ case 169:
+ SpawnMaskedWall(i,j,mw_singlepane,MW_BOTTOMPASSABLE);
+ break;
+ case 170:
+ SpawnMaskedWall(i,j,mw_dogwall,MW_NONDOGBLOCKING|MW_WEAPONBLOCKING);
+ break;
+ case 171:
+ SpawnMaskedWall(i,j,mw_peephole,MW_WEAPONBLOCKING|MW_BLOCKING);
+ break;
+ }
+ }
+ else if (tile == 172)
+ SpawnMaskedWall(i,j,mw_exitarch,MW_BOTTOMPASSABLE);
+ else if (tile == 173)
+ SpawnMaskedWall(i,j,mw_secretexitarch,MW_BOTTOMPASSABLE);
+ else if (tile == 174) // entry gate
+ SpawnMaskedWall(i,j,mw_entrygate,MW_BLOCKING);
+ else if (tile == 157) // hi switch off
+ SpawnMaskedWall(i,j,mw_hiswitchoff,MW_BLOCKING);
+ else if (tile == 175) // hi switch on
+ SpawnMaskedWall(i,j,mw_hiswitchon,MW_BLOCKING|MW_SWITCHON);
+ else if (tile == 179) // railing;
+ SpawnMaskedWall(i,j,mw_railing,MW_ABOVEPASSABLE|MW_MIDDLEPASSABLE);
+// else if (tile == 161) // pillar
+// SpawnMaskedWall(i,j,mw_pillar,MW_BLOCKING);
+ }
+ }
+ for (j=0; j<mapheight; j++)
+ for(i=0; i<mapwidth; i++)
+ {
+ if (IsPlatform(i,j)) // tall platform in icon plane
+ {
+ if ((MAPSPOT(i,j,0)-AREATILE>=0) || (MAPSPOT(i,j,0)==21))
+ // check to see we are not on a wall
+ {
+ int which;
+
+ which=MAPSPOT(i,j,2)-4;
+ switch (which)
+ {
+ case 0:
+ SpawnMaskedWall(i,j,mw_platform1,MW_BOTTOMPASSABLE|MW_MIDDLEPASSABLE);
+ break;
+ case 1:
+ SpawnMaskedWall(i,j,mw_platform2,MW_ABOVEPASSABLE|MW_MIDDLEPASSABLE);
+ break;
+ case 2:
+ SpawnMaskedWall(i,j,mw_platform3,MW_MIDDLEPASSABLE);
+ break;
+ case 3:
+ SpawnMaskedWall(i,j,mw_platform4,MW_BOTTOMPASSABLE);
+ break;
+ case 4:
+ SpawnMaskedWall(i,j,mw_platform5,MW_BOTTOMPASSABLE|MW_ABOVEPASSABLE);
+ break;
+ case 5:
+ SpawnMaskedWall(i,j,mw_platform6,MW_ABOVEPASSABLE);
+ break;
+ case -3:
+ SpawnMaskedWall(i,j,mw_platform7,MW_ABOVEPASSABLE);
+ break;
+ default:
+ Error ("Illegal Maskedwall platform value at x=%d y=%d\n",i,j);
+ break;
+ }
+#if 0
+ if (IsPlatform(i+1,j))
+ {
+ if ( (IsPlatform(i,j+1)) || (IsPlatform(i,j-1)) )
+ SpawnStatic(i,j,83,MAPSPOT(i,j,2));
+ }
+ else if (IsPlatform(i-1,j))
+ {
+ if ( (IsPlatform(i,j+1)) || (IsPlatform(i,j-1)) )
+ SpawnStatic(i,j,83,MAPSPOT(i,j,2));
+ }
+#endif
+ }
+ else
+ Error("You have what appears to be a platform ontop\n a wall at x=%d y=%d\n",i,j);
+ }
+ }
+}
+
+/*
+int GetAreaNumber ( int tilex, int tiley, int dir );
+void RemoveDangerWalls
+ (
+ void
+ )
+
+ {
+ int i;
+ int j;
+ word *map;
+ word tile;
+
+ map = mapplanes[ 1 ];
+
+ for( j = 0; j < mapheight; j++ )
+ {
+ for( i = 0; i < mapwidth; i++ )
+ {
+ tile = *map++;
+ switch( tile )
+ {
+ case 256:
+ case 257:
+ case 258:
+ case 259:
+ if ( MAPSPOT( i, j, 2 ) == 0 )
+ {
+ MAPSPOT( i, j, 0 ) = ( word )( GetAreaNumber( i, j,
+ ( tile - 256 ) << 1 ) + AREATILE );
+ MAPSPOT( i, j, 1 ) = 0;
+ }
+ break;
+
+ case 300:
+ case 318:
+ case 336:
+ case 354:
+ if ( MAPSPOT( i, j, 2 ) == 0 )
+ {
+ MAPSPOT( i, j, 0 ) = ( word )( GetAreaNumber( i, j,
+ ( ( tile - 300 ) / 9 ) + AREATILE ) );
+ MAPSPOT( i, j, 1 ) = 0;
+ }
+ break;
+ }
+ }
+ }
+ }
+*/
+
+
+/*
+==================
+=
+= SetupPushWalls
+=
+==================
+*/
+
+void SetupPushWalls( void )
+{
+ int i,j;
+ word *map,tile;
+ int temp;
+
+ map = mapplanes[1];
+ for(j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ tile = *map++;
+ switch(tile)
+ {
+ case 72:
+ case 73:
+ case 74:
+ case 75:
+ case 76:
+ case 77:
+ case 78:
+ case 79:
+ if (tilemap[i][j] && ActorIsWall(i,j))
+ {
+ temp=tilemap[i][j]&0x1fff;
+ tilemap[i][j] = pwallnum;
+ if (MAPSPOT(i,j,2))
+ SpawnPushWall(i,j,1,temp,tile-72,0);
+ else
+ SpawnPushWall(i,j,0,temp,tile-72,0);
+ }
+ break;
+
+ case 80: //OldPushWall
+ if (tilemap[i][j])
+ {
+ temp=tilemap[i][j]&0x1fff;
+ tilemap[i][j] = pwallnum;
+ if (MAPSPOT(i,j,2))
+ Error("You cannot link a pushwall which has no direction associated\n with it at x=%d y=%d\n",i,j);
+ else
+ SpawnPushWall(i,j,0,temp,nodir,0);
+ }
+ break;
+
+
+ case 256:
+ case 257:
+ case 258:
+ case 259:
+ if (tilemap[i][j])
+ {
+ temp=tilemap[i][j]&0x1fff;
+ tilemap[i][j] = pwallnum;
+ if (MAPSPOT(i,j,2))
+ SpawnPushWall(i,j,0,temp,(tile-256)<<1,2);
+ else
+ SpawnPushWall(i,j,0,temp,(tile-256)<<1,4);
+ }
+ else
+ Error("You have to place a turbomovewall icon on a wall at x=%d y=%d",i,j);
+ break;
+
+ case 300:
+ case 318:
+ case 336:
+ case 354:
+ if (tilemap[i][j])
+ {
+ temp=tilemap[i][j]&0x1fff;
+ tilemap[i][j] = pwallnum;
+ if (MAPSPOT(i,j,2))
+ SpawnPushWall(i,j,0,temp,(tile-300)/9,1);
+ else
+ SpawnPushWall(i,j,0,temp,(tile-300)/9,3);
+ }
+ else
+ Error("You have to place a movewall icon on a wall at x=%d y=%d",i,j);
+ break;
+ }
+ }
+ }
+}
+
+
+/*
+==================
+=
+= GetPushWallNumber
+=
+==================
+*/
+
+int GetPushWallNumber( int tx, int ty )
+{
+ int i;
+
+ for (i=0; i<pwallnum; i++)
+ if ( (pwallobjlist[i]->tilex==tx) && (pwallobjlist[i]->tiley==ty))
+ return i;
+ Error ("Could not find a push wall at x=%d y=%d\n",tx,ty);
+ return -1;
+}
+
+
+/*
+==================
+=
+= SetupPushWallLinks
+=
+==================
+*/
+void SetupPushWallLinks( void )
+{
+ int i,j;
+ word *map,tile;
+ word touchx,touchy;
+
+ map = mapplanes[1];
+ for(j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ tile = *map++;
+ switch(tile)
+ {
+ case 72:
+ case 73:
+ case 74:
+ case 75:
+ case 76:
+ case 77:
+ case 78:
+ case 79:
+ if (ActorIsPushWall(i,j))
+ {
+ if (MAPSPOT(i,j,2))
+ {
+ touchx = (word) ((MAPSPOT(i,j,2) >> 8) & 0xff);
+ touchy = (word) ((MAPSPOT(i,j,2) >> 0) & 0xff);
+ if (touchindices[touchx][touchy])
+ {
+ if (MAPSPOT(i,j+1,2)!=0)
+ {
+#if (DEVELOPMENT == 1)
+ SoftError("MAPWARNING:You left a delay for a linked push wall under the pushwall\n at x=%ld y=%ld\n",i,j);
+#endif
+ }
+ Link_To_Touchplate(touchx,touchy,ActivatePushWall,NULL,GetPushWallNumber(i,j),0);
+ }
+ else
+ Error("tried to link a pushwall at x=%d y=%d to a non-existent touchplate\n",i,j);
+ }
+ }
+ break;
+
+ case 80:
+ if (ActorIsPushWall(i,j))
+ {
+ if (MAPSPOT(i,j,2))
+ {
+ Error("You shouldn't be linking a nondirectional-push wall at x=%d y=%d\n",i,j);
+ }
+ }
+ break;
+ case 256:
+ case 257:
+ case 258:
+ case 259:
+ if (ActorIsPushWall(i,j))
+ {
+ if (MAPSPOT(i,j,2))
+ {
+ touchx = (word) ((MAPSPOT(i,j,2) >> 8) & 0xff);
+ touchy = (word) ((MAPSPOT(i,j,2) >> 0) & 0xff);
+ if (touchindices[touchx][touchy])
+ {
+ if (MAPSPOT(i,j+1,2)!=0)
+ {
+#if (DEVELOPMENT == 1)
+ SoftError("MAPWARNING:You left a delay for a linked push wall under the pushwall\n at x=%ld y=%ld\n",i,j);
+#endif
+ }
+ Link_To_Touchplate(touchx,touchy,ActivateMoveWall,NULL,GetPushWallNumber(i,j),0);
+ }
+ else
+ Error("tried to link a turbomovewall at x=%d y=%d to a non-existent touchplate\n",i,j);
+ }
+ }
+ break;
+
+ case 300:
+ case 318:
+ case 336:
+ case 354:
+ if (ActorIsPushWall(i,j))
+ {
+ if (MAPSPOT(i,j,2))
+ {
+ touchx = (word) ((MAPSPOT(i,j,2) >> 8) & 0xff);
+ touchy = (word) ((MAPSPOT(i,j,2) >> 0) & 0xff);
+ if (touchindices[touchx][touchy])
+ {
+ if (MAPSPOT(i,j+1,2)!=0)
+ {
+#if (DEVELOPMENT == 1)
+ SoftError("MAPWARNING:You left a delay for a linked push wall under the pushwall\n at x=%ld y=%ld\n",i,j);
+#endif
+ }
+ Link_To_Touchplate(touchx,touchy,ActivateMoveWall,NULL,GetPushWallNumber(i,j),0);
+ }
+ else
+ Error("tried to link a movewall at x=%d y=%d to a non-existent touchplate\n",i,j);
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
+/*
+=================
+=
+= SetupElevators
+=
+=================
+*/
+
+void SetupElevators (void)
+{
+ int j, i,x,y,starti;
+ word *map;
+ word tile;
+ elevator_t *elev;
+ doorobj_t* dptr;
+
+ map = mapplanes[1];
+ map += 4 ;
+
+ for (j = 0; j < mapheight; j++)
+ {
+ if (j == 0)
+ starti = 4;
+ else
+ starti = 0;
+
+ for (i = starti; i < mapwidth; i++)
+ { tile = *map++;
+
+ if ((tile > 89) && (tile < 98))
+ { elev = &ELEVATOR[tile-90];
+ if (!elev->sx)
+ { elev->sx = i;
+ elev->sy = j;
+ elev->doortoopen = -1;
+ elev->doorclosing = -1;
+ elev->nextaction = -1;
+ _numelevators ++;
+ }
+ else
+ { elev->dx = i;
+ elev->dy = j;
+ }
+ }
+ }
+ }
+
+ if (_numelevators && (!ELEVATOR[0].sx))
+ Error("Elevators must start at 1, dumb ass.");
+
+ for(i=0; i<_numelevators; i++)
+ { elev = &ELEVATOR[i];
+ x = elev->sx;
+ y = elev->sy;
+ for(j=0; j<doornum; j++)
+ { dptr = doorobjlist[j];
+ if (((dptr->tilex == (x+1)) && (dptr->tiley == y)) ||
+ ((dptr->tilex == (x-1)) && (dptr->tiley == y)) ||
+ ((dptr->tilex == x) && (dptr->tiley == (y+1))) ||
+ ((dptr->tilex == x) && (dptr->tiley == (y-1))))
+ { elev->door1 = j;
+ dptr->eindex = i;
+ if ((dptr->tilex == (x+1)) && (dptr->tiley == y))
+ { elev->esx = x-1;
+ elev->esy = y;
+ }
+ else if ((dptr->tilex == (x-1)) && (dptr->tiley == y))
+ { elev->esx = x+1;
+ elev->esy = y;
+ }
+ else if ((dptr->tilex == x) && (dptr->tiley == (y+1)))
+ { elev->esx = x;
+ elev->esy = y-1;
+ }
+ else if ((dptr->tilex == x) && (dptr->tiley == (y-1)))
+ { elev->esx = x;
+ elev->esy = y+1;
+ }
+ break;
+ }
+ }
+
+ x = elev->dx;
+ y = elev->dy;
+ for(j=0; j<doornum; j++)
+ { dptr = doorobjlist[j];
+ if (((dptr->tilex == (x+1)) && (dptr->tiley == y)) ||
+ ((dptr->tilex == (x-1)) && (dptr->tiley == y)) ||
+ ((dptr->tilex == x) && (dptr->tiley == (y+1))) ||
+ ((dptr->tilex == x) && (dptr->tiley == (y-1))))
+ { elev->door2 = j;
+ dptr->eindex = i;
+ dptr->flags |= DF_ELEVLOCKED;
+ if ((dptr->tilex == (x+1)) && (dptr->tiley == y))
+ { elev->edx = x-1;
+ elev->edy = y;
+ }
+ else if ((dptr->tilex == (x-1)) && (dptr->tiley == y))
+ { elev->edx = x+1;
+ elev->edy = y;
+ }
+ else if ((dptr->tilex == x) && (dptr->tiley == (y+1)))
+ { elev->edx = x;
+ elev->edy = y-1;
+ }
+ else if ((dptr->tilex == x) && (dptr->tiley == (y-1)))
+ { elev->edx = x;
+ elev->edy = y+1;
+ }
+ break;
+ }
+
+ }
+ }
+#if ((DEVELOPMENT == 1))
+#if ((ELEVATORTEST == 1))
+ for(i=0; i<_numelevators; i++)
+ Debug("\nelevator %d door1 %2d, door2 %2d",i,ELEVATOR[i].door1,ELEVATOR[i].door2);
+#endif
+#endif
+}
+
+
+/*
+=================
+=
+= SetupDoors
+=
+=================
+*/
+
+void SetupDoors (void)
+{
+ int j, i;
+ word *map;
+ word tile;
+ byte locked;
+
+ map = mapplanes[0];
+
+ for (j = 0; j < mapheight; j++)
+ for (i = 0; i < mapwidth; i++)
+ {
+ tile = *map++;
+
+ if ((tile >= 33) && (tile <= 35))
+ {
+ tilemap[i][j] = doornum;
+
+ locked=0;
+ if (MAPSPOT (i, j, 2))
+ locked = 5;
+
+ SpawnDoor (i, j, locked, (tile-33)+15);
+ }
+
+ else if ((tile > 89) && (tile < 94))
+ {
+ tilemap[i][j] = doornum;
+
+ locked = 0;
+ if (MAPSPOT (i, j, 2))
+ locked = 5;
+
+ SpawnDoor (i, j, locked, tile-90);
+ }
+
+ else if ((tile > 93) && (tile < 98))
+ {
+ Error("locked door %d being used at %d,%d",tile,i,j);
+ }
+
+
+ else if ((tile > 97) && (tile < 105))
+ {
+ tilemap[i][j] = doornum;
+
+ locked = 0;
+ if (MAPSPOT (i, j, 2))
+ locked = 5;
+
+ SpawnDoor (i, j, locked, tile-90);
+ }
+ else if ((tile >= 154) && (tile <= 156))
+ {
+ tilemap[i][j] = doornum;
+
+ locked=0;
+ if (MAPSPOT (i, j, 2))
+ locked = 5;
+
+ SpawnDoor (i, j, locked, (tile-154)+18);
+ }
+ }
+}
+
+/*
+==================
+=
+= GetDoorNumber
+=
+==================
+*/
+
+int GetDoorNumber( int tx, int ty )
+{
+ int i;
+
+ for (i=0; i<doornum; i++)
+ if ( (doorobjlist[i]->tilex==tx) && (doorobjlist[i]->tiley==ty))
+ return i;
+ Error ("Could not find a door at x=%d y=%d\n",tx,ty);
+ return -1;
+}
+
+/*
+=================
+=
+= SetupDoorLinks
+=
+=================
+*/
+
+void SetupDoorLinks (void)
+{
+ int j,
+ i,
+ k;
+ word *map;
+ int clocklinked;
+ int clockx,clocky;
+ int doornumber;
+ word touchx,
+ tile,
+ touchy;
+
+ map = mapplanes[0];
+
+ for (j = 0; j < mapheight; j++)
+ for (i = 0; i < mapwidth; i++)
+ {
+ tile = *map++;
+
+ if (MAPSPOT (i, j, 2))
+ {
+ if (IsDoor(i,j)==1)
+ {
+ clocklinked = 0;
+
+ doornumber=GetDoorNumber(i,j);
+
+ for (k = 0; k < numclocks; k++)
+ {
+ clockx = Clocks[k].points_to_tilex;
+ clocky = Clocks[k].points_to_tiley;
+
+ if ((clockx == i) && (clocky == j))
+ {
+ clocklinked = 1;
+ ClockLink (LinkedOpenDoor, LinkedCloseDoor, doornumber, k);
+ doorobjlist[doornumber]->lock = 5;
+ doorobjlist[doornumber]->flags |= DF_TIMED;
+ }
+ }
+
+ if (!clocklinked)
+ {
+ touchx = (word) ((MAPSPOT (i, j, 2) >> 8) & 0xff);
+ touchy = (word) ((MAPSPOT (i, j, 2) >> 0) & 0xff);
+
+ if (touchindices[touchx][touchy])
+ {
+ if (MAPSPOT (i, j, 1) == 192)
+ Link_To_Touchplate (touchx, touchy, LinkedCloseDoor,
+ LinkedCloseDoor, doornumber, 0);
+ else
+ Link_To_Touchplate (touchx, touchy, LinkedOpenDoor,
+ LinkedOpenDoor, doornumber, 0);
+ }
+ else
+ Error ("tried to link a door at x=%d y=%d to a non-existent touchplate",i,j);
+ }
+ }
+ }
+ }
+}
+
+
+/*
+=================
+=
+= FindTimeTile
+=
+=================
+*/
+void FindTimeTile ( int * x, int * y )
+{
+ int xx,yy;
+
+ xx=*x;
+ yy=*y;
+
+ if (!(tilemap[xx+1][yy]) && MAPSPOT(xx+1,yy,2))
+ {
+ *x=xx+1;
+ return;
+ }
+ if (!(tilemap[xx-1][yy]) && MAPSPOT(xx-1,yy,2))
+ {
+ *x=xx-1;
+ return;
+ }
+ if (!(tilemap[xx][yy+1]) && MAPSPOT(xx,yy+1,2))
+ {
+ *y=yy+1;
+ return;
+ }
+ if (!(tilemap[xx][yy-1]) && MAPSPOT(xx,yy-1,2))
+ {
+ *y=yy-1;
+ return;
+ }
+ Error ("Could not find an end time for a clock linked item\nat x=%d y=%d\n",*x,*y);
+}
+
+
+
+/*
+=================
+=
+= SetupClocks
+=
+=================
+*/
+
+void SetupClocks (void)
+{
+ int i,
+ j,
+ minutes,
+ seconds,
+ starti;
+ word *map,
+ tile,
+ mapx,
+ mapy;
+ int endtimex,
+ endtimey;
+
+
+ map = mapplanes[1];
+ map += 4 ;
+
+ for (j = 0; j < mapheight; j++)
+ {
+ if (j == 0)
+ starti = 4;
+ else
+ starti = 0;
+
+ for (i = starti; i < mapwidth; i++)
+ {
+ tile = *map++;
+
+ if (tile == 121)
+ {
+ mapx = (word) ((MAPSPOT (i, j, 2) >> 8) & 0xff);
+ mapy = (word) ((MAPSPOT (i, j, 2) >> 0) & 0xff);
+
+ minutes = (int) ((MAPSPOT (mapx, mapy, 2) >> 8) & 0xff);
+ seconds = (int) ((MAPSPOT (mapx, mapy, 2) >> 0) & 0xff);
+
+ if (seconds > 0x59)
+ Error ("seconds of clock time must be below 0x5a (60 secs) ");
+
+ seconds = 10 * (seconds/16) + (seconds % 16);
+ minutes = 60 * (10*(minutes/16) + (minutes % 16));
+
+ // total seconds
+ Clocks[numclocks].time1 = VBLCOUNTER*(seconds + minutes);
+
+ endtimex=mapx;
+ endtimey=mapy;
+
+ FindTimeTile (&endtimex, &endtimey);
+
+ minutes = (int) ((MAPSPOT (endtimex, endtimey, 2) >> 8) & 0xff);
+ seconds = (int) ((MAPSPOT (endtimex, endtimey, 2) >> 0) & 0xff);
+
+ if (seconds > 0x59)
+ Error("seconds of clock time must be below 0x5a (60 secs)");
+
+ seconds = 10 * (seconds/16) + (seconds % 16);
+ minutes = 60 * (10*(minutes/16) + (minutes % 16));
+
+ // total seconds
+ Clocks[numclocks].time2 = VBLCOUNTER * (seconds + minutes);
+ Clocks[numclocks].points_to_tilex = mapx;
+ Clocks[numclocks].points_to_tiley = mapy;
+ Clocks[numclocks].linkindex = lasttouch;
+
+ numclocks ++;
+
+ // clocks treated as virtual touchplates
+ lasttouch ++;
+ }
+ }
+ }
+}
+
+
+
+/*
+=================
+=
+= LinkElevatorDiskGroups
+=
+=================
+*/
+
+void LinkElevatorDiskGroups(void)
+{
+ objtype *diskfinder1,*temp,*master;
+ int maxplatformheight[30]= {-1};
+ int num_distinct_max_heights=0;
+ int i;
+ boolean newdiskheight;
+
+
+#define M_ISELEVDISK(actor) \
+ ((actor->obclass == diskobj) && (actor->state == &s_elevdisk))
+
+
+
+ for(diskfinder1 = FIRSTACTOR; diskfinder1; diskfinder1 = diskfinder1->next)
+ {
+ if (!M_ISELEVDISK(diskfinder1))
+ continue;
+
+ newdiskheight = true;
+ for(i=0; i<num_distinct_max_heights; i++)
+ {
+ if (maxplatformheight[i] == diskfinder1->temp2)
+ {
+ newdiskheight = false;
+ break;
+ }
+ }
+
+ if (newdiskheight == true)
+ maxplatformheight[num_distinct_max_heights++] = diskfinder1->temp2;
+
+ }
+
+
+ for(i=0; i<num_distinct_max_heights; i++)
+ {
+
+ SpawnDisk(64,64,0,true);
+ master = new;
+ master->temp2 = maxplatformheight[i];
+
+ for(temp = FIRSTACTOR; temp; temp = temp->next)
+ {
+ if (temp == master)
+ continue;
+
+ if (!M_ISELEVDISK(temp))
+ continue;
+
+ if (temp->temp2 != maxplatformheight[i])
+ continue;
+
+ temp->target = master;
+ SetTilePosition(master,temp->tilex,temp->tiley);
+ master->areanumber=AREANUMBER(master->tilex,master->tiley);
+
+ }
+ master->flags |= FL_ABP;
+ MakeActive(master);
+ }
+
+
+}
+
+
+/*
+=================
+=
+= LinkActor
+=
+=================
+*/
+
+
+void LinkActor (objtype *ob,int tilex,int tiley,
+ void (*action)(long),void (*swapaction)(long)
+ )
+{
+ word touchx,touchy;
+ int clockx,clocky;
+ int clocklinked,k;
+ wall_t * tswitch;
+
+
+ clocklinked = 0;
+ for(k=0; k<numclocks; k++)
+ {
+ clockx = Clocks[k].points_to_tilex;
+ clocky = Clocks[k].points_to_tiley;
+ if ((clockx == tilex) && (clocky == tiley))
+ {
+ clocklinked = 1;
+ ClockLink(EnableObject,DisableObject,(long)ob,k);
+ }
+ }
+
+ if (!clocklinked)
+ {
+ touchx = (word) ((MAPSPOT(tilex,tiley,2) >> 8) & 0xff);
+ touchy = (word) ((MAPSPOT(tilex,tiley,2) >> 0) & 0xff);
+ if ((MISCVARS->TOMLOC.x == touchx) && (MISCVARS->TOMLOC.y == touchy))
+ {
+ objtype *tom = (objtype*)actorat[touchx][touchy];
+ tom->whatever = ob;
+ }
+
+ else if (touchindices[touchx][touchy])
+ {
+ tswitch = (wall_t*) actorat[touchx][touchy];
+
+ if (tswitch && (ob->obclass == wallfireobj))
+ {
+ tswitch->flags |= FL_REVERSIBLE;
+ if (tswitch->flags & FL_ON)
+ ob->flags |= FL_ACTIVE;
+ }
+
+
+ if (tswitch && (tswitch->flags & FL_ON))
+ Link_To_Touchplate(touchx,touchy,swapaction,action,(long)ob,0);
+ else
+ Link_To_Touchplate(touchx,touchy,action,swapaction,(long)ob,0);
+ if (ob->obclass == gasgrateobj)
+ {
+ ob->temp1 = touchx;
+ ob->temp2 = touchy;
+ }
+ }
+ else
+ Error("tried to link an object at x=%d y=%d to a non-existent touchplate supposedly at x=%d y=%d",tilex,tiley,touchx,touchy);
+ }
+
+ if (tilemap[tilex][tiley])
+ (MAPSPOT(tilex,tiley,2))=21;
+}
+
+
+
+
+/*
+======================
+=
+= SetupInanimateActors
+=
+======================
+*/
+
+
+void SetupInanimateActors (void)
+{
+ int i,j,linked;
+ word *map,tile;
+ void (*action)(long),(*swapaction)(long);
+
+
+ map = mapplanes[1];
+
+
+ // non-linked, harmless inanimate actors
+ for(j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ tile = *map++;
+
+ switch(tile)
+ {
+
+ case 193:
+ SpawnSpring(i,j);
+ break;
+
+#if 0
+ case 460:
+// if ( gamestate.Product != ROTT_SHAREWARE )
+ {
+ SpawnNewObj(i,j,&s_wind,inertobj);
+ }
+ break;
+#endif
+
+ case 462:
+ case 463:
+ case 464:
+ case 465:
+ case 466:
+
+ SpawnDisk(i,j,tile-462,false);
+ break;
+
+ case 285:
+ case 286:
+ case 287:
+ SpawnPushColumn(i,j,tile-285,nodir,0);
+ break;
+ }
+ }
+ }
+
+
+ // linked, harmless actors
+ map = mapplanes[1];
+ for(j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ tile = *map++;
+ action = EnableObject;
+ swapaction = DisableObject;
+ linked = (MAPSPOT(i,j,2) && (!IsPlatform(i,j)));
+
+
+ switch(tile)
+ {
+
+ case 140:
+ case 141:
+ case 142:
+ case 143:
+
+ if ((!BATTLEMODE) || (gamestate.BattleOptions.SpawnDangers))
+ {
+ PreCacheActor(wallfireobj,0);
+ SpawnWallfire(i,j,tile-140);
+ if (!linked)
+ {
+ new->flags |= FL_ACTIVE;
+ if (tilemap[i][j])
+ MAPSPOT(i,j,2) = 21;
+ }
+ else
+ LinkActor(new,i,j,action,swapaction);
+ }
+ else if (tilemap[i][j])
+ MAPSPOT(i,j,2) = 21;
+
+ break;
+
+
+
+
+
+ case 303:
+ case 304:
+ case 305:
+ SpawnPushColumn(i,j,tile-303,east,linked);
+ swapaction = NULL;
+ if (linked)
+ LinkActor(new,i,j,action,swapaction);
+
+ break;
+
+ case 321:
+ case 322:
+ case 323:
+ SpawnPushColumn(i,j,tile-321,north,linked);
+ swapaction = NULL;
+ if (linked)
+ LinkActor(new,i,j,action,swapaction);
+
+ break;
+
+ case 339:
+ case 340:
+ case 341:
+ SpawnPushColumn(i,j,tile-339,west,linked);
+ swapaction = NULL;
+ if (linked)
+ LinkActor(new,i,j,action,swapaction);
+
+ break;
+
+ case 357:
+ case 358:
+ case 359:
+ SpawnPushColumn(i,j,tile-357,south,linked);
+ swapaction = NULL;
+ if (linked)
+ LinkActor(new,i,j,action,swapaction);
+
+ break;
+
+
+ }
+
+ }
+ }
+
+ //harmful actors
+
+ if ((!BATTLEMODE) || (gamestate.BattleOptions.SpawnDangers))
+ {
+ map = mapplanes[1];
+ for(j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ tile = *map++;
+ action = EnableObject;
+ swapaction = DisableObject;
+ linked = (MAPSPOT(i,j,2) && (!IsPlatform(i,j)));
+
+ switch(tile)
+ {
+ case 89:
+ SpawnFourWayGun(i,j);
+ break;
+
+
+ case 156:
+ case 157:
+ SpawnBlade(i,j,nodir,0,tile-156);
+ if (linked)
+ LinkActor(new,i,j,action,swapaction);
+
+ break;
+
+ case 174:
+ case 175:
+ SpawnBlade(i,j,nodir,1,tile-174);
+ if (linked)
+ LinkActor(new,i,j,action,swapaction);
+
+ break;
+
+
+
+ case 412:
+ SpawnSpear(i,j,0);
+ break;
+
+ case 430:
+ SpawnSpear(i,j,1);
+ break;
+
+ case 413:
+ SpawnCrushingColumn(i,j,1); //down
+ break;
+
+ case 431:
+ SpawnCrushingColumn(i,j,0); // up
+ break;
+
+
+ case 192:
+ if (!tilemap[i][j])
+ {
+ SpawnNewObj(i,j,&s_gas1,gasgrateobj);
+ PreCacheActor(gasgrateobj,0);
+ new->flags |= FL_ABP;
+ MakeActive(new);
+ swapaction = NULL;
+ if (linked)
+ LinkActor(new,i,j,action,swapaction);
+
+ }
+ break;
+
+
+ case 301:
+ case 302:
+ SpawnBlade(i,j,east,tile-301,0);
+ if (!linked)
+ new->flags |= FL_ACTIVE;
+ else
+ LinkActor(new,i,j,action,swapaction);
+
+ break;
+
+ case 319:
+ case 320:
+ SpawnBlade(i,j,north,tile-319,0);
+ if (!linked)
+ new->flags |= FL_ACTIVE;
+ else
+ LinkActor(new,i,j,action,swapaction);
+
+ break;
+
+ case 337:
+ case 338:
+ SpawnBlade(i,j,west,tile-337,0);
+ if (!linked)
+ new->flags |= FL_ACTIVE;
+ else
+ LinkActor(new,i,j,action,swapaction);
+
+ break;
+
+ case 355:
+ case 356:
+ SpawnBlade(i,j,south,tile-355,0);
+ if (!linked)
+ new->flags |= FL_ACTIVE;
+ else
+ LinkActor(new,i,j,action,swapaction);
+
+ break;
+
+ case 372:
+ SpawnFirejet(i,j,nodir,0);
+ break;
+
+ case 373:
+ case 374:
+ case 375:
+ case 376:
+ SpawnFirejet(i,j,tile-373,0);
+ break;
+
+ case 390:
+ SpawnFirejet(i,j,nodir,1);
+ break;
+
+ case 391:
+ case 392:
+ case 393:
+ case 394:
+ SpawnFirejet(i,j,tile-391,1);
+ break;
+
+ case 278:
+ case 279:
+ case 280:
+ case 281:
+ SpawnBoulder(i,j,tile-278);
+ if (!linked)
+ new->flags |= FL_ACTIVE;
+ else
+ LinkActor(new,i,j,action,swapaction);
+
+ break;
+
+ }
+
+
+ }
+ }
+ }
+
+ LinkElevatorDiskGroups();
+
+}
+
+
+/*
+===================
+=
+= FixTiles
+=
+===================
+*/
+
+void FixTiles(void)
+{
+ word *map,tile;
+ int i,j;
+
+ map = mapplanes[1];
+ for(j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ tile = *map++;
+ switch(tile)
+ {
+ case 140:
+ case 141:
+ case 142:
+ case 143:
+ case 192:
+ case 278:
+ case 279:
+ case 280:
+ case 281:
+ if (tilemap[i][j])
+ (MAPSPOT(i,j,2))=21;
+ break;
+ }
+ }
+ }
+
+}
+
+
+void Illuminate(void)
+{ statobj_t*temp;
+
+ if (lightsource==0)
+ return;
+ for(temp=FIRSTSTAT; temp; temp=temp->statnext)
+ if (temp->flags & FL_LIGHTON)
+ TurnOnLight(temp->tilex,temp->tiley);
+}
+
+
+/*
+=================
+=
+= SetupLights
+=
+=================
+*/
+void SetupLights(void)
+{
+ int i,j,touchx,touchy;
+ wall_t *tswitch;
+ word *map,tile;
+ int starti;
+
+// Initialize Lights in Area
+
+ memset(LightsInArea,0,sizeof(LightsInArea));
+
+ map = mapplanes[1];
+ map+=5;
+
+ for (j=0; j<mapheight; j++)
+ {
+ if (j==0)
+ starti=5;
+ else
+ starti=0;
+ for(i=starti; i<mapwidth; i++)
+ {
+ tile= *map++;
+
+
+
+ switch (tile)
+ {
+
+ // Add light sourcing to these objects
+
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 42:
+ case 63:
+ case 64:
+ sprites[i][j]->flags |= FL_LIGHTON;
+ break;
+
+ case 28:
+ case 43:
+ if (MAPSPOT(i,j,2))
+ {
+ touchx = (word) ((MAPSPOT(i,j,2) >> 8) & 0xff);
+ touchy = (word) ((MAPSPOT(i,j,2) >> 0) & 0xff);
+ tswitch = (wall_t*) actorat[touchx][touchy];
+
+ if (tswitch && (tswitch->which == WALL))
+ { tswitch->flags |= FL_REVERSIBLE;
+ if (!(tswitch->flags & FL_ON))
+ { sprites[i][j]->shapenum --;
+ if (touchindices[touchx][touchy])
+ { Link_To_Touchplate(touchx,touchy,ActivateLight,DeactivateLight,(long)(sprites[i][j]),0);
+ sprites[i][j]->linked_to = touchindices[touchx][touchy]-1;
+ }
+ else
+ Error("tried to link a light at x=%d y=%d to a non-existent touchplate",i,j);
+ }
+ else
+ { if (touchindices[touchx][touchy])
+ { Link_To_Touchplate(touchx,touchy,DeactivateLight,ActivateLight,(long)(sprites[i][j]),0);
+ sprites[i][j]->linked_to = touchindices[touchx][touchy]-1;
+ }
+ else
+ Error("tried to link a light at x=%d y=%d to a non-existent touchplate",i,j);
+ sprites[i][j]->flags |= FL_LIGHTON;
+ }
+ }
+ else
+ { if (touchindices[touchx][touchy])
+ { Link_To_Touchplate(touchx,touchy,DeactivateLight,ActivateLight,(long)(sprites[i][j]),0);
+ sprites[i][j]->linked_to = touchindices[touchx][touchy]-1;
+ }
+ else
+ Error("tried to link a light at x=%d y=%d to a non-existent touchplate",i,j);
+ sprites[i][j]->flags |= FL_LIGHTON;
+ }
+
+ }
+ else
+ sprites[i][j]->flags |= FL_LIGHTON;
+
+ break;
+ }
+ }
+ }
+}
+
+/*
+==================
+=
+= PrintMapStats
+=
+==================
+*/
+void PrintMapStats (void)
+{
+ int size;
+ int total;
+
+ if (MAPSTATS==false)
+ return;
+
+ OpenMapDebug();
+
+ total=0;
+ MapDebug("MAP STATS Map Number %d\n",gamestate.mapon);
+ MapDebug("=======================\n");
+ size=pwallnum*sizeof(pwallobj_t);
+ total+=size;
+ MapDebug("Number of PushWalls : %4d size = %6d\n",pwallnum,size);
+ size=maskednum*sizeof(maskedwallobj_t);
+ total+=size;
+ MapDebug("Number of MaskedWalls : %4d size = %6d\n",maskednum,size);
+ size=doornum*sizeof(doorobj_t);
+ total+=size;
+ MapDebug("Number of Doors : %4d size = %6d\n",doornum,size);
+ size=lasttouch*sizeof(touchplatetype);
+ total+=size;
+ MapDebug("Number of TouchPlates : %4d size = %6d\n",lasttouch,size);
+ size=_numelevators*sizeof(elevator_t);
+ total+=size;
+ MapDebug("Number of Elevators : %4d size = %6d\n",_numelevators,size);
+ size=statcount*sizeof(statobj_t);
+ total+=size;
+ MapDebug("Number of Sprites : %4d size = %6d\n",statcount,size);
+ size=objcount*sizeof(objtype);
+ total+=size;
+ MapDebug("Number of Actors : %4d size = %6d\n",objcount,size);
+ MapDebug("Number of Clocks : %4d\n",numclocks);
+ MapDebug("\nTotal size of level : %6d\n",total);
+}
+
+
+boolean IsWeapon(int tile)
+{
+ if ((tile >= 46) && (tile <= 56))
+ return true;
+
+ return false;
+
+}
+
+
+char *WeaponName(int tile)
+{
+ switch(tile)
+ {
+ case 46:
+ return "Bat ";
+ break;
+
+ case 47:
+ return "Knife ";
+ break;
+
+ case 48:
+ return "Double Pistol ";
+ break;
+
+ case 49:
+ return "MP40 ";
+ break;
+
+ case 50:
+ return "Bazooka ";
+ break;
+
+ case 51:
+ return "Firebomb ";
+ break;
+
+ case 52:
+ return "Heatseeker ";
+ break;
+
+ case 53:
+ return "Drunk Missile ";
+ break;
+
+ case 54:
+ return "Flamewall ";
+ break;
+
+ case 55:
+ return "Split Missile ";
+ break;
+
+ case 56:
+ return "KES ";
+ break;
+ }
+ return " ";
+}
+
+
+
+int GetLumpForTile(int tile)
+{
+ int wallstart;
+ int exitstart;
+
+ wallstart=W_GetNumForName("WALLSTRT");
+ exitstart=W_GetNumForName("EXITSTRT");
+ elevatorstart = W_GetNumForName("ELEVSTRT");
+
+ if ((tile >= 1) && (tile <= 32))
+ {
+ return (tile + wallstart);
+ }
+ else if ((tile >= 36) && (tile <= 45))
+ {
+ return (tile + wallstart - 3);
+ }
+ else if (tile == 46)
+ {
+ return (wallstart + 74);
+ }
+ else if ((tile >= 47) && (tile <= 48))
+ {
+ return (tile + exitstart - 46);
+ }
+ else if ((tile >= 49) && (tile <= 71))
+ {
+ return (tile + wallstart - 8);
+ }
+ else if ((tile >= 72) && (tile <= 79))
+ {
+ return (tile - 72 + elevatorstart + 1);
+ }
+ else if ((tile >= 80) && (tile <= 89))
+ {
+ return (tile + wallstart - 16);
+ }
+ return -1;
+}
+
+
+
+
+#if (DEVELOPMENT == 1)
+
+
+/*
+==================
+=
+= Insane Dump
+=
+==================
+*/
+
+void InsaneDump(void)
+{
+ int i,j,level;
+ word *map,tile;
+ int tally[1000];
+ int inlevel[1000][10];
+
+ if (TILESTATS==false)
+ return;
+
+ OpenMapDebug();
+
+
+// WALLS
+ memset(tally,0,sizeof(tally));
+ memset(inlevel,0,sizeof(inlevel));
+ MapDebug("=======================\n");
+ MapDebug("= WALLS\n");
+ MapDebug("=======================\n");
+ mapheight = mapwidth = 128;
+ BATTLEMODE = 1;
+ for(level=0; level<8; level ++)
+ {
+ GetEpisode(level);
+ LoadROTTMap(level);
+ map = mapplanes[0];
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ { tile = *map++;
+ if (IsWall(i,j)==true)
+ { tally[tile]++;
+ inlevel[tile][level]=1;
+ }
+
+ }
+ }
+ }
+
+ MapDebug("Wall # Frequency Levels\n");
+ MapDebug("----------------------------\n");
+ for (i=0; i<1000; i++)
+ if (i < 90)
+ { MapDebug("%4d %4d %s",i,tally[i],
+ W_GetNameForNum(GetLumpForTile(i)));
+ MapDebug(" ");
+ for(level=0; level < 10; level ++)
+ if (inlevel[i][level])
+ MapDebug("%d,",level);
+ MapDebug("\n");
+ }
+
+
+
+
+
+// Doors
+ memset(tally,0,sizeof(tally));
+ memset(inlevel,0,sizeof(inlevel));
+ MapDebug("=======================\n");
+ MapDebug("= DOORS\n");
+ MapDebug("=======================\n");
+ for(level=0; level<10; level ++)
+ {
+ GetEpisode(level);
+ LoadROTTMap(level);
+ map = mapplanes[0];
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ { tile = *map++;
+ if (IsDoor(i,j)==true)
+ { tally[tile]++;
+ inlevel[tile][level]=1;
+ }
+
+ }
+ }
+ }
+
+ MapDebug("Door # Frequency Levels\n");
+ MapDebug("----------------------------\n");
+ for (i=0; i<1000; i++)
+ if (tally[i]!=0)
+ { MapDebug("%4d %4d ",i,tally[i]);
+ for(level=0; level < 10; level ++)
+ if (inlevel[i][level])
+ MapDebug("%d,",level);
+ MapDebug("\n");
+
+ }
+
+// MaskedWalls
+ memset(tally,0,sizeof(tally));
+ memset(inlevel,0,sizeof(inlevel));
+ MapDebug("=======================\n");
+ MapDebug("= MASKED WALLS\n");
+ MapDebug("=======================\n");
+ for(level=0; level<10; level ++)
+ {
+ GetEpisode(level);
+ LoadROTTMap(level);
+ map = mapplanes[0];
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ { tile = *map++;
+ if ((IsMaskedWall(i,j)) && (!IsPlatform(i,j)))
+ { tally[tile]++;
+ inlevel[tile][level]=1;
+ }
+
+ }
+ }
+ }
+
+ MapDebug("MWall # Frequency Levels\n");
+ MapDebug("----------------------------\n");
+ for (i=0; i<1000; i++)
+ if (tally[i]!=0)
+ { MapDebug("%4d %4d ",i,tally[i]);
+ for(level=0; level < 10; level ++)
+ if (inlevel[i][level])
+ MapDebug("%d,",level);
+ MapDebug("\n");
+
+ }
+
+}
+
+#endif
+
+/*
+==================
+=
+= PrintTileStats
+=
+==================
+*/
+void PrintTileStats (void)
+{
+ int i,j;
+ word *map;
+ int easytotal;
+ int hardtotal;
+ int tally[1000];
+
+ if (TILESTATS==false)
+ return;
+
+ OpenMapDebug();
+
+ MapDebug("TILE STATS Map Number %d\n",gamestate.mapon);
+ MapDebug("=======================\n\n");
+
+
+// Weapons
+ memset(tally,0,sizeof(tally));
+ MapDebug("=======================\n");
+ MapDebug("= WEAPONS\n");
+ MapDebug("=======================\n");
+ map = mapplanes[1];
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ if (IsWeapon(*map))
+ MapDebug("\n %s at %3d,%3d",WeaponName(*map),i,j);
+ map++;
+ }
+ }
+ MapDebug("\n\n");
+// WALLS
+ memset(tally,0,sizeof(tally));
+ MapDebug("=======================\n");
+ MapDebug("= WALLS\n");
+ MapDebug("=======================\n");
+ map = mapplanes[0];
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ if (IsWall(i,j)==true)
+ tally[(*map)]++;
+ map++;
+ }
+ }
+ MapDebug("Wall # Frequency\n");
+ MapDebug("-----------------------\n");
+ for (i=0; i<1000; i++)
+ if (tally[i]!=0)
+ MapDebug(" %4d %4d\n",i,tally[i]);
+
+// Doors
+ memset(tally,0,sizeof(tally));
+ MapDebug("=======================\n");
+ MapDebug("= DOORS\n");
+ MapDebug("=======================\n");
+ map = mapplanes[0];
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ if (IsDoor(i,j)==true)
+ tally[(*map)]++;
+ map++;
+ }
+ }
+ MapDebug("Door # Frequency\n");
+ MapDebug("-----------------------\n");
+ for (i=0; i<1000; i++)
+ if (tally[i]!=0)
+ MapDebug(" %4d %4d\n",i,tally[i]);
+
+// MaskedWalls
+ memset(tally,0,sizeof(tally));
+ MapDebug("=======================\n");
+ MapDebug("= MASKEDWALLS\n");
+ MapDebug("=======================\n");
+ map = mapplanes[0];
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ if (IsMaskedWall(i,j)==true)
+ if (IsPlatform(i,j)==false)
+ tally[(*map)]++;
+ map++;
+ }
+ }
+ MapDebug("Mwall # Frequency\n");
+ MapDebug("-----------------------\n");
+ for (i=0; i<1000; i++)
+ if (tally[i]!=0)
+ MapDebug(" %4d %4d\n",i,tally[i]);
+// Platforms
+ memset(tally,0,sizeof(tally));
+ MapDebug("=======================\n");
+ MapDebug("= PLATFORMS\n");
+ MapDebug("=======================\n");
+ map = mapplanes[2];
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ if (IsPlatform(i,j)==true)
+ tally[(*map)]++;
+ map++;
+ }
+ }
+ MapDebug("Pform # Frequency\n");
+ MapDebug("-----------------------\n");
+ for (i=0; i<1000; i++)
+ if (tally[i]!=0)
+ MapDebug(" %4d %4d\n",i,tally[i]);
+
+// Actors
+ memset(tally,0,sizeof(tally));
+ MapDebug("=======================\n");
+ MapDebug("= ACTORS\n");
+ MapDebug("=======================\n");
+ map = mapplanes[1];
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ if ((*map)>0)
+ tally[(*map)]++;
+ map++;
+ }
+ }
+
+// Low Guards
+ easytotal=0;
+ hardtotal=0;
+ for (i=108; i<=119; i++)
+ easytotal+=tally[i];
+ for (i=126; i<=137; i++)
+ hardtotal+=tally[i];
+ MapDebug("\nLowGuards\n");
+ MapDebug("-----------------------\n");
+ MapDebug("EasyTotal=%4d\n",easytotal);
+ MapDebug("HardTotal=%4d\n",hardtotal);
+ MapDebug(" Total=%4d\n",easytotal+hardtotal);
+
+// Sneaky Low Guards
+ easytotal=0;
+ hardtotal=0;
+ for (i=120; i<=120; i++)
+ easytotal+=tally[i];
+ for (i=138; i<=138; i++)
+ hardtotal+=tally[i];
+ MapDebug("\nSneakyLowGuards\n");
+ MapDebug("-----------------------\n");
+ MapDebug("EasyTotal=%4d\n",easytotal);
+ MapDebug("HardTotal=%4d\n",hardtotal);
+ MapDebug(" Total=%4d\n",easytotal+hardtotal);
+
+// High Guards
+ easytotal=0;
+ hardtotal=0;
+ for (i=144; i<=155; i++)
+ easytotal+=tally[i];
+ for (i=162; i<=173; i++)
+ hardtotal+=tally[i];
+ MapDebug("\nHighGuards\n");
+ MapDebug("-----------------------\n");
+ MapDebug("EasyTotal=%4d\n",easytotal);
+ MapDebug("HardTotal=%4d\n",hardtotal);
+ MapDebug(" Total=%4d\n",easytotal+hardtotal);
+
+// OverPatrol Guards
+ easytotal=0;
+ hardtotal=0;
+ for (i=216; i<=227; i++)
+ easytotal+=tally[i];
+ for (i=234; i<=245; i++)
+ hardtotal+=tally[i];
+ MapDebug("\nOverPatrolGuards\n");
+ MapDebug("-----------------------\n");
+ MapDebug("EasyTotal=%4d\n",easytotal);
+ MapDebug("HardTotal=%4d\n",hardtotal);
+ MapDebug(" Total=%4d\n",easytotal+hardtotal);
+
+// Strike Guards
+ easytotal=0;
+ hardtotal=0;
+ for (i=180; i<=191; i++)
+ easytotal+=tally[i];
+ for (i=198; i<=204; i++)
+ hardtotal+=tally[i];
+ MapDebug("\nStrikeGuards\n");
+ MapDebug("-----------------------\n");
+ MapDebug("EasyTotal=%4d\n",easytotal);
+ MapDebug("HardTotal=%4d\n",hardtotal);
+ MapDebug(" Total=%4d\n",easytotal+hardtotal);
+
+// TriadEnforcer Guards
+ easytotal=0;
+ hardtotal=0;
+ for (i=288; i<=299; i++)
+ easytotal+=tally[i];
+ for (i=306; i<=317; i++)
+ hardtotal+=tally[i];
+ MapDebug("\nTriadEnforcer Guards\n");
+ MapDebug("-----------------------\n");
+ MapDebug("EasyTotal=%4d\n",easytotal);
+ MapDebug("HardTotal=%4d\n",hardtotal);
+ MapDebug(" Total=%4d\n",easytotal+hardtotal);
+
+// Lightning Guards
+ easytotal=0;
+ hardtotal=0;
+ for (i=324; i<=335; i++)
+ easytotal+=tally[i];
+ for (i=342; i<=353; i++)
+ hardtotal+=tally[i];
+ MapDebug("\nLightningGuards\n");
+ MapDebug("-----------------------\n");
+ MapDebug("EasyTotal=%4d\n",easytotal);
+ MapDebug("HardTotal=%4d\n",hardtotal);
+ MapDebug(" Total=%4d\n",easytotal+hardtotal);
+
+// Random Actors
+ easytotal=0;
+ hardtotal=0;
+ for (i=122; i<=125; i++)
+ easytotal+=tally[i];
+ MapDebug("\nRandom Actors\n");
+ MapDebug("-----------------------\n");
+ MapDebug(" Total=%4d\n",easytotal);
+
+// Monks
+ easytotal=0;
+ hardtotal=0;
+ for (i=360; i<=371; i++)
+ easytotal+=tally[i];
+ for (i=378; i<=389; i++)
+ hardtotal+=tally[i];
+ MapDebug("\nMonks\n");
+ MapDebug("-----------------------\n");
+ MapDebug("EasyTotal=%4d\n",easytotal);
+ MapDebug("HardTotal=%4d\n",hardtotal);
+ MapDebug(" Total=%4d\n",easytotal+hardtotal);
+
+// Fire Monks
+ easytotal=0;
+ hardtotal=0;
+ for (i=396; i<=407; i++)
+ easytotal+=tally[i];
+ for (i=414; i<=425; i++)
+ hardtotal+=tally[i];
+ MapDebug("\nFire Monks\n");
+ MapDebug("-----------------------\n");
+ MapDebug("EasyTotal=%4d\n",easytotal);
+ MapDebug("HardTotal=%4d\n",hardtotal);
+ MapDebug(" Total=%4d\n",easytotal+hardtotal);
+
+// Robo Guards
+ easytotal=0;
+ hardtotal=0;
+ for (i=158; i<=161; i++)
+ easytotal+=tally[i];
+ for (i=176; i<=179; i++)
+ hardtotal+=tally[i];
+ MapDebug("\nRoboGuards\n");
+ MapDebug("-----------------------\n");
+ MapDebug("EasyTotal=%4d\n",easytotal);
+ MapDebug("HardTotal=%4d\n",hardtotal);
+ MapDebug(" Total=%4d\n",easytotal+hardtotal);
+
+// Ballistikrafts
+ easytotal=0;
+ hardtotal=0;
+ for (i=408; i<=411; i++)
+ easytotal+=tally[i];
+ for (i=426; i<=429; i++)
+ hardtotal+=tally[i];
+ MapDebug("\nBallistikrafts\n");
+ MapDebug("-----------------------\n");
+ MapDebug("EasyTotal=%4d\n",easytotal);
+ MapDebug("HardTotal=%4d\n",hardtotal);
+ MapDebug(" Total=%4d\n",easytotal+hardtotal);
+
+// Boulders
+ easytotal=0;
+ hardtotal=0;
+ for (i=278; i<=281; i++)
+ easytotal+=tally[i];
+ for (i=395; i<=395; i++)
+ hardtotal+=tally[i];
+ MapDebug("\nBoulders\n");
+ MapDebug("-----------------------\n");
+ MapDebug("Boulders=%4d\n",easytotal);
+ MapDebug("BoulderHoles=%4d\n",hardtotal);
+
+// PushColumns
+ easytotal=0;
+ hardtotal=0;
+ for (i=285; i<=287; i++)
+ easytotal+=tally[i];
+ for (i=303; i<=305; i++)
+ easytotal+=tally[i];
+ for (i=321; i<=323; i++)
+ easytotal+=tally[i];
+ for (i=339; i<=341; i++)
+ easytotal+=tally[i];
+ for (i=357; i<=359; i++)
+ easytotal+=tally[i];
+ MapDebug("\nPushColumns\n");
+ MapDebug("-----------------------\n");
+ MapDebug(" Total=%4d\n",easytotal);
+
+// Gun Emplacements
+ easytotal=0;
+ hardtotal=0;
+ for (i=194; i<=197; i++)
+ easytotal+=tally[i];
+ for (i=212; i<=215; i++)
+ hardtotal+=tally[i];
+ MapDebug("\nGun Emplacements\n");
+ MapDebug("-----------------------\n");
+ MapDebug("EasyTotal=%4d\n",easytotal);
+ MapDebug("HardTotal=%4d\n",hardtotal);
+ MapDebug(" Total=%4d\n",easytotal+hardtotal);
+
+// 4-way guns
+ easytotal=0;
+ hardtotal=0;
+ for (i=89; i<=89; i++)
+ easytotal+=tally[i];
+ for (i=211; i<=211; i++)
+ hardtotal+=tally[i];
+ MapDebug("\n4-way guns\n");
+ MapDebug("-----------------------\n");
+ MapDebug("EasyTotal=%4d\n",easytotal);
+ MapDebug("HardTotal=%4d\n",hardtotal);
+ MapDebug(" Total=%4d\n",easytotal+hardtotal);
+
+// Stabbers from above
+ MapDebug("\nStabbers from above\n");
+ MapDebug("-----------------------\n");
+ MapDebug(" Total=%4d\n",tally[412]);
+
+// Stabbers from below
+ MapDebug("\nStabbers from below\n");
+ MapDebug("-----------------------\n");
+ MapDebug(" Total=%4d\n",tally[430]);
+
+// Crushing pillar from above
+ MapDebug("\nCrushing pillar from above\n");
+ MapDebug("-----------------------\n");
+ MapDebug(" Total=%4d\n",tally[413]);
+
+// Crushing pillar from below
+ MapDebug("\nCrushing pillar from below\n");
+ MapDebug("-----------------------\n");
+ MapDebug(" Total=%4d\n",tally[431]);
+
+// Above Spinner
+ MapDebug("\nAbove Spinner\n");
+ MapDebug("-----------------------\n");
+ MapDebug(" Total=%4d\n",tally[156]);
+
+// Ground Spinner
+ MapDebug("\nGround Spinner\n");
+ MapDebug("-----------------------\n");
+ MapDebug(" Total=%4d\n",tally[174]);
+
+// Spinner from above
+ MapDebug("\nSpinner from above\n");
+ MapDebug("-----------------------\n");
+ MapDebug(" Total=%4d\n",tally[157]);
+
+// Spinner from below
+ MapDebug("\nSpinner from below\n");
+ MapDebug("-----------------------\n");
+ MapDebug(" Total=%4d\n",tally[175]);
+
+// Bosses
+ easytotal=0;
+ for (i=99; i<=103; i++)
+ easytotal+=tally[i];
+ MapDebug("\nBosses\n");
+ MapDebug("-----------------------\n");
+ MapDebug(" Total=%4d\n",easytotal);
+
+// Spring Boards
+ MapDebug("\nSpring Boards\n");
+ MapDebug("-----------------------\n");
+ MapDebug(" Total=%4d\n",tally[193]);
+
+// Above FlameJets
+ easytotal=0;
+ hardtotal=0;
+ for (i=372; i<=376; i++)
+ easytotal+=tally[i];
+ for (i=390; i<=394; i++)
+ hardtotal+=tally[i];
+ MapDebug("\nFlameJets\n");
+ MapDebug("-----------------------\n");
+ MapDebug(" Above=%4d\n",easytotal);
+ MapDebug(" Ground=%4d\n",hardtotal);
+
+// Fire Chutes
+ easytotal=0;
+ for (i=140; i<=143; i++)
+ easytotal+=tally[i];
+ MapDebug("\nFireChutes\n");
+ MapDebug("-----------------------\n");
+ MapDebug(" Total=%4d\n",easytotal);
+
+// Sprites
+ MapDebug("=======================\n");
+ MapDebug("= SPRITES\n");
+ MapDebug("=======================\n");
+ MapDebug("Sprite # Frequency\n");
+ MapDebug("-----------------------\n");
+ for (i=1; i<=72; i++)
+ if (tally[i]!=0)
+ MapDebug(" %4d %4d\n",i,tally[i]);
+ for (i=210; i<=210; i++)
+ if (tally[i]!=0)
+ MapDebug(" %4d %4d\n",i,tally[i]);
+ for (i=228; i<=233; i++)
+ if (tally[i]!=0)
+ MapDebug(" %4d %4d\n",i,tally[i]);
+ for (i=246; i<=255; i++)
+ if (tally[i]!=0)
+ MapDebug(" %4d %4d\n",i,tally[i]);
+ for (i=260; i<=273; i++)
+ if (tally[i]!=0)
+ MapDebug(" %4d %4d\n",i,tally[i]);
+ for (i=282; i<=284; i++)
+ if (tally[i]!=0)
+ MapDebug(" %4d %4d\n",i,tally[i]);
+}
+
+//***************************************************************************
+//
+// GetSongForLevel - returns song to play for current level
+//
+//***************************************************************************
+int GetSongForLevel ( void )
+{
+ int i;
+ int num;
+
+ for (i=0; i<mapwidth; i++)
+ {
+ num = MAPSPOT(i,0,2);
+ if ( (num>>8) == 0xba )
+ return (num&0xff);
+ }
+// Error("GetSongForLevel: could not find song in level %ld\n",gamestate.mapon);
+// return -1;
+ return 0;
+}
+
+/*
+==================
+=
+= DoSharewareConversionBackgroundPlane
+=
+==================
+*/
+void DoSharewareConversionBackgroundPlane (void)
+{
+ int i,j;
+ word * map;
+
+
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ map=&(mapplanes[0][MAPSIZE*(j)+(i)]);
+ switch (*map)
+ {
+
+ // Tom Face
+ case 45:
+ *map=44;
+ break;
+ // Doors
+ case 90:
+ case 92:
+ case 93:
+ case 98:
+ case 99:
+ case 100:
+ *map=91;
+ break;
+ case 103:
+ case 104:
+ *map=101;
+ break;
+ case 154:
+ *map=33;
+ break;
+ case 155:
+ *map=34;
+ break;
+ case 156:
+ *map=35;
+ break;
+
+ //locked doors
+ case 94:
+ *map = 101;
+ *(&(mapplanes[1][MAPSIZE*(j)+(i)]))=29;
+ break;
+ case 95:
+ *map = 101;
+ *(&(mapplanes[1][MAPSIZE*(j)+(i)]))=30;
+ break;
+ case 96:
+ *map = 101;
+ *(&(mapplanes[1][MAPSIZE*(j)+(i)]))=31;
+ break;
+ case 97:
+ *map = 101;
+ *(&(mapplanes[1][MAPSIZE*(j)+(i)]))=32;
+ break;
+ // Tall pillar
+ case 161:
+ *map=0;
+ break;
+ // Masked Walls
+ case 162:
+ case 166:
+ *map=164;
+ break;
+ case 163:
+ case 167:
+ case 170:
+ case 171:
+ *map=165;
+ break;
+
+ // Floors and Ceilings
+ case 180:
+ case 183:
+ case 184:
+ *map=181;
+ break;
+ case 198:
+ case 201:
+ case 202:
+ *map=199;
+ break;
+ case 188:
+ *map=187;
+ break;
+ case 206:
+ *map=205;
+ break;
+ case 190:
+ *map=191;
+ break;
+ case 208:
+ *map=209;
+ break;
+ case 192:
+ case 193:
+ case 194:
+ case 195:
+ *map=189;
+ break;
+ case 210:
+ case 211:
+ case 212:
+ case 213:
+ *map=207;
+ break;
+ // Skys
+ case 237:
+ case 238:
+ case 239:
+ *map=234;
+ break;
+ // Animating walls
+ case 107:
+ *map=106;
+ break;
+ case 228:
+ case 229:
+ case 230:
+ case 242:
+ *map=21;
+ break;
+ case 233:
+ *map=44;
+ break;
+ case 232:
+ *map=231;
+ break;
+ }
+ }
+ }
+}
+
+
+/*
+========================================
+=
+= DoLowMemoryConversionBackgroundPlane
+=
+========================================
+*/
+void DoLowMemoryConversionBackgroundPlane (void)
+{
+ int i,j;
+ word * map;
+
+
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ map=&(mapplanes[0][MAPSIZE*(j)+(i)]);
+ switch (*map)
+ {
+ //Walls
+
+ case 2:
+ case 3:
+ case 4:
+ *map = 1;
+ break;
+
+ case 6:
+ case 7:
+ case 8:
+ *map = 5;
+ break;
+
+ case 14:
+ case 15:
+ case 16:
+ *map = 13;
+ break;
+
+ case 18:
+ case 19:
+ case 20:
+ *map = 17;
+ break;
+
+ case 26:
+ case 27:
+ case 28:
+ *map = 25;
+ break;
+
+ case 30:
+ case 31:
+ case 32:
+ *map = 29;
+ break;
+
+#if 0
+ case 37:
+ case 38:
+ case 39:
+ *map = 36;
+ break;
+
+ case 41:
+ case 42:
+ case 43:
+ *map = 40;
+ break;
+#endif
+
+ case 50:
+ case 51:
+ case 52:
+ *map = 49;
+ break;
+
+#if 0
+ case 55:
+ case 56:
+ case 57:
+ *map = 54;
+ break;
+
+ case 59:
+ case 60:
+ case 61:
+ *map = 58;
+ break;
+#endif
+
+ case 66:
+ case 67:
+ case 68:
+ *map = 65;
+ break;
+
+ case 70:
+ case 71:
+ *map = 69;
+ break;
+
+ case 81:
+ case 82:
+ case 84:
+ *map = 83;
+ break;
+
+ // Masked Walls
+ case 158:
+ case 159:
+ case 160:
+ case 168:
+ case 169:
+ case 176:
+ case 178:
+ *map=177;
+ break;
+ case 162:
+ case 163:
+ case 164:
+ case 166:
+ case 167:
+ *map=165;
+ break;
+
+ //Doors
+ case 90:
+ case 91:
+ case 92:
+ case 93:
+ case 98:
+ case 99:
+ case 100:
+ case 101:
+ case 103:
+ case 104:
+ case 33:
+ case 34:
+ case 35:
+ case 154:
+ case 155:
+ case 156:
+ *map = 101;
+ break;
+
+ //Animating Walls
+ case 22:
+ case 23:
+ case 24:
+ case 228:
+ case 229:
+ case 230:
+ case 231:
+ case 232:
+ case 242:
+ case 243:
+ case 244:
+ *map = 21;
+ break;
+ case 233:
+ *map = 44;
+ break;
+
+#if 0
+ //Skys
+ case 234:
+ case 235:
+ case 236:
+ case 237:
+ case 238:
+ case 239:
+ *map=(*(&(mapplanes[0][MAPSIZE*(0)+(0)]))) + 18;
+ break;
+#endif
+ }
+ }
+ }
+}
+
+
+/*
+========================================
+=
+= DoLowMemoryConversionIconPlane
+=
+========================================
+*/
+void DoLowMemoryConversionIconPlane (void)
+{
+#if 0
+ int i,j;
+ word * map;
+
+
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ map=&(mapplanes[2][MAPSIZE*(j)+(i)]);
+ switch (*map)
+ {
+ case 13:
+ *(&(mapplanes[0][MAPSIZE*(j)+(i)]))=21;
+ *map=0;
+ break;
+ }
+ }
+ }
+#endif
+}
+
+
+
+/*
+========================================
+=
+= DoLowMemoryConversionForegroundPlane
+=
+========================================
+*/
+
+void DoLowMemoryConversionForegroundPlane (void)
+{
+ int i,j;
+ word * map;
+
+
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ map=&MAPSPOT(i,j,1);
+ switch (*map)
+ {
+ // light sourcing
+ case 139:
+ *map=0;
+ break;
+
+ //sprites
+ case 42:
+ case 43:
+ case 63:
+ case 64:
+ *map = 43;
+ break;
+
+ case 246:
+ case 247:
+ case 248:
+ case 264:
+ case 265:
+ case 267:
+ case 283:
+ *map = 266;
+ break;
+
+ //lightning
+ case 377:
+ *map = 0;
+ break;
+
+ // actor guards
+
+ // normal low guards
+ case 108:
+ case 109:
+ case 110:
+ case 111:
+ case 112:
+ case 113:
+ case 114:
+ case 115:
+ case 116:
+ case 117:
+ case 118:
+ case 119:
+
+ case 126:
+ case 127:
+ case 128:
+ case 129:
+ case 130:
+ case 131:
+ case 132:
+ case 133:
+ case 134:
+ case 135:
+ case 136:
+ case 137:
+ (*map)+=216;
+ break;
+
+ // sneaky low guards
+ case 120:
+ case 138:
+ *map = 0;
+ break;
+
+ // normal over patrol
+ case 216:
+ case 217:
+ case 218:
+ case 219:
+ case 220:
+ case 221:
+ case 222:
+ case 223:
+ case 224:
+ case 225:
+ case 226:
+ case 227:
+
+
+ case 234:
+ case 235:
+ case 236:
+ case 237:
+ case 238:
+ case 239:
+ case 240:
+ case 241:
+ case 242:
+ case 243:
+ case 244:
+ case 245:
+ (*map)-=36;
+ break;
+
+ //environment dangers
+
+#if (SHAREWARE==0)
+ case 412: //spears to firejets
+ *map = 372;
+ break;
+
+ case 430:
+ *map = 390;
+ break;
+
+ case 413: //cylinders down to firejets
+ *map = 372;
+ break;
+#endif
+
+ case 156:
+ case 157:
+ *map = 372; //spinblade stabbers to firejets
+ break;
+
+ case 174:
+ case 175:
+ *map = 390;
+ break;
+
+ case 301: // directional spin blades
+ *map = 373;
+ break;
+
+ case 319: // directional spin blades
+ *map = 374;
+ break;
+
+ case 337: // directional spin blades
+ *map = 375;
+ break;
+
+ case 355: // directional spin blades
+ *map = 376;
+ break;
+
+ case 302: // directional spin blades
+ *map = 391;
+ break;
+
+ case 320: // directional spin blades
+ *map = 392;
+ break;
+
+ case 338: // directional spin blades
+ *map = 393;
+ break;
+
+ case 356: // directional spin blades
+ *map = 394;
+ break;
+
+ case 194: // directional emplacements to four-way
+ case 195: // easy
+ case 196:
+ case 197:
+ *map = 89;
+ break;
+
+ case 212: // hard
+ case 213:
+ case 214:
+ case 215:
+ *map = 211;
+ break;
+
+ }
+ }
+ }
+}
+
+
+/*
+==================
+=
+= DoSharewareConversionForegroundPlane
+=
+==================
+*/
+void DoSharewareConversionForegroundPlane (void)
+{
+ int i,j;
+ word * map;
+
+
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ map=&(mapplanes[1][MAPSIZE*(j)+(i)]);
+ switch (*map)
+ {
+ case 32: // Crystal Key
+ case 47: // Knife
+ case 65: // DIP BALL D
+ case 66: // DIP BALL I
+ case 67: // DIP BALL P
+ case 99: // Boss
+ case 100: // Boss
+ case 101: // Boss
+ case 102: // Boss
+ case 103: // Boss
+ case 210: // Scott's head
+ case 278: // Boulder
+ case 279: // Boulder
+ case 280: // Boulder
+ case 281: // Boulder
+ case 395: // Boulder
+ *map=0;
+ break;
+ case 41: // 3-UP to 1-UP
+ *map=40;
+ break;
+ case 46: // Bat
+ *map=50;
+ break;
+ case 55: // Split Missile
+ *map=52;
+ break;
+ case 56: // KES
+ *map=53;
+ break;
+ case 253: // Dog Mode
+ *map=254;
+ break;
+ case 262: // Tom Larva
+ *map=263;
+ break;
+ }
+ }
+ }
+}
+
+/*
+========================================
+=
+= DoRegisterConversionBackgroundPlane
+=
+========================================
+*/
+void DoRegisterConversionBackgroundPlane (void)
+{
+ int i,j;
+ word * map;
+
+
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ map=&(mapplanes[0][MAPSIZE*(j)+(i)]);
+ switch (*map)
+ {
+ //locked doors
+
+ case 94:
+ *map = 101;
+ *(&(mapplanes[1][MAPSIZE*(j)+(i)]))=29;
+ break;
+ case 95:
+ *map = 101;
+ *(&(mapplanes[1][MAPSIZE*(j)+(i)]))=30;
+ break;
+ case 96:
+ *map = 101;
+ *(&(mapplanes[1][MAPSIZE*(j)+(i)]))=31;
+ break;
+ case 97:
+ *map = 101;
+ *(&(mapplanes[1][MAPSIZE*(j)+(i)]))=32;
+ break;
+
+ case 232:
+ *map = 231; //map chains to machinery
+ break;
+
+ case 228:
+ *map = 230; //map gray water to blue water
+ break;
+
+ }
+ }
+ }
+}
+
+
+
+/*
+========================================
+=
+= DoRegisterConversionForegroundPlane
+=
+========================================
+*/
+void DoRegisterConversionForegroundPlane (void)
+{
+// int i,j;
+// word * map;
+
+
+#if 0
+ for (j=0; j<mapheight; j++)
+ {
+ for(i=0; i<mapwidth; i++)
+ {
+ map=&MAPSPOT(i,j,1);
+ switch (*map)
+ {
+ //sprites
+ case 42:
+ case 43:
+ case 63:
+ case 64:
+ *map = 43;
+ break;
+
+ }
+ }
+ }
+#endif
+}
+
+/*
+==================
+=
+= DoSharewareConversion
+=
+==================
+*/
+void DoSharewareConversion (void)
+{
+ DoSharewareConversionBackgroundPlane ();
+ DoSharewareConversionForegroundPlane ();
+}
+
+
+/*
+==================
+=
+= DoRegisterConversion
+=
+==================
+*/
+void DoRegisterConversion (void)
+{
+ DoRegisterConversionBackgroundPlane ();
+ DoRegisterConversionForegroundPlane ();
+}
+
+/*
+=======================
+=
+= DoPanicMapping
+=
+=======================
+*/
+boolean DoPanicMapping (void)
+{
+ if ((lowmemory==true) && (modemgame==false) && (demorecord==false) && (demoplayback==false))
+ return true;
+ else
+ return false;
+}
+
+/*
+=======================
+=
+= DoLowMemoryConversion
+=
+=======================
+*/
+void DoLowMemoryConversion (void)
+{
+ DoLowMemoryConversionBackgroundPlane ();
+ if ((modemgame==false) && (demorecord==false) && (demoplayback==false))
+ DoLowMemoryConversionForegroundPlane ();
+ DoLowMemoryConversionIconPlane ();
+}
+
+extern objtype * enemiesToRes = NULL;
+extern int freeSlot = 0;
+void SetupZomROTTStuff()
+{
+ if (enemiesToRes)
+ {
+ FreeUpResurrectList();
+ }
+ enemiesToRes = calloc(sizeof(objtype), gamestate.killtotal);
+ memset(enemiesToRes, 0, sizeof(enemiesToRes));
+
+ freeSlot = 0;
+}
+
+/*
+==================
+=
+= SetupGameLevel
+=
+==================
+*/
+
+extern boolean enableZomROTT;
+
+void SetupGameLevel (void)
+{
+ int crud;
+ int i;
+
+#if 0
+ mapwidth = mapheight = 128;
+
+ InsaneDump();
+ /*
+ for(i=0;i<11;i++)
+ {GetEpisode(i);
+ LoadROTTMap(i);
+ MapDebug("\n//================================//");
+ MapDebug("\n// SHAREWARE LEVEL %d //",i);
+ MapDebug("\n//================================//\n\n");
+
+ PrintTileStats();
+ }
+ */
+ Error("okay");
+#endif
+
+ insetupgame=true;
+
+ InitializeRNG ();
+
+ if ((demoplayback==true) || (demorecord==true))
+ SetRNGindex ( 0 );
+
+ if (gamestate.randomseed!=-1)
+ SetRNGindex ( gamestate.randomseed );
+
+ if (tedlevel)
+ {
+ GetEpisode (tedlevelnum);
+ LoadROTTMap(tedlevelnum);
+ gamestate.mapon=tedlevelnum;
+ }
+ else
+ {
+ GetEpisode (gamestate.mapon);
+ LoadROTTMap(gamestate.mapon);
+ }
+ if (DoPanicMapping())
+ {
+ DoLowMemoryConversion();
+ }
+ if ( gamestate.Product == ROTT_SHAREWARE )
+ {
+ DoSharewareConversion ();
+ }
+ else
+ {
+ DoRegisterConversion ();
+ }
+ if ( (NewGame) || (lastlevelloaded!=gamestate.mapon) )
+ {
+ SetupPreCache();
+ lastlevelloaded=gamestate.mapon;
+ MU_StartSong(song_level);
+ }
+ shapestart = W_GetNumForName("SHAPSTRT");
+ shapestop = W_GetNumForName("SHAPSTOP");
+ gunsstart=W_GetNumForName("GUNSTART");
+
+ playstate = ex_stillplaying;
+ SNAKELEVEL = 0;
+ whichpath = 0;
+
+ // som of the code / calls below need bufferofs & friends to point
+ // to to the real screen, not the stretch buffer
+ DisableScreenStretch();//bna++ shut off streech mode
+
+ InitializePlayerstates();
+
+ ResetCheatCodes();
+
+ gamestate.killtotal = gamestate.killcount = 0;
+ gamestate.secrettotal = gamestate.secretcount = 0;
+ gamestate.treasuretotal = gamestate.treasurecount = 0;
+ gamestate.supertotal = gamestate.supercount = 0;
+ gamestate.healthtotal = gamestate.healthcount = 0;
+ gamestate.missiletotal = gamestate.missilecount = 0;
+ gamestate.democratictotal = gamestate.democraticcount = 0;
+ gamestate.planttotal = gamestate.plantcount = 0;
+ gamestate.DODEMOCRATICBONUS1 = true;
+ gamestate.DOGROUNDZEROBONUS = false;
+
+ if (gamestate.mapon == 30)
+ SNAKELEVEL = 1;
+ else if (gamestate.mapon == 32)
+ SNAKELEVEL = 2;
+ else if (gamestate.mapon == 33)
+ SNAKELEVEL = 3;
+
+ InitAreas();
+ InitDoorList();
+ InitElevators();
+ if (loadedgame==false)
+ {
+ InitStaticList ();
+ InitActorList();
+ }
+ memset (tilemap,0,sizeof(tilemap));
+ memset (actorat,0,sizeof(actorat));
+ memset (sprites,0,sizeof(sprites));
+ memset (mapseen,0,sizeof(mapseen));
+ memset (LightsInArea,0,sizeof(LightsInArea));
+
+ PrintTileStats();
+
+ SetupLightLevels();
+
+ crud=(word)MAPSPOT(0,0,1);
+ if ((crud>=90) && (crud<=97))
+ {
+ levelheight=crud-89;
+ maxheight = (levelheight << 6)-32;
+ nominalheight = maxheight-32;
+ }
+ else if ((crud>=450) && (crud<=457))
+ {
+ levelheight=crud-450+9;
+ maxheight = (levelheight << 6)-32;
+ nominalheight = maxheight-32;
+ }
+ else
+ Error("You must specify a valid height sprite icon at (2,0) on map %d\n",gamestate.mapon);
+
+ /*
+ if ( ( BATTLEMODE ) && ( !gamestate.BattleOptions.SpawnDangers ) )
+ {
+ RemoveDangerWalls();
+ }
+ */
+// pheight=maxheight-32;
+ CountAreaTiles();
+ SetupWalls();
+
+ SetupClocks();
+ SetupAnimatedWalls();
+
+ if (loadedgame==false)
+ {
+ SetupSwitches();
+ SetupStatics ();
+ SetupMaskedWalls();
+ SetupDoors();
+ SetupPushWalls();
+ SetupPlayers();
+ if (!BATTLEMODE)
+ {
+ SetupActors();
+ SetupRandomActors();
+ }
+ SetupElevators();
+ SetupDoorLinks();
+ SetupPushWallLinks();
+ FixDoorAreaNumbers();
+ FixMaskedWallAreaNumbers();
+ SetupWindows();
+ SetupLights();
+ SetupInanimateActors();
+ }
+ else {
+ FixTiles();
+ }
+ if (enableZomROTT)
+ {
+ SetupZomROTTStuff();
+ }
+
+ if (gamestate.SpawnEluder || gamestate.SpawnDeluder)
+ {
+//MED
+ for (i=0; i<25; i++)
+ RespawnEluder();
+ }
+
+
+ if ( ( BATTLEMODE ) && ( MapSpecials & MAP_SPECIAL_TOGGLE_PUSHWALLS ) )
+ {
+ ActivateAllPushWalls();
+ }
+ Illuminate();
+
+ if (SNAKELEVEL == 1)
+ SetupSnakePath();
+
+ LoftSprites();
+
+ SetPlaneViewSize();
+ if (loadedgame==false)
+ {
+ ConnectAreas();
+#if (DEVELOPMENT == 1)
+#if (PRECACHETEST == 1)
+ SoftError("Start PreCaching\n");
+#endif
+#endif
+#if (DEVELOPMENT == 1)
+ PrintMapStats();
+#endif
+ PreCache();
+#if (DEVELOPMENT == 1)
+#if (PRECACHETEST == 1)
+ SoftError("Done PreCaching\n");
+#endif
+#endif
+ SetupPlayScreen();
+ SetupScreen(false);
+ }
+
+ if (BATTLEMODE) {
+ SetModemLightLevel ( gamestate.BattleOptions.LightLevel );
+ }
+
+ if (player != NULL) {
+ for (i=0; i<100; i++) {
+ UpdateLightLevel(player->areanumber);
+ }
+ }
+
+ insetupgame=false;
+
+ tedlevel = false; // turn it off once we have done any ted stuff
+
+ EnableScreenStretch();
+}
+
+
+void InitializePlayerstates(void)
+{ int i;
+ playertype * pstate;
+
+ if (NewGame || (gamestate.mapon == 0) || tedlevel)
+ { for(i=0; i<numplayers; i++)
+ InitializeWeapons(&PLAYERSTATE[i]);
+ }
+
+ for(i=0; i<numplayers; i++)
+ {
+ pstate=&PLAYERSTATE[i];
+ if (
+ (pstate->missileweapon == wp_godhand)
+#if (SHAREWARE == 0)
+ ||
+ (pstate->missileweapon == wp_dog)
+#endif
+ )
+ {
+ pstate->weapon=pstate->new_weapon=pstate->oldweapon;
+ pstate->missileweapon = pstate->oldmissileweapon;
+
+ }
+
+ ResetPlayerstate(pstate);
+ }
+
+ NewGame = false;
+
+}
+
+
+void SetupSnakePath(void)
+{
+#if (SHAREWARE == 0)
+ int i,j;
+ word *map,tile;
+
+ map = mapplanes[1];
+
+ for(j=0; j<mapheight; j++)
+ for(i=0; i<mapwidth; i++)
+ { tile = *map++;
+ if ((tile >= 72) && (tile <= 79) && (!tilemap[i][j]))
+ { SNAKEPATH[whichpath].x = i;
+ SNAKEPATH[whichpath].y = j;
+ whichpath ++;
+ }
+
+ }
+#endif
+}
+
+
+void SetupRandomActors(void)
+{ int i,j;
+ word *map,tile;
+ int starti,totalrandom=0,count=0,ambush,locindex,orig;
+ byte actorpresent[10]= {0},index=0,randomtype,used[100]= {0};
+ _2Dpoint randloc[100];
+
+
+ map = mapplanes[1];
+ map+=5;
+ for(i=0; i<10; i++)
+ { if (RANDOMACTORTYPE[i])
+ actorpresent[index++]=i;
+ }
+
+
+ if (!index)
+ return;
+
+ for (j=0; j<mapheight; j++)
+ { if (j==0)
+ starti=5;
+ else
+ starti=0;
+ for(i=starti; i<mapwidth; i++)
+ { tile= *map++;
+
+ if ((tile >= 122) && (tile <= 125))
+ { randloc[totalrandom].x = i;
+ randloc[totalrandom].y = j;
+ totalrandom++;
+ if (totalrandom >= 100)
+ Error("Max random actors (100) exceeded");
+ }
+
+ }
+ }
+
+ orig = totalrandom;
+ switch(gamestate.difficulty)
+ {
+ case gd_baby:
+ totalrandom = 7*totalrandom/10;
+ break;
+
+ case gd_easy:
+ totalrandom = 8*totalrandom/10;
+ break;
+
+ case gd_medium:
+ totalrandom = 9*totalrandom/10;
+ break;
+
+ }
+
+
+ while(count<totalrandom)
+ { locindex = (GameRandomNumber("rand loc index",0) % orig);
+
+ if (!used[locindex])
+ { randomtype = actorpresent[GameRandomNumber("SetupRandomActors",0) % index];
+ ambush = (GameRandomNumber("rand actor",0) < 128);
+ i = randloc[locindex].x;
+ j = randloc[locindex].y;
+ tile = mapplanes[1][j*mapwidth + i];
+ SpawnStand(randomtype,i,j,tile-122,ambush);
+ used[locindex] = 1;
+ PreCacheActor(randomtype,0);
+ count++;
+ }
+ }
+
+}
+
+void SetupActors(void)
+{
+ int i,j;
+ word *map,tile;
+ int starti;
+
+
+ //GetRainActors();
+
+ map = mapplanes[1];
+ map+=5;
+
+ for (j=0; j<mapheight; j++)
+ {
+ if (j==0)
+ starti=5;
+ else
+ starti=0;
+ for(i=starti; i<mapwidth; i++)
+ {
+ tile= *map++;
+
+ switch(tile)
+ {
+
+ case 126:
+ case 127:
+ case 128:
+ case 129:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 108:
+ case 109:
+ case 110:
+ case 111:
+ SpawnStand(lowguardobj,i,j,tile-108,0);
+ break;
+
+
+
+
+ case 130:
+ case 131:
+ case 132:
+ case 133:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 112:
+ case 113:
+ case 114:
+ case 115:
+ SpawnPatrol(lowguardobj,i,j,tile-112);
+ break;
+
+ case 134:
+ case 135:
+ case 136:
+ case 137:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 116:
+ case 117:
+ case 118:
+ case 119:
+ SpawnStand(lowguardobj,i,j,tile-116,1);
+ break;
+
+ case 138:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 120:
+ SpawnSneaky(i,j);
+ break;
+
+ case 162:
+ case 163:
+ case 164:
+ case 165:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 144:
+ case 145:
+ case 146:
+ case 147:
+ SpawnStand(highguardobj,i,j,tile-144,0);
+ break;
+
+ case 170:
+ case 171:
+ case 172:
+ case 173:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 152:
+ case 153:
+ case 154:
+ case 155:
+ SpawnStand(highguardobj,i,j,tile-152,1);
+ break;
+
+
+
+ case 166:
+ case 167:
+ case 168:
+ case 169:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 148:
+ case 149:
+ case 150:
+ case 151:
+ SpawnPatrol(highguardobj,i,j,tile-148);
+ break;
+
+ case 176:
+ case 177:
+ case 178:
+ case 179:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 158:
+ case 159:
+ case 160:
+ case 161:
+ SpawnPatrol(roboguardobj,i,j,tile-158);
+ break;
+
+ case 212:
+ case 213:
+ case 214:
+ case 215:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 194:
+ case 195:
+ case 196:
+ case 197:
+ SpawnGunThingy(patrolgunobj,i,j,tile-194);
+ break;
+
+ case 198:
+ case 199:
+ case 200:
+ case 201:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 180:
+ case 181:
+ case 182:
+ case 183:
+ SpawnStand(strikeguardobj,i,j,tile-180,0);
+ break;
+
+ case 206:
+ case 207:
+ case 208:
+ case 209:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 188:
+ case 189:
+ case 190:
+ case 191:
+ SpawnStand(strikeguardobj,i,j,tile-188,1);
+ break;
+
+ case 202:
+ case 203:
+ case 204:
+ case 205:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 184:
+ case 185:
+ case 186:
+ case 187:
+ SpawnPatrol(strikeguardobj,i,j,tile-184);
+ break;
+
+ case 234:
+ case 235:
+ case 236:
+ case 237:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 216:
+ case 217:
+ case 218:
+ case 219:
+ SpawnStand(overpatrolobj,i,j,tile-216,0);
+ break;
+
+ case 242:
+ case 243:
+ case 244:
+ case 245:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 224:
+ case 225:
+ case 226:
+ case 227:
+ SpawnStand(overpatrolobj,i,j,tile-224,1);
+ break;
+
+ case 238:
+ case 239:
+ case 240:
+ case 241:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 220:
+ case 221:
+ case 222:
+ case 223:
+ SpawnPatrol(overpatrolobj,i,j,tile-220);
+ break;
+ case 306:
+ case 307:
+ case 308:
+ case 309:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 288:
+ case 289:
+ case 290:
+ case 291:
+ SpawnStand(triadenforcerobj,i,j,tile-288,0);
+ break;
+
+ case 314:
+ case 315:
+ case 316:
+ case 317:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 296:
+ case 297:
+ case 298:
+ case 299:
+ SpawnStand(triadenforcerobj,i,j,tile-296,1);
+ break;
+
+ case 310:
+ case 311:
+ case 312:
+ case 313:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 292:
+ case 293:
+ case 294:
+ case 295:
+ SpawnPatrol(triadenforcerobj,i,j,tile-292);
+ break;
+
+ case 342:
+ case 343:
+ case 344:
+ case 345:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 324:
+ case 325:
+ case 326:
+ case 327:
+ SpawnStand(blitzguardobj,i,j,tile-324,0);
+ break;
+
+ case 350:
+ case 351:
+ case 352:
+ case 353:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 332:
+ case 333:
+ case 334:
+ case 335:
+ SpawnStand(blitzguardobj,i,j,tile-332,1);
+ break;
+
+ case 346:
+ case 347:
+ case 348:
+ case 349:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+ case 328:
+ case 329:
+ case 330:
+ case 331:
+ SpawnPatrol(blitzguardobj,i,j,tile-328);
+ break;
+
+ case 378:
+ case 379:
+ case 380:
+ case 381:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 360:
+ case 361:
+ case 362:
+ case 363:
+ SpawnStand(deathmonkobj,i,j,tile-360,0);
+ break;
+
+ case 386:
+ case 387:
+ case 388:
+ case 389:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 368:
+ case 369:
+ case 370:
+ case 371:
+ SpawnStand(deathmonkobj,i,j,tile-368,1);
+ break;
+
+ case 382:
+ case 383:
+ case 384:
+ case 385:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 364:
+ case 365:
+ case 366:
+ case 367:
+ SpawnPatrol(deathmonkobj,i,j,tile-364);
+ break;
+
+ case 414:
+ case 415:
+ case 416:
+ case 417:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 396:
+ case 397:
+ case 398:
+ case 399:
+ SpawnStand(dfiremonkobj,i,j,tile-396,0);
+ break;
+
+
+
+ case 422:
+ case 423:
+ case 424:
+ case 425:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+
+ case 404:
+ case 405:
+ case 406:
+ case 407:
+ SpawnStand(dfiremonkobj,i,j,tile-404,1);
+ break;
+
+ case 418:
+ case 419:
+ case 420:
+ case 421:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 400:
+ case 401:
+ case 402:
+ case 403:
+ SpawnPatrol(dfiremonkobj,i,j,tile-400);
+ break;
+
+ case 99:
+ SpawnStand(b_darianobj,i,j,tile-99,0);
+ break;
+ case 100:
+ SpawnStand(b_heinrichobj,i,j,tile-100,0);
+ break;
+ case 101:
+ SpawnStand(b_darkmonkobj,i,j,tile-101,0);
+ MISCVARS->TOMLOC.x = i;
+ MISCVARS->TOMLOC.y = j;
+ break;
+ case 102:
+ SpawnMultiSpriteActor(b_robobossobj,i,j,tile-102);
+ break;
+
+ case 103:
+ SpawnSnake(i,j);
+ break;
+
+ case 426:
+ case 427:
+ case 428:
+ case 429:
+ if (gamestate.difficulty < gd_hard)
+ break;
+ tile -= 18;
+
+ case 408:
+ case 409:
+ case 410:
+ case 411:
+ SpawnPatrol(wallopobj,i,j,tile-408);
+ break;
+
+
+ }
+ }
+ }
+}
+
+void SetupStatics(void)
+{
+ int i,j,spawnz;
+ word *map,tile;
+ int starti;
+
+ map = mapplanes[1];
+ map+=5;
+
+ BATTLE_NumCollectorItems = 0;
+ for (j=0; j<mapheight; j++)
+ {
+ if (j==0)
+ starti=5;
+ else
+ starti=0;
+ for(i=starti; i<mapwidth; i++)
+ {
+ tile= *map++;
+ spawnz = (MAPSPOT(i,j,2))?(MAPSPOT(i,j,2)):(-1);
+
+ if ( gamestate.BattleOptions.RandomWeapons )
+ {
+ int num;
+
+ switch( tile )
+ {
+ case 46:
+ case 48:
+ case 49:
+ case 50:
+ case 51:
+ case 52:
+ case 53:
+ case 54:
+ case 55:
+ case 56:
+ if ( gamestate.Product == ROTT_SHAREWARE )
+ {
+ num = ( GameRandomNumber( "Random Weapon", 0 ) % 7 );
+ tile = SharewareWeaponTiles[ num ];
+ }
+ else
+ {
+ num = ( GameRandomNumber( "Random Weapon", 1 ) % 10 );
+ tile = NormalWeaponTiles[ num ];
+ }
+ break;
+ }
+ }
+
+ switch (tile)
+ {
+
+ // Add light sourcing to these objects
+
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 42:
+ case 43:
+ case 63:
+ case 64:
+ SpawnStatic(i,j,tile-23,spawnz);
+ break;
+
+ case 44:
+ SpawnStatic(i,j,tile-23,spawnz);
+ if (loadedgame == false)
+ {
+ gamestate.healthtotal ++;
+ gamestate.democratictotal ++;
+ }
+ break;
+
+
+ case 36:
+ case 37:
+ case 38:
+ case 39:
+ SpawnStatic(i,j,tile-23,spawnz);
+ if (loadedgame == false)
+ gamestate.healthtotal ++;
+ break;
+
+ case 29:
+ case 30:
+ case 31:
+ case 32:
+ if (IsDoor (i, j) == 0)
+ {
+ if ( BATTLEMODE )
+ {
+ // Spawn empty table
+ SpawnStatic( i, j, 247 - 246 + 57, spawnz );
+ }
+ else
+ {
+ // Spawn key table
+ SpawnStatic( i, j, tile - 23, spawnz );
+ }
+ }
+ break;
+
+ case 33:
+ case 34:
+ case 35:
+ case 40:
+ case 41:
+ case 45:
+ SpawnStatic(i,j,tile-23,spawnz);
+ break;
+
+ case 46:
+#if (SHAREWARE == 1)
+ Error("\n tried to spawn excalibat at %d,%d in shareware !",i,j);
+#endif
+
+
+ SD_PreCacheSoundGroup(SD_EXCALIBOUNCESND,SD_EXCALIBLASTSND);
+
+
+ PreCacheGroup(W_GetNumForName("EXBAT1"),
+ W_GetNumForName("EXBAT7"),
+ cache_patch_t);
+
+
+
+ SpawnStatic(i,j,tile-23,spawnz);
+ if (loadedgame == false)
+ gamestate.missiletotal ++;
+ break;
+ case 47:
+ PreCacheGroup(W_GetNumForName("KNIFE1"),
+ W_GetNumForName("KNIFE10"),
+ cache_patch_t);
+ PreCacheGroup(W_GetNumForName("ESTATUE1"),
+ W_GetNumForName("ESTATUE8"),
+ cache_patch_t);
+
+ SpawnStatic(i,j,tile-23,spawnz);
+ break;
+
+ case 48:
+ SD_PreCacheSound(SD_ATKTWOPISTOLSND);
+
+ if ((locplayerstate->player == 1) || (locplayerstate->player == 3))
+ PreCacheGroup(W_GetNumForName("RFPIST1"),
+ W_GetNumForName("LFPIST3"),
+ cache_patch_t);
+
+ else if (locplayerstate->player == 2)
+ PreCacheGroup(W_GetNumForName("RBMPIST1"),
+ W_GetNumForName("LBMPIST3"),
+ cache_patch_t);
+
+ else
+ PreCacheGroup(W_GetNumForName("RMPIST1"),
+ W_GetNumForName("LMPIST3"),
+ cache_patch_t);
+
+ SpawnStatic(i,j,tile-23,spawnz);
+
+ break;
+ case 49:
+
+ SD_PreCacheSound(SD_ATKMP40SND);
+ PreCacheGroup(W_GetNumForName("MP401"),
+ W_GetNumForName("MP403"),
+ cache_patch_t);
+ SpawnStatic(i,j,tile-23,spawnz);
+ break;
+
+ case 50:
+ SD_PreCacheSound(SD_MISSILEHITSND);
+ SD_PreCacheSound(SD_MISSILEFLYSND);
+ SD_PreCacheSound(SD_BAZOOKAFIRESND);
+ PreCacheGroup(W_GetNumForName("BAZOOKA1"),
+ W_GetNumForName("BAZOOKA4"),
+ cache_patch_t);
+ SpawnStatic(i,j,tile-23,spawnz);
+ if (loadedgame == false)
+ gamestate.missiletotal ++;
+ break;
+ case 51:
+
+
+ SD_PreCacheSound(SD_MISSILEHITSND);
+ SD_PreCacheSound(SD_MISSILEFLYSND);
+ SD_PreCacheSound(SD_FIREBOMBFIRESND);
+ PreCacheGroup(W_GetNumForName("FBOMB1"),
+ W_GetNumForName("FBOMB4"),
+ cache_patch_t);
+ SpawnStatic(i,j,tile-23,spawnz);
+ if (loadedgame == false)
+ gamestate.missiletotal ++;
+ break;
+ case 52:
+ SD_PreCacheSound(SD_MISSILEHITSND);
+ SD_PreCacheSound(SD_MISSILEFLYSND);
+ SD_PreCacheSound(SD_HEATSEEKFIRESND);
+ PreCacheGroup(W_GetNumForName("HSEEK1"),
+ W_GetNumForName("HSEEK4"),
+ cache_patch_t);
+ SpawnStatic(i,j,tile-23,spawnz);
+ if (loadedgame == false)
+ gamestate.missiletotal ++;
+ break;
+ case 53:
+ SD_PreCacheSound(SD_MISSILEHITSND);
+ SD_PreCacheSound(SD_MISSILEFLYSND);
+ SD_PreCacheSound(SD_DRUNKFIRESND);
+ PreCacheGroup(W_GetNumForName("DRUNK1"),
+ W_GetNumForName("DRUNK4"),
+ cache_patch_t);
+ SpawnStatic(i,j,tile-23,spawnz);
+ if (loadedgame == false)
+ gamestate.missiletotal ++;
+ break;
+ case 54:
+ SD_PreCacheSound(SD_MISSILEHITSND);
+ SD_PreCacheSound(SD_MISSILEFLYSND);
+ SD_PreCacheSound(SD_FLAMEWALLFIRESND);
+ SD_PreCacheSound(SD_FLAMEWALLSND);
+ PreCacheGroup(W_GetNumForName("FIREW1"),
+ W_GetNumForName("FIREW3"),
+ cache_patch_t);
+ PreCacheGroup(W_GetNumForName("FWALL1"),
+ W_GetNumForName("FWALL15"),
+ cache_patch_t);
+ PreCacheGroup(W_GetNumForName("SKEL1"),
+ W_GetNumForName("SKEL48"),
+ cache_patch_t);
+ SpawnStatic(i,j,tile-23,spawnz);
+ if (loadedgame == false)
+ gamestate.missiletotal ++;
+ break;
+ case 55:
+#if (SHAREWARE == 1)
+ Error("\n tried to spawn split missile at %d,%d in shareware !",i,j);
+#endif
+ SD_PreCacheSound(SD_MISSILEHITSND);
+ SD_PreCacheSound(SD_MISSILEFLYSND);
+ SD_PreCacheSound(SD_SPLITFIRESND);
+ SD_PreCacheSound(SD_SPLITSND);
+ PreCacheGroup(W_GetNumForName("SPLIT1"),
+ W_GetNumForName("SPLIT4"),
+ cache_patch_t);
+ SpawnStatic(i,j,tile-23,spawnz);
+ if (loadedgame == false)
+ gamestate.missiletotal ++;
+ break;
+ case 56:
+#if (SHAREWARE == 1)
+ Error("\n tried to spawn kes at %d,%d in shareware !",i,j);
+#endif
+
+
+
+ SD_PreCacheSound(SD_GRAVSND);
+ SD_PreCacheSound(SD_GRAVHITSND);
+ SD_PreCacheSound(SD_GRAVFIRESND);
+ SD_PreCacheSound(SD_GRAVBUILDSND);
+
+ PreCacheGroup(W_GetNumForName("KES1"),
+ W_GetNumForName("KES6"),
+ cache_patch_t);
+ PreCacheGroup(W_GetNumForName("KSPHERE1"),
+ W_GetNumForName("KSPHERE4"),
+ cache_patch_t);
+ SpawnStatic(i,j,tile-23,spawnz);
+ if (loadedgame == false)
+ gamestate.missiletotal ++;
+ break;
+
+ case 57:
+ case 58:
+ case 59:
+ case 60:
+ case 61:
+ case 62:
+ case 65:
+ case 66:
+ case 67:
+ SpawnStatic(i,j,tile-23,spawnz);
+ break;
+
+ case 68:
+ case 69:
+ case 70:
+ case 71:
+ SpawnStatic(i,j,tile-23,spawnz);
+ break;
+
+ case 98:
+ SpawnStatic(i,j,tile-98+49,spawnz);
+ break;
+
+ case 210:
+ SpawnStatic(i,j,stat_scotthead,spawnz);
+ break;
+
+ case 228:
+ case 229:
+ case 230:
+ case 231:
+ case 232:
+ case 233:
+ SpawnStatic(i,j,tile-228+51,spawnz);
+ break;
+ case 246:
+ case 247:
+ case 248:
+ case 249:
+ case 250:
+ case 251:
+ SpawnStatic(i,j,tile-246+57,spawnz);
+ break;
+ case 264:
+ case 265:
+ SpawnStatic(i,j,tile-264+63,spawnz);
+ gamestate.planttotal ++;
+ break;
+
+ case 266:
+ SpawnStatic(i,j,stat_urn,spawnz);
+ break;
+
+ case 268:
+ SpawnStatic(i,j,tile-265+63,spawnz);
+ break;
+
+ case 269:
+ SpawnStatic(i,j,tile-265+63,spawnz);
+ break;
+
+ case 267:
+ SpawnStatic(i,j,stat_emptystatue,spawnz);
+ break;
+
+ case 282:
+ SpawnStatic(i,j,stat_heatgrate,spawnz);
+ break;
+
+ case 283:
+ SpawnStatic(i,j,stat_standardpole,spawnz);
+ break;
+
+ case 284:
+ if ( !BATTLEMODE )
+ {
+ SpawnStatic(i,j,stat_pit,spawnz);
+ }
+ break;
+
+
+
+
+ case 252:
+ SD_PreCacheSound(SD_GRAVSND);
+ SD_PreCacheSound(SD_GRAVHITSND);
+ SD_PreCacheSoundGroup(SD_GODMODEFIRESND,SD_LOSEMODESND);
+ if ((locplayerstate->player == 1) || (locplayerstate->player ==3))
+ SD_PreCacheSound(SD_GODWOMANSND);
+ else
+ SD_PreCacheSound(SD_GODMANSND);
+
+
+ PreCacheGroup(W_GetNumForName("GODHAND1"),
+ W_GetNumForName("GODHAND8"),
+ cache_patch_t);
+
+ PreCacheGroup(W_GetNumForName("VAPO1"),
+ W_GetNumForName("LITSOUL"),
+ cache_patch_t);
+
+ PreCacheGroup(W_GetNumForName("GODFIRE1"),
+ W_GetNumForName("GODFIRE4"),
+ cache_patch_t);
+
+ SpawnStatic(i,j,stat_godmode,spawnz);
+ if (loadedgame == false)
+ gamestate.supertotal ++;
+ break;
+
+ case 253:
+
+#if (SHAREWARE == 1)
+ Error("DogMode Power up in shareware at x=%d y=%d\n",i,j);
+#endif
+
+ SD_PreCacheSoundGroup(SD_DOGMODEPANTSND,SD_DOGMODELICKSND);
+ if ((locplayerstate->player == 1) || (locplayerstate->player ==3))
+ SD_PreCacheSound(SD_DOGWOMANSND);
+ else
+ SD_PreCacheSound(SD_DOGMANSND);
+
+
+
+ PreCacheGroup(W_GetNumForName("DOGNOSE1"),
+ W_GetNumForName("DOGPAW4"),
+ cache_patch_t);
+ SpawnStatic(i,j,stat_dogmode,spawnz);
+ if (loadedgame == false)
+ gamestate.supertotal ++;
+ break;
+
+ case 254:
+ SpawnStatic(i,j,stat_fleetfeet,spawnz);
+ if (loadedgame == false)
+ gamestate.supertotal ++;
+ break;
+
+ case 255:
+ SpawnStatic(i,j,stat_random,spawnz);
+ if (loadedgame == false)
+ gamestate.supertotal ++;
+ break;
+
+ case 260:
+ SpawnStatic(i,j,stat_elastic,spawnz);
+ if (loadedgame == false)
+ gamestate.supertotal ++;
+ break;
+
+ case 261:
+ SpawnStatic(i,j,stat_mushroom,spawnz);
+ if (loadedgame == false)
+ {
+ gamestate.supertotal ++;
+ gamestate.democratictotal ++;
+ }
+ break;
+
+
+ case 262:
+ SpawnStatic(i,j,stat_tomlarva,spawnz);
+ break;
+
+ case 263:
+ if (gamestate.SpawnCollectItems)
+ {
+ SpawnStatic(i,j,stat_collector,spawnz);
+ LASTSTAT->flags |= FL_COLORED;
+ LASTSTAT->hitpoints =
+ ( GameRandomNumber("colors",0) % MAXPLAYERCOLORS );
+ BATTLE_NumCollectorItems++;
+ }
+ break;
+
+ case 270:
+ SpawnStatic(i,j,stat_bulletproof,spawnz);
+ if (loadedgame == false)
+ gamestate.supertotal ++;
+ break;
+ case 271:
+ SpawnStatic(i,j,stat_asbesto,spawnz);
+ if (loadedgame == false)
+ gamestate.supertotal ++;
+ break;
+ case 272:
+ SpawnStatic(i,j,stat_gasmask,spawnz);
+ if (loadedgame == false)
+ gamestate.supertotal ++;
+ break;
+ case 461:
+ SpawnStatic(i,j,stat_disk,spawnz);
+ break;
+ }
+ }
+ }
+}
+
+
+
+void RaiseSprites( int x, int y, int count, int dir )
+{
+ int a,c;
+ int dx,dy;
+ int h;
+ int i;
+ int xx;
+ int hc;
+ int d;
+
+ dx=0;
+ dy=0;
+ if (dir==1)
+ dx=1;
+ else
+ dy=1;
+
+
+ if (((statobj_t *)sprites[x][y])->z==-65)
+ {
+ c=(maxheight+20)<<8;
+ hc=(count+1)<<7;
+ a=(c<<8)/(hc*hc);
+ for (i=0; i<count; i++)
+ {
+ xx=-hc+((i+1)<<8);
+ h=(c-FixedMulShift(a,(xx*xx),8) )>>8;
+ ((statobj_t *)sprites[x+(dx*i)][y+(dy*i)])->z=maxheight-h;
+ }
+ }
+ else
+ {
+ if (ActorIsSpring(x-(dx),y-(dy)))
+ d=1;
+ else if (ActorIsSpring(x+(dx*count),y+(dy*count)))
+ d=0;
+ else
+ Error("Cannot find a spring board around a ramp ascension near x=%d y=%d\n",x,y);
+
+ hc=((maxheight+20)<<16)/(count+1);
+ h=hc<<1;
+ for (i=0; i<count; i++)
+ {
+ if (d==1)
+ ((statobj_t *)sprites[x+(dx*i)][y+(dy*i)])->z=maxheight-(h>>16);
+ else
+ ((statobj_t *)sprites[x+(dx*(count-i-1))][y+(dy*(count-i-1))])->z=maxheight-(h>>16);
+ h+=hc;
+ }
+ }
+}
+
+void LoftSprites( void )
+{
+ int x,y;
+ int count;
+
+ for(y=1; y<mapheight-1; y++)
+ {
+ for(x=1; x<mapwidth-1; x++)
+ {
+ if (StaticUndefined(x,y))
+ {
+ if (StaticUndefined(x+1,y))
+ {
+ count=1;
+ while (StaticUndefined(x+count,y))
+ count++;
+ if (count<3)
+ Error ("Are You kidding me? You are trying to loft <3 sprites in an arc??? \n x=%d y=%d\n",x,y);
+ RaiseSprites(x,y,count,1);
+ }
+ else if (StaticUndefined(x,y+1))
+ {
+ count=1;
+ while (StaticUndefined(x,y+count))
+ count++;
+ if (count<3)
+ Error ("Are You kidding me? You are trying to loft <3 sprites??? \n x=%d y=%d\n",x,y);
+ RaiseSprites(x,y,count,0);
+ }
+ else
+ Error ("Sprite Lofter is confused around x=%d y=%d\n",x,y);
+ }
+ }
+ }
+}
+
--- /dev/null
+++ b/rott/rt_ted.h
@@ -1,0 +1,184 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// RT_TED.C - Ted stuff for maps and such
+//
+//***************************************************************************
+
+#include "rottnet.h"
+
+
+#ifndef _rt_ted_public
+#define _rt_ted_public
+
+#define MAXCLOCKS 10
+#define MAXSPAWNLOCATIONS 50
+#define POWERUPTICS ((VBLCOUNTER*60)+6)
+#define IsPlatform(x,y) ( (MAPSPOT((x),(y),2)==1) || ((MAPSPOT((x),(y),2)>=4) && (MAPSPOT((x),(y),2)<=9)))
+
+#define EXITTILE (107)
+#define SECRETEXITTILE (106)
+
+#define FL_SWITCH 0x01
+#define FL_ON 0x02
+#define FL_REVERSIBLE 0x04
+#define FL_W_DAMAGE 0x08
+#define FL_W_INVERTED 0x10
+#define FL_S_FLIPPED 0x20
+
+
+
+#define MAXTEAMS 11
+
+typedef struct
+{
+ int nummembers;
+ int uniformcolor;
+ int tilex,tiley;
+ byte dir;
+
+} teamtype;
+
+extern teamtype TEAM[MAXPLAYERS];
+
+typedef struct
+{ thingtype which;
+ byte flags;
+ byte hitpoints;
+ word tile;
+ byte tilex,tiley;
+
+
+} wall_t;
+
+typedef struct
+{
+ int number;
+ char mapname[23];
+} mapinfo_t;
+
+typedef struct
+{
+ int nummaps;
+ mapinfo_t maps[100];
+} mapfileinfo_t;
+
+#define MAXLEVELNAMELENGTH 23
+#define ALLOCATEDLEVELNAMELENGTH 24
+#define NUMPLANES 3
+#define NUMHEADEROFFSETS 100
+
+#define MAP_SPECIAL_TOGGLE_PUSHWALLS 0x0001
+
+typedef struct
+{
+ unsigned used;
+ unsigned CRC;
+ unsigned RLEWtag;
+ unsigned MapSpecials;
+ unsigned planestart[ NUMPLANES ];
+ unsigned planelength[ NUMPLANES ];
+ char Name[ ALLOCATEDLEVELNAMELENGTH ];
+} RTLMAP;
+
+
+typedef struct
+{ int x,y,dir;
+} _2dvec;
+
+extern _2dvec SPAWNLOC[MAXSPAWNLOCATIONS],FIRST,SECOND;
+
+typedef struct
+{ int time1;
+ int time2;
+ byte points_to_tilex;
+ byte points_to_tiley;
+ int linkindex;
+} str_clock;
+
+
+extern int numareatiles[NUMAREAS+1];
+extern int shapestart,shapestop;
+extern int NUMSPAWNLOCATIONS;
+extern int mapwidth;
+extern int mapheight;
+
+extern wall_t walls[MAXWALLTILES];
+extern str_clock Clocks[MAXCLOCKS];
+extern int LightsInArea[NUMAREAS+1];
+extern int numclocks;
+extern word ELEVATORLOCATION;
+
+extern unsigned short int *mapplanes[3];
+extern int gunsstart;
+extern int elevatorstart;
+extern int spritestop;
+extern int fog;
+extern int lightsource;
+extern int SNAKELEVEL;
+extern boolean insetupgame;
+extern char LevelName[80];
+extern boolean ISRTL;
+
+void PreCacheGroup(int,int,int); // added type
+void AssignTeams(void);
+void LoadTedMap( const char *extension, int mapnum );
+void SetupGameLevel(void);
+void ScanInfoPlane(void);
+void PreCacheLump( int lump, int level, int type ); // added type
+void SetupGameLevelAgain (void);
+void ScanInfoPlaneAgain (void);
+void PreCacheActor( int actor, int which );
+void PreCache( void );
+
+void SetupWalls( void );
+void SetupAnimatedWalls( void );
+void SetupSwitches( void );
+void SetupPlayers( void );
+void SetupMaskedWalls( void );
+void SetupPushWalls( void );
+void SetupPushWallLinks( void );
+void SetupDoors (void);
+void SetupDoorLinks (void);
+void SetupClocks (void);
+void SetupLinkedActors (void);
+void SetupLights(void);
+void SetupWindows ( void );
+
+int GetWallIndex( int texture );
+void PrintMapStats (void);
+void PrintTileStats (void);
+
+void GetMapInfo (mapfileinfo_t * mapinfo);
+void GetMapFileName ( char * filename );
+void SetBattleMapFileName ( char * filename );
+word GetMapCRC ( int num );
+
+int GetNextMap ( int tilex, int tiley );
+void Illuminate();
+
+int GetSongForLevel ( void );
+void CheckHolidays(void);
+boolean IsChristmas(void);
+
+boolean DoPanicMapping (void);
+
+#endif
--- /dev/null
+++ b/rott/rt_util.c
@@ -1,0 +1,1924 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "rt_def.h"
+
+#ifdef DOS
+#include <malloc.h>
+#include <dos.h>
+#include <conio.h>
+#include <io.h>
+#include <direct.h>
+#elif USE_SDL
+#include "SDL.h"
+#endif
+
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <time.h>
+#include "watcom.h"
+#include "_rt_util.h"
+#include "rt_util.h"
+#include "isr.h"
+#include "z_zone.h"
+#include "rt_dr_a.h"
+#include "rt_in.h"
+#include "rt_main.h"
+#include "scriplib.h"
+#include "rt_menu.h"
+#include "rt_playr.h"
+#include "version.h"
+#include "develop.h"
+#include "rt_vid.h"
+#include "rt_view.h"
+#include "modexlib.h"
+#include "rt_cfg.h"
+//MED
+#include "memcheck.h"
+
+int egacolor[16];
+byte * origpal;
+FILE * errout;
+FILE * debugout;
+FILE * mapdebugout;
+
+static boolean SoftErrorStarted=false;
+static boolean DebugStarted=false;
+static boolean MapDebugStarted=false;
+
+static unsigned char egargb[48]= { 0x00,0x00,0x00,
+ 0x00,0x00,0xab,
+ 0x00,0xab,0x00,
+ 0x00,0xab,0xab,
+ 0xab,0x00,0x00,
+ 0xab,0x00,0xab,
+ 0xab,0x57,0x00,
+ 0xab,0xab,0xab,
+ 0x57,0x57,0x57,
+ 0x57,0x57,0xff,
+ 0x57,0xff,0x57,
+ 0x57,0xff,0xff,
+ 0xff,0x57,0x57,
+ 0xff,0x57,0xff,
+ 0xff,0xff,0x57,
+ 0xff,0xff,0xff
+ };
+
+extern const byte * ROTT_ERR;
+
+#if (DEVELOPMENT == 1)
+int TotalStaticMemory=0;
+#endif
+
+#define SWAP(a,b) \
+ { \
+ a=(a)^(b); \
+ b=(a)^(b); \
+ a=(a)^(b); \
+ } \
+
+//******************************************************************************
+//
+// FindDistance
+//
+//******************************************************************************
+
+int FindDistance(int ix, int iy)
+{
+ int t;
+
+ ix= abs(ix); /* absolute values */
+ iy= abs(iy);
+
+ if (ix<iy)
+ SWAP(ix,iy);
+
+ t = iy + (iy>>1);
+
+ return (ix - (ix>>5) - (ix>>7) + (t>>2) + (t>>6));
+}
+
+
+//******************************************************************************
+//
+// Find_3D_Distance
+//
+//******************************************************************************
+
+int Find_3D_Distance(int ix, int iy, int iz)
+{
+ int t;
+
+ ix= abs(ix); /* absolute values */
+ iy= abs(iy);
+ iz= abs(iz);
+
+ if (ix<iy)
+ SWAP(ix,iy);
+
+ if (ix<iz)
+ SWAP(ix,iz);
+
+ t = iy + iz;
+
+ return (ix - (ix>>4) + (t>>2) + (t>>3));
+}
+
+//******************************************************************************
+//
+// atan2_appx
+//
+//******************************************************************************
+
+int atan2_appx(int dx, int dy)
+{ int absdx, absdy;
+ fixed angle;
+ fixed ratio;
+
+
+ if (!(dx||dy))
+ return 0;
+ absdx = abs(dx);
+ absdy = abs(dy);
+ if (absdx >= absdy)
+ ratio = FixedDiv2(absdy,absdx);
+ else
+ ratio = FixedDiv2(absdx,absdy);
+
+ if (dx >= 0)
+ { if (dy >= 0)
+ { if (absdx >= absdy)
+ angle = ratio; // 1st octant
+ else
+ angle = (2<<16) - ratio; // 2nd octant
+ }
+ else
+ { if (absdx >= absdy)
+ angle = (8<<16) - ratio; // 8th octant
+ else
+ angle = (6<<16) + ratio; // 7th octant
+ }
+ }
+ else
+ { if (dy >= 0)
+ { if (absdx >= absdy)
+ angle = (4<<16) - ratio; // 4th octant
+ else
+ angle = (2<<16) + ratio; // 3rd octant
+ }
+ else
+ { if (absdx >= absdy)
+ angle = (4<<16) + ratio; // 5th octant
+ else
+ angle = (6<<16) - ratio; // 6th octant
+ }
+ }
+
+ return (((int)FixedMul(angle,ANGLESDIV8))&(FINEANGLES-1));
+}
+
+
+
+//******************************************************************************
+//
+// StringsNotEqual
+//
+//******************************************************************************
+boolean StringsNotEqual (char * s1, char * s2, int length)
+{
+ int i;
+
+ for (i=0; i<length; i++)
+ if (s1[i]!=s2[i])
+ return true;
+ return false;
+}
+
+
+
+void markgetch( void )
+{
+ int done;
+ int i;
+
+ done=0;
+ while (done==0)
+ {
+ IN_UpdateKeyboard ();
+ for (i=0; i<127; i++)
+ if (Keyboard[i]==1)
+ done=i;
+ }
+ while (Keyboard[done])
+ IN_UpdateKeyboard ();
+}
+
+/*
+====================
+=
+= FindEGAColors
+=
+====================
+*/
+
+void FindEGAColors ( void )
+{
+ int i;
+
+ for (i=0; i<16; i++)
+ egacolor[i]=BestColor((int)egargb[i*3],(int)egargb[i*3+1],(int)egargb[i*3+2],origpal);
+}
+
+//===========================================================================
+
+
+byte BestColor (int r, int g, int b, byte *palette)
+{
+ int i;
+ long dr, dg, db;
+ long bestdistortion, distortion;
+ int bestcolor;
+ byte *pal;
+
+//
+// let any color go to 0 as a last resort
+//
+ bestdistortion = ( (long)WeightR*r*r + (long)WeightG*g*g + (long)WeightB*b*b )*2;
+ bestcolor = 0;
+
+ pal = &palette[0];
+ for (i=0 ; i<= 255 ; i++,pal+=3)
+ {
+ dr = r - (int)pal[0];
+ dg = g - (int)pal[1];
+ db = b - (int)pal[2];
+ distortion = WeightR*dr*dr + WeightG*dg*dg + WeightB*db*db;
+ if (distortion < bestdistortion)
+ {
+ if (!distortion)
+ return i; // perfect match
+
+ bestdistortion = distortion;
+ bestcolor = i;
+ }
+ }
+
+ return bestcolor;
+}
+
+void ClearGraphicsScreen( void )
+{
+ VL_ClearVideo(0);
+}
+
+void ClearBuffer( char * buf, int size )
+{
+ memset(buf,0,size);
+}
+
+/*
+=============================================================================
+
+ MISC FUNCTIONS
+
+=============================================================================
+*/
+
+/*
+=================
+=
+= Error
+=
+= For abnormal program terminations
+=
+=================
+*/
+
+void Error (char *error, ...)
+{
+ char msgbuf[300];
+ va_list argptr;
+ char i;
+ int size;
+ char * sptr;
+ char buf[30];
+ int handle;
+ int x,y;
+ int level;
+ static int inerror = 0;
+ char filename[ 128 ];
+
+
+ inerror++;
+ if (inerror > 1)
+ abort();
+
+
+ SetTextMode ();
+#ifdef DOS
+ memcpy ((byte *)0xB8000, &ROTT_ERR, 160*7);
+#elif defined (ANSIESC)
+ DisplayTextSplash (&ROTT_ERR, 7);
+#endif
+ memset (msgbuf, 0, 300);
+
+#ifdef DOS
+ px = ERRORVERSIONCOL-1;
+ py = ERRORVERSIONROW;
+#if (SHAREWARE == 1)
+ UL_printf ("S");
+#else
+ UL_printf ("R");
+#endif
+
+ px = ERRORVERSIONCOL;
+ py = ERRORVERSIONROW;
+#if (BETA == 1)
+ UL_printf ("�");
+#else
+ UL_printf (itoa(ROTTMAJORVERSION,&buf[0],10));
+#endif
+
+ // Skip the dot
+ px++;
+
+ UL_printf (itoa(ROTTMINORVERSION,&buf[0],10));
+#endif
+
+ va_start (argptr, error);
+ vsprintf (&msgbuf[0], error, argptr);
+ va_end (argptr);
+
+ scriptbuffer = &msgbuf[0];
+ size = strlen (msgbuf);
+
+ sptr = script_p = scriptbuffer;
+ scriptend_p = script_p + size;
+ scriptline = 1;
+ endofscript = false;
+ tokenready = false;
+
+ px = ERRORCOL;
+ py = ERRORROW;
+
+ GetToken (true);
+ while (!endofscript)
+ {
+ if ((script_p - sptr) >= 60)
+ {
+ px = ERRORCOL;
+ py++;
+ sptr = script_p;
+ }
+
+ UL_printf (token);
+ px++; //SPACE
+ GetToken (true);
+ }
+
+#ifdef ANSIESC
+ for (i = 0; i < 8; i++)
+ printf ("\n");
+#endif
+
+ if (player!=NULL)
+ {
+ printf ("Player X = %lx\n", (long int)player->x);
+ printf ("Player Y = %lx\n", (long int)player->y);
+ printf ("Player Angle = %lx\n\n", (long int)player->angle);
+ }
+ printf ("Episode = %ld\n", (long int)gamestate.episode);
+
+ if (gamestate.episode > 1)
+ level = (gamestate.mapon+1) - ((gamestate.episode-1) << 3);
+ else
+ level = gamestate.mapon+1;
+
+ printf ("Area = %ld\n", (long int)level);
+
+ ShutDown(); // DDOI - moved this so that it doesn't try to access player
+ // which is freed by this function.
+
+#ifdef DOS
+ GetPathFromEnvironment( filename, ApogeePath, ERRORFILE );
+ handle=SafeOpenAppend ( filename );
+ for (y=0; y<16; y++)
+ {
+ for (x=0; x<160; x+=2)
+ SafeWrite(handle,(byte *)0xB8000+(y*160)+x,1);
+ i=10;
+ SafeWrite(handle,&i,1);
+ i=13;
+ SafeWrite(handle,&i,1);
+ }
+
+ close(handle);
+
+ if ( SOUNDSETUP )
+ {
+ getch();
+ }
+
+#endif
+
+#if USE_SDL
+ SDL_Quit();
+#endif
+
+ exit (1);
+}
+
+//#if (SOFTERROR==1)
+
+/*
+=================
+=
+= SoftwareError
+=
+=================
+*/
+void SoftwareError (char *error, ...)
+{
+ va_list argptr;
+
+ if (SoftErrorStarted==false)
+ return;
+ va_start (argptr, error);
+ vfprintf (errout, error, argptr);
+ va_end (argptr);
+}
+
+//#endif
+
+
+//#if (DEBUG == 1)
+
+/*
+=================
+=
+= DebugError
+=
+=================
+*/
+void DebugError (char *error, ...)
+{
+ va_list argptr;
+
+ if (DebugStarted==false)
+ return;
+ va_start (argptr, error);
+ vfprintf (debugout, error, argptr);
+ va_end (argptr);
+}
+
+//#endif
+
+/*
+=================
+=
+= OpenSoftError
+=
+=================
+*/
+void OpenSoftError ( void )
+{
+ errout = fopen(SOFTERRORFILE,"wt+");
+ SoftErrorStarted=true;
+}
+
+/*
+=================
+=
+= MapDebug
+=
+=================
+*/
+void MapDebug (char *error, ...)
+{
+ va_list argptr;
+
+ if (MapDebugStarted==false)
+ return;
+ va_start (argptr, error);
+ vfprintf (mapdebugout, error, argptr);
+ va_end (argptr);
+}
+
+/*
+=================
+=
+= OpenMapDebug
+=
+=================
+*/
+void OpenMapDebug ( void )
+{
+ char filename[ 128 ];
+
+ if (MapDebugStarted==true)
+ return;
+ GetPathFromEnvironment( filename, ApogeePath, MAPDEBUGFILE );
+ mapdebugout = fopen(filename,"wt+");
+ MapDebugStarted=true;
+}
+
+
+/*
+=================
+=
+= StartupSoftError
+=
+=================
+*/
+void StartupSoftError ( void )
+{
+#if (DEBUG == 1)
+ if (DebugStarted==false)
+ {
+ debugout = fopen(DEBUGFILE,"wt+");
+ DebugStarted=true;
+ }
+#endif
+#if (SOFTERROR == 1)
+ if (SoftErrorStarted==false)
+ OpenSoftError();
+#endif
+}
+
+/*
+=================
+=
+= ShutdownSoftError
+=
+=================
+*/
+void ShutdownSoftError ( void )
+{
+ if (DebugStarted==true)
+ {
+ fclose(debugout);
+ DebugStarted=false;
+ }
+ if (SoftErrorStarted==true)
+ {
+ fclose(errout);
+ SoftErrorStarted=false;
+ }
+ if (MapDebugStarted==true)
+ {
+ fclose(mapdebugout);
+ MapDebugStarted=false;
+ }
+}
+
+
+/*
+=================
+=
+= CheckParm
+=
+= Checks for the given parameter in the program's command line arguments
+=
+= Returns the argument number (1 to argc-1) or 0 if not present
+=
+=================
+*/
+
+int CheckParm (char *check)
+{
+ int i;
+ char *parm;
+
+ for (i = 1; i<_argc; i++)
+ {
+ parm = _argv[i];
+ if ( !isalpha(*parm) ) // skip - / \ etc.. in front of parm
+ {
+ parm++;
+ if (!*parm)
+ continue; // parm was only one char
+ }
+
+ if ( !_fstricmp(check,parm) )
+ return i;
+ }
+
+ return 0;
+}
+
+
+
+int SafeOpenAppend (char *_filename)
+{
+ int handle;
+ char filename[MAX_PATH];
+ strncpy(filename, _filename, sizeof (filename));
+ filename[sizeof (filename) - 1] = '\0';
+ FixFilePath(filename);
+
+ handle = open(filename,O_RDWR | O_BINARY | O_CREAT | O_APPEND
+ , S_IREAD | S_IWRITE);
+
+ if (handle == -1)
+ Error ("Error opening for append %s: %s",filename,strerror(errno));
+
+ return handle;
+}
+
+int SafeOpenWrite (char *_filename)
+{
+ int handle;
+ char filename[MAX_PATH];
+ strncpy(filename, _filename, sizeof (filename));
+ filename[sizeof (filename) - 1] = '\0';
+ FixFilePath(filename);
+
+ handle = open(filename,O_RDWR | O_BINARY | O_CREAT | O_TRUNC
+ , S_IREAD | S_IWRITE);
+
+ if (handle == -1)
+ Error ("Error opening %s: %s",filename,strerror(errno));
+
+ return handle;
+}
+
+int SafeOpenRead (char *_filename)
+{
+ int handle;
+ char filename[MAX_PATH];
+ strncpy(filename, _filename, sizeof (filename));
+ filename[sizeof (filename) - 1] = '\0';
+ FixFilePath(filename);
+
+ handle = open(filename,O_RDONLY | O_BINARY);
+
+ if (handle == -1)
+ Error ("Error opening %s: %s",filename,strerror(errno));
+
+ return handle;
+}
+
+
+void SafeRead (int handle, void *buffer, long count)
+{
+ unsigned iocount;
+
+ while (count)
+ {
+ iocount = count > 0x8000 ? 0x8000 : count;
+ if (read (handle,buffer,iocount) != (int)iocount)
+ Error ("File read failure reading %ld bytes",count);
+ buffer = (void *)( (byte *)buffer + iocount );
+ count -= iocount;
+ }
+}
+
+
+void SafeWrite (int handle, void *buffer, long count)
+{
+ unsigned iocount;
+
+ while (count)
+ {
+ iocount = count > 0x8000 ? 0x8000 : count;
+ if (write (handle,buffer,iocount) != (int)iocount)
+ Error ("File write failure writing %ld bytes",count);
+ buffer = (void *)( (byte *)buffer + iocount );
+ count -= iocount;
+ }
+}
+
+void SafeWriteString (int handle, char * buffer)
+{
+ unsigned iocount;
+
+ iocount=strlen(buffer);
+ if (write (handle,buffer,iocount) != (int)iocount)
+ Error ("File write string failure writing %s\n",buffer);
+}
+
+void *SafeMalloc (long size)
+{
+ void *ptr;
+
+ if (zonememorystarted==false)
+ Error("Called SafeMalloc without starting zone memory\n");
+ ptr = Z_Malloc (size,PU_STATIC,NULL);
+
+ if (!ptr)
+ Error ("SafeMalloc failure for %lu bytes",size);
+
+ return ptr;
+}
+
+void *SafeLevelMalloc (long size)
+{
+ void *ptr;
+
+ if (zonememorystarted==false)
+ Error("Called SafeLevelMalloc without starting zone memory\n");
+ ptr = Z_LevelMalloc (size,PU_STATIC,NULL);
+
+ if (!ptr)
+ Error ("SafeLevelMalloc failure for %lu bytes",size);
+
+ return ptr;
+}
+
+void SafeFree (void * ptr)
+{
+ if ( ptr == NULL )
+ Error ("SafeFree : Tried to free a freed pointer\n");
+
+ Z_Free (ptr);
+}
+
+/*
+==============
+=
+= LoadFile
+=
+==============
+*/
+
+long LoadFile (char *filename, void **bufferptr)
+{
+ int handle;
+ long length;
+
+ handle = SafeOpenRead (filename);
+ length = filelength (handle);
+ *bufferptr = SafeMalloc (length);
+ SafeRead (handle,*bufferptr, length);
+ close (handle);
+ return length;
+}
+
+
+/*
+==============
+=
+= SaveFile
+=
+==============
+*/
+
+void SaveFile (char *filename, void *buffer, long count)
+{
+ int handle;
+
+ handle = SafeOpenWrite (filename);
+ SafeWrite (handle, buffer, count);
+ close (handle);
+}
+
+
+void FixFilePath(char *filename)
+{
+#if PLATFORM_UNIX
+ char *ptr;
+ char *lastsep = filename;
+
+ if ((!filename) || (*filename == '\0'))
+ return;
+
+ if (access(filename, F_OK) == 0) /* File exists; we're good to go. */
+ return;
+
+ for (ptr = filename; 1; ptr++)
+ {
+ if (*ptr == '\\')
+ *ptr = PATH_SEP_CHAR;
+
+ if ((*ptr == PATH_SEP_CHAR) || (*ptr == '\0'))
+ {
+ char pch = *ptr;
+ struct dirent *dent = NULL;
+ DIR *dir;
+
+ if ((pch == PATH_SEP_CHAR) && (*(ptr + 1) == '\0'))
+ return; /* eos is pathsep; we're done. */
+
+ if (lastsep == ptr)
+ continue; /* absolute path; skip to next one. */
+
+ *ptr = '\0';
+ if (lastsep == filename) {
+ dir = opendir((*lastsep == PATH_SEP_CHAR) ? ROOTDIR : CURDIR);
+
+ if (*lastsep == PATH_SEP_CHAR) {
+ lastsep++;
+ }
+ }
+ else
+ {
+ *lastsep = '\0';
+ dir = opendir(filename);
+ *lastsep = PATH_SEP_CHAR;
+ lastsep++;
+ }
+
+ if (dir == NULL)
+ {
+ *ptr = PATH_SEP_CHAR;
+ return; /* maybe dir doesn't exist? give up. */
+ }
+
+ while ((dent = readdir(dir)) != NULL)
+ {
+ if (strcasecmp(dent->d_name, lastsep) == 0)
+ {
+ /* found match; replace it. */
+ strcpy(lastsep, dent->d_name);
+ break;
+ }
+ }
+
+ closedir(dir);
+ *ptr = pch;
+ lastsep = ptr;
+
+ if (dent == NULL)
+ return; /* no match. oh well. */
+
+ if (pch == '\0') /* eos? */
+ return;
+ }
+ }
+#endif
+}
+
+
+#if PLATFORM_DOS
+/* no-op. */
+
+#elif PLATFORM_WIN32
+int _dos_findfirst(char *filename, int x, struct find_t *f)
+{
+ long rc = _findfirst(filename, &f->data);
+ f->handle = rc;
+ if (rc != -1)
+ {
+ strncpy(f->name, f->data.name, sizeof (f->name) - 1);
+ f->name[sizeof (f->name) - 1] = '\0';
+ return(0);
+ }
+ return(1);
+}
+
+int _dos_findnext(struct find_t *f)
+{
+ int rc = 0;
+ if (f->handle == -1)
+ return(1); /* invalid handle. */
+
+ rc = _findnext(f->handle, &f->data);
+ if (rc == -1)
+ {
+ _findclose(f->handle);
+ f->handle = -1;
+ return(1);
+ }
+
+ strncpy(f->name, f->data.name, sizeof (f->name) - 1);
+ f->name[sizeof (f->name) - 1] = '\0';
+ return(0);
+}
+
+#elif PLATFORM_UNIX
+int _dos_findfirst(char *filename, int x, struct find_t *f)
+{
+ char *ptr;
+
+ if (strlen(filename) >= sizeof (f->pattern))
+ return(1);
+
+ strcpy(f->pattern, filename);
+ FixFilePath(f->pattern);
+ ptr = strrchr(f->pattern, PATH_SEP_CHAR);
+
+ if (ptr == NULL)
+ {
+ ptr = filename;
+ f->dir = opendir(CURDIR);
+ }
+ else
+ {
+ *ptr = '\0';
+ f->dir = opendir(f->pattern);
+ memmove(f->pattern, ptr + 1, strlen(ptr + 1) + 1);
+ }
+
+ return(_dos_findnext(f));
+}
+
+
+static int check_pattern_nocase(const char *x, const char *y)
+{
+ if ((x == NULL) || (y == NULL))
+ return(0); /* not a match. */
+
+ while ((*x) && (*y))
+ {
+ if (*x == '*')
+ Error("Unexpected wildcard!"); /* FIXME? */
+
+ else if (*x == '?')
+ {
+ if (*y == '\0')
+ return(0); /* anything but EOS is okay. */
+ }
+
+ else
+ {
+ if (toupper((int) *x) != toupper((int) *y))
+ return(0); /* not a match. */
+ }
+
+ x++;
+ y++;
+ }
+
+ return(*x == *y); /* it's a match (both should be EOS). */
+}
+
+int _dos_findnext(struct find_t *f)
+{
+ struct dirent *dent;
+
+ if (f->dir == NULL)
+ return(1); /* no such dir or we're just done searching. */
+
+ while ((dent = readdir(f->dir)) != NULL)
+ {
+ if (check_pattern_nocase(f->pattern, dent->d_name))
+ {
+ if (strlen(dent->d_name) < sizeof (f->name))
+ {
+ strcpy(f->name, dent->d_name);
+ return(0); /* match. */
+ }
+ }
+ }
+
+ closedir(f->dir);
+ f->dir = NULL;
+ return(1); /* no match in whole directory. */
+}
+#else
+#error please define for your platform.
+#endif
+
+
+#if !PLATFORM_DOS
+void _dos_getdate(struct dosdate_t *date)
+{
+ time_t curtime = time(NULL);
+ struct tm *tm;
+
+ if (date == NULL) {
+ return;
+ }
+
+ memset(date, 0, sizeof(struct dosdate_t));
+
+ if ((tm = localtime(&curtime)) != NULL) {
+ date->day = tm->tm_mday;
+ date->month = tm->tm_mon + 1;
+ date->year = tm->tm_year + 1900;
+ date->dayofweek = tm->tm_wday + 1;
+ }
+}
+#endif
+
+
+void GetPathFromEnvironment( char *fullname, const char *envname, const char *filename )
+{
+
+#ifdef DOS
+ char *path;
+ path = getenv( envname );
+#else
+ const char *path;
+ path = envname;
+#endif
+
+ if ( path != NULL )
+ {
+ strcpy( fullname, path );
+ if ( fullname[ strlen( fullname ) - 1 ] != PATH_SEP_CHAR )
+ {
+ strcat( fullname, PATH_SEP_STR );
+ }
+ strcat( fullname, filename );
+ }
+ else
+ {
+ strcpy( fullname, filename );
+ }
+
+ FixFilePath(fullname);
+}
+
+void DefaultExtension (char *path, char *extension)
+{
+ char *src;
+//
+// if path doesn't have a .EXT, append extension
+// (extension should include the .)
+//
+ src = path + strlen(path) - 1;
+
+ while (*src != PATH_SEP_CHAR && src != path)
+ {
+ if (*src == '.')
+ return; // it has an extension
+ src--;
+ }
+
+ strcat (path, extension);
+}
+
+void DefaultPath (char *path, char *basepath)
+{
+ char temp[128];
+
+ if (path[0] == PATH_SEP_CHAR)
+ return; // absolute path location
+ strcpy (temp,path);
+ strcpy (path,basepath);
+ strcat (path,temp);
+}
+
+
+void ExtractFileBase (char *path, char *dest)
+{
+ char *src;
+ int length;
+
+ src = path + strlen(path) - 1;
+
+//
+// back up until a \ or the start
+//
+ while (src != path && *(src-1) != PATH_SEP_CHAR)
+ src--;
+
+//
+// copy up to eight characters
+//
+ memset (dest,0,8);
+ length = 0;
+ while (*src && *src != '.')
+ {
+ if (++length == 9)
+ Error ("Filename base of %s >8 chars",path);
+ *dest++ = toupper(*src++);
+ }
+}
+
+
+/*
+==============
+=
+= ParseNum / ParseHex
+=
+==============
+*/
+
+long ParseHex (char *hex)
+{
+ char *str;
+ long num;
+
+ num = 0;
+ str = hex;
+
+ while (*str)
+ {
+ num <<= 4;
+ if (*str >= '0' && *str <= '9')
+ num += *str-'0';
+ else if (*str >= 'a' && *str <= 'f')
+ num += 10 + *str-'a';
+ else if (*str >= 'A' && *str <= 'F')
+ num += 10 + *str-'A';
+ else
+ Error ("Bad hex number: %s",hex);
+ str++;
+ }
+
+ return num;
+}
+
+
+long ParseNum (char *str)
+{
+ if (str[0] == '$')
+ return ParseHex (str+1);
+ if (str[0] == '0' && str[1] == 'x')
+ return ParseHex (str+2);
+ return atol (str);
+}
+
+
+#if (BYTE_ORDER == LITTLE_ENDIAN)
+#define KeepShort IntelShort
+#define SwapShort MotoShort
+#define KeepLong IntelLong
+#define SwapLong MotoLong
+#else
+#define KeepShort MotoShort
+#define SwapShort IntelShort
+#define KeepLong MotoLong
+#define SwapLong IntelLong
+#endif
+
+short SwapShort (short l)
+{
+ byte b1,b2;
+
+ b1 = l&255;
+ b2 = (l>>8)&255;
+
+ return (b1<<8) + b2;
+}
+
+short KeepShort (short l)
+{
+ return l;
+}
+
+
+int SwapLong (int l)
+{
+ byte b1,b2,b3,b4;
+
+ b1 = l&255;
+ b2 = (l>>8)&255;
+ b3 = (l>>16)&255;
+ b4 = (l>>24)&255;
+
+ return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
+}
+
+int KeepLong (int l)
+{
+ return l;
+}
+
+
+#undef KeepShort
+#undef KeepLong
+#undef SwapShort
+#undef SwapLong
+
+void SwapIntelLong(int *l)
+{
+ *l = IntelLong(*l);
+}
+
+void SwapIntelShort(short *s)
+{
+ *s = IntelShort(*s);
+}
+
+void SwapIntelLongArray(int *l, int num)
+{
+ while (num--) {
+ SwapIntelLong(l);
+ l++;
+ }
+}
+
+void SwapIntelShortArray(short *s, int num)
+{
+ while (num--) {
+ SwapIntelShort(s);
+ s++;
+ }
+}
+
+/*
+============================================================================
+
+ BASIC GRAPHICS
+
+============================================================================
+*/
+
+/*
+==============
+=
+= GetaPalette
+=
+= Return an 8 bit / color palette
+=
+==============
+*/
+
+void GetaPalette (byte *palette)
+{
+#ifdef DOS
+ int i;
+
+ OUTP (PEL_READ_ADR,0);
+ for (i=0 ; i<768 ; i++)
+ palette[i] = inp (PEL_DATA)<<2;
+#else
+ int i;
+ SDL_Palette *pal = SDL_GetVideoSurface()->format->palette;
+
+ for (i = 0; i < 256; i++) {
+ palette[0] = pal->colors[i].r;
+ palette[1] = pal->colors[i].g;
+ palette[2] = pal->colors[i].b;
+
+ palette += 3;
+ }
+#endif
+}
+
+/*
+==============
+=
+= SetaPalette
+=
+= Sets an 8 bit / color palette
+=
+==============
+*/
+
+void SetaPalette (byte *pal)
+{
+#ifdef DOS
+ int i;
+
+ OUTP (PEL_WRITE_ADR,0);
+ for (i=0 ; i<768 ; i++)
+ OUTP (PEL_DATA, pal[i]>>2);
+#else
+ SDL_Color cmap[256];
+ int i;
+
+ for (i = 0; i < 256; i++)
+ {
+ cmap[i].r = pal[i*3+0];
+ cmap[i].g = pal[i*3+1];
+ cmap[i].b = pal[i*3+2];
+ }
+
+ SDL_SetColors (SDL_GetVideoSurface (), cmap, 0, 256);
+#endif
+}
+
+void GetPalette(char * palette)
+{
+#ifdef DOS
+ int i;
+
+ OUTP(0x03c7,0);
+ for (i=0; i<256*3; i++)
+ *(palette+(unsigned char)i)=inp(0x3c9)<<2;
+#else
+ int i;
+ SDL_Palette *pal = SDL_GetVideoSurface()->format->palette;
+
+ for (i = 0; i < 256; i++) {
+ palette[0] = pal->colors[i].r;
+ palette[1] = pal->colors[i].g;
+ palette[2] = pal->colors[i].b;
+
+ palette += 3;
+ }
+#endif
+}
+
+void SetPalette ( char * pal )
+{
+ VL_SetPalette (pal);
+}
+
+
+
+//******************************************************************************
+//
+// US_CheckParm() - checks to see if a string matches one of a set of
+// strings. The check is case insensitive. The routine returns the
+// index of the string that matched, or -1 if no matches were found
+//
+//******************************************************************************
+
+int US_CheckParm (char *parm, char **strings)
+{
+ char cp,cs,
+ *p,*s;
+ int i;
+ int length;
+
+ length=strlen(parm);
+ while ( (!isalpha(*parm)) && (length>0)) // Skip non-alphas
+ {
+ length--;
+ parm++;
+ }
+
+ for (i = 0; *strings && **strings; i++)
+ {
+ for (s = *strings++,p = parm,cs = cp = 0; cs == cp;)
+ {
+ cs = *s++;
+ if (!cs)
+ return(i);
+ cp = *p++;
+
+ if (isupper(cs))
+ cs = tolower(cs);
+ if (isupper(cp))
+ cp = tolower(cp);
+ }
+ }
+ return(-1);
+}
+
+/*
+=============================================================================
+
+ PALETTE OPS
+
+ To avoid snow, do a WaitVBL BEFORE calling these
+
+=============================================================================
+*/
+
+
+/*
+=================
+=
+= VL_FillPalette
+=
+=================
+*/
+
+void VL_FillPalette (int red, int green, int blue)
+{
+#ifdef DOS
+ int i;
+
+ OUTP (PEL_WRITE_ADR,0);
+ for (i=0; i<256; i++)
+ {
+ OUTP (PEL_DATA,red);
+ OUTP (PEL_DATA,green);
+ OUTP (PEL_DATA,blue);
+ }
+#else
+ SDL_Color cmap[256];
+ int i;
+
+ for (i = 0; i < 256; i++)
+ {
+ cmap[i].r = red << 2;
+ cmap[i].g = green << 2;
+ cmap[i].b = blue << 2;
+ }
+
+ SDL_SetColors (SDL_GetVideoSurface (), cmap, 0, 256);
+#endif
+}
+
+//===========================================================================
+
+/*
+=================
+=
+= VL_SetColor
+=
+=================
+*/
+
+void VL_SetColor (int color, int red, int green, int blue)
+{
+#ifdef DOS
+ OUTP (PEL_WRITE_ADR,color);
+ OUTP (PEL_DATA,red);
+ OUTP (PEL_DATA,green);
+ OUTP (PEL_DATA,blue);
+#else
+ STUB_FUNCTION;
+#endif
+}
+
+//===========================================================================
+
+/*
+=================
+=
+= VL_GetColor
+=
+=================
+*/
+
+void VL_GetColor (int color, int *red, int *green, int *blue)
+{
+#ifdef DOS
+ OUTP (PEL_READ_ADR,color);
+ *red = inp (PEL_DATA);
+ *green = inp (PEL_DATA);
+ *blue = inp (PEL_DATA);
+#else
+ STUB_FUNCTION;
+#endif
+}
+
+//===========================================================================
+
+/*
+=================
+=
+= VL_NormalizePalette
+=
+=================
+*/
+
+void VL_NormalizePalette (byte *palette)
+{
+ int i;
+
+ for (i = 0; i < 768; i++)
+ *(palette+i)=(*(palette+i))>>2;
+}
+
+
+/*
+=================
+=
+= VL_SetPalette
+=
+= If fast palette setting has been tested for, it is used
+= -some cards don't like outsb palette setting-
+=
+=================
+*/
+
+void VL_SetPalette (byte *palette)
+{
+#ifdef DOS
+ int i;
+
+ OUTP (PEL_WRITE_ADR, 0);
+
+ for (i = 0; i < 768; i++)
+ {
+ OUTP (PEL_DATA, gammatable[(gammaindex<<6)+(*palette++)]);
+ }
+#else
+ SDL_Color cmap[256];
+ int i;
+
+ for (i = 0; i < 256; i++)
+ {
+ cmap[i].r = gammatable[(gammaindex<<6)+(*palette++)] << 2;
+ cmap[i].g = gammatable[(gammaindex<<6)+(*palette++)] << 2;
+ cmap[i].b = gammatable[(gammaindex<<6)+(*palette++)] << 2;
+ }
+
+ SDL_SetColors (SDL_GetVideoSurface (), cmap, 0, 256);
+#endif
+}
+
+
+//===========================================================================
+
+/*
+=================
+=
+= VL_GetPalette
+=
+= This does not use the port string instructions,
+= due to some incompatabilities
+=
+=================
+*/
+
+void VL_GetPalette (byte *palette)
+{
+#ifdef DOS
+ int i;
+
+ OUTP (PEL_READ_ADR, 0);
+
+ for (i = 0; i < 768; i++)
+ *palette++ = inp (PEL_DATA);
+#else
+ int i;
+ SDL_Palette *pal = SDL_GetVideoSurface()->format->palette;
+
+ for (i = 0; i < 256; i++) {
+ palette[0] = pal->colors[i].r >> 2;
+ palette[1] = pal->colors[i].g >> 2;
+ palette[2] = pal->colors[i].b >> 2;
+
+ palette += 3;
+ }
+#endif
+}
+
+
+/*
+=================
+=
+= UL_DisplayMemoryError ()
+=
+=================
+*/
+
+void UL_DisplayMemoryError ( int memneeded )
+{
+#ifdef DOS
+ char buf[4000];
+ int i;
+
+ ShutDown ();
+ TextMode ();
+
+ for (i = 0; i < 19; i++)
+ printf ("\n");
+
+ memcpy (buf, &ROTT_ERR, 4000);
+ memcpy ((byte *)0xB8000, &buf[160*7], 4000-(160*7));
+
+ px = ERRORVERSIONCOL;
+ py = ERRORVERSIONROW;
+#if (BETA == 1)
+ UL_printf ("�");
+#else
+ UL_printf (itoa(ROTTMAJORVERSION,&buf[0],10));
+#endif
+ px++;
+
+ UL_printf (itoa(ROTTMINORVERSION,&buf[0],10));
+
+ px = LOWMEMORYCOL;
+ py = LOWMEMORYROW;
+ UL_printf ("You need ");
+ UL_printf (itoa(memneeded,&buf[0],10));
+ UL_printf (" bytes more memory");
+ if ( SOUNDSETUP )
+ {
+ getch();
+ }
+#else
+ STUB_FUNCTION;
+#endif
+ exit (0);
+}
+
+
+/*
+=================
+=
+= UL_printf
+=
+=================
+*/
+
+void UL_printf (byte *str)
+{
+#ifdef DOS
+ byte *s;
+ byte *screen;
+
+ s = str;
+ screen = (byte *)(0xB8000 + (py*160) + (px<<1));
+
+ while (*s)
+ {
+ *screen = *s;
+ s++;
+ screen += 2;
+ px++;
+
+ if ((*s < 32) && (*s > 0))
+ s++;
+ }
+#else
+#ifdef ANSIESC
+ printf ("\x1b[%d;%dH%s",py,px,str);
+#else
+ printf ("%s ",str); // Hackish but works - DDOI
+#endif
+#endif
+}
+
+/*
+=================
+=
+= UL_ColorBox
+=
+=================
+*/
+
+void UL_ColorBox (int x, int y, int w, int h, int color)
+{
+#ifdef DOS
+ byte *screen;
+ int i,j;
+
+
+ for (j=0; j<h; j++)
+ {
+ screen = (byte *)(0xB8000 + ((y+j)*160) + (x<<1) + 1);
+ for (i=0; i<w; i++)
+ {
+ *screen = (byte)color;
+ screen+=2;
+ }
+ }
+#elif defined (ANSIESC)
+ int i,j;
+
+
+ for (j=0; j<h; j++)
+ {
+ for (i=0; i<w; i++)
+ {
+ printf ("\x1b[%d;%dH",y+j,x+i);
+ put_dos2ansi(color);
+ }
+ }
+#endif
+}
+
+//******************************************************************************
+//
+// SideOfLine
+//
+//******************************************************************************
+
+int SideOfLine(int x1, int y1, int x2, int y2, int x3, int y3)
+{
+ int a1,b1,c1;
+
+ /* Compute a1, b1, c1, where line joining points 1 and 2
+ * is "a1 x + b1 y + c1 = 0".
+ */
+
+ a1 = y2 - y1;
+ b1 = x1 - x2;
+ c1 = FixedMulShift(x2,y1,16) - FixedMulShift(x1,y2,16);
+
+ return SGN(FixedMulShift(a1,x3,16) + FixedMulShift(b1,y3,16) + c1);
+}
+
+
+
+//******************************************************************************
+//
+// HSORT - heap sort
+//
+//******************************************************************************
+
+typedef int (*PFI)(); /* pointer to a function returning int */
+typedef void (*PFV)(); /* pointer to a function returning int */
+static PFI Comp; /* pointer to comparison routine */
+static PFV Switch; /* pointer to comparison routine */
+static int Width; /* width of an object in bytes */
+static char *Base; /* pointer to element [-1] of array */
+
+
+static void newsift_down(L,U) int L,U;
+{ int c;
+
+ while(1)
+ { c=L+L;
+ if(c>U) break;
+ if( (c+Width <= U) && ((*Comp)(Base+c+Width,Base+c)>0) ) c+= Width;
+ if ((*Comp)(Base+L,Base+c)>=0) break;
+ (*Switch)(Base+L, Base+c);
+ L=c;
+ }
+}
+
+void hsort(char * base, int nel, int width, int (*compare)(), void (*switcher)())
+{
+ static int i,n,stop;
+ /* Perform a heap sort on an array starting at base. The array is
+ nel elements large and width is the size of a single element in
+ bytes. Compare is a pointer to a comparison routine which will
+ be passed pointers to two elements of the array. It should
+ return a negative number if the left-most argument is less than
+ the rightmost, 0 if the two arguments are equal, a positive
+ number if the left argument is greater than the right. (That
+ is, it acts like a "subtract" operator.) If compare is 0 then
+ the default comparison routine, argvcmp (which sorts an
+ argv-like array of pointers to strings), is used. */
+
+ Width=width;
+ Comp= compare;
+ Switch= switcher;
+ n=nel*Width;
+ Base=base-Width;
+ for (i=(n/Width/2)*Width; i>=Width; i-=Width) newsift_down(i,n);
+ stop=Width+Width;
+ for (i=n; i>=stop; )
+ {
+ (*Switch)(base, Base+i);
+ newsift_down(Width,i-=Width);
+ }
+
+}
+
+/*---------------------------------------------------------------------------*/
+
+//******************************************************************************
+//
+// UL_GetPath
+//
+// Purpose
+// To parse the directory entered by the user to make the directory.
+//
+// Parms
+// Path - the path to be parsed.
+//
+// Returns
+// Pointer to next path
+//
+//******************************************************************************
+
+char * UL_GetPath (char * path, char *dir)
+{
+ boolean done = 0;
+ char *dr = dir;
+ int cnt = 0;
+
+ if (*path == SLASHES)
+ path++;
+
+ while (!done)
+ {
+ *dr = *path;
+
+ cnt++; // make sure the number of characters in the dir
+ if (cnt > MAXCHARS) // name doesn't exceed acceptable limits.
+ Error ("ERROR : Directory name can only be %d characters long.\n", MAXCHARS);
+
+ path++;
+ dr++;
+
+ if ((*path == SLASHES) || (*path == 0))
+ done = true;
+ }
+
+ *dr = 0;
+ return (path);
+}
+
+
+//******************************************************************************
+//
+// UL_ChangeDirectory ()
+//
+// Purpose
+// To change to a directory. Checks for drive changes.
+//
+// Parms
+// path - The path to change to.
+//
+// Returns
+// TRUE - If successful.
+// FALSE - If unsuccessful.
+//
+//******************************************************************************
+
+boolean UL_ChangeDirectory (char *path)
+{
+#ifdef DOS
+ char *p;
+ char dir[9];
+ char *d;
+
+ d = &dir[0];
+ p = path;
+ memset (dir, 0, 9);
+
+ // Check for a drive at the beginning of the path
+ if (*(p+1) == ':')
+ {
+ *d++ = *p++; // drive letter
+ *d++ = *p++; // colon
+
+ if (UL_ChangeDrive (dir) == false)
+ return (false);
+ }
+
+ if (*p == SLASHES)
+ {
+ chdir ("\\");
+ p++;
+ }
+
+ d = &dir[0];
+ while (*p)
+ {
+ p = UL_GetPath (p, d);
+
+ if (chdir (d) == -1)
+ return (false);
+ }
+
+ return (true);
+#else
+ if (!path || !*path) {
+ return true;
+ }
+
+ if (chdir (path) == -1) {
+ return (false);
+ }
+
+ return true;
+#endif
+}
+
+
+
+//******************************************************************************
+//
+// UL_ChangeDrive ()
+//
+// Purpose
+// To change drives.
+//
+// Parms
+// drive - The drive to change to.
+//
+// Returns
+// TRUE - If drive change successful.
+// FALSE - If drive change unsuccessful.
+//
+//******************************************************************************
+
+boolean UL_ChangeDrive (char *drive)
+{
+#ifdef DOS
+ unsigned d, total, tempd;
+
+ d = toupper (*drive);
+
+ d = d - 'A' + 1;
+
+ _dos_setdrive (d, &total);
+ _dos_getdrive (&tempd);
+
+ if (d != tempd)
+ return (false);
+
+ return (true);
+#else
+ STUB_FUNCTION;
+
+ return false;
+#endif
+}
+
+
+/*
+=============
+=
+= AbortCheck
+=
+=============
+*/
+void AbortCheck (char * abortstring)
+{
+ // User abort check
+
+ IN_UpdateKeyboard ();
+
+ if (Keyboard[sc_Escape])
+ Error("%s\n",abortstring);
+}
--- /dev/null
+++ b/rott/rt_util.h
@@ -1,0 +1,210 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// RT_UTIL.C - various utils palette funcs and modex stuff
+//
+//***************************************************************************
+
+#ifndef _rt_util_public
+#define _rt_util_public
+
+#define ERRORVERSIONROW 1
+#define ERRORVERSIONCOL 67
+
+#define LOWMEMORYROW 18
+#define LOWMEMORYCOL 1
+
+#include "develop.h"
+
+extern int egacolor[16];
+extern byte * origpal;
+extern int _argc;
+extern char ** _argv;
+
+void markgetch( void );
+boolean StringsNotEqual (char * s1, char * s2, int length);
+void GetPalette(char * pal);
+void ClearGraphicsScreen( void );
+void ClearBuffer( char * buf, int size );
+void Error (char *error, ...) __attribute__((noreturn,format(printf,1,2)));
+void StartupSoftError ( void );
+void ShutdownSoftError ( void );
+int CheckParm (char *check);
+int SafeOpenWrite (char *filename);
+int SafeOpenAppend (char *filename);
+int SafeOpenRead (char *filename);
+void SafeRead (int handle, void *buffer, long count);
+void SafeWrite (int handle, void *buffer, long count);
+void SafeWriteString (int handle, char * buffer);
+void *SafeMalloc (long size);
+void *SafeLevelMalloc (long size);
+void SafeFree (void * ptr);
+long LoadFile (char *filename, void **bufferptr);
+void SaveFile (char *filename, void *buffer, long count);
+void GetPathFromEnvironment( char *fullname, const char *envname, const char *filename );
+void DefaultExtension (char *path, char *extension);
+void DefaultPath (char *path, char *basepath);
+void ExtractFileBase (char *path, char *dest);
+long ParseHex (char *hex);
+long ParseNum (char *str);
+short MotoShort (short l);
+short IntelShort (short l);
+int MotoLong (int l);
+int IntelLong (int l);
+void SwapIntelLong (int *l);
+void SwapIntelShort(short *s);
+void SwapIntelLongArray (int *l, int num);
+void SwapIntelShortArray (short *s, int num);
+int US_CheckParm (char *parm, char **strings);
+byte BestColor (int r, int g, int b, byte *palette);
+int atan2_appx(int,int);
+int FindDistance(int ix, int iy);
+int Find_3D_Distance(int ix, int iy, int iz);
+void SetPalette ( char * pal );
+void SetaPalette ( byte * pal );
+void FindEGAColors ( void );
+void VL_FillPalette (int red, int green, int blue);
+void VL_SetColor (int color, int red, int green, int blue);
+void VL_GetColor (int color, int *red, int *green, int *blue);
+void VL_SetPalette (byte *palette);
+void VL_GetPalette (byte *palette);
+void UL_printf (byte *str);
+void VL_NormalizePalette (byte *palette);
+void MapDebug (char *error, ...) __attribute__((format(printf,1,2)));
+void OpenMapDebug ( void );
+void UL_ColorBox (int x, int y, int w, int h, int color);
+
+void UL_DisplayMemoryError ( int memneeded );
+
+int SideOfLine(int x1, int y1, int x2, int y2, int x3, int y3);
+
+void hsort(char * base, int nel, int width, int (*compare)(), void (*switcher)());
+
+char * UL_GetPath (char * path, char *dir);
+boolean UL_ChangeDirectory (char *path);
+boolean UL_ChangeDrive (char *drive);
+void AbortCheck (char * abortstring);
+
+void FixFilePath(char *filename);
+
+
+#if PLATFORM_WIN32
+#include <io.h>
+struct find_t
+{
+ long handle;
+ struct _finddata_t data;
+ char name[MAX_PATH];
+};
+int _dos_findfirst(char *filename, int x, struct find_t *f);
+int _dos_findnext(struct find_t *f);
+
+#elif PLATFORM_UNIX
+struct find_t
+{
+ DIR *dir;
+ char pattern[MAX_PATH];
+ char name[MAX_PATH];
+};
+int _dos_findfirst(char *filename, int x, struct find_t *f);
+int _dos_findnext(struct find_t *f);
+
+#elif PLATFORM_DOS
+/* no-op */
+#else
+#error please define for your platform.
+#endif
+
+
+#if !PLATFORM_DOS
+struct dosdate_t
+{
+ unsigned char day;
+ unsigned char month;
+ unsigned int year;
+ unsigned char dayofweek;
+};
+
+void _dos_getdate(struct dosdate_t *date);
+#endif
+
+
+#if (SOFTERROR==1)
+
+void SoftwareError (char *error, ...) __attribute__((format(printf,1,2)));
+#define SoftError SoftwareError
+
+#else
+void SoftwareError (char *error, ...) __attribute__((format(printf,1,2)));
+//#define SoftError SoftwareError
+
+#define SoftError if (1) {} else SoftwareError
+
+//#define SoftError
+
+#endif
+
+#if (DEBUG==1)
+
+void DebugError (char *error, ...) __attribute__((format(printf,1,2)));
+#define Debug DebugError
+
+#else
+
+void DebugError (char *error, ...) __attribute__((format(printf,1,2)));
+#define Debug DebugError
+//#define Debug
+
+#endif
+
+void Square (void);
+
+#ifdef __WATCOMC__
+#pragma aux Square=\
+ "mov edx,03c4h", \
+ "mov eax,0100h", \
+ "out dx,ax", \
+ "mov eax,0e3h", \
+ "mov edx,03c2h", \
+ "out dx,ax", \
+ "mov eax,0300h", \
+ "mov edx,03c4h", \
+ "out dx,ax" \
+ modify exact [eax edx]
+#endif
+
+
+#ifdef DOS
+void my_outp(int port, int data);
+#else
+#define my_outp(a,b)
+#endif
+
+#ifdef __WATCOMC__
+#pragma aux my_outp = \
+ "out dx,al", \
+ parm [edx] [eax] \
+ modify exact []
+#endif
+
+#define OUTP my_outp
+
+#endif
--- /dev/null
+++ b/rott/rt_vh_a.h
@@ -1,0 +1,36 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_vh_a_public
+#define _rt_vh_a_public
+
+//***************************************************************************
+//
+// Public header for RT_VH_A.ASM.
+//
+//***************************************************************************
+
+void VH_UpdateScreen (void);
+void JoyStick_Vals (void);
+
+#ifdef __WATCOMC__
+#pragma aux JoyStick_Vals modify exact [eax ebx ecx edx esi edi]
+#endif
+
+#endif
--- /dev/null
+++ b/rott/rt_vid.c
@@ -1,0 +1,1341 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef DOS
+#include <dos.h>
+#include <conio.h>
+#endif
+
+#include "rt_def.h"
+#include "rt_vid.h"
+#include "_rt_vid.h"
+#include "rt_menu.h"
+#include "rt_util.h"
+#include "modexlib.h"
+#include "profile.h"
+#include "watcom.h"
+#include "rt_str.h"
+#include "rt_draw.h"
+#include "rt_in.h"
+#include "rt_main.h"
+#include "z_zone.h"
+#include "lumpy.h"
+#include "rt_vh_a.h"
+#include "isr.h"
+#include "rt_view.h"
+#include "cin_efct.h"
+#include "w_wad.h"
+//MED
+#include "memcheck.h"
+
+
+//******************************************************************************
+//
+// GLOBALS
+//
+//******************************************************************************
+
+byte *updateptr;
+unsigned mapwidthtable[64];
+unsigned uwidthtable[UPDATEHIGH];
+unsigned blockstarts[UPDATEWIDE*UPDATEHIGH];
+byte update[UPDATESIZE];
+byte palette1[256][3], palette2[256][3];
+boolean screenfaded;
+
+
+//******************************************************************************
+//
+// LOCALS
+//
+//******************************************************************************
+
+static byte pixmasks[4] = {1,2,4,8};
+static byte leftmasks[4] = {15,14,12,8};
+static byte rightmasks[4] = {1,3,7,15};
+
+
+
+//******************************************************************************
+//
+// VL_MemToScreen ()
+//
+//******************************************************************************
+
+void VL_MemToScreen (byte *source, int width, int height, int x, int y)
+{
+#ifdef DOS
+ byte *screen, *dest, mask;
+ int plane;
+
+ dest = (byte *)(bufferofs+ylookup[y]+(x>>2));
+// dest = (byte *)(displayofs+ylookup[y]+(x>>2));
+ mask = 1 << (x&3);
+
+
+ for (plane = 0; plane<4; plane++)
+ {
+ VGAMAPMASK (mask);
+
+ screen = dest;
+ for (y = 0; y < height; y++, screen += linewidth, source+=width)
+ memcpy (screen, source, width);
+
+
+ mask <<= 1;
+
+ if (mask == 16)
+ {
+ mask = 1;
+ dest++;
+ }
+ }
+#else
+ /* TODO please optimize me */
+
+ byte *ptr, *destline;
+ int plane, i, j;
+
+ ptr = source;
+
+ for (plane = 0; plane < 4; plane++) {
+ for (j = 0; j < height; j++) {
+ destline = (byte *)(bufferofs+ylookup[y+j]+x);
+
+ for (i = 0; i < width; i++) {
+// if (ptr < bufferofs + toplimit) { //bnafix zxcvb
+ *(destline + i*4 + plane) = *ptr++;
+// }
+ }
+ }
+ }
+#endif
+}
+// bna function start
+void VL_MemToScreenClipped (byte *source, int width, int height, int x, int y);
+void VL_MemToScreenClipped (byte *source, int width, int height, int x, int y)
+{
+ byte *ptr, *destline;
+ int plane, i, j;//,toplimit;
+ ptr = source;
+ for (plane = 0; plane < 4; plane++) {
+ for (j = 0; j < height; j++) {
+ destline = (byte *)(bufferofs+ylookup[y+j]+x);
+ for (i = 0; i < width; i++) {
+ if (*ptr != 255) {
+ *(destline + i*4 + plane) = *ptr++;
+ } else {
+ ptr++;
+ }
+ }
+ }
+ }
+}
+
+//copy picture to mem (bufferofs) in doublesize
+void VL_MemStrechedToScreen (byte *source, int width, int height, int x, int y)
+{
+ byte *ptr, *destline,*tmp,*o;
+ int plane, i, j;
+
+ tmp = bufferofs;
+ ptr = source;
+
+ for (plane = 0; plane < 4; plane++) {
+ for (j = 0; j < height; j++) {
+ destline = (byte *)(bufferofs+(iGLOBAL_SCREENWIDTH*j)+ylookup[y+j]+x);
+ o = ptr;
+ for (i = 0; i < width; i+=1) {
+ *(destline + i*4 + plane) = *ptr;
+ destline++;
+ *(destline + i*4 + plane) = *ptr++;
+ }
+ ptr = o;
+
+ destline = (byte *)(bufferofs+iGLOBAL_SCREENWIDTH+(iGLOBAL_SCREENWIDTH*j)+ylookup[y+j]+x);
+ for (i = 0; i < width; i+=1) {
+ *(destline + i*4 + plane) = *ptr;
+ destline++;
+ *(destline + i*4 + plane) = *ptr++;
+
+ }
+
+ }
+ }
+ bufferofs = tmp;
+}
+// bna function end
+
+
+//*************************************************************************
+//
+// DrawTiledRegion () - Fills the specified region with a tiled image
+//
+//*************************************************************************
+void DrawTiledRegion
+(
+ int x,
+ int y,
+ int width,
+ int height,
+ int offx,
+ int offy,
+ pic_t *tile
+)
+
+{
+ byte *source;
+ byte *sourceoff;
+ int sourcex;
+ int sourcey;
+ int sourcewidth;
+ int sourceheight;
+ int mask;
+ int plane;
+ int planesize;
+ byte *start;
+ byte *origdest;
+ byte *dest;
+ int startoffset;
+ int HeightIndex;
+ int WidthIndex;
+
+#ifdef DOS
+ start = ( byte * )( bufferofs + ( x>>2 ) + ylookup[ y ] );
+#else
+ start = ( byte * )( bufferofs + x + ylookup[ y ] );
+#endif
+
+ source = &tile->data;
+ sourcewidth = tile->width;
+ sourceheight = tile->height;
+#ifdef DOS
+ offx >>= 2;
+#endif
+ if ( offx >= sourcewidth )
+ {
+ offx %= sourcewidth;
+ }
+ if ( offy >= sourceheight )
+ {
+ offy %= sourceheight;
+ }
+
+ startoffset = offy * sourcewidth;
+ planesize = sourcewidth * sourceheight;
+
+#ifdef DOS
+ width >>= 2;
+
+ mask = 1 << ( x & 3 );
+#endif
+ plane = 4;
+ while( plane > 0 )
+ {
+ VGAMAPMASK( mask );
+
+#ifdef DOS
+ origdest = start;
+#else
+ origdest = start+(4-plane);
+#endif
+
+ sourcey = offy;
+ sourceoff = source + startoffset;
+ HeightIndex = height;
+
+ while( HeightIndex-- )
+ {
+ dest = origdest;
+ sourcex = offx;
+ WidthIndex = width;
+ while( WidthIndex-- )
+ {
+ *dest = sourceoff[ sourcex ];
+#ifdef DOS
+ dest++;
+#else
+ dest += 4;
+#endif
+
+ sourcex++;
+ if ( sourcex >= sourcewidth )
+ {
+ sourcex = 0;
+ }
+ }
+
+#ifdef DOS
+ origdest += iGLOBAL_SCREENBWIDE;
+#else
+ origdest += iGLOBAL_SCREENWIDTH;
+#endif
+
+ sourceoff += sourcewidth;
+ sourcey++;
+ if ( sourcey >= sourceheight )
+ {
+ sourcey = 0;
+ sourceoff = source;
+ }
+ }
+
+ source += planesize;
+
+#ifdef DOS
+ mask <<= 1;
+ if ( mask > 8 )
+ {
+ mask = 1;
+ }
+#endif
+
+ plane--;
+ }
+}
+
+
+//******************************************************************************
+//
+// VWB_DrawPic () - Draws a linear pic and marks the update block
+//
+//******************************************************************************
+
+void VWB_DrawPic (int x, int y, pic_t *pic)
+{
+ if (((iGLOBAL_SCREENWIDTH > 320) && !StretchScreen) ||
+ VW_MarkUpdateBlock (x, y, x+(pic->width<<2)-1, y+(pic->height)-1))
+ VL_MemToScreen ((byte *)&pic->data, pic->width, pic->height, x, y);
+}
+
+
+
+//******************************************************************************
+//
+// VL_Bar () - Draws a bar
+//
+//******************************************************************************
+
+void VL_Bar (int x, int y, int width, int height, int color)
+{
+#ifdef DOS
+ byte *dest;
+ byte leftmask,rightmask;
+ int midbytes,linedelta;
+
+ leftmask = leftmasks[x&3];
+ rightmask = rightmasks[(x+width-1)&3];
+ midbytes = ((x+width+3)>>2) - (x>>2) - 2;
+ linedelta = linewidth-(midbytes+1);
+
+ dest = (byte *)(bufferofs+ylookup[y]+(x>>2));
+
+ if (midbytes < 0)
+ {
+ // all in one byte
+ VGAMAPMASK (leftmask&rightmask);
+ while (height--)
+ {
+ *dest = color;
+ dest += linewidth;
+ }
+ VGAMAPMASK (15);
+ return;
+ }
+
+ while (height--)
+ {
+ VGAMAPMASK (leftmask);
+ *dest++ = color;
+
+ VGAMAPMASK (15);
+ memset (dest,color,midbytes);
+ dest += midbytes;
+
+ VGAMAPMASK (rightmask);
+ *dest = color;
+
+ dest += linedelta;
+ }
+
+ VGAMAPMASK(15);
+#else
+ byte *dest = (byte *)(bufferofs+ylookup[y]+x);
+
+ while (height--) {
+ memset(dest, color, width);
+
+ dest += linewidth;
+ }
+#endif
+}
+
+
+
+//******************************************************************************
+//
+// VWB_Bar () - Draws a block and marks the update block
+//
+//******************************************************************************
+
+void VWB_Bar (int x, int y, int width, int height, int color)
+{
+ if (((iGLOBAL_SCREENWIDTH > 320) && !StretchScreen) ||
+ VW_MarkUpdateBlock (x,y,x+width,y+height-1) )
+ VL_Bar (x, y, width, height, color);
+}
+
+
+//******************************************************************************
+//
+// VL_TBar () - Draws a bar
+//
+//******************************************************************************
+
+void VL_TBar (int x, int y, int width, int height)
+{
+#ifdef DOS
+ byte *dest;
+ byte pixel;
+ byte readmask;
+ byte writemask;
+ int w = width;
+
+ while (height--)
+ {
+ width = w;
+
+ dest = (byte*)(bufferofs+ylookup[y]+(x>>2));
+ readmask = (x&3);
+ writemask = 1 << readmask;
+
+ VGAREADMAP (readmask);
+ VGAMAPMASK (writemask);
+
+ while (width--)
+ {
+ pixel = *dest;
+
+ pixel = *(colormap+(27<<8)+pixel);
+
+ *dest = pixel;
+
+ writemask <<= 1;
+ if (writemask == 16)
+ {
+ writemask = 1;
+ dest++;
+ }
+
+ readmask++;
+ if (readmask == 4)
+ readmask = 0;
+
+ VGAREADMAP (readmask);
+ VGAMAPMASK (writemask);
+ }
+
+ y++;
+ }
+#else
+ int w = width;
+
+ while (height--) {
+ byte *dest = (byte *)(bufferofs+ylookup[y]+x);
+
+ width = w;
+
+ while (width--) {
+ byte pixel = *dest;
+
+ pixel = *(colormap+(27<<8)+pixel);
+
+ *dest = pixel;
+
+ dest++;
+ }
+
+ y++;
+ }
+
+#endif
+}
+
+
+
+//******************************************************************************
+//
+// VWB_TBar () - Draws a block and marks the update block
+//
+//******************************************************************************
+
+void VWB_TBar (int x, int y, int width, int height)
+{
+ if (VW_MarkUpdateBlock (x,y,x+width,y+height-1))
+ VL_TBar (x, y, width, height);
+}
+
+
+//******************************************************************************
+//
+// VL_Hlin () - Draws a horizontal line
+//
+//******************************************************************************
+
+void VL_Hlin (unsigned x, unsigned y, unsigned width, unsigned color)
+{
+#ifdef DOS
+ unsigned xbyte;
+ byte *dest;
+ byte leftmask,
+ rightmask;
+ int midbytes;
+
+ xbyte = x >> 2;
+ leftmask = leftmasks[x&3];
+ rightmask = rightmasks[(x+width-1)&3];
+ midbytes = ((x+width+3)>>2) - xbyte - 2;
+
+ dest = (byte*)(bufferofs+ylookup[y]+xbyte);
+
+ if (midbytes<0)
+ {
+ // all in one byte
+ VGAMAPMASK (leftmask & rightmask);
+ *dest = color;
+ VGAMAPMASK(15);
+ return;
+ }
+
+ VGAMAPMASK (leftmask);
+ *dest++ = color;
+
+ VGAMAPMASK (15);
+ memset (dest, color, midbytes);
+ dest += midbytes;
+
+ VGAMAPMASK (rightmask);
+ *dest = color;
+
+ VGAMAPMASK (15);
+#else
+ byte *dest = (byte*)(bufferofs+ylookup[y]+x);
+
+ memset(dest, color, width);
+#endif
+}
+
+
+//******************************************************************************
+//
+// VL_Vlin () - Draws a vertical line
+//
+//******************************************************************************
+
+void VL_Vlin (int x, int y, int height, int color)
+{
+#ifdef DOS
+ byte *dest,
+ mask;
+
+ mask = pixmasks[x&3];
+ VGAMAPMASK (mask);
+
+ dest = (byte *)(bufferofs+ylookup[y]+(x>>2));
+
+ while (height--)
+ {
+ *dest = color;
+ dest += linewidth;
+ }
+
+ VGAMAPMASK (15);
+#else
+ byte *dest = (byte*)(bufferofs+ylookup[y]+x);
+
+ while (height--) {
+ *dest = color;
+
+ dest += linewidth;
+ }
+#endif
+}
+
+
+
+//******************************************************************************
+//
+// VWB_Hlin () - Draws a horizontal line and marks the update block
+//
+//******************************************************************************
+
+void VWB_Hlin (int x1, int x2, int y, int color)
+{
+ if (VW_MarkUpdateBlock (x1,y,x2,y))
+ VW_Hlin(x1,x2,y,color);
+}
+
+
+//******************************************************************************
+//
+// VWB_Vlin () - Draws a vertical line and marks the update block
+//
+//******************************************************************************
+
+void VWB_Vlin (int y1, int y2, int x, int color)
+{
+ if (VW_MarkUpdateBlock (x,y1,x,y2))
+ VW_Vlin(y1,y2,x,color);
+}
+
+
+
+
+//******************************************************************************
+//
+// VL_THlin ()
+//
+//******************************************************************************
+
+void VL_THlin (unsigned x, unsigned y, unsigned width, boolean up)
+{
+#ifdef DOS
+ byte *dest;
+ byte pixel;
+ byte readmask;
+ byte writemask;
+
+
+ readmask = (x&3);
+ writemask = 1 << readmask;
+
+ dest = (byte*)(bufferofs+ylookup[y]+(x>>2));
+
+ VGAREADMAP (readmask);
+ VGAMAPMASK (writemask);
+
+ while (width--)
+ {
+ pixel = *dest;
+
+ if (up)
+ pixel = *(colormap+(13<<8)+pixel);
+ else
+ pixel = *(colormap+(27<<8)+pixel);
+
+ *dest = pixel;
+
+ writemask <<= 1;
+ if (writemask == 16)
+ {
+ writemask = 1;
+ dest++;
+ }
+
+ readmask++;
+ if (readmask == 4)
+ readmask = 0;
+
+ VGAREADMAP (readmask);
+ VGAMAPMASK (writemask);
+ }
+#else
+ byte *dest = (byte*)(bufferofs+ylookup[y]+x);
+
+ while (width--) {
+ byte pixel = *dest;
+
+ if (up) {
+ pixel = *(colormap+(13<<8)+pixel);
+ } else {
+ pixel = *(colormap+(27<<8)+pixel);
+ }
+
+ *dest = pixel;
+
+ dest++;
+ }
+#endif
+}
+
+
+
+//******************************************************************************
+//
+// VL_TVlin ()
+//
+//******************************************************************************
+
+void VL_TVlin (unsigned x, unsigned y, unsigned height, boolean up)
+{
+#ifdef DOS
+ byte *dest;
+ byte pixel;
+ byte readmask;
+ byte writemask;
+
+
+
+ readmask = (x&3);
+ writemask = 1 << readmask;
+
+ dest = (byte*)(bufferofs+ylookup[y]+(x>>2));
+
+ VGAREADMAP (readmask);
+ VGAMAPMASK (writemask);
+
+ while (height--)
+ {
+ pixel = *dest;
+
+ if (up)
+ pixel = *(colormap+(13<<8)+pixel);
+ else
+ pixel = *(colormap+(27<<8)+pixel);
+
+ *dest = pixel;
+
+ dest += linewidth;
+ }
+#else
+ byte *dest = (byte*)(bufferofs+ylookup[y]+x);
+
+ while (height--) {
+ byte pixel = *dest;
+
+ if (up) {
+ pixel = *(colormap+(13<<8)+pixel);
+ } else {
+ pixel = *(colormap+(27<<8)+pixel);
+ }
+
+ *dest = pixel;
+
+ dest += linewidth;
+ }
+#endif
+}
+
+
+
+//******************************************************************************
+//
+// VWB_THlin () - Draws a horizontal line and marks the update block
+//
+//******************************************************************************
+
+void VWB_THlin (int x1, int x2, int y, boolean up)
+{
+ if (VW_MarkUpdateBlock (x1,y,x2,y))
+ VW_THlin (x1,x2,y,up);
+}
+
+
+//******************************************************************************
+//
+// VWB_TVlin () - Draws a vertical line and marks the update block
+//
+//******************************************************************************
+
+void VWB_TVlin (int y1, int y2, int x, boolean up)
+{
+ if (VW_MarkUpdateBlock (x,y1,x,y2))
+ VW_TVlin (y1,y2,x,up);
+}
+
+
+
+/*
+================================================================================
+
+ Double buffer management routines
+
+================================================================================
+*/
+
+
+//******************************************************************************
+//
+// VW_MarkUpdateBlock
+//
+// Takes a pixel bounded block and marks the tiles in bufferblocks
+// Returns 0 if the entire block is off the buffer screen
+//
+//******************************************************************************
+
+int VW_MarkUpdateBlock (int x1, int y1, int x2, int y2)
+{
+ int x,
+ y,
+ xt1,
+ yt1,
+ xt2,
+ yt2,
+ nextline;
+ byte *mark;
+
+ xt1 = x1 >> PIXTOBLOCK;
+ yt1 = y1 >> PIXTOBLOCK;
+
+ xt2 = x2 >> PIXTOBLOCK;
+ yt2 = y2 >> PIXTOBLOCK;
+
+ if (xt1 < 0)
+ xt1 = 0;
+ else if (xt1 >= UPDATEWIDE)
+ return 0;
+
+ if (yt1 < 0)
+ yt1 = 0;
+ else if (yt1 > UPDATEHIGH)
+ return 0;
+
+ if (xt2 < 0)
+ return 0;
+ else if (xt2 >= UPDATEWIDE)
+ xt2 = UPDATEWIDE-1;
+
+ if (yt2 < 0)
+ return 0;
+ else if (yt2 >= UPDATEHIGH)
+ yt2 = UPDATEHIGH-1;
+
+ mark = updateptr + uwidthtable[yt1] + xt1;
+ nextline = UPDATEWIDE - (xt2-xt1) - 1;
+
+ for (y = yt1; y <= yt2; y++)
+ {
+ for (x = xt1; x <= xt2; x++)
+ *mark++ = 1; // this tile will need to be updated
+
+ mark += nextline;
+ }
+
+ return 1;
+}
+
+
+//******************************************************************************
+//
+// VW_UpdateScreen ()
+//
+//******************************************************************************
+
+
+void VW_UpdateScreen (void)
+{
+ VH_UpdateScreen ();
+}
+
+//===========================================================================
+
+/*
+=================
+=
+= VL_FadeOut
+=
+= Fades the current palette to the given color in the given number of steps
+=
+=================
+*/
+
+void VL_FadeOut (int start, int end, int red, int green, int blue, int steps)
+{
+ int i,j,orig,delta;
+ byte *origptr, *newptr;
+
+ if (screenfaded)
+ return;
+
+ WaitVBL ();
+ VL_GetPalette (&palette1[0][0]);
+ memcpy (palette2, palette1, 768);
+
+//
+// fade through intermediate frames
+//
+ for (i = 0; i < steps; i++)
+ {
+ origptr = &palette1[start][0];
+ newptr = &palette2[start][0];
+
+ for (j = start; j <= end; j++)
+ {
+ orig = *origptr++;
+ delta = red-orig;
+ *newptr++ = orig + delta * i / steps;
+ orig = *origptr++;
+ delta = green-orig;
+ *newptr++ = orig + delta * i / steps;
+ orig = *origptr++;
+ delta = blue-orig;
+ *newptr++ = orig + delta * i / steps;
+ }
+
+ WaitVBL ();
+ VL_SetPalette (&palette2[0][0]);
+ }
+
+//
+// final color
+//
+ VL_FillPalette (red,green,blue);
+
+ screenfaded = true;
+}
+
+
+/*
+=================
+=
+= VL_FadeToColor
+=
+= Fades the current palette to the given color in the given number of steps
+=
+=================
+*/
+
+void VL_FadeToColor (int time, int red, int green, int blue)
+{
+ int i,j,orig,delta;
+ byte *origptr, *newptr;
+ int dmax,dmin;
+
+ if (screenfaded)
+ return;
+
+ WaitVBL ();
+ VL_GetPalette (&palette1[0][0]);
+ memcpy (palette2, palette1, 768);
+
+ dmax=(maxshade<<16)/time;
+ dmin=(minshade<<16)/time;
+//
+// fade through intermediate frames
+//
+ for (i = 0; i < time; i+=tics)
+ {
+ origptr = &palette1[0][0];
+ newptr = &palette2[0][0];
+
+ for (j = 0; j <= 255; j++)
+ {
+ orig = *origptr++;
+ delta = ((red>>2)-orig)<<16;
+ *newptr++ = orig + FixedMul(delta/time,i);
+ orig = *origptr++;
+ delta = ((green>>2)-orig)<<16;
+ *newptr++ = orig + FixedMul(delta/time,i);
+ orig = *origptr++;
+ delta = ((blue>>2)-orig)<<16;
+ *newptr++ = orig + FixedMul(delta/time,i);
+ }
+
+ maxshade=(dmax*(time-i))>>16;
+ minshade=(dmin*(time-i))>>16;
+ WaitVBL ();
+ VL_SetPalette (&palette2[0][0]);
+ ThreeDRefresh();
+ CalcTics();
+
+ }
+
+//
+// final color
+//
+ VL_FillPalette (red>>2,green>>2,blue>>2);
+
+ screenfaded = true;
+}
+
+
+
+
+/*
+=================
+=
+= VL_FadeIn
+=
+=================
+*/
+
+void VL_FadeIn (int start, int end, byte *palette, int steps)
+{
+ int i,j,delta;
+
+ WaitVBL ();
+ VL_GetPalette (&palette1[0][0]);
+
+ memcpy (&palette2[0][0], &palette1[0][0], sizeof(palette1));
+
+ start *= 3;
+ end = end*3+2;
+
+//
+// fade through intermediate frames
+//
+ for (i=0; i<steps; i++)
+ {
+ for (j=start; j<=end; j++)
+ {
+ delta = palette[j]-palette1[0][j];
+ palette2[0][j] = palette1[0][j] + delta * i / steps;
+ }
+
+ WaitVBL ();
+ VL_SetPalette (&palette2[0][0]);
+ }
+
+//
+// final color
+//
+ VL_SetPalette (palette);
+ screenfaded = false;
+}
+
+
+
+//******************************************************************************
+//
+// SwitchPalette
+//
+//******************************************************************************
+
+void SwitchPalette (byte * newpal, int steps)
+{
+ byte *temp;
+
+ VL_FadeOut(0,255,0,0,0,steps>>1);
+
+ temp = bufferofs;
+ bufferofs = displayofs;
+ VL_Bar (0, 0, 320, 200, 0);
+ bufferofs = temp;
+
+ VL_FadeIn(0,255,newpal,steps>>1);
+}
+
+
+#if 0
+
+/*
+=================
+=
+= VL_TestPaletteSet
+=
+= Sets the palette with outsb, then reads it in and compares
+= If it compares ok, fastpalette is set to true.
+=
+=================
+*/
+
+void VL_TestPaletteSet (void)
+{
+ int i;
+
+ for (i=0; i<768; i++)
+ palette1[0][i] = i;
+
+ fastpalette = true;
+ VL_SetPalette (&palette1[0][0]);
+ VL_GetPalette (&palette2[0][0]);
+ if (_fmemcmp (&palette1[0][0],&palette2[0][0],768))
+ fastpalette = false;
+}
+
+
+/*
+==================
+=
+= VL_ColorBorder
+=
+==================
+*/
+
+void VL_ColorBorder (int color)
+{
+ _AH=0x10;
+ _AL=1;
+ _BH=color;
+ geninterrupt (0x10);
+ bordercolor = color;
+}
+
+
+#endif
+
+
+//==========================================================================
+
+//****************************************************************************
+//
+// VL_DecompressLBM ()
+//
+// LIMITATIONS - Only works with 320x200!!!
+//
+//****************************************************************************
+
+void VL_DecompressLBM (lbm_t *lbminfo, boolean flip)
+{
+ int count;
+ byte b, rept;
+ byte *source = (byte *)&lbminfo->data;
+ byte *buf;
+ int ht = lbminfo->height;
+ byte pal[768];
+
+ EnableScreenStretch();
+
+ memcpy(&pal[0],lbminfo->palette,768);
+
+ VL_NormalizePalette (&pal[0]);
+
+ VW_MarkUpdateBlock (0, 0, 320, 200);
+
+ buf = (byte *)bufferofs;
+
+ while (ht--)
+ {
+ count = 0;
+
+ do
+ {
+ rept = *source++;
+
+ if (rept > 0x80)
+ {
+ rept = (rept^0xff)+2;
+ b = *source++;
+ memset (buf, b, rept);
+ buf += rept;
+ }
+ else if (rept < 0x80)
+ {
+ rept++;
+ memcpy (buf, source, rept);
+ buf += rept;
+ source += rept;
+ }
+ else
+ rept = 0; // rept of 0x80 is NOP
+
+ count += rept;
+
+ } while (count < lbminfo->width);
+ if (iGLOBAL_SCREENWIDTH > 320) {
+ buf += (iGLOBAL_SCREENWIDTH-320); //eg 800 - 320)
+ }
+ }
+
+ if (flip==true)
+ VW_UpdateScreen ();
+
+ VL_FadeIn (0, 255, &pal[0], 15);
+
+}
+
+//****************************************************************************
+//
+// SetBorderColor
+//
+//****************************************************************************
+
+void SetBorderColor (int color)
+{
+ // bna section start
+
+ byte *cnt,*Ycnt,*b;
+
+ b=(byte *)bufferofs;
+
+ // color 56 could be used
+
+ //paint top red line
+ for (cnt=b; cnt<b+viewwidth; cnt++) {
+ for (Ycnt=cnt; Ycnt<cnt+(5*iGLOBAL_SCREENWIDTH); Ycnt+=iGLOBAL_SCREENWIDTH) {
+ *Ycnt = color;
+ }
+ }
+ //paint left red line
+ for (cnt=b; cnt<b+5; cnt++) {
+ for (Ycnt=cnt; Ycnt<cnt+(viewheight*iGLOBAL_SCREENWIDTH); Ycnt+=iGLOBAL_SCREENWIDTH) {
+ *Ycnt = color;
+ }
+ }
+ //paint right red line
+ for (cnt=b+(viewwidth-5); cnt<b+viewwidth; cnt++) {
+ for (Ycnt=cnt; Ycnt<cnt+(viewheight*iGLOBAL_SCREENWIDTH); Ycnt+=iGLOBAL_SCREENWIDTH) {
+ *Ycnt = color;
+ }
+ }
+ //paint lower red line
+ for (cnt=b+((viewheight-5)*iGLOBAL_SCREENWIDTH); cnt<b+((viewheight-5)*iGLOBAL_SCREENWIDTH)+viewwidth; cnt++) {
+ for (Ycnt=cnt; Ycnt<b+(viewheight*iGLOBAL_SCREENWIDTH); Ycnt+=iGLOBAL_SCREENWIDTH) {
+ *Ycnt = color;
+ }
+ }
+ // bna section end
+
+#ifdef DOS
+ inp (STATUS_REGISTER_1);
+ outp (ATR_INDEX,0x31);
+ outp (ATR_INDEX,color);
+#endif
+}
+
+//****************************************************************************
+//
+// SetBorderColorInterrupt
+//
+//****************************************************************************
+
+void SetBorderColorInterrupt (int color)
+{
+#ifdef DOS
+ union REGS regs;
+
+ regs.w.ax = 0x1001;
+ regs.w.bx = color<<8;
+ int386(0x10,®s,®s);
+#else
+ STUB_FUNCTION;
+#endif
+}
+
+
+//****************************************************************************
+//
+// VL_DrawPostPic
+//
+//****************************************************************************
+
+void VL_DrawPostPic (int lumpnum)
+{
+ DrawPostPic(lumpnum);
+ VW_MarkUpdateBlock (0, 0, 319, 199);
+}
+
+//****************************************************************************
+//
+// VL_DrawLine
+//
+//****************************************************************************
+
+void VL_DrawLine (int x1, int y1, int x2, int y2, byte color)
+{
+ int dx;
+ int dy;
+ int xinc;
+ int yinc;
+ int count;
+
+ dx=(x2-x1);
+ dy=(y2-y1);
+ if (abs(dy)>=abs(dx))
+ {
+ count=abs(dy);
+ yinc=(dy<<16)/count;
+ if (dy==0)
+ {
+ return;
+ }
+ else
+ {
+ xinc=(dx<<16)/count;
+ }
+ }
+ else
+ {
+ count=abs(dx);
+ xinc=(dx<<16)/count;
+ if (dx==0)
+ {
+ return;
+ }
+ else
+ {
+ yinc=(dy<<16)/count;
+ }
+ }
+ x1<<=16;
+ y1<<=16;
+ while (count>0)
+ {
+#ifdef DOS
+ VGAWRITEMAP((x1>>16)&3);
+ *((byte *)bufferofs+(x1>>18)+(ylookup[y1>>16]))=color;
+#else
+ *((byte *)bufferofs+(x1>>16)+(ylookup[y1>>16]))=color;
+#endif
+ x1+=xinc;
+ y1+=yinc;
+ count--;
+ }
+}
+
+
+//******************************************************************************
+//
+// DrawXYPic
+//
+//******************************************************************************
+
+void DrawXYPic (int x, int y, int shapenum)
+{
+ byte *buffer;
+ byte *buf;
+ int xx,yy;
+ int plane;
+ byte *src;
+ pic_t *p;
+
+ p = (pic_t *) W_CacheLumpNum (shapenum, PU_CACHE, Cvt_pic_t, 1);
+
+ if ((x<0) || ((x+(p->width<<2))>=320))
+ Error ("DrawXYPic: x is out of range\n");
+ if ((y<0) || ((y+p->height)>=200))
+ Error ("DrawXYPic: y is out of range\n");
+
+#ifdef DOS
+ buffer = (byte*)bufferofs+(x>>2)+ylookup[y];
+#else
+ buffer = (byte*)bufferofs+ylookup[y];
+#endif
+
+ src=(byte *)&p->data;
+
+ for (plane=x; plane<x+4; plane++)
+ {
+ VGAWRITEMAP((plane&3));
+ for (yy = 0; yy < p->height; yy++)
+ {
+ buf=buffer+ylookup[yy];
+ for (xx = 0; xx < p->width; xx++,buf++)
+#ifdef DOS
+ *(buf)=*(src++);
+#else
+ *(buf+plane+xx*4)=*(src++);
+#endif
+ }
+ }
+}
--- /dev/null
+++ b/rott/rt_vid.h
@@ -1,0 +1,94 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _rt_vid_public
+#define _rt_vid_public
+
+//***************************************************************************
+//
+// Public header for RT_VID.C
+//
+//***************************************************************************
+
+#include "lumpy.h"
+
+//***************************************************************************
+//
+// DEFINES
+//
+//***************************************************************************
+
+#define PORTTILESWIDE 20 // all drawing takes place inside a
+#define PORTTILESHIGH 13 // non displayed port of this size
+
+#define UPDATEWIDE PORTTILESWIDE
+#define UPDATEHIGH PORTTILESHIGH
+#define UPDATESIZE (UPDATEWIDE*UPDATEHIGH)
+
+
+//***************************************************************************
+//
+// GLOBALS
+//
+//***************************************************************************
+
+extern byte *updateptr;
+extern unsigned mapwidthtable[64];
+extern unsigned uwidthtable[UPDATEHIGH];
+extern unsigned blockstarts[UPDATEWIDE*UPDATEHIGH];
+extern byte update[UPDATESIZE];
+extern boolean screenfaded;
+
+
+//***************************************************************************
+//
+// PROTOTYPES
+//
+//***************************************************************************
+void VL_MemStrechedToScreen (byte *source, int width, int height, int x, int y);
+void VL_MemToScreen (byte *source, int width, int height, int x, int y);
+void DrawTiledRegion( int x, int y, int width, int height, int offx, int offy, pic_t *tile );
+void VWB_DrawPic (int x, int y, pic_t *pic);
+void VL_Bar (int x, int y, int width, int height, int color);
+void VWB_Bar (int x, int y, int width, int height, int color);
+void VWB_Hlin (int x1, int x2, int y, int color);
+void VWB_Vlin (int y1, int y2, int x, int color);
+void VWB_THlin (int x1, int x2, int y, boolean up);
+void VWB_TVlin (int y1, int y2, int x, boolean up);
+int VW_MarkUpdateBlock (int x1, int y1, int x2, int y2);
+void VW_UpdateScreen (void);
+
+void VL_FadeOut (int start, int end, int red, int green, int blue, int steps);
+void VL_FadeIn (int start, int end, byte *palette, int steps);
+void VL_DecompressLBM (lbm_t *lbminfo, boolean flip);
+void VL_FadeToColor (int time, int red, int green, int blue);
+void VWB_TBar (int x, int y, int width, int height);
+
+void SwitchPalette (byte * newpal, int steps);
+void SetBorderColor (int color);
+
+void VL_DrawPostPic (int lumpnum);
+void VL_DrawLine (int x1, int y1, int x2, int y2, byte color);
+
+#define MenuFadeOut() VL_FadeOut (0, 255, 0, 0, 0, 10)
+#define MenuFadeIn() VL_FadeIn (0, 255, origpal, 10)
+
+void DrawXYPic (int x, int y, int shapenum);
+
+#endif
--- /dev/null
+++ b/rott/rt_view.c
@@ -1,0 +1,952 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include "rt_def.h"
+#include "rt_view.h"
+#include "z_zone.h"
+#include "w_wad.h"
+#include "lumpy.h"
+#include "rt_util.h"
+#include "rt_vid.h"
+#include "rt_game.h"
+#include "rt_draw.h"
+#include "rt_ted.h"
+#include "isr.h"
+#include "rt_rand.h"
+#include "rt_sound.h"
+#include "modexlib.h"
+#include "rt_menu.h"
+
+#ifdef DOS
+#include <mem.h>
+#endif
+
+#include <stdlib.h>
+
+#include "rt_main.h"
+#include "rt_battl.h"
+#include "rt_floor.h"
+#include "rt_str.h"
+#include "watcom.h"
+#include "develop.h"
+//MED
+#include "memcheck.h"
+
+#define LIGHTNINGLEVEL 4
+#define MINLIGHTNINGLEVEL 2
+#define MAXLIGHTNINGLEVEL 10
+
+/*
+=============================================================================
+
+ GLOBALS
+
+=============================================================================
+*/
+extern int G_weaponscale;
+
+
+int StatusBar = 0;
+int lightninglevel=0;
+boolean lightning=false;
+int normalshade;
+int darknesslevel;
+int maxshade;
+int minshade;
+int baseminshade;
+int basemaxshade;
+int viewheight;
+int viewwidth;
+longword heightnumerator;
+fixed scale;
+int screenofs;
+int centerx;
+int centery;
+int centeryfrac;
+int fulllight;
+int weaponscale;
+int viewsize;
+byte * colormap;
+byte * redmap;
+byte * greenmap;
+byte * playermaps[MAXPLAYERCOLORS];
+//short pixelangle[MAXVIEWWIDTH];
+short pixelangle[800];
+byte gammatable[GAMMAENTRIES];
+int gammaindex;
+int focalwidth=160;
+int yzangleconverter;
+byte uniformcolors[MAXPLAYERCOLORS]= {
+ 25,
+ 222,
+ 29,
+ 206,
+ 52,
+ 6,
+ 155,
+ 16,
+ 90,
+ 129,
+ 109
+};
+
+#ifdef DOS
+byte mapmasks1[4][9] = {
+ {1,3,7,15,15,15,15,15,15},
+ {2,6,14,14,14,14,14,14,14},
+ {4,12,12,12,12,12,12,12,12},
+ {8,8,8,8,8,8,8,8,8}
+};
+
+byte mapmasks2[4][9] = {
+ {0,0,0,0,1,3,7,15,15},
+ {0,0,0,1,3,7,15,15,15},
+ {0,0,1,3,7,15,15,15,15},
+ {0,1,3,7,15,15,15,15,15}
+};
+
+byte mapmasks3[4][9] = {
+ {0,0,0,0,0,0,0,0,1},
+ {0,0,0,0,0,0,0,1,3},
+ {0,0,0,0,0,0,1,3,7},
+ {0,0,0,0,0,1,3,7,15}
+};
+#endif
+
+
+/*
+=============================================================================
+
+ LOCAL
+
+=============================================================================
+*/
+
+static char *YourComputerSucksString = "Buy a 486! :)";
+
+static int viewsizes[MAXVIEWSIZES*2]= { 80,48,
+ 128,72,
+ 160,88,
+ 192,104,
+ 224,120,
+ 256,136,
+ 288,152,
+ 320,168,
+ 320,184,
+ 320,200,
+ 320,200
+ };
+
+static int ColorMapLoaded=0;
+
+static int lightningtime=0;
+static int lightningdelta=0;
+static int lightningdistance=0;
+static int lightningsoundtime=0;
+static boolean periodic=false;
+static int periodictime=0;
+
+void SetViewDelta ( void );
+void UpdatePeriodicLighting (void);
+
+/*
+====================
+=
+= ResetFocalWidth
+=
+====================
+*/
+void ResetFocalWidth ( void )
+{
+ focalwidth=iGLOBAL_FOCALWIDTH;//FOCALWIDTH;
+ SetViewDelta();
+}
+
+/*
+====================
+=
+= ChangeFocalWidth
+=
+====================
+*/
+void ChangeFocalWidth ( int amount )
+{
+ focalwidth=iGLOBAL_FOCALWIDTH+amount;//FOCALWIDTH+amount;
+ SetViewDelta();
+}
+
+
+/*
+====================
+=
+= SetViewDelta
+=
+====================
+*/
+
+void SetViewDelta ( void )
+{
+//iGLOBAL_SCREENHEIGHT
+//iGLOBAL_SCREENWIDTH
+//
+// calculate scale value for vertical height calculations
+// and sprite x calculations
+//
+ if ( iGLOBAL_SCREENWIDTH == 320) {
+ scale = (centerx*focalwidth)/(160);
+ } else if ( iGLOBAL_SCREENWIDTH == 640) {
+ scale = (centerx*focalwidth)/(160);
+ } else if ( iGLOBAL_SCREENWIDTH == 800) {
+ scale = (centerx*focalwidth)/(160);
+ }
+//
+// divide heightnumerator by a posts distance to get the posts height for
+// the heightbuffer. The pixel height is height>>HEIGHTFRACTION
+//
+ heightnumerator = (((focalwidth/10)*centerx*4096)<<HEIGHTFRACTION);
+}
+
+/*
+====================
+=
+= CalcProjection
+=
+====================
+*/
+
+void CalcProjection ( void )
+{
+ int i;
+ int frac;
+ int intang;
+ byte * table;
+ byte * ptr;
+ int length;
+ int * pangle;
+
+
+
+// Already being called in ResetFocalWidth
+// SetViewDelta();
+
+//
+// load in tables file
+//
+
+
+//Hey, isn't this stuff already loaded in?
+//Why don't we make this a lump?
+ table=W_CacheLumpName("tables",PU_STATIC, CvtNull, 1);
+ ptr=table;
+
+//
+// get size of table
+//
+
+ memcpy(&length,ptr,sizeof(int));
+ SwapIntelLong(&length);
+ ptr+=sizeof(int);
+ pangle=SafeMalloc(length*sizeof(int));
+ memcpy(pangle,ptr,length*sizeof(int));
+
+ frac=((length*65536/centerx))>>1;
+ for (i=0; i<centerx; i++)
+ {
+ // start 1/2 pixel over, so viewangle bisects two middle pixels
+ intang=pangle[frac>>16];
+ SwapIntelLong(&intang);
+ pixelangle[centerx-1-i] =(short) intang;
+ pixelangle[centerx+i] =(short) -intang;
+ frac+=(length*65536/centerx);
+ }
+ table=W_CacheLumpName("tables",PU_CACHE, CvtNull, 1);
+ SafeFree(pangle);
+}
+
+
+/*
+==========================
+=
+= SetViewSize
+=
+==========================
+*/
+
+void SetViewSize
+(
+ int size
+)
+
+{
+ int height;
+ int maxheight;
+ int screenx;
+ int screeny;
+ int topy;
+ /*
+ if (size>=10){
+
+ SetTextMode ( );
+ screenx=screenx;
+ return;
+ }
+ */
+
+ if ( iGLOBAL_SCREENWIDTH == 640) {
+ height = 0;//we use height as dummy cnt
+ viewsizes[height++]= 380;
+ viewsizes[height++]= 336;
+ viewsizes[height++]= 428;
+ viewsizes[height++]= 352;
+ viewsizes[height++]= 460;
+ viewsizes[height++]= 368;
+ viewsizes[height++]= 492;
+ viewsizes[height++]= 384;
+ viewsizes[height++]= 524;
+ viewsizes[height++]= 400;
+ viewsizes[height++]= 556;
+ viewsizes[height++]= 416;
+ viewsizes[height++]= 588;
+ viewsizes[height++]= 432;
+ viewsizes[height++]= 640;
+ viewsizes[height++]= 448;
+ viewsizes[height++]= 640;
+ viewsizes[height++]= 464;
+ viewsizes[height++]= 640;
+ viewsizes[height++]= 480;
+ viewsizes[height++]= 640;
+ viewsizes[height++]= 480;
+ } else if ( iGLOBAL_SCREENWIDTH == 800) {
+ height = 0;
+ viewsizes[height++]= 556;
+ viewsizes[height++]= 488;
+ viewsizes[height++]= 588;
+ viewsizes[height++]= 504;
+ viewsizes[height++]= 620;
+ viewsizes[height++]= 520;
+ viewsizes[height++]= 652;
+ viewsizes[height++]= 536;
+ viewsizes[height++]= 684;
+ viewsizes[height++]= 552;
+ viewsizes[height++]= 716;
+ viewsizes[height++]= 568;
+ viewsizes[height++]= 748;
+ viewsizes[height++]= 584;
+ viewsizes[height++]= 800;
+ viewsizes[height++]= 600;
+ viewsizes[height++]= 800;
+ viewsizes[height++]= 600;
+ viewsizes[height++]= 800;
+ viewsizes[height++]= 600;
+ viewsizes[height++]= 800;
+ viewsizes[height++]= 600;
+ }
+
+
+ if ((size<0) || (size>=MAXVIEWSIZES)) { //bna added
+ printf("Illegal screen size = %d\n",size);
+ size = 8;//set default value
+ viewsize = 8;
+ }
+
+ //if ((size<0) || (size>=MAXVIEWSIZES))
+ // Error("Illegal screen size = %ld\n",size);
+
+ viewwidth = viewsizes[ size << 1 ]; // must be divisable by 16
+ viewheight = viewsizes[ ( size << 1 ) + 1 ]; // must be even
+
+ maxheight = iGLOBAL_SCREENHEIGHT;
+ topy = 0;
+
+ // Only keep the kills flag
+ StatusBar &= ~( BOTTOM_STATUS_BAR | TOP_STATUS_BAR |
+ STATUS_PLAYER_STATS );
+
+ if ( SHOW_KILLS() )
+ {
+ // Account for height of kill boxes
+ maxheight -= 24;
+ }
+
+ if ( size < 9 )
+ {
+ StatusBar |= TOP_STATUS_BAR;
+
+ // Account for height of top status bar
+ maxheight -= 16;
+ topy += 16;
+ }
+
+// if ( size == 7 ){maxheight -= 16;}//bna++
+// if ( size <= 6 ){topy -= 8;}//bna++
+
+ if ( size < 8 )
+ {
+ // Turn on health and ammo bar
+ StatusBar |= BOTTOM_STATUS_BAR;
+
+ maxheight -= 16;
+
+ }
+ else if ( size < 10 )
+ {
+ // Turn on transparent health and ammo bar
+ StatusBar |= STATUS_PLAYER_STATS;
+ }
+ // SetTextMode ( );
+ // viewheight=viewheight;
+ height = viewheight;
+ if ( height > 168*iGLOBAL_SCREENHEIGHT/200 )
+ {
+ // Prevent weapon from being scaled too big
+ height = 168*iGLOBAL_SCREENHEIGHT/200;
+ }
+
+ weaponscale = ( height << 16 ) / 168;//( height << 16 ) = 170 * 65536
+
+
+ centerx = viewwidth >> 1;
+ centery = viewheight >> 1;
+ centeryfrac = (centery << 16);
+ yzangleconverter = ( 0xaf85 * viewheight ) / iGLOBAL_SCREENHEIGHT;
+
+ // Center the view horizontally
+ screenx = ( iGLOBAL_SCREENWIDTH - viewwidth ) >> 1;
+
+ if ( viewheight >= maxheight )
+ {
+ screeny = topy;
+ viewheight = maxheight;
+ }
+ else
+ {
+ // Center the view vertically
+ screeny = ( ( maxheight - viewheight ) >> 1 ) + topy;
+ }
+
+ // Calculate offset of view window
+#ifdef DOS
+ screenofs = ( screenx >> 2 ) + ylookup[ screeny ];
+#else
+ screenofs = screenx + ylookup[ screeny ];
+#endif
+
+//
+// calculate trace angles and projection constants
+//
+
+ ResetFocalWidth();
+
+
+// Already being called in ResetFocalWidth
+// SetViewDelta();
+
+
+ CalcProjection();
+
+}
+
+
+//******************************************************************************
+//
+// DrawCPUJape ()
+//
+//******************************************************************************
+
+void DrawCPUJape
+(
+ void
+)
+
+{
+ int width;
+ int height;
+
+ CurrentFont = tinyfont;
+ VW_MeasurePropString( YourComputerSucksString, &width, &height );
+
+ DrawGameString( 160 - width / 2, 100 + 48 / 2 + 2,
+ YourComputerSucksString, true );
+}
+
+
+/*
+==========================
+=
+= SetupScreen
+=
+==========================
+*/
+
+void SetupScreen ( boolean flip )
+{
+ pic_t *shape;
+
+ SetViewSize(viewsize);
+
+ if ( viewsize < 7 )
+ {
+ shape = ( pic_t * )W_CacheLumpName( "backtile", PU_CACHE, Cvt_pic_t, 1 );
+ //DrawTiledRegion( 0, 16, 320, 200 - 32, 0, 16, shape );
+ DrawTiledRegion( 0, 16, iGLOBAL_SCREENWIDTH, iGLOBAL_SCREENHEIGHT - 32, 0, 16, shape );//bna++
+ }
+
+ if ( viewsize == 0 )
+ {
+ DrawCPUJape();
+ }
+
+ DrawPlayScreen (true);
+ if (flip==true)
+ {
+ ThreeDRefresh();
+ VL_CopyDisplayToHidden();
+ }
+}
+
+
+
+void LoadColorMap( void )
+{
+ int i,j;
+ int lump, length;
+
+ if (ColorMapLoaded==1)
+ Error("Called LoadColorMap twice\n");
+ ColorMapLoaded=1;
+//
+// load in the light tables
+// 256 byte align tables
+//
+
+ lump = W_GetNumForName("colormap");
+ length = W_LumpLength (lump) + 255;
+ colormap = SafeMalloc (length);
+ colormap = (byte *)( ((long)colormap + 255)&~0xff);
+ W_ReadLump (lump,colormap);
+
+// Fix fire colors in colormap
+
+ for (i=31; i>=16; i--)
+ for (j=0xea; j<0xf9; j++)
+ colormap[i*256+j]=colormap[(((i-16)/4+16))*256+j];
+
+// Get special maps
+
+ lump = W_GetNumForName("specmaps");
+ length = W_LumpLength (lump+1) + 255;
+ redmap = SafeMalloc (length);
+ redmap = (byte *)( ((long)redmap + 255)&~0xff);
+ W_ReadLump (lump+1,redmap);
+ greenmap = redmap+(16*256);
+
+// Get player colormaps
+
+// if (modemgame==true)
+ {
+ lump = W_GetNumForName("playmaps")+1;
+ for (i=0; i<MAXPLAYERCOLORS; i++)
+ {
+ length = W_LumpLength (lump+i) + 255;
+ playermaps[i] = SafeMalloc (length);
+ playermaps[i] = (byte *)( ((long)playermaps[i] + 255)&~0xff);
+ W_ReadLump (lump+i,playermaps[i]);
+ }
+ }
+
+ if (!quiet)
+ printf("RT_VIEW: Colormaps Initialized\n");
+
+}
+
+/*
+==========================
+=
+= SetupLightLevels
+=
+==========================
+*/
+#define LIGHTRATEBASE 252
+#define LIGHTRATEEND 267
+#define LIGHTLEVELBASE 216
+#define LIGHTLEVELEND 223
+void SetupLightLevels ( void )
+{
+ int glevel;
+
+ periodic=false;
+ fog=0;
+ lightsource=0;
+
+// Set up light level for level
+
+ if (((word)MAPSPOT(2,0,1)>=104) && ((word)MAPSPOT(2,0,1)<=105))
+ fog=(word)MAPSPOT(2,0,1)-104;
+ else
+ Error ("There is no Fog icon on map %d\n",gamestate.mapon);
+ if ((word)MAPSPOT(3,0,1)==139)
+ {
+ if (fog==0)
+ {
+ lightsource=1;
+ lights=Z_Malloc(MAPSIZE*MAPSIZE*(sizeof(unsigned long)),PU_LEVEL,NULL);
+ memset (lights,0,MAPSIZE*MAPSIZE*(sizeof(unsigned long)));
+ }
+ else
+ Error("You cannot use light sourcing on a level with fog on map %d\n",gamestate.mapon);
+ }
+ else if ((word)MAPSPOT(3,0,1))
+ Error("You must use the lightsource icon or nothing at all at (3,0) in plane 1 on map %d\n",gamestate.mapon);
+ if (((word)MAPSPOT(2,0,0)>=LIGHTLEVELBASE) && ((word)MAPSPOT(2,0,0)<=LIGHTLEVELEND))
+ glevel=(MAPSPOT(2,0,0)-LIGHTLEVELBASE);
+ else
+ Error("You must specify a valid darkness level icon at (2,0) on map %d\n",gamestate.mapon);
+
+ SetLightLevels ( glevel );
+
+ if (((word)MAPSPOT(3,0,0)>=LIGHTRATEBASE) && ((word)MAPSPOT(3,0,0)<=LIGHTRATEEND))
+ glevel=(MAPSPOT(3,0,0)-LIGHTRATEBASE);
+ else
+ {
+// Error("You must specify a valid darkness rate icon at (3,0) on map %ld\n",gamestate.mapon);
+ glevel = 4;
+ }
+
+ SetLightRate ( glevel );
+ lightningtime=0;
+ lightningdistance=0;
+ lightninglevel=0;
+ lightningdelta=0;
+ lightningsoundtime=0;
+}
+
+/*
+==========================
+=
+= SetLightLevels
+=
+==========================
+*/
+void SetLightLevels ( int darkness )
+{
+ if (fog==0)
+ {
+ baseminshade=0x10+((7-darkness)>>1);
+ basemaxshade=0x1f-(darkness>>1);
+ }
+ else
+ {
+ baseminshade=darkness;
+ basemaxshade=0x10;
+ }
+ minshade=baseminshade;
+ maxshade=basemaxshade;
+ darknesslevel=darkness;
+}
+
+/*
+==========================
+=
+= GetLightLevelTile
+=
+==========================
+*/
+int GetLightLevelTile ( void )
+{
+ if (fog==0)
+ {
+ return ((7-((baseminshade-0x10)<<1))+LIGHTLEVELBASE);
+ }
+ else
+ {
+ return (baseminshade+LIGHTLEVELBASE);
+ }
+}
+
+
+/*
+==========================
+=
+= SetLightRate
+=
+==========================
+*/
+void SetLightRate ( int rate )
+{
+ normalshade=(HEIGHTFRACTION+8)-rate;
+ if (normalshade>14) normalshade=14;
+ if (normalshade<3) normalshade=3;
+}
+
+/*
+==========================
+=
+= GetLightRate
+=
+==========================
+*/
+int GetLightRate ( void )
+{
+ return ((HEIGHTFRACTION+8)-normalshade);
+}
+
+/*
+==========================
+=
+= GetLightRateTile
+=
+==========================
+*/
+int GetLightRateTile ( void )
+{
+ return ((HEIGHTFRACTION+8)-normalshade+LIGHTRATEBASE);
+}
+
+
+
+/*
+==========================
+=
+= UpdateLightLevel
+=
+==========================
+*/
+void UpdateLightLevel (int area)
+{
+ int numlights;
+ int targetmin;
+ int targetmax;
+ int numtiles;
+
+ if (fog==true)
+ return;
+
+ numtiles=(numareatiles[area]>>5)-2;
+ numlights=(LightsInArea[area]-numtiles)>>1;
+
+ if (numlights<0)
+ numlights=0;
+ if (numlights>GENERALNUMLIGHTS)
+ numlights=GENERALNUMLIGHTS;
+ targetmin=baseminshade+(GENERALNUMLIGHTS-numlights);
+ targetmax=basemaxshade-numlights;
+ if (targetmax<baseminshade)
+ targetmax=baseminshade;
+ if (targetmin>targetmax)
+ targetmin=targetmax;
+
+ if (minshade>targetmin)
+ minshade-=1;
+ else if (minshade<targetmin)
+ minshade+=1;
+
+ if (maxshade>targetmax)
+ maxshade-=1;
+ else if (maxshade<targetmax)
+ maxshade+=1;
+
+#if 0
+ targetlevel=baseminshade+(GENERALNUMLIGHTS-numlights);
+ if (abs(minshade-targetlevel)==1)
+ minshade=targetlevel;
+ else if (minshade>targetlevel)
+ minshade-=2;
+ else if (minshade<targetlevel)
+ minshade+=2;
+#endif
+}
+
+/*
+==========================
+=
+= SetIllumination
+=
+= Postive value lightens
+= Negative value darkens
+=
+==========================
+*/
+void SetIllumination (int level)
+{
+ if (fog)
+ return;
+ maxshade-=level;
+ if (maxshade>31)
+ maxshade=31;
+ if (maxshade<0x10)
+ maxshade=0x10;
+ minshade-=level;
+ if (minshade<0x10)
+ minshade=0x10;
+ if (minshade>31)
+ minshade=31;
+}
+
+/*
+==========================
+=
+= GetIlluminationDelta
+=
+==========================
+*/
+int GetIlluminationDelta (void)
+{
+ if (fog)
+ return 0;
+ else
+ return maxshade-basemaxshade;
+}
+
+/*
+==========================
+=
+= UpdateLightning
+=
+==========================
+*/
+void UpdateLightning (void)
+{
+ if (periodic==true)
+ {
+ UpdatePeriodicLighting();
+ return;
+ }
+ if ((fog==1) || (lightning==false))
+ return;
+
+ if (lightningtime<=0)
+ {
+ if (lightningsoundtime>0)
+ SD_Play3D (SD_LIGHTNINGSND, 0, lightningdistance);
+ lightningtime=GameRandomNumber("UpdateLightning",0)<<1;
+ lightningdistance=GameRandomNumber("UpdateLightning",0);
+ lightninglevel=(255-lightningdistance)>>LIGHTNINGLEVEL;
+ if (lightninglevel<MINLIGHTNINGLEVEL)
+ lightninglevel=MINLIGHTNINGLEVEL;
+ if (lightninglevel>MAXLIGHTNINGLEVEL)
+ lightninglevel=MAXLIGHTNINGLEVEL;
+ lightningdelta=lightninglevel>>1;
+ lightningsoundtime=lightningdistance>>1;
+ if (lightningdistance<100)
+ {
+ SetIllumination(lightninglevel);
+ }
+ }
+ else if (lightninglevel>0)
+ {
+ lightninglevel-=lightningdelta;
+ if (lightninglevel<=0)
+ {
+ lightninglevel=0;
+ }
+ }
+ else
+ lightningtime--;
+ if (lightningsoundtime)
+ {
+ lightningsoundtime--;
+ if (lightningsoundtime<=0)
+ {
+ int volume;
+
+ volume=255-lightningdistance;
+ if (volume>170) volume=170;
+ SD_PlayPitchedSound ( SD_LIGHTNINGSND, volume,-(lightningdistance<<2));
+ lightningsoundtime=0;
+ }
+ }
+}
+
+/*
+==========================
+=
+= UpdatePeriodicLighting
+=
+==========================
+*/
+#define PERIODICMAG (6)
+#define PERIODICSTEP (20)
+#define PERIODICBASE (0x0f)
+void UpdatePeriodicLighting (void)
+{
+ int val;
+
+ val=FixedMul(PERIODICMAG,sintable[periodictime]);
+ periodictime=(periodictime+PERIODICSTEP)&(FINEANGLES-1);
+ basemaxshade=PERIODICBASE+(PERIODICMAG)+val;
+ baseminshade=basemaxshade-GENERALNUMLIGHTS-1;
+}
+
+/*
+==========================
+=
+= SetModemLightLevel
+=
+==========================
+*/
+void SetModemLightLevel ( int type )
+{
+ periodic=false;
+ fulllight=false;
+ switch (type)
+ {
+ case bo_light_dark:
+ MAPSPOT(2,0,0)=(word)216;
+ MAPSPOT(3,0,0)=(word)255;
+ MAPSPOT(3,0,1)=(word)139;
+ MAPSPOT(2,0,1)=(word)104;
+ SetupLightLevels ();
+ break;
+ case bo_light_normal:
+ break;
+ case bo_light_bright:
+ MAPSPOT(2,0,0)=(word)223;
+ MAPSPOT(3,0,0)=(word)267;
+ MAPSPOT(3,0,1)=(word)0;
+ MAPSPOT(2,0,1)=(word)104;
+ SetupLightLevels ();
+ break;
+ case bo_light_fog:
+ MAPSPOT(2,0,0)=(word)219;
+ MAPSPOT(3,0,0)=(word)259;
+ MAPSPOT(2,0,1)=(word)105;
+ MAPSPOT(3,0,1)=(word)0;
+ SetupLightLevels ();
+ break;
+ case bo_light_periodic:
+ fog=0;
+ MAPSPOT(2,0,1)=(word)104;
+ MAPSPOT(3,0,1)=(word)139;
+ SetupLightLevels ();
+ periodic=true;
+ break;
+ case bo_light_lightning:
+ if (sky!=0)
+ {
+ MAPSPOT(2,0,0)=(word)222;
+ MAPSPOT(3,0,0)=(word)255;
+ MAPSPOT(3,0,1)=(word)139;
+ MAPSPOT(2,0,1)=(word)104;
+ SetupLightLevels ();
+ lightning=true;
+ }
+ break;
+ }
+}
+
--- /dev/null
+++ b/rott/rt_view.h
@@ -1,0 +1,131 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// RT_VIEW.H
+//
+//***************************************************************************
+#ifndef _rt_view_public
+#define _rt_view_public
+
+#include "modexlib.h"
+
+#define HEIGHTFRACTION 6
+#define MAXVIEWSIZES 11
+
+//#define FOCALWIDTH 160//160
+//#define FPFOCALWIDTH 160.0//160.0
+
+
+#define NUMGAMMALEVELS 8
+#define GAMMAENTRIES (64*8)
+
+#define GENERALNUMLIGHTS (5)
+
+extern int StatusBar;
+
+// Kill count
+#define STATUS_KILLS 0x1
+// Transparent health bar
+#define STATUS_PLAYER_STATS 0x2
+// Bottom status bar
+#define BOTTOM_STATUS_BAR 0x4
+// Top status bar
+#define TOP_STATUS_BAR 0x8
+
+#define SHOW_KILLS() ( StatusBar & STATUS_KILLS )
+#define SHOW_PLAYER_STATS() ( StatusBar & STATUS_PLAYER_STATS )
+#define SHOW_BOTTOM_STATUS_BAR() ( StatusBar & BOTTOM_STATUS_BAR )
+#define SHOW_TOP_STATUS_BAR() ( StatusBar & TOP_STATUS_BAR )
+
+#define YOURCPUSUCKS_Y ( 100 + 48 / 2 + 2 )
+#define YOURCPUSUCKS_HEIGHT 8
+
+#define MAXPLAYERCOLORS (11)
+typedef enum
+{
+ pc_gray,
+ pc_brown,
+ pc_black,
+ pc_tan,
+ pc_red,
+ pc_olive,
+ pc_blue,
+ pc_white,
+ pc_green,
+ pc_purple,
+ pc_orange
+} playercolors;
+
+extern byte * playermaps[MAXPLAYERCOLORS];
+//extern short pixelangle[MAXVIEWWIDTH];
+extern short pixelangle[800];
+extern byte gammatable[GAMMAENTRIES];
+extern int gammaindex;
+extern byte uniformcolors[MAXPLAYERCOLORS];
+
+extern byte mapmasks1[4][9]; // Map Mask for post scaling
+extern byte mapmasks2[4][9]; // Map Mask for post scaling
+extern byte mapmasks3[4][9]; // Map Mask for post scaling
+
+extern int normalshade; // Normal shading level for stuff
+extern int maxshade; // max shading level
+extern int minshade; // min shading level
+extern int baseminshade;
+extern int basemaxshade;
+extern int viewheight;
+extern int viewwidth;
+extern longword heightnumerator;
+extern fixed scale;
+extern int screenofs;
+extern int centerx;
+extern int centery;
+extern int centeryfrac;
+extern int fulllight;
+extern byte * colormap;
+extern byte * greenmap;
+extern byte * redmap;
+extern int weaponscale;
+extern int viewsize;
+extern int focalwidth;
+extern int yzangleconverter;
+extern int lightninglevel;
+extern boolean lightning;
+extern int darknesslevel;
+
+void DrawCPUJape( void );
+void SetupScreen ( boolean flip );
+void ResetFocalWidth ( void );
+void ChangeFocalWidth ( int amount );
+void SetViewSize ( int size );
+void LoadColorMap( void );
+void UpdateLightLevel (int area);
+void SetIllumination (int level);
+int GetIlluminationDelta (void);
+void UpdateLightning (void);
+void SetLightLevels ( int darkness );
+void SetupLightLevels ( void );
+void SetLightRate ( int rate );
+int GetLightRate ( void );
+void SetModemLightLevel ( int type );
+int GetLightRateTile ( void );
+int GetLightLevelTile ( void );
+
+#endif
--- /dev/null
+++ b/rott/sbconfig.c
@@ -1,0 +1,499 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/* Copyright 1995 Spacetec IMC Corporation */
+
+#if defined(__BORLANDC__)
+# pragma inline
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <dos.h>
+
+typedef long fixed;
+
+#include "rt_def.h"
+
+#include "develop.h"
+#include "sbconfig.h"
+//MED
+#include "memcheck.h"
+
+/* ----------------------------------------------------------------------- */
+
+#define DEFAULT_CONFIG_FILENAME "sbconfig.dat"
+
+#define NUM_ELEMENTS(x) (sizeof(x)/sizeof(x[0]))
+#define SIGN(x) ((x<0)?-1:1)
+
+/* ----------------------------------------------------------------------- */
+
+#if defined(__BORLANDC__)
+
+fixed FIXED_MUL(fixed a, fixed b)
+{
+
+ fixed ret_code;
+
+ asm {
+
+ mov eax,a
+ mov edx,b
+ imul edx
+ shrd eax,edx,16
+ mov ret_code,eax
+ }
+
+ return ret_code;
+}
+
+#elif defined(_MSC_VER)
+
+/* Microsoft C7.0 can not be done with inline assembler because it
+ can not handle 32-bit instructions
+*/
+fixed FIXED_MUL(fixed a,fixed b)
+{
+ fixed sgn,ah,al,bh,bl;
+
+ sgn = (SIGN(a) ^ SIGN(b)) ? -1 : 1 ;
+ ah = (a >> 16) & 0xffff ;
+ al = (a & 0xffff);
+ bh = (b >> 16) & 0xffff ;
+ bl = (b & 0xffff);
+
+ return sgn * ( ((al*bl)>>16) + (ah*bl) + (al*bh) + ((ah*bh)<<16) );
+}
+
+#elif defined(__WATCOMC__)
+
+fixed FIXED_MUL(fixed a, fixed b);
+
+#pragma aux FIXED_MUL = \
+ "imul edx" \
+ "shrd eax,edx,16" \
+ parm [eax] [edx] \
+ value [eax] \
+ modify exact [eax] ;
+
+#endif /* definition of inline FIXED_MUL */
+
+
+static
+fixed StrToFx1616(char *string, char **ret_string)
+{
+ long whole;
+ long fract;
+ fixed result;
+ int sign;
+
+ /* Skip whitespace */
+ while((*string==' ')||(*string=='\t')||(*string=='\n')) string++;
+
+ /* Accept numbers in the form: [+-]?[0-9]+(.[0-9]*)
+ */
+
+ sign=1;
+ if(*string=='-')
+ {
+ string++;
+ sign=-1;
+ }
+ else if(*string=='+')
+ {
+ string++;
+ sign=1;
+ }
+
+ /* Read in the whole part */
+ whole=0;
+ while((*string>='0')&&(*string<='9'))
+ whole=whole*10+(*string++)-'0';
+
+ /* Read the optional fraction part */
+ fract=0;
+ if(*string=='.')
+ {
+ long place=1;
+ string++;
+ while((*string>='0')&&(*string<='9'))
+ {
+ fract=fract*10+(*string++)-'0';
+ place*=10;
+ }
+ /* Convert to fixed point */
+ fract=(fract<<16)/place;
+ }
+
+ if(ret_string) *ret_string=string;
+
+ if(sign==1)
+ result= (whole<<16) + fract;
+ else
+ result=-(whole<<16) + fract;
+
+ return result;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static char *SbButtonNames[]= {
+ "BUTTON_A",
+ "BUTTON_B",
+ "BUTTON_C",
+ "BUTTON_D",
+ "BUTTON_E",
+ "BUTTON_F"
+};
+
+static int cfgFileVersion=0;
+static char cfgButtons[NUM_ELEMENTS(SbButtonNames)][MAX_STRING_LENGTH];
+static WarpRecord *pCfgWarps;
+static int nCfgWarps=0;
+
+/*-------------------------------------------------------------------------*/
+
+/* Read a string in the form: "{#, #, #}"
+ * and return a pointer to the character AFTER the '}'
+ * or NULL if error
+ */
+static char *GetWarpLevels(char *string, WarpRange *pw)
+{
+ short value;
+ fixed fxvalue;
+
+ if((*string++)!='{')
+ return NULL;
+
+ if(!*string)
+ return NULL;
+
+ /* Expecting the first number - low */
+ value=(short)strtol(string, &string, 0);
+ if(pw) pw->low=value;
+
+ /* Skip any whitespace */
+ while(isspace(*string)) string++;
+
+ if(*string++!=',')
+ return NULL;
+
+ /* Expecting the second number - high */
+ value=(short)strtol(string, &string, 0);
+ if(pw) pw->high=value;
+
+ /* Skip any whitespace */
+ while(isspace(*string)) string++;
+
+ if(*string++!=',')
+ return NULL;
+
+ /* Expecting the third number - multiplier */
+ fxvalue=StrToFx1616(string, &string);
+ if(pw) pw->mult=fxvalue;
+
+ /* Skip any whitespace */
+ while(isspace(*string)) string++;
+
+ if(*string!='}')
+ return NULL;
+
+ return string+1;
+}
+
+
+
+static int GetWarp(char *string, WarpRecord *pRecord)
+{
+ int nWarp;
+ WarpRange *pWarp;
+
+ /* Only update the field if we successfully read the entire line */
+ nWarp=0;
+ pWarp=NULL;
+
+ /* Skip whitespace */
+ while(isspace(*string)) string++;
+
+ if(*string++!='{') return 0;
+
+ while(string && *string)
+ {
+ switch(*string)
+ {
+ case ' ':
+ case '\t':
+ case '\n':
+ string++;
+ break;
+
+ case ',':
+ string++;
+ break;
+
+ case '{':
+ if(nWarp++==0)
+ pWarp=malloc(sizeof(WarpRange));
+ else
+ pWarp=realloc(pWarp, nWarp*sizeof(WarpRange));
+
+ string=GetWarpLevels(string, pWarp+nWarp-1);
+ break;
+
+ case '}':
+ pRecord->nWarp=nWarp;
+ pRecord->pWarp=pWarp;
+ return 1;
+ }
+ }
+
+ /* Early EOL (didn't get closing '}') */
+ if(nWarp) free(pWarp);
+ return 0;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+int SbConfigParse(char *_filename)
+{
+ int i;
+ FILE *file;
+ char *pc;
+ char buffer[128];
+ char filename[MAX_PATH];
+
+ if(!_filename) _filename=DEFAULT_CONFIG_FILENAME;
+
+ strncpy(filename, _filename, sizeof (filename));
+ filename[sizeof (filename) - 1] = '\0';
+ FixFilePath(filename);
+
+ if(!(file=fopen(filename, "r")))
+ {
+ printf("Config file: %s, not found\n", filename);
+ return 0;
+ }
+
+ while(fgets(buffer, sizeof(buffer), file))
+ {
+ int lineParsed=0;
+
+ /* each line in config file starts with either a ;, VERSION or an
+ ** element of GameButtonNames or WarpNames
+ */
+ pc=strtok(buffer, " \t\n,");
+
+ if(*pc==';') /* commented out line? */
+ continue;
+
+ /* VERSION? The version will be used in the future to allow fx1616
+ ** values in the config file
+ */
+ if(!stricmp(pc,"VERSION"))
+ {
+ pc=strtok(NULL, " \t\n,");
+ cfgFileVersion=atoi(pc);
+ }
+
+ /* Check if first token is an element of SbButtonNames */
+ for(i=0; i<NUM_ELEMENTS(SbButtonNames); i++)
+ if(!stricmp(pc, SbButtonNames[i]))
+ {
+ lineParsed=1;
+
+ /* Save the next token in the appropriate slot */
+ pc=strtok(NULL," \t\n,");
+
+ strncpy(cfgButtons[i], pc, MAX_STRING_LENGTH-1);
+ cfgButtons[i][MAX_STRING_LENGTH-1]=0;
+ }
+
+ /* If the first token is not from GameButtonNames,
+ ** it must be a WarpName
+ */
+ if(!lineParsed)
+ {
+ char *name;
+
+ name=pc;
+ pc=pc+strlen(pc)+1; /* Skip this token */
+ while(isspace(*pc)) pc++; /* Skip any whitespace */
+
+ if(*pc=='{')
+ {
+ WarpRecord warpRec;
+
+ strcpy(warpRec.name, name);
+ warpRec.pWarp=NULL;
+ warpRec.nWarp=0;
+
+ if(GetWarp(pc, &warpRec))
+ {
+ if(nCfgWarps++==0)
+ pCfgWarps=(WarpRecord *)malloc(sizeof(WarpRecord));
+ else
+ pCfgWarps=(WarpRecord *)realloc(pCfgWarps, nCfgWarps*sizeof(WarpRecord));
+ pCfgWarps[nCfgWarps-1]=warpRec;
+ }
+ }
+ }
+ } /* end of while getting lines from config file */
+
+ fclose(file);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------*/
+
+char *SbConfigGetButton(char *btnName)
+{
+ int i;
+ for(i=0; i<NUM_ELEMENTS(SbButtonNames); i++)
+ {
+ if(!stricmp(btnName, SbButtonNames[i]))
+ if(cfgButtons[i][0])
+ return cfgButtons[i];
+ else
+ return NULL; /* Empty slot */
+
+ if(!stricmp(btnName, cfgButtons[i]))
+ return SbButtonNames[i];
+ }
+
+ /* Unknown button name */
+ return NULL;
+}
+
+
+
+int SbConfigGetButtonNumber(char *btnName)
+{
+ int i;
+ for(i=0; i<NUM_ELEMENTS(SbButtonNames); i++)
+ {
+ if(!stricmp(btnName, cfgButtons[i]))
+ return i;
+ }
+
+ /* Unknown button name */
+ return -1;
+}
+
+/*-------------------------------------------------------------------------*/
+
+WarpRecord *SbConfigGetWarpRange(char *rngName)
+{
+ int i;
+ for(i=0; i<nCfgWarps; i++)
+ if(!stricmp(rngName, pCfgWarps[i].name))
+ return &pCfgWarps[i];
+
+ return NULL;
+}
+
+/*-------------------------------------------------------------------------*/
+
+fixed SbFxConfigWarp(WarpRecord *warp, short value)
+{
+ int i;
+ short absValue;
+ fixed accum;
+ int sign;
+
+ if(!warp) return INT_TO_FIXED(value);
+
+ absValue=value;
+ sign=1;
+ if(absValue<0)
+ {
+ absValue= (short)-absValue;
+ sign=-1;
+ }
+
+ accum=INT_TO_FIXED(0);
+
+ for(i=0; i<warp->nWarp; i++)
+ {
+ if(absValue<=warp->pWarp[i].low)
+ ; /* Ignore it if below this range (if required, will have
+ ** been caught by the previous warp)
+ */
+ else if((absValue>warp->pWarp[i].low) && (absValue<=warp->pWarp[i].high))
+ {
+ fixed diff;
+ fixed partial;
+ diff=INT_TO_FIXED((long)absValue-(long)warp->pWarp[i].low);
+ partial=FIXED_MUL(diff, warp->pWarp[i].mult);
+ accum=FIXED_ADD(accum, partial);
+ break; /* Exit the for loop */
+ }
+ else /* Accumulate if greater than this range */
+ {
+ fixed partial;
+ partial=FIXED_MUL(INT_TO_FIXED((long)warp->pWarp[i].high-(long)warp->pWarp[i].low),
+ warp->pWarp[i].mult);
+ accum=FIXED_ADD(accum, partial);
+ }
+ }
+
+ if(sign==1)
+ return accum;
+ else
+ return -accum;
+
+#if 0 /* Old technique */
+ if((absValue>=warp->pWarp[i].low) && (absValue<=warp->pWarp[i].high))
+ if(warp->pWarp[i].shift>=0)
+ value=accum+((absValue-warp->pWarp[i].low)<<warp->pWarp[i].shift);
+ else
+ value=accum+((absValue-warp->pWarp[i].low)>>abs(warp->pWarp[i].shift));
+ else if(warp->pWarp[i].shift>=0)
+ accum+=(warp->pWarp[i].high-warp->pWarp[i].low)<<warp->pWarp[i].shift;
+ else
+ accum+=(warp->pWarp[i].high-warp->pWarp[i].low)>>abs(warp->pWarp[i].shift);
+
+ if(absValue>warp->pWarp[warp->nWarp-1].high)
+ value=accum;
+
+ return sign*value;
+#endif
+}
+
+
+/*-------------------------------------------------------------------------*/
+
+long SbConfigWarp(WarpRecord *warp, short value)
+{
+ /* An apparent bug in the msc70 compiler, trashes r
+ if it is on the stack. Leave in unitialized global segment.
+ */
+ static fixed r;
+
+ r = SbFxConfigWarp(warp,value);
+
+ return r >> 16 ;
+}
+
+
+/*-------------------------------------------------------------------------*/
+
--- /dev/null
+++ b/rott/sbconfig.h
@@ -1,0 +1,132 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef SBCONFIG_H
+#define SBCONFIG_H
+/* ----------------------------------------------------------------------- */
+/* See the bottom of this file for a syntax diagram for the config file */
+
+#define MAX_STRING_LENGTH 40
+
+/* ----------------------------------------------------------------------- */
+
+//typedef long fixed; /* 16.16 fixed pt number */
+
+#define INT_TO_FIXED(n) ((fixed)((long)(n)<<16))
+#define FIXED_TO_INT(n) ((long)((n)>>16))
+#define FLOAT_TO_FIXED(n) ((fixed)((n)*65536.0))
+
+#define FIXED_ADD(a, b) ((a)+(b))
+#define FIXED_SUB(a, b) ((a)-(b))
+
+/* ----------------------------------------------------------------------- */
+
+typedef struct {
+ short low; /* range of input values this warp covers */
+ short high;
+ fixed mult; /* multiplier to be applied to this range */
+} WarpRange;
+
+
+
+typedef struct {
+ char name[MAX_STRING_LENGTH];
+ WarpRange *pWarp;
+ int nWarp;
+} WarpRecord;
+
+/* ----------------------------------------------------------------------- */
+
+/* Parse the config file */
+int SbConfigParse(char *filename);
+
+/* Get the button config name for the button named <btnName> or return NULL
+ * if none exists. <btnName> can be either the left or the right side name.
+ * So, for the config line:
+ *
+ * BUTTON_A MY_BUTTON
+ *
+ * ConfigGetButton("BUTTON_A") will return "MY_BUTTON"
+ * ConfigGetButton("MY_BUTTON") will return "BUTTON_A"
+ *
+ * Note that this makes it illegal to have game button names have the names
+ * "BUTTON_A", "BUTTON_B", "BUTTON_C", etc...
+ *
+ * Also, the comparison is CASE INSENSITIVE.
+ */
+char *SbConfigGetButton(char *btnName);
+int SbConfigGetButtonNumber(char *btnName);
+
+/*
+ * Get the warp ranges for the config range named <rngName> or return NULL
+ * if none exists.
+ */
+WarpRecord *SbConfigGetWarpRange(char *rngName);
+
+/*
+ * Warp a value based on the given warp range
+ */
+fixed SbFxConfigWarp(WarpRecord *warp, short value); /* returns fixed pt */
+long SbConfigWarp(WarpRecord *warp, short value); /* returns integer */
+
+/* ----------------------------------------------------------------------- */
+/* Lexical Definitions:
+**
+** comment: ;[^\n]*\n
+** integer: [0-9]+
+** identifier: [A-Za-z_][A-Za-z_0-9]*
+**
+*/
+/* Syntax Diagram: (Line by Line parsing)
+**
+**
+** ConfigFile:
+** | ConfigLine ConfigFile
+** ;
+**
+** ConfigLine:
+** | comment
+** | VersionLine comment
+** | ButtonLine comment
+** | RangeLine comment
+** ;
+**
+** VersionLine: 'VERSION' integer
+** ;
+**
+** ButtonLine: 'BUTTON_A' identifier
+** | 'BUTTON_B' identifier
+** | 'BUTTON_C' identifier
+** | 'BUTTON_D' identifier
+** | 'BUTTON_E' identifier
+** | 'BUTTON_F' identifier
+** ;
+**
+** RangeLine: identifier '{' RangeList '}'
+** ;
+**
+** RangeList:
+** | '{' integer ',' integer ',' integer '}'
+** | '{' integer ',' integer ',' integer '}' ',' RangeList
+** ;
+**
+*/
+/* ----------------------------------------------------------------------- */
+#endif
+
--- /dev/null
+++ b/rott/scriplib.c
@@ -1,0 +1,319 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// scriplib.c
+
+#ifdef DOS
+#include <io.h>
+#include <dos.h>
+#endif
+
+#include <fcntl.h>
+#include <string.h>
+
+#include "rt_def.h"
+#include "scriplib.h"
+#include "rt_util.h"
+//MED
+#include "memcheck.h"
+
+/*
+=============================================================================
+
+ PARSING STUFF
+
+=============================================================================
+*/
+
+char token[MAXTOKEN];
+char name[MAXTOKEN*2];
+char scriptfilename[512];
+char *scriptbuffer,*script_p,*scriptend_p;
+int scriptline;
+boolean endofscript;
+boolean tokenready; // only true if UnGetToken was just called
+
+/*
+==============
+=
+= LoadScriptFile
+=
+==============
+*/
+
+void LoadScriptFile (char *filename)
+{
+ long size;
+
+ size = LoadFile (filename, (void **)&scriptbuffer);
+
+ snprintf(scriptfilename, sizeof(scriptfilename), "%s", filename);
+ script_p = scriptbuffer;
+ scriptend_p = script_p + size;
+ scriptline = 1;
+ endofscript = false;
+ tokenready = false;
+}
+
+
+/*
+==============
+=
+= UnGetToken
+=
+= Signals that the current token was not used, and should be reported
+= for the next GetToken. Note that
+
+GetToken (true);
+UnGetToken ();
+GetToken (false);
+
+= could cross a line boundary.
+=
+==============
+*/
+
+void UnGetToken (void)
+{
+ tokenready = true;
+}
+
+
+/*
+==============
+=
+= GetToken
+=
+==============
+*/
+
+void GetToken (boolean crossline)
+{
+ char *token_p;
+
+ if (tokenready) // is a token allready waiting?
+ {
+ tokenready = false;
+ return;
+ }
+
+ if (script_p >= scriptend_p)
+ {
+ if (!crossline)
+ Error ("Line %i is incomplete\nin file %s\n",
+ scriptline,scriptfilename);
+ endofscript = true;
+ return;
+ }
+
+//
+// skip space
+//
+skipspace:
+ while (*script_p <= 32)
+ {
+ if (script_p >= scriptend_p)
+ {
+ if (!crossline)
+ Error ("Line %i is incomplete\nin file %s\n",
+ scriptline,scriptfilename);
+ endofscript = true;
+ return;
+ }
+ if (*script_p++ == '\n')
+ {
+ if (!crossline)
+ Error ("Line %i is incomplete\nin file %s\n",
+ scriptline,scriptfilename);
+ scriptline++;
+ }
+ }
+
+ if (script_p >= scriptend_p)
+ {
+ if (!crossline)
+ Error ("Line %i is incomplete\nin file %s\n",
+ scriptline,scriptfilename);
+ endofscript = true;
+ return;
+ }
+
+ if (*script_p == ';') // semicolon is comment field
+ {
+ if (!crossline)
+ Error ("Line %i is incomplete\nin file %s\n",
+ scriptline,scriptfilename);
+ while (*script_p++ != '\n')
+ if (script_p >= scriptend_p)
+ {
+ endofscript = true;
+ return;
+ }
+ goto skipspace;
+ }
+
+//
+// copy token
+//
+ token_p = token;
+
+ while ( *script_p > 32 && *script_p != ';')
+ {
+ *token_p++ = *script_p++;
+ if (script_p == scriptend_p)
+ break;
+ if (token_p == &token[MAXTOKEN])
+ Error ("Token too large on line %i\nin file %s\n",
+ scriptline,scriptfilename);
+ }
+
+ *token_p = 0;
+}
+
+
+
+/*
+==============
+=
+= GetTokenEOL
+=
+==============
+*/
+
+void GetTokenEOL (boolean crossline)
+{
+ char *name_p;
+
+ if (tokenready) // is a token allready waiting?
+ {
+ tokenready = false;
+ return;
+ }
+
+ if (script_p >= scriptend_p)
+ {
+ if (!crossline)
+ Error ("Line %i is incomplete\nin file %s\n",
+ scriptline,scriptfilename);
+ endofscript = true;
+ return;
+ }
+
+//
+// skip space
+//
+skipspace:
+ while (*script_p <= 32)
+ {
+ if (script_p >= scriptend_p)
+ {
+ if (!crossline)
+ Error ("Line %i is incomplete\nin file %s\n",
+ scriptline,scriptfilename);
+ endofscript = true;
+ return;
+ }
+ if (*script_p++ == '\n')
+ {
+ if (!crossline)
+ Error ("Line %i is incomplete\nin file %s\n",
+ scriptline,scriptfilename);
+ scriptline++;
+ }
+ }
+
+ if (script_p >= scriptend_p)
+ {
+ if (!crossline)
+ Error ("Line %i is incomplete\nin file %s\n",
+ scriptline,scriptfilename);
+ endofscript = true;
+ return;
+ }
+
+ if (*script_p == ';') // semicolon is comment field
+ {
+ if (!crossline)
+ Error ("Line %i is incomplete\nin file %s\n",
+ scriptline,scriptfilename);
+ while (*script_p++ != '\n')
+ if (script_p >= scriptend_p)
+ {
+ endofscript = true;
+ return;
+ }
+ goto skipspace;
+ }
+
+//
+// copy token
+//
+ name_p = name;
+
+ while (*script_p >= 32)
+ {
+ *name_p++ = *script_p++;
+ if (script_p == scriptend_p)
+ break;
+ if (name_p == &name[MAXTOKEN*2])
+ Error ("Name too large on line %i\nin file %s\n",
+ scriptline,scriptfilename);
+ }
+
+ *name_p = 0;
+}
+
+
+
+/*
+==============
+=
+= TokenAvailable
+=
+= Returns true if there is another token on the line
+=
+==============
+*/
+
+boolean TokenAvailable (void)
+{
+ char *search_p;
+
+ search_p = script_p;
+
+ if (search_p >= scriptend_p)
+ return false;
+
+ while ( *search_p <= 32)
+ {
+ if (*search_p == '\n')
+ return false;
+ search_p++;
+ if (search_p == scriptend_p)
+ return false;
+
+ }
+
+ if (*search_p == ';')
+ return false;
+
+ return true;
+}
+
+
--- /dev/null
+++ b/rott/scriplib.h
@@ -1,0 +1,41 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// scriplib.h
+
+#ifndef _scriplib_public
+#define _scriplib_public
+
+#define MAXTOKEN 128
+
+extern char token[MAXTOKEN];
+extern char name[MAXTOKEN*2];
+extern char *scriptbuffer,*script_p,*scriptend_p;
+extern int scriptline;
+extern boolean endofscript;
+extern boolean tokenready; // only true if UnGetToken was just called
+
+
+void LoadScriptFile (char *filename);
+void GetToken (boolean crossline);
+void GetTokenEOL (boolean crossline);
+void UnGetToken (void);
+boolean TokenAvailable (void);
+
+#endif
--- /dev/null
+++ b/rott/snd_reg.h
@@ -1,0 +1,1435 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+typedef enum {
+
+// MENU SOUNDS
+
+ D_MENUFLIP,
+ D_ESCPRESSEDSND,
+ D_MOVECURSORSND,
+ D_SELECTSND,
+ D_WARNINGBOXSND,
+ D_INFOBOXSND,
+ D_QUESTIONBOXSND,
+ D_NOPESND,
+ D_QUIT1SND,
+ D_QUIT2SND,
+ D_QUIT3SND,
+ D_QUIT4SND,
+ D_QUIT5SND,
+ D_QUIT6SND,
+ D_QUIT7SND,
+
+
+// GAME SOUNDS
+
+ D_LEVELSTARTSND,
+ D_LEVELDONESND,
+ D_GAMEOVERSND,
+
+// LEVEL END SCREEN
+
+ D_ENDBONUS1SND,
+ D_NOBONUSSND,
+ D_PERCENT100SND,
+
+// PLAYER SOUNDS
+
+ D_HITWALLSND,
+ D_SELECTWPNSND,
+ D_NOWAYSND,
+ D_DONOTHINGSND,
+// D_NOITEMSND,
+ D_PLAYERDYINGSND,
+
+ D_PLAYERTBDEATHSND,
+ D_PLAYERTCDEATHSND,
+ D_PLAYERLNDEATHSND,
+ D_PLAYERDWDEATHSND,
+ D_PLAYERIPFDEATHSND,
+ D_PLAYERTBHURTSND,
+ D_PLAYERTCHURTSND,
+ D_PLAYERLNHURTSND,
+ D_PLAYERDWHURTSND,
+ D_PLAYERIPFHURTSND,
+ D_PLAYERTBSND,
+ D_PLAYERTCSND,
+ D_PLAYERLNSND,
+ D_PLAYERDWSND,
+ D_PLAYERIPFSND,
+// D_WALK1SND,
+// D_WALK2SND,
+ D_PLAYERBURNEDSND,
+ D_PLAYERLANDSND,
+ D_PLAYERCOUGHMSND,
+ D_PLAYERCOUGHFSND,
+ D_NETWIGGLESND,
+ D_NETFALLSND,
+
+// PLAYER WEAPONS
+
+ D_ATKPISTOLSND,
+ D_ATKTWOPISTOLSND,
+ D_ATKMP40SND,
+ D_RICOCHET1SND,
+ D_RICOCHET2SND,
+ D_RICOCHET3SND,
+ D_BAZOOKAFIRESND,
+ D_FIREBOMBFIRESND,
+ D_HEATSEEKFIRESND,
+ D_DRUNKFIRESND,
+ D_FLAMEWALLFIRESND,
+ D_FLAMEWALLSND,
+ D_SPLITFIRESND,
+ D_SPLITSND,
+ D_GRAVBUILDSND,
+ D_GRAVFIRESND,
+ D_GRAVSND,
+ D_GRAVHITSND,
+ D_FIREHITSND,
+ D_MISSILEFLYSND,
+ D_MISSILEHITSND,
+ D_EXCALIBOUNCESND,
+ D_EXCALISWINGSND,
+ D_EXCALIHITSND,
+ D_EXCALIBUILDSND,
+ D_EXCALIBLASTSND,
+ D_GODMODEFIRESND,
+ D_GODMODE1SND,
+ D_GODMODE2SND,
+ D_GODMODE3SND,
+ D_LOSEMODESND,
+ D_DOGMODEPANTSND,
+ D_DOGMODEBITE1SND,
+ D_DOGMODEBITE2SND,
+ D_DOGMODELICKSND,
+ D_DOGMODEBLASTSND,
+ D_DOGMODEPREPBLASTSND,
+ D_DOGMANSND,
+ D_DOGWOMANSND,
+ D_GODMANSND,
+ D_GODWOMANSND,
+ D_FLYINGSND,
+
+// PLAYER-CAUSED SOUNDS
+
+ D_GLASSBREAKSND,
+ D_ITEMBLOWSND,
+ D_BONUSBARRELSND,
+ D_TOUCHPLATESND,
+ D_BADTOUCHSND,
+ D_EXPLODEFLOORSND,
+ D_EXPLODESND,
+// D_GASSTARTSND,
+ D_GASHISSSND,
+ D_GASENDSND,
+ D_GASMASKSND,
+
+// GET ITEM SOUNDS
+
+ D_GETKEYSND,
+ D_GETBONUSSND,
+ D_GETHEALTH1SND,
+ D_GETHEALTH2SND,
+ D_COOKHEALTHSND,
+
+ D_GETWEAPONSND,
+ D_GETKNIFESND,
+ D_GETGODSND,
+ D_GETDOGSND,
+ D_GETFLEETSND,
+ D_GETELASTSND,
+ D_GETSHROOMSSND,
+ D_GETBVESTSND,
+ D_GETAVESTSND,
+ D_GETMASKSND,
+ D_GETBATSND,
+ D_GETHEADSND,
+
+ D_GET1UPSND,
+ D_GET3UPSND,
+ D_RESPAWNSND,
+ D_PLAYERSPAWNSND,
+
+// ACTOR SOUNDS
+
+ D_LOWGUARD1SEESND,
+ D_LOWGUARD1ASEESND,
+ D_LOWGUARD1SEE2SND,
+// D_LOWGUARD2SEESND,
+// D_LOWGUARD2ASEESND,
+// D_LOWGUARD2SEE2SND,
+ D_LOWGUARDOUCHSND,
+ D_LOWGUARD1DIESND,
+// D_LOWGUARD2DIESND,
+ D_SNEAKYSPRINGMSND,
+// D_SNEAKYSPRINGFSND,
+
+ D_HIGHGUARD1SEESND,
+ D_HIGHGUARD2SEESND,
+ D_HIGHGUARDOUCHSND,
+ D_HIGHGUARDDIESND,
+
+ D_OVERP1SEESND,
+// D_OVERP2SEESND,
+ D_OVERPNETSND,
+ D_OVERPOUCHSND,
+ D_OVERPDIESND,
+
+ D_STRIKE1SEESND,
+// D_STRIKE2SEESND,
+ D_STRIKEROLLSND,
+ D_STRIKEOUCHSND,
+ D_STRIKEDIESND,
+
+ D_BLITZ1SEESND,
+ D_BLITZ2SEESND,
+ D_BLITZSTEALSND,
+ D_BLITZOUCHSND,
+ D_BLITZDIESND,
+ D_BLITZPLEADSND,
+ D_BLITZPLEAD1SND,
+ D_BLITZPLEAD2SND,
+
+ D_ENFORCERSEESND,
+ D_ENFORCERFIRESND,
+ D_ENFORCERTHROWSND,
+ D_ENFORCEROUCHSND,
+ D_ENFORCERDIESND,
+
+ D_MONKSEESND,
+ D_MONKGRABSND,
+ D_MONKOUCHSND,
+ D_MONKDIESND,
+
+ D_FIREMONKSEESND,
+ D_FIREMONKFIRESND,
+ D_FIREMONKOUCHSND,
+ D_FIREMONKDIESND,
+
+ D_ROBOTSEESND,
+ D_ROBOTFIRESND,
+ D_ROBOTDIESND,
+
+ D_DARIANSEESND,
+ D_DARIANGONNAUSESND,
+ D_DARIANHIDESND,
+ D_DARIANDIESND,
+ D_DARIANSAY1,
+ D_DARIANSAY2,
+ D_DARIANSAY3,
+
+ D_KRISTSEESND,
+ D_KRISTMOTORSND,
+ D_KRISTTURNSND,
+ D_KRISTDROPSND,
+ D_KRISTMINEBEEPSND,
+ D_KRISTMINEHITSND,
+ D_KRISTDIESND,
+ D_KRISTSAY1,
+ D_KRISTSAY2,
+ D_KRISTSAY3,
+
+ D_NMESEESND,
+ D_NMEREADYSND,
+ D_NMEAPARTSND,
+ D_NMEUFOSND,
+
+ D_DARKMONKSEESND,
+ D_DARKMONKFIRE1SND,
+ D_DARKMONKFIRE2SND,
+ D_DARKMONKFIRE3SND,
+ D_DARKMONKFIRE4SND,
+ D_DARKMONKRECHARGESND,
+ D_DARKMONKFLOATSND,
+ D_DARKMONKDIESND,
+ D_DARKMONKSAY1,
+ D_DARKMONKSAY2,
+ D_DARKMONKSAY3,
+
+ D_SNAKESEESND,
+ D_SNAKEREADYSND,
+ D_SNAKECHARGESND,
+ D_SNAKEOUCHSND,
+ D_SNAKEDIESND,
+ D_SNAKESPITSND,
+ D_SNAKESAY1,
+ D_SNAKESAY2,
+ D_SNAKESAY3,
+
+ D_EMPLACEMENTSEESND,
+ D_EMPLACEMENTFIRESND,
+ D_BIGEMPLACEFIRESND,
+
+
+// ENVIRONMENT SOUNDS
+
+ D_OPENDOORSND,
+ D_CLOSEDOORSND,
+ D_DOORHITSND,
+ D_FIRECHUTESND,
+ D_FIREBALLSND,
+ D_FIREBALLHITSND,
+ D_BLADESPINSND,
+ D_PUSHWALLSND,
+ D_PUSHWALLHITSND,
+ D_GOWALLSND,
+ D_TURBOWALLSND,
+ D_BOULDERHITSND,
+ D_BOULDERROLLSND,
+ D_PITTRAPSND,
+ D_FIREJETSND,
+ D_ACTORSQUISHSND,
+ D_ACTORBURNEDSND,
+ D_ACTORSKELETONSND,
+
+ D_SPEARSTABSND,
+ D_CYLINDERMOVESND,
+ D_ELEVATORONSND,
+ D_ELEVATORENDSND,
+
+ D_SPRINGBOARDSND,
+ D_LIGHTNINGSND,
+ D_WINDSND,
+// D_WATERSND,
+
+// SECRET SOUNDS
+
+ D_DOPEFISHSND,
+ D_YOUSUCKSND,
+
+ D_SILLYMOVESND,
+ D_SOUNDSELECTSND,
+ D_SOUNDESCSND,
+ D_BODYLANDSND,
+ D_GIBSPLASHSND,
+ D_ACTORLANDSND,
+
+ D_LASTSOUND=-1
+
+} digisounds;
+
+static sound_t sounds[MAXSOUNDS] = {
+//SD_MENUFLIP,
+//|-------DIGITAL--------|---------MUSE---------|----FLAGS---|
+ {{D_MENUFLIP, MUSE_MENUFLIPSND, }, 0,SD_PRIOMENU, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ESCPRESSEDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ESCPRESSEDSND, MUSE_ESCPRESSEDSND, }, 0,SD_PRIOMENU, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_MOVECURSORSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_MOVECURSORSND, MUSE_MOVECURSORSND, }, 0,SD_PRIOMENU, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SELECTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SELECTSND, MUSE_SELECTSND, }, 0,SD_PRIOMENU, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_WARNINGBOXSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_WARNINGBOXSND, MUSE_WARNINGBOXSND, }, 0,SD_PRIOMENU, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_INFOBOXSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_INFOBOXSND, MUSE_INFOBOXSND, }, 0,SD_PRIOMENU, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_QUESTIONBOXSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_QUESTIONBOXSND, MUSE_QUESTIONBOXSND, }, 0,SD_PRIOMENU, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NOPESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_NOPESND, MUSE_NOPESND, }, 0,SD_PRIOMENU, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_QUIT1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_QUIT1SND, MUSE_SELECTSND, }, 0,SD_PRIOQUIT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_QUIT2SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_QUIT2SND, MUSE_SELECTSND, }, 0,SD_PRIOQUIT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_QUIT3SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_QUIT3SND, MUSE_SELECTSND, }, 0,SD_PRIOQUIT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_QUIT4SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_QUIT4SND, MUSE_SELECTSND, }, 0,SD_PRIOQUIT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_QUIT5SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_QUIT5SND, MUSE_SELECTSND, }, 0,SD_PRIOQUIT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_QUIT6SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_QUIT6SND, MUSE_SELECTSND, }, 0,SD_PRIOQUIT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_QUIT7SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_QUIT7SND, MUSE_SELECTSND, }, 0,SD_PRIOQUIT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LEVELSTARTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LEVELSTARTSND, MUSE_LEVELSTARTSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LEVELDONESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LEVELDONESND, MUSE_LEVELENDSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GAMEOVERSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GAMEOVERSND, MUSE_GAMEOVERSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ENDBONUS1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ENDBONUS1SND, MUSE_ENDBONUS1SND, }, SD_PITCHSHIFTOFF,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NOBONUSSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_NOBONUSSND, MUSE_NOBONUSSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PERCENT100SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PERCENT100SND, MUSE_PERCENT100SND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_HITWALLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_HITWALLSND, MUSE_HITWALLSND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SELECTWPNSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SELECTWPNSND, MUSE_SELECTWPNSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NOWAYSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_NOWAYSND, MUSE_NOWAYSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DONOTHINGSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DONOTHINGSND, MUSE_DONOTHINGSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NOITEMSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_NOWAYSND, MUSE_NOITEMSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERDYINGSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERDYINGSND, MUSE_PLAYERDYINGSND, }, SD_PITCHSHIFTOFF,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERTCDEATHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTCDEATHSND, MUSE_PLAYERDEATHSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERTBDEATHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTBDEATHSND, MUSE_PLAYERDEATHSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERDWDEATHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERDWDEATHSND, MUSE_PLAYERDEATHSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERLNDEATHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERLNDEATHSND, MUSE_PLAYERDEATHSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERIPFDEATHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERIPFDEATHSND, MUSE_PLAYERDEATHSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERTCHURTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTCHURTSND, MUSE_PLAYERHURTSND, }, SD_PLAYONCE, SD_PRIOPHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERTBHURTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTBHURTSND, MUSE_PLAYERHURTSND, }, SD_PLAYONCE, SD_PRIOPHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERDWHURTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERDWHURTSND, MUSE_PLAYERHURTSND, }, SD_PLAYONCE, SD_PRIOPHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERLNHURTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERLNHURTSND, MUSE_PLAYERHURTSND, }, SD_PLAYONCE, SD_PRIOPHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERIPFHURTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERIPFHURTSND, MUSE_PLAYERHURTSND, }, SD_PLAYONCE, SD_PRIOPHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERTCSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTCSND, MUSE_PLAYERYESSND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERTBSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTBSND, MUSE_PLAYERYESSND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERDWSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERDWSND, MUSE_PLAYERYESSND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERLNSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERLNSND, MUSE_PLAYERYESSND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERIPFSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERIPFSND, MUSE_PLAYERYESSND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_WALK1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+// {{D_WALK1SND, MUSE_WALK1SND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_WALK2SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+// {{D_WALK2SND, MUSE_WALK2SND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERBURNEDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERBURNEDSND, MUSE_PLAYERHURTSND, }, SD_PLAYONCE,SD_PRIOPHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERLANDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERLANDSND, MUSE_PLAYERLANDSND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERCOUGHMSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERCOUGHMSND, MUSE_LASTSOUND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERCOUGHFSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERCOUGHFSND, MUSE_LASTSOUND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NETWIGGLESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_NETWIGGLESND, MUSE_LASTSOUND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NETFALLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_NETFALLSND, MUSE_NETFALLSND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ATKPISTOLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ATKPISTOLSND, MUSE_ATKPISTOLSND, }, SD_WRITE,SD_PRIOPGUNS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ATKTWOPISTOLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ATKTWOPISTOLSND, MUSE_ATKPISTOLSND, }, SD_WRITE,SD_PRIOPGUNS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ATKMP40SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ATKMP40SND, MUSE_ATKMP40SND, }, SD_WRITE,SD_PRIOPMP40, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_RICOCHET1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_RICOCHET1SND, MUSE_RICOCHETSND, }, SD_WRITE,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_RICOCHET2SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_RICOCHET2SND, MUSE_RICOCHETSND, }, SD_WRITE,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_RICOCHET3SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_RICOCHET3SND, MUSE_RICOCHETSND, }, SD_WRITE,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BAZOOKAFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BAZOOKAFIRESND, MUSE_MISSILEFIRESND, }, SD_WRITE,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIREBOMBFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FIREBOMBFIRESND, MUSE_MISSILEFIRESND, }, SD_WRITE,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_HEATSEEKFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_HEATSEEKFIRESND, MUSE_MISSILEFIRESND, }, SD_WRITE,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DRUNKFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DRUNKFIRESND, MUSE_MISSILEFIRESND, }, SD_WRITE,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FLAMEWALLFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FLAMEWALLFIRESND, MUSE_MISSILEFIRESND, }, SD_WRITE,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FLAMEWALLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FLAMEWALLSND, MUSE_FLAMEWALLSND, }, 0,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SPLITFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SPLITFIRESND, MUSE_MISSILEFIRESND, }, 0,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SPLITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SPLITSND, MUSE_MISSILEFIRESND, }, 0,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GRAVBUILDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GRAVBUILDSND, MUSE_WEAPONBUILDSND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GRAVFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GRAVFIRESND, MUSE_ENERGYFIRESND, }, 0,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GRAVSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GRAVSND, MUSE_LASTSOUND, }, 0,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GRAVHITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GRAVHITSND, MUSE_MISSILEHITSND, }, 0,SD_PRIOEXPL, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIREHITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FIREHITSND, MUSE_MISSILEHITSND, }, 0,SD_PRIOEXPL, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_MISSILEFLYSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_MISSILEFLYSND, MUSE_LASTSOUND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_MISSILEHITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_MISSILEHITSND, MUSE_MISSILEHITSND, }, 0,SD_PRIOEXPL, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_EXCALIBOUNCESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_EXCALIBOUNCESND, MUSE_LASTSOUND, }, 0,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_EXCALISWINGSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_EXCALISWINGSND, MUSE_MISSILEFIRESND, }, 0,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_EXCALIHITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_EXCALIHITSND, MUSE_MISSILEHITSND, }, 0,SD_PRIOEXPL, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_EXCALIBUILDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_EXCALIBUILDSND, MUSE_WEAPONBUILDSND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_EXCALIBLASTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_EXCALIBLASTSND, MUSE_ENERGYFIRESND, }, 0,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GODMODEFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GODMODEFIRESND, MUSE_ENERGYFIRESND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GODMODE1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GODMODE1SND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GODMODE2SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GODMODE2SND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GODMODE3SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GODMODE3SND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOSEMODESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOSEMODESND, MUSE_LOSEMODESND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOGMODEPANTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DOGMODEPANTSND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOGMODEBITE1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DOGMODEBITE1SND, MUSE_DOGBITESND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOGMODEBITE2SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DOGMODEBITE2SND, MUSE_DOGBITESND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOGMODELICKSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DOGMODELICKSND, MUSE_DOGLICKSND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOGMODEBLASTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DOGMODEBLASTSND, MUSE_DOGBITESND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOGMODEPREPBLASTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DOGMODEPREPBLASTSND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOGMANSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DOGMANSND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOGWOMANSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DOGWOMANSND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GODMANSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GODMANSND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GODWOMANSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GODWOMANSND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FLYINGSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FLYINGSND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GLASSBREAKSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GLASSBREAKSND, MUSE_GLASSBREAKSND, }, 0,SD_PRIOGLASS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ITEMBLOWSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ITEMBLOWSND, MUSE_EXPLOSIONSND, }, 0,SD_PRIOEXPL, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BONUSBARRELSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BONUSBARRELSND, MUSE_EXPLOSIONSND, }, 0,SD_PRIOEXPL, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_TOUCHPLATESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_TOUCHPLATESND, MUSE_TOUCHPLATESND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BADTOUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BADTOUCHSND, MUSE_BADTOUCHSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_EXPLODEFLOORSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_EXPLODEFLOORSND, MUSE_EXPLOSIONSND, }, 0,SD_PRIOEXPL, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_EXPLODESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_EXPLODESND, MUSE_EXPLOSIONSND, }, 0,SD_PRIOEXPL, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GASSTARTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_TOUCHPLATESND, MUSE_SWITCHSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GASHISSSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GASHISSSND, MUSE_LASTSOUND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GASENDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GASENDSND, MUSE_SWITCHSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GASMASKSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GASMASKSND, MUSE_LASTSOUND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETKEYSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETKEYSND, MUSE_GETKEYSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETBONUSSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETBONUSSND, MUSE_GETBONUSSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETHEALTH1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETHEALTH1SND, MUSE_GETHEALTHSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETHEALTH2SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETHEALTH2SND, MUSE_GETHEALTHSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_COOKHEALTHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_COOKHEALTHSND, MUSE_GETBONUSSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETWEAPONSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETWEAPONSND, MUSE_GETWEAPONSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETKNIFESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETKNIFESND, MUSE_GETWEAPONSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETGODSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETGODSND, MUSE_GETPOWERUPSND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETDOGSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETDOGSND, MUSE_GETPOWERUPSND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETFLEETSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETFLEETSND, MUSE_GETPOWERUPSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETELASTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETELASTSND, MUSE_GETPOWERDOWNSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETSHROOMSSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETSHROOMSSND, MUSE_GETPOWERDOWNSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETBVESTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETBVESTSND, MUSE_GETARMORSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETAVESTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETAVESTSND, MUSE_GETARMORSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETMASKSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETMASKSND, MUSE_GETARMORSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETBATSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETBATSND, MUSE_GETWEIRDSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETHEADSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETHEADSND, MUSE_GETWEIRDSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GET1UPSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GET1UPSND, MUSE_GETLIFESND, }, SD_PITCHSHIFTOFF,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GET3UPSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GET3UPSND, MUSE_GETLIFESND, }, SD_PITCHSHIFTOFF,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_RESPAWNSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_RESPAWNSND, MUSE_GETBONUSSND, }, SD_PITCHSHIFTOFF,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERSPAWNSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERSPAWNSND, MUSE_GETLIFESND, }, SD_PITCHSHIFTOFF,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARD1SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOWGUARD1SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARD1ASEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOWGUARD1ASEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARD1SEE3SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOWGUARD1SEE2SND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARD2SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOWGUARD1SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARD2ASEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOWGUARD1ASEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARD2SEE3SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOWGUARD1SEE2SND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARDFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ATKPISTOLSND, MUSE_ACTORFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARDOUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOWGUARDOUCHSND, MUSE_ACTOROUCHSND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARD1DIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOWGUARD1DIESND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARD2DIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOWGUARD1DIESND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNEAKYSPRINGMSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SNEAKYSPRINGMSND, MUSE_ACTORDOITSND, }, 0,SD_PRIOASNEAK, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNEAKYSPRINGFSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SNEAKYSPRINGMSND, MUSE_ACTORDOITSND, }, 0,SD_PRIOASNEAK, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_HIGHGUARD1SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_HIGHGUARD1SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_HIGHGUARD2SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_HIGHGUARD2SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_HIGHGUARDFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ATKMP40SND, MUSE_ACTORFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_HIGHGUARDOUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_HIGHGUARDOUCHSND, MUSE_ACTOROUCHSND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_HIGHGUARDDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_HIGHGUARDDIESND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_OVERP1SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_OVERP1SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_OVERP2SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_OVERP1SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_OVERPFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ATKPISTOLSND, MUSE_ACTORFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_OVERPNETSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_OVERPNETSND, MUSE_ACTORTHROWSND, }, 0,SD_PRIOASNEAK, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_OVERPOUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_OVERPOUCHSND, MUSE_ACTOROUCHSND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_OVERPDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_OVERPDIESND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_STRIKE1SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_STRIKE1SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_STRIKE2SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_STRIKE1SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_STRIKEFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ATKPISTOLSND, MUSE_ACTORFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_STRIKEROLLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_STRIKEROLLSND, MUSE_ACTORROLLSND, }, 0,SD_PRIOASNEAK, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_STRIKEOUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_STRIKEOUCHSND, MUSE_ACTOROUCHSND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_STRIKEDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_STRIKEDIESND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLITZ1SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BLITZ1SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLITZ2SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BLITZ2SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLITZFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ATKPISTOLSND, MUSE_ACTORFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLITZSTEALSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BLITZSTEALSND, MUSE_GETPOWERDOWNSND, }, 0,SD_PRIOASNEAK, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLITZOUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BLITZOUCHSND, MUSE_ACTOROUCHSND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLITZDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BLITZDIESND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLITZPLEADSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BLITZPLEADSND, MUSE_LASTSOUND, }, SD_PLAYONCE,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLITZPLEAD1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BLITZPLEAD1SND, MUSE_LASTSOUND, }, SD_PLAYONCE,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLITZPLEAD2SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BLITZPLEAD2SND, MUSE_LASTSOUND, }, SD_PLAYONCE,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ENFORCERSEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ENFORCERSEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ENFORCERFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ENFORCERFIRESND, MUSE_ACTORFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ENFORCERTHROWSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ENFORCERTHROWSND, MUSE_ACTORTHROWSND, }, 0,SD_PRIOASNEAK, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ENFORCEROUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ENFORCEROUCHSND, MUSE_ACTOROUCHSND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ENFORCERDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ENFORCERDIESND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_MONKSEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_MONKSEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_MONKGRABSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_MONKGRABSND, MUSE_ACTORDOITSND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_MONKOUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_MONKOUCHSND, MUSE_ACTOROUCHSND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_MONKDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_MONKDIESND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIREMONKSEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FIREMONKSEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIREMONKFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FIREMONKFIRESND, MUSE_ACTORFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIREMONKOUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FIREMONKOUCHSND, MUSE_ACTOROUCHSND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIREMONKDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FIREMONKDIESND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ROBOTSEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ROBOTSEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ROBOTFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ROBOTFIRESND, MUSE_ACTORFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ROBOTDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ROBOTDIESND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ROBOTMOVESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_KRISTMOTORSND, MUSE_LASTSOUND, }, SD_PLAYONCE,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BALLISTIKRAFTSEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BAZOOKAFIRESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BALLISTIKRAFTFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ROBOTFIRESND, MUSE_ACTORFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARIANSEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DARIANSEESND, MUSE_BOSSSEESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARIANFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BAZOOKAFIRESND, MUSE_BOSSFIRESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARIANGONNAUSESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DARIANGONNAUSESND, MUSE_BOSSDOSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARIANUSESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_TOUCHPLATESND, MUSE_BOSSDOSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARIANHIDESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DARIANHIDESND, MUSE_BOSSDOSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARIANDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DARIANDIESND, MUSE_BOSSDIESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARIANSAY1,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DARIANSAY1, MUSE_BOSSWARNSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARIANSAY2,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DARIANSAY2, MUSE_BOSSHEYSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARIANSAY3,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DARIANSAY3, MUSE_BOSSWARNSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTSEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_KRISTSEESND, MUSE_BOSSSEESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BAZOOKAFIRESND, MUSE_BOSSFIRESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTMOTORSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_KRISTMOTORSND, MUSE_LASTSOUND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTTURNSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_KRISTTURNSND, MUSE_BOSSBEEPSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTDROPSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_KRISTDROPSND, MUSE_BOSSDOSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTMINEBEEPSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_KRISTMINEBEEPSND, MUSE_BOSSBEEPSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTMINEHITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_KRISTMINEHITSND, MUSE_MISSILEHITSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_KRISTDIESND, MUSE_BOSSDIESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTSAY1,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_KRISTSAY1, MUSE_BOSSWARNSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTSAY2,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_KRISTSAY2, MUSE_BOSSHEYSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTSAY3,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_KRISTSAY3, MUSE_BOSSWARNSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NMESEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_NMESEESND, MUSE_BOSSSEESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NMEREADYSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_NMEREADYSND, MUSE_BOSSWARNSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NMEFIRE1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BAZOOKAFIRESND, MUSE_BOSSFIRESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NMEAPARTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_NMEAPARTSND, MUSE_BOSSBEEPSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NMEUFOSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_NMEUFOSND, MUSE_MISSILEFIRESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NMEDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_EXPLODESND, MUSE_BOSSDIESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKSEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DARKMONKSEESND, MUSE_BOSSSEESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKFIRE1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DARKMONKFIRE1SND, MUSE_BOSSFIRESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKFIRE2SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DARKMONKFIRE2SND, MUSE_BOSSFIRE2SND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKFIRE3SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DARKMONKFIRE3SND, MUSE_BOSSFIRESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKFIRE4SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DARKMONKFIRE4SND, MUSE_BOSSFIRE2SND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKRECHARGESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DARKMONKRECHARGESND, MUSE_WEAPONBUILDSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKFLOATSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DARKMONKFLOATSND, MUSE_LASTSOUND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DARKMONKDIESND, MUSE_BOSSDIESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKSAY1,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DARKMONKSAY1, MUSE_BOSSWARNSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKSAY2,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DARKMONKSAY2, MUSE_BOSSHEYSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKSAY3,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DARKMONKSAY3, MUSE_BOSSWARNSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNAKESEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SNAKESEESND, MUSE_BOSSSEESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNAKEREADYSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SNAKEREADYSND, MUSE_BOSSBEEPSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNAKECHARGESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SNAKECHARGESND, MUSE_WEAPONBUILDSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNAKEOUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SNAKEOUCHSND, MUSE_BOSSOUCHSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNAKEDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SNAKEDIESND, MUSE_BOSSDIESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNAKESPITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SNAKESPITSND, MUSE_BOSSFIRESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNAKESAY1,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SNAKESAY1, MUSE_BOSSWARNSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNAKESAY2,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SNAKESAY2, MUSE_BOSSHEYSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNAKESAY3,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SNAKESAY3, MUSE_BOSSWARNSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_EMPLACEMENTSEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_EMPLACEMENTSEESND, MUSE_SWITCHSND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_EMPLACEMENTFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_EMPLACEMENTFIRESND, MUSE_EMPFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BIGEMPLACEFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BIGEMPLACEFIRESND, MUSE_EMPFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_OPENDOORSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_OPENDOORSND, MUSE_OPENDOORSND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_CLOSEDOORSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_CLOSEDOORSND, MUSE_CLOSEDOORSND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOORHITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ELEVATORENDSND, MUSE_LASTSOUND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIRECHUTESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FIRECHUTESND, MUSE_MISSILEFIRESND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIREBALLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FIREBALLSND, MUSE_LASTSOUND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIREBALLHITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FIREBALLHITSND, MUSE_MISSILEHITSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLADESPINSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BLADESPINSND, MUSE_SPINBLADESND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PUSHWALLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PUSHWALLSND, MUSE_PUSHWALLSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PUSHWALLHITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PUSHWALLHITSND, MUSE_MISSILEHITSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GOWALLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GOWALLSND, MUSE_PUSHWALLSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_TURBOWALLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_TURBOWALLSND, MUSE_PUSHWALLSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BOULDERHITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BOULDERHITSND, MUSE_MISSILEHITSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BOULDERROLLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BOULDERROLLSND, MUSE_BOULDERSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BOULDERFALLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BOULDERHITSND, MUSE_PITTRAPSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PITTRAPSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PITTRAPSND, MUSE_PITTRAPSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIREJETSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FIREJETSND, MUSE_FIREJETSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ACTORSQUISHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ACTORSQUISHSND, MUSE_ACTORSQUISHSND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ACTORBURNEDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ACTORBURNEDSND, MUSE_ACTOROUCHSND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ACTORSKELETONSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ACTORSKELETONSND, MUSE_LASTSOUND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SPEARSTABSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SPEARSTABSND, MUSE_STABBERSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_CYLINDERMOVESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_CYLINDERMOVESND, MUSE_CYLINDERHITSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ELEVATORONSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ELEVATORONSND, MUSE_ELEVATORSND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ELEVATORENDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ELEVATORENDSND, MUSE_LASTSOUND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SPRINGBOARDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SPRINGBOARDSND, MUSE_SPRINGBOARDSND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LIGHTNINGSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LIGHTNINGSND, MUSE_LASTSOUND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_WINDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_WINDSND, MUSE_LASTSOUND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_WATERSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_LASTSOUND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BODYLANDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BODYLANDSND, MUSE_LASTSOUND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GIBSPLASHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GIBSPLASHSND, MUSE_LASTSOUND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ACTORLANDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ACTORLANDSND, MUSE_LASTSOUND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOPEFISHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DOPEFISHSND, MUSE_LASTSOUND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_YOUSUCKSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_YOUSUCKSND, MUSE_LASTSOUND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SILLYMOVESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SILLYMOVESND, MUSE_LASTSOUND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SOUNDSELECTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SOUNDSELECTSND, MUSE_LASTSOUND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SOUNDESCSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SOUNDESCSND, MUSE_LASTSOUND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM1SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM2SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM2SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM3SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM3SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM4SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM4SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM5SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM5SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM6SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM6SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM7SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM7SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM8SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM8SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM9SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM9SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM10SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM10SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LASTSOUND
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_LASTSOUND, }, 0,SD_PRIOSECRET, 0, 0, 0}
+//����������������������������������������������������������������������
+};
+
--- /dev/null
+++ b/rott/snd_shar.h
@@ -1,0 +1,1302 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+typedef enum {
+
+ D_LASTSOUND=-1,
+// MENU SOUNDS
+
+ D_MENUFLIP,
+ D_ESCPRESSEDSND,
+ D_MOVECURSORSND,
+ D_SELECTSND,
+ D_WARNINGBOXSND,
+ D_INFOBOXSND,
+ D_QUESTIONBOXSND,
+ D_NOPESND,
+
+// GAME SOUNDS
+
+ D_LEVELSTARTSND,
+ D_LEVELDONESND,
+ D_GAMEOVERSND,
+
+// LEVEL END SCREEN
+
+ D_ENDBONUS1SND,
+
+// PLAYER SOUNDS
+
+ D_HITWALLSND,
+ D_SELECTWPNSND,
+ D_NOWAYSND,
+ D_DONOTHINGSND,
+//D_NOITEMSND,
+ D_PLAYERDYINGSND,
+
+ D_PLAYERTCDEATHSND,
+ D_PLAYERTCHURTSND,
+ D_PLAYERTCSND,
+//D_WALK1SND,
+//D_WALK2SND,
+ D_PLAYERBURNEDSND,
+ D_PLAYERLANDSND,
+ D_PLAYERCOUGHMSND,
+
+// PLAYER WEAPONS
+
+ D_ATKPISTOLSND,
+ D_ATKTWOPISTOLSND,
+ D_ATKMP40SND,
+ D_RICOCHET1SND,
+ D_RICOCHET2SND,
+ D_RICOCHET3SND,
+ D_BAZOOKAFIRESND,
+ D_HEATSEEKFIRESND,
+ D_FIREBOMBFIRESND,
+ D_DRUNKFIRESND,
+ D_FLAMEWALLFIRESND,
+ D_FLAMEWALLSND,
+ D_GRAVSND,
+ D_FIREHITSND,
+ D_MISSILEFLYSND,
+ D_MISSILEHITSND,
+ D_GODMODEFIRESND,
+ D_GODMODE1SND,
+ D_GODMODE2SND,
+ D_GODMODE3SND,
+ D_LOSEMODESND,
+ D_GODMANSND,
+ D_FLYINGSND,
+
+// PLAYER-CAUSED SOUNDS
+
+ D_GLASSBREAKSND,
+ D_ITEMBLOWSND,
+ D_BONUSBARRELSND,
+ D_TOUCHPLATESND,
+ D_BADTOUCHSND,
+ D_EXPLODEFLOORSND,
+ D_EXPLODESND,
+//D_GASSTARTSND,
+ D_GASHISSSND,
+ D_GASENDSND,
+ D_GASMASKSND,
+
+// GET ITEM SOUNDS
+
+ D_GETKEYSND,
+ D_GETBONUSSND,
+ D_GETHEALTH1SND,
+ D_COOKHEALTHSND,
+
+ D_GETWEAPONSND,
+ D_GETGODSND,
+ D_GETFLEETSND,
+ D_GETELASTSND,
+ D_GETSHROOMSSND,
+ D_GETBVESTSND,
+ D_GETAVESTSND,
+ D_GETMASKSND,
+
+ D_GET1UPSND,
+ D_RESPAWNSND,
+ D_PLAYERSPAWNSND,
+
+// ACTOR SOUNDS
+
+ D_LOWGUARD1SEESND,
+ D_LOWGUARD1SEE2SND,
+ D_LOWGUARDOUCHSND,
+ D_LOWGUARD1DIESND,
+ D_SNEAKYSPRINGMSND,
+
+ D_HIGHGUARD1SEESND,
+ D_HIGHGUARDOUCHSND,
+ D_HIGHGUARDDIESND,
+
+ D_STRIKE1SEESND,
+ D_STRIKEROLLSND,
+ D_STRIKEOUCHSND,
+ D_STRIKEDIESND,
+
+ D_BLITZ1SEESND,
+ D_BLITZSTEALSND,
+ D_BLITZOUCHSND,
+ D_BLITZDIESND,
+ D_BLITZPLEADSND,
+ D_BLITZPLEAD1SND,
+ D_BLITZPLEAD2SND,
+
+ D_ENFORCERSEESND,
+ D_ENFORCERFIRESND,
+ D_ENFORCERTHROWSND,
+ D_ENFORCEROUCHSND,
+ D_ENFORCERDIESND,
+
+ D_ROBOTSEESND,
+ D_ROBOTFIRESND,
+ D_ROBOTDIESND,
+
+ D_KRISTMOTORSND,
+
+// ENVIRONMENT SOUNDS
+
+ D_OPENDOORSND,
+ D_CLOSEDOORSND,
+ D_DOORHITSND,
+
+ D_FIRECHUTESND,
+ D_FIREBALLSND,
+ D_FIREBALLHITSND,
+ D_BLADESPINSND,
+ D_PUSHWALLSND,
+ D_PUSHWALLHITSND,
+ D_GOWALLSND,
+ D_TURBOWALLSND,
+ D_PITTRAPSND,
+ D_FIREJETSND,
+ D_ACTORSQUISHSND,
+ D_ACTORBURNEDSND,
+ D_ACTORSKELETONSND,
+
+ D_SPEARSTABSND,
+ D_CYLINDERMOVESND,
+ D_ELEVATORONSND,
+ D_ELEVATORENDSND,
+ D_SPRINGBOARDSND,
+ D_LIGHTNINGSND,
+//D_WINDSND,
+
+// SECRET SOUNDS
+
+ D_YOUSUCKSND,
+ D_BODYLANDSND,
+ D_GIBSPLASHSND,
+ D_ACTORLANDSND
+
+} digisounds;
+
+
+static sound_t sounds[MAXSOUNDS] = {
+//SD_MENUFLIP,
+//|-------DIGITAL--------|---------MUSE---------|-MIDI----------FLAGS---|
+ {{D_MENUFLIP, MUSE_MENUFLIPSND, }, 0,SD_PRIOMENU, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ESCPRESSEDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ESCPRESSEDSND, MUSE_ESCPRESSEDSND, }, 0,SD_PRIOMENU, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_MOVECURSORSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_MOVECURSORSND, MUSE_MOVECURSORSND, }, 0,SD_PRIOMENU, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SELECTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SELECTSND, MUSE_SELECTSND, }, 0,SD_PRIOMENU, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_WARNINGBOXSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_WARNINGBOXSND, MUSE_WARNINGBOXSND, }, 0,SD_PRIOMENU, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_INFOBOXSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_INFOBOXSND, MUSE_INFOBOXSND, }, 0,SD_PRIOMENU, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_QUESTIONBOXSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_QUESTIONBOXSND, MUSE_QUESTIONBOXSND, }, 0,SD_PRIOMENU, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NOPESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_NOPESND, MUSE_NOPESND, }, 0,SD_PRIOMENU, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_QUIT1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_SELECTSND, }, 0,SD_PRIOQUIT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_QUIT2SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_SELECTSND, }, 0,SD_PRIOQUIT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_QUIT3SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_SELECTSND, }, 0,SD_PRIOQUIT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_QUIT4SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_SELECTSND, }, 0,SD_PRIOQUIT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_QUIT5SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_SELECTSND, }, 0,SD_PRIOQUIT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_QUIT6SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_SELECTSND, }, 0,SD_PRIOQUIT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_QUIT7SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_SELECTSND, }, 0,SD_PRIOQUIT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LEVELSTARTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LEVELSTARTSND, MUSE_LEVELSTARTSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LEVELDONESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LEVELDONESND, MUSE_LEVELENDSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GAMEOVERSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GAMEOVERSND, MUSE_GAMEOVERSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ENDBONUS1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ENDBONUS1SND, MUSE_ENDBONUS1SND, }, SD_PITCHSHIFTOFF,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NOBONUSSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_NOBONUSSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PERCENT100SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_PERCENT100SND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_HITWALLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_HITWALLSND, MUSE_HITWALLSND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SELECTWPNSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SELECTWPNSND, MUSE_SELECTWPNSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NOWAYSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_NOWAYSND, MUSE_NOWAYSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DONOTHINGSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DONOTHINGSND, MUSE_DONOTHINGSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NOITEMSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_NOWAYSND, MUSE_NOITEMSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERDYINGSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERDYINGSND, MUSE_PLAYERDYINGSND, }, SD_PITCHSHIFTOFF,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERTCDEATHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTCDEATHSND, MUSE_PLAYERDEATHSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERTBDEATHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTCDEATHSND, MUSE_PLAYERDEATHSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERDWDEATHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTCDEATHSND, MUSE_PLAYERDEATHSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERLNDEATHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTCDEATHSND, MUSE_PLAYERDEATHSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERIPFDEATHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTCDEATHSND, MUSE_PLAYERDEATHSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERTCHURTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTCHURTSND, MUSE_PLAYERHURTSND, }, SD_PLAYONCE, SD_PRIOPHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERTBHURTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTCHURTSND, MUSE_PLAYERHURTSND, }, SD_PLAYONCE, SD_PRIOPHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERDWHURTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTCHURTSND, MUSE_PLAYERHURTSND, }, SD_PLAYONCE, SD_PRIOPHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERLNHURTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTCHURTSND, MUSE_PLAYERHURTSND, }, SD_PLAYONCE, SD_PRIOPHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERIPFHURTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTCHURTSND, MUSE_PLAYERHURTSND, }, SD_PLAYONCE, SD_PRIOPHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERTCSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTCSND, MUSE_PLAYERYESSND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERTBSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTCSND, MUSE_PLAYERYESSND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERDWSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTCSND, MUSE_PLAYERYESSND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERLNSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTCSND, MUSE_PLAYERYESSND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERIPFSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERTCSND, MUSE_PLAYERYESSND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_WALK1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+// {{D_WALK1SND, MUSE_WALK1SND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_WALK2SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+// {{D_WALK2SND, MUSE_WALK2SND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERBURNEDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERBURNEDSND, MUSE_PLAYERHURTSND, }, SD_PLAYONCE,SD_PRIOPHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERLANDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERLANDSND, MUSE_PLAYERLANDSND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERCOUGHMSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERCOUGHMSND, MUSE_LASTSOUND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERCOUGHFSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_LASTSOUND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NETWIGGLESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_LASTSOUND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NETFALLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_NETFALLSND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ATKPISTOLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ATKPISTOLSND, MUSE_ATKPISTOLSND, }, SD_WRITE,SD_PRIOPGUNS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ATKTWOPISTOLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ATKTWOPISTOLSND, MUSE_ATKPISTOLSND, }, SD_WRITE,SD_PRIOPGUNS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ATKMP40SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ATKMP40SND, MUSE_ATKMP40SND, }, SD_WRITE,SD_PRIOPMP40, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_RICOCHET1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_RICOCHET1SND, MUSE_RICOCHETSND, }, SD_WRITE,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_RICOCHET2SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_RICOCHET2SND, MUSE_RICOCHETSND, }, SD_WRITE,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_RICOCHET3SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_RICOCHET3SND, MUSE_RICOCHETSND, }, SD_WRITE,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BAZOOKAFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BAZOOKAFIRESND, MUSE_MISSILEFIRESND, }, SD_WRITE,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIREBOMBFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FIREBOMBFIRESND, MUSE_MISSILEFIRESND, }, SD_WRITE,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_HEATSEEKFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_HEATSEEKFIRESND, MUSE_MISSILEFIRESND, }, SD_WRITE,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DRUNKFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_DRUNKFIRESND, MUSE_MISSILEFIRESND, }, SD_WRITE,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FLAMEWALLFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FLAMEWALLFIRESND, MUSE_MISSILEFIRESND, }, SD_WRITE,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FLAMEWALLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FLAMEWALLSND, MUSE_FLAMEWALLSND, }, 0,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SPLITFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_MISSILEFIRESND, }, 0,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SPLITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_MISSILEFIRESND, }, 0,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GRAVBUILDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_WEAPONBUILDSND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GRAVFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_ENERGYFIRESND, }, 0,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GRAVSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GRAVSND, MUSE_LASTSOUND, }, 0,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GRAVHITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_MISSILEHITSND, }, 0,SD_PRIOEXPL, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIREHITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FIREHITSND, MUSE_MISSILEHITSND, }, 0,SD_PRIOEXPL, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_MISSILEFLYSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_MISSILEFLYSND, MUSE_LASTSOUND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_MISSILEHITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_MISSILEHITSND, MUSE_MISSILEHITSND, }, 0,SD_PRIOEXPL, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_EXCALIBOUNCESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_LASTSOUND, }, 0,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_EXCALISWINGSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_MISSILEFIRESND, }, 0,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_EXCALIHITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_MISSILEHITSND, }, 0,SD_PRIOEXPL, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_EXCALIBUILDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_WEAPONBUILDSND, }, 0,SD_PRIOPSNDS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_EXCALIBLASTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_ENERGYFIRESND, }, 0,SD_PRIOPMISS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GODMODEFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GODMODEFIRESND, MUSE_ENERGYFIRESND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GODMODE1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GODMODE1SND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GODMODE2SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GODMODE2SND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GODMODE3SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GODMODE3SND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOSEMODESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOSEMODESND, MUSE_LOSEMODESND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOGMODEPANTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOGMODEBITE1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_DOGBITESND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOGMODEBITE2SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_DOGBITESND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOGMODELICKSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_DOGLICKSND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOGMODEBLASTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_DOGBITESND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOGMODEPREPBLASTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOGMANSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOGWOMANSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GODMANSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GODMANSND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GODWOMANSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FLYINGSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FLYINGSND, MUSE_LASTSOUND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GLASSBREAKSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GLASSBREAKSND, MUSE_GLASSBREAKSND, }, 0,SD_PRIOGLASS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ITEMBLOWSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ITEMBLOWSND, MUSE_EXPLOSIONSND, }, 0,SD_PRIOEXPL, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BONUSBARRELSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BONUSBARRELSND, MUSE_EXPLOSIONSND, }, 0,SD_PRIOEXPL, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_TOUCHPLATESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_TOUCHPLATESND, MUSE_TOUCHPLATESND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BADTOUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BADTOUCHSND, MUSE_BADTOUCHSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_EXPLODEFLOORSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_EXPLODEFLOORSND, MUSE_EXPLOSIONSND, }, 0,SD_PRIOEXPL, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_EXPLODESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_EXPLODESND, MUSE_EXPLOSIONSND, }, 0,SD_PRIOEXPL, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GASSTARTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_TOUCHPLATESND, MUSE_SWITCHSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GASHISSSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GASHISSSND, MUSE_LASTSOUND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GASENDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GASENDSND, MUSE_SWITCHSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GASMASKSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GASMASKSND, MUSE_LASTSOUND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETKEYSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETKEYSND, MUSE_GETKEYSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETBONUSSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETBONUSSND, MUSE_GETBONUSSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETHEALTH1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETHEALTH1SND, MUSE_GETHEALTHSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETHEALTH2SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETHEALTH1SND, MUSE_GETHEALTHSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_COOKHEALTHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_COOKHEALTHSND, MUSE_GETBONUSSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETWEAPONSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETWEAPONSND, MUSE_GETWEAPONSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETKNIFESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_GETWEAPONSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETGODSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETGODSND, MUSE_GETPOWERUPSND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETDOGSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_GETPOWERUPSND, }, 0,SD_PRIOGODDOG, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETFLEETSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETFLEETSND, MUSE_GETPOWERUPSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETELASTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETELASTSND, MUSE_GETPOWERDOWNSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETSHROOMSSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETSHROOMSSND, MUSE_GETPOWERDOWNSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETBVESTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETBVESTSND, MUSE_GETARMORSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETAVESTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETAVESTSND, MUSE_GETARMORSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETMASKSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GETMASKSND, MUSE_GETARMORSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETBATSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_GETWEIRDSND, }, 0,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GETHEADSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_GETWEIRDSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GET1UPSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GET1UPSND, MUSE_GETLIFESND, }, SD_PITCHSHIFTOFF,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GET3UPSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_GETLIFESND, }, SD_PITCHSHIFTOFF,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_RESPAWNSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_RESPAWNSND, MUSE_GETBONUSSND, }, SD_PITCHSHIFTOFF,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PLAYERSPAWNSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PLAYERSPAWNSND, MUSE_GETLIFESND, }, SD_PITCHSHIFTOFF,SD_PRIOGAME, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARD1SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOWGUARD1SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARD1ASEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOWGUARD1SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARD1SEE3SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOWGUARD1SEE2SND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARD2SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOWGUARD1SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARD2ASEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOWGUARD1SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARD2SEE3SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOWGUARD1SEE2SND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARDFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ATKPISTOLSND, MUSE_ACTORFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARDOUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOWGUARDOUCHSND, MUSE_ACTOROUCHSND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARD1DIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOWGUARD1DIESND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LOWGUARD2DIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LOWGUARD1DIESND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNEAKYSPRINGMSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SNEAKYSPRINGMSND, MUSE_ACTORDOITSND, }, 0,SD_PRIOASNEAK, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNEAKYSPRINGFSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SNEAKYSPRINGMSND, MUSE_ACTORDOITSND, }, 0,SD_PRIOASNEAK, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_HIGHGUARD1SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_HIGHGUARD1SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_HIGHGUARD2SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_HIGHGUARD1SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_HIGHGUARDFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ATKMP40SND, MUSE_ACTORFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_HIGHGUARDOUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_HIGHGUARDOUCHSND, MUSE_ACTOROUCHSND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_HIGHGUARDDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_HIGHGUARDDIESND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_OVERP1SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_OVERP2SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_OVERPFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ATKPISTOLSND, MUSE_ACTORFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_OVERPNETSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_ACTORTHROWSND, }, 0,SD_PRIOASNEAK, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_OVERPOUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_ACTOROUCHSND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_OVERPDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_STRIKE1SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_STRIKE1SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_STRIKE2SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_STRIKE1SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_STRIKEFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ATKPISTOLSND, MUSE_ACTORFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_STRIKEROLLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_STRIKEROLLSND, MUSE_ACTORROLLSND, }, 0,SD_PRIOASNEAK, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_STRIKEOUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_STRIKEOUCHSND, MUSE_ACTOROUCHSND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_STRIKEDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_STRIKEDIESND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLITZ1SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BLITZ1SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLITZ2SEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BLITZ1SEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLITZFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ATKPISTOLSND, MUSE_ACTORFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLITZSTEALSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BLITZSTEALSND, MUSE_GETPOWERDOWNSND, }, 0,SD_PRIOASNEAK, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLITZOUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BLITZOUCHSND, MUSE_ACTOROUCHSND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLITZDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BLITZDIESND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLITZPLEADSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BLITZPLEADSND, MUSE_LASTSOUND, }, SD_PLAYONCE,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLITZPLEAD1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BLITZPLEAD1SND, MUSE_LASTSOUND, }, SD_PLAYONCE,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLITZPLEAD2SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BLITZPLEAD2SND, MUSE_LASTSOUND, }, SD_PLAYONCE,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ENFORCERSEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ENFORCERSEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ENFORCERFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ENFORCERFIRESND, MUSE_ACTORFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ENFORCERTHROWSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ENFORCERTHROWSND, MUSE_ACTORTHROWSND, }, 0,SD_PRIOASNEAK, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ENFORCEROUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ENFORCEROUCHSND, MUSE_ACTOROUCHSND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ENFORCERDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ENFORCERDIESND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_MONKSEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_MONKGRABSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_ACTORDOITSND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_MONKOUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_ACTOROUCHSND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_MONKDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIREMONKSEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIREMONKFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_ACTORFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIREMONKOUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_ACTOROUCHSND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIREMONKDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ROBOTSEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ROBOTSEESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ROBOTFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ROBOTFIRESND, MUSE_ACTORFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ROBOTDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ROBOTDIESND, MUSE_ACTORDIESND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ROBOTMOVESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_KRISTMOTORSND, MUSE_LASTSOUND, }, SD_PLAYONCE,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BALLISTIKRAFTSEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BAZOOKAFIRESND, MUSE_ACTORSEESND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BALLISTIKRAFTFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ROBOTFIRESND, MUSE_ACTORFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARIANSEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSSEESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARIANFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BAZOOKAFIRESND, MUSE_BOSSFIRESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARIANGONNAUSESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSDOSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARIANUSESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_TOUCHPLATESND, MUSE_BOSSDOSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARIANHIDESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSDOSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARIANDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSDIESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARIANSAY1,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSWARNSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARIANSAY2,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSHEYSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARIANSAY3,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSWARNSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTSEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSSEESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BAZOOKAFIRESND, MUSE_BOSSFIRESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTMOTORSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_LASTSOUND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTTURNSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSBEEPSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTDROPSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSDOSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTMINEBEEPSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSBEEPSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTMINEHITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_MISSILEHITSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSDIESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTSAY1,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSWARNSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTSAY2,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSHEYSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_KRISTSAY3,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSWARNSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NMESEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSSEESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NMEREADYSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSWARNSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NMEFIRE1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BAZOOKAFIRESND, MUSE_BOSSFIRESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NMEAPARTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSBEEPSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NMEUFOSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_MISSILEFIRESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_NMEDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_EXPLODESND, MUSE_BOSSDIESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKSEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSSEESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKFIRE1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSFIRESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKFIRE2SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSFIRE2SND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKFIRE3SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSFIRESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKFIRE4SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSFIRE2SND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKRECHARGESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_WEAPONBUILDSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKFLOATSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_LASTSOUND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSDIESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKSAY1,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSWARNSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKSAY2,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSHEYSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DARKMONKSAY3,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSWARNSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNAKESEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSSEESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNAKEREADYSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSBEEPSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNAKECHARGESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_WEAPONBUILDSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNAKEOUCHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSOUCHSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNAKEDIESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSDIESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNAKESPITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSFIRESND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNAKESAY1,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSWARNSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNAKESAY2,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSHEYSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SNAKESAY3,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOSSWARNSND, }, 0,SD_PRIOBOSS, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_EMPLACEMENTSEESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_SWITCHSND, }, 0,SD_PRIOAGREET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_EMPLACEMENTFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_EMPFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BIGEMPLACEFIRESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_EMPFIRESND, }, 0,SD_PRIOAFIRE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_OPENDOORSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_OPENDOORSND, MUSE_OPENDOORSND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_CLOSEDOORSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_CLOSEDOORSND, MUSE_CLOSEDOORSND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOORHITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ELEVATORENDSND, MUSE_LASTSOUND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIRECHUTESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FIRECHUTESND, MUSE_MISSILEFIRESND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIREBALLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FIREBALLSND, MUSE_LASTSOUND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIREBALLHITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FIREBALLHITSND, MUSE_MISSILEHITSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BLADESPINSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BLADESPINSND, MUSE_SPINBLADESND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PUSHWALLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PUSHWALLSND, MUSE_PUSHWALLSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PUSHWALLHITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PUSHWALLHITSND, MUSE_MISSILEHITSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GOWALLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GOWALLSND, MUSE_PUSHWALLSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_TURBOWALLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_TURBOWALLSND, MUSE_PUSHWALLSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BOULDERHITSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_MISSILEHITSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BOULDERROLLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_BOULDERSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BOULDERFALLSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_PITTRAPSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_PITTRAPSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_PITTRAPSND, MUSE_PITTRAPSND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_FIREJETSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_FIREJETSND, MUSE_FIREJETSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ACTORSQUISHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ACTORSQUISHSND, MUSE_ACTORSQUISHSND, }, 0,SD_PRIOADEATH, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ACTORBURNEDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ACTORBURNEDSND, MUSE_ACTOROUCHSND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ACTORSKELETONSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ACTORSKELETONSND, MUSE_LASTSOUND, }, 0,SD_PRIOAHURT, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SPEARSTABSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SPEARSTABSND, MUSE_STABBERSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_CYLINDERMOVESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_CYLINDERMOVESND, MUSE_CYLINDERHITSND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ELEVATORONSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ELEVATORONSND, MUSE_ELEVATORSND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ELEVATORENDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ELEVATORENDSND, MUSE_LASTSOUND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SPRINGBOARDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_SPRINGBOARDSND, MUSE_SPRINGBOARDSND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LIGHTNINGSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LIGHTNINGSND, MUSE_LASTSOUND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_WINDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_LASTSOUND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_WATERSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_LASTSOUND, }, 0,SD_PRIOPCAUSD, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_BODYLANDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_BODYLANDSND, MUSE_LASTSOUND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_GIBSPLASHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_GIBSPLASHSND, MUSE_LASTSOUND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_ACTORLANDSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_ACTORLANDSND, MUSE_LASTSOUND, }, 0,SD_PRIOENVRON, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_DOPEFISHSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_LASTSOUND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_YOUSUCKSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_YOUSUCKSND, MUSE_LASTSOUND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SILLYMOVESND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_LASTSOUND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SOUNDSELECTSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_LASTSOUND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_SOUNDESCSND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_YOUSUCKSND, MUSE_LASTSOUND, }, 0,SD_PRIOSECRET, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM1SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM1SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM2SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM2SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM3SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM3SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM4SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM4SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM5SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM5SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM6SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM6SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM7SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM7SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM8SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM8SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM9SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM9SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_REMOTEM10SND,
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_REMOTEM10SND, MUSE_LASTSOUND, }, 0,SD_PRIOREMOTE, 0, 0, 0},
+//�����������������������������������������������������������
+//SD_LASTSOUND
+//|-------DIGITAL--------|--------MUSE----------|----FLAGS---|
+ {{D_LASTSOUND, MUSE_LASTSOUND, }, 0,SD_PRIOSECRET, 0, 0, 0}
+//�����������������������������������������������������������
+};
--- /dev/null
+++ b/rott/sndcards.h
@@ -1,0 +1,60 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: SNDCARDS.H
+
+ author: James R. Dose
+ phone: (214)-271-1365 Ext #221
+ date: March 31, 1994
+
+ Contains enumerated type definitions for sound cards.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __SNDCARDS_H
+#define __SNDCARDS_H
+
+#define ASS_VERSION_STRING "1.04"
+
+typedef enum
+{
+// ASS_NoSound,
+ SoundBlaster,
+#ifdef DOS
+ ProAudioSpectrum,
+ SoundMan16,
+ Adlib,
+ GenMidi,
+ SoundCanvas,
+ Awe32,
+ WaveBlaster,
+#endif
+ SoundScape,
+ UltraSound,
+#ifdef DOS
+ SoundSource,
+ TandySoundSource,
+ PC,
+#endif
+ NumSoundCards
+} soundcardnames;
+
+#endif
--- /dev/null
+++ b/rott/splib.h
@@ -1,0 +1,213 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef SPLIB_H
+#define SPLIB_H
+
+/* ======================================================================= *
+ * Please Read "SpReadme.doc" for usage *
+ * ======================================================================= */
+
+/* ======================================================================= *
+ * Compiler & Memory Mode Wrappers. *
+ * ----------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+# if PLATFORM_DOS
+# define REALMODE
+# endif
+#endif
+
+#if defined(REALMODE)
+#define FAR __far
+#else
+#define FAR
+#endif
+
+//---------------------------------------------------------------------------
+// Constants
+
+#define TSR_SERIAL_LENGTH 14
+#define TSR_MAX_LENGTH 80
+
+//---------------------------------------------------------------------------
+
+typedef struct {
+ char copyright[TSR_MAX_LENGTH]; // driver copyright
+ short major; // driver version number
+ short minor;
+ short count; // # of available devices
+} SpwDrvOpenPacket;
+
+
+
+typedef struct {
+ char copyright[TSR_MAX_LENGTH]; // device copyright
+ char serial[TSR_SERIAL_LENGTH]; // device serial number
+} SpwDevOpenPacket;
+
+
+
+typedef struct {
+ long timestamp; // time of event
+ unsigned short period; // period since last MOVEMENT
+ unsigned short button; // button pressed mask
+ short tx; // Translation X
+ short ty; // Y
+ short tz; // Z
+ short rx; // Rotation X
+ short ry; // Y
+ short rz; // Z
+} SpwForcePacket;
+
+
+
+typedef struct {
+ long timestamp; // time of event
+ unsigned short period; // period since last BUTTON
+ unsigned short button; // button pressed mask
+} SpwButtonPacket;
+
+
+
+typedef struct {
+ unsigned long data; // MUST be TSRCMD_DATA
+} SpwCommandPacket;
+
+#define TSRCMD_DATA 0xFF0000FF
+
+//---------------------------------------------------------------------------
+
+typedef union {
+ char padding[128]; /* Extra room for future expansion */
+
+ SpwCommandPacket command;
+
+ SpwDrvOpenPacket drvOpen;
+ SpwDevOpenPacket devOpen;
+
+ SpwForcePacket force;
+ SpwButtonPacket button;
+} SpwPacket;
+
+
+
+// TSR Interrupt Functions
+#define TSR_DRIVER_CLOSE 0x0000
+#define TSR_DRIVER_OPEN 0x8001
+#define TSR_DEVICE_CLOSE 0x0002
+#define TSR_DEVICE_OPEN 0x8003
+
+#define TSR_DEVICE_DISABLE 0x0010
+#define TSR_DEVICE_ENABLE 0x0011
+
+#define TSR_DEVICE_GETFORCE 0x8020
+#define TSR_DEVICE_GETBUTTONS 0x8021
+
+/* ======================================================================= *
+ * Function Prototypes *
+ * ======================================================================= */
+
+short SpwOpenDriver(SpwPacket FAR *packet);
+short SpwCloseDriver(void);
+
+short SpwOpenDevice(short device, SpwPacket FAR *packet);
+short SpwCloseDevice(short device);
+
+short SpwEnableDevice(short device);
+short SpwDisableDevice(short device);
+
+short SpwGetForce(short device, SpwPacket FAR *packet);
+short SpwGetButton(short device, SpwPacket FAR *packet);
+
+/* ======================================================================= *
+ * Convience functions *
+ * ======================================================================= */
+
+/* ----------------------------------------------------------------------- *
+ * The SpwSimple... functions are just convienence wrappers for the above *
+ * functions. *
+ * ----------------------------------------------------------------------- */
+
+#ifndef SPWSTRUCTS
+#define SPWSTRUCTS
+
+enum SpwDeviceType {
+ SPW_AVENGER=1,
+};
+
+
+
+enum SpwEventType {
+ SPW_NO_EVENT=0,
+ SPW_BUTTON_HELD=1,
+ SPW_BUTTON_DOWN=2,
+ SPW_BUTTON_UP=4,
+ SPW_MOTION=8
+};
+
+
+
+/* ----------------------------------------------------------------------- *
+ * Data struct for handling library calls *
+ * ----------------------------------------------------------------------- */
+
+typedef struct {
+ short new;
+ short cur;
+ short old;
+} SpwButtonRec;
+
+
+
+typedef struct {
+ short tx; /* Current Translation vector */
+ short ty;
+ short tz;
+ short rx; /* Current Rotation vector */
+ short ry;
+ short rz;
+ SpwButtonRec buttons; /* Current Button Record */
+ short newData; /* An SpEventType mask of newData, 0 if none */
+} SpwRawData;
+
+#endif
+
+
+
+short SpwSimpleGet(short devNum, SpwRawData FAR *splayer);
+short SpwSimpleOpen(short devNum);
+short SpwSimpleClose(short devNum);
+
+/* ======================================================================= *
+ * Compiler & Memory Mode Wrappers. *
+ * ======================================================================= *
+ */
+
+#ifdef __cplusplus
+};
+#endif
+
+/* ======================================================================= */
+#endif
+
--- /dev/null
+++ b/rott/sprites.h
@@ -1,0 +1,1611 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _sprites_public
+#define _sprites_public
+
+#include "develop.h"
+
+typedef enum {ACTOR_START_LABEL,
+
+
+ /*************** UNTERWACHE *************************************/
+
+
+ SPR_LOWGRD_SHOOT1,SPR_LOWGRD_SHOOT2,SPR_LOWGRD_SHOOT3,SPR_LOWGRD_SHOOT4,
+
+ SPR_LOWGRD_S1,SPR_LOWGRD_S2,SPR_LOWGRD_S3,SPR_LOWGRD_S4,
+ SPR_LOWGRD_S5,SPR_LOWGRD_S6,SPR_LOWGRD_S7,SPR_LOWGRD_S8,
+
+ SPR_LOWGRD_W11,SPR_LOWGRD_W12,SPR_LOWGRD_W13,SPR_LOWGRD_W14,
+ SPR_LOWGRD_W15,SPR_LOWGRD_W16,SPR_LOWGRD_W17,SPR_LOWGRD_W18,
+
+ SPR_LOWGRD_W21,SPR_LOWGRD_W22,SPR_LOWGRD_W23,SPR_LOWGRD_W24,
+ SPR_LOWGRD_W25,SPR_LOWGRD_W26,SPR_LOWGRD_W27,SPR_LOWGRD_W28,
+
+ SPR_LOWGRD_W31,SPR_LOWGRD_W32,SPR_LOWGRD_W33,SPR_LOWGRD_W34,
+ SPR_LOWGRD_W35,SPR_LOWGRD_W36,SPR_LOWGRD_W37,SPR_LOWGRD_W38,
+
+ SPR_LOWGRD_W41,SPR_LOWGRD_W42,SPR_LOWGRD_W43,SPR_LOWGRD_W44,
+ SPR_LOWGRD_W45,SPR_LOWGRD_W46,SPR_LOWGRD_W47,SPR_LOWGRD_W48,
+
+
+ SPR_LOWGRD_PAIN1, SPR_LOWGRD_PAIN2, SPR_LOWGRD_DIE1, SPR_LOWGRD_DIE2,
+ SPR_LOWGRD_DIE3, SPR_LOWGRD_DIE4, SPR_LOWGRD_DEAD,
+
+ SPR_LOWGRD_WPAIN1, SPR_LOWGRD_WPAIN2, SPR_LOWGRD_WDIE1, SPR_LOWGRD_WDIE2,
+ SPR_LOWGRD_WDIE3, SPR_LOWGRD_WDIE4, SPR_LOWGRD_WDEAD,
+
+
+ SPR_SNEAKY_DEAD, SPR_RISE1, SPR_RISE2, SPR_RISE3, SPR_RISE4,
+
+ /*
+ SPR_LOWGRD_USE11,SPR_LOWGRD_USE12,SPR_LOWGRD_USE13,SPR_LOWGRD_USE14,
+ SPR_LOWGRD_USE15,SPR_LOWGRD_USE16,SPR_LOWGRD_USE17,SPR_LOWGRD_USE18,
+
+ SPR_LOWGRD_USE21,SPR_LOWGRD_USE22,SPR_LOWGRD_USE23,SPR_LOWGRD_USE24,
+ SPR_LOWGRD_USE25,SPR_LOWGRD_USE26,SPR_LOWGRD_USE27,SPR_LOWGRD_USE28,
+ */
+
+
+ /***************** Highguard 1 (Steve B.) ***************************************/
+
+
+
+
+ SPR_HIGHGRD_SHOOT1,SPR_HIGHGRD_SHOOT2,SPR_HIGHGRD_SHOOT3,SPR_HIGHGRD_SHOOT4,
+
+ SPR_HIGHGRD_S1,SPR_HIGHGRD_S2,SPR_HIGHGRD_S3,SPR_HIGHGRD_S4,
+ SPR_HIGHGRD_S5,SPR_HIGHGRD_S6,SPR_HIGHGRD_S7,SPR_HIGHGRD_S8,
+
+ SPR_HIGHGRD_W11,SPR_HIGHGRD_W12,SPR_HIGHGRD_W13,SPR_HIGHGRD_W14,
+ SPR_HIGHGRD_W15,SPR_HIGHGRD_W16,SPR_HIGHGRD_W17,SPR_HIGHGRD_W18,
+
+ SPR_HIGHGRD_W21,SPR_HIGHGRD_W22,SPR_HIGHGRD_W23,SPR_HIGHGRD_W24,
+ SPR_HIGHGRD_W25,SPR_HIGHGRD_W26,SPR_HIGHGRD_W27,SPR_HIGHGRD_W28,
+
+ SPR_HIGHGRD_W31,SPR_HIGHGRD_W32,SPR_HIGHGRD_W33,SPR_HIGHGRD_W34,
+ SPR_HIGHGRD_W35,SPR_HIGHGRD_W36,SPR_HIGHGRD_W37,SPR_HIGHGRD_W38,
+
+ SPR_HIGHGRD_W41,SPR_HIGHGRD_W42,SPR_HIGHGRD_W43,SPR_HIGHGRD_W44,
+ SPR_HIGHGRD_W45,SPR_HIGHGRD_W46,SPR_HIGHGRD_W47,SPR_HIGHGRD_W48,
+
+
+ SPR_HIGHGRD_PAIN1,SPR_HIGHGRD_PAIN2,
+ SPR_HIGHGRD_DIE1,SPR_HIGHGRD_DIE2,SPR_HIGHGRD_DIE3,SPR_HIGHGRD_DIE4,
+ SPR_HIGHGRD_DIE5,SPR_HIGHGRD_DEAD,
+
+ SPR_HIGHGRD_WPAIN1,SPR_HIGHGRD_WPAIN2,
+ SPR_HIGHGRD_WDIE1,SPR_HIGHGRD_WDIE2,SPR_HIGHGRD_WDIE3,SPR_HIGHGRD_WDIE4,
+ SPR_HIGHGRD_WDIE5,SPR_HIGHGRD_WDEAD,
+
+ /*
+ SPR_HIGHGRD_USE11,SPR_HIGHGRD_USE12,SPR_HIGHGRD_USE13,SPR_HIGHGRD_USE14,
+ SPR_HIGHGRD_USE15,SPR_HIGHGRD_USE16,SPR_HIGHGRD_USE17,SPR_HIGHGRD_USE18,
+
+ SPR_HIGHGRD_USE21,SPR_HIGHGRD_USE22,SPR_HIGHGRD_USE23,SPR_HIGHGRD_USE24,
+ SPR_HIGHGRD_USE25,SPR_HIGHGRD_USE26,SPR_HIGHGRD_USE27,SPR_HIGHGRD_USE28,
+ */
+
+
+
+
+ /******************** ANGRIFFSTUPPE **********************************/
+
+
+ SPR_STRIKE_SHOOT1,SPR_STRIKE_SHOOT2,SPR_STRIKE_SHOOT3,SPR_STRIKE_SHOOT4,
+ SPR_STRIKE_KSHOOT1,SPR_STRIKE_KSHOOT2,SPR_STRIKE_KSHOOT3,
+
+
+ SPR_STRIKE_S1,SPR_STRIKE_S2,SPR_STRIKE_S3,SPR_STRIKE_S4,
+ SPR_STRIKE_S5,SPR_STRIKE_S6,SPR_STRIKE_S7,SPR_STRIKE_S8,
+
+ SPR_STRIKE_W11,SPR_STRIKE_W12,SPR_STRIKE_W13,SPR_STRIKE_W14,
+ SPR_STRIKE_W15,SPR_STRIKE_W16,SPR_STRIKE_W17,SPR_STRIKE_W18,
+
+ SPR_STRIKE_W21,SPR_STRIKE_W22,SPR_STRIKE_W23,SPR_STRIKE_W24,
+ SPR_STRIKE_W25,SPR_STRIKE_W26,SPR_STRIKE_W27,SPR_STRIKE_W28,
+
+ SPR_STRIKE_W31,SPR_STRIKE_W32,SPR_STRIKE_W33,SPR_STRIKE_W34,
+ SPR_STRIKE_W35,SPR_STRIKE_W36,SPR_STRIKE_W37,SPR_STRIKE_W38,
+
+ SPR_STRIKE_W41,SPR_STRIKE_W42,SPR_STRIKE_W43,SPR_STRIKE_W44,
+ SPR_STRIKE_W45,SPR_STRIKE_W46,SPR_STRIKE_W47,SPR_STRIKE_W48,
+
+
+ SPR_STRIKE_PAIN1,SPR_STRIKE_PAIN2,
+ SPR_STRIKE_DIE1,SPR_STRIKE_DIE2,SPR_STRIKE_DIE3,
+ SPR_STRIKE_DIE4,SPR_STRIKE_DEAD1,SPR_STRIKE_DEAD2,SPR_STRIKE_DEAD3,
+
+ SPR_STRIKE_WPAIN1,SPR_STRIKE_WPAIN2,
+ SPR_STRIKE_WDIE1,SPR_STRIKE_WDIE2,SPR_STRIKE_WDIE3,
+ SPR_STRIKE_WDIE4,SPR_STRIKE_WDEAD1,SPR_STRIKE_WDEAD2,SPR_STRIKE_WDEAD3,
+
+ SPR_STRIKE_RROLL1,SPR_STRIKE_RROLL2,SPR_STRIKE_RROLL3,SPR_STRIKE_RROLL4,
+ SPR_STRIKE_RROLL5,SPR_STRIKE_RROLL6,
+
+ SPR_STRIKE_LROLL1,SPR_STRIKE_LROLL2,SPR_STRIKE_LROLL3,SPR_STRIKE_LROLL4,
+ SPR_STRIKE_LROLL5,SPR_STRIKE_LROLL6,
+
+
+
+
+ /********************** BLITZWACHE **********************************/
+
+
+ SPR_BLITZ_SHOOT1,SPR_BLITZ_SHOOT2,SPR_BLITZ_SHOOT3,SPR_BLITZ_SHOOT4,
+
+ SPR_BLITZ_S1,SPR_BLITZ_S2,SPR_BLITZ_S3,SPR_BLITZ_S4,
+ SPR_BLITZ_S5,SPR_BLITZ_S6,SPR_BLITZ_S7,SPR_BLITZ_S8,
+
+ SPR_BLITZ_W11,SPR_BLITZ_W12,SPR_BLITZ_W13,SPR_BLITZ_W14,
+ SPR_BLITZ_W15,SPR_BLITZ_W16,SPR_BLITZ_W17,SPR_BLITZ_W18,
+
+ SPR_BLITZ_W21,SPR_BLITZ_W22,SPR_BLITZ_W23,SPR_BLITZ_W24,
+ SPR_BLITZ_W25,SPR_BLITZ_W26,SPR_BLITZ_W27,SPR_BLITZ_W28,
+
+ SPR_BLITZ_W31,SPR_BLITZ_W32,SPR_BLITZ_W33,SPR_BLITZ_W34,
+ SPR_BLITZ_W35,SPR_BLITZ_W36,SPR_BLITZ_W37,SPR_BLITZ_W38,
+
+ SPR_BLITZ_W41,SPR_BLITZ_W42,SPR_BLITZ_W43,SPR_BLITZ_W44,
+ SPR_BLITZ_W45,SPR_BLITZ_W46,SPR_BLITZ_W47,SPR_BLITZ_W48,
+
+
+ SPR_BLITZ_PAIN1, SPR_BLITZ_PAIN2,SPR_BLITZ_DIE1,SPR_BLITZ_DIE2,
+ SPR_BLITZ_DIE3,SPR_BLITZ_DIE4,SPR_BLITZ_DEAD1, SPR_BLITZ_DEAD2,
+
+ SPR_BLITZ_WPAIN1, SPR_BLITZ_WPAIN2,SPR_BLITZ_WDIE1,SPR_BLITZ_WDIE2,
+ SPR_BLITZ_WDIE3,SPR_BLITZ_WDIE4,SPR_BLITZ_WDEAD1, SPR_BLITZ_WDEAD2,
+
+ SPR_BLITZ_RISE1, SPR_BLITZ_RISE2, SPR_BLITZ_RISE3, SPR_BLITZ_RISE4,
+
+ SPR_BLITZ_USE11,SPR_BLITZ_USE12,SPR_BLITZ_USE13,SPR_BLITZ_USE14,
+ SPR_BLITZ_USE15,SPR_BLITZ_USE16,SPR_BLITZ_USE17,SPR_BLITZ_USE18,
+
+ SPR_BLITZ_USE21,SPR_BLITZ_USE22,SPR_BLITZ_USE23,SPR_BLITZ_USE24,
+ SPR_BLITZ_USE25,SPR_BLITZ_USE26,SPR_BLITZ_USE27,SPR_BLITZ_USE28,
+
+ SPR_BLITZ_PLEAD1,SPR_BLITZ_PLEAD2,SPR_BLITZ_PLEAD3,SPR_BLITZ_PLEAD4,
+ SPR_BLITZ_PLEAD5,SPR_BLITZ_PLEAD6,SPR_BLITZ_PLEAD7,SPR_BLITZ_PLEAD8,
+ SPR_BLITZ_PLEAD9,SPR_BLITZ_PLEAD10,SPR_BLITZ_PLEAD11,
+
+
+
+
+ /******************** DREIHEITWACHE ***********************************/
+
+
+ SPR_ENFORCER_SHOOT1,SPR_ENFORCER_SHOOT2,SPR_ENFORCER_SHOOT3,
+ SPR_ENFORCER_SHOOT4,
+
+ SPR_ENFORCER_S1,SPR_ENFORCER_S2,SPR_ENFORCER_S3,SPR_ENFORCER_S4,
+ SPR_ENFORCER_S5,SPR_ENFORCER_S6,SPR_ENFORCER_S7,SPR_ENFORCER_S8,
+
+ SPR_ENFORCER_W11,SPR_ENFORCER_W12,SPR_ENFORCER_W13,SPR_ENFORCER_W14,
+ SPR_ENFORCER_W15,SPR_ENFORCER_W16,SPR_ENFORCER_W17,SPR_ENFORCER_W18,
+
+ SPR_ENFORCER_W21,SPR_ENFORCER_W22,SPR_ENFORCER_W23,SPR_ENFORCER_W24,
+ SPR_ENFORCER_W25,SPR_ENFORCER_W26,SPR_ENFORCER_W27,SPR_ENFORCER_W28,
+
+ SPR_ENFORCER_W31,SPR_ENFORCER_W32,SPR_ENFORCER_W33,SPR_ENFORCER_W34,
+ SPR_ENFORCER_W35,SPR_ENFORCER_W36,SPR_ENFORCER_W37,SPR_ENFORCER_W38,
+
+ SPR_ENFORCER_W41,SPR_ENFORCER_W42,SPR_ENFORCER_W43,SPR_ENFORCER_W44,
+ SPR_ENFORCER_W45,SPR_ENFORCER_W46,SPR_ENFORCER_W47,SPR_ENFORCER_W48,
+
+
+ SPR_ENFORCER_THROW1,SPR_ENFORCER_THROW2,SPR_ENFORCER_THROW3,SPR_ENFORCER_THROW4,
+ SPR_ENFORCER_THROW5,SPR_ENFORCER_THROW6,SPR_ENFORCER_THROW7,SPR_ENFORCER_THROW8,
+
+ SPR_ENFORCER_PAIN1,SPR_ENFORCER_PAIN2,
+ SPR_ENFORCER_DIE1,SPR_ENFORCER_DIE2,SPR_ENFORCER_DIE3,SPR_ENFORCER_DIE4,
+ SPR_ENFORCER_DEAD,
+
+ SPR_ENFORCER_WPAIN1,SPR_ENFORCER_WPAIN2,
+ SPR_ENFORCER_WDIE1,SPR_ENFORCER_WDIE2,SPR_ENFORCER_WDIE3,SPR_ENFORCER_WDIE4,
+ SPR_ENFORCER_WDEAD,
+
+ /*
+ SPR_ENFORCER_USE11,SPR_ENFORCER_USE12,SPR_ENFORCER_USE13,SPR_ENFORCER_USE14,
+ SPR_ENFORCER_USE15,SPR_ENFORCER_USE16,SPR_ENFORCER_USE17,SPR_ENFORCER_USE18,
+
+ SPR_ENFORCER_USE21,SPR_ENFORCER_USE22,SPR_ENFORCER_USE23,SPR_ENFORCER_USE24,
+ SPR_ENFORCER_USE25,SPR_ENFORCER_USE26,SPR_ENFORCER_USE27,SPR_ENFORCER_USE28,
+ */
+
+
+ /************************* ROBOT GUARD *********************************/
+
+
+ SPR_ROBOGRD_S11,SPR_ROBOGRD_S12,SPR_ROBOGRD_S13,SPR_ROBOGRD_S14,
+ SPR_ROBOGRD_S15,SPR_ROBOGRD_S16,SPR_ROBOGRD_S17,SPR_ROBOGRD_S18,
+
+ SPR_ROBOGRD_S21,SPR_ROBOGRD_S22,SPR_ROBOGRD_S23,SPR_ROBOGRD_S24,
+ SPR_ROBOGRD_S25,SPR_ROBOGRD_S26,SPR_ROBOGRD_S27,SPR_ROBOGRD_S28,
+
+ ROBOGRDDIE1,ROBOGRDDIE2,ROBOGRDDIE3,ROBOGRDDIE4,
+ ROBOGRDDIE5,ROBOGRDDIE6,ROBOGRDDIE7,ROBOGRDDIE8,
+ ROBOGRDDIE9,ROBOGRDDEAD,
+
+
+
+ /************************* EXPLOSIONS *******************************/
+
+ SPR_EXPLOSION1,SPR_EXPLOSION2,SPR_EXPLOSION3,SPR_EXPLOSION4,
+ SPR_EXPLOSION5,SPR_EXPLOSION6,SPR_EXPLOSION7,SPR_EXPLOSION8,
+ SPR_EXPLOSION9,SPR_EXPLOSION10,SPR_EXPLOSION11,SPR_EXPLOSION12,
+ SPR_EXPLOSION13,SPR_EXPLOSION14,SPR_EXPLOSION15,SPR_EXPLOSION16,
+ SPR_EXPLOSION17,SPR_EXPLOSION18,SPR_EXPLOSION19,SPR_EXPLOSION20,
+
+
+
+ SPR_STATICEXPL1,SPR_STATICEXPL2,SPR_STATICEXPL3,SPR_STATICEXPL4,
+ SPR_STATICEXPL5,SPR_STATICEXPL6,SPR_STATICEXPL7,SPR_STATICEXPL8,
+ SPR_STATICEXPL9,SPR_STATICEXPL10,SPR_STATICEXPL11,SPR_STATICEXPL12,
+ SPR_STATICEXPL13,SPR_STATICEXPL14,SPR_STATICEXPL15,SPR_STATICEXPL16,
+ SPR_STATICEXPL17,SPR_STATICEXPL18,SPR_STATICEXPL19,SPR_STATICEXPL20,
+ SPR_STATICEXPL21,SPR_STATICEXPL22,SPR_STATICEXPL23,SPR_STATICEXPL24,
+ SPR_STATICEXPL25,
+
+ SPR_GROUNDEXPL1,SPR_GROUNDEXPL2,SPR_GROUNDEXPL3,SPR_GROUNDEXPL4,
+ SPR_GROUNDEXPL5,SPR_GROUNDEXPL6,SPR_GROUNDEXPL7,SPR_GROUNDEXPL8,
+ SPR_GROUNDEXPL9,SPR_GROUNDEXPL10,SPR_GROUNDEXPL11,SPR_GROUNDEXPL12,
+ SPR_GROUNDEXPL13,SPR_GROUNDEXPL14,SPR_GROUNDEXPL15,SPR_GROUNDEXPL16,
+ SPR_GROUNDEXPL17,SPR_GROUNDEXPL18,SPR_GROUNDEXPL19,SPR_GROUNDEXPL20,
+
+
+ /************************* HAZARDS *******************************/
+
+
+
+ UBLADE1,UBLADE2,UBLADE3,UBLADE4,
+ UBLADE5,UBLADE6,UBLADE7,UBLADE8,
+ UBLADE9,//UBLADE10,UBLADE11,UBLADE12,
+//UBLADE13,UBLADE14,UBLADE15,UBLADE16,
+
+
+
+
+ FIREJETUP1,FIREJETUP2,FIREJETUP3,FIREJETUP4,
+ FIREJETUP5,FIREJETUP6,FIREJETUP7,FIREJETUP8,
+ FIREJETUP9,FIREJETUP10,FIREJETUP11,FIREJETUP12,
+ FIREJETUP13,FIREJETUP14,FIREJETUP15,FIREJETUP16,
+ FIREJETUP17,FIREJETUP18,FIREJETUP19,FIREJETUP20,
+ FIREJETUP21,FIREJETUP22,FIREJETUP23,
+
+
+
+ CRUSHDOWN1,CRUSHDOWN2,CRUSHDOWN3,CRUSHDOWN4,
+ CRUSHDOWN5,CRUSHDOWN6,CRUSHDOWN7,CRUSHDOWN8,
+//CRUSHDOWN9,CRUSHDOWN10,CRUSHDOWN11,CRUSHDOWN12,
+//CRUSHDOWN13,CRUSHDOWN14,CRUSHDOWN15,CRUSHDOWN16,
+
+
+
+ SPEARUP1,SPEARUP2,SPEARUP3,SPEARUP4,
+ SPEARUP5,SPEARUP6,SPEARUP7,SPEARUP8,
+ SPEARUP9,SPEARUP10,SPEARUP11,SPEARUP12,
+ SPEARUP13,SPEARUP14,SPEARUP15,SPEARUP16,
+
+
+
+
+
+ SPRING1,SPRING2,SPRING3,SPRING4,
+ SPRING5,SPRING6,SPRING7,SPRING8,
+ SPRING9,SPRING10,
+
+
+
+
+ FIREW1,FIREW2,FIREW3,FIREW4,FIREW5,FIREW6,FIREW7,FIREW8,
+ FIREW9,FIREW10,FIREW11,FIREW12,FIREW13,FIREW14,FIREW15,
+
+
+
+
+ GUTS1,GUTS2,GUTS3,GUTS4,
+ GUTS5,GUTS6,GUTS7,GUTS8,
+ GUTS9,GUTS10,GUTS11,GUTS12,
+
+
+ PARTICLE01,PARTICLE02,PARTICLE03,PARTICLE04,
+ PARTICLE05,PARTICLE06,PARTICLE07,PARTICLE08,
+ PARTICLE09,PARTICLE10,PARTICLE11,PARTICLE12,
+
+ ORGAN01,ORGAN02,ORGAN03,ORGAN04,
+ ORGAN05,ORGAN06,ORGAN07,ORGAN08,
+ ORGAN09,ORGAN10,ORGAN11,ORGAN12,
+
+ RIB01,RIB02,RIB03,RIB04,
+ RIB05,RIB06,RIB07,RIB08,
+ RIB09,RIB10,RIB11,RIB12,
+
+ PINK01, PINK02, PINK03, PINK04,
+ PINK05, PINK06, PINK07, PINK08,
+ PINK09, PINK10, PINK11, PINK12,
+
+ GIBHEAD01,GIBHEAD02,GIBHEAD03,GIBHEAD04,
+ GIBHEAD05,GIBHEAD06,GIBHEAD07,GIBHEAD08,
+ GIBHEAD09,GIBHEAD10,GIBHEAD11,GIBHEAD12,
+
+ GARM01,GARM02,GARM03,GARM04,
+ GARM05,GARM06,GARM07,GARM08,
+ GARM09,GARM10,GARM11,GARM12,
+
+ GLEG01,GLEG02,GLEG03,GLEG04,
+ GLEG05,GLEG06,GLEG07,GLEG08,
+ GLEG09,GLEG10,GLEG11,GLEG12,
+
+ HUMERUS01, HUMERUS02, HUMERUS03, HUMERUS04,
+ HUMERUS05, HUMERUS06, HUMERUS07, HUMERUS08,
+ HUMERUS09, HUMERUS10, HUMERUS11, HUMERUS12,
+
+ PELVIS01, PELVIS02, PELVIS03, PELVIS04,
+ PELVIS05, PELVIS06, PELVIS07, PELVIS08,
+ PELVIS09, PELVIS10, PELVIS11, PELVIS12,
+
+ LIMB01, LIMB02, LIMB03, LIMB04,
+ LIMB05, LIMB06, LIMB07, LIMB08,
+ LIMB09, LIMB10, LIMB11, LIMB12,
+
+
+ DEADHEAD,
+
+ WALLGIB1,WALLGIB2,WALLGIB3,WALLGIB4,
+
+ GIBEYE1,GIBEYE2,GIBEYE3,
+
+ VAPORIZED1,VAPORIZED2,VAPORIZED3,VAPORIZED4,
+ VAPORIZED5,VAPORIZED6,VAPORIZED7,VAPORIZED8,
+
+ BIGSOUL,LITTLESOUL,
+ COLLECTOR1,
+ COLLECTOR3,
+ COLLECTOR5,
+ COLLECTOR7,
+ COLLECTOR9,
+ COLLECTOR11,
+ COLLECTOR13,
+ COLLECTOR15,
+
+
+ ITEMSPAWN1,ITEMSPAWN2,ITEMSPAWN3,ITEMSPAWN4,
+ ITEMSPAWN5,ITEMSPAWN6,ITEMSPAWN7,ITEMSPAWN8,
+
+ DEADBLOOD1,DEADBLOOD2,DEADBLOOD3,DEADBLOOD4,
+ DEADBLOOD5,DEADBLOOD6,DEADBLOOD7,
+
+
+ FLASH1,FLASH2,FLASH3,FLASH4,
+ FLASH5,FLASH6,FLASH7,FLASH8,
+
+
+ SKELETON1,SKELETON2,SKELETON3,SKELETON4,
+ SKELETON5,SKELETON6,SKELETON7,SKELETON8,
+
+ SKELETON9,SKELETON10,SKELETON11,SKELETON12,
+ SKELETON13,SKELETON14,SKELETON15,SKELETON16,
+
+ SKELETON17,SKELETON18,SKELETON19,SKELETON20,
+ SKELETON21,SKELETON22,SKELETON23,SKELETON24,
+
+ SKELETON25,SKELETON26,SKELETON27,SKELETON28,
+ SKELETON29,SKELETON30,SKELETON31,SKELETON32,
+
+ SKELETON33,SKELETON34,SKELETON35,SKELETON36,
+ SKELETON37,SKELETON38,SKELETON39,SKELETON40,
+
+ SKELETON41,SKELETON42,SKELETON43,SKELETON44,
+ SKELETON45,SKELETON46,SKELETON47,SKELETON48,
+
+
+ SPR_PUSHCOLUMN1,SPR_PUSHCOLUMN1a,
+ /*
+ SPR_PUSHCOLUMN2,SPR_PUSHCOLUMN2a,
+ SPR_PUSHCOLUMN3,SPR_PUSHCOLUMN3a,
+ */
+
+ BLOODSPURT1,BLOODSPURT2,BLOODSPURT3,BLOODSPURT4,
+ BLOODSPURT5,BLOODSPURT6,BLOODSPURT7,BLOODSPURT8,
+
+ GUNSMOKE1,GUNSMOKE2,GUNSMOKE3,GUNSMOKE4,
+ GUNSMOKE5,GUNSMOKE6,GUNSMOKE7,GUNSMOKE8,
+
+
+
+ HITMETALWALL1,HITMETALWALL2,HITMETALWALL3,HITMETALWALL4,
+
+ HITMETALACTOR1,HITMETALACTOR2,HITMETALACTOR3,HITMETALACTOR4,
+
+
+ PLATFORM1, PLATFORM2, PLATFORM3, PLATFORM4, PLATFORM5,
+
+
+ SPR_CROSSFIRE11, SPR_CROSSFIRE12,SPR_CROSSFIRE13, SPR_CROSSFIRE14,
+ SPR_CROSSFIRE15, SPR_CROSSFIRE16,SPR_CROSSFIRE17, SPR_CROSSFIRE18,
+
+ SPR_CROSSFIRE31, SPR_CROSSFIRE32,SPR_CROSSFIRE33, SPR_CROSSFIRE34,
+ SPR_CROSSFIRE35, SPR_CROSSFIRE36,SPR_CROSSFIRE37, SPR_CROSSFIRE38,
+
+ SPR_CREXP1,SPR_CREXP2,SPR_CREXP3,SPR_CREXP4,SPR_CREXP5,
+
+
+ GODFIRE1,GODFIRE2,GODFIRE3,GODFIRE4,
+
+
+
+ SPR_ENFORCER_GR1,SPR_ENFORCER_GR2,SPR_ENFORCER_GR3,SPR_ENFORCER_GR4,
+ SPR_ENFORCER_GR5,SPR_ENFORCER_GR6,SPR_ENFORCER_GR7,SPR_ENFORCER_GR8,
+ SPR_ENFORCER_GR9,SPR_ENFORCER_GR10,
+
+ SPR_ENFORCER_FALL1,SPR_ENFORCER_FALL2,SPR_ENFORCER_FALL3,SPR_ENFORCER_FALL4,
+ SPR_ENFORCER_FALL5,SPR_ENFORCER_FALL6,
+
+
+ SPR_MINE1,SPR_MINE2,SPR_MINE3,SPR_MINE4,
+
+ SPR_BJMISS11,SPR_BJMISS12,SPR_BJMISS13,SPR_BJMISS14,
+ SPR_BJMISS15,SPR_BJMISS16,SPR_BJMISS17,SPR_BJMISS18,
+ SPR_BJMISS19,SPR_BJMISS110,SPR_BJMISS111,SPR_BJMISS112,
+ SPR_BJMISS113,SPR_BJMISS114,SPR_BJMISS115,SPR_BJMISS116,
+
+
+ SPR_BSTAR1,SPR_BSTAR2,SPR_BSTAR3,SPR_BSTAR4,
+
+
+
+ GODPOWERUP1, GODPOWERUP2, GODPOWERUP3, GODPOWERUP4,
+ GODPOWERUP5, GODPOWERUP6, GODPOWERUP7, GODPOWERUP8,
+
+
+
+ ELASTICPOWERUP1, ELASTICPOWERUP2, ELASTICPOWERUP3, ELASTICPOWERUP4,
+ ELASTICPOWERUP5, ELASTICPOWERUP6, ELASTICPOWERUP7, ELASTICPOWERUP8,
+
+ RANDOMPOWERUP1, RANDOMPOWERUP2, RANDOMPOWERUP3, RANDOMPOWERUP4,
+ RANDOMPOWERUP5, RANDOMPOWERUP6, RANDOMPOWERUP7, RANDOMPOWERUP8,
+
+ FLEETFEETPOWERUP1, FLEETFEETPOWERUP2, FLEETFEETPOWERUP3, FLEETFEETPOWERUP4,
+ FLEETFEETPOWERUP5, FLEETFEETPOWERUP6, FLEETFEETPOWERUP7, FLEETFEETPOWERUP8,
+
+ MUSHROOMPOWERUP1, MUSHROOMPOWERUP2, MUSHROOMPOWERUP3, MUSHROOMPOWERUP4,
+ MUSHROOMPOWERUP5, MUSHROOMPOWERUP6, MUSHROOMPOWERUP7, MUSHROOMPOWERUP8,
+
+
+ ONEUP01, ONEUP02, ONEUP03, ONEUP04,
+ ONEUP05, ONEUP06, ONEUP07, ONEUP08,
+
+
+ LIFEITEMA01, LIFEITEMA02, LIFEITEMA03, LIFEITEMA04,
+ LIFEITEMA05, LIFEITEMA06, LIFEITEMA07, LIFEITEMA08,
+
+ LIFEITEMB01, LIFEITEMB02, LIFEITEMB03, LIFEITEMB04,
+ LIFEITEMB05, LIFEITEMB06, LIFEITEMB07, LIFEITEMB08,
+
+ LIFEITEMC01, LIFEITEMC02, LIFEITEMC03, LIFEITEMC04,
+ LIFEITEMC05, LIFEITEMC06, LIFEITEMC07, LIFEITEMC08,
+ LIFEITEMC09, LIFEITEMC10, LIFEITEMC11, LIFEITEMC12,
+ LIFEITEMC13, LIFEITEMC14, LIFEITEMC15,
+
+ LIFEITEMD01, LIFEITEMD02, LIFEITEMD03, LIFEITEMD04,
+ LIFEITEMD05, LIFEITEMD06, LIFEITEMD07, LIFEITEMD08,
+
+
+ RUBBLE1,RUBBLE2,RUBBLE3,RUBBLE4,RUBBLE5,RUBBLE6,RUBBLE7,
+ RUBBLE8,RUBBLE9,RUBBLE10,
+
+ WOODFRAG1,WOODFRAG2,WOODFRAG3,WOODFRAG4,WOODFRAG5,WOODFRAG6,
+ WOODFRAG7,WOODFRAG8,WOODFRAG9,WOODFRAG10,WOODFRAG11,WOODFRAG12,
+ WOODFRAG13,WOODFRAG14,
+
+
+
+ MISSMOKE1,MISSMOKE2,MISSMOKE3,MISSMOKE4,
+
+ SPR62_ETOUCH1, SPR63_ETOUCH2, SPR64_ETOUCH3,
+
+ SPR73_GKEY1, SPR74_GKEY2, SPR75_GKEY3, SPR76_GKEY4,
+ SPR77_GKEY5, SPR78_GKEY6, SPR79_GKEY7, SPR80_GKEY8,
+ SPR81_GKEY9, SPR82_GKEY10, SPR83_GKEY11, SPR84_GKEY12,
+ SPR85_GKEY13, SPR86_GKEY14, SPR87_GKEY15, SPR88_GKEY16,
+
+
+ SPR6_GIBS1, SPR7_GIBS2, SPR8_GIBS3, SPR33_CBARREL,
+ SPR34_TOUCH1, SPR35_TOUCH2, SPR36_TOUCH3, SPR37_TOUCH4,
+ SPR40_GARBAGE3,SPR41_SHIT, BLUEVASE, SPR54_HAY,
+ BULLETHOLE, ALTBULLETHO,
+ STNPOLE1, STNPOLE2, STNPOLE3, STNPOLE4,
+ STNPOLE5, STNPOLE6, STNPOLE7, STNPOLE8,
+
+
+ HGRATE1, HGRATE2, HGRATE3,
+ HGRATE4,
+
+ SPR0_YLIGHT, SPR1_RLIGHT, SPR2_GLIGHT,
+ SPR3_BLIGHT, SPR4_CHAND, SPR5_LAMPOFF, SPR5_LAMP,
+ SPR9_MONKMEAL, SPR_ABRAZIEROFF, SPR_ABRAZIER2,
+ SPR32_EXPLOS, SPR38_GARBAGE1,SPR39_GARBAGE2,
+ SPR42_GRATE, SPR43_MSHARDS, SPR44_PEDESTAL,SPR45_ETABLE,
+ SPR46_STOOL, SPR50_TREE, SPR51_PLANT,
+ SPR55_IBARREL, FBASIN1, FBASIN2, FBASIN3,
+ EBASIN, PORRIDGE1, PORRIDGE2, PORRIDGE3,
+ PORRIDGE4, PORRIDGE5, PORRIDGE6, MONKCRYSTAL11,
+ MONKCRYSTAL12, MONKCRYSTAL13, MONKCRYSTAL14, MONKCRYSTAL15,
+ MONKCRYSTAL16, MONKCRYSTAL21,
+ MONKCRYSTAL22, MONKCRYSTAL23, MONKCRYSTAL24, MONKCRYSTAL25,
+ MONKCRYSTAL26, MONKCRYSTAL27, TORCH1,
+ TORCH2, TORCH3, TORCH4, TORCH5,
+ TORCH6, TORCH7, TORCH8, TORCH9,
+ TORCH10, TORCH11, TORCH12, TORCH13,
+ TORCH14, TORCH15,
+
+ /*
+ ATORCH2, ATORCH3,
+ ATORCH4, ATORCH5, ATORCH6, ATORCH7,
+ ATORCH8, ATORCH9, ATORCH10, ATORCH11,
+ ATORCH12, ATORCH13, ATORCH14, ATORCH15,
+ ATORCH16,
+ */
+
+ FFLAME1,
+ FFLAME2, FFLAME3, FFLAME4, FFLAME5,
+ FFLAME6, FFLAME7, SPR_TWOPIST, SPR_MP40,
+ SPR_BAZOOKA, SPR_FIREBOMB, SPR_HEATSEEK, SPR_DRUNK,
+ SPR_FIREWALL, SPR_KES, SPR_SPLIT,
+
+
+
+ GASMASKPOWERUP,
+ BULLETPROOFPOWERUP, ASBESTOSPOWERUP,PREPIT,POSTPIT,
+
+
+ CASSATT_SHOOT11,CASSATT_SHOOT12,CASSATT_SHOOT13,CASSATT_SHOOT14,
+ CASSATT_SHOOT15,CASSATT_SHOOT16,CASSATT_SHOOT17,CASSATT_SHOOT18,
+
+ CASSATT_SHOOT21,CASSATT_SHOOT22,CASSATT_SHOOT23,CASSATT_SHOOT24,
+ CASSATT_SHOOT25,CASSATT_SHOOT26,CASSATT_SHOOT27,CASSATT_SHOOT28,
+
+
+
+ CASSATTM_SHOOT11,CASSATTM_SHOOT12,CASSATTM_SHOOT13,CASSATTM_SHOOT14,
+ CASSATTM_SHOOT15,CASSATTM_SHOOT16,CASSATTM_SHOOT17,CASSATTM_SHOOT18,
+
+ CASSATTM_SHOOT21,CASSATTM_SHOOT22,CASSATTM_SHOOT23,CASSATTM_SHOOT24,
+ CASSATTM_SHOOT25,CASSATTM_SHOOT26,CASSATTM_SHOOT27,CASSATTM_SHOOT28,
+
+
+
+ CASSATT_S1,CASSATT_S2,CASSATT_S3,CASSATT_S4,
+ CASSATT_S5,CASSATT_S6,CASSATT_S7,CASSATT_S8,
+
+ CASSATT_W11,CASSATT_W12,CASSATT_W13,CASSATT_W14,
+ CASSATT_W15,CASSATT_W16,CASSATT_W17,CASSATT_W18,
+
+ CASSATT_W21,CASSATT_W22,CASSATT_W23,CASSATT_W24,
+ CASSATT_W25,CASSATT_W26,CASSATT_W27,CASSATT_W28,
+
+ CASSATT_W31,CASSATT_W32,CASSATT_W33,CASSATT_W34,
+ CASSATT_W35,CASSATT_W36,CASSATT_W37,CASSATT_W38,
+
+ CASSATT_W41,CASSATT_W42,CASSATT_W43,CASSATT_W44,
+ CASSATT_W45,CASSATT_W46,CASSATT_W47,CASSATT_W48,
+
+
+ CASSATT_VDIE1,CASSATT_VDIE2,CASSATT_VDIE3,CASSATT_VDIE4,CASSATT_VDIE5,
+ CASSATT_VDIE6,
+ CASSATT_VDEAD,
+
+ CASSATT_DIE1,CASSATT_DIE2,CASSATT_DIE3,CASSATT_DIE4,CASSATT_DIE5,
+ CASSATT_DIE6,
+ CASSATT_DEAD,
+
+
+// DDOI - Wad ends here
+
+ BARRETT_SHOOT11,BARRETT_SHOOT12,BARRETT_SHOOT13,BARRETT_SHOOT14,
+ BARRETT_SHOOT15,BARRETT_SHOOT16,BARRETT_SHOOT17,BARRETT_SHOOT18,
+
+
+ BARRETT_SHOOT21,BARRETT_SHOOT22,BARRETT_SHOOT23,BARRETT_SHOOT24,
+ BARRETT_SHOOT25,BARRETT_SHOOT26,BARRETT_SHOOT27,BARRETT_SHOOT28,
+
+
+ BARRETTM_SHOOT11,BARRETTM_SHOOT12,BARRETTM_SHOOT13,BARRETTM_SHOOT14,
+ BARRETTM_SHOOT15,BARRETTM_SHOOT16,BARRETTM_SHOOT17,BARRETTM_SHOOT18,
+
+ BARRETTM_SHOOT21,BARRETTM_SHOOT22,BARRETTM_SHOOT23,BARRETTM_SHOOT24,
+ BARRETTM_SHOOT25,BARRETTM_SHOOT26,BARRETTM_SHOOT27,BARRETTM_SHOOT28,
+
+
+
+ BARRETT_S1,BARRETT_S2,BARRETT_S3,BARRETT_S4,
+ BARRETT_S5,BARRETT_S6,BARRETT_S7,BARRETT_S8,
+
+ BARRETT_W11,BARRETT_W12,BARRETT_W13,BARRETT_W14,
+ BARRETT_W15,BARRETT_W16,BARRETT_W17,BARRETT_W18,
+
+ BARRETT_W21,BARRETT_W22,BARRETT_W23,BARRETT_W24,
+ BARRETT_W25,BARRETT_W26,BARRETT_W27,BARRETT_W28,
+
+ BARRETT_W31,BARRETT_W32,BARRETT_W33,BARRETT_W34,
+ BARRETT_W35,BARRETT_W36,BARRETT_W37,BARRETT_W38,
+
+ BARRETT_W41,BARRETT_W42,BARRETT_W43,BARRETT_W44,
+ BARRETT_W45,BARRETT_W46,BARRETT_W47,BARRETT_W48,
+
+
+ BARRETT_VDIE1,BARRETT_VDIE2,BARRETT_VDIE3,BARRETT_VDIE4,BARRETT_VDIE5,
+ BARRETT_VDIE6,
+ BARRETT_VDEAD,
+
+ BARRETT_DIE1,BARRETT_DIE2,BARRETT_DIE3,BARRETT_DIE4,BARRETT_DIE5,
+ BARRETT_DIE6,
+ BARRETT_DEAD,
+
+
+
+ WENDT_SHOOT11,WENDT_SHOOT12,WENDT_SHOOT13,WENDT_SHOOT14,
+ WENDT_SHOOT15,WENDT_SHOOT16,WENDT_SHOOT17,WENDT_SHOOT18,
+
+ WENDT_SHOOT21,WENDT_SHOOT22,WENDT_SHOOT23,WENDT_SHOOT24,
+ WENDT_SHOOT25,WENDT_SHOOT26,WENDT_SHOOT27,WENDT_SHOOT28,
+
+
+
+ WENDTM_SHOOT11,WENDTM_SHOOT12,WENDTM_SHOOT13,WENDTM_SHOOT14,
+ WENDTM_SHOOT15,WENDTM_SHOOT16,WENDTM_SHOOT17,WENDTM_SHOOT18,
+
+ WENDTM_SHOOT21,WENDTM_SHOOT22,WENDTM_SHOOT23,WENDTM_SHOOT24,
+ WENDTM_SHOOT25,WENDTM_SHOOT26,WENDTM_SHOOT27,WENDTM_SHOOT28,
+
+
+
+ WENDT_S1,WENDT_S2,WENDT_S3,WENDT_S4,
+ WENDT_S5,WENDT_S6,WENDT_S7,WENDT_S8,
+
+ WENDT_W11,WENDT_W12,WENDT_W13,WENDT_W14,
+ WENDT_W15,WENDT_W16,WENDT_W17,WENDT_W18,
+
+ WENDT_W21,WENDT_W22,WENDT_W23,WENDT_W24,
+ WENDT_W25,WENDT_W26,WENDT_W27,WENDT_W28,
+
+ WENDT_W31,WENDT_W32,WENDT_W33,WENDT_W34,
+ WENDT_W35,WENDT_W36,WENDT_W37,WENDT_W38,
+
+ WENDT_W41,WENDT_W42,WENDT_W43,WENDT_W44,
+ WENDT_W45,WENDT_W46,WENDT_W47,WENDT_W48,
+
+
+ WENDT_VDIE1,WENDT_VDIE2,WENDT_VDIE3,WENDT_VDIE4,WENDT_VDIE5,WENDT_VDIE6,
+ WENDT_VDEAD,
+
+ WENDT_DIE1,WENDT_DIE2,WENDT_DIE3,WENDT_DIE4,WENDT_DIE5,WENDT_DIE6,
+ WENDT_DEAD,
+
+
+//======
+
+
+ NI_SHOOT11,NI_SHOOT12,NI_SHOOT13,NI_SHOOT14,
+ NI_SHOOT15,NI_SHOOT16,NI_SHOOT17,NI_SHOOT18,
+
+ NI_SHOOT21,NI_SHOOT22,NI_SHOOT23,NI_SHOOT24,
+ NI_SHOOT25,NI_SHOOT26,NI_SHOOT27,NI_SHOOT28,
+
+
+
+ NIM_SHOOT11,NIM_SHOOT12,NIM_SHOOT13,NIM_SHOOT14,
+ NIM_SHOOT15,NIM_SHOOT16,NIM_SHOOT17,NIM_SHOOT18,
+
+ NIM_SHOOT21,NIM_SHOOT22,NIM_SHOOT23,NIM_SHOOT24,
+ NIM_SHOOT25,NIM_SHOOT26,NIM_SHOOT27,NIM_SHOOT28,
+
+
+
+ NI_S1,NI_S2,NI_S3,NI_S4,
+ NI_S5,NI_S6,NI_S7,NI_S8,
+
+ NI_W11,NI_W12,NI_W13,NI_W14,
+ NI_W15,NI_W16,NI_W17,NI_W18,
+
+ NI_W21,NI_W22,NI_W23,NI_W24,
+ NI_W25,NI_W26,NI_W27,NI_W28,
+
+ NI_W31,NI_W32,NI_W33,NI_W34,
+ NI_W35,NI_W36,NI_W37,NI_W38,
+
+ NI_W41,NI_W42,NI_W43,NI_W44,
+ NI_W45,NI_W46,NI_W47,NI_W48,
+
+
+ NI_VDIE1,NI_VDIE2,NI_VDIE3,NI_VDIE4,NI_VDIE5,NI_VDIE6,
+ NI_VDEAD,
+
+ NI_DIE1,NI_DIE2,NI_DIE3,NI_DIE4,NI_DIE5,NI_DIE6,
+ NI_DEAD,
+
+
+
+
+ IPF_SHOOT11,IPF_SHOOT12,IPF_SHOOT13,IPF_SHOOT14,
+ IPF_SHOOT15,IPF_SHOOT16,IPF_SHOOT17,IPF_SHOOT18,
+
+ IPF_SHOOT21,IPF_SHOOT22,IPF_SHOOT23,IPF_SHOOT24,
+ IPF_SHOOT25,IPF_SHOOT26,IPF_SHOOT27,IPF_SHOOT28,
+
+
+ IPFM_SHOOT11,IPFM_SHOOT12,IPFM_SHOOT13,IPFM_SHOOT14,
+ IPFM_SHOOT15,IPFM_SHOOT16,IPFM_SHOOT17,IPFM_SHOOT18,
+
+ IPFM_SHOOT21,IPFM_SHOOT22,IPFM_SHOOT23,IPFM_SHOOT24,
+ IPFM_SHOOT25,IPFM_SHOOT26,IPFM_SHOOT27,IPFM_SHOOT28,
+
+
+
+ IPF_S1,IPF_S2,IPF_S3,IPF_S4,
+ IPF_S5,IPF_S6,IPF_S7,IPF_S8,
+
+ IPF_W11,IPF_W12,IPF_W13,IPF_W14,
+ IPF_W15,IPF_W16,IPF_W17,IPF_W18,
+
+ IPF_W21,IPF_W22,IPF_W23,IPF_W24,
+ IPF_W25,IPF_W26,IPF_W27,IPF_W28,
+
+ IPF_W31,IPF_W32,IPF_W33,IPF_W34,
+ IPF_W35,IPF_W36,IPF_W37,IPF_W38,
+
+ IPF_W41,IPF_W42,IPF_W43,IPF_W44,
+ IPF_W45,IPF_W46,IPF_W47,IPF_W48,
+
+
+ IPF_VDIE1,IPF_VDIE2,IPF_VDIE3,IPF_VDIE4,IPF_VDIE5,IPF_VDIE6,
+ IPF_VDEAD,
+
+ IPF_DIE1,IPF_DIE2,IPF_DIE3,IPF_DIE4,IPF_DIE5,IPF_DIE6,
+ IPF_DEAD,
+
+
+ SERIALDOG_W11,SERIALDOG_W12,SERIALDOG_W13,SERIALDOG_W14,
+ SERIALDOG_W15,SERIALDOG_W16,SERIALDOG_W17,SERIALDOG_W18,
+
+ SERIALDOG_W21,SERIALDOG_W22,SERIALDOG_W23,SERIALDOG_W24,
+ SERIALDOG_W25,SERIALDOG_W26,SERIALDOG_W27,SERIALDOG_W28,
+
+ SERIALDOG_W31,SERIALDOG_W32,SERIALDOG_W33,SERIALDOG_W34,
+ SERIALDOG_W35,SERIALDOG_W36,SERIALDOG_W37,SERIALDOG_W38,
+
+ SERIALDOG_W41,SERIALDOG_W42,SERIALDOG_W43,SERIALDOG_W44,
+ SERIALDOG_W45,SERIALDOG_W46,SERIALDOG_W47,SERIALDOG_W48,
+
+ SERIALDOG_ATTACK1,SERIALDOG_ATTACK2,SERIALDOG_ATTACK3,SERIALDOG_ATTACK4,
+ SERIALDOG_ATTACK5,SERIALDOG_ATTACK6,SERIALDOG_ATTACK7,SERIALDOG_ATTACK8,
+
+
+ /*************** Lowguard 2 (Marianna) *************************************/
+
+
+ /*
+ SPR_MARIANNA_SHOOT1,SPR_MARIANNA_SHOOT2,SPR_MARIANNA_SHOOT3,SPR_MARIANNA_SHOOT4,
+
+ SPR_MARIANNA_S1,SPR_MARIANNA_S2,SPR_MARIANNA_S3,SPR_MARIANNA_S4,
+ SPR_MARIANNA_S5,SPR_MARIANNA_S6,SPR_MARIANNA_S7,SPR_MARIANNA_S8,
+
+ SPR_MARIANNA_W11,SPR_MARIANNA_W12,SPR_MARIANNA_W13,SPR_MARIANNA_W14,
+ SPR_MARIANNA_W15,SPR_MARIANNA_W16,SPR_MARIANNA_W17,SPR_MARIANNA_W18,
+
+ SPR_MARIANNA_W21,SPR_MARIANNA_W22,SPR_MARIANNA_W23,SPR_MARIANNA_W24,
+ SPR_MARIANNA_W25,SPR_MARIANNA_W26,SPR_MARIANNA_W27,SPR_MARIANNA_W28,
+
+ SPR_MARIANNA_W31,SPR_MARIANNA_W32,SPR_MARIANNA_W33,SPR_MARIANNA_W34,
+ SPR_MARIANNA_W35,SPR_MARIANNA_W36,SPR_MARIANNA_W37,SPR_MARIANNA_W38,
+
+ SPR_MARIANNA_W41,SPR_MARIANNA_W42,SPR_MARIANNA_W43,SPR_MARIANNA_W44,
+ SPR_MARIANNA_W45,SPR_MARIANNA_W46,SPR_MARIANNA_W47,SPR_MARIANNA_W48,
+
+
+ SPR_MARIANNA_PAIN1, SPR_MARIANNA_PAIN2, SPR_MARIANNA_DIE1, SPR_MARIANNA_DIE2,
+ SPR_MARIANNA_DIE3, SPR_MARIANNA_DIE4, SPR_MARIANNA_DEAD,
+
+ SPR_MARIANNA_WPAIN1, SPR_MARIANNA_WPAIN2, SPR_MARIANNA_WDIE1, SPR_MARIANNA_WDIE2,
+ SPR_MARIANNA_WDIE3, SPR_MARIANNA_WDIE4, SPR_MARIANNA_WDEAD,
+
+
+ SPR_SNMAR_DEAD, SPR_MARISE1, SPR_MARISE2, SPR_MARISE3, SPR_MARISE4,
+ */
+
+
+ /****************** OBERPATROLLE (Nolan) ***********************************/
+
+
+ SPR_OP_SHOOT1,SPR_OP_SHOOT2,SPR_OP_SHOOT3,SPR_OP_SHOOT4,
+
+ SPR_OP_BOLOSHOOT1,SPR_OP_BOLOSHOOT2,SPR_OP_BOLOSHOOT3,SPR_OP_BOLOSHOOT4,
+ SPR_OP_BOLOSHOOT5,
+
+ SPR_OP_S1,SPR_OP_S2,SPR_OP_S3,SPR_OP_S4,
+ SPR_OP_S5,SPR_OP_S6,SPR_OP_S7,SPR_OP_S8,
+
+ SPR_OP_W11,SPR_OP_W12,SPR_OP_W13,SPR_OP_W14,
+ SPR_OP_W15,SPR_OP_W16,SPR_OP_W17,SPR_OP_W18,
+
+ SPR_OP_W21,SPR_OP_W22,SPR_OP_W23,SPR_OP_W24,
+ SPR_OP_W25,SPR_OP_W26,SPR_OP_W27,SPR_OP_W28,
+
+ SPR_OP_W31,SPR_OP_W32,SPR_OP_W33,SPR_OP_W34,
+ SPR_OP_W35,SPR_OP_W36,SPR_OP_W37,SPR_OP_W38,
+
+ SPR_OP_W41,SPR_OP_W42,SPR_OP_W43,SPR_OP_W44,
+ SPR_OP_W45,SPR_OP_W46,SPR_OP_W47,SPR_OP_W48,
+
+
+ SPR_OP_PAIN1,SPR_OP_PAIN2,
+ SPR_OP_ALTDIE1,SPR_OP_ALTDIE2,SPR_OP_ALTDIE3,
+ SPR_OP_ALTDIE4,SPR_OP_ALTDIE5,SPR_OP_ALTDEAD,
+
+ SPR_OP_WPAIN1,SPR_OP_WPAIN2,
+ SPR_OP_WALTDIE1,SPR_OP_WALTDIE2,SPR_OP_WALTDIE3,
+ SPR_OP_WALTDIE4,SPR_OP_WALTDIE5,SPR_OP_WALTDEAD,
+
+ SPR_OP_DIE1,SPR_OP_DIE2,SPR_OP_DIE3,
+ SPR_OP_DIE4,SPR_OP_DIE5,SPR_OP_DIE6,
+ SPR_OP_DEAD,
+
+
+
+
+
+ /******************* Normal monk (Lee)**********************************/
+
+
+ SPR_MONK_DRAIN1,SPR_MONK_DRAIN2,SPR_MONK_DRAIN3,SPR_MONK_DRAIN4,
+ SPR_MONK_DRAIN5,SPR_MONK_DRAIN6,
+
+ /*SPR_MONK_CAST1,SPR_MONK_CAST2,SPR_MONK_CAST3,SPR_MONK_CAST4,
+ SPR_MONK_CAST5,SPR_MONK_CAST6,SPR_MONK_CAST7,SPR_MONK_CAST8,*/
+
+ SPR_MONK_S1,SPR_MONK_S2,SPR_MONK_S3,SPR_MONK_S4,
+ SPR_MONK_S5,SPR_MONK_S6,SPR_MONK_S7,SPR_MONK_S8,
+
+ SPR_MONK_W11,SPR_MONK_W12,SPR_MONK_W13,SPR_MONK_W14,
+ SPR_MONK_W15,SPR_MONK_W16,SPR_MONK_W17,SPR_MONK_W18,
+
+ SPR_MONK_W21,SPR_MONK_W22,SPR_MONK_W23,SPR_MONK_W24,
+ SPR_MONK_W25,SPR_MONK_W26,SPR_MONK_W27,SPR_MONK_W28,
+
+ SPR_MONK_W31,SPR_MONK_W32,SPR_MONK_W33,SPR_MONK_W34,
+ SPR_MONK_W35,SPR_MONK_W36,SPR_MONK_W37,SPR_MONK_W38,
+
+ SPR_MONK_W41,SPR_MONK_W42,SPR_MONK_W43,SPR_MONK_W44,
+ SPR_MONK_W45,SPR_MONK_W46,SPR_MONK_W47,SPR_MONK_W48,
+
+ SPR_MONK_PAIN1,SPR_MONK_PAIN2,
+
+ SPR_MONK_DIE1,SPR_MONK_DIE2,SPR_MONK_DIE3,SPR_MONK_DIE4,
+ SPR_MONK_DEAD,
+
+ /*SPR_MONK_USE11,SPR_MONK_USE12,SPR_MONK_USE13,SPR_MONK_USE14,
+ SPR_MONK_USE15,SPR_MONK_USE16,SPR_MONK_USE17,SPR_MONK_USE18,
+
+ SPR_MONK_USE21,SPR_MONK_USE22,SPR_MONK_USE23,SPR_MONK_USE24,
+ SPR_MONK_USE25,SPR_MONK_USE26,SPR_MONK_USE27,SPR_MONK_USE28,
+ */
+
+
+ /******************* Fire monk (Allen)**********************************/
+
+ SPR_FIREMONK_CAST1,SPR_FIREMONK_CAST2,SPR_FIREMONK_CAST3,SPR_FIREMONK_CAST4,
+ SPR_FIREMONK_CAST5,SPR_FIREMONK_CAST6,SPR_FIREMONK_CAST7,
+
+ SPR_FIREMONK_S1,SPR_FIREMONK_S2,SPR_FIREMONK_S3,SPR_FIREMONK_S4,
+ SPR_FIREMONK_S5,SPR_FIREMONK_S6,SPR_FIREMONK_S7,SPR_FIREMONK_S8,
+
+ SPR_FIREMONK_W11,SPR_FIREMONK_W12,SPR_FIREMONK_W13,SPR_FIREMONK_W14,
+ SPR_FIREMONK_W15,SPR_FIREMONK_W16,SPR_FIREMONK_W17,SPR_FIREMONK_W18,
+
+ SPR_FIREMONK_W21,SPR_FIREMONK_W22,SPR_FIREMONK_W23,SPR_FIREMONK_W24,
+ SPR_FIREMONK_W25,SPR_FIREMONK_W26,SPR_FIREMONK_W27,SPR_FIREMONK_W28,
+
+ SPR_FIREMONK_W31,SPR_FIREMONK_W32,SPR_FIREMONK_W33,SPR_FIREMONK_W34,
+ SPR_FIREMONK_W35,SPR_FIREMONK_W36,SPR_FIREMONK_W37,SPR_FIREMONK_W38,
+
+ SPR_FIREMONK_W41,SPR_FIREMONK_W42,SPR_FIREMONK_W43,SPR_FIREMONK_W44,
+ SPR_FIREMONK_W45,SPR_FIREMONK_W46,SPR_FIREMONK_W47,SPR_FIREMONK_W48,
+
+ SPR_FIREMONK_PAIN1,SPR_FIREMONK_PAIN2,
+
+ SPR_FIREMONK_DIE1,SPR_FIREMONK_DIE2,SPR_FIREMONK_DIE3,SPR_FIREMONK_DIE4,
+ SPR_FIREMONK_DEAD1,SPR_FIREMONK_DEAD2,SPR_FIREMONK_DEAD3,SPR_FIREMONK_DEAD4,
+ SPR_FIREMONK_DEAD5,SPR_FIREMONK_DEAD6,SPR_FIREMONK_DEAD7,
+
+
+
+ /*
+ SPR_ALLEN_USE11,SPR_ALLEN_USE12,SPR_ALLEN_USE13,SPR_ALLEN_USE14,
+ SPR_ALLEN_USE15,SPR_ALLEN_USE16,SPR_ALLEN_USE17,SPR_ALLEN_USE18,
+
+ SPR_ALLEN_USE21,SPR_ALLEN_USE22,SPR_ALLEN_USE23,SPR_ALLEN_USE24,
+ SPR_ALLEN_USE25,SPR_ALLEN_USE26,SPR_ALLEN_USE27,SPR_ALLEN_USE28,
+ */
+ BCRAFT01,BCRAFT02,BCRAFT03,BCRAFT04,
+ BCRAFT05,BCRAFT06,BCRAFT07,BCRAFT08,
+ BCRAFT09,BCRAFT10,BCRAFT11,BCRAFT12,
+ BCRAFT13,BCRAFT14,BCRAFT15,BCRAFT16,
+
+
+ /************************* GENERAL DARIAN *******************************/
+
+
+ SPR_DARIAN_SHOOT1,SPR_DARIAN_SHOOT2,SPR_DARIAN_SHOOT3,SPR_DARIAN_SHOOT4,
+
+ SPR_DARIAN_SINK1,SPR_DARIAN_SINK2,SPR_DARIAN_SINK3,SPR_DARIAN_SINK4,
+ SPR_DARIAN_SINK5,SPR_DARIAN_SINK6,SPR_DARIAN_SINK7,SPR_DARIAN_SINK8,
+
+
+ SPR_DARIAN_S1,SPR_DARIAN_S2,SPR_DARIAN_S3,SPR_DARIAN_S4,
+ SPR_DARIAN_S5,SPR_DARIAN_S6,SPR_DARIAN_S7,SPR_DARIAN_S8,
+
+ SPR_DARIAN_W11,SPR_DARIAN_W12,SPR_DARIAN_W13,SPR_DARIAN_W14,
+ SPR_DARIAN_W15,SPR_DARIAN_W16,SPR_DARIAN_W17,SPR_DARIAN_W18,
+
+ SPR_DARIAN_W21,SPR_DARIAN_W22,SPR_DARIAN_W23,SPR_DARIAN_W24,
+ SPR_DARIAN_W25,SPR_DARIAN_W26,SPR_DARIAN_W27,SPR_DARIAN_W28,
+
+ SPR_DARIAN_W31,SPR_DARIAN_W32,SPR_DARIAN_W33,SPR_DARIAN_W34,
+ SPR_DARIAN_W35,SPR_DARIAN_W36,SPR_DARIAN_W37,SPR_DARIAN_W38,
+
+ SPR_DARIAN_W41,SPR_DARIAN_W42,SPR_DARIAN_W43,SPR_DARIAN_W44,
+ SPR_DARIAN_W45,SPR_DARIAN_W46,SPR_DARIAN_W47,SPR_DARIAN_W48,
+
+
+ SPR_DARIAN_PAIN1, SPR_DARIAN_PAIN2, SPR_DARIAN_DIE1, SPR_DARIAN_DIE2,
+ SPR_DARIAN_DIE3, SPR_DARIAN_DIE4,SPR_DARIAN_DIE5, SPR_DARIAN_DIE6,
+ SPR_DARIAN_DIE7, SPR_DARIAN_DIE8,SPR_DARIAN_DIE9, SPR_DARIAN_DIE10,
+ SPR_DARIAN_DEAD,
+
+ SPR_DARIAN_WPAIN1, SPR_DARIAN_WPAIN2, SPR_WDARIAN_DIE1, SPR_WDARIAN_DIE2,
+ SPR_DARIAN_WDIE3, SPR_DARIAN_WDIE4,SPR_WDARIAN_DIE5, SPR_WDARIAN_DIE6,
+ SPR_DARIAN_WDIE7, SPR_DARIAN_WDIE8,SPR_WDARIAN_DIE9, SPR_WDARIAN_DIE10,
+ SPR_DARIAN_WDEAD,
+
+
+ SPR_DARIAN_USE11,SPR_DARIAN_USE12,SPR_DARIAN_USE13,SPR_DARIAN_USE14,
+ SPR_DARIAN_USE15,SPR_DARIAN_USE16,SPR_DARIAN_USE17,SPR_DARIAN_USE18,
+
+ SPR_DARIAN_USE21,SPR_DARIAN_USE22,SPR_DARIAN_USE23,SPR_DARIAN_USE24,
+ SPR_DARIAN_USE25,SPR_DARIAN_USE26,SPR_DARIAN_USE27,SPR_DARIAN_USE28,
+
+
+
+ /************************* HEINRICH KRIST ******************************/
+
+
+ SPR_KRIST_S1,SPR_KRIST_S2,SPR_KRIST_S3,SPR_KRIST_S4,
+ SPR_KRIST_S5,SPR_KRIST_S6,SPR_KRIST_S7,SPR_KRIST_S8,
+
+ SPR_KRIST_LEFT1,SPR_KRIST_LEFT2,SPR_KRIST_LEFT3,SPR_KRIST_LEFT4,
+ SPR_KRIST_LEFT5,SPR_KRIST_LEFT6,SPR_KRIST_LEFT7,SPR_KRIST_LEFT8,
+
+
+ SPR_KRIST_SHOOT1,SPR_KRIST_SHOOT2,SPR_KRIST_SHOOT3,SPR_KRIST_SHOOT4,
+ SPR_KRIST_SHOOT5,SPR_KRIST_SHOOT6,SPR_KRIST_SHOOT7,SPR_KRIST_SHOOT8,
+ SPR_KRIST_SHOOT9,SPR_KRIST_SHOOT10,SPR_KRIST_SHOOT11,
+
+//SPR_KRIST_PAIN1,SPR_KRIST_PAIN2,SPR_KRIST_PAIN3,SPR_KRIST_PAIN4,
+//SPR_KRIST_PAIN5,SPR_KRIST_PAIN6,SPR_KRIST_PAIN7,SPR_KRIST_PAIN8,
+
+ SPR_KRIST_DIE1,SPR_KRIST_DIE2,SPR_KRIST_DEAD1,SPR_KRIST_DEAD2,
+ SPR_KRIST_DEAD3,SPR_KRIST_DEAD4,SPR_KRIST_DEAD5,SPR_KRIST_DEAD6,
+ SPR_KRIST_DEAD7,SPR_KRIST_DEAD8,
+
+ SPR_KRIST_RIGHT1,SPR_KRIST_RIGHT2,SPR_KRIST_RIGHT3,SPR_KRIST_RIGHT4,
+ SPR_KRIST_RIGHT5,SPR_KRIST_RIGHT6,SPR_KRIST_RIGHT7,SPR_KRIST_RIGHT8,
+
+ SPR_KRIST_FOR1,SPR_KRIST_FOR2,SPR_KRIST_FOR3,SPR_KRIST_FOR4,
+ SPR_KRIST_FOR5,SPR_KRIST_FOR6,SPR_KRIST_FOR7,SPR_KRIST_FOR8,
+
+//SPR_KRIST_BACK1,SPR_KRIST_BACK2,SPR_KRIST_BACK3,SPR_KRIST_BACK4,
+//SPR_KRIST_BACK5,SPR_KRIST_BACK6,SPR_KRIST_BACK7,SPR_KRIST_BACK8,
+
+ SPR_KRIST_MINERIGHT1,SPR_KRIST_MINERIGHT2,SPR_KRIST_MINERIGHT3,SPR_KRIST_MINERIGHT4,
+ SPR_KRIST_MINERIGHT5,SPR_KRIST_MINERIGHT6,SPR_KRIST_MINERIGHT7,SPR_KRIST_MINERIGHT8,
+
+//SPR_KRIST_MINELEFT1,SPR_KRIST_MINELEFT2,SPR_KRIST_MINELEFT3,SPR_KRIST_MINELEFT4,
+//SPR_KRIST_MINELEFT5,SPR_KRIST_MINELEFT6,SPR_KRIST_MINELEFT7,SPR_KRIST_MINELEFT8,
+
+ SPR_KRIST_DOPE1,SPR_KRIST_DOPE2,SPR_KRIST_DOPE3,
+
+
+ /************************* NME ******************************/
+
+ NMEHEAD1_01,NMEHEAD1_02,NMEHEAD1_03,NMEHEAD1_04,
+ NMEHEAD1_05,NMEHEAD1_06,NMEHEAD1_07,NMEHEAD1_08,
+ NMEHEAD1_09,NMEHEAD1_10,NMEHEAD1_11,NMEHEAD1_12,
+ NMEHEAD1_13,NMEHEAD1_14,NMEHEAD1_15,NMEHEAD1_16,
+
+ NMEHEAD2_01,NMEHEAD2_02,NMEHEAD2_03,NMEHEAD2_04,
+ NMEHEAD2_05,NMEHEAD2_06,NMEHEAD2_07,NMEHEAD2_08,
+ NMEHEAD2_09,NMEHEAD2_10,NMEHEAD2_11,NMEHEAD2_12,
+ NMEHEAD2_13,NMEHEAD2_14,NMEHEAD2_15,NMEHEAD2_16,
+
+ NMEBODY1_01,NMEBODY1_02,NMEBODY1_03,NMEBODY1_04,
+ NMEBODY1_05,NMEBODY1_06,NMEBODY1_07,NMEBODY1_08,
+ NMEBODY1_09,NMEBODY1_10,NMEBODY1_11,NMEBODY1_12,
+ NMEBODY1_13,NMEBODY1_14,NMEBODY1_15,NMEBODY1_16,
+
+ NMEBODY2_01,NMEBODY2_02,NMEBODY2_03,NMEBODY2_04,
+ NMEBODY2_05,NMEBODY2_06,NMEBODY2_07,NMEBODY2_08,
+ NMEBODY2_09,NMEBODY2_10,NMEBODY2_11,NMEBODY2_12,
+ NMEBODY2_13,NMEBODY2_14,NMEBODY2_15,NMEBODY2_16,
+
+ NMEBODY3_01,NMEBODY3_02,NMEBODY3_03,NMEBODY3_04,
+ NMEBODY3_05,NMEBODY3_06,NMEBODY3_07,NMEBODY3_08,
+ NMEBODY3_09,NMEBODY3_10,NMEBODY3_11,NMEBODY3_12,
+ NMEBODY3_13,NMEBODY3_14,NMEBODY3_15,NMEBODY3_16,
+
+ NMEBODY4_01,NMEBODY4_02,NMEBODY4_03,NMEBODY4_04,
+ NMEBODY4_05,NMEBODY4_06,NMEBODY4_07,NMEBODY4_08,
+ NMEBODY4_09,NMEBODY4_10,NMEBODY4_11,NMEBODY4_12,
+ NMEBODY4_13,NMEBODY4_14,NMEBODY4_15,NMEBODY4_16,
+
+ NMEWHEEL1_01,NMEWHEEL1_02,NMEWHEEL1_03,NMEWHEEL1_04,
+ NMEWHEEL1_05,NMEWHEEL1_06,NMEWHEEL1_07,NMEWHEEL1_08,
+ NMEWHEEL1_09,NMEWHEEL1_10,NMEWHEEL1_11,NMEWHEEL1_12,
+ NMEWHEEL1_13,NMEWHEEL1_14,NMEWHEEL1_15,NMEWHEEL1_16,
+
+ NMEWHEEL2_01,NMEWHEEL2_02,NMEWHEEL2_03,NMEWHEEL2_04,
+ NMEWHEEL2_05,NMEWHEEL2_06,NMEWHEEL2_07,NMEWHEEL2_08,
+ NMEWHEEL2_09,NMEWHEEL2_10,NMEWHEEL2_11,NMEWHEEL2_12,
+ NMEWHEEL2_13,NMEWHEEL2_14,NMEWHEEL2_15,NMEWHEEL2_16,
+
+ NMEWHEEL3_01,NMEWHEEL3_02,NMEWHEEL3_03,NMEWHEEL3_04,
+ NMEWHEEL3_05,NMEWHEEL3_06,NMEWHEEL3_07,NMEWHEEL3_08,
+ NMEWHEEL3_09,NMEWHEEL3_10,NMEWHEEL3_11,NMEWHEEL3_12,
+ NMEWHEEL3_13,NMEWHEEL3_14,NMEWHEEL3_15,NMEWHEEL3_16,
+
+ NMEWHEEL4_01,NMEWHEEL4_02,NMEWHEEL4_03,NMEWHEEL4_04,
+ NMEWHEEL4_05,NMEWHEEL4_06,NMEWHEEL4_07,NMEWHEEL4_08,
+ NMEWHEEL4_09,NMEWHEEL4_10,NMEWHEEL4_11,NMEWHEEL4_12,
+ NMEWHEEL4_13,NMEWHEEL4_14,NMEWHEEL4_15,NMEWHEEL4_16,
+
+ NMEWHEEL5_01,NMEWHEEL5_02,NMEWHEEL5_03,NMEWHEEL5_04,
+ NMEWHEEL5_05,NMEWHEEL5_06,NMEWHEEL5_07,NMEWHEEL5_08,
+ NMEWHEEL5_09,NMEWHEEL5_10,NMEWHEEL5_11,NMEWHEEL5_12,
+ NMEWHEEL5_13,NMEWHEEL5_14,NMEWHEEL5_15,NMEWHEEL5_16,
+
+ NMEROCKET_01,NMEROCKET_02,NMEROCKET_03,NMEROCKET_04,
+ NMEROCKET_05,NMEROCKET_06,NMEROCKET_07,NMEROCKET_08,
+ NMEROCKET_09,NMEROCKET_10,NMEROCKET_11,NMEROCKET_12,
+ NMEROCKET_13,NMEROCKET_14,NMEROCKET_15,NMEROCKET_16,
+
+ NMEROCKET2_01,NMEROCKET2_02,NMEROCKET2_03,NMEROCKET2_04,
+ NMEROCKET2_05,NMEROCKET2_06,NMEROCKET2_07,NMEROCKET2_08,
+ NMEROCKET2_09,NMEROCKET2_10,NMEROCKET2_11,NMEROCKET2_12,
+ NMEROCKET2_13,NMEROCKET2_14,NMEROCKET2_15,NMEROCKET2_16,
+
+ NMEMINIBALL_01,NMEMINIBALL_02,NMEMINIBALL_03,NMEMINIBALL_04,
+ NMESAUCER_01,NMESAUCER_02,NMESAUCER_03,NMESAUCER_04,
+
+
+ /************************** TOM ****************************************/
+
+ TOMS1,TOMS2,TOMS3,TOMS4,TOMS5,TOMS6,TOMS7,TOMS8,
+
+ TOMFLY11,TOMFLY12,TOMFLY13,TOMFLY14,
+ TOMFLY15,TOMFLY16,TOMFLY17,TOMFLY18,
+
+ TOMFLY21,TOMFLY22,TOMFLY23,TOMFLY24,
+ TOMFLY25,TOMFLY26,TOMFLY27,TOMFLY28,
+
+ TOMLG1,TOMLG2,TOMLG3,TOMLG4,
+ TOMLG5,TOMLG6,TOMLG7,TOMLG8,
+
+ TOMLG9,TOMLG10,TOMLG11,
+
+ TOMFS1,TOMFS2,TOMFS3,TOMFS4,
+ TOMFS5,TOMFS6,
+
+ TOMBR1,TOMBR2,TOMBR3,TOMBR4,
+ TOMBR5,TOMBR6,TOMBR7,TOMBR8,
+
+ TOMHEAD1,TOMHEAD2,TOMHEAD3,TOMHEAD4,
+ TOMHEAD5,TOMHEAD6,TOMHEAD7,TOMHEAD8,
+
+ TPREPARE,
+ THDIE1,
+ THDIE2,
+ TAWAKEN1,TAWAKEN2,TAWAKEN3,TAWAKEN4,
+ TAWAKEN5,
+
+ THBALL1,THBALL2,THBALL3,THBALL4,
+ THBALL5,THBALL6,THBALL7,THBALL8,
+ THBALL9,
+
+ TSPHERE1,TSPHERE2,TSPHERE3,TSPHERE4,
+ TSPHERE5,TSPHERE6,TSPHERE7,TSPHERE8,
+ TSPHERE9,TSPHERE10,
+
+ TBBALL1,TBBALL2,TBBALL3,TBBALL4,
+ TBBALL5,TBBALL6,TBBALL7,TBBALL8,
+ TBBALL9,
+
+ TSCAREB1,TSCAREB2,TSCAREB3,TSCAREB4,
+ TSCAREB5,
+
+ TOMDIE1,TOMDIE2,TOMDIE3,TOMDIE4,
+ TOMDIE5,TOMDIE6,TOMDIE7,TOMDIE8,
+
+ TOMRH1,TOMRH2,TOMRH3,TOMRH4,
+ TOMRH5,TOMRH6,TOMRH7,TOMRH8,
+
+ TOHRH1,TOHRH2,TOHRH3,TOHRH4,
+ TOHRH5,TOHRH6,TOHRH7,TOHRH8,
+
+
+
+
+ SPEARDOWN1,SPEARDOWN2,SPEARDOWN3,SPEARDOWN4,
+ SPEARDOWN5,SPEARDOWN6,SPEARDOWN7,SPEARDOWN8,
+ SPEARDOWN9,SPEARDOWN10,SPEARDOWN11,SPEARDOWN12,
+ SPEARDOWN13,SPEARDOWN14,SPEARDOWN15,SPEARDOWN16,
+
+
+ DBLADE1,DBLADE2,DBLADE3,DBLADE4,
+ DBLADE5,DBLADE6,DBLADE7,DBLADE8,
+ DBLADE9,//DBLADE10,DBLADE11,DBLADE12,
+//DBLADE13,DBLADE14,DBLADE15,DBLADE16,
+
+ FIREJETDOWN1,FIREJETDOWN2,FIREJETDOWN3,FIREJETDOWN4,
+ FIREJETDOWN5,FIREJETDOWN6,FIREJETDOWN7,FIREJETDOWN8,
+ FIREJETDOWN9,FIREJETDOWN10,FIREJETDOWN11,FIREJETDOWN12,
+ FIREJETDOWN13,FIREJETDOWN14,FIREJETDOWN15,FIREJETDOWN16,
+ FIREJETDOWN17,FIREJETDOWN18,FIREJETDOWN19,FIREJETDOWN20,
+ FIREJETDOWN21,FIREJETDOWN22,FIREJETDOWN23,
+
+
+ CRUSHUP1,CRUSHUP2,CRUSHUP3,CRUSHUP4,
+ CRUSHUP5,CRUSHUP6,CRUSHUP7,CRUSHUP8,
+
+
+
+ SPINUBLADE_01,SPINUBLADE_02,SPINUBLADE_03,SPINUBLADE_04,
+ SPINUBLADE_05,SPINUBLADE_06,SPINUBLADE_07,SPINUBLADE_08,
+
+ SPINUBLADE_09,SPINUBLADE_10,SPINUBLADE_11,SPINUBLADE_12,
+ SPINUBLADE_13,SPINUBLADE_14,SPINUBLADE_15,SPINUBLADE_16,
+
+
+
+
+ SPINDBLADE_01,SPINDBLADE_02,SPINDBLADE_03,SPINDBLADE_04,
+ SPINDBLADE_05,SPINDBLADE_06,SPINDBLADE_07,SPINDBLADE_08,
+
+ SPINDBLADE_09,SPINDBLADE_10,SPINDBLADE_11,SPINDBLADE_12,
+ SPINDBLADE_13,SPINDBLADE_14,SPINDBLADE_15,SPINDBLADE_16,
+
+
+
+ DIP11,DIP21,DIP31,
+ TOMLARVA1, TOMLARVA2, TOMLARVA3, TOMLARVA4,
+
+ SCOTHEAD1,SCOTHEAD2,SCOTHEAD3,SCOTHEAD4,
+ SCOTHEAD5,SCOTHEAD6,SCOTHEAD7,
+
+ KNIFE_STATUE1,KNIFE_STATUE2,KNIFE_STATUE3,KNIFE_STATUE4,
+ KNIFE_STATUE5,KNIFE_STATUE6,KNIFE_STATUE7,KNIFE_STATUE8,
+
+ EMPTY_STATUE1,EMPTY_STATUE2,EMPTY_STATUE3,EMPTY_STATUE4,
+ EMPTY_STATUE5,EMPTY_STATUE6,EMPTY_STATUE7,EMPTY_STATUE8,
+
+
+ BAT1,BAT2,BAT3,BAT4,
+ BAT5,BAT6,BAT7,BAT8,
+ BAT9,BAT10,BAT11,BAT12,
+ BAT13,BAT14,BAT15,BAT16,
+
+ DOGPOWERUP1, DOGPOWERUP2, DOGPOWERUP3, DOGPOWERUP4,
+ DOGPOWERUP5, DOGPOWERUP6, DOGPOWERUP7, DOGPOWERUP8,
+
+
+ THREEUP01, THREEUP02, THREEUP03, THREEUP04,
+ THREEUP05, THREEUP06, THREEUP07, THREEUP08,
+
+
+
+ BOULDER11,BOULDER21,BOULDER31,BOULDER41,
+
+ BDROP1,BDROP2,BDROP3,BDROP4,BDROP5,BDROP6,BDROP7,BDROP8,BDROP9,
+ BDROP10,BDROP11,
+
+ BSINK1,BSINK2,BSINK3,BSINK4,BSINK5,BSINK6,BSINK7,BSINK8,BSINK9,
+
+
+ GUNRISE11,GUNRISE12,GUNRISE13,GUNRISE14,
+ GUNRISE15,GUNRISE16,GUNRISE17,GUNRISE18,
+
+ GUNRISE21,GUNRISE22,GUNRISE23,GUNRISE24,
+ GUNRISE25,GUNRISE26,GUNRISE27,GUNRISE28,
+
+ GUNRISE31,GUNRISE32,GUNRISE33,GUNRISE34,
+ GUNRISE35,GUNRISE36,GUNRISE37,GUNRISE38,
+
+ GUNRISE41,GUNRISE42,GUNRISE43,GUNRISE44,
+ GUNRISE45,GUNRISE46,GUNRISE47,GUNRISE48,
+
+ GUNRISE51,GUNRISE52,GUNRISE53,GUNRISE54,
+ GUNRISE55,GUNRISE56,GUNRISE57,GUNRISE58,
+
+ GUNFIRE1,GUNFIRE2,GUNFIRE3,GUNFIRE4,
+ GUNFIRE5,GUNFIRE6,GUNFIRE7,GUNFIRE8,
+
+ GUNDEAD1,GUNDEAD2,
+
+
+ FOURWAY01,FOURWAY02,FOURWAY03,FOURWAY04,
+ FOURWAY05,FOURWAY06,FOURWAY07,FOURWAY08,
+ FOURWAYFIRE01,FOURWAYFIRE02,FOURWAYFIRE03,FOURWAYFIRE04,
+ FOURWAYFIRE05,FOURWAYFIRE06,FOURWAYFIRE07,FOURWAYFIRE08,
+
+
+
+
+ TOMLIGHTNING1,TOMLIGHTNING2,TOMLIGHTNING3,TOMLIGHTNING4,
+ TOMLIGHTNING5,TOMLIGHTNING6,TOMLIGHTNING7,TOMLIGHTNING8,
+
+ TOMSPHERE1,TOMSPHERE2,TOMSPHERE3,TOMSPHERE4,
+
+ TOMHANDBALL1,TOMHANDBALL2,
+
+ TOMFACEBALL1,TOMFACEBALL2,
+
+ TOMFLOORSPARK1,TOMFLOORSPARK2,TOMFLOORSPARK3,TOMFLOORSPARK4,
+
+
+ TOMSPIT1,TOMSPIT2,TOMSPIT3,TOMSPIT4,
+
+ SPITHIT1,SPITHIT2,SPITHIT3,SPITHIT4,
+
+
+
+ MONKFIRE1,MONKFIRE2,MONKFIRE3,MONKFIRE4,
+
+
+ BATBLAST1,BATBLAST2,BATBLAST3,BATBLAST4,
+
+ KESSPHERE1,KESSPHERE2,KESSPHERE3,KESSPHERE4,
+ KESSPHERE5,KESSPHERE6,KESSPHERE7,KESSPHERE8,
+
+ SPR_BOLO1,SPR_BOLO2,SPR_BOLO3,SPR_BOLO4,
+
+//MED
+ DOPE1,DOPE2,DOPE3,DOPE4,DOPE5,DOPE6,DOPE7,DOPE8,
+//CRUSHUP9,CRUSHUP10,CRUSHUP11,CRUSHUP12,
+//CRUSHUP13,CRUSHUP14,CRUSHUP15,CRUSHUP16,
+
+
+ /***************** Highguard 2 (Steve H.) ***************************************/
+
+
+ SPR_HIGHGRD2_SHOOT1,SPR_HIGHGRD2_SHOOT2,SPR_HIGHGRD2_SHOOT3,SPR_HIGHGRD2_SHOOT4,
+
+
+ SPR_HIGHGRD2_S1,SPR_HIGHGRD2_S2,SPR_HIGHGRD2_S3,SPR_HIGHGRD2_S4,
+ SPR_HIGHGRD2_S5,SPR_HIGHGRD2_S6,SPR_HIGHGRD2_S7,SPR_HIGHGRD2_S8,
+
+ SPR_HIGHGRD2_W11,SPR_HIGHGRD2_W12,SPR_HIGHGRD2_W13,SPR_HIGHGRD2_W14,
+ SPR_HIGHGRD2_W15,SPR_HIGHGRD2_W16,SPR_HIGHGRD2_W17,SPR_HIGHGRD2_W18,
+
+ SPR_HIGHGRD2_W21,SPR_HIGHGRD2_W22,SPR_HIGHGRD2_W23,SPR_HIGHGRD2_W24,
+ SPR_HIGHGRD2_W25,SPR_HIGHGRD2_W26,SPR_HIGHGRD2_W27,SPR_HIGHGRD2_W28,
+
+ SPR_HIGHGRD2_W31,SPR_HIGHGRD2_W32,SPR_HIGHGRD2_W33,SPR_HIGHGRD2_W34,
+ SPR_HIGHGRD2_W35,SPR_HIGHGRD2_W36,SPR_HIGHGRD2_W37,SPR_HIGHGRD2_W38,
+
+ SPR_HIGHGRD2_W41,SPR_HIGHGRD2_W42,SPR_HIGHGRD2_W43,SPR_HIGHGRD2_W44,
+ SPR_HIGHGRD2_W45,SPR_HIGHGRD2_W46,SPR_HIGHGRD2_W47,SPR_HIGHGRD2_W48,
+
+
+ SPR_HIGHGRD2_PAIN1,SPR_HIGHGRD2_PAIN2,
+ SPR_HIGHGRD2_DIE1,SPR_HIGHGRD2_DIE2,SPR_HIGHGRD2_DIE3,SPR_HIGHGRD2_DIE4,
+ SPR_HIGHGRD2_DIE5,SPR_HIGHGRD2_DEAD,
+
+ SPR_HIGHGRD2_WPAIN1,SPR_HIGHGRD2_WPAIN2,
+ SPR_HIGHGRD2_WDIE1,SPR_HIGHGRD2_WDIE2,SPR_HIGHGRD2_WDIE3,SPR_HIGHGRD2_WDIE4,
+ SPR_HIGHGRD2_WDIE5,SPR_HIGHGRD2_WDEAD,
+
+ /*
+ SPR_HIGHGRD2_USE11,SPR_HIGHGRD2_USE12,SPR_HIGHGRD2_USE13,SPR_HIGHGRD2_USE14,
+ SPR_HIGHGRD2_USE15,SPR_HIGHGRD2_USE16,SPR_HIGHGRD2_USE17,SPR_HIGHGRD2_USE18,
+
+ SPR_HIGHGRD2_USE21,SPR_HIGHGRD2_USE22,SPR_HIGHGRD2_USE23,SPR_HIGHGRD2_USE24,
+ SPR_HIGHGRD2_USE25,SPR_HIGHGRD2_USE26,SPR_HIGHGRD2_USE27,SPR_HIGHGRD2_USE28,
+ */
+
+
+ /****************** Alt. Overpatrol (Pat) ***********************************/
+
+ SPR_PAT_SHOOT1,SPR_PAT_SHOOT2,SPR_PAT_SHOOT3,SPR_PAT_SHOOT4,
+
+ SPR_PAT_BOLOSHOOT1,SPR_PAT_BOLOSHOOT2,SPR_PAT_BOLOSHOOT3,SPR_PAT_BOLOSHOOT4,
+ SPR_PAT_BOLOSHOOT5,
+
+ SPR_PAT_S1,SPR_PAT_S2,SPR_PAT_S3,SPR_PAT_S4,
+ SPR_PAT_S5,SPR_PAT_S6,SPR_PAT_S7,SPR_PAT_S8,
+
+ SPR_PAT_W11,SPR_PAT_W12,SPR_PAT_W13,SPR_PAT_W14,
+ SPR_PAT_W15,SPR_PAT_W16,SPR_PAT_W17,SPR_PAT_W18,
+
+ SPR_PAT_W21,SPR_PAT_W22,SPR_PAT_W23,SPR_PAT_W24,
+ SPR_PAT_W25,SPR_PAT_W26,SPR_PAT_W27,SPR_PAT_W28,
+
+ SPR_PAT_W31,SPR_PAT_W32,SPR_PAT_W33,SPR_PAT_W34,
+ SPR_PAT_W35,SPR_PAT_W36,SPR_PAT_W37,SPR_PAT_W38,
+
+ SPR_PAT_W41,SPR_PAT_W42,SPR_PAT_W43,SPR_PAT_W44,
+ SPR_PAT_W45,SPR_PAT_W46,SPR_PAT_W47,SPR_PAT_W48,
+
+
+ SPR_PAT_PAIN1,SPR_PAT_PAIN2,
+ SPR_PAT_ALTDIE1,SPR_PAT_ALTDIE2,SPR_PAT_ALTDIE3,
+ SPR_PAT_ALTDIE4,SPR_PAT_ALTDIE5,SPR_PAT_ALTDEAD,
+
+ SPR_PAT_WPAIN1,SPR_PAT_WPAIN2,
+ SPR_PAT_WALTDIE1,SPR_PAT_WALTDIE2,SPR_PAT_WALTDIE3,
+ SPR_PAT_WALTDIE4,SPR_PAT_WALTDIE5,SPR_PAT_WALTDEAD,
+
+ SPR_PAT_DIE1,SPR_PAT_DIE2,SPR_PAT_DIE3,
+ SPR_PAT_DIE4,SPR_PAT_DIE5,SPR_PAT_DIE6,
+ SPR_PAT_DEAD,
+
+
+ /******************** Alt. Lightning Guard (Ann) **********************************/
+
+
+ SPR_ANN_SHOOT1,SPR_ANN_SHOOT2,SPR_ANN_SHOOT3,SPR_ANN_SHOOT4,
+ SPR_ANN_KSHOOT1,SPR_ANN_KSHOOT2,SPR_ANN_KSHOOT3,
+
+
+ SPR_ANN_S1,SPR_ANN_S2,SPR_ANN_S3,SPR_ANN_S4,
+ SPR_ANN_S5,SPR_ANN_S6,SPR_ANN_S7,SPR_ANN_S8,
+
+ SPR_ANN_W11,SPR_ANN_W12,SPR_ANN_W13,SPR_ANN_W14,
+ SPR_ANN_W15,SPR_ANN_W16,SPR_ANN_W17,SPR_ANN_W18,
+
+ SPR_ANN_W21,SPR_ANN_W22,SPR_ANN_W23,SPR_ANN_W24,
+ SPR_ANN_W25,SPR_ANN_W26,SPR_ANN_W27,SPR_ANN_W28,
+
+ SPR_ANN_W31,SPR_ANN_W32,SPR_ANN_W33,SPR_ANN_W34,
+ SPR_ANN_W35,SPR_ANN_W36,SPR_ANN_W37,SPR_ANN_W38,
+
+ SPR_ANN_W41,SPR_ANN_W42,SPR_ANN_W43,SPR_ANN_W44,
+ SPR_ANN_W45,SPR_ANN_W46,SPR_ANN_W47,SPR_ANN_W48,
+
+
+ SPR_ANN_PAIN1,SPR_ANN_PAIN2,
+ SPR_ANN_DIE1,SPR_ANN_DIE2,SPR_ANN_DIE3,
+ SPR_ANN_DIE4,SPR_ANN_DEAD1,SPR_ANN_DEAD2,SPR_ANN_DEAD3,
+
+ SPR_ANN_WPAIN1,SPR_ANN_WPAIN2,
+ SPR_ANN_WDIE1,SPR_ANN_WDIE2,SPR_ANN_WDIE3,
+ SPR_ANN_WDIE4,SPR_ANN_WDEAD1,SPR_ANN_WDEAD2,SPR_ANN_WDEAD3,
+
+ SPR_ANN_RROLL1,SPR_ANN_RROLL2,SPR_ANN_RROLL3,SPR_ANN_RROLL4,
+ SPR_ANN_RROLL5,SPR_ANN_RROLL6,
+
+ SPR_ANN_LROLL1,SPR_ANN_LROLL2,SPR_ANN_LROLL3,SPR_ANN_LROLL4,
+ SPR_ANN_LROLL5,SPR_ANN_LROLL6,
+
+
+ /********************** Alt. Blitzguard (William) **********************************/
+
+
+ SPR_WILLIAM_SHOOT1,SPR_WILLIAM_SHOOT2,SPR_WILLIAM_SHOOT3,SPR_WILLIAM_SHOOT4,
+
+ SPR_WILLIAM_S1,SPR_WILLIAM_S2,SPR_WILLIAM_S3,SPR_WILLIAM_S4,
+ SPR_WILLIAM_S5,SPR_WILLIAM_S6,SPR_WILLIAM_S7,SPR_WILLIAM_S8,
+
+ SPR_WILLIAM_W11,SPR_WILLIAM_W12,SPR_WILLIAM_W13,SPR_WILLIAM_W14,
+ SPR_WILLIAM_W15,SPR_WILLIAM_W16,SPR_WILLIAM_W17,SPR_WILLIAM_W18,
+
+ SPR_WILLIAM_W21,SPR_WILLIAM_W22,SPR_WILLIAM_W23,SPR_WILLIAM_W24,
+ SPR_WILLIAM_W25,SPR_WILLIAM_W26,SPR_WILLIAM_W27,SPR_WILLIAM_W28,
+
+ SPR_WILLIAM_W31,SPR_WILLIAM_W32,SPR_WILLIAM_W33,SPR_WILLIAM_W34,
+ SPR_WILLIAM_W35,SPR_WILLIAM_W36,SPR_WILLIAM_W37,SPR_WILLIAM_W38,
+
+ SPR_WILLIAM_W41,SPR_WILLIAM_W42,SPR_WILLIAM_W43,SPR_WILLIAM_W44,
+ SPR_WILLIAM_W45,SPR_WILLIAM_W46,SPR_WILLIAM_W47,SPR_WILLIAM_W48,
+
+
+ SPR_WILLIAM_PAIN1, SPR_WILLIAM_PAIN2,SPR_WILLIAM_DIE1,SPR_WILLIAM_DIE2,
+ SPR_WILLIAM_DIE3,SPR_WILLIAM_DIE4,SPR_WILLIAM_DEAD1, SPR_WILLIAM_DEAD2,
+
+ SPR_WILLIAM_WPAIN1, SPR_WILLIAM_WPAIN2,SPR_WILLIAM_WDIE1,SPR_WILLIAM_WDIE2,
+ SPR_WILLIAM_WDIE3,SPR_WILLIAM_WDIE4,SPR_WILLIAM_WDEAD1, SPR_WILLIAM_WDEAD2,
+
+ SPR_WILLIAM_RISE1, SPR_WILLIAM_RISE2, SPR_WILLIAM_RISE3, SPR_WILLIAM_RISE4,
+
+ SPR_WILLIAM_USE11,SPR_WILLIAM_USE12,SPR_WILLIAM_USE13,SPR_WILLIAM_USE14,
+ SPR_WILLIAM_USE15,SPR_WILLIAM_USE16,SPR_WILLIAM_USE17,SPR_WILLIAM_USE18,
+
+ SPR_WILLIAM_USE21,SPR_WILLIAM_USE22,SPR_WILLIAM_USE23,SPR_WILLIAM_USE24,
+ SPR_WILLIAM_USE25,SPR_WILLIAM_USE26,SPR_WILLIAM_USE27,SPR_WILLIAM_USE28,
+
+ /******************* Fire monk (Mark)**********************************/
+
+
+ SPR_MARK_CAST1,SPR_MARK_CAST2,SPR_MARK_CAST3,SPR_MARK_CAST4,
+ SPR_MARK_CAST5,SPR_MARK_CAST6,SPR_MARK_CAST7,
+
+ SPR_MARK_S1,SPR_MARK_S2,SPR_MARK_S3,SPR_MARK_S4,
+ SPR_MARK_S5,SPR_MARK_S6,SPR_MARK_S7,SPR_MARK_S8,
+
+ SPR_MARK_W11,SPR_MARK_W12,SPR_MARK_W13,SPR_MARK_W14,
+ SPR_MARK_W15,SPR_MARK_W16,SPR_MARK_W17,SPR_MARK_W18,
+
+ SPR_MARK_W21,SPR_MARK_W22,SPR_MARK_W23,SPR_MARK_W24,
+ SPR_MARK_W25,SPR_MARK_W26,SPR_MARK_W27,SPR_MARK_W28,
+
+ SPR_MARK_W31,SPR_MARK_W32,SPR_MARK_W33,SPR_MARK_W34,
+ SPR_MARK_W35,SPR_MARK_W36,SPR_MARK_W37,SPR_MARK_W38,
+
+ SPR_MARK_W41,SPR_MARK_W42,SPR_MARK_W43,SPR_MARK_W44,
+ SPR_MARK_W45,SPR_MARK_W46,SPR_MARK_W47,SPR_MARK_W48,
+
+ SPR_MARK_PAIN1,SPR_MARK_PAIN2,
+
+ SPR_MARK_DIE1,SPR_MARK_DIE2,SPR_MARK_DIE3,SPR_MARK_DIE4,
+ SPR_MARK_DEAD1,SPR_MARK_DEAD2,SPR_MARK_DEAD3,SPR_MARK_DEAD4,
+ SPR_MARK_DEAD5,SPR_MARK_DEAD6,SPR_MARK_DEAD7,
+
+
+ /*
+ SPR_FIREMONK_USE11,SPR_FIREMONK_USE12,SPR_FIREMONK_USE13,SPR_FIREMONK_USE14,
+ SPR_FIREMONK_USE15,SPR_FIREMONK_USE16,SPR_FIREMONK_USE17,SPR_FIREMONK_USE18,
+
+ SPR_FIREMONK_USE21,SPR_FIREMONK_USE22,SPR_FIREMONK_USE23,SPR_FIREMONK_USE24,
+ SPR_FIREMONK_USE25,SPR_FIREMONK_USE26,SPR_FIREMONK_USE27,SPR_FIREMONK_USE28,
+ */
+
+//#endif
+
+ } actornames_t;
+
+typedef enum
+{ GUNSTART_LABEL,
+
+#if (SHAREWARE == 0)
+
+ W_KNIFE,WK2,WK3,WK4,WK5,WK6,WK7,WK8,WK9,WK10,
+
+ W_BMALEPISTOL1,xab,xcd,
+ W_BMRIGHTPISTOL1,xef,xgh,
+ W_BMLEFTPISTOL1,xij,xkl,
+#endif
+
+ W_MALEPISTOL1,x5,x6,
+ W_MRIGHTPISTOL1,x7,x8,
+ W_MLEFTPISTOL1,x9,x10,
+
+#if (SHAREWARE == 0)
+ W_FEMALEPISTOL1,x11,x12,
+ W_FRIGHTPISTOL1,x13,x14,
+ W_FLEFTPISTOL1,x15,x16,
+#endif
+
+ W_MP40,FN7,FN8,
+ W_BAZOOKA,FN22,fn104,fn105,
+ W_HEATSEEKER,FN80,fn108,fn109,
+ W_DRUNK,FN72,FN73,FN74,
+ W_FIREBOMB,FN33,fn106,fn107,
+ W_FIREWALL,FN66,FN67,
+ W_GODHAND,ded1,ded2,ded3,ded4,ded5,ded6,ded7,
+
+#if (SHAREWARE == 0)
+
+ W_SPLIT,FN69,FN70,FN71,
+ W_KES,fn101,fn102,fn103,x99,x100,
+ W_BAT,fn111,fn112,fn113,fn114,fn115,fn117,
+ W_DOG,bite1,bite2,bite3,nose1,nose2,nose3,nose4,paw1,paw2,paw3,paw4
+#endif
+} weaponsprites;
+
+
+#define SPR_DDOG_FIRE1 SPR_DDOG_JUMP1
+#define SPR_DDOG_FIRE2 SPR_DDOG_JUMP2
+#define SPR_DDOG_BOLTS2 SPR_DDOG_BOLTS1
+#define SPR_DDOG_BOLTS3 SPR_DDOG_BOLTS1
+#define SPR_DDOG_BOLTS4 SPR_DDOG_BOLTS1
+#define SPR_DDOG_HIT1 -1
+#define SPR_DDOG_HIT2 -1
+#define SPR_DDOG_HIT3 -1
+#define SPR_DDOG_PAIN1 SPR_DDOG_DIE1
+#define SPR_DDOG_PAIN2 SPR_DDOG_DIE1
+
+
+#define SPR_BLITZ_USE SPR_BLITZ_S1
+
+#define SPR_BLITZ_STEAL1 SPR_BLITZ_USE11
+#define SPR_BLITZ_STEAL2 SPR_BLITZ_USE12
+
+
+
+#define SPR_GRENADE_HIT1 -1
+#define SPR_GRENADE_HIT2 -1
+#define SPR_GRENADE_HIT3 -1
+
+#define SPR_FIREBALL_HIT1 -1
+#define SPR_FIREBALL_HIT2 -1
+#define SPR_FIREBALL_HIT3 -1
+
+#define SPR_ROBOGRD_SHURIKEN1 SPR_BSTAR1
+#define SPR_ROBOGRD_SHURIKEN2 SPR_BSTAR2
+#define SPR_ROBOGRD_SHURIKEN3 SPR_BSTAR3
+#define SPR_ROBOGRD_SHURIKEN4 SPR_BSTAR4
+#define SPR_SHURIKEN_HIT1 -1
+#define SPR_SHURIKEN_HIT2 -1
+#define SPR_SHURIKEN_HIT3 -1
+
+
+#define SPR_ESAU_USE SPR_ESAU_S1
+#define SPR_ESAU_WINS SPR_ESAU_S1
+#define SPR_ESAU_DIE4 SPR_ESAU_DIE3
+#define SPR_ESAU_DIE5 SPR_ESAU_DIE3
+#define SPR_ESAU_DIE6 SPR_ESAU_DIE3
+#define SPR_ESAU_DIE7 SPR_ESAU_DIE3
+
+
+#define SPR_MISSILEHIT1 -1
+#define SPR_MISSILEHIT2 -1
+#define SPR_MISSILEHIT3 -1
+#define SPR_HEINRICH_DIE4 SPR_HEINRICH_DIE3
+#define SPR_HEINRICH_DIE5 SPR_HEINRICH_DIE3
+#define SPR_HEINRICH_DIE6 SPR_HEINRICH_DIE3
+#define SPR_HEINRICH_DIE7 SPR_HEINRICH_DIE3
+#define SPR_HEINRICH_DEAD SPR_HEINRICH_DIE3
+#define SPR_HEINRICH_MINE SPR_HEINRICH_S1
+#define SPR_HEINRICH_USE SPR_HEINRICH_S1
+
+#define SPR_DMFBALL11 SPR_FIREBALL1
+#define SPR_DMFBALL21 SPR_FIREBALL2
+#define SPR_DMFBALL31 SPR_FIREBALL3
+#define SPR_DMFBALL41 SPR_FIREBALL4
+#define SPR_DMFBALLHIT1 -1
+#define SPR_DMFBALLHIT2 -1
+#define SPR_DMFBALLHIT3 -1
+#define SPR_DARKMONK_DIE4 SPR_DARKMONK_DIE3
+#define SPR_DARKMONK_DIE5 SPR_DARKMONK_DIE3
+#define SPR_DARKMONK_DIE6 SPR_DARKMONK_DIE3
+#define SPR_DARKMONK_DIE7 SPR_DARKMONK_DIE3
+#define SPR_DARKMONK_PAIN1 SPR_DARKMONK_DIE1
+#define SPR_DARKMONK_PAIN2 SPR_DARKMONK_DIE5
+
+#define SPR_OSHURHIT1 -1
+#define SPR_OSHURHIT2 -1
+#define SPR_OSHURHIT3 -1
+
+#define SPR_OSHUR1 SPR_BSTAR1
+#define SPR_OSHUR2 SPR_BSTAR2
+#define SPR_OSHUR3 SPR_BSTAR4
+#define SPR_OSHUR4 SPR_BSTAR4
+
+#define SPR_WALLSHOOT SPR_WALLSTAND1
+#define SPR_WALLPATH1 SPR_WALLSTAND1
+
+#endif
--- /dev/null
+++ b/rott/states.h
@@ -1,0 +1,668 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _states_public
+#define _states_public
+
+#include "develop.h"
+
+#if (SHAREWARE == 0)
+#define MAXSTATES 1300+17+8+32+32
+#else
+#define MAXSTATES 660+17+8+32+32
+#endif
+
+#define SF_CLOSE 0x01
+#define SF_CRUSH 0x02
+#define SF_UP 0x04
+#define SF_DOWN 0x08
+#define SF_SOUND 0x10
+#define SF_BLOCK 0x20
+#define SF_EYE1 0
+#define SF_EYE2 1
+#define SF_EYE3 2
+#define SF_DOGSTATE 0x40
+#define SF_BAT 0x80
+#define SF_FAKING 0x80
+#define SF_DEAD 0x80
+
+typedef struct statestruct
+{
+ byte rotate;
+ short shapenum; // a shapenum of -1 means get from ob->temp1
+ short tictime;
+ void (*think) ();
+ signed char condition;
+ struct statestruct *next;
+} statetype;
+
+extern statetype * statetable[MAXSTATES];
+
+extern statetype s_lowgrdstand;
+extern statetype s_lowgrdpath4;
+extern statetype s_lowgrdpath3;
+extern statetype s_lowgrdpath2;
+extern statetype s_lowgrdpath1;
+extern statetype s_lowgrdcollide;
+extern statetype s_lowgrdcollide2;
+//extern statetype s_lowgrduse1;
+extern statetype s_lowgrdshoot1;
+extern statetype s_lowgrdchase1;
+extern statetype s_lowgrddie1;
+
+extern statetype s_lowgrddie4rev;
+
+extern statetype s_lowgrdcrushed1;
+extern statetype s_lowgrdcrushed1;
+extern statetype s_sneakydown;
+extern statetype s_sneakyrise1;
+
+
+extern statetype s_highgrdstand;
+extern statetype s_highgrdpath1;
+extern statetype s_highgrdcollide;
+extern statetype s_highgrdcollide2;
+//extern statetype s_highgrduse1;
+extern statetype s_highgrdshoot1;
+extern statetype s_highgrdshoot3;
+extern statetype s_highgrdchase1;
+extern statetype s_highgrddie1;
+
+extern statetype s_highgrddie5rev;
+
+extern statetype s_highgrdcrushed1;
+
+
+extern statetype s_strikestand;
+extern statetype s_strikepath1;
+extern statetype s_strikecollide;
+extern statetype s_strikecollide2;
+extern statetype s_strikeshoot1;
+//extern statetype s_strikeuse1;
+extern statetype s_strikerollright1;
+extern statetype s_strikerollright3;
+extern statetype s_strikerollleft1;
+extern statetype s_strikerollleft3;
+extern statetype s_strikechase1;
+extern statetype s_strikedie1;
+
+extern statetype s_strikedie4rev;
+
+extern statetype s_strikewait;
+extern statetype s_strikecrushed1;
+
+
+extern statetype s_blitzstand;
+extern statetype s_blitzpath1;
+extern statetype s_blitzcollide;
+extern statetype s_blitzcollide2;
+extern statetype s_blitzshoot1;
+extern statetype s_blitzuse;
+extern statetype s_blitzsteal1;
+extern statetype s_blitzchase1;
+extern statetype s_blitzdie1;
+extern statetype s_blitzdie3;
+
+extern statetype s_blitzdie4rev;
+
+extern statetype s_blitzplead1;
+extern statetype s_blitzplead3;
+extern statetype s_blitzplead4;
+extern statetype s_blitzplead7;
+extern statetype s_blitzaplead5;
+extern statetype s_blitzaplead4;
+extern statetype s_blitzcrushed1;
+extern statetype s_blitzfakedie1;
+extern statetype s_blitzrise2;
+extern statetype s_blitzstruggledie1;
+extern statetype s_blitzstruggledead;
+
+extern statetype s_enforcerstand;
+extern statetype s_enforcerpath1;
+extern statetype s_enforcercollide;
+extern statetype s_enforcercollide2;
+//extern statetype s_enforceruse1;
+extern statetype s_enforcershoot1;
+extern statetype s_enforcershoot3;
+extern statetype s_enforcerthrow1;
+extern statetype s_grenade1;
+extern statetype s_grenadehit1;
+extern statetype s_enforcerchase1;
+extern statetype s_enforcerdie1;
+
+extern statetype s_enforcerdie4rev;
+
+extern statetype s_grenade_fall1;
+extern statetype s_grenade_fall6;
+extern statetype s_enforcercrushed1;
+
+
+extern statetype s_robogrdstand;
+extern statetype s_robogrdpath1;
+extern statetype s_robogrdshoot1;
+extern statetype s_robogrdshuriken1;
+extern statetype s_shurikenhit1;
+extern statetype s_robogrdchase1;
+extern statetype s_robogrddie1;
+extern statetype s_robogrdcollide;
+extern statetype s_robogrdcollide2;
+extern statetype s_robogrdcrushed1;
+extern statetype s_roboalign;
+extern statetype s_robowait;
+extern statetype s_roborealign;
+
+
+
+
+
+extern statetype s_altexplosion10;
+extern statetype s_altexplosion9 ;
+extern statetype s_altexplosion8 ;
+extern statetype s_altexplosion7 ;
+extern statetype s_altexplosion6 ;
+extern statetype s_altexplosion5 ;
+extern statetype s_altexplosion4 ;
+extern statetype s_altexplosion3 ;
+extern statetype s_altexplosion2 ;
+extern statetype s_altexplosion1 ;
+
+
+
+extern statetype s_explosion1;
+extern statetype s_explosion2;
+extern statetype s_explosion3;
+extern statetype s_explosion4;
+extern statetype s_explosion5;
+extern statetype s_explosion6;
+extern statetype s_explosion7;
+extern statetype s_explosion8;
+extern statetype s_explosion9;
+extern statetype s_explosion10;
+extern statetype s_explosion11;
+extern statetype s_explosion12;
+extern statetype s_explosion13;
+extern statetype s_explosion14;
+extern statetype s_explosion15;
+extern statetype s_explosion16;
+extern statetype s_explosion17;
+extern statetype s_explosion18;
+extern statetype s_explosion19;
+extern statetype s_explosion20;
+
+extern statetype s_grexplosion1;
+extern statetype s_grexplosion2;
+extern statetype s_grexplosion3;
+extern statetype s_grexplosion4;
+extern statetype s_grexplosion5;
+extern statetype s_grexplosion6;
+extern statetype s_grexplosion7;
+extern statetype s_grexplosion8;
+extern statetype s_grexplosion9;
+extern statetype s_grexplosion10;
+extern statetype s_grexplosion11;
+extern statetype s_grexplosion12;
+extern statetype s_grexplosion13;
+extern statetype s_grexplosion14;
+extern statetype s_grexplosion15;
+extern statetype s_grexplosion16;
+extern statetype s_grexplosion17;
+extern statetype s_grexplosion18;
+extern statetype s_grexplosion19;
+extern statetype s_grexplosion20;
+
+
+
+extern statetype s_staticexplosion1;
+extern statetype s_staticexplosion2;
+extern statetype s_staticexplosion3;
+extern statetype s_staticexplosion4;
+extern statetype s_staticexplosion5;
+extern statetype s_staticexplosion6;
+extern statetype s_staticexplosion7;
+extern statetype s_staticexplosion8;
+extern statetype s_staticexplosion9;
+extern statetype s_staticexplosion10;
+extern statetype s_staticexplosion11;
+extern statetype s_staticexplosion12;
+extern statetype s_staticexplosion13;
+extern statetype s_staticexplosion14;
+extern statetype s_staticexplosion15;
+extern statetype s_staticexplosion16;
+extern statetype s_staticexplosion17;
+extern statetype s_staticexplosion18;
+extern statetype s_staticexplosion19;
+extern statetype s_staticexplosion20;
+extern statetype s_staticexplosion21;
+extern statetype s_staticexplosion22;
+extern statetype s_staticexplosion23;
+extern statetype s_staticexplosion24;
+extern statetype s_staticexplosion25;
+
+extern statetype s_upblade1;
+
+extern statetype s_firejetup1;
+
+
+extern statetype s_columndowndown1;
+
+
+extern statetype s_spearup1;
+extern statetype s_pushcolumn1;
+extern statetype s_pushcolumn2;
+extern statetype s_pushcolumn3;
+
+extern statetype s_wallfireball;
+extern statetype s_crossfire1;
+extern statetype s_crossdone1;
+
+
+
+
+extern statetype s_fireunit1;
+extern statetype s_firespan1;
+
+extern statetype s_p_bazooka1;
+extern statetype s_p_bazooka2;
+
+extern statetype s_p_grenade;
+extern statetype s_p_gfall1;
+extern statetype s_p_gfall2;
+extern statetype s_p_gfall3;
+extern statetype s_p_gfall4;
+
+extern statetype s_gunsmoke1;
+extern statetype s_bloodspurt1;
+extern statetype s_hitmetalwall1;
+extern statetype s_hitmetalactor1;
+
+
+
+
+
+
+extern statetype s_dust;
+
+
+
+extern statetype s_skeleton1;
+
+
+extern statetype s_gas2;
+extern statetype s_gas1;
+
+
+extern statetype s_spring1;
+extern statetype s_spring2;
+
+
+
+
+extern statetype s_player;
+extern statetype s_free;
+
+extern statetype s_pgunattack1;
+extern statetype s_pmissattack1;
+extern statetype s_pgunattack2;
+extern statetype s_pmissattack2;
+extern statetype s_remoteinelev;
+extern statetype s_remotemove1;
+
+
+extern statetype s_godfire1;
+
+
+
+extern statetype s_remotedie1;
+
+
+extern statetype s_guts1;
+extern statetype s_guts12;
+
+
+extern statetype s_bossdeath;
+extern statetype s_megaexplosions;
+
+extern statetype s_superparticles;
+extern statetype s_gibs1;
+extern statetype s_gibsdone1;
+extern statetype s_bigsoul;
+extern statetype s_littlesoul;
+extern statetype s_vaporized1;
+extern statetype s_autospring1;
+extern statetype s_pbatblast;
+
+
+
+extern statetype s_collectorwander1;
+extern statetype s_collectorfdoor1;
+extern statetype s_tag;
+extern statetype s_timekeeper;
+extern statetype s_skeleton48;
+extern statetype s_skeleton24;
+
+extern statetype s_wind;
+extern statetype s_remoteguts1;
+extern statetype s_voidwait;
+extern statetype s_ashwait;
+extern statetype s_deadwait;
+extern statetype s_gutwait;
+extern statetype s_vaporized8;
+extern statetype s_remoteguts12;
+extern statetype s_eye1;
+extern statetype s_itemspawn1;
+extern statetype s_deadblood1;
+
+
+extern statetype s_flash1;
+
+extern statetype s_elevdisk;
+extern statetype s_pathdisk;
+extern statetype s_megaremove;
+
+extern statetype s_respawn1;
+extern statetype s_basemarker1;
+
+extern statetype s_blooddrip1;
+
+extern statetype s_diskmaster;
+extern statetype s_bstar1;
+
+
+#if (SHAREWARE == 0)
+
+extern statetype s_scottwander1;
+extern statetype s_scottwanderdoor1;
+
+extern statetype s_opstand;
+extern statetype s_oppath1;
+extern statetype s_opcollide;
+extern statetype s_opcollide2;
+extern statetype s_opgiveup;
+//extern statetype s_opuse1;
+extern statetype s_opshoot1;
+extern statetype s_opbolo1;
+extern statetype s_bolocast1;
+extern statetype s_opchase1;
+extern statetype s_opdie1;
+
+extern statetype s_opdie5rev;
+
+extern statetype s_opcrushed1;
+
+
+extern statetype s_dmonkstand;
+extern statetype s_dmonkpath1;
+extern statetype s_dmonkshoot1;
+extern statetype s_dmonkshoot2;
+extern statetype s_dmonkchase1;
+extern statetype s_dmonkdie1;
+
+extern statetype s_dmonkdie4rev;
+
+extern statetype s_dmonkcollide;
+extern statetype s_dmonkcollide2;
+extern statetype s_dmonkcrushed1;
+extern statetype s_dmonkshoot5;
+extern statetype s_dmonkshoot3;
+extern statetype s_dmonkshoot4;
+
+
+extern statetype s_firemonkstand;
+extern statetype s_firemonkpath1;
+extern statetype s_firemonkcast1;
+extern statetype s_monkfire1;
+extern statetype s_fireballhit1;
+extern statetype s_firemonkchase1;
+extern statetype s_firemonkdie1;
+
+extern statetype s_firemonkdie4rev;
+
+extern statetype s_firemonkcollide;
+extern statetype s_firemonkcollide2;
+extern statetype s_firemonkcrushed1;
+
+
+extern statetype s_wallstand;
+extern statetype s_wallpath;
+extern statetype s_wallshoot;
+extern statetype s_wallcollide;
+extern statetype s_wallalign;
+extern statetype s_wallwait;
+extern statetype s_wallrestore;
+
+
+extern statetype s_darianstand;
+extern statetype s_darianchase1;
+extern statetype s_darianuse;
+extern statetype s_darianshoot1;
+extern statetype s_dariancollide;
+extern statetype s_dariancollide2;
+extern statetype s_dariandie1;
+extern statetype s_darianspears;
+extern statetype s_darianuse1;
+extern statetype s_dariansink1;
+extern statetype s_dariansink9;
+extern statetype s_darianrise1;
+extern statetype s_darianwait;
+extern statetype s_dariandefend1;
+
+
+extern statetype s_heinrichstand;
+extern statetype s_heinrichshoot1;
+extern statetype s_heinrichshoot4;
+extern statetype s_heinrichshoot9;
+extern statetype s_heinrichooc;
+extern statetype s_heinrichchase;
+extern statetype s_heinexp1;
+extern statetype s_kristleft;
+extern statetype s_kristright;
+
+
+extern statetype s_missile1;
+extern statetype s_missilehit1;
+extern statetype s_mine1;
+extern statetype s_heinrichchase1;
+extern statetype s_heinrichuse;
+extern statetype s_heinrichmine;
+extern statetype s_heinrichdie1;
+extern statetype s_heinrichdead;
+extern statetype s_heinrichdefend;
+
+extern statetype s_dexplosion22;
+extern statetype s_dexplosion21;
+extern statetype s_dexplosion20;
+extern statetype s_dexplosion19;
+extern statetype s_dexplosion18;
+extern statetype s_dexplosion17;
+extern statetype s_dexplosion16;
+extern statetype s_dexplosion15;
+extern statetype s_dexplosion14;
+extern statetype s_dexplosion13;
+extern statetype s_dexplosion12;
+extern statetype s_dexplosion11;
+extern statetype s_dexplosion10;
+extern statetype s_dexplosion9;
+extern statetype s_dexplosion8;
+extern statetype s_dexplosion7;
+extern statetype s_dexplosion6;
+extern statetype s_dexplosion5;
+extern statetype s_dexplosion4;
+extern statetype s_dexplosion3;
+extern statetype s_dexplosion2;
+extern statetype s_dexplosion1;
+extern statetype s_dspear1;
+
+
+
+extern statetype s_NMEchase;
+extern statetype s_NMEdie;
+extern statetype s_NMEhead1;
+extern statetype s_NMEhead2;
+extern statetype s_NMEwheels1;
+extern statetype s_NMEwheels2;
+extern statetype s_NMEwheels3;
+extern statetype s_NMEwheels4;
+extern statetype s_NMEwheels5;
+extern statetype s_NMEwindup;
+extern statetype s_NMEwheels120;
+
+extern statetype s_NMEwrotleft3;
+extern statetype s_NMEwrotleft2;
+extern statetype s_NMEwrotleft1;
+
+extern statetype s_NMEwrotright3;
+extern statetype s_NMEwrotright2;
+extern statetype s_NMEwrotright1;
+extern statetype s_NMEminiball1;
+extern statetype s_NMEattack;
+extern statetype s_NMEsaucer1;
+extern statetype s_NMEhead1rl;
+extern statetype s_NMEhead2rl;
+extern statetype s_NMEspinattack;
+extern statetype s_NMEwheelspin;
+extern statetype s_NMEcollide;
+extern statetype s_NMEdeathbuildup;
+extern statetype s_NMEheadexplosion;
+extern statetype s_NMEstand;
+extern statetype s_NMEspinfire;
+extern statetype s_shootinghead;
+extern statetype s_oshuriken1;
+extern statetype s_oshurikenhit1;
+
+
+
+
+extern statetype s_darkmonkstand;
+extern statetype s_darkmonkcharge1;
+extern statetype s_darkmonkreact;
+extern statetype s_darkmonkland;
+extern statetype s_darkmonkchase1;
+extern statetype s_darkmonkcover1;
+extern statetype s_darkmonkawaken1;
+extern statetype s_darkmonklightning1;
+extern statetype s_darkmonkfspark1;
+extern statetype s_darkmonkbreathe1;
+extern statetype s_darkmonksummon1;
+extern statetype s_darkmonkhead;
+extern statetype s_darkmonkhspawn;
+extern statetype s_darkmonksneer1;
+extern statetype s_darkmonkheadhappy;
+extern statetype s_darkmonkheaddie1;
+extern statetype s_darkmonkhball1;
+extern statetype s_darkmonksphere1;
+extern statetype s_darkmonksphere8;
+extern statetype s_darkmonkbball1;
+extern statetype s_darkmonkscare1;
+extern statetype s_darkmonkdie1;
+extern statetype s_darkmonkredhead;
+extern statetype s_redheadhit;
+extern statetype s_darkmonksnakelink;
+extern statetype s_darkmonkredlink;
+extern statetype s_redlinkhit;
+extern statetype s_energysphere1;
+extern statetype s_lightning;
+extern statetype s_handball2;
+extern statetype s_handball1;
+extern statetype s_faceball2;
+extern statetype s_faceball1;
+extern statetype s_floorspark1;
+extern statetype s_dmlandandfire;
+
+extern statetype s_darkmonkhball7;
+extern statetype s_darkmonkbball7;
+extern statetype s_darkmonklightning9;
+extern statetype s_darkmonkfspark5;
+extern statetype s_darkmonkbreathe6;
+extern statetype s_darkmonkabsorb1;
+extern statetype s_dmgreenthing1;
+extern statetype s_dmgreenthing8;
+extern statetype s_darkmonkfastspawn;
+extern statetype s_spit1;
+extern statetype s_spithit1;
+extern statetype s_snakefire1;
+extern statetype s_snakepath;
+extern statetype s_snakefindpath;
+extern statetype s_snakefireworks1;
+extern statetype s_snakefireworks2;
+
+
+extern statetype s_speardown1;
+
+
+extern statetype s_downblade1;
+
+
+extern statetype s_firejetdown1;
+
+extern statetype s_columnupup1;
+extern statetype s_columnupup2;
+extern statetype s_columnupup8;
+extern statetype s_columnupup7;
+extern statetype s_columnupdown1;
+extern statetype s_columnupdown6;
+
+extern statetype s_spinupblade1;
+extern statetype s_spindownblade1;
+
+extern statetype s_boulderdrop12;
+extern statetype s_boulderdrop10;
+extern statetype s_boulderdrop8;
+
+
+extern statetype s_boulderdrop1;
+extern statetype s_boulderspawn;
+extern statetype s_bouldersink1;
+extern statetype s_boulderroll1;
+
+extern statetype s_gunfire1;
+extern statetype s_gunfire2;
+extern statetype s_gundie1;
+extern statetype s_gunstand;
+extern statetype s_gunraise1;
+extern statetype s_gunlower1;
+extern statetype s_4waygunfire1;
+extern statetype s_4waygunfire2;
+extern statetype s_4waygun;
+
+
+extern statetype s_kessphere1;
+extern statetype s_batblast1;
+extern statetype s_slop1;
+
+
+
+extern statetype s_serialdog4;
+extern statetype s_serialdog3;
+extern statetype s_serialdog2;
+extern statetype s_serialdog;
+extern statetype s_serialdogattack;
+extern statetype s_doguse;
+extern statetype s_doglick;
+extern statetype s_dogwait;
+
+
+
+#endif
+
+
+
+
+
+
+#endif
--- /dev/null
+++ b/rott/stdout.txt
@@ -1,0 +1,14 @@
+Rise of the Triad Startup Version 1.4
+ Commercial Version
+Z_INIT: 8950000 bytes
+IN_Startup: Mouse Present
+ Adding DARKWAR.WAD.
+ Adding REMOTE1.RTS.
+W_Wad: Wad Manager Started NUMLUMPS=3904
+RT_DRAW: Tables Initialized
+MU_Startup:
+SD_SetupFXCard: Fx ok.
+SD_Startup: Fx ok.
+RT_MAIN: Fonts Initialized
+RT_MSG: Message System Started
+RT_VIEW: Colormaps Initialized
--- /dev/null
+++ b/rott/task_man.h
@@ -1,0 +1,69 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+/**********************************************************************
+ module: TASK_MAN.C
+
+ author: James R. Dose
+ phone: (214)-271-1365 Ext #221
+ date: July 25, 1994
+
+ Public header for TASK_MAN.C, a low level timer task scheduler.
+
+ (c) Copyright 1994 James R. Dose. All Rights Reserved.
+**********************************************************************/
+
+#ifndef __TASK_MAN_H
+#define __TASK_MAN_H
+
+enum TASK_ERRORS
+{
+ TASK_Warning = -2,
+ TASK_Error = -1,
+ TASK_Ok = 0
+};
+
+typedef struct task
+{
+ struct task *next;
+ struct task *prev;
+ void ( *TaskService )( struct task * );
+ void *data;
+ long rate;
+ volatile long count;
+ int priority;
+ int active;
+} task;
+
+// TS_InInterrupt is TRUE during a taskman interrupt.
+// Use this if you have code that may be used both outside
+// and within interrupts.
+
+extern volatile int TS_InInterrupt;
+
+void TS_Shutdown( void );
+task *TS_ScheduleTask( void ( *Function )( task * ), int rate,
+ int priority, void *data );
+int TS_Terminate( task *ptr );
+void TS_Dispatch( void );
+void TS_SetTaskRate( task *Task, int rate );
+void TS_UnlockMemory( void );
+int TS_LockMemory( void );
+
+#endif
--- /dev/null
+++ b/rott/version.h
@@ -1,0 +1,28 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef VERSION_H
+#define VERSION_H
+
+#define ROTTMAJORVERSION 1
+#define ROTTMINORVERSION 4
+#define ROTTVERSION ((ROTTMAJORVERSION*10)+(ROTTMINORVERSION))
+
+#endif
--- /dev/null
+++ b/rott/w_wad.c
@@ -1,0 +1,544 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// W_wad.c
+
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#if PLATFORM_DOS
+#include <malloc.h>
+#include <conio.h>
+#include <io.h>
+#endif
+
+#include "rt_def.h"
+#include "rt_util.h"
+#include "_w_wad.h"
+#include "w_wad.h"
+#include "z_zone.h"
+#include "isr.h"
+#include "develop.h"
+
+#include "rt_crc.h"
+#include "rt_main.h"
+
+//=============
+// GLOBALS
+//=============
+
+int numlumps;
+void **lumpcache;
+
+//=============
+// STATICS
+//=============
+
+static lumpinfo_t *lumpinfo; // location of each lump on disk
+
+
+#if (DATACORRUPTIONTEST == 1)
+static byte *lumpcheck;
+#endif
+
+/*
+============================================================================
+
+ LUMP BASED ROUTINES
+
+============================================================================
+*/
+
+/*
+====================
+=
+= W_AddFile
+=
+= All files are optional, but at least one file must be found
+= Files with a .wad extension are wadlink files with multiple lumps
+= Other files are single lumps with the base filename for the lump name
+=
+====================
+*/
+
+void W_AddFile (char *_filename)
+{
+ wadinfo_t header;
+ lumpinfo_t *lump_p;
+ unsigned i;
+ int handle, length;
+ int startlump;
+ filelump_t *fileinfo, singleinfo;
+
+ char filename[MAX_PATH];
+ char buf[MAX_PATH+100];//bna++
+
+ strncpy(filename, _filename, sizeof (filename));
+ filename[sizeof (filename) - 1] = '\0';
+ FixFilePath(filename);
+
+ //bna section start
+ if (access (filename, 0) != 0) {
+ strcpy (buf,"Error, Could not find User file '");
+ strcat (buf,filename);
+ strcat (buf,"', ignoring file");
+ printf("%s", buf);
+ }
+ //bna section end
+
+//
+// read the entire file in
+// FIXME: shared opens
+
+#ifdef PLATFORM_DOS
+ if ( (handle = open (filename,O_RDWR | O_BINARY)) == -1)
+#else
+ if ( (handle = open (filename,O_RDONLY | O_BINARY)) == -1)
+#endif
+ return;
+
+ startlump = numlumps;
+
+ if ( (strcmpi (filename+strlen(filename)-3, "wad" ) ) &&
+ (strcmpi (filename+strlen(filename)-3, "rts" ) ) )
+ {
+ // single lump file
+ if (!quiet)
+ printf(" Adding single file %s.\n",filename);
+ fileinfo = &singleinfo;
+ singleinfo.filepos = 0;
+ singleinfo.size = LONG(filelength(handle));
+ ExtractFileBase (filename, singleinfo.name);
+ numlumps++;
+ }
+ else
+ {
+ // WAD file
+ if (!quiet)
+ printf(" Adding %s.\n",filename);
+ read (handle, &header, sizeof(header));
+ if (strncmp(header.identification,"IWAD",4))
+ Error ("Wad file %s doesn't have IWAD id\n",filename);
+ header.numlumps = IntelLong(LONG(header.numlumps));
+ header.infotableofs = IntelLong(LONG(header.infotableofs));
+ length = header.numlumps*sizeof(filelump_t);
+ fileinfo = alloca (length);
+ if (!fileinfo)
+ Error ("Wad file could not allocate header info on stack");
+ lseek (handle, header.infotableofs, SEEK_SET);
+ read (handle, fileinfo, length);
+
+ numlumps += header.numlumps;
+ }
+
+//
+// Fill in lumpinfo
+//
+ Z_Realloc((void **)&lumpinfo,numlumps*sizeof(lumpinfo_t));
+// lumpinfo = realloc (lumpinfo, numlumps*sizeof(lumpinfo_t));
+// if (!lumpinfo)
+// Error("W_AddFile: Could not realloc %ld bytes",numlumps*sizeof(lumpinfo_t));
+ lump_p = &lumpinfo[startlump];
+
+ for (i=startlump ; i<(unsigned int)numlumps ; i++,lump_p++, fileinfo++)
+ {
+ fileinfo->filepos = IntelLong(LONG(fileinfo->filepos));
+ fileinfo->size = IntelLong(LONG(fileinfo->size));
+ lump_p->handle = handle;
+ lump_p->position = LONG(fileinfo->filepos);
+ lump_p->size = LONG(fileinfo->size);
+ strncpy (lump_p->name, fileinfo->name, 8);
+ }
+}
+
+
+
+/*
+====================
+=
+= W_CheckWADIntegrity
+=
+====================
+*/
+
+void W_CheckWADIntegrity ( void )
+{
+ int crc;
+
+// CRC disabled because it's not very useful these days
+
+#ifdef DOS
+ crc = CalculateCRC ((byte *)lumpinfo, numlumps*sizeof(lumpinfo_t) );
+
+ if (crc != WADCHECKSUM)
+ {
+ printf("==============================================================================\n");
+ printf("ATTENTION: This version of ROTT has been modified. If you would like to get\n");
+ printf("a copy of the original game, call 1-800-APOGEE1 or run ROTTHELP.EXE.\n");
+ printf(" You will not receive technical support for this modified version.\n");
+// printf(" Press any key to continue\n");
+ printf("==============================================================================\n");
+// printf("crc=%ld\n",crc);
+// getch();
+ }
+#endif
+}
+
+
+
+/*
+====================
+=
+= W_InitMultipleFiles
+=
+= Pass a null terminated list of files to use.
+=
+= All files are optional, but at least one file must be found
+=
+= Files with a .wad extension are idlink files with multiple lumps
+=
+= Other files are single lumps with the base filename for the lump name
+=
+= Lump names can appear multiple times. The name searcher looks backwards,
+= so a later file can override an earlier one.
+=
+====================
+*/
+
+void W_InitMultipleFiles (char **filenames)
+{
+//
+// open all the files, load headers, and count lumps
+//
+ numlumps = 0;
+ lumpinfo = SafeMalloc(5); // will be realloced as lumps are added
+
+ for ( ; *filenames ; filenames++)
+ W_AddFile (*filenames);
+
+ if (!numlumps)
+ Error ("W_InitFiles: no files found");
+
+//
+// set up caching
+//
+ lumpcache = calloc (numlumps, sizeof(*lumpcache));
+ if (!lumpcache)
+ Error("W_InitFiles: lumpcache malloc failed size=%d\n",numlumps<<2);
+
+ if (!quiet)
+ printf("W_Wad: Wad Manager Started NUMLUMPS=%ld\n",(long int)numlumps);
+#if (DATACORRUPTIONTEST == 1)
+ lumpcheck=SafeMalloc(numlumps);
+ memset(lumpcheck,255,numlumps);
+#endif
+#ifdef DOS
+ if (!SOUNDSETUP)
+#endif
+ W_CheckWADIntegrity ();
+}
+
+
+
+
+/*
+====================
+=
+= W_InitFile
+=
+= Just initialize from a single file
+=
+====================
+*/
+
+void W_InitFile (char *filename)
+{
+ char *names[2];
+
+ names[0] = filename;
+ names[1] = NULL;
+ W_InitMultipleFiles (names);
+}
+
+
+
+/*
+====================
+=
+= W_NumLumps
+=
+====================
+*/
+
+int W_NumLumps (void)
+{
+ return numlumps;
+}
+
+
+
+/*
+====================
+=
+= W_CheckNumForName
+=
+= Returns -1 if name not found
+=
+====================
+*/
+
+int W_CheckNumForName (char *name)
+{
+ char name8[9];
+ int v1,v2;
+ lumpinfo_t *lump_p;
+ lumpinfo_t *endlump;
+
+// make the name into two integers for easy compares
+
+ strncpy (name8,name,8);
+ name8[8] = 0; // in case the name was a fill 8 chars
+ strupr (name8); // case insensitive
+
+ v1 = *(int *)name8;
+ v2 = *(int *)&name8[4];
+
+
+// scan backwards so patch lump files take precedence
+
+ lump_p = lumpinfo;
+ endlump = lumpinfo + numlumps;
+
+ while (lump_p != endlump)
+ {
+ if ( *(int *)lump_p->name == v1 && *(int *)&lump_p->name[4] == v2)
+ return lump_p - lumpinfo;
+ lump_p++;
+ }
+
+
+ return -1;
+}
+
+
+/*
+====================
+=
+= W_GetNumForName
+=
+= Calls W_CheckNumForName, but bombs out if not found
+=
+====================
+*/
+
+int W_GetNumForName (char *name)
+{
+ int i;
+
+ i = W_CheckNumForName (name);
+ if (i != -1)
+ return i;
+
+ Error ("W_GetNumForName: %s not found!",name);
+ return -1;
+}
+
+
+/*
+====================
+=
+= W_LumpLength
+=
+= Returns the buffer size needed to load the given lump
+=
+====================
+*/
+
+int W_LumpLength (int lump)
+{
+ if (lump >= numlumps)
+ Error ("W_LumpLength: %i >= numlumps",lump);
+ return lumpinfo[lump].size;
+}
+
+/*
+====================
+=
+= W_GetNameForNum
+=
+====================
+*/
+
+char * W_GetNameForNum (int i)
+{
+
+ if (i>=numlumps)
+ Error ("W_GetNameForNum: %i >= numlumps",i);
+ return &(lumpinfo[i].name[0]);
+}
+
+/*
+====================
+=
+= W_ReadLump
+=
+= Loads the lump into the given buffer, which must be >= W_LumpLength()
+=
+====================
+*/
+int readinglump;
+byte * lumpdest;
+void W_ReadLump (int lump, void *dest)
+{
+ int c;
+ lumpinfo_t *l;
+
+ readinglump=lump;
+ lumpdest=dest;
+ if (lump >= numlumps)
+ Error ("W_ReadLump: %i >= numlumps",lump);
+ if (lump < 0)
+ Error ("W_ReadLump: %i < 0",lump);
+ l = lumpinfo+lump;
+
+ lseek (l->handle, l->position, SEEK_SET);
+ c = read (l->handle, dest, l->size);
+ if (c < l->size)
+ Error ("W_ReadLump: only read %i of %i on lump %i",c,l->size,lump);
+}
+
+
+/*
+====================
+=
+= W_WriteLump
+=
+= Writes the lump into the given buffer, which must be >= W_LumpLength()
+=
+====================
+*/
+
+void W_WriteLump (int lump, void *src)
+{
+ int c;
+ lumpinfo_t *l;
+
+ if (lump >= numlumps)
+ Error ("W_WriteLump: %i >= numlumps",lump);
+ if (lump < 0)
+ Error ("W_WriteLump: %i < 0",lump);
+ l = lumpinfo+lump;
+
+ lseek (l->handle, l->position, SEEK_SET);
+ c = write (l->handle, src, l->size);
+ if (c < l->size)
+ Error ("W_WriteLump: only wrote %i of %i on lump %i",c,l->size,lump);
+}
+
+
+/*
+====================
+=
+= W_CacheLumpNum
+=
+====================
+*/
+void *W_CacheLumpNum (int lump, int tag, converter_t converter, int numrec)
+{
+ if (lump >= (int)numlumps)
+ Error ("W_CacheLumpNum: %i >= numlumps",lump);
+
+ else if (lump < 0)
+ Error ("W_CacheLumpNum: %i < 0 Taglevel: %i",lump,tag);
+
+ if (!lumpcache[lump])
+ {
+ // read the lump in
+#if (PRECACHETEST == 1)
+ char str[9];
+ strncpy(&str[0],W_GetNameForNum(lump),8);
+ str[8]=0;
+ SoftError("Lump #%d, %s cached at %ld tics size=%ld tag=%ld\n",lump,str,ticcount,W_LumpLength (lump),tag);
+ if (W_LumpLength(lump)==0)
+ SoftError("Caching in zero length lump #%d, %s cached at %ld tics size=%ld tag=%ld\n",lump,str,ticcount,W_LumpLength (lump),tag);
+#endif
+
+#if (DATACORRUPTIONTEST == 1)
+ {
+ int length;
+
+ *(lumpcheck+lump)=CHECKPERIOD;
+ length=W_LumpLength(lump);
+ Z_Malloc (length+sizeof(word), tag, &lumpcache[lump]);
+ W_ReadLump (lump, lumpcache[lump]);
+ Debug("Invoking endian converter on %p, %i records.\n", lumpcache[lump], numrec);
+ converter(lumpcache[lump], numrec);
+
+ *( (word *) ((byte *)lumpcache[lump]+length) ) = CalculateCRC (lumpcache[lump], length);
+ }
+#else
+ Z_Malloc (W_LumpLength (lump), tag, &lumpcache[lump]);
+ W_ReadLump (lump, lumpcache[lump]);
+ Debug("Invoking endian converter on %p, %i records\n", lumpcache[lump], numrec);
+ converter(lumpcache[lump], numrec);
+#endif
+ }
+ else
+ {
+#if (DATACORRUPTIONTEST == 1)
+
+ if (*(lumpcheck+lump)==255)
+ Error("Tried using lump%ld before reading it in\n",lump);
+ (*(lumpcheck+lump))--;
+ if (*(lumpcheck+lump)==0)
+ {
+ word storedcrc;
+ word crc;
+ int length;
+
+ *(lumpcheck+lump)=CHECKPERIOD;
+
+ length=W_LumpLength(lump);
+ storedcrc = *( (word *) ((byte *)lumpcache[lump]+length) );
+ crc = CalculateCRC (lumpcache[lump], length);
+ if (crc!=storedcrc)
+ Error("Data corruption lump=%ld\n",lump);
+ }
+#endif
+ Z_ChangeTag (lumpcache[lump],tag);
+ }
+
+ return lumpcache[lump];
+}
+
+
+/*
+====================
+=
+= W_CacheLumpName
+=
+====================
+*/
+
+void *W_CacheLumpName (char *name, int tag, converter_t converter, int numrec)
+{
+ return W_CacheLumpNum (W_GetNumForName(name), tag, converter, numrec);
+}
--- /dev/null
+++ b/rott/w_wad.h
@@ -1,0 +1,51 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// W_WAD.C - Wad managment utilities
+//
+//***************************************************************************
+
+#ifndef _w_wad_public
+#define _w_wad_public
+
+#include "byteordr.h"
+
+void W_InitMultipleFiles (char **filenames); // Initialize multiple wads
+void W_InitFile (char *filename); // Init a single wad file
+
+int W_CheckNumForName (char *name); // Check to see if the named lump exists
+int W_GetNumForName (char *name); // Get the number for the named lump
+char * W_GetNameForNum (int i); // Get the name for a number
+
+int W_NumLumps (void); // Get the current number of lumps managed
+int W_LumpLength (int lump); // Get the length of the numbered lump
+void W_ReadLump (int lump, void *dest); // Read the numbered lump into a buffer
+void W_WriteLump (int lump, void *src);
+
+void *W_CacheLumpNum (int lump, int tag, converter_t converter, int numrecs);
+// Cache in the numbered lump with the appropriate memory tag
+void *W_CacheLumpName (char *name, int tag, converter_t converter, int numrecs);
+// Cache in the named lump with the appropriate memory tag
+
+extern int numlumps;
+extern void **lumpcache;
+
+#endif
--- /dev/null
+++ b/rott/watcom.c
@@ -1,0 +1,43 @@
+#include "rt_def.h"
+
+#include "watcom.h"
+
+/*
+ C versions of watcom.h assembly.
+ Uses the '__int64' type (see rt_def.h).
+ */
+
+fixed FixedMul(fixed a, fixed b)
+{
+ __int64 scratch1 = (__int64) a * (__int64) b + (__int64) 0x8000;
+ return (scratch1 >> 16) & 0xffffffff;
+}
+
+fixed FixedMulShift(fixed a, fixed b, fixed shift)
+{
+ __int64 x = a;
+ __int64 y = b;
+ __int64 z = x * y;
+
+ return (((unsigned __int64)z) >> shift) & 0xffffffff;
+}
+
+fixed FixedDiv2(fixed a, fixed b)
+{
+ __int64 x = (signed int)a;
+ __int64 y = (signed int)b;
+ __int64 z = x * 65536 / y;
+
+ return (z) & 0xffffffff;
+}
+
+fixed FixedScale(fixed orig, fixed factor, fixed divisor)
+{
+ __int64 x = orig;
+ __int64 y = factor;
+ __int64 z = divisor;
+
+ __int64 w = (x * y) / z;
+
+ return (w) & 0xffffffff;
+}
--- /dev/null
+++ b/rott/watcom.h
@@ -1,0 +1,59 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _watcom_h_public
+#define _watcom_h_public
+fixed FixedMul(fixed a, fixed b);
+fixed FixedDiv2(fixed a, fixed b);
+fixed FixedScale(fixed orig, fixed factor, fixed divisor);
+fixed FixedMulShift(fixed a, fixed b, fixed shift);
+#ifdef __WATCOMC__
+#pragma aux FixedMul = \
+ "imul ebx", \
+ "add eax, 8000h" \
+ "adc edx,0h" \
+ "shrd eax,edx,16" \
+ parm [eax] [ebx] \
+ value [eax] \
+ modify exact [eax edx]
+
+#pragma aux FixedMulShift = \
+ "imul ebx", \
+ "shrd eax,edx,cl" \
+ parm [eax] [ebx] [ecx]\
+ value [eax] \
+ modify exact [eax edx]
+
+#pragma aux FixedDiv2 = \
+ "cdq", \
+ "shld edx,eax,16", \
+ "sal eax,16", \
+ "idiv ebx" \
+ parm [eax] [ebx] \
+ value [eax] \
+ modify exact [eax edx]
+#pragma aux FixedScale = \
+ "imul ebx", \
+ "idiv ecx" \
+ parm [eax] [ebx] [ecx]\
+ value [eax] \
+ modify exact [eax edx]
+#endif
+
+#endif
--- /dev/null
+++ b/rott/winrott.c
@@ -1,0 +1,170 @@
+/* Routines from winrott needed for the highres support for the SDL port */
+#include <stdlib.h>
+#include <string.h>
+#include "WinRott.h"
+#include "modexlib.h"
+
+//typedef unsigned char byte;
+
+int iGLOBAL_SCREENWIDTH = 640;//bna val 800
+int iGLOBAL_SCREENHEIGHT = 480;//bna val 600
+int iGLOBAL_SCREENBWIDE ;
+int iG_SCREENWIDTH;// default screen width in bytes
+
+int iGLOBAL_HEALTH_X;
+int iGLOBAL_HEALTH_Y;
+int iGLOBAL_AMMO_X;
+int iGLOBAL_AMMO_Y;
+
+int iGLOBAL_FOCALWIDTH;
+double dGLOBAL_FPFOCALWIDTH;
+
+double dTopYZANGLELIMIT;
+
+int iG_X_center;
+int iG_Y_center;
+
+//int topBarCenterOffset = 0;
+
+boolean iG_aimCross = 0;
+
+extern int viewheight;
+extern int viewwidth;
+
+//----------------------------------------------------------------------
+#define FINEANGLES 2048
+void SetRottScreenRes (int Width, int Height)
+{
+
+ iGLOBAL_SCREENWIDTH = Width;
+ iGLOBAL_SCREENHEIGHT = Height;
+
+
+ iGLOBAL_SCREENBWIDE = iGLOBAL_SCREENWIDTH*(96/320);
+ iG_SCREENWIDTH = iGLOBAL_SCREENWIDTH*(96/320);;// default screen width in bytes
+
+ if (iGLOBAL_SCREENWIDTH == 320) {
+ iGLOBAL_FOCALWIDTH = 160;
+ dGLOBAL_FPFOCALWIDTH = 160.0;
+ iGLOBAL_HEALTH_X = 20;
+ iGLOBAL_HEALTH_Y = 185;
+ iGLOBAL_AMMO_X = 300;
+ iGLOBAL_AMMO_Y = 184;
+
+ dTopYZANGLELIMIT = (44*FINEANGLES/360);;
+ }
+ if (iGLOBAL_SCREENWIDTH == 640) {
+ iGLOBAL_FOCALWIDTH = 180;
+ dGLOBAL_FPFOCALWIDTH = 180.0 ;
+ iGLOBAL_HEALTH_X = 40;//20*2;
+ iGLOBAL_HEALTH_Y = 466;//(185*2)+16;
+ iGLOBAL_AMMO_X = 600;//300*2;
+ iGLOBAL_AMMO_Y = 464;//480-16;
+
+ dTopYZANGLELIMIT = (42*FINEANGLES/360);;
+ }
+ if (iGLOBAL_SCREENWIDTH == 800) {
+ iGLOBAL_FOCALWIDTH = 200;
+ dGLOBAL_FPFOCALWIDTH = 200.0 ;
+ iGLOBAL_HEALTH_X = 40;//20*2;
+ iGLOBAL_HEALTH_Y = 585;//(185/200)*600;
+ iGLOBAL_AMMO_X = 750;//(300/320)*800;
+ iGLOBAL_AMMO_Y = 584;//600-16;
+
+ dTopYZANGLELIMIT = (90*FINEANGLES/360);;
+ }
+
+ //dYZANGLELIMIT = (12*FINEANGLES/360);
+ //#define YZANGLELIMIT (12*FINEANGLES/360)//bna--(30*FINEANGLES/360)
+
+ //#define TopYZANGLELIMIT (44*FINEANGLES/360)//bna added
+
+// GetCurrentDirectory(sizeof(ApogeePath),ApogeePath);// curent directory name
+
+}
+
+//----------------------------------------------------------------------
+//luckey for me that I am not programmin a 386 or the next
+//4 function would never have worked. bna++
+extern int viewsize;
+void MoveScreenUpLeft()
+{
+ int startX,startY,startoffset;
+ byte *Ycnt,*b;
+// SetTextMode ( );
+ b=(byte *)bufferofs;
+ b += (((iGLOBAL_SCREENHEIGHT-viewheight)/2)*iGLOBAL_SCREENWIDTH)+((iGLOBAL_SCREENWIDTH-viewwidth)/2);
+ if (viewsize == 8) {
+ b += 8*iGLOBAL_SCREENWIDTH;
+ }
+ startX = 3; //take 3 pixels to the right
+ startY = 3; //take 3 lines down
+ startoffset = (startY*iGLOBAL_SCREENWIDTH)+startX;
+
+ for (Ycnt=b; Ycnt<b+((viewheight-startY)*iGLOBAL_SCREENWIDTH); Ycnt+=iGLOBAL_SCREENWIDTH) {
+ memcpy(Ycnt,Ycnt+startoffset, viewwidth-startX);
+ }
+}
+//----------------------------------------------------------------------
+void MoveScreenDownLeft()
+{
+ int startX,startY,startoffset;
+ byte *Ycnt,*b;
+// SetTextMode ( );
+ b=(byte *)bufferofs;
+ b += (((iGLOBAL_SCREENHEIGHT-viewheight)/2)*iGLOBAL_SCREENWIDTH)+((iGLOBAL_SCREENWIDTH-viewwidth)/2);
+ if (viewsize == 8) {
+ b += 8*iGLOBAL_SCREENWIDTH;
+ }
+ startX = 3; //take 3 pixels to the right
+ startY = 3; //take 3 lines down
+ startoffset = (startY*iGLOBAL_SCREENWIDTH);//+startX;
+
+ //Ycnt starts in botton of screen and copys lines upwards
+ for (Ycnt=b+((viewheight-startY-1)*iGLOBAL_SCREENWIDTH); Ycnt>b; Ycnt-=iGLOBAL_SCREENWIDTH) {
+ memcpy(Ycnt+startoffset,Ycnt+startX,viewwidth-startX);
+ }
+}
+//----------------------------------------------------------------------
+void MoveScreenUpRight()
+{
+ int startX,startY,startoffset;
+ byte *Ycnt,*b;
+// SetTextMode ( );
+ b=(byte *)bufferofs;
+
+ b += (((iGLOBAL_SCREENHEIGHT-viewheight)/2)*iGLOBAL_SCREENWIDTH)+((iGLOBAL_SCREENWIDTH-viewwidth)/2);
+ if (viewsize == 8) {
+ b += 8*iGLOBAL_SCREENWIDTH;
+ }
+ startX = 3; //take 3 pixels to the right
+ startY = 3; //take 3 lines down
+ startoffset = (startY*iGLOBAL_SCREENWIDTH);//+startX;
+
+ for (Ycnt=b; Ycnt<b+((viewheight-startY)*iGLOBAL_SCREENWIDTH); Ycnt+=iGLOBAL_SCREENWIDTH) {
+ memcpy(Ycnt+startX,Ycnt+startoffset, viewwidth-startX);
+ }
+}
+//----------------------------------------------------------------------
+void MoveScreenDownRight()
+{
+ int startX,startY,startoffset;
+ byte *Ycnt,*b;
+// SetTextMode ( );
+ b=(byte *)bufferofs;
+
+ b += (((iGLOBAL_SCREENHEIGHT-viewheight)/2)*iGLOBAL_SCREENWIDTH)+((iGLOBAL_SCREENWIDTH-viewwidth)/2);
+ if (viewsize == 8) {
+ b += 8*iGLOBAL_SCREENWIDTH;
+ }
+ startX = 3; //take 3 pixels to the right
+ startY = 3; //take 3 lines down
+ startoffset = (startY*iGLOBAL_SCREENWIDTH)+startX;
+
+ //Ycnt starts in botton of screen and copys lines upwards
+ for (Ycnt=b+((viewheight-startY-1)*iGLOBAL_SCREENWIDTH); Ycnt>b; Ycnt-=iGLOBAL_SCREENWIDTH) {
+ memcpy(Ycnt+startoffset,Ycnt,viewwidth-startX);
+ }
+}
+
+
--- /dev/null
+++ b/rott/z_zone.c
@@ -1,0 +1,798 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// Z_zone.c
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef DOS
+#include <dos.h>
+#include <conio.h>
+#endif
+
+#include "rt_def.h"
+#include "_z_zone.h"
+#include "z_zone.h"
+#include "rt_util.h"
+#include "develop.h"
+#include "rt_net.h"
+
+#if (DEVELOPMENT == 1)
+#include "rt_main.h"
+#endif
+//MED
+#include "memcheck.h"
+
+int lowmemory=0;
+
+/*
+==============================================================================
+
+ ZONE MEMORY ALLOCATION
+
+There is never any space between memblocks, and there will never be two
+contiguous free memblocks.
+
+The rover can be left pointing at a non-empty block
+
+It is of no value to free a cachable block, because it will get overwritten
+automatically if needed
+
+==============================================================================
+*/
+
+//Globals
+
+int zonememorystarted=0;
+
+// Statics
+
+static memzone_t *mainzone;
+static memzone_t *levelzone;
+static int levelzonesize=LEVELZONESIZE;
+static struct meminfo
+{
+ unsigned LargestBlockAvail;
+ unsigned MaxUnlockedPage;
+ unsigned LargestLockablePage;
+ unsigned LinAddrSpace;
+ unsigned NumFreePagesAvail;
+ unsigned NumPhysicalPagesFree;
+ unsigned TotalPhysicalPages;
+ unsigned FreeLinAddrSpace;
+ unsigned SizeOfPageFile;
+ unsigned Reserved[3];
+} MemInfo;
+
+/*
+========================
+=
+= Z_ClearZone
+=
+========================
+*/
+
+void Z_ClearZone (memzone_t *zone)
+{
+ memblock_t *block;
+
+// set the entire zone to one free block
+
+ zone->blocklist.next = zone->blocklist.prev = block =
+ (memblock_t *)( (byte *)zone + sizeof(memzone_t) );
+ zone->blocklist.user = (void *)zone;
+ zone->blocklist.tag = PU_STATIC;
+ zone->rover = block;
+
+ block->prev = block->next = &zone->blocklist;
+ block->user = NULL; // free block
+ block->size = zone->size - sizeof(memzone_t);
+}
+
+
+/*
+========================
+=
+= Z_AllocateZone
+=
+========================
+*/
+
+memzone_t *Z_AllocateZone (int size)
+{
+ memzone_t *header;
+
+ header = malloc (size+sizeof(memzone_t));
+ if (!header)
+ Error ("Z_AllocateZone: Couldn't malloc %zd bytes avail=%d\n",
+ size+sizeof(memzone_t), Z_AvailHeap());
+ header->size = size;
+ Z_ClearZone (header);
+ return header;
+}
+
+/*
+========================
+=
+= Z_Init
+=
+========================
+*/
+void Z_Init (int size, int min)
+{
+ int maxsize;
+ int sz;
+
+ if (zonememorystarted==1)
+ return;
+ zonememorystarted=1;
+
+ sz = GamePacketSize();
+
+ sz*=MAXCMDS;
+
+ if (ConsoleIsServer() == true)
+ levelzonesize+=((numplayers*2)+1)*sz;
+ else
+ levelzonesize+=(numplayers+1)*sz;
+
+ maxsize=((int)(Z_AvailHeap())-size-levelzonesize);
+ if (maxsize<min)
+ {
+ UL_DisplayMemoryError (min-maxsize);
+ }
+ if (maxsize>MAXMEMORYSIZE)
+ maxsize=(MAXMEMORYSIZE-levelzonesize);
+
+ mainzone = Z_AllocateZone (maxsize);
+ levelzone = Z_AllocateZone (levelzonesize);
+
+ if (!quiet)
+ printf("Z_INIT: %ld bytes\n",(long int)(maxsize+levelzonesize));
+
+ if (maxsize<(min+(min>>1)))
+ {
+ lowmemory = 1;
+
+ printf("==============================================================================\n");
+ printf("WARNING: You are running ROTT with very little memory. ROTT runs best with\n");
+ printf("8 Megabytes of memory and no TSR's loaded in memory. If you can free up more\n");
+ printf("memory for ROTT then you should press CTRL-BREAK at this time. If you are\n");
+ printf("unable to do this you will experience momentary pauses in game-play whenever\n");
+ printf("you enter new areas of the game as well as an overall decreased performance.\n");
+ printf(" Press any key to continue\n");
+ printf("==============================================================================\n");
+ getch();
+ }
+}
+
+/*
+========================
+=
+= Z_ShutDown
+=
+========================
+*/
+
+void Z_ShutDown( void )
+{
+ if (zonememorystarted==0)
+ return;
+ zonememorystarted=0;
+ free(mainzone);
+ free(levelzone);
+}
+
+/*
+========================
+=
+= Z_GetSize
+=
+========================
+*/
+
+int Z_GetSize (void *ptr)
+{
+ memblock_t *block;
+
+ block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
+ return (block->size - sizeof(memblock_t));
+}
+
+
+/*
+========================
+=
+= Z_Free
+=
+========================
+*/
+
+void Z_Free (void *ptr)
+{
+ memblock_t *block, *other;
+
+ block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
+ if (!block->user)
+ Error ("Z_Free: freed a freed pointer");
+
+ if (block->user > (void **)0x100) // smaller values are not pointers
+ *block->user = 0; // clear the user's mark
+ block->user = NULL; // mark as free
+
+ other = block->prev;
+ if (!other->user)
+ { // merge with previous free block
+ other->size += block->size;
+ other->next = block->next;
+ other->next->prev = other;
+ if (block == mainzone->rover)
+ mainzone->rover = other;
+ else if (block == levelzone->rover)
+ levelzone->rover = other;
+ block = other;
+ }
+
+ other = block->next;
+ if (!other->user)
+ { // merge the next free block onto the end
+ block->size += other->size;
+ block->next = other->next;
+ block->next->prev = block;
+ if (other == mainzone->rover)
+ mainzone->rover = block;
+ else if (other == levelzone->rover)
+ levelzone->rover = block;
+ }
+}
+
+
+/*
+========================
+=
+= Z_Malloc
+=
+= You can pass a NULL user if the tag is < PU_PURGELEVEL
+========================
+*/
+
+#if (DEVELOPMENT == 1)
+int totallevelsize=0;
+#endif
+
+void *Z_Malloc (int size, int tag, void *user)
+{
+ int extra;
+ memblock_t *start, *rover, *new, *base;
+
+//
+// scan through the block list looking for the first free block
+// of sufficient size, throwing out any purgable blocks along the way
+//
+// size += sizeof(memblock_t); // account for size of block header
+ size = (size + sizeof(memblock_t) + 3)&~3; // account for size of block header
+
+
+//
+// if there is a free block behind the rover, back up over them
+//
+ base = mainzone->rover;
+ if (!base->prev->user)
+ base = base->prev;
+
+ rover = base;
+ start = base->prev;
+
+ do
+ {
+ if (rover == start) // scaned all the way around the list
+ {
+ SoftError("OHSHIT\n");
+ Z_DumpHeap(0,200);
+ Error ("Z_Malloc: failed on allocation of %i bytes",size);
+ }
+ if (rover->user)
+ {
+ if (rover->tag < PU_PURGELEVEL)
+ // hit a block that can't be purged, so move base past it
+ base = rover = rover->next;
+ else
+ {
+ // free the rover block (adding the size to base)
+ base = base->prev; // the rover can be the base block
+ Z_Free ((byte *)rover+sizeof(memblock_t));
+ base = base->next;
+ rover = base->next;
+ }
+ }
+ else
+ rover = rover->next;
+ } while (base->user || base->size < size);
+
+//
+// found a block big enough
+//
+ extra = base->size - size;
+ if (extra > MINFRAGMENT)
+ { // there will be a free fragment after the allocated block
+ new = (memblock_t *) ((byte *)base + size );
+ new->size = extra;
+ new->user = NULL; // free block
+ new->tag = 0;
+ new->prev = base;
+ new->next = base->next;
+ new->next->prev = new;
+ base->next = new;
+ base->size = size;
+ }
+
+ if (user)
+ {
+ base->user = user; // mark as an in use block
+ *(void **)user = (void *) ((byte *)base + sizeof(memblock_t));
+ }
+ else
+ {
+ if (tag >= PU_PURGELEVEL)
+ Error ("Z_Malloc: an owner is required for purgable blocks");
+ base->user = (void *)2; // mark as in use, but unowned
+ }
+ base->tag = tag;
+
+ mainzone->rover = base->next; // next allocation will start looking here
+
+
+#if (MEMORYCORRUPTIONTEST==1)
+ base->posttag=MEMORYPOSTTAG;
+ base->pretag=MEMORYPRETAG;
+#endif
+
+ return (void *) ((byte *)base + sizeof(memblock_t));
+}
+
+/*
+========================
+=
+= Z_LevelMalloc
+=
+= Only use this for level structures.
+= You can pass a NULL user if the tag is < PU_PURGELEVEL
+========================
+*/
+
+void *Z_LevelMalloc (int size, int tag, void *user)
+{
+ int extra;
+ memblock_t *start, *rover, *new, *base;
+
+//
+// scan through the block list looking for the first free block
+// of sufficient size, throwing out any purgable blocks along the way
+//
+// size += sizeof(memblock_t); // account for size of block header
+ size = (size + sizeof(memblock_t) + 3)&~3; // account for size of block header
+
+
+//
+// if there is a free block behind the rover, back up over them
+//
+ base = levelzone->rover;
+ if (!base->prev->user)
+ base = base->prev;
+
+ rover = base;
+ start = base->prev;
+
+ do
+ {
+ if (rover == start) // scaned all the way around the list
+ {
+ SoftError("OHSHIT\n");
+ Z_DumpHeap(0,200);
+ Error ("Z_LevelMalloc: failed on allocation of %i bytes",size);
+ }
+ if (rover->user)
+ {
+ if (rover->tag < PU_PURGELEVEL)
+ // hit a block that can't be purged, so move base past it
+ base = rover = rover->next;
+ else
+ {
+ // free the rover block (adding the size to base)
+ base = base->prev; // the rover can be the base block
+ Z_Free ((byte *)rover+sizeof(memblock_t));
+ base = base->next;
+ rover = base->next;
+ }
+ }
+ else
+ rover = rover->next;
+ } while (base->user || base->size < size);
+
+//
+// found a block big enough
+//
+ extra = base->size - size;
+ if (extra > MINFRAGMENT)
+ { // there will be a free fragment after the allocated block
+ new = (memblock_t *) ((byte *)base + size );
+ new->size = extra;
+ new->user = NULL; // free block
+ new->tag = 0;
+ new->prev = base;
+ new->next = base->next;
+ new->next->prev = new;
+ base->next = new;
+ base->size = size;
+ }
+
+ if (user)
+ {
+ base->user = user; // mark as an in use block
+ *(void **)user = (void *) ((byte *)base + sizeof(memblock_t));
+ }
+ else
+ {
+ if (tag >= PU_PURGELEVEL)
+ Error ("Z_Malloc: an owner is required for purgable blocks");
+ base->user = (void *)2; // mark as in use, but unowned
+ }
+ base->tag = tag;
+
+ levelzone->rover = base->next; // next allocation will start looking here
+
+#if (MEMORYCORRUPTIONTEST==1)
+ base->posttag=MEMORYPOSTTAG;
+ base->pretag=MEMORYPRETAG;
+#endif
+
+ return (void *) ((byte *)base + sizeof(memblock_t));
+}
+
+
+
+/*
+========================
+=
+= Z_FreeTags
+=
+========================
+*/
+
+void Z_FreeTags (int lowtag, int hightag)
+{
+ memblock_t *block, *next;
+
+ for (block = mainzone->blocklist.next ; block != &mainzone->blocklist
+ ; block = next)
+ {
+ next = block->next; // get link before freeing
+ if (!block->user)
+ continue; // free block
+ if (block->tag >= lowtag && block->tag <= hightag)
+ Z_Free ( (byte *)block+sizeof(memblock_t));
+ }
+ for (block = levelzone->blocklist.next ; block != &levelzone->blocklist
+ ; block = next)
+ {
+ next = block->next; // get link before freeing
+ if (!block->user)
+ continue; // free block
+ if (block->tag >= lowtag && block->tag <= hightag)
+ Z_Free ( (byte *)block+sizeof(memblock_t));
+ }
+}
+
+/*
+========================
+=
+= Z_DumpHeap
+=
+========================
+*/
+
+void Z_DumpHeap (int lowtag, int hightag)
+{
+ memblock_t *block;
+ int totalsize;
+
+ SoftError("MAIN ZONE\n");
+ SoftError("zone size: %i location: %p\n",mainzone->size,mainzone);
+ SoftError("tag range: %i to %i\n",lowtag, hightag);
+
+ totalsize=0;
+
+ for (block = mainzone->blocklist.next ; ; block = block->next)
+ {
+ if (block->tag >= lowtag && block->tag <= hightag)
+ {
+ SoftError("block:%p size:%7i user:%p tag:%3i\n",
+ block, block->size, block->user, block->tag);
+ totalsize+=block->size;
+ }
+
+ if (block->next == &mainzone->blocklist) {
+ break; // all blocks have been hit
+ }
+ if ( (byte *)block + block->size != (byte *)block->next) {
+ SoftError("ERROR: block size does not touch the next block\n");
+ }
+ if ( block->next->prev != block) {
+ SoftError("ERROR: next block doesn't have proper back link\n");
+ }
+ if (!block->user && !block->next->user) {
+ SoftError("ERROR: two consecutive free blocks\n");
+ }
+ }
+ SoftError("Total Size of blocks = %d\n",totalsize);
+
+ SoftError("LEVEL ZONE\n");
+ SoftError("zone size: %i location: %p\n",levelzone->size,levelzone);
+ SoftError("tag range: %i to %i\n",lowtag, hightag);
+
+ totalsize=0;
+
+ for (block = levelzone->blocklist.next ; ; block = block->next)
+ {
+ if (block->tag >= lowtag && block->tag <= hightag)
+ {
+ SoftError("block:%p size:%7i user:%p tag:%3i\n",
+ block, block->size, block->user, block->tag);
+ totalsize+=block->size;
+ }
+
+ if (block->next == &levelzone->blocklist)
+ break; // all blocks have been hit
+ if ( (byte *)block + block->size != (byte *)block->next) {
+ SoftError("ERROR: block size does not touch the next block\n");
+ }
+ if ( block->next->prev != block) {
+ SoftError("ERROR: next block doesn't have proper back link\n");
+ }
+ if (!block->user && !block->next->user) {
+ SoftError("ERROR: two consecutive free blocks\n");
+ }
+ }
+ SoftError("Total Size of blocks = %d\n",totalsize);
+
+}
+
+/*
+========================
+=
+= Z_UsedHeap
+=
+========================
+*/
+
+int Z_UsedHeap ( void )
+{
+ memblock_t *block;
+ int heapsize;
+
+
+ heapsize=0;
+ for (block = mainzone->blocklist.next ; ; block = block->next)
+ {
+ if ((block->tag>0) && (block->user>(void **)0))
+ heapsize+=(block->size);
+ if (block->next == &mainzone->blocklist)
+ break; // all blocks have been hit
+ }
+ return heapsize;
+}
+
+/*
+========================
+=
+= Z_UsedLevelHeap
+=
+========================
+*/
+
+int Z_UsedLevelHeap ( void )
+{
+ memblock_t *block;
+ int heapsize;
+
+
+ heapsize=0;
+ for (block = levelzone->blocklist.next ; ; block = block->next)
+ {
+ if ((block->tag>0) && (block->user>(void **)0))
+ heapsize+=(block->size);
+ if (block->next == &levelzone->blocklist)
+ break; // all blocks have been hit
+ }
+ return heapsize;
+}
+
+
+/*
+========================
+=
+= Z_UsedStaticHeap
+=
+========================
+*/
+
+int Z_UsedStaticHeap ( void )
+{
+ memblock_t *block;
+ int heapsize;
+
+
+ heapsize=0;
+ for (block = mainzone->blocklist.next ; ; block = block->next)
+ {
+ if ((block->tag>0) && (block->tag<PU_PURGELEVEL) && (block->user>(void **)0))
+ heapsize+=(block->size);
+ if (block->next == &mainzone->blocklist)
+ break; // all blocks have been hit
+ }
+ return heapsize;
+}
+
+
+/*
+========================
+=
+= Z_HeapSize
+=
+========================
+*/
+
+int Z_HeapSize ( void )
+{
+ return mainzone->size;
+}
+
+
+/*
+========================
+=
+= Z_CheckHeap
+=
+========================
+*/
+
+void Z_CheckHeap (void)
+{
+ memblock_t *block;
+
+ // Check mainzone
+
+ for (block = mainzone->blocklist.next ; ; block = block->next)
+ {
+ if (block->next == &mainzone->blocklist)
+ break; // all blocks have been hit
+ if ( (byte *)block + block->size != (byte *)block->next)
+ Error ("Z_CheckHeap: block size does not touch the next block\n");
+ if ( block->next->prev != block)
+ Error ("Z_CheckHeap: next block doesn't have proper back link\n");
+ if (!block->user && !block->next->user)
+ Error ("Z_CheckHeap: two consecutive free blocks\n");
+#if (MEMORYCORRUPTIONTEST==1)
+ if ((block->tag>0) && (block->user>0))
+ {
+ if (block->posttag!=MEMORYPOSTTAG)
+ Error("Z_CheckHeap: Corrupted posttag\n");
+ if (block->pretag!=MEMORYPRETAG)
+ Error("Z_CheckHeap: Corrupted pretag\n");
+ }
+#endif
+ }
+
+ // Check levelzone
+
+ for (block = levelzone->blocklist.next ; ; block = block->next)
+ {
+ if (block->next == &levelzone->blocklist)
+ break; // all blocks have been hit
+ if ( (byte *)block + block->size != (byte *)block->next)
+ Error ("Z_CheckHeap: block size does not touch the next block\n");
+ if ( block->next->prev != block)
+ Error ("Z_CheckHeap: next block doesn't have proper back link\n");
+ if (!block->user && !block->next->user)
+ Error ("Z_CheckHeap: two consecutive free blocks\n");
+#if (MEMORYCORRUPTIONTEST==1)
+ if ((block->tag>0) && (block->user>0))
+ {
+ if (block->posttag!=MEMORYPOSTTAG)
+ Error("Z_CheckHeap: Corrupted posttag\n");
+ if (block->pretag!=MEMORYPRETAG)
+ Error("Z_CheckHeap: Corrupted pretag\n");
+ }
+#endif
+ }
+}
+
+
+/*
+========================
+=
+= Z_ChangeTag
+=
+========================
+*/
+
+void Z_ChangeTag (void *ptr, int tag)
+{
+ memblock_t *block;
+
+ block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
+ block->tag = tag;
+}
+
+/*
+========================
+=
+= Z_AvailHeap
+=
+========================
+*/
+
+int Z_AvailHeap ( void )
+{
+#ifdef DOS
+ union REGS zregs;
+ struct SREGS zsregs;
+
+
+ zregs.x.eax = 0x00000500;
+ memset( &zsregs, 0, sizeof(zsregs) );
+ zsregs.es = FP_SEG( &MemInfo );
+ zregs.x.edi = FP_OFF( &MemInfo );
+
+ int386x( DPMI_INT, &zregs, &zregs, &zsregs );
+
+ return ((int)MemInfo.LargestBlockAvail);
+#else
+ return MAXMEMORYSIZE;
+#endif
+}
+
+/*
+========================
+=
+= Z_Realloc
+=
+========================
+*/
+
+void Z_Realloc (void ** ptr, int newsize)
+{
+ memblock_t *block;
+ void * newptr;
+ int oldsize;
+
+ block = (memblock_t *) ( (byte *)(*ptr) - sizeof(memblock_t));
+ oldsize = block->size;
+ newptr = SafeMalloc(newsize);
+ if (oldsize > newsize)
+ {
+ oldsize = newsize;
+ }
+ memcpy( newptr, *ptr, oldsize );
+ SafeFree( *ptr );
+ *ptr = newptr;
+}
+
--- /dev/null
+++ b/rott/z_zone.h
@@ -1,0 +1,79 @@
+/*
+Copyright (C) 1994-1995 Apogee Software, Ltd.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+//***************************************************************************
+//
+// Z_Zone Memory management Constants
+//
+//***************************************************************************
+
+
+#ifndef _z_zone_public
+#define _z_zone_public
+
+
+extern int lowmemory;
+
+// tags < 100 are not overwritten until freed
+#define PU_STATIC 1 // static entire execution time
+#define PU_GAME 20 // static until game completed
+#define PU_LEVELSTRUCT 49 // start of static until level exited
+#define PU_LEVEL 50 // start of static until level exited
+#define PU_LEVELEND 51 // end of static until level exited
+
+// tags >= 100 are purgable whenever needed
+#define PU_PURGELEVEL 100
+#define PU_CACHE 101
+#define PU_CACHEWALLS 155
+#define PU_CACHESPRITES 154
+#define PU_CACHEBJWEAP 153
+#define PU_CACHEACTORS 152
+#define PU_CACHESOUNDS 120
+#define PU_FLAT 102
+#define PU_PATCH 103
+#define PU_TEXTURE 104
+
+#define URGENTLEVELSTART PU_LEVEL
+
+//***************************************************************************
+//
+// Z_ZONE.C - Carmack's Memory manager for protected mode
+//
+//***************************************************************************
+
+extern int zonememorystarted;
+
+void Z_Init (int size, int min); // Starts up Memory manager (size is in bytes), (min is minimum requirement)
+void Z_Free (void *ptr); // Free a pointer in Z_Zone's domain
+void *Z_Malloc (int size, int tag, void *user); // Malloc You can pass a NULL user if the tag is < PU_PURGELEVEL
+void *Z_LevelMalloc (int size, int tag, void *user); // Level Malloc for level structures
+void Z_FreeTags (int lowtag, int hightag); // Free a series of memory tags
+void Z_DumpHeap (int lowtag, int hightag); // Dump the heap (for debugging purposes)
+void Z_CheckHeap (void); // Check the heap for corruption
+void Z_ChangeTag (void *ptr, int tag); // Change the tag of a memory item
+int Z_HeapSize ( void ); // Return the total heap size
+int Z_UsedHeap ( void ); // Return used portion of heap size
+int Z_AvailHeap ( void ); // Returns largest available contiguous block
+int Z_UsedStaticHeap ( void ); // Returns amount of heap which is static ( < PURGELEVEL )
+void Z_ShutDown( void );
+int Z_GetSize (void *ptr);
+int Z_UsedLevelHeap ( void );
+void Z_Realloc (void ** ptr, int newsize);
+
+#endif