// Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // // Copyright(C) 1993-1996 Id Software, Inc. // Copyright(C) 1993-2008 Raven Software // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // 02111-1307, USA. // //----------------------------------------------------------------------------- #include #include #include #include #include #include "h2def.h" #include "m_argv.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 *) ®s, ®s); 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, ®s, ®s); // 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, ®s, ®s); 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, ®s, ®s, &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, ®s, ®s, &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, ®s, ®s); #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, ®s, ®s); 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 *)®s, ®s); // 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, ®s, ®s, &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, ®s, ®s); 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, ®s, ®s); // 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, ®s, ®s); } //========================================================================== // // 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, ®s, ®s); } } //========================================================================== // // 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