📄 i_ibm.c
字号:
//**************************************************************************
//**
//** 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -