summaryrefslogtreecommitdiff
path: root/src/hexen/i_ibm.c
diff options
context:
space:
mode:
authorSimon Howard2008-09-04 23:15:36 +0000
committerSimon Howard2008-09-04 23:15:36 +0000
commit0df2cb80cf03d7259746834220d209b306a8c503 (patch)
treefdc5037429c91dcbc8207c3e75fc787ef96e207a /src/hexen/i_ibm.c
parent6a294daa7859eaf0250aa4a77484dd11550e5c5e (diff)
downloadchocolate-doom-0df2cb80cf03d7259746834220d209b306a8c503.tar.gz
chocolate-doom-0df2cb80cf03d7259746834220d209b306a8c503.tar.bz2
chocolate-doom-0df2cb80cf03d7259746834220d209b306a8c503.zip
Add GPLed Heretic/Hexen source.
Subversion-branch: /branches/raven-branch Subversion-revision: 1195
Diffstat (limited to 'src/hexen/i_ibm.c')
-rw-r--r--src/hexen/i_ibm.c2782
1 files changed, 2782 insertions, 0 deletions
diff --git a/src/hexen/i_ibm.c b/src/hexen/i_ibm.c
new file mode 100644
index 00000000..20ed3220
--- /dev/null
+++ b/src/hexen/i_ibm.c
@@ -0,0 +1,2782 @@
+
+//**************************************************************************
+//**
+//** I_IBM.C
+//**
+//**************************************************************************
+
+#include <dos.h>
+#include <conio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <graph.h>
+#include "h2def.h"
+#include "r_local.h"
+#include "p_local.h" // for P_AproxDistance
+#include "sounds.h"
+#include "i_sound.h"
+#include "soundst.h"
+#include "st_start.h"
+#include "dmx.h"
+#include "dpmiapi.h"
+
+// Macros
+
+#define DEFAULT_ARCHIVEPATH "o:\\sound\\archive\\"
+#define PRIORITY_MAX_ADJUST 10
+#define DIST_ADJUST (MAX_SND_DIST/PRIORITY_MAX_ADJUST)
+
+#define DPMI_INT 0x31
+
+#define SEQ_ADDR 0x3C4
+#define SEQ_DATA 0x3C5
+#define REG_MAPMASK 0x02
+
+#define MASK_PLANE0 0x01
+#define MASK_PLANE1 0x02
+#define MASK_PLANE2 0x04
+#define MASK_PLANE3 0x08
+
+#define P0OFFSET 38400*0
+#define P1OFFSET 38400*1
+#define P2OFFSET 38400*2
+#define P3OFFSET 38400*3
+
+#define VID_INT 0x10
+#define VB_SYNC {while(!(inp(0x3da)&8)); while(inp(0x3da)&8);}
+#define BITPLANE(p) (outp(SEQ_ADDR,REG_MAPMASK),outp(SEQ_DATA,(p)))
+
+//#define NOKBD
+//#define NOTIMER
+
+// Public Data
+
+int DisplayTicker = 0;
+
+// Code
+
+void main(int argc, char **argv)
+{
+ myargc = argc;
+ myargv = argv;
+ H2_Main();
+}
+
+void I_StartupNet (void);
+void I_ShutdownNet (void);
+void I_ReadExternDriver(void);
+
+typedef struct
+{
+ unsigned edi, esi, ebp, reserved, ebx, edx, ecx, eax;
+ unsigned short flags, es, ds, fs, gs, ip, cs, sp, ss;
+} dpmiregs_t;
+
+extern dpmiregs_t dpmiregs;
+
+void I_ReadMouse (void);
+
+extern int usemouse, usejoystick;
+
+extern void **lumpcache;
+
+int i_Vector;
+externdata_t *i_ExternData;
+boolean useexterndriver;
+
+boolean i_CDMusic;
+int i_CDTrack;
+int i_CDCurrentTrack;
+int i_CDMusicLength;
+int oldTic;
+
+/*
+===============================================================================
+
+ MUSIC & SFX API
+
+===============================================================================
+*/
+
+//static channel_t channel[MAX_CHANNELS];
+
+//static int rs; //the current registered song.
+//int mus_song = -1;
+//int mus_lumpnum;
+//void *mus_sndptr;
+//byte *soundCurve;
+
+extern sfxinfo_t S_sfx[];
+extern musicinfo_t S_music[];
+
+static channel_t Channel[MAX_CHANNELS];
+static int RegisteredSong; //the current registered song.
+static int NextCleanup;
+static boolean MusicPaused;
+static int Mus_Song = -1;
+static int Mus_LumpNum;
+static void *Mus_SndPtr;
+static byte *SoundCurve;
+
+static boolean UseSndScript;
+static char ArchivePath[128];
+
+extern int snd_MusicDevice;
+extern int snd_SfxDevice;
+extern int snd_MaxVolume;
+extern int snd_MusicVolume;
+extern int snd_Channels;
+
+extern int startepisode;
+extern int startmap;
+
+// int AmbChan;
+
+//==========================================================================
+//
+// S_Start
+//
+//==========================================================================
+
+void S_Start(void)
+{
+ S_StopAllSound();
+ S_StartSong(gamemap, true);
+}
+
+//==========================================================================
+//
+// S_StartSong
+//
+//==========================================================================
+
+void S_StartSong(int song, boolean loop)
+{
+ char *songLump;
+ int track;
+
+ if(i_CDMusic)
+ { // Play a CD track, instead
+ if(i_CDTrack)
+ { // Default to the player-chosen track
+ track = i_CDTrack;
+ }
+ else
+ {
+ track = P_GetMapCDTrack(gamemap);
+ }
+ if(track == i_CDCurrentTrack && i_CDMusicLength > 0)
+ {
+ return;
+ }
+ if(!I_CDMusPlay(track))
+ {
+ if(loop)
+ {
+ i_CDMusicLength = 35*I_CDMusTrackLength(track);
+ oldTic = gametic;
+ }
+ else
+ {
+ i_CDMusicLength = -1;
+ }
+ i_CDCurrentTrack = track;
+ }
+ }
+ else
+ {
+ if(song == Mus_Song)
+ { // don't replay an old song
+ return;
+ }
+ if(RegisteredSong)
+ {
+ I_StopSong(RegisteredSong);
+ I_UnRegisterSong(RegisteredSong);
+ if(UseSndScript)
+ {
+ Z_Free(Mus_SndPtr);
+ }
+ else
+ {
+ Z_ChangeTag(lumpcache[Mus_LumpNum], PU_CACHE);
+ }
+ #ifdef __WATCOMC__
+ _dpmi_unlockregion(Mus_SndPtr, lumpinfo[Mus_LumpNum].size);
+ #endif
+ RegisteredSong = 0;
+ }
+ songLump = P_GetMapSongLump(song);
+ if(!songLump)
+ {
+ return;
+ }
+ if(UseSndScript)
+ {
+ char name[128];
+ sprintf(name, "%s%s.lmp", ArchivePath, songLump);
+ M_ReadFile(name, (byte **)&Mus_SndPtr);
+ }
+ else
+ {
+ Mus_LumpNum = W_GetNumForName(songLump);
+ Mus_SndPtr = W_CacheLumpNum(Mus_LumpNum, PU_MUSIC);
+ }
+ #ifdef __WATCOMC__
+ _dpmi_lockregion(Mus_SndPtr, lumpinfo[Mus_LumpNum].size);
+ #endif
+ RegisteredSong = I_RegisterSong(Mus_SndPtr);
+ I_PlaySong(RegisteredSong, loop); // 'true' denotes endless looping.
+ Mus_Song = song;
+ }
+}
+
+//==========================================================================
+//
+// S_StartSongName
+//
+//==========================================================================
+
+void S_StartSongName(char *songLump, boolean loop)
+{
+ int cdTrack;
+
+ if(!songLump)
+ {
+ return;
+ }
+ if(i_CDMusic)
+ {
+ cdTrack = 0;
+
+ if(!strcmp(songLump, "hexen"))
+ {
+ cdTrack = P_GetCDTitleTrack();
+ }
+ else if(!strcmp(songLump, "hub"))
+ {
+ cdTrack = P_GetCDIntermissionTrack();
+ }
+ else if(!strcmp(songLump, "hall"))
+ {
+ cdTrack = P_GetCDEnd1Track();
+ }
+ else if(!strcmp(songLump, "orb"))
+ {
+ cdTrack = P_GetCDEnd2Track();
+ }
+ else if(!strcmp(songLump, "chess") && !i_CDTrack)
+ {
+ cdTrack = P_GetCDEnd3Track();
+ }
+/* Uncomment this, if Kevin writes a specific song for startup
+ else if(!strcmp(songLump, "start"))
+ {
+ cdTrack = P_GetCDStartTrack();
+ }
+*/
+ if(!cdTrack || (cdTrack == i_CDCurrentTrack && i_CDMusicLength > 0))
+ {
+ return;
+ }
+ if(!I_CDMusPlay(cdTrack))
+ {
+ if(loop)
+ {
+ i_CDMusicLength = 35*I_CDMusTrackLength(cdTrack);
+ oldTic = gametic;
+ }
+ else
+ {
+ i_CDMusicLength = -1;
+ }
+ i_CDCurrentTrack = cdTrack;
+ i_CDTrack = false;
+ }
+ }
+ else
+ {
+ if(RegisteredSong)
+ {
+ I_StopSong(RegisteredSong);
+ I_UnRegisterSong(RegisteredSong);
+ if(UseSndScript)
+ {
+ Z_Free(Mus_SndPtr);
+ }
+ else
+ {
+ Z_ChangeTag(lumpcache[Mus_LumpNum], PU_CACHE);
+ }
+ #ifdef __WATCOMC__
+ _dpmi_unlockregion(Mus_SndPtr, lumpinfo[Mus_LumpNum].size);
+ #endif
+ RegisteredSong = 0;
+ }
+ if(UseSndScript)
+ {
+ char name[128];
+ sprintf(name, "%s%s.lmp", ArchivePath, songLump);
+ M_ReadFile(name, (byte **)&Mus_SndPtr);
+ }
+ else
+ {
+ Mus_LumpNum = W_GetNumForName(songLump);
+ Mus_SndPtr = W_CacheLumpNum(Mus_LumpNum, PU_MUSIC);
+ }
+ #ifdef __WATCOMC__
+ _dpmi_lockregion(Mus_SndPtr, lumpinfo[Mus_LumpNum].size);
+ #endif
+ RegisteredSong = I_RegisterSong(Mus_SndPtr);
+ I_PlaySong(RegisteredSong, loop); // 'true' denotes endless looping.
+ Mus_Song = -1;
+ }
+}
+
+//==========================================================================
+//
+// S_GetSoundID
+//
+//==========================================================================
+
+int S_GetSoundID(char *name)
+{
+ int i;
+
+ for(i = 0; i < NUMSFX; i++)
+ {
+ if(!strcmp(S_sfx[i].tagName, name))
+ {
+ return i;
+ }
+ }
+ return 0;
+}
+
+//==========================================================================
+//
+// S_StartSound
+//
+//==========================================================================
+
+void S_StartSound(mobj_t *origin, int sound_id)
+{
+ S_StartSoundAtVolume(origin, sound_id, 127);
+}
+
+//==========================================================================
+//
+// S_StartSoundAtVolume
+//
+//==========================================================================
+
+void S_StartSoundAtVolume(mobj_t *origin, int sound_id, int volume)
+{
+ int dist, vol;
+ int i;
+ int priority;
+ int sep;
+ int angle;
+ int absx;
+ int absy;
+
+ static int sndcount = 0;
+ int chan;
+
+ if(sound_id == 0 || snd_MaxVolume == 0)
+ return;
+ if(origin == NULL)
+ {
+ origin = players[displayplayer].mo;
+ }
+ if(volume == 0)
+ {
+ return;
+ }
+
+ // calculate the distance before other stuff so that we can throw out
+ // sounds that are beyond the hearing range.
+ absx = abs(origin->x-players[displayplayer].mo->x);
+ absy = abs(origin->y-players[displayplayer].mo->y);
+ dist = absx+absy-(absx > absy ? absy>>1 : absx>>1);
+ dist >>= FRACBITS;
+ if(dist >= MAX_SND_DIST)
+ {
+ return; // sound is beyond the hearing range...
+ }
+ if(dist < 0)
+ {
+ dist = 0;
+ }
+ priority = S_sfx[sound_id].priority;
+ priority *= (PRIORITY_MAX_ADJUST-(dist/DIST_ADJUST));
+ if(!S_StopSoundID(sound_id, priority))
+ {
+ return; // other sounds have greater priority
+ }
+ for(i=0; i<snd_Channels; i++)
+ {
+ if(origin->player)
+ {
+ i = snd_Channels;
+ break; // let the player have more than one sound.
+ }
+ if(origin == Channel[i].mo)
+ { // only allow other mobjs one sound
+ S_StopSound(Channel[i].mo);
+ break;
+ }
+ }
+ if(i >= snd_Channels)
+ {
+ for(i = 0; i < snd_Channels; i++)
+ {
+ if(Channel[i].mo == NULL)
+ {
+ break;
+ }
+ }
+ if(i >= snd_Channels)
+ {
+ // look for a lower priority sound to replace.
+ sndcount++;
+ if(sndcount >= snd_Channels)
+ {
+ sndcount = 0;
+ }
+ for(chan = 0; chan < snd_Channels; chan++)
+ {
+ i = (sndcount+chan)%snd_Channels;
+ if(priority >= Channel[i].priority)
+ {
+ chan = -1; //denote that sound should be replaced.
+ break;
+ }
+ }
+ if(chan != -1)
+ {
+ return; //no free channels.
+ }
+ else //replace the lower priority sound.
+ {
+ if(Channel[i].handle)
+ {
+ if(I_SoundIsPlaying(Channel[i].handle))
+ {
+ I_StopSound(Channel[i].handle);
+ }
+ if(S_sfx[Channel[i].sound_id].usefulness > 0)
+ {
+ S_sfx[Channel[i].sound_id].usefulness--;
+ }
+ }
+ }
+ }
+ }
+ if(S_sfx[sound_id].lumpnum == 0)
+ {
+ S_sfx[sound_id].lumpnum = I_GetSfxLumpNum(&S_sfx[sound_id]);
+ }
+ if(S_sfx[sound_id].snd_ptr == NULL)
+ {
+ if(UseSndScript)
+ {
+ char name[128];
+ sprintf(name, "%s%s.lmp", ArchivePath, S_sfx[sound_id].lumpname);
+ M_ReadFile(name, (byte **)&S_sfx[sound_id].snd_ptr);
+ }
+ else
+ {
+ S_sfx[sound_id].snd_ptr = W_CacheLumpNum(S_sfx[sound_id].lumpnum,
+ PU_SOUND);
+ }
+ #ifdef __WATCOMC__
+ _dpmi_lockregion(S_sfx[sound_id].snd_ptr,
+ lumpinfo[S_sfx[sound_id].lumpnum].size);
+ #endif
+ }
+
+ vol = (SoundCurve[dist]*(snd_MaxVolume*8)*volume)>>14;
+ if(origin == players[displayplayer].mo)
+ {
+ sep = 128;
+// vol = (volume*(snd_MaxVolume+1)*8)>>7;
+ }
+ else
+ {
+ angle = R_PointToAngle2(players[displayplayer].mo->x,
+ players[displayplayer].mo->y, Channel[i].mo->x, Channel[i].mo->y);
+ angle = (angle-viewangle)>>24;
+ sep = angle*2-128;
+ if(sep < 64)
+ sep = -sep;
+ if(sep > 192)
+ sep = 512-sep;
+// vol = SoundCurve[dist];
+ }
+
+ if(S_sfx[sound_id].changePitch)
+ {
+ Channel[i].pitch = (byte)(127+(M_Random()&7)-(M_Random()&7));
+ }
+ else
+ {
+ Channel[i].pitch = 127;
+ }
+ Channel[i].handle = I_StartSound(sound_id, S_sfx[sound_id].snd_ptr, vol,
+ sep, Channel[i].pitch, 0);
+ Channel[i].mo = origin;
+ Channel[i].sound_id = sound_id;
+ Channel[i].priority = priority;
+ Channel[i].volume = volume;
+ if(S_sfx[sound_id].usefulness < 0)
+ {
+ S_sfx[sound_id].usefulness = 1;
+ }
+ else
+ {
+ S_sfx[sound_id].usefulness++;
+ }
+}
+
+//==========================================================================
+//
+// S_StopSoundID
+//
+//==========================================================================
+
+boolean S_StopSoundID(int sound_id, int priority)
+{
+ int i;
+ int lp; //least priority
+ int found;
+
+ if(S_sfx[sound_id].numchannels == -1)
+ {
+ return(true);
+ }
+ lp = -1; //denote the argument sound_id
+ found = 0;
+ for(i=0; i<snd_Channels; i++)
+ {
+ if(Channel[i].sound_id == sound_id && Channel[i].mo)
+ {
+ found++; //found one. Now, should we replace it??
+ if(priority >= Channel[i].priority)
+ { // if we're gonna kill one, then this'll be it
+ lp = i;
+ priority = Channel[i].priority;
+ }
+ }
+ }
+ if(found < S_sfx[sound_id].numchannels)
+ {
+ return(true);
+ }
+ else if(lp == -1)
+ {
+ return(false); // don't replace any sounds
+ }
+ if(Channel[lp].handle)
+ {
+ if(I_SoundIsPlaying(Channel[lp].handle))
+ {
+ I_StopSound(Channel[lp].handle);
+ }
+ if(S_sfx[Channel[lp].sound_id].usefulness > 0)
+ {
+ S_sfx[Channel[lp].sound_id].usefulness--;
+ }
+ Channel[lp].mo = NULL;
+ }
+ return(true);
+}
+
+//==========================================================================
+//
+// S_StopSound
+//
+//==========================================================================
+
+void S_StopSound(mobj_t *origin)
+{
+ int i;
+
+ for(i=0;i<snd_Channels;i++)
+ {
+ if(Channel[i].mo == origin)
+ {
+ I_StopSound(Channel[i].handle);
+ if(S_sfx[Channel[i].sound_id].usefulness > 0)
+ {
+ S_sfx[Channel[i].sound_id].usefulness--;
+ }
+ Channel[i].handle = 0;
+ Channel[i].mo = NULL;
+ }
+ }
+}
+
+//==========================================================================
+//
+// S_StopAllSound
+//
+//==========================================================================
+
+void S_StopAllSound(void)
+{
+ int i;
+
+ //stop all sounds
+ for(i=0; i < snd_Channels; i++)
+ {
+ if(Channel[i].handle)
+ {
+ S_StopSound(Channel[i].mo);
+ }
+ }
+ memset(Channel, 0, 8*sizeof(channel_t));
+}
+
+//==========================================================================
+//
+// S_SoundLink
+//
+//==========================================================================
+
+void S_SoundLink(mobj_t *oldactor, mobj_t *newactor)
+{
+ int i;
+
+ for(i=0;i<snd_Channels;i++)
+ {
+ if(Channel[i].mo == oldactor)
+ Channel[i].mo = newactor;
+ }
+}
+
+//==========================================================================
+//
+// S_PauseSound
+//
+//==========================================================================
+
+void S_PauseSound(void)
+{
+ if(i_CDMusic)
+ {
+ I_CDMusStop();
+ }
+ else
+ {
+ I_PauseSong(RegisteredSong);
+ }
+}
+
+//==========================================================================
+//
+// S_ResumeSound
+//
+//==========================================================================
+
+void S_ResumeSound(void)
+{
+ if(i_CDMusic)
+ {
+ I_CDMusResume();
+ }
+ else
+ {
+ I_ResumeSong(RegisteredSong);
+ }
+}
+
+//==========================================================================
+//
+// S_UpdateSounds
+//
+//==========================================================================
+
+void S_UpdateSounds(mobj_t *listener)
+{
+ int i, dist, vol;
+ int angle;
+ int sep;
+ int priority;
+ int absx;
+ int absy;
+
+ if(i_CDMusic)
+ {
+ I_UpdateCDMusic();
+ }
+ if(snd_MaxVolume == 0)
+ {
+ return;
+ }
+
+ // Update any Sequences
+ SN_UpdateActiveSequences();
+
+ if(NextCleanup < gametic)
+ {
+ if(UseSndScript)
+ {
+ for(i = 0; i < NUMSFX; i++)
+ {
+ if(S_sfx[i].usefulness == 0 && S_sfx[i].snd_ptr)
+ {
+ S_sfx[i].usefulness = -1;
+ }
+ }
+ }
+ else
+ {
+ for(i = 0; i < NUMSFX; i++)
+ {
+ if(S_sfx[i].usefulness == 0 && S_sfx[i].snd_ptr)
+ {
+ if(lumpcache[S_sfx[i].lumpnum])
+ {
+ if(((memblock_t *)((byte*)
+ (lumpcache[S_sfx[i].lumpnum])-
+ sizeof(memblock_t)))->id == 0x1d4a11)
+ { // taken directly from the Z_ChangeTag macro
+ Z_ChangeTag2(lumpcache[S_sfx[i].lumpnum],
+ PU_CACHE);
+#ifdef __WATCOMC__
+ _dpmi_unlockregion(S_sfx[i].snd_ptr,
+ lumpinfo[S_sfx[i].lumpnum].size);
+#endif
+ }
+ }
+ S_sfx[i].usefulness = -1;
+ S_sfx[i].snd_ptr = NULL;
+ }
+ }
+ }
+ NextCleanup = gametic+35*30; // every 30 seconds
+ }
+ for(i=0;i<snd_Channels;i++)
+ {
+ if(!Channel[i].handle || S_sfx[Channel[i].sound_id].usefulness == -1)
+ {
+ continue;
+ }
+ if(!I_SoundIsPlaying(Channel[i].handle))
+ {
+ if(S_sfx[Channel[i].sound_id].usefulness > 0)
+ {
+ S_sfx[Channel[i].sound_id].usefulness--;
+ }
+ Channel[i].handle = 0;
+ Channel[i].mo = NULL;
+ Channel[i].sound_id = 0;
+ }
+ if(Channel[i].mo == NULL || Channel[i].sound_id == 0
+ || Channel[i].mo == listener)
+ {
+ continue;
+ }
+ else
+ {
+ absx = abs(Channel[i].mo->x-listener->x);
+ absy = abs(Channel[i].mo->y-listener->y);
+ dist = absx+absy-(absx > absy ? absy>>1 : absx>>1);
+ dist >>= FRACBITS;
+
+ if(dist >= MAX_SND_DIST)
+ {
+ S_StopSound(Channel[i].mo);
+ continue;
+ }
+ if(dist < 0)
+ {
+ dist = 0;
+ }
+ //vol = SoundCurve[dist];
+ vol = (SoundCurve[dist]*(snd_MaxVolume*8)*Channel[i].volume)>>14;
+ if(Channel[i].mo == listener)
+ {
+ sep = 128;
+ }
+ else
+ {
+ angle = R_PointToAngle2(listener->x, listener->y,
+ Channel[i].mo->x, Channel[i].mo->y);
+ angle = (angle-viewangle)>>24;
+ sep = angle*2-128;
+ if(sep < 64)
+ sep = -sep;
+ if(sep > 192)
+ sep = 512-sep;
+ }
+ I_UpdateSoundParams(Channel[i].handle, vol, sep,
+ Channel[i].pitch);
+ priority = S_sfx[Channel[i].sound_id].priority;
+ priority *= PRIORITY_MAX_ADJUST-(dist/DIST_ADJUST);
+ Channel[i].priority = priority;
+ }
+ }
+}
+
+//==========================================================================
+//
+// S_Init
+//
+//==========================================================================
+
+void S_Init(void)
+{
+ SoundCurve = W_CacheLumpName("SNDCURVE", PU_STATIC);
+// SoundCurve = Z_Malloc(MAX_SND_DIST, PU_STATIC, NULL);
+ I_StartupSound();
+ if(snd_Channels > 8)
+ {
+ snd_Channels = 8;
+ }
+ I_SetChannels(snd_Channels);
+ I_SetMusicVolume(snd_MusicVolume);
+
+ // Attempt to setup CD music
+ if(snd_MusicDevice == snd_CDMUSIC)
+ {
+ ST_Message(" Attempting to initialize CD Music: ");
+ if(!cdrom)
+ {
+ i_CDMusic = (I_CDMusInit() != -1);
+ }
+ else
+ { // The user is trying to use the cdrom for both game and music
+ i_CDMusic = false;
+ }
+ if(i_CDMusic)
+ {
+ ST_Message("initialized.\n");
+ }
+ else
+ {
+ ST_Message("failed.\n");
+ }
+ }
+}
+
+//==========================================================================
+//
+// S_GetChannelInfo
+//
+//==========================================================================
+
+void S_GetChannelInfo(SoundInfo_t *s)
+{
+ int i;
+ ChanInfo_t *c;
+
+ s->channelCount = snd_Channels;
+ s->musicVolume = snd_MusicVolume;
+ s->soundVolume = snd_MaxVolume;
+ for(i = 0; i < snd_Channels; i++)
+ {
+ c = &s->chan[i];
+ c->id = Channel[i].sound_id;
+ c->priority = Channel[i].priority;
+ c->name = S_sfx[c->id].lumpname;
+ c->mo = Channel[i].mo;
+ c->distance = P_AproxDistance(c->mo->x-viewx, c->mo->y-viewy)
+ >>FRACBITS;
+ }
+}
+
+//==========================================================================
+//
+// S_GetSoundPlayingInfo
+//
+//==========================================================================
+
+boolean S_GetSoundPlayingInfo(mobj_t *mobj, int sound_id)
+{
+ int i;
+
+ for(i = 0; i < snd_Channels; i++)
+ {
+ if(Channel[i].sound_id == sound_id && Channel[i].mo == mobj)
+ {
+ if(I_SoundIsPlaying(Channel[i].handle))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+//==========================================================================
+//
+// S_SetMusicVolume
+//
+//==========================================================================
+
+void S_SetMusicVolume(void)
+{
+ if(i_CDMusic)
+ {
+ I_CDMusSetVolume(snd_MusicVolume*16); // 0-255
+ }
+ else
+ {
+ I_SetMusicVolume(snd_MusicVolume);
+ }
+ if(snd_MusicVolume == 0)
+ {
+ if(!i_CDMusic)
+ {
+ I_PauseSong(RegisteredSong);
+ }
+ MusicPaused = true;
+ }
+ else if(MusicPaused)
+ {
+ if(!i_CDMusic)
+ {
+ I_ResumeSong(RegisteredSong);
+ }
+ MusicPaused = false;
+ }
+}
+
+//==========================================================================
+//
+// S_ShutDown
+//
+//==========================================================================
+
+void S_ShutDown(void)
+{
+ extern int tsm_ID;
+ if(tsm_ID != -1)
+ {
+ I_StopSong(RegisteredSong);
+ I_UnRegisterSong(RegisteredSong);
+ I_ShutdownSound();
+ }
+ if(i_CDMusic)
+ {
+ I_CDMusStop();
+ }
+}
+
+//==========================================================================
+//
+// S_InitScript
+//
+//==========================================================================
+
+void S_InitScript(void)
+{
+ int p;
+ int i;
+
+ strcpy(ArchivePath, DEFAULT_ARCHIVEPATH);
+ if(!(p = M_CheckParm("-devsnd")))
+ {
+ UseSndScript = false;
+ SC_OpenLump("sndinfo");
+ }
+ else
+ {
+ UseSndScript = true;
+ SC_OpenFile(myargv[p+1]);
+ }
+ while(SC_GetString())
+ {
+ if(*sc_String == '$')
+ {
+ if(!stricmp(sc_String, "$ARCHIVEPATH"))
+ {
+ SC_MustGetString();
+ strcpy(ArchivePath, sc_String);
+ }
+ else if(!stricmp(sc_String, "$MAP"))
+ {
+ SC_MustGetNumber();
+ SC_MustGetString();
+ if(sc_Number)
+ {
+ P_PutMapSongLump(sc_Number, sc_String);
+ }
+ }
+ continue;
+ }
+ else
+ {
+ for(i = 0; i < NUMSFX; i++)
+ {
+ if(!strcmp(S_sfx[i].tagName, sc_String))
+ {
+ SC_MustGetString();
+ if(*sc_String != '?')
+ {
+ strcpy(S_sfx[i].lumpname, sc_String);
+ }
+ else
+ {
+ strcpy(S_sfx[i].lumpname, "default");
+ }
+ break;
+ }
+ }
+ if(i == NUMSFX)
+ {
+ SC_MustGetString();
+ }
+ }
+ }
+ SC_Close();
+
+ for(i = 0; i < NUMSFX; i++)
+ {
+ if(!strcmp(S_sfx[i].lumpname, ""))
+ {
+ strcpy(S_sfx[i].lumpname, "default");
+ }
+ }
+}
+
+//==========================================================================
+//
+// I_UpdateCDMusic
+//
+// Updates playing time for current track, and restarts the track, if
+// needed
+//
+//==========================================================================
+
+void I_UpdateCDMusic(void)
+{
+ extern boolean MenuActive;
+
+ if(MusicPaused || i_CDMusicLength < 0
+ || (paused && !MenuActive))
+ { // Non-looping song/song paused
+ return;
+ }
+ i_CDMusicLength -= gametic-oldTic;
+ oldTic = gametic;
+ if(i_CDMusicLength <= 0)
+ {
+ S_StartSong(gamemap, true);
+ }
+}
+
+/*
+============================================================================
+
+ CONSTANTS
+
+============================================================================
+*/
+
+#define SC_INDEX 0x3C4
+#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_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_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
+#define PEL_MASK 0x3c6
+
+// boolean grmode;
+
+//==================================================
+//
+// joystick vars
+//
+//==================================================
+
+boolean joystickpresent;
+extern unsigned joystickx, joysticky;
+boolean I_ReadJoystick (void); // returns false if not connected
+
+
+//==================================================
+
+#define VBLCOUNTER 34000 // hardware tics to a frame
+
+
+#define TIMERINT 8
+#define KEYBOARDINT 9
+
+#define CRTCOFF (_inbyte(STATUS_REGISTER_1)&1)
+#define CLI _disable()
+#define STI _enable()
+
+#define _outbyte(x,y) (outp(x,y))
+#define _outhword(x,y) (outpw(x,y))
+
+#define _inbyte(x) (inp(x))
+#define _inhword(x) (inpw(x))
+
+#define MOUSEB1 1
+#define MOUSEB2 2
+#define MOUSEB3 4
+
+boolean mousepresent;
+//static int tsm_ID = -1; // tsm init flag
+
+//===============================
+
+int ticcount;
+
+// REGS stuff used for int calls
+union REGS regs;
+struct SREGS segregs;
+
+boolean novideo; // if true, stay in text mode for debugging
+
+#define KBDQUESIZE 32
+byte keyboardque[KBDQUESIZE];
+int kbdtail, kbdhead;
+
+#define KEY_LSHIFT 0xfe
+
+#define KEY_INS (0x80+0x52)
+#define KEY_DEL (0x80+0x53)
+#define KEY_PGUP (0x80+0x49)
+#define KEY_PGDN (0x80+0x51)
+#define KEY_HOME (0x80+0x47)
+#define KEY_END (0x80+0x4f)
+
+#define SC_RSHIFT 0x36
+#define SC_LSHIFT 0x2a
+
+byte scantokey[128] =
+ {
+// 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', '-', '=', KEY_BACKSPACE, 9, // 0
+ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
+ 'o', 'p', '[', ']', 13 , KEY_RCTRL,'a', 's', // 1
+ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
+ 39 , '`', KEY_LSHIFT,92, 'z', 'x', 'c', 'v', // 2
+ 'b', 'n', 'm', ',', '.', '/', KEY_RSHIFT,'*',
+ KEY_RALT,' ', 0 , KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, // 3
+ KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10,0 , 0 , KEY_HOME,
+ KEY_UPARROW,KEY_PGUP,'-',KEY_LEFTARROW,'5',KEY_RIGHTARROW,'+',KEY_END, //4
+ KEY_DOWNARROW,KEY_PGDN,KEY_INS,KEY_DEL,0,0, 0, KEY_F11,
+ KEY_F12,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
+ };
+
+//==========================================================================
+
+//--------------------------------------------------------------------------
+//
+// FUNC I_GetTime
+//
+// Returns time in 1/35th second tics.
+//
+//--------------------------------------------------------------------------
+
+int I_GetTime (void)
+{
+#ifdef NOTIMER
+ ticcount++;
+#endif
+ return(ticcount);
+}
+
+//--------------------------------------------------------------------------
+//
+// PROC I_ColorBorder
+//
+//--------------------------------------------------------------------------
+
+/*
+void I_ColorBorder(void)
+{
+ int i;
+
+ I_WaitVBL(1);
+ _outbyte(PEL_WRITE_ADR, 0);
+ for(i = 0; i < 3; i++)
+ {
+ _outbyte(PEL_DATA, 63);
+ }
+}
+*/
+
+//--------------------------------------------------------------------------
+//
+// PROC I_UnColorBorder
+//
+//--------------------------------------------------------------------------
+
+/*
+void I_UnColorBorder(void)
+{
+ int i;
+
+ I_WaitVBL(1);
+ _outbyte(PEL_WRITE_ADR, 0);
+ for(i = 0; i < 3; i++)
+ {
+ _outbyte(PEL_DATA, 0);
+ }
+}
+*/
+
+/*
+============================================================================
+
+ USER INPUT
+
+============================================================================
+*/
+
+//--------------------------------------------------------------------------
+//
+// PROC I_WaitVBL
+//
+//--------------------------------------------------------------------------
+
+void I_WaitVBL(int vbls)
+{
+ int stat;
+
+ if(novideo)
+ {
+ return;
+ }
+ while(vbls--)
+ {
+ do
+ {
+ stat = inp(STATUS_REGISTER_1);
+ if(stat&8)
+ {
+ break;
+ }
+ } while(1);
+ do
+ {
+ stat = inp(STATUS_REGISTER_1);
+ if((stat&8) == 0)
+ {
+ break;
+ }
+ } while(1);
+ }
+}
+
+//--------------------------------------------------------------------------
+//
+// PROC I_SetPalette
+//
+// Palette source must use 8 bit RGB elements.
+//
+//--------------------------------------------------------------------------
+
+void I_SetPalette(byte *palette)
+{
+ int i;
+
+ if(novideo)
+ {
+ return;
+ }
+ I_WaitVBL(1);
+ _outbyte(PEL_WRITE_ADR, 0);
+ for(i = 0; i < 768; i++)
+ {
+ _outbyte(PEL_DATA, (gammatable[usegamma][*palette++])>>2);
+ }
+}
+
+/*
+============================================================================
+
+ GRAPHICS MODE
+
+============================================================================
+*/
+
+byte *pcscreen, *destscreen, *destview;
+
+
+/*
+==============
+=
+= I_Update
+=
+==============
+*/
+
+int UpdateState;
+extern int screenblocks;
+
+void I_Update (void)
+{
+ int i;
+ byte *dest;
+ int tics;
+ static int lasttic;
+
+//
+// blit screen to video
+//
+ if(DisplayTicker)
+ {
+ if(screenblocks > 9 || UpdateState&(I_FULLSCRN|I_MESSAGES))
+ {
+ dest = (byte *)screen;
+ }
+ else
+ {
+ dest = (byte *)pcscreen;
+ }
+ tics = ticcount-lasttic;
+ lasttic = ticcount;
+ if(tics > 20)
+ {
+ tics = 20;
+ }
+ for(i = 0; i < tics; i++)
+ {
+ *dest = 0xff;
+ dest += 2;
+ }
+ for(i = tics; i < 20; i++)
+ {
+ *dest = 0x00;
+ dest += 2;
+ }
+ }
+
+ //memset(pcscreen, 255, SCREENHEIGHT*SCREENWIDTH);
+
+ if(UpdateState == I_NOUPDATE)
+ {
+ return;
+ }
+ if(UpdateState&I_FULLSCRN)
+ {
+ memcpy(pcscreen, screen, SCREENWIDTH*SCREENHEIGHT);
+ UpdateState = I_NOUPDATE; // clear out all draw types
+ }
+ if(UpdateState&I_FULLVIEW)
+ {
+ if(UpdateState&I_MESSAGES && screenblocks > 7)
+ {
+ for(i = 0; i <
+ (viewwindowy+viewheight)*SCREENWIDTH; i += SCREENWIDTH)
+ {
+ memcpy(pcscreen+i, screen+i, SCREENWIDTH);
+ }
+ UpdateState &= ~(I_FULLVIEW|I_MESSAGES);
+ }
+ else
+ {
+ for(i = viewwindowy*SCREENWIDTH+viewwindowx; i <
+ (viewwindowy+viewheight)*SCREENWIDTH; i += SCREENWIDTH)
+ {
+ memcpy(pcscreen+i, screen+i, viewwidth);
+ }
+ UpdateState &= ~I_FULLVIEW;
+ }
+ }
+ if(UpdateState&I_STATBAR)
+ {
+ memcpy(pcscreen+SCREENWIDTH*(SCREENHEIGHT-SBARHEIGHT),
+ screen+SCREENWIDTH*(SCREENHEIGHT-SBARHEIGHT),
+ SCREENWIDTH*SBARHEIGHT);
+ UpdateState &= ~I_STATBAR;
+ }
+ if(UpdateState&I_MESSAGES)
+ {
+ memcpy(pcscreen, screen, SCREENWIDTH*28);
+ UpdateState &= ~I_MESSAGES;
+ }
+
+
+// memcpy(pcscreen, screen, SCREENHEIGHT*SCREENWIDTH);
+}
+
+//--------------------------------------------------------------------------
+//
+// PROC I_InitGraphics
+//
+//--------------------------------------------------------------------------
+
+void I_InitGraphics(void)
+{
+ if(novideo)
+ {
+ return;
+ }
+ //grmode = true;
+ regs.w.ax = 0x13;
+ int386(0x10, (const union REGS *)&regs, &regs);
+ pcscreen = destscreen = (byte *)0xa0000;
+ I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
+}
+
+//--------------------------------------------------------------------------
+//
+// PROC I_ShutdownGraphics
+//
+//--------------------------------------------------------------------------
+
+void I_ShutdownGraphics(void)
+{
+ byte mode;
+
+ // don't reset mode if it didn't get set
+ mode = *(byte *)0x449;
+ if(mode == 0x12 || mode == 0x13)
+ {
+ regs.w.ax = 3;
+ int386(0x10, &regs, &regs); // back to text mode
+ }
+}
+
+//--------------------------------------------------------------------------
+//
+// PROC I_ReadScreen
+//
+// Reads the screen currently displayed into a linear buffer.
+//
+//--------------------------------------------------------------------------
+
+/*
+void I_ReadScreen(byte *scr)
+{
+ memcpy(scr, screen, SCREENWIDTH*SCREENHEIGHT);
+}
+*/
+
+//===========================================================================
+
+/*
+===================
+=
+= I_StartTic
+=
+// called by D_DoomLoop
+// called before processing each tic in a frame
+// can call D_PostEvent
+// asyncronous interrupt functions should maintain private ques that are
+// read by the syncronous functions to be converted into events
+===================
+*/
+
+/*
+ OLD STARTTIC STUFF
+
+void I_StartTic (void)
+{
+ int k;
+ event_t ev;
+
+
+ I_ReadMouse ();
+
+//
+// keyboard events
+//
+ while (kbdtail < kbdhead)
+ {
+ k = keyboardque[kbdtail&(KBDQUESIZE-1)];
+
+// if (k==14)
+// I_Error ("exited");
+
+ kbdtail++;
+
+ // extended keyboard shift key bullshit
+ if ( (k&0x7f)==KEY_RSHIFT )
+ {
+ if ( keyboardque[(kbdtail-2)&(KBDQUESIZE-1)]==0xe0 )
+ continue;
+ k &= 0x80;
+ k |= KEY_RSHIFT;
+ }
+
+ if (k==0xe0)
+ continue; // special / pause keys
+ if (keyboardque[(kbdtail-2)&(KBDQUESIZE-1)] == 0xe1)
+ continue; // pause key bullshit
+
+ if (k==0xc5 && keyboardque[(kbdtail-2)&(KBDQUESIZE-1)] == 0x9d)
+ {
+ ev.type = ev_keydown;
+ ev.data1 = KEY_PAUSE;
+ D_PostEvent (&ev);
+ continue;
+ }
+
+ if (k&0x80)
+ ev.type = ev_keyup;
+ else
+ ev.type = ev_keydown;
+ k &= 0x7f;
+
+ ev.data1 = k;
+ //ev.data1 = scantokey[k];
+
+ D_PostEvent (&ev);
+ }
+}
+*/
+
+#define SC_UPARROW 0x48
+#define SC_DOWNARROW 0x50
+#define SC_LEFTARROW 0x4b
+#define SC_RIGHTARROW 0x4d
+
+void I_StartTic (void)
+{
+ int k;
+ event_t ev;
+
+
+ I_ReadMouse ();
+
+//
+// keyboard events
+//
+ while (kbdtail < kbdhead)
+ {
+ k = keyboardque[kbdtail&(KBDQUESIZE-1)];
+ kbdtail++;
+
+ // extended keyboard shift key bullshit
+ if ( (k&0x7f)==SC_LSHIFT || (k&0x7f)==SC_RSHIFT )
+ {
+ if ( keyboardque[(kbdtail-2)&(KBDQUESIZE-1)]==0xe0 )
+ continue;
+ k &= 0x80;
+ k |= SC_RSHIFT;
+ }
+
+ if (k==0xe0)
+ continue; // special / pause keys
+ if (keyboardque[(kbdtail-2)&(KBDQUESIZE-1)] == 0xe1)
+ continue; // pause key bullshit
+
+ if (k==0xc5 && keyboardque[(kbdtail-2)&(KBDQUESIZE-1)] == 0x9d)
+ {
+ ev.type = ev_keydown;
+ ev.data1 = KEY_PAUSE;
+ H2_PostEvent (&ev);
+ continue;
+ }
+
+ if (k&0x80)
+ ev.type = ev_keyup;
+ else
+ ev.type = ev_keydown;
+ k &= 0x7f;
+ switch (k)
+ {
+ case SC_UPARROW:
+ ev.data1 = KEY_UPARROW;
+ break;
+ case SC_DOWNARROW:
+ ev.data1 = KEY_DOWNARROW;
+ break;
+ case SC_LEFTARROW:
+ ev.data1 = KEY_LEFTARROW;
+ break;
+ case SC_RIGHTARROW:
+ ev.data1 = KEY_RIGHTARROW;
+ break;
+ default:
+ ev.data1 = scantokey[k];
+ break;
+ }
+ H2_PostEvent (&ev);
+ }
+
+}
+
+
+/*
+void I_ReadKeys (void)
+{
+ int k;
+
+
+ while (1)
+ {
+ while (kbdtail < kbdhead)
+ {
+ k = keyboardque[kbdtail&(KBDQUESIZE-1)];
+ kbdtail++;
+ printf ("0x%x\n",k);
+ if (k == 1)
+ I_Quit ();
+ }
+ }
+}
+*/
+
+/*
+===============
+=
+= I_StartFrame
+=
+===============
+*/
+
+void I_StartFrame (void)
+{
+ I_JoystickEvents ();
+ if(useexterndriver)
+ {
+ DPMIInt(i_Vector);
+ }
+}
+
+/*
+============================================================================
+
+ TIMER INTERRUPT
+
+============================================================================
+*/
+
+/*
+void I_ColorBlack (int r, int g, int b)
+{
+_outbyte (PEL_WRITE_ADR,0);
+_outbyte(PEL_DATA,r);
+_outbyte(PEL_DATA,g);
+_outbyte(PEL_DATA,b);
+}
+*/
+
+
+/*
+================
+=
+= I_TimerISR
+=
+================
+*/
+
+int I_TimerISR (void)
+{
+ ticcount++;
+ return 0;
+}
+
+/*
+============================================================================
+
+ KEYBOARD
+
+============================================================================
+*/
+
+void (__interrupt __far *oldkeyboardisr) () = NULL;
+
+int lastpress;
+
+/*
+================
+=
+= I_KeyboardISR
+=
+================
+*/
+
+void __interrupt I_KeyboardISR (void)
+{
+// Get the scan code
+
+ keyboardque[kbdhead&(KBDQUESIZE-1)] = lastpress = _inbyte(0x60);
+ kbdhead++;
+
+// acknowledge the interrupt
+
+ _outbyte(0x20,0x20);
+}
+
+
+
+/*
+===============
+=
+= I_StartupKeyboard
+=
+===============
+*/
+
+void I_StartupKeyboard (void)
+{
+#ifndef NOKBD
+ oldkeyboardisr = _dos_getvect(KEYBOARDINT);
+ _dos_setvect (0x8000 | KEYBOARDINT, I_KeyboardISR);
+#endif
+
+//I_ReadKeys ();
+}
+
+
+void I_ShutdownKeyboard (void)
+{
+ if (oldkeyboardisr)
+ _dos_setvect (KEYBOARDINT, oldkeyboardisr);
+ *(short *)0x41c = *(short *)0x41a; // clear bios key buffer
+}
+
+
+
+/*
+============================================================================
+
+ MOUSE
+
+============================================================================
+*/
+
+
+int I_ResetMouse (void)
+{
+ regs.w.ax = 0; // reset
+ int386 (0x33, &regs, &regs);
+ return regs.w.ax;
+}
+
+
+
+/*
+================
+=
+= StartupMouse
+=
+================
+*/
+
+void I_StartupCyberMan(void);
+
+void I_StartupMouse (void)
+{
+ //
+ // General mouse detection
+ //
+ mousepresent = 0;
+ if ( M_CheckParm ("-nomouse") || !usemouse )
+ return;
+
+ if (I_ResetMouse () != 0xffff)
+ {
+ ST_Message("Mouse: not present\n");
+ return;
+ }
+ ST_Message("Mouse: detected\n");
+
+ mousepresent = 1;
+
+ I_StartupCyberMan();
+}
+
+
+/*
+================
+=
+= ShutdownMouse
+=
+================
+*/
+
+void I_ShutdownMouse (void)
+{
+ if (!mousepresent)
+ return;
+
+ I_ResetMouse ();
+}
+
+
+/*
+================
+=
+= I_ReadMouse
+=
+================
+*/
+
+void I_ReadMouse (void)
+{
+ event_t ev;
+
+//
+// mouse events
+//
+ if (!mousepresent)
+ return;
+
+ ev.type = ev_mouse;
+
+ memset (&dpmiregs,0,sizeof(dpmiregs));
+ dpmiregs.eax = 3; // read buttons / position
+ DPMIInt (0x33);
+ ev.data1 = dpmiregs.ebx;
+
+ dpmiregs.eax = 11; // read counters
+ DPMIInt (0x33);
+ ev.data2 = (short)dpmiregs.ecx;
+ ev.data3 = -(short)dpmiregs.edx;
+
+ H2_PostEvent (&ev);
+}
+
+/*
+============================================================================
+
+ JOYSTICK
+
+============================================================================
+*/
+
+int joyxl, joyxh, joyyl, joyyh;
+
+boolean WaitJoyButton (void)
+{
+ int oldbuttons, buttons;
+
+ oldbuttons = 0;
+ do
+ {
+ I_WaitVBL (1);
+ buttons = ((inp(0x201) >> 4)&1)^1;
+ if (buttons != oldbuttons)
+ {
+ oldbuttons = buttons;
+ continue;
+ }
+
+ if ( (lastpress& 0x7f) == 1 )
+ {
+ joystickpresent = false;
+ return false;
+ }
+ } while ( !buttons);
+
+ do
+ {
+ I_WaitVBL (1);
+ buttons = ((inp(0x201) >> 4)&1)^1;
+ if (buttons != oldbuttons)
+ {
+ oldbuttons = buttons;
+ continue;
+ }
+
+ if ( (lastpress& 0x7f) == 1 )
+ {
+ joystickpresent = false;
+ return false;
+ }
+ } while ( buttons);
+
+ return true;
+}
+
+
+
+/*
+===============
+=
+= I_StartupJoystick
+=
+===============
+*/
+
+int basejoyx, basejoyy;
+
+void I_StartupJoystick (void)
+{
+ int centerx, centery;
+
+ joystickpresent = 0;
+ if ( M_CheckParm ("-nojoy") || !usejoystick )
+ return;
+
+ if (!I_ReadJoystick ())
+ {
+ joystickpresent = false;
+ ST_Message("joystick not found\n ");
+ return;
+ }
+ ST_Message("joystick found\n");
+ joystickpresent = true;
+
+ ST_RealMessage("CENTER the joystick and press button 1:");
+ if (!WaitJoyButton ())
+ return;
+ I_ReadJoystick ();
+ centerx = joystickx;
+ centery = joysticky;
+
+ ST_RealMessage("\nPush the joystick to the UPPER LEFT corner and press button 1:");
+ if (!WaitJoyButton ())
+ return;
+ I_ReadJoystick ();
+ joyxl = (centerx + joystickx)/2;
+ joyyl = (centerx + joysticky)/2;
+
+ ST_RealMessage("\nPush the joystick to the LOWER RIGHT corner and press button 1:");
+ if (!WaitJoyButton ())
+ return;
+ I_ReadJoystick ();
+ joyxh = (centerx + joystickx)/2;
+ joyyh = (centery + joysticky)/2;
+ ST_RealMessage("\n");
+}
+
+/*
+===============
+=
+= I_JoystickEvents
+=
+===============
+*/
+
+void I_JoystickEvents (void)
+{
+ event_t ev;
+
+//
+// joystick events
+//
+ if (!joystickpresent)
+ return;
+
+ I_ReadJoystick ();
+ ev.type = ev_joystick;
+ ev.data1 = ((inp(0x201) >> 4)&15)^15;
+
+ if (joystickx < joyxl)
+ ev.data2 = -1;
+ else if (joystickx > joyxh)
+ ev.data2 = 1;
+ else
+ ev.data2 = 0;
+ if (joysticky < joyyl)
+ ev.data3 = -1;
+ else if (joysticky > joyyh)
+ ev.data3 = 1;
+ else
+ ev.data3 = 0;
+
+ H2_PostEvent (&ev);
+}
+
+
+
+/*
+============================================================================
+
+ DPMI STUFF
+
+============================================================================
+*/
+
+#define REALSTACKSIZE 1024
+
+dpmiregs_t dpmiregs;
+
+unsigned realstackseg;
+
+void I_DivException (void);
+int I_SetDivException (void);
+
+/*
+void DPMIFarCall (void)
+{
+ segread (&segregs);
+ regs.w.ax = 0x301;
+ regs.w.bx = 0;
+ regs.w.cx = 0;
+ regs.x.edi = (unsigned)&dpmiregs;
+ segregs.es = segregs.ds;
+ int386x( DPMI_INT, &regs, &regs, &segregs );
+}
+*/
+
+void DPMIInt (int i)
+{
+ dpmiregs.ss = realstackseg;
+ dpmiregs.sp = REALSTACKSIZE-4;
+
+ segread (&segregs);
+ regs.w.ax = 0x300;
+ regs.w.bx = i;
+ regs.w.cx = 0;
+ regs.x.edi = (unsigned)&dpmiregs;
+ segregs.es = segregs.ds;
+ int386x( DPMI_INT, &regs, &regs, &segregs );
+}
+
+
+/*
+==============
+=
+= I_StartupDPMI
+=
+==============
+*/
+
+void I_StartupDPMI (void)
+{
+// extern char __begtext;
+// extern char ___argc;
+// int n,d;
+
+//
+// allocate a decent stack for real mode ISRs
+//
+ realstackseg = (int)I_AllocLow (1024) >> 4;
+
+//
+// lock the entire program down
+//
+
+// _dpmi_lockregion (&__begtext, &___argc - &__begtext);
+
+
+//
+// catch divide by 0 exception
+//
+#if 0
+ segread(&segregs);
+ regs.w.ax = 0x0203; // DPMI set processor exception handler vector
+ regs.w.bx = 0; // int 0
+ regs.w.cx = segregs.cs;
+ regs.x.edx = (int)&I_DivException;
+ printf ("%x : %x\n",regs.w.cx, regs.x.edx);
+ int386( DPMI_INT, &regs, &regs);
+#endif
+
+#if 0
+ n = I_SetDivException ();
+ printf ("return: %i\n",n);
+ n = 100;
+ d = 0;
+ printf ("100 / 0 = %i\n",n/d);
+
+exit (1);
+#endif
+}
+
+
+
+/*
+============================================================================
+
+ TIMER INTERRUPT
+
+============================================================================
+*/
+
+void (__interrupt __far *oldtimerisr) ();
+
+
+/*
+void IO_ColorBlack (int r, int g, int b)
+{
+_outbyte (PEL_WRITE_ADR,0);
+_outbyte(PEL_DATA,r);
+_outbyte(PEL_DATA,g);
+_outbyte(PEL_DATA,b);
+}
+*/
+
+
+/*
+================
+=
+= IO_TimerISR
+=
+================
+*/
+
+//void __interrupt IO_TimerISR (void)
+
+void __interrupt __far IO_TimerISR (void)
+{
+ ticcount++;
+ _outbyte(0x20,0x20); // Ack the interrupt
+}
+
+/*
+=====================
+=
+= IO_SetTimer0
+=
+= Sets system timer 0 to the specified speed
+=
+=====================
+*/
+
+void IO_SetTimer0(int speed)
+{
+ if (speed > 0 && speed < 150)
+ I_Error ("INT_SetTimer0: %i is a bad value",speed);
+
+ _outbyte(0x43,0x36); // Change timer 0
+ _outbyte(0x40,speed);
+ _outbyte(0x40,speed >> 8);
+}
+
+
+
+/*
+===============
+=
+= IO_StartupTimer
+=
+===============
+*/
+
+/*
+void IO_StartupTimer (void)
+{
+ oldtimerisr = _dos_getvect(TIMERINT);
+
+ _dos_setvect (0x8000 | TIMERINT, IO_TimerISR);
+ IO_SetTimer0 (VBLCOUNTER);
+}
+*/
+
+void IO_ShutdownTimer (void)
+{
+ if (oldtimerisr)
+ {
+ IO_SetTimer0 (0); // back to 18.4 ips
+ _dos_setvect (TIMERINT, oldtimerisr);
+ }
+}
+
+//===========================================================================
+
+
+/*
+===============
+=
+= I_Init
+=
+= hook interrupts and set graphics mode
+=
+===============
+*/
+
+void I_Init (void)
+{
+ extern void I_StartupTimer(void);
+
+ novideo = M_CheckParm("novideo");
+ ST_Message(" I_StartupDPMI\n");
+ I_StartupDPMI();
+ ST_Message(" I_StartupMouse ");
+ I_StartupMouse();
+// tprintf("I_StartupJoystick ",1);
+// I_StartupJoystick();
+// tprintf("I_StartupKeyboard ",1);
+// I_StartupKeyboard();
+ ST_Message(" S_Init... ");
+ S_Init();
+ //IO_StartupTimer();
+ S_Start();
+}
+
+
+/*
+===============
+=
+= I_Shutdown
+=
+= return to default system state
+=
+===============
+*/
+
+void I_Shutdown (void)
+{
+ I_ShutdownGraphics ();
+ IO_ShutdownTimer ();
+ S_ShutDown ();
+ I_ShutdownMouse ();
+ I_ShutdownKeyboard ();
+
+ IO_SetTimer0 (0);
+}
+
+
+/*
+================
+=
+= I_Error
+=
+================
+*/
+
+void I_Error (char *error, ...)
+{
+ union REGS regs;
+
+ va_list argptr;
+
+ D_QuitNetGame ();
+ I_Shutdown ();
+ va_start (argptr,error);
+ regs.x.eax = 0x3;
+ int386(0x10, &regs, &regs);
+ vprintf (error,argptr);
+ va_end (argptr);
+ printf ("\n");
+ exit (1);
+}
+
+//--------------------------------------------------------------------------
+//
+// I_Quit
+//
+// Shuts down net game, saves defaults, prints the exit text message,
+// goes to text mode, and exits.
+//
+//--------------------------------------------------------------------------
+
+void I_Quit(void)
+{
+ D_QuitNetGame();
+ M_SaveDefaults();
+ I_Shutdown();
+
+// scr = (byte *)W_CacheLumpName("ENDTEXT", PU_CACHE);
+/*
+ memcpy((void *)0xb8000, scr, 80*25*2);
+ regs.w.ax = 0x0200;
+ regs.h.bh = 0;
+ regs.h.dl = 0;
+ regs.h.dh = 23;
+ int386(0x10, (const union REGS *)&regs, &regs); // Set text pos
+ _settextposition(24, 1);
+*/
+ printf("\nHexen: Beyond Heretic\n");
+ exit(0);
+}
+
+/*
+===============
+=
+= I_ZoneBase
+=
+===============
+*/
+
+byte *I_ZoneBase (int *size)
+{
+ int meminfo[32];
+ int heap;
+ byte *ptr;
+
+ memset (meminfo,0,sizeof(meminfo));
+ segread(&segregs);
+ segregs.es = segregs.ds;
+ regs.w.ax = 0x500; // get memory info
+ regs.x.edi = (int)&meminfo;
+ int386x( 0x31, &regs, &regs, &segregs );
+
+ heap = meminfo[0];
+ ST_Message (" DPMI memory: 0x%x, ",heap);
+ ST_Message ("Maxzone: 0x%x\n", maxzone);
+
+ do
+ {
+ heap -= 0x10000; // leave 64k alone
+ if (heap > maxzone)
+ heap = maxzone;
+ ptr = malloc (heap);
+ } while (!ptr);
+
+ ST_Message (" 0x%x allocated for zone, ", heap);
+ ST_Message ("ZoneBase: 0x%X\n", (int)ptr);
+
+ if (heap < 0x180000)
+ I_Error (" Insufficient DPMI memory!");
+#if 0
+ regs.w.ax = 0x501; // allocate linear block
+ regs.w.bx = heap>>16;
+ regs.w.cx = heap&0xffff;
+ int386( 0x31, &regs, &regs);
+ if (regs.w.cflag)
+ I_Error (" Couldn't allocate DPMI memory!");
+
+ block = (regs.w.si << 16) + regs.w.di;
+#endif
+
+ *size = heap;
+ return ptr;
+}
+
+/*
+=============
+=
+= I_AllocLow
+=
+=============
+*/
+
+byte *I_AllocLow (int length)
+{
+ byte *mem;
+
+ // DPMI call 100h allocates DOS memory
+ segread(&segregs);
+ regs.w.ax = 0x0100; // DPMI allocate DOS memory
+ regs.w.bx = (length+15) / 16;
+ int386( DPMI_INT, &regs, &regs);
+// segment = regs.w.ax;
+// selector = regs.w.dx;
+ if (regs.w.cflag != 0)
+ I_Error ("I_AllocLow: DOS alloc of %i failed, %i free",
+ length, regs.w.bx*16);
+
+
+ mem = (void *) ((regs.x.eax & 0xFFFF) << 4);
+
+ memset (mem,0,length);
+ return mem;
+}
+
+/*
+============================================================================
+
+ NETWORKING
+
+============================================================================
+*/
+
+/* // FUCKED LINES
+typedef struct
+{
+ char priv[508];
+} doomdata_t;
+*/ // FUCKED LINES
+
+#define DOOMCOM_ID 0x12345678l
+
+/* // FUCKED LINES
+typedef struct
+{
+ long id;
+ short intnum; // DOOM executes an int to execute commands
+
+// communication between DOOM 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 doomdata to be sent
+
+// info common to all nodes
+ short numnodes; // console is allways node 0
+ short ticdup; // 1 = no duplication, 2-5 = dup for slow nets
+ short extratics; // 1 = send a backup tic in every packet
+ short deathmatch; // 1 = deathmatch
+ short savegame; // -1 = new game, 0-5 = load savegame
+ short episode; // 1-3
+ short map; // 1-9
+ short skill; // 1-5
+
+// info specific to this node
+ short consoleplayer;
+ short numplayers;
+ short angleoffset; // 1 = left, 0 = center, -1 = right
+ short drone; // 1 = drone
+
+// packet data to be sent
+ doomdata_t data;
+} doomcom_t;
+*/ // FUCKED LINES
+
+extern doomcom_t *doomcom;
+
+/*
+====================
+=
+= I_InitNetwork
+=
+====================
+*/
+
+void I_InitNetwork (void)
+{
+ int i;
+
+ i = M_CheckParm ("-net");
+ if (!i)
+ {
+ //
+ // single player game
+ //
+ doomcom = malloc (sizeof (*doomcom) );
+ memset (doomcom, 0, sizeof(*doomcom) );
+ netgame = false;
+ doomcom->id = DOOMCOM_ID;
+ doomcom->numplayers = doomcom->numnodes = 1;
+ doomcom->deathmatch = false;
+ doomcom->consoleplayer = 0;
+ doomcom->ticdup = 1;
+ doomcom->extratics = 0;
+ return;
+ }
+
+ netgame = true;
+ doomcom = (doomcom_t *)atoi(myargv[i+1]);
+//DEBUG
+doomcom->skill = startskill;
+doomcom->episode = startepisode;
+doomcom->map = startmap;
+doomcom->deathmatch = deathmatch;
+
+}
+
+void I_NetCmd (void)
+{
+ if (!netgame)
+ I_Error ("I_NetCmd when not in netgame");
+ DPMIInt (doomcom->intnum);
+}
+
+//=========================================================================
+//
+// I_CheckExternDriver
+//
+// Checks to see if a vector, and an address for an external driver
+// have been passed.
+//=========================================================================
+
+void I_CheckExternDriver(void)
+{
+ int i;
+
+ if(!(i = M_CheckParm("-externdriver")))
+ {
+ return;
+ }
+ i_ExternData = (externdata_t *)atoi(myargv[i+1]);
+ i_Vector = i_ExternData->vector;
+
+ useexterndriver = true;
+}
+
+//=========================================================================
+//=========================================================================
+// Hi-Res (mode 12) stuff
+//=========================================================================
+//=========================================================================
+
+
+//==========================================================================
+//
+// SetVideoModeHR - Set video mode to 640x480x16
+//
+//==========================================================================
+
+
+void SetVideoModeHR(void)
+{
+ union REGS regs;
+ regs.x.eax = 0x12;
+ int386(VID_INT, &regs, &regs);
+}
+
+
+//==========================================================================
+//
+// ClearScreenHR - Clear the screen to color 0
+//
+//==========================================================================
+
+void ClearScreenHR(void)
+{
+ BITPLANE(MASK_PLANE0|MASK_PLANE1|MASK_PLANE2|MASK_PLANE3);
+ memset((char *)0xa0000,0,38400);
+}
+
+
+//==========================================================================
+//
+// SlamHR - copy 4-plane buffer to screen
+//
+//==========================================================================
+
+void SlamHR(char *buffer)
+{
+ BITPLANE(MASK_PLANE0);
+ memcpy((char *)0xA0000, buffer+P0OFFSET, 38400);
+ BITPLANE(MASK_PLANE1);
+ memcpy((char *)0xA0000, buffer+P1OFFSET, 38400);
+ BITPLANE(MASK_PLANE2);
+ memcpy((char *)0xA0000, buffer+P2OFFSET, 38400);
+ BITPLANE(MASK_PLANE3);
+ memcpy((char *)0xA0000, buffer+P3OFFSET, 38400);
+}
+
+
+//==========================================================================
+//
+// SlamHR - copy 4-plane buffer to screen
+//
+// X and Width should be a multiple of 8
+// src should be 4 planes of block size, back to back
+//==========================================================================
+
+void SlamBlockHR(int x, int y, int w, int h, char *src)
+{
+ int srcwid = w>>3;
+ char *dest = ((char *)0xA0000) + (y*(640/8)) + (x>>3);
+ char *dst;
+ int i;
+
+ VB_SYNC;
+
+ BITPLANE(MASK_PLANE0);
+ dst = dest;
+ for ( i=0; i<h; i++ )
+ {
+ memcpy(dst, src, srcwid);
+ dst += 640/8;
+ src += srcwid;
+ }
+ BITPLANE(MASK_PLANE1);
+ dst = dest;
+ for ( i=0; i<h; i++ )
+ {
+ memcpy(dst, src, srcwid);
+ dst += 640/8;
+ src += srcwid;
+ }
+ BITPLANE(MASK_PLANE2);
+ dst = dest;
+ for ( i=0; i<h; i++ )
+ {
+ memcpy(dst, src, srcwid);
+ dst += 640/8;
+ src += srcwid;
+ }
+ BITPLANE(MASK_PLANE3);
+ dst = dest;
+ for ( i=0; i<h; i++ )
+ {
+ memcpy(dst, src, srcwid);
+ dst += 640/8;
+ src += srcwid;
+ }
+}
+
+//==========================================================================
+//
+// InitPaletteHR
+//
+//==========================================================================
+
+void InitPaletteHR(void)
+{
+ int i;
+ union REGS regs;
+
+ // Set palette registers to point into color registers
+ for ( i=0; i<16; i++ )
+ {
+ regs.x.eax = (0x10<<8)|0x00;
+ regs.x.ebx = (i<<8)|i;
+ int386(VID_INT, &regs, &regs);
+ }
+
+}
+
+
+//==========================================================================
+//
+// SetPaletteHR - Set the HR palette
+//
+//==========================================================================
+
+void SetPaletteHR(byte *palette)
+{
+ int i;
+ VB_SYNC;
+ outp(PEL_WRITE_ADR, 0);
+
+ for(i = 0; i < 16*3; i++)
+ {
+ outp(PEL_DATA, (*palette++));
+ }
+}
+
+
+//==========================================================================
+//
+// GetPaletteHR - Get the HR palette
+//
+//==========================================================================
+
+void GetPaletteHR(byte *palette)
+{
+ int i;
+ outp(PEL_READ_ADR, 0);
+ for (i=0; i<16*3; i++)
+ {
+ *palette++ = inp(PEL_DATA);
+ }
+}
+
+
+//==========================================================================
+//
+// FadeToPaletteHR
+//
+//==========================================================================
+
+void FadeToPaletteHR(byte *palette)
+{
+ int i,j;
+ int steps=140; // two-seconds
+ byte basep[16*3];
+ byte work[16*3];
+ int delta;
+
+ GetPaletteHR(basep);
+ for(i = 0; i < steps; i++)
+ {
+ for(j = 0; j < 16*3; j++)
+ {
+ delta = palette[j]-basep[j];
+ work[j] = basep[j]+delta*i/steps;
+ }
+ SetPaletteHR(work);
+ }
+ SetPaletteHR(palette);
+}
+
+
+//==========================================================================
+//
+// FadeToBlackHR - Fades the palette out to black
+//
+//==========================================================================
+
+/*
+void FadeToBlackHR(void)
+{
+ char work[16*3];
+ char base[16*3];
+ int i,j,steps=70;
+
+ GetPaletteHR(base);
+ for (i=0; i<steps; i++)
+ {
+ for (j=0; j<16*3; j++)
+ {
+ work[j] = base[j]-(base[j]*i/steps);
+ }
+ VB_SYNC;
+ SetPaletteHR(work);
+ }
+ memset(work,0,16*3);
+ SetPaletteHR(work);
+}
+*/
+
+//==========================================================================
+//
+// BlackPaletteHR - Instantly blacks out the palette
+//
+//==========================================================================
+
+void BlackPaletteHR(void)
+{
+ char blackpal[16*3];
+
+ memset(blackpal,0,16*3);
+ SetPaletteHR(blackpal);
+}
+
+//==========================================================================
+//
+//
+// I_StartupReadKeys
+//
+//
+//==========================================================================
+
+void I_StartupReadKeys(void)
+{
+ int k;
+
+ while (kbdtail < kbdhead)
+ {
+ k = keyboardque[kbdtail&(KBDQUESIZE-1)];
+ kbdtail++;
+ if (k == 1)
+ I_Quit ();
+ }
+}