Subversion Repositories Kolibri OS

Compare Revisions

Ignore whitespace Rev 341 → Rev 342

/programs/games/doom/trunk/d_main.c
436,7 → 436,7
S_UpdateSounds (players[consoleplayer].mo);// move positional sounds
 
D_Display ();
// I_UpdateSound();
// I_UpdateSound();
XXX(105);
}
}
1120,8 → 1120,8
printf ("D_CheckNetGame: Checking network game status.\n\r");
D_CheckNetGame ();
 
// printf ("S_Init: Setting up sound.\n\r");
// S_Init (snd_SfxVolume /* *8 */, snd_MusicVolume /* *8*/ );
printf ("S_Init: Setting up sound.\n\r");
S_Init (snd_SfxVolume /* *8 */, snd_MusicVolume /* *8*/ );
 
printf ("HU_Init: Setting up heads up display.\n\r");
HU_Init ();
/programs/games/doom/trunk/h/doomdata.h
42,17 → 42,17
// to provide a complete scene geometry description.
enum
{
ML_LABEL, // A separator, name, ExMx or MAPxx
ML_THINGS, // Monsters, items..
ML_LINEDEFS, // LineDefs, from editing
ML_SIDEDEFS, // SideDefs, from editing
ML_VERTEXES, // Vertices, edited and BSP splits generated
ML_SEGS, // LineSegs, from LineDefs split by BSP
ML_SSECTORS, // SubSectors, list of LineSegs
ML_NODES, // BSP nodes
ML_SECTORS, // Sectors, from editing
ML_REJECT, // LUT, sector-sector visibility
ML_BLOCKMAP // LUT, motion clipping, walls/grid element
ML_LABEL, // A separator, name, ExMx or MAPxx
ML_THINGS, // Monsters, items..
ML_LINEDEFS, // LineDefs, from editing
ML_SIDEDEFS, // SideDefs, from editing
ML_VERTEXES, // Vertices, edited and BSP splits generated
ML_SEGS, // LineSegs, from LineDefs split by BSP
ML_SSECTORS, // SubSectors, list of LineSegs
ML_NODES, // BSP nodes
ML_SECTORS, // Sectors, from editing
ML_REJECT, // LUT, sector-sector visibility
ML_BLOCKMAP // LUT, motion clipping, walls/grid element
};
 
 
59,8 → 59,8
// A single Vertex.
typedef struct
{
short x;
short y;
short x;
short y;
} mapvertex_t;
 
 
68,13 → 68,13
// by setting textures and offsets.
typedef struct
{
short textureoffset;
short rowoffset;
char toptexture[8];
char bottomtexture[8];
char midtexture[8];
short textureoffset;
short rowoffset;
char toptexture[8];
char bottomtexture[8];
char midtexture[8];
// Front sector, towards viewer.
short sector;
short sector;
} mapsidedef_t;
 
 
83,13 → 83,13
// to the BSP builder.
typedef struct
{
short v1;
short v2;
short flags;
short special;
short tag;
short v1;
short v2;
short flags;
short special;
short tag;
// sidenum[1] will be -1 if one sided
short sidenum[2];
short sidenum[2];
} maplinedef_t;
 
 
98,14 → 98,14
//
 
// Solid, is an obstacle.
#define ML_BLOCKING 1
#define ML_BLOCKING 1
 
// Blocks monsters only.
#define ML_BLOCKMONSTERS 2
#define ML_BLOCKMONSTERS 2
 
// Backside will not be present at all
// if not two sided.
#define ML_TWOSIDED 4
#define ML_TWOSIDED 4
 
// If a texture is pegged, the texture will have
// the end exposed to air held constant at the
117,44 → 117,44
// top and bottom textures (use next to windows).
 
// upper texture unpegged
#define ML_DONTPEGTOP 8
#define ML_DONTPEGTOP 8
 
// lower texture unpegged
#define ML_DONTPEGBOTTOM 16
#define ML_DONTPEGBOTTOM 16
 
// In AutoMap: don't map as two sided: IT'S A SECRET!
#define ML_SECRET 32
#define ML_SECRET 32
 
// Sound rendering: don't let sound cross two of these.
#define ML_SOUNDBLOCK 64
#define ML_SOUNDBLOCK 64
 
// Don't draw on the automap at all.
#define ML_DONTDRAW 128
#define ML_DONTDRAW 128
 
// Set if already seen, thus drawn in automap.
#define ML_MAPPED 256
#define ML_MAPPED 256
 
 
 
 
// Sector definition, from editing.
typedef struct
typedef struct
{
short floorheight;
short ceilingheight;
char floorpic[8];
char ceilingpic[8];
short lightlevel;
short special;
short tag;
short floorheight;
short ceilingheight;
char floorpic[8];
char ceilingpic[8];
short lightlevel;
short special;
short tag;
} mapsector_t;
 
// SubSector, as generated by BSP.
typedef struct
{
short numsegs;
short numsegs;
// Index of first one, segs are stored sequentially.
short firstseg;
short firstseg;
} mapsubsector_t;
 
 
162,12 → 162,12
// using partition lines selected by BSP builder.
typedef struct
{
short v1;
short v2;
short angle;
short linedef;
short side;
short offset;
short v1;
short v2;
short angle;
short linedef;
short side;
short offset;
} mapseg_t;
 
 
175,23 → 175,23
// BSP node structure.
 
// Indicate a leaf.
#define NF_SUBSECTOR 0x8000
#define NF_SUBSECTOR 0x8000
 
typedef struct
{
// Partition line from (x,y) to x+dx,y+dy)
short x;
short y;
short dx;
short dy;
short x;
short y;
short dx;
short dy;
 
// Bounding box for each child,
// clip against view frustum.
short bbox[2][4];
short bbox[2][4];
 
// If NF_SUBSECTOR its a subsector,
// else it's a node of another subtree.
unsigned short children[2];
unsigned short children[2];
 
} mapnode_t;
 
202,11 → 202,11
// plus skill/visibility flags and attributes.
typedef struct
{
short x;
short y;
short angle;
short type;
short options;
short x;
short y;
short angle;
short type;
short options;
} mapthing_t;
 
 
213,7 → 213,7
 
 
 
#endif // __DOOMDATA__
#endif // __DOOMDATA__
//-----------------------------------------------------------------------------
//
// $Log:$
/programs/games/doom/trunk/h/r_defs.h
23,7 → 23,7
#ifndef __R_DEFS__
#define __R_DEFS__
 
 
#include "doomtype.h"
// Screenwidth.
#include "doomdef.h"
 
/programs/games/doom/trunk/i_sound.c
1,671 → 1,685
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// $Log:$
//
// DESCRIPTION:
// System interface for sound.
//
//-----------------------------------------------------------------------------
 
static const char
rcsid[] = "$Id: i_unix.c,v 1.5 1997/02/03 22:45:10 b1 Exp $";
 
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
 
#include <math.h>
 
#include <sys/types.h>
 
#include <fcntl.h>
 
// Timer stuff. Experimental.
#include <time.h>
#include <signal.h>
 
#include "z_zone.h"
 
#include "i_system.h"
#include "i_sound.h"
#include "m_argv.h"
#include "m_misc.h"
#include "w_wad.h"
 
#include "doomdef.h"
 
// The number of internal mixing channels,
// the samples calculated for each mixing step,
// the size of the 16bit, 2 hardware channel (stereo)
// mixing buffer, and the samplerate of the raw data.
 
 
// Needed for calling the actual sound output.
#define SAMPLECOUNT 512
#define NUM_CHANNELS 16
// It is 2 for 16bit, and 2 for two channels.
#define BUFMUL 4
#define MIXBUFFERSIZE (SAMPLECOUNT*BUFMUL)
 
#define SAMPLERATE 11025 // Hz
#define SAMPLESIZE 2 // 16bit
 
// The actual lengths of all sound effects.
int lengths[NUMSFX];
 
// The actual output device.
int audio_fd;
 
// The global mixing buffer.
// Basically, samples from all active internal channels
// are modifed and added, and stored in the buffer
// that is submitted to the audio device.
signed short mixbuffer[MIXBUFFERSIZE];
 
 
// The channel step amount...
unsigned int channelstep[NUM_CHANNELS];
// ... and a 0.16 bit remainder of last step.
unsigned int channelstepremainder[NUM_CHANNELS];
 
 
// The channel data pointers, start and end.
unsigned char* channels[NUM_CHANNELS];
unsigned char* channelsend[NUM_CHANNELS];
 
 
// Time/gametic that the channel started playing,
// used to determine oldest, which automatically
// has lowest priority.
// In case number of active sounds exceeds
// available channels.
int channelstart[NUM_CHANNELS];
 
// The sound in channel handles,
// determined on registration,
// might be used to unregister/stop/modify,
// currently unused.
int channelhandles[NUM_CHANNELS];
 
// SFX id of the playing sound effect.
// Used to catch duplicates (like chainsaw).
int channelids[NUM_CHANNELS];
 
// Pitch to stepping lookup, unused.
int steptable[256];
 
// Volume lookups.
int vol_lookup[128*256];
 
// Hardware left and right channel volume lookup.
int* channelleftvol_lookup[NUM_CHANNELS];
int* channelrightvol_lookup[NUM_CHANNELS];
 
 
//
// This function loads the sound data from the WAD lump,
// for single sound.
//
void* getsfx (char* sfxname, int* len)
{
unsigned char* sfx;
unsigned char* paddedsfx;
int i;
int size;
int paddedsize;
char name[20];
int sfxlump;
 
// Get the sound data from the WAD, allocate lump
// in zone memory.
sprintf(name, "ds%s", sfxname);
 
// Now, there is a severe problem with the
// sound handling, in it is not (yet/anymore)
// gamemode aware. That means, sounds from
// DOOM II will be requested even with DOOM
// shareware.
// The sound list is wired into sounds.c,
// which sets the external variable.
// I do not do runtime patches to that
// variable. Instead, we will use a
// default sound for replacement.
if ( W_CheckNumForName(name) == -1 )
sfxlump = W_GetNumForName("dspistol");
else
sfxlump = W_GetNumForName(name);
size = W_LumpLength( sfxlump );
 
// Debug.
// fprintf( stderr, "." );
//fprintf( stderr, " -loading %s (lump %d, %d bytes)\n",
// sfxname, sfxlump, size );
//fflush( stderr );
sfx = (unsigned char*)W_CacheLumpNum( sfxlump, PU_STATIC );
 
// Pads the sound effect out to the mixing buffer size.
// The original realloc would interfere with zone memory.
paddedsize = ((size-8 + (SAMPLECOUNT-1)) / SAMPLECOUNT) * SAMPLECOUNT;
 
// Allocate from zone memory.
paddedsfx = (unsigned char*)Z_Malloc( paddedsize+8, PU_STATIC, 0 );
// ddt: (unsigned char *) realloc(sfx, paddedsize+8);
// This should interfere with zone memory handling,
// which does not kick in in the soundserver.
 
// Now copy and pad.
memcpy( paddedsfx, sfx, size );
for (i=size ; i<paddedsize+8 ; i++)
paddedsfx[i] = 128;
 
// Remove the cached lump.
Z_Free( sfx );
// Preserve padded length.
*len = paddedsize;
 
// Return allocated padded data.
return (void *) (paddedsfx + 8);
}
 
//
// This function adds a sound to the
// list of currently active sounds,
// which is maintained as a given number
// (eight, usually) of internal channels.
// Returns a handle.
//
 
static unsigned short handlenums = 0;
 
int addsfx(int sfxid, int volume, int step, int seperation)
{
 
int i;
int rc = -1;
int oldest = gametic;
int oldestnum = 0;
int slot;
 
int rightvol;
int leftvol;
 
// Chainsaw troubles.
// Play these sound effects only one at a time.
if ( sfxid == sfx_sawup
|| sfxid == sfx_sawidl
|| sfxid == sfx_sawful
|| sfxid == sfx_sawhit
|| sfxid == sfx_stnmov
|| sfxid == sfx_pistol )
{
// Loop all channels, check.
for (i=0 ; i<NUM_CHANNELS ; i++)
{
// Active, and using the same SFX?
if ( (channels[i])
&& (channelids[i] == sfxid) )
{
// Reset.
channels[i] = 0;
// We are sure that iff,
// there will only be one.
break;
}
}
}
 
// Loop all channels to find oldest SFX.
for (i=0; (i<NUM_CHANNELS) && (channels[i]); i++)
{
if (channelstart[i] < oldest)
{
oldestnum = i;
oldest = channelstart[i];
}
}
 
// Tales from the cryptic.
// If we found a channel, fine.
// If not, we simply overwrite the first one, 0.
// Probably only happens at startup.
if (i == NUM_CHANNELS)
slot = oldestnum;
else
slot = i;
 
// Okay, in the less recent channel,
// we will handle the new SFX.
// Set pointer to raw data.
channels[slot] = (unsigned char *) S_sfx[sfxid].data;
// Set pointer to end of raw data.
channelsend[slot] = channels[slot] + lengths[sfxid];
 
// Reset current handle number, limited to 0..100.
if (!handlenums)
handlenums = 100;
 
// Assign current handle number.
// Preserved so sounds could be stopped (unused).
channelhandles[slot] = rc = handlenums++;
 
channelstep[slot] = step;
channelstepremainder[slot] = 0;
// Should be gametic, I presume.
channelstart[slot] = gametic;
 
// Separation, that is, orientation/stereo.
// range is: 1 - 256
seperation += 1;
volume *=7;
// Per left/right channel.
// x^2 seperation,
// adjust volume properly.
leftvol =
volume - ((volume*seperation*seperation) >> 16); ///(256*256);
seperation = seperation - 257;
rightvol =
volume - ((volume*seperation*seperation) >> 16);
 
// Sanity check, clamp volume.
if (rightvol < 0 || rightvol > 127)
I_Error("rightvol out of bounds");
if (leftvol < 0 || leftvol > 127)
I_Error("leftvol out of bounds");
// Get the proper lookup table piece
// for this volume level???
channelleftvol_lookup[slot] = &vol_lookup[leftvol*256];
channelrightvol_lookup[slot] = &vol_lookup[rightvol*256];
 
// Preserve sound SFX id,
// e.g. for avoiding duplicates of chainsaw.
channelids[slot] = sfxid;
 
// You tell me.
return rc;
}
 
//
// SFX API
// Note: this was called by S_Init.
// However, whatever they did in the
// old DPMS based DOS version, this
// were simply dummies in the Linux
// version.
// See soundserver initdata().
//
void I_SetChannels()
{
// Init internal lookups (raw data, mixing buffer, channels).
// This function sets up internal lookups used during
// the mixing process.
int i;
int j;
int* steptablemid = steptable + 128;
// Okay, reset internal mixing channels to zero.
for (i=0; i<NUM_CHANNELS; i++)
{
channels[i] = 0;
}
 
// for (i=-128 ; i<128 ; i++)
// steptablemid[i] = (int)(pow(2.0, (i/64.0))*65536.0);
// Generates volume lookup tables
// which also turn the unsigned samples
// into signed samples.
for (i=0 ; i<128 ; i++)
for (j=0 ; j<256 ; j++)
vol_lookup[i*256+j] = (i*(j-128)*256)/127;
}
 
void I_SetSfxVolume(int volume)
{
// Identical to DOS.
// Basically, this should propagate
// the menu/config file setting
// to the state variable used in
// the mixing.
snd_SfxVolume = volume;
}
 
// MUSIC API - dummy. Some code from DOS version.
void I_SetMusicVolume(int volume)
{
// Internal state variable.
snd_MusicVolume = volume;
}
 
 
//
// Retrieve the raw data lump index
// for a given SFX name.
//
int I_GetSfxLumpNum(sfxinfo_t* sfx)
{
char namebuf[9];
sprintf(namebuf, "ds%s", sfx->name);
return W_GetNumForName(namebuf);
}
 
//
// Starting a sound means adding it
// to the current list of active sounds
// in the internal channels.
// As the SFX info struct contains
// e.g. a pointer to the raw data,
// it is ignored.
// As our sound handling does not handle
// priority, it is ignored.
// Pitching (that is, increased speed of playback)
//
int I_StartSound(int id, int vol, int sep,
int pitch, int priority )
{
// Returns a handle (not used).
id = addsfx( id, vol, steptable[pitch], sep );
return id;
}
 
void I_StopSound (int handle)
{
// You need the handle returned by StartSound.
// Would be looping all channels,
// tracking down the handle,
// an setting the channel to zero.
// UNUSED.
handle = 0;
}
 
 
int I_SoundIsPlaying(int handle)
{
// Ouch.
return gametic < handle;
}
 
//
// This function loops all active (internal) sound
// channels, retrieves a given number of samples
// from the raw sound data, modifies it according
// to the current (internal) channel parameters,
// mixes the per channel samples into the global
// mixbuffer, clamping it to the allowed range,
// and sets up everything for transferring the
// contents of the mixbuffer to the (two)
// hardware channels (left and right, that is).
//
// This function currently supports only 16bit.
//
void I_UpdateSound( void )
{
// Mix current sound data.
// Data, from raw sound, for right and left.
register unsigned int sample;
register int dl;
register int dr;
// Pointers in global mixbuffer, left, right, end.
signed short* leftout;
signed short* rightout;
signed short* leftend;
// Step in mixbuffer, left and right, thus two.
int step;
 
// Mixing channel index.
int chan;
// Left and right channel
// are in global mixbuffer, alternating.
leftout = mixbuffer;
rightout = mixbuffer+1;
step = 2;
 
// Determine end, for left channel only
// (right channel is implicit).
leftend = mixbuffer + SAMPLECOUNT*step;
 
// Mix sounds into the mixing buffer.
// Loop over step*SAMPLECOUNT,
// that is 512 values for two channels.
while (leftout != leftend)
{
// Reset left/right value.
dl = 0;
dr = 0;
 
// Love thy L2 chache - made this a loop.
// Now more channels could be set at compile time
// as well. Thus loop those channels.
for ( chan = 0; chan < NUM_CHANNELS; chan++ )
{
// Check channel, if active.
if (channels[ chan ])
{
// Get the raw data from the channel.
sample = *channels[ chan ];
// Add left and right part
// for this channel (sound)
// to the current data.
// Adjust volume accordingly.
dl += channelleftvol_lookup[ chan ][sample];
dr += channelrightvol_lookup[ chan ][sample];
channelstepremainder[ chan ] += channelstep[ chan ];
channels[ chan ] += channelstepremainder[ chan ] >> 16;
channelstepremainder[ chan ] &= 65536-1;
 
// Check whether we are done.
if (channels[ chan ] >= channelsend[ chan ])
channels[ chan ] = 0;
}
}
// Clamp to range. Left hardware channel.
// Has been char instead of short.
// if (dl > 127) *leftout = 127;
// else if (dl < -128) *leftout = -128;
// else *leftout = dl;
 
if (dl > 0x7fff)
*leftout = 0x7fff;
else if (dl < -0x8000)
*leftout = -0x8000;
else
*leftout = dl;
 
// Same for right hardware channel.
if (dr > 0x7fff)
*rightout = 0x7fff;
else if (dr < -0x8000)
*rightout = -0x8000;
else
*rightout = dr;
 
// Increment current pointers in mixbuffer.
leftout += step;
rightout += step;
}
// I_SubmitSound(mixbuffer);
}
 
 
//
// This would be used to write out the mixbuffer
// during each game loop update.
// Updates sound buffer and audio device at runtime.
// It is called during Timer interrupt with SNDINTR.
// Mixing now done synchronous, and
// only output be done asynchronous?
//
//void I_SubmitSound(void)
//{
// Write it to DSP device.
// write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL);
//}
 
 
void I_UpdateSoundParams(int handle, int vol, int sep, int pitch)
{
// I fail too see that this is used.
// Would be using the handle to identify
// on which channel the sound might be active,
// and resetting the channel parameters.
 
// UNUSED.
handle = vol = sep = pitch = 0;
}
 
void I_ShutdownSound(void)
{
// Wait till all pending sounds are finished.
int done = 0;
int i;
// FIXME (below).
printf( "I_ShutdownSound: NOT finishing pending sounds\n");
while ( !done )
{
for( i=0 ; i<8 && !channels[i] ; i++);
// FIXME. No proper channel output.
//if (i==8)
done=1;
}
return;
}
 
void I_InitSound()
{ int i;
 
printf("I_InitSound: ");
for (i=1 ; i<NUMSFX ; i++)
{
// Alias? Example is the chaingun sound linked to pistol.
if (!S_sfx[i].link)
{
// Load data from WAD file.
S_sfx[i].data = getsfx( S_sfx[i].name, &lengths[i] );
}
else
{
// Previously loaded already?
S_sfx[i].data = S_sfx[i].link->data;
lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)];
}
}
 
printf( " pre-cached all sound data\n");
// Now initialize mixbuffer with zero.
for ( i = 0; i< MIXBUFFERSIZE; i++ )
mixbuffer[i] = 0;
// Finished initialization.
printf("I_InitSound: sound module ready\n");
}
 
 
//
// MUSIC API.
// Still no music done.
// Remains. Dummies.
//
void I_InitMusic(void) { }
void I_ShutdownMusic(void) { }
 
static int looping=0;
static int musicdies=-1;
 
void I_PlaySong(int handle, int looping)
{
// UNUSED.
handle = looping = 0;
musicdies = gametic + TICRATE*30;
}
 
void I_PauseSong (int handle)
{
// UNUSED.
handle = 0;
}
 
void I_ResumeSong (int handle)
{
// UNUSED.
handle = 0;
}
 
void I_StopSong(int handle)
{
// UNUSED.
handle = 0;
looping = 0;
musicdies = 0;
}
 
void I_UnRegisterSong(int handle)
{
// UNUSED.
handle = 0;
}
 
int I_RegisterSong(void* data)
{
// UNUSED.
data = NULL;
return 1;
}
 
// Is the song playing?
int I_QrySongPlaying(int handle)
{
// UNUSED.
handle = 0;
return looping || musicdies > gametic;
}
 
 
// Interrupt handler.
void I_HandleSoundTimer( int ignore )
{
// UNUSED, but required.
ignore = 0;
return;
}
 
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// $Log:$
//
// DESCRIPTION:
// System interface for sound.
//
//-----------------------------------------------------------------------------
 
static const char
rcsid[] = "$Id: i_unix.c,v 1.5 1997/02/03 22:45:10 b1 Exp $";
 
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
 
#include <math.h>
 
#include <sys/types.h>
 
#include <fcntl.h>
 
// Timer stuff. Experimental.
#include <time.h>
#include <signal.h>
 
#include "z_zone.h"
 
#include "i_system.h"
#include "i_sound.h"
#include "m_argv.h"
#include "m_misc.h"
#include "w_wad.h"
 
#include "doomdef.h"
 
#include "kolibri.h"
 
// The number of internal mixing channels,
// the samples calculated for each mixing step,
// the size of the 16bit, 2 hardware channel (stereo)
// mixing buffer, and the samplerate of the raw data.
 
 
// Needed for calling the actual sound output.
#define SAMPLECOUNT 8192
#define NUM_CHANNELS 16
// It is 2 for 16bit, and 2 for two channels.
#define BUFMUL 4
#define MIXBUFFERSIZE (SAMPLECOUNT*BUFMUL)
 
#define SAMPLERATE 11025 // Hz
#define SAMPLESIZE 2 // 16bit
 
// The actual lengths of all sound effects.
int lengths[NUMSFX];
 
// The actual output device.
int audio_fd;
 
// The global mixing buffer.
// Basically, samples from all active internal channels
// are modifed and added, and stored in the buffer
// that is submitted to the audio device.
signed short mixbuffer[MIXBUFFERSIZE];
 
 
// The channel step amount...
unsigned int channelstep[NUM_CHANNELS];
// ... and a 0.16 bit remainder of last step.
unsigned int channelstepremainder[NUM_CHANNELS];
 
 
// The channel data pointers, start and end.
unsigned char* channels[NUM_CHANNELS];
unsigned char* channelsend[NUM_CHANNELS];
 
 
// Time/gametic that the channel started playing,
// used to determine oldest, which automatically
// has lowest priority.
// In case number of active sounds exceeds
// available channels.
int channelstart[NUM_CHANNELS];
 
// The sound in channel handles,
// determined on registration,
// might be used to unregister/stop/modify,
// currently unused.
int channelhandles[NUM_CHANNELS];
 
// SFX id of the playing sound effect.
// Used to catch duplicates (like chainsaw).
int channelids[NUM_CHANNELS];
 
// Pitch to stepping lookup, unused.
int steptable[256];
 
// Volume lookups.
int vol_lookup[128*256];
 
// Hardware left and right channel volume lookup.
int* channelleftvol_lookup[NUM_CHANNELS];
int* channelrightvol_lookup[NUM_CHANNELS];
 
 
//
// This function loads the sound data from the WAD lump,
// for single sound.
//
void* getsfx (char* sfxname, int* len)
{
unsigned char* sfx;
unsigned char* paddedsfx;
int i;
int size;
int paddedsize;
char name[20];
int sfxlump;
 
// Get the sound data from the WAD, allocate lump
// in zone memory.
sprintf(name, "ds%s", sfxname);
 
// Now, there is a severe problem with the
// sound handling, in it is not (yet/anymore)
// gamemode aware. That means, sounds from
// DOOM II will be requested even with DOOM
// shareware.
// The sound list is wired into sounds.c,
// which sets the external variable.
// I do not do runtime patches to that
// variable. Instead, we will use a
// default sound for replacement.
if ( W_CheckNumForName(name) == -1 )
sfxlump = W_GetNumForName("dspistol");
else
sfxlump = W_GetNumForName(name);
size = W_LumpLength( sfxlump );
 
// Debug.
// fprintf( stderr, "." );
//fprintf( stderr, " -loading %s (lump %d, %d bytes)\n",
// sfxname, sfxlump, size );
//fflush( stderr );
sfx = (unsigned char*)W_CacheLumpNum( sfxlump, PU_STATIC );
 
// Pads the sound effect out to the mixing buffer size.
// The original realloc would interfere with zone memory.
paddedsize = ((size-8 + (SAMPLECOUNT-1)) / SAMPLECOUNT) * SAMPLECOUNT;
 
// Allocate from zone memory.
paddedsfx = (unsigned char*)Z_Malloc( paddedsize+8, PU_STATIC, 0 );
// ddt: (unsigned char *) realloc(sfx, paddedsize+8);
// This should interfere with zone memory handling,
// which does not kick in in the soundserver.
 
// Now copy and pad.
memcpy( paddedsfx, sfx, size );
for (i=size ; i<paddedsize+8 ; i++)
paddedsfx[i] = 128;
 
// Remove the cached lump.
Z_Free( sfx );
// Preserve padded length.
*len = paddedsize;
 
// Return allocated padded data.
return (void *) (paddedsfx + 8);
}
 
//
// This function adds a sound to the
// list of currently active sounds,
// which is maintained as a given number
// (eight, usually) of internal channels.
// Returns a handle.
//
 
static unsigned short handlenums = 0;
 
int addsfx(int sfxid, int volume, int step, int seperation)
{
 
int i;
int rc = -1;
int oldest = gametic;
int oldestnum = 0;
int slot;
 
int rightvol;
int leftvol;
 
// Chainsaw troubles.
// Play these sound effects only one at a time.
if ( sfxid == sfx_sawup
|| sfxid == sfx_sawidl
|| sfxid == sfx_sawful
|| sfxid == sfx_sawhit
|| sfxid == sfx_stnmov
|| sfxid == sfx_pistol )
{
// Loop all channels, check.
for (i=0 ; i<NUM_CHANNELS ; i++)
{
// Active, and using the same SFX?
if ( (channels[i])
&& (channelids[i] == sfxid) )
{
// Reset.
channels[i] = 0;
// We are sure that iff,
// there will only be one.
break;
}
}
}
 
// Loop all channels to find oldest SFX.
for (i=0; (i<NUM_CHANNELS) && (channels[i]); i++)
{
if (channelstart[i] < oldest)
{
oldestnum = i;
oldest = channelstart[i];
}
}
 
// Tales from the cryptic.
// If we found a channel, fine.
// If not, we simply overwrite the first one, 0.
// Probably only happens at startup.
if (i == NUM_CHANNELS)
slot = oldestnum;
else
slot = i;
 
// Okay, in the less recent channel,
// we will handle the new SFX.
// Set pointer to raw data.
channels[slot] = (unsigned char *) S_sfx[sfxid].data;
// Set pointer to end of raw data.
channelsend[slot] = channels[slot] + lengths[sfxid];
 
// Reset current handle number, limited to 0..100.
if (!handlenums)
handlenums = 100;
 
// Assign current handle number.
// Preserved so sounds could be stopped (unused).
channelhandles[slot] = rc = handlenums++;
 
channelstep[slot] = step;
channelstepremainder[slot] = 0;
// Should be gametic, I presume.
channelstart[slot] = gametic;
 
// Separation, that is, orientation/stereo.
// range is: 1 - 256
seperation += 1;
volume *=7;
// Per left/right channel.
// x^2 seperation,
// adjust volume properly.
leftvol =
volume - ((volume*seperation*seperation) >> 16); ///(256*256);
seperation = seperation - 257;
rightvol =
volume - ((volume*seperation*seperation) >> 16);
 
// Sanity check, clamp volume.
if (rightvol < 0 || rightvol > 127)
I_Error("rightvol out of bounds");
if (leftvol < 0 || leftvol > 127)
I_Error("leftvol out of bounds");
// Get the proper lookup table piece
// for this volume level???
channelleftvol_lookup[slot] = &vol_lookup[leftvol*256];
channelrightvol_lookup[slot] = &vol_lookup[rightvol*256];
 
// Preserve sound SFX id,
// e.g. for avoiding duplicates of chainsaw.
channelids[slot] = sfxid;
 
// You tell me.
return rc;
}
 
//
// SFX API
// Note: this was called by S_Init.
// However, whatever they did in the
// old DPMS based DOS version, this
// were simply dummies in the Linux
// version.
// See soundserver initdata().
//
void I_SetChannels()
{
// Init internal lookups (raw data, mixing buffer, channels).
// This function sets up internal lookups used during
// the mixing process.
int i;
int j;
int* steptablemid = steptable + 128;
// Okay, reset internal mixing channels to zero.
for (i=0; i<NUM_CHANNELS; i++)
{
channels[i] = 0;
}
 
for (i=-128 ; i<128 ; i++)
steptablemid[i] = (int)(pow(2.0, (i/64.0))*65536.0);
// Generates volume lookup tables
// which also turn the unsigned samples
// into signed samples.
for (i=0 ; i<128 ; i++)
for (j=0 ; j<256 ; j++)
vol_lookup[i*256+j] = (i*(j-128)*256)/127;
}
 
void I_SetSfxVolume(int volume)
{
// Identical to DOS.
// Basically, this should propagate
// the menu/config file setting
// to the state variable used in
// the mixing.
snd_SfxVolume = volume;
}
 
// MUSIC API - dummy. Some code from DOS version.
void I_SetMusicVolume(int volume)
{
// Internal state variable.
snd_MusicVolume = volume;
}
 
 
//
// Retrieve the raw data lump index
// for a given SFX name.
//
int I_GetSfxLumpNum(sfxinfo_t* sfx)
{
char namebuf[9];
sprintf(namebuf, "ds%s", sfx->name);
return W_GetNumForName(namebuf);
}
 
//
// Starting a sound means adding it
// to the current list of active sounds
// in the internal channels.
// As the SFX info struct contains
// e.g. a pointer to the raw data,
// it is ignored.
// As our sound handling does not handle
// priority, it is ignored.
// Pitching (that is, increased speed of playback)
//
int I_StartSound(int id, int vol, int sep,
int pitch, int priority )
{
// Returns a handle (not used).
id = addsfx( id, vol, steptable[pitch], sep );
return id;
}
 
void I_StopSound (int handle)
{
// You need the handle returned by StartSound.
// Would be looping all channels,
// tracking down the handle,
// an setting the channel to zero.
// UNUSED.
handle = 0;
}
 
 
int I_SoundIsPlaying(int handle)
{
// Ouch.
return gametic < handle;
}
 
//
// This function loops all active (internal) sound
// channels, retrieves a given number of samples
// from the raw sound data, modifies it according
// to the current (internal) channel parameters,
// mixes the per channel samples into the global
// mixbuffer, clamping it to the allowed range,
// and sets up everything for transferring the
// contents of the mixbuffer to the (two)
// hardware channels (left and right, that is).
//
// This function currently supports only 16bit.
//
 
extern DWORD hMixBuff[4];
extern int mix_ptr;
 
void I_UpdateSound( void )
{
// Mix current sound data.
// Data, from raw sound, for right and left.
register unsigned int sample;
register int dl;
register int dr;
// Pointers in global mixbuffer, left, right, end.
signed short* leftout;
signed short* rightout;
signed short* leftend;
// Step in mixbuffer, left and right, thus two.
int step;
 
// Mixing channel index.
int chan;
int i;
int flags;
flags = 0;
// Left and right channel
// are in global mixbuffer, alternating.
leftout = mixbuffer;
rightout = mixbuffer+1;
step = 2;
 
// Determine end, for left channel only
// (right channel is implicit).
leftend = mixbuffer + SAMPLECOUNT*step;
 
// Mix sounds into the mixing buffer.
// Loop over step*SAMPLECOUNT,
// that is 512 values for two channels.
for (i=0; i < 8192; i++)
{
// Reset left/right value.
dl = 0;
dr = 0;
 
// Love thy L2 chache - made this a loop.
// Now more channels could be set at compile time
// as well. Thus loop those channels.
for ( chan = 0; chan < NUM_CHANNELS; chan++ )
{
// Check channel, if active.
if (channels[ chan ])
{
flags=1;
// Get the raw data from the channel.
sample = *channels[ chan ];
// Add left and right part
// for this channel (sound)
// to the current data.
// Adjust volume accordingly.
dl += channelleftvol_lookup[ chan ][sample];
dr += channelrightvol_lookup[ chan ][sample];
channelstepremainder[ chan ] += channelstep[ chan ];
channels[ chan ] += channelstepremainder[ chan ] >> 16;
channelstepremainder[ chan ] &= 65536-1;
 
// Check whether we are done.
if (channels[ chan ] >= channelsend[ chan ])
channels[ chan ] = 0;
}
}
// Clamp to range. Left hardware channel.
// Has been char instead of short.
// if (dl > 127) *leftout = 127;
// else if (dl < -128) *leftout = -128;
// else *leftout = dl;
 
if (dl > 0x7fff)
*leftout = 0x7fff;
else if (dl < -0x8000)
*leftout = -0x8000;
else
*leftout = dl;
 
// Same for right hardware channel.
if (dr > 0x7fff)
*rightout = 0x7fff;
else if (dr < -0x8000)
*rightout = -0x8000;
else
*rightout = dr;
 
// Increment current pointers in mixbuffer.
leftout += step;
rightout += step;
}
if(flags)
{ WaveOut(hMixBuff[mix_ptr],(char*)&mixbuffer[0],32768);
mix_ptr= (mix_ptr+1)&3;
};
}
 
 
//
// This would be used to write out the mixbuffer
// during each game loop update.
// Updates sound buffer and audio device at runtime.
// It is called during Timer interrupt with SNDINTR.
// Mixing now done synchronous, and
// only output be done asynchronous?
//
//void I_SubmitSound(void)
//{
// Write it to DSP device.
// write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL);
//}
 
 
void I_UpdateSoundParams(int handle, int vol, int sep, int pitch)
{
// I fail too see that this is used.
// Would be using the handle to identify
// on which channel the sound might be active,
// and resetting the channel parameters.
 
// UNUSED.
handle = vol = sep = pitch = 0;
}
 
void I_ShutdownSound(void)
{
// Wait till all pending sounds are finished.
int done = 0;
int i;
// FIXME (below).
printf( "I_ShutdownSound: NOT finishing pending sounds\n");
while ( !done )
{
for( i=0 ; i<8 && !channels[i] ; i++);
// FIXME. No proper channel output.
//if (i==8)
done=1;
}
return;
}
 
void I_InitSound()
{ int i;
 
printf("I_InitSound: ");
for (i=1 ; i<NUMSFX ; i++)
{
// Alias? Example is the chaingun sound linked to pistol.
if (!S_sfx[i].link)
{
// Load data from WAD file.
S_sfx[i].data = getsfx( S_sfx[i].name, &lengths[i] );
}
else
{
// Previously loaded already?
S_sfx[i].data = S_sfx[i].link->data;
lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)];
}
}
 
printf( " pre-cached all sound data\n");
// Now initialize mixbuffer with zero.
for ( i = 0; i< MIXBUFFERSIZE; i++ )
mixbuffer[i] = 0;
// Finished initialization.
printf("I_InitSound: sound module ready\n");
}
 
 
//
// MUSIC API.
// Still no music done.
// Remains. Dummies.
//
void I_InitMusic(void) { }
void I_ShutdownMusic(void) { }
 
static int looping=0;
static int musicdies=-1;
 
void I_PlaySong(int handle, int looping)
{
// UNUSED.
handle = looping = 0;
musicdies = gametic + TICRATE*30;
}
 
void I_PauseSong (int handle)
{
// UNUSED.
handle = 0;
}
 
void I_ResumeSong (int handle)
{
// UNUSED.
handle = 0;
}
 
void I_StopSong(int handle)
{
// UNUSED.
handle = 0;
looping = 0;
musicdies = 0;
}
 
void I_UnRegisterSong(int handle)
{
// UNUSED.
handle = 0;
}
 
int I_RegisterSong(void* data)
{
// UNUSED.
data = NULL;
return 1;
}
 
// Is the song playing?
int I_QrySongPlaying(int handle)
{
// UNUSED.
handle = 0;
return looping || musicdies > gametic;
}
 
 
// Interrupt handler.
void I_HandleSoundTimer( int ignore )
{
// UNUSED, but required.
ignore = 0;
return;
}
 
/programs/games/doom/trunk/i_system.c
99,7 → 99,7
void I_Init (void)
{
I_InitGraphics();
// I_InitSound();
I_InitSound();
}
 
//
/programs/games/doom/trunk/m_fixed.c
17,7 → 17,7
// $Log:$
//
// DESCRIPTION:
// Fixed point implementation.
// Fixed point implementation.
//
//-----------------------------------------------------------------------------
 
42,8 → 42,8
 
fixed_t
FixedMul
( fixed_t a,
fixed_t b )
( fixed_t a,
fixed_t b )
{
return ((long long) a * (long long) b) >> FRACBITS;
}
56,11 → 56,11
 
fixed_t
FixedDiv
( fixed_t a,
fixed_t b )
( fixed_t a,
fixed_t b )
{
if ( (abs(a)>>14) >= abs(b))
return (a^b)<0 ? MININT : MAXINT;
return (a^b)<0 ? MININT : MAXINT;
return FixedDiv2 (a,b);
}
 
68,8 → 68,8
 
fixed_t
FixedDiv2
( fixed_t a,
fixed_t b )
( fixed_t a,
fixed_t b )
{
#if 0
long long c;
82,6 → 82,6
c = ((double)a) / ((double)b) * FRACUNIT;
 
if (c >= 2147483648.0 || c < -2147483648.0)
I_Error("FixedDiv: divide by zero");
I_Error("FixedDiv: divide by zero");
return (fixed_t) c;
}
/programs/games/doom/trunk/p_map.c
17,8 → 17,8
// $Log:$
//
// DESCRIPTION:
// Movement, collision handling.
// Shooting and aiming.
// Movement, collision handling.
// Shooting and aiming.
//
//-----------------------------------------------------------------------------
 
27,6 → 27,7
 
#include <stdlib.h>
 
#include "doomtype.h"
#include "m_bbox.h"
#include "m_random.h"
#include "i_system.h"
43,31 → 44,31
#include "sounds.h"
 
 
fixed_t tmbbox[4];
mobj_t* tmthing;
int tmflags;
fixed_t tmx;
fixed_t tmy;
fixed_t tmbbox[4];
mobj_t* tmthing;
int tmflags;
fixed_t tmx;
fixed_t tmy;
 
 
// If "floatok" true, move would be ok
// if within "tmfloorz - tmceilingz".
boolean floatok;
boolean floatok;
 
fixed_t tmfloorz;
fixed_t tmceilingz;
fixed_t tmdropoffz;
fixed_t tmfloorz;
fixed_t tmceilingz;
fixed_t tmdropoffz;
 
// keep track of the line that lowers the ceiling,
// so missiles don't explode against sky hack walls
line_t* ceilingline;
line_t* ceilingline;
 
// keep track of special lines as they are hit,
// but don't process them until the move is proven valid
#define MAXSPECIALCROSS 8
#define MAXSPECIALCROSS 8
 
line_t* spechit[MAXSPECIALCROSS];
int numspechit;
line_t* spechit[MAXSPECIALCROSS];
int numspechit;
 
 
 
80,30 → 81,30
//
boolean PIT_StompThing (mobj_t* thing)
{
fixed_t blockdist;
fixed_t blockdist;
if (!(thing->flags & MF_SHOOTABLE) )
return true;
return true;
blockdist = thing->radius + tmthing->radius;
if ( abs(thing->x - tmx) >= blockdist
|| abs(thing->y - tmy) >= blockdist )
|| abs(thing->y - tmy) >= blockdist )
{
// didn't hit it
return true;
// didn't hit it
return true;
}
// don't clip against self
if (thing == tmthing)
return true;
return true;
// monsters don't stomp things except on boss level
if ( !tmthing->player && gamemap != 30)
return false;
return false;
P_DamageMobj (thing, tmthing, tmthing, 10000);
return true;
}
 
113,26 → 114,26
//
boolean
P_TeleportMove
( mobj_t* thing,
fixed_t x,
fixed_t y )
( mobj_t* thing,
fixed_t x,
fixed_t y )
{
int xl;
int xh;
int yl;
int yh;
int bx;
int by;
int xl;
int xh;
int yl;
int yh;
int bx;
int by;
subsector_t* newsubsec;
subsector_t* newsubsec;
// kill anything occupying the position
tmthing = thing;
tmflags = thing->flags;
tmx = x;
tmy = y;
tmbbox[BOXTOP] = y + tmthing->radius;
tmbbox[BOXBOTTOM] = y - tmthing->radius;
tmbbox[BOXRIGHT] = x + tmthing->radius;
147,7 → 148,7
// will adjust them.
tmfloorz = tmdropoffz = newsubsec->sector->floorheight;
tmceilingz = newsubsec->sector->ceilingheight;
validcount++;
numspechit = 0;
158,9 → 159,9
yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
 
for (bx=xl ; bx<=xh ; bx++)
for (by=yl ; by<=yh ; by++)
if (!P_BlockThingsIterator(bx,by,PIT_StompThing))
return false;
for (by=yl ; by<=yh ; by++)
if (!P_BlockThingsIterator(bx,by,PIT_StompThing))
return false;
// the move is ok,
// so link the thing into its new position
167,12 → 168,12
P_UnsetThingPosition (thing);
 
thing->floorz = tmfloorz;
thing->ceilingz = tmceilingz;
thing->ceilingz = tmceilingz;
thing->x = x;
thing->y = y;
 
P_SetThingPosition (thing);
return true;
}
 
189,14 → 190,14
boolean PIT_CheckLine (line_t* ld)
{
if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT]
|| tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
|| tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM]
|| tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] )
return true;
|| tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
|| tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM]
|| tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] )
return true;
 
if (P_BoxOnLineSide (tmbbox, ld) != -1)
return true;
return true;
// A line has been hit
// The moving thing's destination position will cross
209,38 → 210,38
// could be crossed in either order.
if (!ld->backsector)
return false; // one sided line
return false; // one sided line
if (!(tmthing->flags & MF_MISSILE) )
{
if ( ld->flags & ML_BLOCKING )
return false; // explicitly blocking everything
if ( ld->flags & ML_BLOCKING )
return false; // explicitly blocking everything
 
if ( !tmthing->player && ld->flags & ML_BLOCKMONSTERS )
return false; // block monsters only
if ( !tmthing->player && ld->flags & ML_BLOCKMONSTERS )
return false; // block monsters only
}
 
// set openrange, opentop, openbottom
P_LineOpening (ld);
P_LineOpening (ld);
// adjust floor / ceiling heights
if (opentop < tmceilingz)
{
tmceilingz = opentop;
ceilingline = ld;
tmceilingz = opentop;
ceilingline = ld;
}
 
if (openbottom > tmfloorz)
tmfloorz = openbottom;
tmfloorz = openbottom;
 
if (lowfloor < tmdropoffz)
tmdropoffz = lowfloor;
tmdropoffz = lowfloor;
// if contacted a special line, add it to the list
if (ld->special)
{
spechit[numspechit] = ld;
numspechit++;
spechit[numspechit] = ld;
numspechit++;
}
 
return true;
251,39 → 252,39
//
boolean PIT_CheckThing (mobj_t* thing)
{
fixed_t blockdist;
boolean solid;
int damage;
fixed_t blockdist;
boolean solid;
int damage;
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE) ))
return true;
return true;
blockdist = thing->radius + tmthing->radius;
 
if ( abs(thing->x - tmx) >= blockdist
|| abs(thing->y - tmy) >= blockdist )
|| abs(thing->y - tmy) >= blockdist )
{
// didn't hit it
return true;
// didn't hit it
return true;
}
// don't clip against self
if (thing == tmthing)
return true;
return true;
// check for skulls slamming into things
if (tmthing->flags & MF_SKULLFLY)
{
damage = ((P_Random()%8)+1)*tmthing->info->damage;
P_DamageMobj (thing, tmthing, tmthing, damage);
tmthing->flags &= ~MF_SKULLFLY;
tmthing->momx = tmthing->momy = tmthing->momz = 0;
P_SetMobjState (tmthing, tmthing->info->spawnstate);
return false; // stop moving
damage = ((P_Random()%8)+1)*tmthing->info->damage;
P_DamageMobj (thing, tmthing, tmthing, damage);
tmthing->flags &= ~MF_SKULLFLY;
tmthing->momx = tmthing->momy = tmthing->momz = 0;
P_SetMobjState (tmthing, tmthing->info->spawnstate);
return false; // stop moving
}
 
290,55 → 291,55
// missiles can hit other things
if (tmthing->flags & MF_MISSILE)
{
// see if it went over / under
if (tmthing->z > thing->z + thing->height)
return true; // overhead
if (tmthing->z+tmthing->height < thing->z)
return true; // underneath
if (tmthing->target && (
tmthing->target->type == thing->type ||
(tmthing->target->type == MT_KNIGHT && thing->type == MT_BRUISER)||
(tmthing->target->type == MT_BRUISER && thing->type == MT_KNIGHT) ) )
{
// Don't hit same species as originator.
if (thing == tmthing->target)
return true;
// see if it went over / under
if (tmthing->z > thing->z + thing->height)
return true; // overhead
if (tmthing->z+tmthing->height < thing->z)
return true; // underneath
if (tmthing->target && (
tmthing->target->type == thing->type ||
(tmthing->target->type == MT_KNIGHT && thing->type == MT_BRUISER)||
(tmthing->target->type == MT_BRUISER && thing->type == MT_KNIGHT) ) )
{
// Don't hit same species as originator.
if (thing == tmthing->target)
return true;
 
if (thing->type != MT_PLAYER)
{
// Explode, but do no damage.
// Let players missile other players.
return false;
}
}
if (! (thing->flags & MF_SHOOTABLE) )
{
// didn't do any damage
return !(thing->flags & MF_SOLID);
}
// damage / explode
damage = ((P_Random()%8)+1)*tmthing->info->damage;
P_DamageMobj (thing, tmthing, tmthing->target, damage);
if (thing->type != MT_PLAYER)
{
// Explode, but do no damage.
// Let players missile other players.
return false;
}
}
if (! (thing->flags & MF_SHOOTABLE) )
{
// didn't do any damage
return !(thing->flags & MF_SOLID);
}
// damage / explode
damage = ((P_Random()%8)+1)*tmthing->info->damage;
P_DamageMobj (thing, tmthing, tmthing->target, damage);
 
// don't traverse any more
return false;
// don't traverse any more
return false;
}
// check for special pickup
if (thing->flags & MF_SPECIAL)
{
solid = thing->flags&MF_SOLID;
if (tmflags&MF_PICKUP)
{
// can remove thing
P_TouchSpecialThing (thing, tmthing);
}
return !solid;
solid = thing->flags&MF_SOLID;
if (tmflags&MF_PICKUP)
{
// can remove thing
P_TouchSpecialThing (thing, tmthing);
}
return !solid;
}
return !(thing->flags & MF_SOLID);
}
 
373,24 → 374,24
//
boolean
P_CheckPosition
( mobj_t* thing,
fixed_t x,
fixed_t y )
( mobj_t* thing,
fixed_t x,
fixed_t y )
{
int xl;
int xh;
int yl;
int yh;
int bx;
int by;
subsector_t* newsubsec;
int xl;
int xh;
int yl;
int yh;
int bx;
int by;
subsector_t* newsubsec;
 
tmthing = thing;
tmflags = thing->flags;
tmx = x;
tmy = y;
tmbbox[BOXTOP] = y + tmthing->radius;
tmbbox[BOXBOTTOM] = y - tmthing->radius;
tmbbox[BOXRIGHT] = x + tmthing->radius;
405,12 → 406,12
// will adjust them.
tmfloorz = tmdropoffz = newsubsec->sector->floorheight;
tmceilingz = newsubsec->sector->ceilingheight;
validcount++;
numspechit = 0;
 
if ( tmflags & MF_NOCLIP )
return true;
return true;
// Check things first, possibly picking things up.
// The bounding box is extended by MAXRADIUS
423,9 → 424,9
yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
 
for (bx=xl ; bx<=xh ; bx++)
for (by=yl ; by<=yh ; by++)
if (!P_BlockThingsIterator(bx,by,PIT_CheckThing))
return false;
for (by=yl ; by<=yh ; by++)
if (!P_BlockThingsIterator(bx,by,PIT_CheckThing))
return false;
// check lines
xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
434,9 → 435,9
yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
 
for (bx=xl ; bx<=xh ; bx++)
for (by=yl ; by<=yh ; by++)
if (!P_BlockLinesIterator (bx,by,PIT_CheckLine))
return false;
for (by=yl ; by<=yh ; by++)
if (!P_BlockLinesIterator (bx,by,PIT_CheckLine))
return false;
 
return true;
}
449,38 → 450,38
//
boolean
P_TryMove
( mobj_t* thing,
fixed_t x,
fixed_t y )
( mobj_t* thing,
fixed_t x,
fixed_t y )
{
fixed_t oldx;
fixed_t oldy;
int side;
int oldside;
line_t* ld;
fixed_t oldx;
fixed_t oldy;
int side;
int oldside;
line_t* ld;
 
floatok = false;
if (!P_CheckPosition (thing, x, y))
return false; // solid wall or thing
return false; // solid wall or thing
if ( !(thing->flags & MF_NOCLIP) )
{
if (tmceilingz - tmfloorz < thing->height)
return false; // doesn't fit
if (tmceilingz - tmfloorz < thing->height)
return false; // doesn't fit
 
floatok = true;
if ( !(thing->flags&MF_TELEPORT)
&&tmceilingz - thing->z < thing->height)
return false; // mobj must lower itself to fit
floatok = true;
if ( !(thing->flags&MF_TELEPORT)
&&tmceilingz - thing->z < thing->height)
return false; // mobj must lower itself to fit
 
if ( !(thing->flags&MF_TELEPORT)
&& tmfloorz - thing->z > 24*FRACUNIT )
return false; // too big a step up
if ( !(thing->flags&MF_TELEPORT)
&& tmfloorz - thing->z > 24*FRACUNIT )
return false; // too big a step up
 
if ( !(thing->flags&(MF_DROPOFF|MF_FLOAT))
&& tmfloorz - tmdropoffz > 24*FRACUNIT )
return false; // don't stand over a dropoff
if ( !(thing->flags&(MF_DROPOFF|MF_FLOAT))
&& tmfloorz - tmdropoffz > 24*FRACUNIT )
return false; // don't stand over a dropoff
}
// the move is ok,
490,7 → 491,7
oldx = thing->x;
oldy = thing->y;
thing->floorz = tmfloorz;
thing->ceilingz = tmceilingz;
thing->ceilingz = tmceilingz;
thing->x = x;
thing->y = y;
 
499,18 → 500,18
// if any special lines were hit, do the effect
if (! (thing->flags&(MF_TELEPORT|MF_NOCLIP)) )
{
while (numspechit--)
{
// see if the line was crossed
ld = spechit[numspechit];
side = P_PointOnLineSide (thing->x, thing->y, ld);
oldside = P_PointOnLineSide (oldx, oldy, ld);
if (side != oldside)
{
if (ld->special)
P_CrossSpecialLine (ld-lines, oldside, thing);
}
}
while (numspechit--)
{
// see if the line was crossed
ld = spechit[numspechit];
side = P_PointOnLineSide (thing->x, thing->y, ld);
oldside = P_PointOnLineSide (oldx, oldy, ld);
if (side != oldside)
{
if (ld->special)
P_CrossSpecialLine (ld-lines, oldside, thing);
}
}
}
 
return true;
529,31 → 530,31
//
boolean P_ThingHeightClip (mobj_t* thing)
{
boolean onfloor;
boolean onfloor;
onfloor = (thing->z == thing->floorz);
P_CheckPosition (thing, thing->x, thing->y);
P_CheckPosition (thing, thing->x, thing->y);
// what about stranding a monster partially off an edge?
thing->floorz = tmfloorz;
thing->ceilingz = tmceilingz;
if (onfloor)
{
// walking monsters rise and fall with the floor
thing->z = thing->floorz;
// walking monsters rise and fall with the floor
thing->z = thing->floorz;
}
else
{
// don't adjust a floating monster unless forced to
if (thing->z+thing->height > thing->ceilingz)
thing->z = thing->ceilingz - thing->height;
// don't adjust a floating monster unless forced to
if (thing->z+thing->height > thing->ceilingz)
thing->z = thing->ceilingz - thing->height;
}
if (thing->ceilingz - thing->floorz < thing->height)
return false;
return false;
return true;
}
 
563,16 → 564,16
// SLIDE MOVE
// Allows the player to slide along any angled walls.
//
fixed_t bestslidefrac;
fixed_t secondslidefrac;
fixed_t bestslidefrac;
fixed_t secondslidefrac;
 
line_t* bestslideline;
line_t* secondslideline;
line_t* bestslideline;
line_t* secondslideline;
 
mobj_t* slidemo;
mobj_t* slidemo;
 
fixed_t tmxmove;
fixed_t tmymove;
fixed_t tmxmove;
fixed_t tmymove;
 
 
 
583,50 → 584,50
//
void P_HitSlideLine (line_t* ld)
{
int side;
int side;
 
angle_t lineangle;
angle_t moveangle;
angle_t deltaangle;
angle_t lineangle;
angle_t moveangle;
angle_t deltaangle;
fixed_t movelen;
fixed_t newlen;
fixed_t movelen;
fixed_t newlen;
if (ld->slopetype == ST_HORIZONTAL)
{
tmymove = 0;
return;
tmymove = 0;
return;
}
if (ld->slopetype == ST_VERTICAL)
{
tmxmove = 0;
return;
tmxmove = 0;
return;
}
side = P_PointOnLineSide (slidemo->x, slidemo->y, ld);
lineangle = R_PointToAngle2 (0,0, ld->dx, ld->dy);
 
if (side == 1)
lineangle += ANG180;
lineangle += ANG180;
 
moveangle = R_PointToAngle2 (0,0, tmxmove, tmymove);
deltaangle = moveangle-lineangle;
 
if (deltaangle > ANG180)
deltaangle += ANG180;
// I_Error ("SlideLine: ang>ANG180");
deltaangle += ANG180;
// I_Error ("SlideLine: ang>ANG180");
 
lineangle >>= ANGLETOFINESHIFT;
deltaangle >>= ANGLETOFINESHIFT;
movelen = P_AproxDistance (tmxmove, tmymove);
newlen = FixedMul (movelen, finecosine[deltaangle]);
 
tmxmove = FixedMul (newlen, finecosine[lineangle]);
tmymove = FixedMul (newlen, finesine[lineangle]);
tmxmove = FixedMul (newlen, finecosine[lineangle]);
tmymove = FixedMul (newlen, finesine[lineangle]);
}
 
 
635,21 → 636,21
//
boolean PTR_SlideTraverse (intercept_t* in)
{
line_t* li;
line_t* li;
if (!in->isaline)
I_Error ("PTR_SlideTraverse: not a line?");
I_Error ("PTR_SlideTraverse: not a line?");
li = in->d.line;
if ( ! (li->flags & ML_TWOSIDED) )
{
if (P_PointOnLineSide (slidemo->x, slidemo->y, li))
{
// don't hit the back side
return true;
}
goto isblocking;
if (P_PointOnLineSide (slidemo->x, slidemo->y, li))
{
// don't hit the back side
return true;
}
goto isblocking;
}
 
// set openrange, opentop, openbottom
656,29 → 657,29
P_LineOpening (li);
if (openrange < slidemo->height)
goto isblocking; // doesn't fit
goto isblocking; // doesn't fit
if (opentop - slidemo->z < slidemo->height)
goto isblocking; // mobj is too high
goto isblocking; // mobj is too high
 
if (openbottom - slidemo->z > 24*FRACUNIT )
goto isblocking; // too big a step up
goto isblocking; // too big a step up
 
// this line doesn't block movement
return true;
return true;
// the line does block movement,
// see if it is closer than best so far
isblocking:
isblocking:
if (in->frac < bestslidefrac)
{
secondslidefrac = bestslidefrac;
secondslideline = bestslideline;
bestslidefrac = in->frac;
bestslideline = li;
secondslidefrac = bestslidefrac;
secondslideline = bestslideline;
bestslidefrac = in->frac;
bestslideline = li;
}
return false; // stop
return false; // stop
}
 
 
694,73 → 695,73
//
void P_SlideMove (mobj_t* mo)
{
fixed_t leadx;
fixed_t leady;
fixed_t trailx;
fixed_t traily;
fixed_t newx;
fixed_t newy;
int hitcount;
fixed_t leadx;
fixed_t leady;
fixed_t trailx;
fixed_t traily;
fixed_t newx;
fixed_t newy;
int hitcount;
slidemo = mo;
hitcount = 0;
retry:
if (++hitcount == 3)
goto stairstep; // don't loop forever
goto stairstep; // don't loop forever
 
// trace along the three leading corners
if (mo->momx > 0)
{
leadx = mo->x + mo->radius;
trailx = mo->x - mo->radius;
leadx = mo->x + mo->radius;
trailx = mo->x - mo->radius;
}
else
{
leadx = mo->x - mo->radius;
trailx = mo->x + mo->radius;
leadx = mo->x - mo->radius;
trailx = mo->x + mo->radius;
}
if (mo->momy > 0)
{
leady = mo->y + mo->radius;
traily = mo->y - mo->radius;
leady = mo->y + mo->radius;
traily = mo->y - mo->radius;
}
else
{
leady = mo->y - mo->radius;
traily = mo->y + mo->radius;
leady = mo->y - mo->radius;
traily = mo->y + mo->radius;
}
bestslidefrac = FRACUNIT+1;
P_PathTraverse ( leadx, leady, leadx+mo->momx, leady+mo->momy,
PT_ADDLINES, PTR_SlideTraverse );
PT_ADDLINES, PTR_SlideTraverse );
P_PathTraverse ( trailx, leady, trailx+mo->momx, leady+mo->momy,
PT_ADDLINES, PTR_SlideTraverse );
PT_ADDLINES, PTR_SlideTraverse );
P_PathTraverse ( leadx, traily, leadx+mo->momx, traily+mo->momy,
PT_ADDLINES, PTR_SlideTraverse );
PT_ADDLINES, PTR_SlideTraverse );
// move up to the wall
if (bestslidefrac == FRACUNIT+1)
{
// the move most have hit the middle, so stairstep
// the move most have hit the middle, so stairstep
stairstep:
if (!P_TryMove (mo, mo->x, mo->y + mo->momy))
P_TryMove (mo, mo->x + mo->momx, mo->y);
return;
if (!P_TryMove (mo, mo->x, mo->y + mo->momy))
P_TryMove (mo, mo->x + mo->momx, mo->y);
return;
}
 
// fudge a bit to make sure it doesn't hit
bestslidefrac -= 0x800;
bestslidefrac -= 0x800;
if (bestslidefrac > 0)
{
newx = FixedMul (mo->momx, bestslidefrac);
newy = FixedMul (mo->momy, bestslidefrac);
if (!P_TryMove (mo, mo->x+newx, mo->y+newy))
goto stairstep;
newx = FixedMul (mo->momx, bestslidefrac);
newy = FixedMul (mo->momy, bestslidefrac);
if (!P_TryMove (mo, mo->x+newx, mo->y+newy))
goto stairstep;
}
// Now continue along the wall.
768,22 → 769,22
bestslidefrac = FRACUNIT-(bestslidefrac+0x800);
if (bestslidefrac > FRACUNIT)
bestslidefrac = FRACUNIT;
bestslidefrac = FRACUNIT;
if (bestslidefrac <= 0)
return;
return;
tmxmove = FixedMul (mo->momx, bestslidefrac);
tmymove = FixedMul (mo->momy, bestslidefrac);
 
P_HitSlideLine (bestslideline); // clip the moves
P_HitSlideLine (bestslideline); // clip the moves
 
mo->momx = tmxmove;
mo->momy = tmymove;
if (!P_TryMove (mo, mo->x+tmxmove, mo->y+tmymove))
{
goto retry;
goto retry;
}
}
 
791,21 → 792,21
//
// P_LineAttack
//
mobj_t* linetarget; // who got hit (or NULL)
mobj_t* shootthing;
mobj_t* linetarget; // who got hit (or NULL)
mobj_t* shootthing;
 
// Height if not aiming up or down
// ???: use slope for monsters?
fixed_t shootz;
fixed_t shootz;
 
int la_damage;
fixed_t attackrange;
int la_damage;
fixed_t attackrange;
 
fixed_t aimslope;
fixed_t aimslope;
 
// slopes to top and bottom of target
extern fixed_t topslope;
extern fixed_t bottomslope;
extern fixed_t topslope;
extern fixed_t bottomslope;
 
 
//
815,57 → 816,57
boolean
PTR_AimTraverse (intercept_t* in)
{
line_t* li;
mobj_t* th;
fixed_t slope;
fixed_t thingtopslope;
fixed_t thingbottomslope;
fixed_t dist;
line_t* li;
mobj_t* th;
fixed_t slope;
fixed_t thingtopslope;
fixed_t thingbottomslope;
fixed_t dist;
if (in->isaline)
{
li = in->d.line;
if ( !(li->flags & ML_TWOSIDED) )
return false; // stop
// Crosses a two sided line.
// A two sided line will restrict
// the possible target ranges.
P_LineOpening (li);
if (openbottom >= opentop)
return false; // stop
dist = FixedMul (attackrange, in->frac);
li = in->d.line;
if ( !(li->flags & ML_TWOSIDED) )
return false; // stop
// Crosses a two sided line.
// A two sided line will restrict
// the possible target ranges.
P_LineOpening (li);
if (openbottom >= opentop)
return false; // stop
dist = FixedMul (attackrange, in->frac);
 
if (li->frontsector->floorheight != li->backsector->floorheight)
{
slope = FixedDiv (openbottom - shootz , dist);
if (slope > bottomslope)
bottomslope = slope;
}
if (li->frontsector->ceilingheight != li->backsector->ceilingheight)
{
slope = FixedDiv (opentop - shootz , dist);
if (slope < topslope)
topslope = slope;
}
if (topslope <= bottomslope)
return false; // stop
return true; // shot continues
if (li->frontsector->floorheight != li->backsector->floorheight)
{
slope = FixedDiv (openbottom - shootz , dist);
if (slope > bottomslope)
bottomslope = slope;
}
if (li->frontsector->ceilingheight != li->backsector->ceilingheight)
{
slope = FixedDiv (opentop - shootz , dist);
if (slope < topslope)
topslope = slope;
}
if (topslope <= bottomslope)
return false; // stop
return true; // shot continues
}
// shoot a thing
th = in->d.thing;
if (th == shootthing)
return true; // can't shoot self
return true; // can't shoot self
if (!(th->flags&MF_SHOOTABLE))
return true; // corpse or something
return true; // corpse or something
 
// check angles to see if the thing can be aimed at
dist = FixedMul (attackrange, in->frac);
872,24 → 873,24
thingtopslope = FixedDiv (th->z+th->height - shootz , dist);
 
if (thingtopslope < bottomslope)
return true; // shot over the thing
return true; // shot over the thing
 
thingbottomslope = FixedDiv (th->z - shootz, dist);
 
if (thingbottomslope > topslope)
return true; // shot under the thing
return true; // shot under the thing
// this thing can be hit!
if (thingtopslope > topslope)
thingtopslope = topslope;
thingtopslope = topslope;
if (thingbottomslope < bottomslope)
thingbottomslope = bottomslope;
thingbottomslope = bottomslope;
 
aimslope = (thingtopslope+thingbottomslope)/2;
linetarget = th;
 
return false; // don't go any farther
return false; // don't go any farther
}
 
 
898,98 → 899,98
//
boolean PTR_ShootTraverse (intercept_t* in)
{
fixed_t x;
fixed_t y;
fixed_t z;
fixed_t frac;
fixed_t x;
fixed_t y;
fixed_t z;
fixed_t frac;
line_t* li;
line_t* li;
mobj_t* th;
mobj_t* th;
 
fixed_t slope;
fixed_t dist;
fixed_t thingtopslope;
fixed_t thingbottomslope;
fixed_t slope;
fixed_t dist;
fixed_t thingtopslope;
fixed_t thingbottomslope;
if (in->isaline)
{
li = in->d.line;
if (li->special)
P_ShootSpecialLine (shootthing, li);
li = in->d.line;
if (li->special)
P_ShootSpecialLine (shootthing, li);
 
if ( !(li->flags & ML_TWOSIDED) )
goto hitline;
// crosses a two sided line
P_LineOpening (li);
dist = FixedMul (attackrange, in->frac);
if ( !(li->flags & ML_TWOSIDED) )
goto hitline;
// crosses a two sided line
P_LineOpening (li);
dist = FixedMul (attackrange, in->frac);
 
if (li->frontsector->floorheight != li->backsector->floorheight)
{
slope = FixedDiv (openbottom - shootz , dist);
if (slope > aimslope)
goto hitline;
}
if (li->frontsector->ceilingheight != li->backsector->ceilingheight)
{
slope = FixedDiv (opentop - shootz , dist);
if (slope < aimslope)
goto hitline;
}
if (li->frontsector->floorheight != li->backsector->floorheight)
{
slope = FixedDiv (openbottom - shootz , dist);
if (slope > aimslope)
goto hitline;
}
if (li->frontsector->ceilingheight != li->backsector->ceilingheight)
{
slope = FixedDiv (opentop - shootz , dist);
if (slope < aimslope)
goto hitline;
}
 
// shot continues
return true;
// hit line
// shot continues
return true;
// hit line
hitline:
// position a bit closer
frac = in->frac - FixedDiv (4*FRACUNIT,attackrange);
x = trace.x + FixedMul (trace.dx, frac);
y = trace.y + FixedMul (trace.dy, frac);
z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange));
// position a bit closer
frac = in->frac - FixedDiv (4*FRACUNIT,attackrange);
x = trace.x + FixedMul (trace.dx, frac);
y = trace.y + FixedMul (trace.dy, frac);
z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange));
 
if (li->frontsector->ceilingpic == skyflatnum)
{
// don't shoot the sky!
if (z > li->frontsector->ceilingheight)
return false;
// it's a sky hack wall
if (li->backsector && li->backsector->ceilingpic == skyflatnum)
return false;
}
if (li->frontsector->ceilingpic == skyflatnum)
{
// don't shoot the sky!
if (z > li->frontsector->ceilingheight)
return false;
// it's a sky hack wall
if (li->backsector && li->backsector->ceilingpic == skyflatnum)
return false;
}
 
// Spawn bullet puffs.
P_SpawnPuff (x,y,z);
// don't go any farther
return false;
// Spawn bullet puffs.
P_SpawnPuff (x,y,z);
// don't go any farther
return false;
}
// shoot a thing
th = in->d.thing;
if (th == shootthing)
return true; // can't shoot self
return true; // can't shoot self
if (!(th->flags&MF_SHOOTABLE))
return true; // corpse or something
return true; // corpse or something
// check angles to see if the thing can be aimed at
dist = FixedMul (attackrange, in->frac);
thingtopslope = FixedDiv (th->z+th->height - shootz , dist);
 
if (thingtopslope < aimslope)
return true; // shot over the thing
return true; // shot over the thing
 
thingbottomslope = FixedDiv (th->z - shootz, dist);
 
if (thingbottomslope > aimslope)
return true; // shot under the thing
return true; // shot under the thing
 
// hit thing
1003,16 → 1004,16
// Spawn bullet puffs or blod spots,
// depending on target type.
if (in->d.thing->flags & MF_NOBLOOD)
P_SpawnPuff (x,y,z);
P_SpawnPuff (x,y,z);
else
P_SpawnBlood (x,y,z, la_damage);
P_SpawnBlood (x,y,z, la_damage);
 
if (la_damage)
P_DamageMobj (th, shootthing, shootthing, la_damage);
P_DamageMobj (th, shootthing, shootthing, la_damage);
 
// don't go any farther
return false;
}
 
 
1021,13 → 1022,13
//
fixed_t
P_AimLineAttack
( mobj_t* t1,
angle_t angle,
fixed_t distance )
( mobj_t* t1,
angle_t angle,
fixed_t distance )
{
fixed_t x2;
fixed_t y2;
fixed_t x2;
fixed_t y2;
angle >>= ANGLETOFINESHIFT;
shootthing = t1;
1036,19 → 1037,19
shootz = t1->z + (t1->height>>1) + 8*FRACUNIT;
 
// can't shoot outside view angles
topslope = 100*FRACUNIT/160;
topslope = 100*FRACUNIT/160;
bottomslope = -100*FRACUNIT/160;
attackrange = distance;
linetarget = NULL;
P_PathTraverse ( t1->x, t1->y,
x2, y2,
PT_ADDLINES|PT_ADDTHINGS,
PTR_AimTraverse );
x2, y2,
PT_ADDLINES|PT_ADDTHINGS,
PTR_AimTraverse );
if (linetarget)
return aimslope;
return aimslope;
 
return 0;
}
1061,15 → 1062,15
//
void
P_LineAttack
( mobj_t* t1,
angle_t angle,
fixed_t distance,
fixed_t slope,
int damage )
( mobj_t* t1,
angle_t angle,
fixed_t distance,
fixed_t slope,
int damage )
{
fixed_t x2;
fixed_t y2;
fixed_t x2;
fixed_t y2;
angle >>= ANGLETOFINESHIFT;
shootthing = t1;
la_damage = damage;
1078,11 → 1079,11
shootz = t1->z + (t1->height>>1) + 8*FRACUNIT;
attackrange = distance;
aimslope = slope;
P_PathTraverse ( t1->x, t1->y,
x2, y2,
PT_ADDLINES|PT_ADDTHINGS,
PTR_ShootTraverse );
x2, y2,
PT_ADDLINES|PT_ADDTHINGS,
PTR_ShootTraverse );
}
 
1090,32 → 1091,32
//
// USE LINES
//
mobj_t* usething;
mobj_t* usething;
 
boolean PTR_UseTraverse (intercept_t* in)
boolean PTR_UseTraverse (intercept_t* in)
{
int side;
int side;
if (!in->d.line->special)
{
P_LineOpening (in->d.line);
if (openrange <= 0)
{
S_StartSound (usething, sfx_noway);
// can't use through a wall
return false;
}
// not a special line, but keep checking
return true ;
P_LineOpening (in->d.line);
if (openrange <= 0)
{
S_StartSound (usething, sfx_noway);
// can't use through a wall
return false;
}
// not a special line, but keep checking
return true ;
}
side = 0;
if (P_PointOnLineSide (usething->x, usething->y, in->d.line) == 1)
side = 1;
side = 1;
// return false; // don't use back side
// return false; // don't use back side
P_UseSpecialLine (usething, in->d.line, side);
 
// can't use for than one special line in a row
1127,16 → 1128,16
// P_UseLines
// Looks for special lines in front of the player to activate.
//
void P_UseLines (player_t* player)
void P_UseLines (player_t* player)
{
int angle;
fixed_t x1;
fixed_t y1;
fixed_t x2;
fixed_t y2;
int angle;
fixed_t x1;
fixed_t y1;
fixed_t x2;
fixed_t y2;
usething = player->mo;
angle = player->mo->angle >> ANGLETOFINESHIFT;
 
x1 = player->mo->x;
1143,7 → 1144,7
y1 = player->mo->y;
x2 = x1 + (USERANGE>>FRACBITS)*finecosine[angle];
y2 = y1 + (USERANGE>>FRACBITS)*finesine[angle];
P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse );
}
 
1151,9 → 1152,9
//
// RADIUS ATTACK
//
mobj_t* bombsource;
mobj_t* bombspot;
int bombdamage;
mobj_t* bombsource;
mobj_t* bombspot;
int bombdamage;
 
 
//
1163,19 → 1164,19
//
boolean PIT_RadiusAttack (mobj_t* thing)
{
fixed_t dx;
fixed_t dy;
fixed_t dist;
fixed_t dx;
fixed_t dy;
fixed_t dist;
if (!(thing->flags & MF_SHOOTABLE) )
return true;
return true;
 
// Boss spider and cyborg
// take no damage from concussion.
if (thing->type == MT_CYBORG
|| thing->type == MT_SPIDER)
return true;
|| thing->type == MT_SPIDER)
return true;
dx = abs(thing->x - bombspot->x);
dy = abs(thing->y - bombspot->y);
1183,15 → 1184,15
dist = (dist - thing->radius) >> FRACBITS;
 
if (dist < 0)
dist = 0;
dist = 0;
 
if (dist >= bombdamage)
return true; // out of range
return true; // out of range
 
if ( P_CheckSight (thing, bombspot) )
{
// must be in direct path
P_DamageMobj (thing, bombspot, bombsource, bombdamage - dist);
// must be in direct path
P_DamageMobj (thing, bombspot, bombsource, bombdamage - dist);
}
return true;
1204,20 → 1205,20
//
void
P_RadiusAttack
( mobj_t* spot,
mobj_t* source,
int damage )
( mobj_t* spot,
mobj_t* source,
int damage )
{
int x;
int y;
int x;
int y;
int xl;
int xh;
int yl;
int yh;
int xl;
int xh;
int yl;
int yh;
fixed_t dist;
fixed_t dist;
dist = (damage+MAXRADIUS)<<FRACBITS;
yh = (spot->y + dist - bmaporgy)>>MAPBLOCKSHIFT;
yl = (spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT;
1226,10 → 1227,10
bombspot = spot;
bombsource = source;
bombdamage = damage;
for (y=yl ; y<=yh ; y++)
for (x=xl ; x<=xh ; x++)
P_BlockThingsIterator (x, y, PIT_RadiusAttack );
for (x=xl ; x<=xh ; x++)
P_BlockThingsIterator (x, y, PIT_RadiusAttack );
}
 
 
1247,21 → 1248,21
// the way it was and call P_ChangeSector again
// to undo the changes.
//
boolean crushchange;
boolean nofit;
boolean crushchange;
boolean nofit;
 
 
//
// PIT_ChangeSector
//
boolean PIT_ChangeSector (mobj_t* thing)
boolean PIT_ChangeSector (mobj_t* thing)
{
mobj_t* mo;
mobj_t* mo;
if (P_ThingHeightClip (thing))
{
// keep checking
return true;
// keep checking
return true;
}
 
1268,29 → 1269,29
// crunch bodies to giblets
if (thing->health <= 0)
{
P_SetMobjState (thing, S_GIBS);
P_SetMobjState (thing, S_GIBS);
 
thing->flags &= ~MF_SOLID;
thing->height = 0;
thing->radius = 0;
thing->flags &= ~MF_SOLID;
thing->height = 0;
thing->radius = 0;
 
// keep checking
return true;
// keep checking
return true;
}
 
// crunch dropped items
if (thing->flags & MF_DROPPED)
{
P_RemoveMobj (thing);
// keep checking
return true;
P_RemoveMobj (thing);
// keep checking
return true;
}
 
if (! (thing->flags & MF_SHOOTABLE) )
{
// assume it is bloody gibs or something
return true;
// assume it is bloody gibs or something
return true;
}
nofit = true;
1297,19 → 1298,19
 
if (crushchange && !(leveltime&3) )
{
P_DamageMobj(thing,NULL,NULL,10);
P_DamageMobj(thing,NULL,NULL,10);
 
// spray blood in a random direction
mo = P_SpawnMobj (thing->x,
thing->y,
thing->z + thing->height/2, MT_BLOOD);
mo->momx = (P_Random() - P_Random ())<<12;
mo->momy = (P_Random() - P_Random ())<<12;
// spray blood in a random direction
mo = P_SpawnMobj (thing->x,
thing->y,
thing->z + thing->height/2, MT_BLOOD);
mo->momx = (P_Random() - P_Random ())<<12;
mo->momy = (P_Random() - P_Random ())<<12;
}
 
// keep checking (crush other things)
return true;
// keep checking (crush other things)
return true;
}
 
 
1319,21 → 1320,21
//
boolean
P_ChangeSector
( sector_t* sector,
boolean crunch )
( sector_t* sector,
boolean crunch )
{
int x;
int y;
int x;
int y;
nofit = false;
crushchange = crunch;
// re-check heights for all things near the moving sector
for (x=sector->blockbox[BOXLEFT] ; x<= sector->blockbox[BOXRIGHT] ; x++)
for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++)
P_BlockThingsIterator (x, y, PIT_ChangeSector);
for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++)
P_BlockThingsIterator (x, y, PIT_ChangeSector);
return nofit;
}
 
/programs/games/doom/trunk/p_telept.c
17,7 → 17,7
// $Log:$
//
// DESCRIPTION:
// Teleportation.
// Teleportation.
//
//-----------------------------------------------------------------------------
 
25,7 → 25,7
rcsid[] = "$Id: p_telept.c,v 1.3 1997/01/28 22:08:29 b1 Exp $";
 
 
 
#include "doomtype.h"
#include "doomdef.h"
 
#include "s_sound.h"
46,86 → 46,86
//
int
EV_Teleport
( line_t* line,
int side,
mobj_t* thing )
( line_t* line,
int side,
mobj_t* thing )
{
int i;
int tag;
mobj_t* m;
mobj_t* fog;
unsigned an;
thinker_t* thinker;
sector_t* sector;
fixed_t oldx;
fixed_t oldy;
fixed_t oldz;
int i;
int tag;
mobj_t* m;
mobj_t* fog;
unsigned an;
thinker_t* thinker;
sector_t* sector;
fixed_t oldx;
fixed_t oldy;
fixed_t oldz;
 
// don't teleport missiles
if (thing->flags & MF_MISSILE)
return 0;
return 0;
 
// Don't teleport if hit back of line,
// so you can get out of teleporter.
if (side == 1)
return 0;
if (side == 1)
return 0;
 
tag = line->tag;
for (i = 0; i < numsectors; i++)
{
if (sectors[ i ].tag == tag )
{
thinker = thinkercap.next;
for (thinker = thinkercap.next;
thinker != &thinkercap;
thinker = thinker->next)
{
// not a mobj
if (thinker->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
if (sectors[ i ].tag == tag )
{
thinker = thinkercap.next;
for (thinker = thinkercap.next;
thinker != &thinkercap;
thinker = thinker->next)
{
// not a mobj
if (thinker->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
 
m = (mobj_t *)thinker;
// not a teleportman
if (m->type != MT_TELEPORTMAN )
continue;
m = (mobj_t *)thinker;
// not a teleportman
if (m->type != MT_TELEPORTMAN )
continue;
 
sector = m->subsector->sector;
// wrong sector
if (sector-sectors != i )
continue;
sector = m->subsector->sector;
// wrong sector
if (sector-sectors != i )
continue;
 
oldx = thing->x;
oldy = thing->y;
oldz = thing->z;
if (!P_TeleportMove (thing, m->x, m->y))
return 0;
thing->z = thing->floorz; //fixme: not needed?
if (thing->player)
thing->player->viewz = thing->z+thing->player->viewheight;
// spawn teleport fog at source and destination
fog = P_SpawnMobj (oldx, oldy, oldz, MT_TFOG);
S_StartSound (fog, sfx_telept);
an = m->angle >> ANGLETOFINESHIFT;
fog = P_SpawnMobj (m->x+20*finecosine[an], m->y+20*finesine[an]
, thing->z, MT_TFOG);
oldx = thing->x;
oldy = thing->y;
oldz = thing->z;
if (!P_TeleportMove (thing, m->x, m->y))
return 0;
thing->z = thing->floorz; //fixme: not needed?
if (thing->player)
thing->player->viewz = thing->z+thing->player->viewheight;
// spawn teleport fog at source and destination
fog = P_SpawnMobj (oldx, oldy, oldz, MT_TFOG);
S_StartSound (fog, sfx_telept);
an = m->angle >> ANGLETOFINESHIFT;
fog = P_SpawnMobj (m->x+20*finecosine[an], m->y+20*finesine[an]
, thing->z, MT_TFOG);
 
// emit sound, where?
S_StartSound (fog, sfx_telept);
// don't move for a bit
if (thing->player)
thing->reactiontime = 18;
// emit sound, where?
S_StartSound (fog, sfx_telept);
// don't move for a bit
if (thing->player)
thing->reactiontime = 18;
 
thing->angle = m->angle;
thing->momx = thing->momy = thing->momz = 0;
return 1;
}
}
thing->angle = m->angle;
thing->momx = thing->momy = thing->momz = 0;
return 1;
}
}
}
return 0;
}
/programs/games/doom/trunk/r_draw.c
17,9 → 17,9
// $Log:$
//
// DESCRIPTION:
// The actual span/column drawing functions.
// Here find the main potential for optimization,
// e.g. inline assembly, different algorithms.
// The actual span/column drawing functions.
// Here find the main potential for optimization,
// e.g. inline assembly, different algorithms.
//
//-----------------------------------------------------------------------------
 
27,7 → 27,7
static const char
rcsid[] = "$Id: r_draw.c,v 1.4 1997/02/03 16:47:55 b1 Exp $";
 
 
#include "doomtype.h"
#include "doomdef.h"
 
#include "i_system.h"
44,11 → 44,11
 
 
// ?
#define MAXWIDTH 1120
#define MAXHEIGHT 832
#define MAXWIDTH 1120
#define MAXHEIGHT 832
 
// status bar height at bottom of screen
#define SBARHEIGHT 32
#define SBARHEIGHT 32
 
//
// All drawing to the view buffer is accomplished in this file.
60,20 → 60,20
//
 
 
byte* viewimage;
int viewwidth;
int scaledviewwidth;
int viewheight;
int viewwindowx;
int viewwindowy;
byte* ylookup[MAXHEIGHT];
int columnofs[MAXWIDTH];
byte* viewimage;
int viewwidth;
int scaledviewwidth;
int viewheight;
int viewwindowx;
int viewwindowy;
byte* ylookup[MAXHEIGHT];
int columnofs[MAXWIDTH];
 
// Color tables for different players,
// translate a limited part to another
// (color ramps used for suit colors).
//
byte translations[3][256];
byte translations[3][256];
 
82,18 → 82,18
// R_DrawColumn
// Source is the top of the column to scale.
//
lighttable_t* dc_colormap;
int dc_x;
int dc_yl;
int dc_yh;
fixed_t dc_iscale;
fixed_t dc_texturemid;
lighttable_t* dc_colormap;
int dc_x;
int dc_yl;
int dc_yh;
fixed_t dc_iscale;
fixed_t dc_texturemid;
 
// first pixel in a column (possibly virtual)
byte* dc_source;
byte* dc_source;
 
// just for profiling
int dccount;
int dccount;
 
//
// A column is a vertical slice/span from a wall texture that,
104,22 → 104,22
//
void R_DrawColumn (void)
{
int count;
byte* dest;
fixed_t frac;
fixed_t fracstep;
int count;
byte* dest;
fixed_t frac;
fixed_t fracstep;
count = dc_yh - dc_yl;
 
// Zero length, column does not exceed a pixel.
if (count < 0)
return;
return;
#ifdef RANGECHECK
if ((unsigned)dc_x >= SCREENWIDTH
|| dc_yl < 0
|| dc_yh >= SCREENHEIGHT)
I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
|| dc_yl < 0
|| dc_yh >= SCREENHEIGHT)
I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
#endif
 
// Framebuffer destination address.
137,13 → 137,13
// This is as fast as it gets.
do
{
// Re-map color indices from wall texture column
// using a lighting/special effects LUT.
*dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
dest += SCREENWIDTH;
frac += fracstep;
// Re-map color indices from wall texture column
// using a lighting/special effects LUT.
*dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
dest += SCREENWIDTH;
frac += fracstep;
} while (count--);
}
 
154,23 → 154,23
#if 0
void R_DrawColumn (void)
{
int count;
byte* source;
byte* dest;
byte* colormap;
int count;
byte* source;
byte* dest;
byte* colormap;
unsigned frac;
unsigned fracstep;
unsigned fracstep2;
unsigned fracstep3;
unsigned fracstep4;
unsigned frac;
unsigned fracstep;
unsigned fracstep2;
unsigned fracstep3;
unsigned fracstep4;
count = dc_yh - dc_yl + 1;
 
source = dc_source;
colormap = dc_colormap;
colormap = dc_colormap;
dest = ylookup[dc_yl] + columnofs[dc_x];
fracstep = dc_iscale<<9;
frac = (dc_texturemid + (dc_yl-centery)*dc_iscale)<<9;
177,32 → 177,32
fracstep2 = fracstep+fracstep;
fracstep3 = fracstep2+fracstep;
fracstep4 = fracstep3+fracstep;
while (count >= 8)
{
dest[0] = colormap[source[frac>>25]];
dest[SCREENWIDTH] = colormap[source[(frac+fracstep)>>25]];
dest[SCREENWIDTH*2] = colormap[source[(frac+fracstep2)>>25]];
dest[SCREENWIDTH*3] = colormap[source[(frac+fracstep3)>>25]];
frac += fracstep4;
dest[0] = colormap[source[frac>>25]];
dest[SCREENWIDTH] = colormap[source[(frac+fracstep)>>25]];
dest[SCREENWIDTH*2] = colormap[source[(frac+fracstep2)>>25]];
dest[SCREENWIDTH*3] = colormap[source[(frac+fracstep3)>>25]];
frac += fracstep4;
 
dest[SCREENWIDTH*4] = colormap[source[frac>>25]];
dest[SCREENWIDTH*5] = colormap[source[(frac+fracstep)>>25]];
dest[SCREENWIDTH*6] = colormap[source[(frac+fracstep2)>>25]];
dest[SCREENWIDTH*7] = colormap[source[(frac+fracstep3)>>25]];
dest[SCREENWIDTH*4] = colormap[source[frac>>25]];
dest[SCREENWIDTH*5] = colormap[source[(frac+fracstep)>>25]];
dest[SCREENWIDTH*6] = colormap[source[(frac+fracstep2)>>25]];
dest[SCREENWIDTH*7] = colormap[source[(frac+fracstep3)>>25]];
 
frac += fracstep4;
dest += SCREENWIDTH*8;
count -= 8;
frac += fracstep4;
dest += SCREENWIDTH*8;
count -= 8;
}
while (count > 0)
{
*dest = colormap[source[frac>>25]];
dest += SCREENWIDTH;
frac += fracstep;
count--;
*dest = colormap[source[frac>>25]];
dest += SCREENWIDTH;
frac += fracstep;
count--;
}
}
#endif
210,27 → 210,27
 
void R_DrawColumnLow (void)
{
int count;
byte* dest;
byte* dest2;
fixed_t frac;
fixed_t fracstep;
int count;
byte* dest;
byte* dest2;
fixed_t frac;
fixed_t fracstep;
count = dc_yh - dc_yl;
 
// Zero length.
if (count < 0)
return;
return;
#ifdef RANGECHECK
if ((unsigned)dc_x >= SCREENWIDTH
|| dc_yl < 0
|| dc_yh >= SCREENHEIGHT)
|| dc_yl < 0
|| dc_yh >= SCREENHEIGHT)
{
I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
}
// dccount++;
// dccount++;
#endif
// Blocky mode, need to multiply by 2.
dc_x <<= 1;
243,11 → 243,11
do
{
// Hack. Does not work corretly.
*dest2 = *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
dest += SCREENWIDTH;
dest2 += SCREENWIDTH;
frac += fracstep;
// Hack. Does not work corretly.
*dest2 = *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
dest += SCREENWIDTH;
dest2 += SCREENWIDTH;
frac += fracstep;
 
} while (count--);
}
256,11 → 256,11
//
// Spectre/Invisibility.
//
#define FUZZTABLE 50
#define FUZZOFF (SCREENWIDTH)
#define FUZZTABLE 50
#define FUZZOFF (SCREENWIDTH)
 
 
int fuzzoffset[FUZZTABLE] =
int fuzzoffset[FUZZTABLE] =
{
FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
271,7 → 271,7
FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF
};
 
int fuzzpos = 0;
int fuzzpos = 0;
 
 
//
284,32 → 284,32
//
void R_DrawFuzzColumn (void)
{
int count;
byte* dest;
fixed_t frac;
fixed_t fracstep;
int count;
byte* dest;
fixed_t frac;
fixed_t fracstep;
 
// Adjust borders. Low...
if (!dc_yl)
dc_yl = 1;
dc_yl = 1;
 
// .. and high.
if (dc_yh == viewheight-1)
dc_yh = viewheight - 2;
dc_yh = viewheight - 2;
count = dc_yh - dc_yl;
 
// Zero length.
if (count < 0)
return;
return;
 
#ifdef RANGECHECK
if ((unsigned)dc_x >= SCREENWIDTH
|| dc_yl < 0 || dc_yh >= SCREENHEIGHT)
|| dc_yl < 0 || dc_yh >= SCREENHEIGHT)
{
I_Error ("R_DrawFuzzColumn: %i to %i at %i",
dc_yl, dc_yh, dc_x);
I_Error ("R_DrawFuzzColumn: %i to %i at %i",
dc_yl, dc_yh, dc_x);
}
#endif
 
319,23 → 319,23
/* WATCOM code
if (detailshift)
{
if (dc_x & 1)
{
outpw (GC_INDEX,GC_READMAP+(2<<8) );
outp (SC_INDEX+1,12);
}
else
{
outpw (GC_INDEX,GC_READMAP);
outp (SC_INDEX+1,3);
}
dest = destview + dc_yl*80 + (dc_x>>1);
if (dc_x & 1)
{
outpw (GC_INDEX,GC_READMAP+(2<<8) );
outp (SC_INDEX+1,12);
}
else
{
outpw (GC_INDEX,GC_READMAP);
outp (SC_INDEX+1,3);
}
dest = destview + dc_yl*80 + (dc_x>>1);
}
else
{
outpw (GC_INDEX,GC_READMAP+((dc_x&3)<<8) );
outp (SC_INDEX+1,1<<(dc_x&3));
dest = destview + dc_yl*80 + (dc_x>>2);
outpw (GC_INDEX,GC_READMAP+((dc_x&3)<<8) );
outp (SC_INDEX+1,1<<(dc_x&3));
dest = destview + dc_yl*80 + (dc_x>>2);
}*/
 
351,19 → 351,19
// brighter than average).
do
{
// Lookup framebuffer, and retrieve
// a pixel that is either one column
// left or right of the current one.
// Add index from colormap to index.
*dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]];
// Lookup framebuffer, and retrieve
// a pixel that is either one column
// left or right of the current one.
// Add index from colormap to index.
*dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]];
 
// Clamp table lookup index.
if (++fuzzpos == FUZZTABLE)
fuzzpos = 0;
dest += SCREENWIDTH;
// Clamp table lookup index.
if (++fuzzpos == FUZZTABLE)
fuzzpos = 0;
dest += SCREENWIDTH;
 
frac += fracstep;
frac += fracstep;
} while (count--);
}
379,27 → 379,27
// of the BaronOfHell, the HellKnight, uses
// identical sprites, kinda brightened up.
//
byte* dc_translation;
byte* translationtables;
byte* dc_translation;
byte* translationtables;
 
void R_DrawTranslatedColumn (void)
{
int count;
byte* dest;
fixed_t frac;
fixed_t fracstep;
int count;
byte* dest;
fixed_t frac;
fixed_t fracstep;
count = dc_yh - dc_yl;
if (count < 0)
return;
return;
#ifdef RANGECHECK
if ((unsigned)dc_x >= SCREENWIDTH
|| dc_yl < 0
|| dc_yh >= SCREENHEIGHT)
|| dc_yl < 0
|| dc_yh >= SCREENHEIGHT)
{
I_Error ( "R_DrawColumn: %i to %i at %i",
dc_yl, dc_yh, dc_x);
I_Error ( "R_DrawColumn: %i to %i at %i",
dc_yl, dc_yh, dc_x);
}
#endif
409,18 → 409,18
/* Keep for fixing.
if (detailshift)
{
if (dc_x & 1)
outp (SC_INDEX+1,12);
else
outp (SC_INDEX+1,3);
dest = destview + dc_yl*80 + (dc_x>>1);
if (dc_x & 1)
outp (SC_INDEX+1,12);
else
outp (SC_INDEX+1,3);
dest = destview + dc_yl*80 + (dc_x>>1);
}
else
{
outp (SC_INDEX+1,1<<(dc_x&3));
outp (SC_INDEX+1,1<<(dc_x&3));
 
dest = destview + dc_yl*80 + (dc_x>>2);
dest = destview + dc_yl*80 + (dc_x>>2);
}*/
 
434,15 → 434,15
// Here we do an additional index re-mapping.
do
{
// Translation tables are used
// to map certain colorramps to other ones,
// used with PLAY sprites.
// Thus the "green" ramp of the player 0 sprite
// is mapped to gray, red, black/indigo.
*dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
dest += SCREENWIDTH;
frac += fracstep;
// Translation tables are used
// to map certain colorramps to other ones,
// used with PLAY sprites.
// Thus the "green" ramp of the player 0 sprite
// is mapped to gray, red, black/indigo.
*dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
dest += SCREENWIDTH;
frac += fracstep;
} while (count--);
}
 
458,8 → 458,8
//
void R_InitTranslationTables (void)
{
int i;
int i;
translationtables = Z_Malloc (256*3+255, PU_STATIC, 0);
translationtables = (byte *)(( (int)translationtables + 255 )& ~255);
466,19 → 466,19
// translate just the 16 green colors
for (i=0 ; i<256 ; i++)
{
if (i >= 0x70 && i<= 0x7f)
{
// map green ramp to gray, brown, red
translationtables[i] = 0x60 + (i&0xf);
translationtables [i+256] = 0x40 + (i&0xf);
translationtables [i+512] = 0x20 + (i&0xf);
}
else
{
// Keep all other colors as is.
translationtables[i] = translationtables[i+256]
= translationtables[i+512] = i;
}
if (i >= 0x70 && i<= 0x7f)
{
// map green ramp to gray, brown, red
translationtables[i] = 0x60 + (i&0xf);
translationtables [i+256] = 0x40 + (i&0xf);
translationtables [i+512] = 0x20 + (i&0xf);
}
else
{
// Keep all other colors as is.
translationtables[i] = translationtables[i+256]
= translationtables[i+512] = i;
}
}
}
 
497,22 → 497,22
// In consequence, flats are not stored by column (like walls),
// and the inner loop has to step in texture space u and v.
//
int ds_y;
int ds_x1;
int ds_x2;
int ds_y;
int ds_x1;
int ds_x2;
 
lighttable_t* ds_colormap;
lighttable_t* ds_colormap;
 
fixed_t ds_xfrac;
fixed_t ds_yfrac;
fixed_t ds_xstep;
fixed_t ds_ystep;
fixed_t ds_xfrac;
fixed_t ds_yfrac;
fixed_t ds_xstep;
fixed_t ds_ystep;
 
// start of a 64*64 tile image
byte* ds_source;
byte* ds_source;
 
// just for profiling
int dscount;
int dscount;
 
 
//
519,28 → 519,28
// Draws the actual span.
void R_DrawSpan (void)
{
fixed_t xfrac;
fixed_t yfrac;
byte* dest;
int count;
int spot;
fixed_t xfrac;
fixed_t yfrac;
byte* dest;
int count;
int spot;
#ifdef RANGECHECK
if (ds_x2 < ds_x1
|| ds_x1<0
|| ds_x2>=SCREENWIDTH
|| (unsigned)ds_y>SCREENHEIGHT)
|| ds_x1<0
|| ds_x2>=SCREENWIDTH
|| (unsigned)ds_y>SCREENHEIGHT)
{
I_Error( "R_DrawSpan: %i to %i at %i",
ds_x1,ds_x2,ds_y);
I_Error( "R_DrawSpan: %i to %i at %i",
ds_x1,ds_x2,ds_y);
}
// dscount++;
// dscount++;
#endif
 
xfrac = ds_xfrac;
yfrac = ds_yfrac;
dest = ylookup[ds_y] + columnofs[ds_x1];
 
// We do not check for zero spans here?
548,17 → 548,17
 
do
{
// Current texture index in u,v.
spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
// Current texture index in u,v.
spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
 
// Lookup pixel from flat texture tile,
// re-index using light/colormap.
*dest++ = ds_colormap[ds_source[spot]];
// Lookup pixel from flat texture tile,
// re-index using light/colormap.
*dest++ = ds_colormap[ds_source[spot]];
 
// Next step in u,v.
xfrac += ds_xstep;
yfrac += ds_ystep;
// Next step in u,v.
xfrac += ds_xstep;
yfrac += ds_ystep;
} while (count--);
}
 
569,69 → 569,69
#if 0
void R_DrawSpan (void)
{
unsigned position, step;
unsigned position, step;
 
byte* source;
byte* colormap;
byte* dest;
byte* source;
byte* colormap;
byte* dest;
unsigned count;
usingned spot;
unsigned value;
unsigned temp;
unsigned xtemp;
unsigned ytemp;
unsigned count;
usingned spot;
unsigned value;
unsigned temp;
unsigned xtemp;
unsigned ytemp;
position = ((ds_xfrac<<10)&0xffff0000) | ((ds_yfrac>>6)&0xffff);
step = ((ds_xstep<<10)&0xffff0000) | ((ds_ystep>>6)&0xffff);
source = ds_source;
colormap = ds_colormap;
dest = ylookup[ds_y] + columnofs[ds_x1];
dest = ylookup[ds_y] + columnofs[ds_x1];
count = ds_x2 - ds_x1 + 1;
while (count >= 4)
{
ytemp = position>>4;
ytemp = ytemp & 4032;
xtemp = position>>26;
spot = xtemp | ytemp;
position += step;
dest[0] = colormap[source[spot]];
ytemp = position>>4;
ytemp = ytemp & 4032;
xtemp = position>>26;
spot = xtemp | ytemp;
position += step;
dest[0] = colormap[source[spot]];
 
ytemp = position>>4;
ytemp = ytemp & 4032;
xtemp = position>>26;
spot = xtemp | ytemp;
position += step;
dest[1] = colormap[source[spot]];
ytemp = position>>4;
ytemp = ytemp & 4032;
xtemp = position>>26;
spot = xtemp | ytemp;
position += step;
dest[2] = colormap[source[spot]];
ytemp = position>>4;
ytemp = ytemp & 4032;
xtemp = position>>26;
spot = xtemp | ytemp;
position += step;
dest[3] = colormap[source[spot]];
count -= 4;
dest += 4;
ytemp = position>>4;
ytemp = ytemp & 4032;
xtemp = position>>26;
spot = xtemp | ytemp;
position += step;
dest[1] = colormap[source[spot]];
ytemp = position>>4;
ytemp = ytemp & 4032;
xtemp = position>>26;
spot = xtemp | ytemp;
position += step;
dest[2] = colormap[source[spot]];
ytemp = position>>4;
ytemp = ytemp & 4032;
xtemp = position>>26;
spot = xtemp | ytemp;
position += step;
dest[3] = colormap[source[spot]];
count -= 4;
dest += 4;
}
while (count > 0)
{
ytemp = position>>4;
ytemp = ytemp & 4032;
xtemp = position>>26;
spot = xtemp | ytemp;
position += step;
*dest++ = colormap[source[spot]];
count--;
ytemp = position>>4;
ytemp = ytemp & 4032;
xtemp = position>>26;
spot = xtemp | ytemp;
position += step;
*dest++ = colormap[source[spot]];
count--;
}
}
#endif
642,24 → 642,24
//
void R_DrawSpanLow (void)
{
fixed_t xfrac;
fixed_t yfrac;
byte* dest;
int count;
int spot;
fixed_t xfrac;
fixed_t yfrac;
byte* dest;
int count;
int spot;
#ifdef RANGECHECK
if (ds_x2 < ds_x1
|| ds_x1<0
|| ds_x2>=SCREENWIDTH
|| (unsigned)ds_y>SCREENHEIGHT)
|| ds_x1<0
|| ds_x2>=SCREENWIDTH
|| (unsigned)ds_y>SCREENHEIGHT)
{
I_Error( "R_DrawSpan: %i to %i at %i",
ds_x1,ds_x2,ds_y);
I_Error( "R_DrawSpan: %i to %i at %i",
ds_x1,ds_x2,ds_y);
}
// dscount++;
// dscount++;
#endif
xfrac = ds_xfrac;
yfrac = ds_yfrac;
 
673,14 → 673,14
count = ds_x2 - ds_x1;
do
{
spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
// Lowres/blocky mode does it twice,
// while scale is adjusted appropriately.
*dest++ = ds_colormap[ds_source[spot]];
*dest++ = ds_colormap[ds_source[spot]];
xfrac += ds_xstep;
yfrac += ds_ystep;
spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
// Lowres/blocky mode does it twice,
// while scale is adjusted appropriately.
*dest++ = ds_colormap[ds_source[spot]];
*dest++ = ds_colormap[ds_source[spot]];
xfrac += ds_xstep;
yfrac += ds_ystep;
 
} while (count--);
}
694,10 → 694,10
//
void
R_InitBuffer
( int width,
int height )
( int width,
int height )
{
int i;
int i;
 
// Handle resize,
// e.g. smaller view windows
706,17 → 706,17
 
// Column offset. For windows.
for (i=0 ; i<width ; i++)
columnofs[i] = viewwindowx + i;
columnofs[i] = viewwindowx + i;
 
// Samw with base row offset.
if (width == SCREENWIDTH)
viewwindowy = 0;
viewwindowy = 0;
else
viewwindowy = (SCREENHEIGHT-SBARHEIGHT-height) >> 1;
viewwindowy = (SCREENHEIGHT-SBARHEIGHT-height) >> 1;
 
// Preclaculate all row offsets.
for (i=0 ; i<height ; i++)
ylookup[i] = screens[0] + (i+viewwindowy)*SCREENWIDTH;
ylookup[i] = screens[0] + (i+viewwindowy)*SCREENWIDTH;
}
730,84 → 730,84
//
void R_FillBackScreen (void)
{
byte* src;
byte* dest;
int x;
int y;
patch_t* patch;
byte* src;
byte* dest;
int x;
int y;
patch_t* patch;
 
// DOOM border patch.
char name1[] = "FLOOR7_2";
char name1[] = "FLOOR7_2";
 
// DOOM II border patch.
char name2[] = "GRNROCK";
char name2[] = "GRNROCK";
 
char* name;
char* name;
if (scaledviewwidth == 320)
return;
return;
if ( gamemode == commercial)
name = name2;
name = name2;
else
name = name1;
name = name1;
src = W_CacheLumpName (name, PU_CACHE);
dest = screens[1];
for (y=0 ; y<SCREENHEIGHT-SBARHEIGHT ; y++)
{
for (x=0 ; x<SCREENWIDTH/64 ; x++)
{
memcpy (dest, src+((y&63)<<6), 64);
dest += 64;
}
for (x=0 ; x<SCREENWIDTH/64 ; x++)
{
memcpy (dest, src+((y&63)<<6), 64);
dest += 64;
}
 
if (SCREENWIDTH&63)
{
memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
dest += (SCREENWIDTH&63);
}
if (SCREENWIDTH&63)
{
memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
dest += (SCREENWIDTH&63);
}
}
patch = W_CacheLumpName ("brdr_t",PU_CACHE);
 
for (x=0 ; x<scaledviewwidth ; x+=8)
V_DrawPatch (viewwindowx+x,viewwindowy-8,1,patch);
V_DrawPatch (viewwindowx+x,viewwindowy-8,1,patch);
patch = W_CacheLumpName ("brdr_b",PU_CACHE);
 
for (x=0 ; x<scaledviewwidth ; x+=8)
V_DrawPatch (viewwindowx+x,viewwindowy+viewheight,1,patch);
V_DrawPatch (viewwindowx+x,viewwindowy+viewheight,1,patch);
patch = W_CacheLumpName ("brdr_l",PU_CACHE);
 
for (y=0 ; y<viewheight ; y+=8)
V_DrawPatch (viewwindowx-8,viewwindowy+y,1,patch);
V_DrawPatch (viewwindowx-8,viewwindowy+y,1,patch);
patch = W_CacheLumpName ("brdr_r",PU_CACHE);
 
for (y=0 ; y<viewheight ; y+=8)
V_DrawPatch (viewwindowx+scaledviewwidth,viewwindowy+y,1,patch);
V_DrawPatch (viewwindowx+scaledviewwidth,viewwindowy+y,1,patch);
 
 
// Draw beveled edge.
V_DrawPatch (viewwindowx-8,
viewwindowy-8,
1,
W_CacheLumpName ("brdr_tl",PU_CACHE));
viewwindowy-8,
1,
W_CacheLumpName ("brdr_tl",PU_CACHE));
V_DrawPatch (viewwindowx+scaledviewwidth,
viewwindowy-8,
1,
W_CacheLumpName ("brdr_tr",PU_CACHE));
viewwindowy-8,
1,
W_CacheLumpName ("brdr_tr",PU_CACHE));
V_DrawPatch (viewwindowx-8,
viewwindowy+viewheight,
1,
W_CacheLumpName ("brdr_bl",PU_CACHE));
viewwindowy+viewheight,
1,
W_CacheLumpName ("brdr_bl",PU_CACHE));
V_DrawPatch (viewwindowx+scaledviewwidth,
viewwindowy+viewheight,
1,
W_CacheLumpName ("brdr_br",PU_CACHE));
viewwindowy+viewheight,
1,
W_CacheLumpName ("brdr_br",PU_CACHE));
}
 
816,8 → 816,8
//
void
R_VideoErase
( unsigned ofs,
int count )
( unsigned ofs,
int count )
{
// LFB copy.
// This might not be a good idea if memcpy
835,20 → 835,20
//
void
V_MarkRect
( int x,
int y,
int width,
int height );
( int x,
int y,
int width,
int height );
void R_DrawViewBorder (void)
{
int top;
int side;
int ofs;
int i;
int top;
int side;
int ofs;
int i;
if (scaledviewwidth == SCREENWIDTH)
return;
return;
top = ((SCREENHEIGHT-SBARHEIGHT)-viewheight)/2;
side = (SCREENWIDTH-scaledviewwidth)/2;
866,8 → 866,8
for (i=1 ; i<viewheight ; i++)
{
R_VideoErase (ofs, side);
ofs += SCREENWIDTH;
R_VideoErase (ofs, side);
ofs += SCREENWIDTH;
}
 
// ?
/programs/games/doom/trunk/r_things.c
1,989 → 1,995
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// $Log:$
//
// DESCRIPTION:
// Refresh of things, i.e. objects represented by sprites.
//
//-----------------------------------------------------------------------------
 
 
static const char
rcsid[] = "$Id: r_things.c,v 1.5 1997/02/03 16:47:56 b1 Exp $";
 
 
#include <stdio.h>
#include <stdlib.h>
 
 
#include "doomdef.h"
#include "m_swap.h"
 
#include "i_system.h"
#include "z_zone.h"
#include "w_wad.h"
 
#include "r_local.h"
 
#include "doomstat.h"
 
 
 
#define MINZ (FRACUNIT*4)
#define BASEYCENTER 100
 
//void R_DrawColumn (void);
//void R_DrawFuzzColumn (void);
 
 
 
typedef struct
{
int x1;
int x2;
int column;
int topclip;
int bottomclip;
 
} maskdraw_t;
 
 
 
//
// Sprite rotation 0 is facing the viewer,
// rotation 1 is one angle turn CLOCKWISE around the axis.
// This is not the same as the angle,
// which increases counter clockwise (protractor).
// There was a lot of stuff grabbed wrong, so I changed it...
//
fixed_t pspritescale;
fixed_t pspriteiscale;
 
lighttable_t** spritelights;
 
// constant arrays
// used for psprite clipping and initializing clipping
short negonearray[SCREENWIDTH];
short screenheightarray[SCREENWIDTH];
 
 
//
// INITIALIZATION FUNCTIONS
//
 
// variables used to look up
// and range check thing_t sprites patches
spritedef_t* sprites;
int numsprites;
 
spriteframe_t sprtemp[29];
int maxframe;
char* spritename;
 
 
 
 
//
// R_InstallSpriteLump
// Local function for R_InitSprites.
//
void
R_InstallSpriteLump
( int lump,
unsigned frame,
unsigned rotation,
boolean flipped )
{
int r;
if (frame >= 29 || rotation > 8)
I_Error("R_InstallSpriteLump: "
"Bad frame characters in lump %i", lump);
if ((int)frame > maxframe)
maxframe = frame;
if (rotation == 0)
{
// the lump should be used for all rotations
if (sprtemp[frame].rotate == false)
I_Error ("R_InitSprites: Sprite %s frame %c has "
"multip rot=0 lump", spritename, 'A'+frame);
 
if (sprtemp[frame].rotate == true)
I_Error ("R_InitSprites: Sprite %s frame %c has rotations "
"and a rot=0 lump", spritename, 'A'+frame);
sprtemp[frame].rotate = false;
for (r=0 ; r<8 ; r++)
{
sprtemp[frame].lump[r] = lump - firstspritelump;
sprtemp[frame].flip[r] = (byte)flipped;
}
return;
}
// the lump is only used for one rotation
if (sprtemp[frame].rotate == false)
I_Error ("R_InitSprites: Sprite %s frame %c has rotations "
"and a rot=0 lump", spritename, 'A'+frame);
sprtemp[frame].rotate = true;
 
// make 0 based
rotation--;
if (sprtemp[frame].lump[rotation] != -1)
I_Error ("R_InitSprites: Sprite %s : %c : %c "
"has two lumps mapped to it",
spritename, 'A'+frame, '1'+rotation);
sprtemp[frame].lump[rotation] = lump - firstspritelump;
sprtemp[frame].flip[rotation] = (byte)flipped;
}
 
 
 
 
//
// R_InitSpriteDefs
// Pass a null terminated list of sprite names
// (4 chars exactly) to be used.
// Builds the sprite rotation matrixes to account
// for horizontally flipped sprites.
// Will report an error if the lumps are inconsistant.
// Only called at startup.
//
// Sprite lump names are 4 characters for the actor,
// a letter for the frame, and a number for the rotation.
// A sprite that is flippable will have an additional
// letter/number appended.
// The rotation character can be 0 to signify no rotations.
//
void R_InitSpriteDefs (char** namelist)
{
char** check;
int i;
int l;
int intname;
int frame;
int rotation;
int start;
int end;
int patched;
// count the number of sprite names
check = namelist;
while (*check != NULL)
check++;
 
numsprites = check-namelist;
if (!numsprites)
return;
sprites = Z_Malloc(numsprites *sizeof(*sprites), PU_STATIC, NULL);
start = firstspritelump-1;
end = lastspritelump+1;
// scan all the lump names for each of the names,
// noting the highest frame letter.
// Just compare 4 characters as ints
for (i=0 ; i<numsprites ; i++)
{
spritename = namelist[i];
memset (sprtemp,-1, sizeof(sprtemp));
maxframe = -1;
intname = *(int *)namelist[i];
// scan the lumps,
// filling in the frames for whatever is found
for (l=start+1 ; l<end ; l++)
{
if (*(int *)lumpinfo[l].name == intname)
{
frame = lumpinfo[l].name[4] - 'A';
rotation = lumpinfo[l].name[5] - '0';
 
if (modifiedgame)
patched = W_GetNumForName (lumpinfo[l].name);
else
patched = l;
 
R_InstallSpriteLump (patched, frame, rotation, false);
 
if (lumpinfo[l].name[6])
{
frame = lumpinfo[l].name[6] - 'A';
rotation = lumpinfo[l].name[7] - '0';
R_InstallSpriteLump (l, frame, rotation, true);
}
}
}
// check the frames that were found for completeness
if (maxframe == -1)
{
sprites[i].numframes = 0;
continue;
}
maxframe++;
for (frame = 0 ; frame < maxframe ; frame++)
{
switch ((int)sprtemp[frame].rotate)
{
case -1:
// no rotations were found for that frame at all
I_Error ("R_InitSprites: No patches found "
"for %s frame %c", namelist[i], frame+'A');
break;
case 0:
// only the first rotation is needed
break;
case 1:
// must have all 8 frames
for (rotation=0 ; rotation<8 ; rotation++)
if (sprtemp[frame].lump[rotation] == -1)
I_Error ("R_InitSprites: Sprite %s frame %c "
"is missing rotations",
namelist[i], frame+'A');
break;
}
}
// allocate space for the frames present and copy sprtemp to it
sprites[i].numframes = maxframe;
sprites[i].spriteframes =
Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL);
memcpy (sprites[i].spriteframes, sprtemp, maxframe*sizeof(spriteframe_t));
}
 
}
 
 
 
 
//
// GAME FUNCTIONS
//
vissprite_t vissprites[MAXVISSPRITES];
vissprite_t* vissprite_p;
int newvissprite;
 
 
 
//
// R_InitSprites
// Called at program start.
//
void R_InitSprites (char** namelist)
{
int i;
for (i=0 ; i<SCREENWIDTH ; i++)
{
negonearray[i] = -1;
}
R_InitSpriteDefs (namelist);
}
 
 
 
//
// R_ClearSprites
// Called at frame start.
//
void R_ClearSprites (void)
{
vissprite_p = vissprites;
}
 
 
//
// R_NewVisSprite
//
vissprite_t overflowsprite;
 
vissprite_t* R_NewVisSprite (void)
{
if (vissprite_p == &vissprites[MAXVISSPRITES])
return &overflowsprite;
vissprite_p++;
return vissprite_p-1;
}
 
 
 
//
// R_DrawMaskedColumn
// Used for sprites and masked mid textures.
// Masked means: partly transparent, i.e. stored
// in posts/runs of opaque pixels.
//
short* mfloorclip;
short* mceilingclip;
 
fixed_t spryscale;
fixed_t sprtopscreen;
 
void R_DrawMaskedColumn (column_t* column)
{
int topscreen;
int bottomscreen;
fixed_t basetexturemid;
basetexturemid = dc_texturemid;
for ( ; column->topdelta != 0xff ; )
{
// calculate unclipped screen coordinates
// for post
topscreen = sprtopscreen + spryscale*column->topdelta;
bottomscreen = topscreen + spryscale*column->length;
 
dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS;
dc_yh = (bottomscreen-1)>>FRACBITS;
if (dc_yh >= mfloorclip[dc_x])
dc_yh = mfloorclip[dc_x]-1;
if (dc_yl <= mceilingclip[dc_x])
dc_yl = mceilingclip[dc_x]+1;
 
if (dc_yl <= dc_yh)
{
dc_source = (byte *)column + 3;
dc_texturemid = basetexturemid - (column->topdelta<<FRACBITS);
// dc_source = (byte *)column + 3 - column->topdelta;
 
// Drawn by either R_DrawColumn
// or (SHADOW) R_DrawFuzzColumn.
colfunc ();
}
column = (column_t *)( (byte *)column + column->length + 4);
}
dc_texturemid = basetexturemid;
}
 
 
 
//
// R_DrawVisSprite
// mfloorclip and mceilingclip should also be set.
//
void
R_DrawVisSprite
( vissprite_t* vis,
int x1,
int x2 )
{
column_t* column;
int texturecolumn;
fixed_t frac;
patch_t* patch;
patch = W_CacheLumpNum (vis->patch+firstspritelump, PU_CACHE);
 
dc_colormap = vis->colormap;
if (!dc_colormap)
{
// NULL colormap = shadow draw
colfunc = fuzzcolfunc;
}
else if (vis->mobjflags & MF_TRANSLATION)
{
colfunc = R_DrawTranslatedColumn;
dc_translation = translationtables - 256 +
( (vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT-8) );
}
dc_iscale = abs(vis->xiscale)>>detailshift;
dc_texturemid = vis->texturemid;
frac = vis->startfrac;
spryscale = vis->scale;
sprtopscreen = centeryfrac - FixedMul(dc_texturemid,spryscale);
for (dc_x=vis->x1 ; dc_x<=vis->x2 ; dc_x++, frac += vis->xiscale)
{
texturecolumn = frac>>FRACBITS;
#ifdef RANGECHECK
if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
I_Error ("R_DrawSpriteRange: bad texturecolumn");
#endif
column = (column_t *) ((byte *)patch +
LONG(patch->columnofs[texturecolumn]));
R_DrawMaskedColumn (column);
}
 
colfunc = basecolfunc;
}
 
 
 
//
// R_ProjectSprite
// Generates a vissprite for a thing
// if it might be visible.
//
void R_ProjectSprite (mobj_t* thing)
{
fixed_t tr_x;
fixed_t tr_y;
fixed_t gxt;
fixed_t gyt;
fixed_t tx;
fixed_t tz;
 
fixed_t xscale;
int x1;
int x2;
 
spritedef_t* sprdef;
spriteframe_t* sprframe;
int lump;
unsigned rot;
boolean flip;
int index;
 
vissprite_t* vis;
angle_t ang;
fixed_t iscale;
// transform the origin point
tr_x = thing->x - viewx;
tr_y = thing->y - viewy;
gxt = FixedMul(tr_x,viewcos);
gyt = -FixedMul(tr_y,viewsin);
tz = gxt-gyt;
 
// thing is behind view plane?
if (tz < MINZ)
return;
xscale = FixedDiv(projection, tz);
gxt = -FixedMul(tr_x,viewsin);
gyt = FixedMul(tr_y,viewcos);
tx = -(gyt+gxt);
 
// too far off the side?
if (abs(tx)>(tz<<2))
return;
// decide which patch to use for sprite relative to player
#ifdef RANGECHECK
if ((unsigned)thing->sprite >= numsprites)
I_Error ("R_ProjectSprite: invalid sprite number %i ",
thing->sprite);
#endif
sprdef = &sprites[thing->sprite];
#ifdef RANGECHECK
if ( (thing->frame&FF_FRAMEMASK) >= sprdef->numframes )
I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ",
thing->sprite, thing->frame);
#endif
sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK];
 
if (sprframe->rotate)
{
// choose a different rotation based on player view
ang = R_PointToAngle (thing->x, thing->y);
rot = (ang-thing->angle+(unsigned)(ANG45/2)*9)>>29;
lump = sprframe->lump[rot];
flip = (boolean)sprframe->flip[rot];
}
else
{
// use single rotation for all views
lump = sprframe->lump[0];
flip = (boolean)sprframe->flip[0];
}
// calculate edges of the shape
tx -= spriteoffset[lump];
x1 = (centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS;
 
// off the right side?
if (x1 > viewwidth)
return;
tx += spritewidth[lump];
x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1;
 
// off the left side
if (x2 < 0)
return;
// store information in a vissprite
vis = R_NewVisSprite ();
vis->mobjflags = thing->flags;
vis->scale = xscale<<detailshift;
vis->gx = thing->x;
vis->gy = thing->y;
vis->gz = thing->z;
vis->gzt = thing->z + spritetopoffset[lump];
vis->texturemid = vis->gzt - viewz;
vis->x1 = x1 < 0 ? 0 : x1;
vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
iscale = FixedDiv (FRACUNIT, xscale);
 
if (flip)
{
vis->startfrac = spritewidth[lump]-1;
vis->xiscale = -iscale;
}
else
{
vis->startfrac = 0;
vis->xiscale = iscale;
}
 
if (vis->x1 > x1)
vis->startfrac += vis->xiscale*(vis->x1-x1);
vis->patch = lump;
// get light level
if (thing->flags & MF_SHADOW)
{
// shadow draw
vis->colormap = NULL;
}
else if (fixedcolormap)
{
// fixed map
vis->colormap = fixedcolormap;
}
else if (thing->frame & FF_FULLBRIGHT)
{
// full bright
vis->colormap = colormaps;
}
else
{
// diminished light
index = xscale>>(LIGHTSCALESHIFT-detailshift);
 
if (index >= MAXLIGHTSCALE)
index = MAXLIGHTSCALE-1;
 
vis->colormap = spritelights[index];
}
}
 
 
 
 
//
// R_AddSprites
// During BSP traversal, this adds sprites by sector.
//
void R_AddSprites (sector_t* sec)
{
mobj_t* thing;
int lightnum;
 
// BSP is traversed by subsector.
// A sector might have been split into several
// subsectors during BSP building.
// Thus we check whether its already added.
if (sec->validcount == validcount)
return;
 
// Well, now it will be done.
sec->validcount = validcount;
lightnum = (sec->lightlevel >> LIGHTSEGSHIFT)+extralight;
 
if (lightnum < 0)
spritelights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
spritelights = scalelight[LIGHTLEVELS-1];
else
spritelights = scalelight[lightnum];
 
// Handle all things in sector.
for (thing = sec->thinglist ; thing ; thing = thing->snext)
R_ProjectSprite (thing);
}
 
 
//
// R_DrawPSprite
//
void R_DrawPSprite (pspdef_t* psp)
{
fixed_t tx;
int x1;
int x2;
spritedef_t* sprdef;
spriteframe_t* sprframe;
int lump;
boolean flip;
vissprite_t* vis;
vissprite_t avis;
// decide which patch to use
#ifdef RANGECHECK
if ( (unsigned)psp->state->sprite >= numsprites)
I_Error ("R_ProjectSprite: invalid sprite number %i ",
psp->state->sprite);
#endif
sprdef = &sprites[psp->state->sprite];
#ifdef RANGECHECK
if ( (psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes)
I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ",
psp->state->sprite, psp->state->frame);
#endif
sprframe = &sprdef->spriteframes[ psp->state->frame & FF_FRAMEMASK ];
 
lump = sprframe->lump[0];
flip = (boolean)sprframe->flip[0];
// calculate edges of the shape
tx = psp->sx-160*FRACUNIT;
tx -= spriteoffset[lump];
x1 = (centerxfrac + FixedMul (tx,pspritescale) ) >>FRACBITS;
 
// off the right side
if (x1 > viewwidth)
return;
 
tx += spritewidth[lump];
x2 = ((centerxfrac + FixedMul (tx, pspritescale) ) >>FRACBITS) - 1;
 
// off the left side
if (x2 < 0)
return;
// store information in a vissprite
vis = &avis;
vis->mobjflags = 0;
vis->texturemid = (BASEYCENTER<<FRACBITS)+FRACUNIT/2-(psp->sy-spritetopoffset[lump]);
vis->x1 = x1 < 0 ? 0 : x1;
vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
vis->scale = pspritescale<<detailshift;
if (flip)
{
vis->xiscale = -pspriteiscale;
vis->startfrac = spritewidth[lump]-1;
}
else
{
vis->xiscale = pspriteiscale;
vis->startfrac = 0;
}
if (vis->x1 > x1)
vis->startfrac += vis->xiscale*(vis->x1-x1);
 
vis->patch = lump;
 
if (viewplayer->powers[pw_invisibility] > 4*32
|| viewplayer->powers[pw_invisibility] & 8)
{
// shadow draw
vis->colormap = NULL;
}
else if (fixedcolormap)
{
// fixed color
vis->colormap = fixedcolormap;
}
else if (psp->state->frame & FF_FULLBRIGHT)
{
// full bright
vis->colormap = colormaps;
}
else
{
// local light
vis->colormap = spritelights[MAXLIGHTSCALE-1];
}
R_DrawVisSprite (vis, vis->x1, vis->x2);
}
 
 
 
//
// R_DrawPlayerSprites
//
void R_DrawPlayerSprites (void)
{
int i;
int lightnum;
pspdef_t* psp;
// get light level
lightnum =
(viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT)
+extralight;
 
if (lightnum < 0)
spritelights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
spritelights = scalelight[LIGHTLEVELS-1];
else
spritelights = scalelight[lightnum];
// clip to screen bounds
mfloorclip = screenheightarray;
mceilingclip = negonearray;
// add all active psprites
for (i=0, psp=viewplayer->psprites;
i<NUMPSPRITES;
i++,psp++)
{
if (psp->state)
R_DrawPSprite (psp);
}
}
 
 
 
 
//
// R_SortVisSprites
//
vissprite_t vsprsortedhead;
 
 
void R_SortVisSprites (void)
{
int i;
int count;
vissprite_t* ds;
vissprite_t* best;
vissprite_t unsorted;
fixed_t bestscale;
 
count = vissprite_p - vissprites;
unsorted.next = unsorted.prev = &unsorted;
 
if (!count)
return;
for (ds=vissprites ; ds<vissprite_p ; ds++)
{
ds->next = ds+1;
ds->prev = ds-1;
}
vissprites[0].prev = &unsorted;
unsorted.next = &vissprites[0];
(vissprite_p-1)->next = &unsorted;
unsorted.prev = vissprite_p-1;
// pull the vissprites out by scale
//best = 0; // shut up the compiler warning
vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead;
for (i=0 ; i<count ; i++)
{
bestscale = MAXINT;
for (ds=unsorted.next ; ds!= &unsorted ; ds=ds->next)
{
if (ds->scale < bestscale)
{
bestscale = ds->scale;
best = ds;
}
}
best->next->prev = best->prev;
best->prev->next = best->next;
best->next = &vsprsortedhead;
best->prev = vsprsortedhead.prev;
vsprsortedhead.prev->next = best;
vsprsortedhead.prev = best;
}
}
 
 
 
//
// R_DrawSprite
//
void R_DrawSprite (vissprite_t* spr)
{
drawseg_t* ds;
short clipbot[SCREENWIDTH];
short cliptop[SCREENWIDTH];
int x;
int r1;
int r2;
fixed_t scale;
fixed_t lowscale;
int silhouette;
for (x = spr->x1 ; x<=spr->x2 ; x++)
clipbot[x] = cliptop[x] = -2;
// Scan drawsegs from end to start for obscuring segs.
// The first drawseg that has a greater scale
// is the clip seg.
for (ds=ds_p-1 ; ds >= drawsegs ; ds--)
{
// determine if the drawseg obscures the sprite
if (ds->x1 > spr->x2
|| ds->x2 < spr->x1
|| (!ds->silhouette
&& !ds->maskedtexturecol) )
{
// does not cover sprite
continue;
}
r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1;
r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2;
 
if (ds->scale1 > ds->scale2)
{
lowscale = ds->scale2;
scale = ds->scale1;
}
else
{
lowscale = ds->scale1;
scale = ds->scale2;
}
if (scale < spr->scale
|| ( lowscale < spr->scale
&& !R_PointOnSegSide (spr->gx, spr->gy, ds->curline) ) )
{
// masked mid texture?
if (ds->maskedtexturecol)
R_RenderMaskedSegRange (ds, r1, r2);
// seg is behind sprite
continue;
}
 
// clip this piece of the sprite
silhouette = ds->silhouette;
if (spr->gz >= ds->bsilheight)
silhouette &= ~SIL_BOTTOM;
 
if (spr->gzt <= ds->tsilheight)
silhouette &= ~SIL_TOP;
if (silhouette == 1)
{
// bottom sil
for (x=r1 ; x<=r2 ; x++)
if (clipbot[x] == -2)
clipbot[x] = ds->sprbottomclip[x];
}
else if (silhouette == 2)
{
// top sil
for (x=r1 ; x<=r2 ; x++)
if (cliptop[x] == -2)
cliptop[x] = ds->sprtopclip[x];
}
else if (silhouette == 3)
{
// both
for (x=r1 ; x<=r2 ; x++)
{
if (clipbot[x] == -2)
clipbot[x] = ds->sprbottomclip[x];
if (cliptop[x] == -2)
cliptop[x] = ds->sprtopclip[x];
}
}
}
// all clipping has been performed, so draw the sprite
 
// check for unclipped columns
for (x = spr->x1 ; x<=spr->x2 ; x++)
{
if (clipbot[x] == -2)
clipbot[x] = viewheight;
 
if (cliptop[x] == -2)
cliptop[x] = -1;
}
mfloorclip = clipbot;
mceilingclip = cliptop;
R_DrawVisSprite (spr, spr->x1, spr->x2);
}
 
 
 
 
//
// R_DrawMasked
//
void R_DrawMasked (void)
{
vissprite_t* spr;
drawseg_t* ds;
R_SortVisSprites ();
 
if (vissprite_p > vissprites)
{
// draw all vissprites back to front
for (spr = vsprsortedhead.next ;
spr != &vsprsortedhead ;
spr=spr->next)
{
R_DrawSprite (spr);
}
}
// render any remaining masked mid textures
for (ds=ds_p-1 ; ds >= drawsegs ; ds--)
if (ds->maskedtexturecol)
R_RenderMaskedSegRange (ds, ds->x1, ds->x2);
// draw the psprites on top of everything
// but does not draw on side views
if (!viewangleoffset)
R_DrawPlayerSprites ();
}
 
 
 
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// $Log:$
//
// DESCRIPTION:
// Refresh of things, i.e. objects represented by sprites.
//
//-----------------------------------------------------------------------------
 
 
static const char
rcsid[] = "$Id: r_things.c,v 1.5 1997/02/03 16:47:56 b1 Exp $";
 
 
#include <stdio.h>
#include <stdlib.h>
 
#include "doomtype.h"
 
#include "doomdef.h"
#include "m_swap.h"
 
#include "i_system.h"
#include "z_zone.h"
#include "w_wad.h"
 
#include "r_local.h"
 
#include "doomstat.h"
 
 
 
#define MINZ (FRACUNIT*4)
#define BASEYCENTER 100
 
//void R_DrawColumn (void);
//void R_DrawFuzzColumn (void);
 
 
 
typedef struct
{
int x1;
int x2;
int column;
int topclip;
int bottomclip;
 
} maskdraw_t;
 
 
 
//
// Sprite rotation 0 is facing the viewer,
// rotation 1 is one angle turn CLOCKWISE around the axis.
// This is not the same as the angle,
// which increases counter clockwise (protractor).
// There was a lot of stuff grabbed wrong, so I changed it...
//
fixed_t pspritescale;
fixed_t pspriteiscale;
 
lighttable_t** spritelights;
 
// constant arrays
// used for psprite clipping and initializing clipping
short negonearray[SCREENWIDTH];
short screenheightarray[SCREENWIDTH];
 
 
//
// INITIALIZATION FUNCTIONS
//
 
// variables used to look up
// and range check thing_t sprites patches
spritedef_t* sprites;
int numsprites;
 
spriteframe_t sprtemp[29];
int maxframe;
char* spritename;
 
 
 
 
//
// R_InstallSpriteLump
// Local function for R_InitSprites.
//
void
R_InstallSpriteLump
( int lump,
unsigned frame,
unsigned rotation,
boolean flipped )
{
int r;
if (frame >= 29 || rotation > 8)
I_Error("R_InstallSpriteLump: "
"Bad frame characters in lump %i", lump);
if ((int)frame > maxframe)
maxframe = frame;
if (rotation == 0)
{
// the lump should be used for all rotations
if (sprtemp[frame].rotate == false)
I_Error ("R_InitSprites: Sprite %s frame %c has "
"multip rot=0 lump", spritename, 'A'+frame);
 
if (sprtemp[frame].rotate == true)
I_Error ("R_InitSprites: Sprite %s frame %c has rotations "
"and a rot=0 lump", spritename, 'A'+frame);
sprtemp[frame].rotate = false;
for (r=0 ; r<8 ; r++)
{
sprtemp[frame].lump[r] = lump - firstspritelump;
sprtemp[frame].flip[r] = (byte)flipped;
}
return;
}
// the lump is only used for one rotation
if (sprtemp[frame].rotate == false)
I_Error ("R_InitSprites: Sprite %s frame %c has rotations "
"and a rot=0 lump", spritename, 'A'+frame);
sprtemp[frame].rotate = true;
 
// make 0 based
rotation--;
if (sprtemp[frame].lump[rotation] != -1)
I_Error ("R_InitSprites: Sprite %s : %c : %c "
"has two lumps mapped to it",
spritename, 'A'+frame, '1'+rotation);
sprtemp[frame].lump[rotation] = lump - firstspritelump;
sprtemp[frame].flip[rotation] = (byte)flipped;
}
 
 
 
 
//
// R_InitSpriteDefs
// Pass a null terminated list of sprite names
// (4 chars exactly) to be used.
// Builds the sprite rotation matrixes to account
// for horizontally flipped sprites.
// Will report an error if the lumps are inconsistant.
// Only called at startup.
//
// Sprite lump names are 4 characters for the actor,
// a letter for the frame, and a number for the rotation.
// A sprite that is flippable will have an additional
// letter/number appended.
// The rotation character can be 0 to signify no rotations.
//
void R_InitSpriteDefs (char** namelist)
{
char** check;
int i;
int l;
int intname;
int frame;
int rotation;
int start;
int end;
int patched;
// count the number of sprite names
check = namelist;
while (*check != NULL)
check++;
 
numsprites = check-namelist;
if (!numsprites)
return;
sprites = Z_Malloc(numsprites *sizeof(*sprites), PU_STATIC, NULL);
start = firstspritelump-1;
end = lastspritelump+1;
// scan all the lump names for each of the names,
// noting the highest frame letter.
// Just compare 4 characters as ints
for (i=0 ; i<numsprites ; i++)
{
spritename = namelist[i];
memset (sprtemp,-1, sizeof(sprtemp));
maxframe = -1;
intname = *(int *)namelist[i];
// scan the lumps,
// filling in the frames for whatever is found
for (l=start+1 ; l<end ; l++)
{
if (*(int *)lumpinfo[l].name == intname)
{
frame = lumpinfo[l].name[4] - 'A';
rotation = lumpinfo[l].name[5] - '0';
 
if (modifiedgame)
patched = W_GetNumForName (lumpinfo[l].name);
else
patched = l;
 
R_InstallSpriteLump (patched, frame, rotation, false);
 
if (lumpinfo[l].name[6])
{
frame = lumpinfo[l].name[6] - 'A';
rotation = lumpinfo[l].name[7] - '0';
R_InstallSpriteLump (l, frame, rotation, true);
}
}
}
// check the frames that were found for completeness
if (maxframe == -1)
{
sprites[i].numframes = 0;
continue;
}
maxframe++;
for (frame = 0 ; frame < maxframe ; frame++)
{
switch ((int)sprtemp[frame].rotate)
{
case -1:
// no rotations were found for that frame at all
I_Error ("R_InitSprites: No patches found "
"for %s frame %c", namelist[i], frame+'A');
break;
case 0:
// only the first rotation is needed
break;
case 1:
// must have all 8 frames
for (rotation=0 ; rotation<8 ; rotation++)
if (sprtemp[frame].lump[rotation] == -1)
I_Error ("R_InitSprites: Sprite %s frame %c "
"is missing rotations",
namelist[i], frame+'A');
break;
}
}
// allocate space for the frames present and copy sprtemp to it
sprites[i].numframes = maxframe;
sprites[i].spriteframes =
Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL);
memcpy (sprites[i].spriteframes, sprtemp, maxframe*sizeof(spriteframe_t));
}
 
}
 
 
 
 
//
// GAME FUNCTIONS
//
vissprite_t vissprites[MAXVISSPRITES];
vissprite_t* vissprite_p;
int newvissprite;
 
 
 
//
// R_InitSprites
// Called at program start.
//
void R_InitSprites (char** namelist)
{
int i;
for (i=0 ; i<SCREENWIDTH ; i++)
{
negonearray[i] = -1;
}
R_InitSpriteDefs (namelist);
}
 
 
 
//
// R_ClearSprites
// Called at frame start.
//
void R_ClearSprites (void)
{
vissprite_p = vissprites;
}
 
 
//
// R_NewVisSprite
//
vissprite_t overflowsprite;
 
vissprite_t* R_NewVisSprite (void)
{
if (vissprite_p == &vissprites[MAXVISSPRITES])
return &overflowsprite;
vissprite_p++;
return vissprite_p-1;
}
 
 
 
//
// R_DrawMaskedColumn
// Used for sprites and masked mid textures.
// Masked means: partly transparent, i.e. stored
// in posts/runs of opaque pixels.
//
short* mfloorclip;
short* mceilingclip;
 
fixed_t spryscale;
fixed_t sprtopscreen;
 
void R_DrawMaskedColumn (column_t* column)
{
int topscreen;
int bottomscreen;
fixed_t basetexturemid;
basetexturemid = dc_texturemid;
for ( ; column->topdelta != 0xff ; )
{
// calculate unclipped screen coordinates
// for post
topscreen = sprtopscreen + spryscale*column->topdelta;
bottomscreen = topscreen + spryscale*column->length;
 
dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS;
dc_yh = (bottomscreen-1)>>FRACBITS;
if (dc_yh >= mfloorclip[dc_x])
dc_yh = mfloorclip[dc_x]-1;
if (dc_yl <= mceilingclip[dc_x])
dc_yl = mceilingclip[dc_x]+1;
 
if (dc_yl <= dc_yh)
{
dc_source = (byte *)column + 3;
dc_texturemid = basetexturemid - (column->topdelta<<FRACBITS);
// dc_source = (byte *)column + 3 - column->topdelta;
 
// Drawn by either R_DrawColumn
// or (SHADOW) R_DrawFuzzColumn.
colfunc ();
}
column = (column_t *)( (byte *)column + column->length + 4);
}
dc_texturemid = basetexturemid;
}
 
 
 
//
// R_DrawVisSprite
// mfloorclip and mceilingclip should also be set.
//
void
R_DrawVisSprite
( vissprite_t* vis,
int x1,
int x2 )
{
column_t* column;
int texturecolumn;
fixed_t frac;
patch_t* patch;
patch = W_CacheLumpNum (vis->patch+firstspritelump, PU_CACHE);
 
dc_colormap = vis->colormap;
if (!dc_colormap)
{
// NULL colormap = shadow draw
colfunc = fuzzcolfunc;
}
else if (vis->mobjflags & MF_TRANSLATION)
{
colfunc = R_DrawTranslatedColumn;
dc_translation = translationtables - 256 +
( (vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT-8) );
}
dc_iscale = abs(vis->xiscale)>>detailshift;
dc_texturemid = vis->texturemid;
frac = vis->startfrac;
spryscale = vis->scale;
sprtopscreen = centeryfrac - FixedMul(dc_texturemid,spryscale);
for (dc_x=vis->x1 ; dc_x<=vis->x2 ; dc_x++, frac += vis->xiscale)
{
texturecolumn = frac>>FRACBITS;
#ifdef RANGECHECK
if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
{
// I_Error ("R_DrawSpriteRange: bad texturecolumn");
printf( "texturecolumn= %d, width= %d\n\r",
texturecolumn,patch->width);
texturecolumn=patch->width-1;
}
#endif
column = (column_t *) ((byte *)patch +
LONG(patch->columnofs[texturecolumn]));
R_DrawMaskedColumn (column);
}
 
colfunc = basecolfunc;
}
 
 
 
//
// R_ProjectSprite
// Generates a vissprite for a thing
// if it might be visible.
//
void R_ProjectSprite (mobj_t* thing)
{
fixed_t tr_x;
fixed_t tr_y;
fixed_t gxt;
fixed_t gyt;
fixed_t tx;
fixed_t tz;
 
fixed_t xscale;
int x1;
int x2;
 
spritedef_t* sprdef;
spriteframe_t* sprframe;
int lump;
unsigned rot;
boolean flip;
int index;
 
vissprite_t* vis;
angle_t ang;
fixed_t iscale;
// transform the origin point
tr_x = thing->x - viewx;
tr_y = thing->y - viewy;
gxt = FixedMul(tr_x,viewcos);
gyt = -FixedMul(tr_y,viewsin);
tz = gxt-gyt;
 
// thing is behind view plane?
if (tz < MINZ)
return;
xscale = FixedDiv(projection, tz);
gxt = -FixedMul(tr_x,viewsin);
gyt = FixedMul(tr_y,viewcos);
tx = -(gyt+gxt);
 
// too far off the side?
if (abs(tx)>(tz<<2))
return;
// decide which patch to use for sprite relative to player
#ifdef RANGECHECK
if ((unsigned)thing->sprite >= numsprites)
I_Error ("R_ProjectSprite: invalid sprite number %i ",
thing->sprite);
#endif
sprdef = &sprites[thing->sprite];
#ifdef RANGECHECK
if ( (thing->frame&FF_FRAMEMASK) >= sprdef->numframes )
I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ",
thing->sprite, thing->frame);
#endif
sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK];
 
if (sprframe->rotate)
{
// choose a different rotation based on player view
ang = R_PointToAngle (thing->x, thing->y);
rot = (ang-thing->angle+(unsigned)(ANG45/2)*9)>>29;
lump = sprframe->lump[rot];
flip = (boolean)sprframe->flip[rot];
}
else
{
// use single rotation for all views
lump = sprframe->lump[0];
flip = (boolean)sprframe->flip[0];
}
// calculate edges of the shape
tx -= spriteoffset[lump];
x1 = (centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS;
 
// off the right side?
if (x1 > viewwidth)
return;
tx += spritewidth[lump];
x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1;
 
// off the left side
if (x2 < 0)
return;
// store information in a vissprite
vis = R_NewVisSprite ();
vis->mobjflags = thing->flags;
vis->scale = xscale<<detailshift;
vis->gx = thing->x;
vis->gy = thing->y;
vis->gz = thing->z;
vis->gzt = thing->z + spritetopoffset[lump];
vis->texturemid = vis->gzt - viewz;
vis->x1 = x1 < 0 ? 0 : x1;
vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
iscale = FixedDiv (FRACUNIT, xscale);
 
if (flip)
{
vis->startfrac = spritewidth[lump]-1;
vis->xiscale = -iscale;
}
else
{
vis->startfrac = 0;
vis->xiscale = iscale;
}
 
if (vis->x1 > x1)
vis->startfrac += vis->xiscale*(vis->x1-x1);
vis->patch = lump;
// get light level
if (thing->flags & MF_SHADOW)
{
// shadow draw
vis->colormap = NULL;
}
else if (fixedcolormap)
{
// fixed map
vis->colormap = fixedcolormap;
}
else if (thing->frame & FF_FULLBRIGHT)
{
// full bright
vis->colormap = colormaps;
}
else
{
// diminished light
index = xscale>>(LIGHTSCALESHIFT-detailshift);
 
if (index >= MAXLIGHTSCALE)
index = MAXLIGHTSCALE-1;
 
vis->colormap = spritelights[index];
}
}
 
 
 
 
//
// R_AddSprites
// During BSP traversal, this adds sprites by sector.
//
void R_AddSprites (sector_t* sec)
{
mobj_t* thing;
int lightnum;
 
// BSP is traversed by subsector.
// A sector might have been split into several
// subsectors during BSP building.
// Thus we check whether its already added.
if (sec->validcount == validcount)
return;
 
// Well, now it will be done.
sec->validcount = validcount;
lightnum = (sec->lightlevel >> LIGHTSEGSHIFT)+extralight;
 
if (lightnum < 0)
spritelights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
spritelights = scalelight[LIGHTLEVELS-1];
else
spritelights = scalelight[lightnum];
 
// Handle all things in sector.
for (thing = sec->thinglist ; thing ; thing = thing->snext)
R_ProjectSprite (thing);
}
 
 
//
// R_DrawPSprite
//
void R_DrawPSprite (pspdef_t* psp)
{
fixed_t tx;
int x1;
int x2;
spritedef_t* sprdef;
spriteframe_t* sprframe;
int lump;
boolean flip;
vissprite_t* vis;
vissprite_t avis;
// decide which patch to use
#ifdef RANGECHECK
if ( (unsigned)psp->state->sprite >= numsprites)
I_Error ("R_ProjectSprite: invalid sprite number %i ",
psp->state->sprite);
#endif
sprdef = &sprites[psp->state->sprite];
#ifdef RANGECHECK
if ( (psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes)
I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ",
psp->state->sprite, psp->state->frame);
#endif
sprframe = &sprdef->spriteframes[ psp->state->frame & FF_FRAMEMASK ];
 
lump = sprframe->lump[0];
flip = (boolean)sprframe->flip[0];
// calculate edges of the shape
tx = psp->sx-160*FRACUNIT;
tx -= spriteoffset[lump];
x1 = (centerxfrac + FixedMul (tx,pspritescale) ) >>FRACBITS;
 
// off the right side
if (x1 > viewwidth)
return;
 
tx += spritewidth[lump];
x2 = ((centerxfrac + FixedMul (tx, pspritescale) ) >>FRACBITS) - 1;
 
// off the left side
if (x2 < 0)
return;
// store information in a vissprite
vis = &avis;
vis->mobjflags = 0;
vis->texturemid = (BASEYCENTER<<FRACBITS)+FRACUNIT/2-(psp->sy-spritetopoffset[lump]);
vis->x1 = x1 < 0 ? 0 : x1;
vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
vis->scale = pspritescale<<detailshift;
if (flip)
{
vis->xiscale = -pspriteiscale;
vis->startfrac = spritewidth[lump]-1;
}
else
{
vis->xiscale = pspriteiscale;
vis->startfrac = 0;
}
if (vis->x1 > x1)
vis->startfrac += vis->xiscale*(vis->x1-x1);
 
vis->patch = lump;
 
if (viewplayer->powers[pw_invisibility] > 4*32
|| viewplayer->powers[pw_invisibility] & 8)
{
// shadow draw
vis->colormap = NULL;
}
else if (fixedcolormap)
{
// fixed color
vis->colormap = fixedcolormap;
}
else if (psp->state->frame & FF_FULLBRIGHT)
{
// full bright
vis->colormap = colormaps;
}
else
{
// local light
vis->colormap = spritelights[MAXLIGHTSCALE-1];
}
R_DrawVisSprite (vis, vis->x1, vis->x2);
}
 
 
 
//
// R_DrawPlayerSprites
//
void R_DrawPlayerSprites (void)
{
int i;
int lightnum;
pspdef_t* psp;
// get light level
lightnum =
(viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT)
+extralight;
 
if (lightnum < 0)
spritelights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
spritelights = scalelight[LIGHTLEVELS-1];
else
spritelights = scalelight[lightnum];
// clip to screen bounds
mfloorclip = screenheightarray;
mceilingclip = negonearray;
// add all active psprites
for (i=0, psp=viewplayer->psprites;
i<NUMPSPRITES;
i++,psp++)
{
if (psp->state)
R_DrawPSprite (psp);
}
}
 
 
 
 
//
// R_SortVisSprites
//
vissprite_t vsprsortedhead;
 
 
void R_SortVisSprites (void)
{
int i;
int count;
vissprite_t* ds;
vissprite_t* best;
vissprite_t unsorted;
fixed_t bestscale;
 
count = vissprite_p - vissprites;
unsorted.next = unsorted.prev = &unsorted;
 
if (!count)
return;
for (ds=vissprites ; ds<vissprite_p ; ds++)
{
ds->next = ds+1;
ds->prev = ds-1;
}
vissprites[0].prev = &unsorted;
unsorted.next = &vissprites[0];
(vissprite_p-1)->next = &unsorted;
unsorted.prev = vissprite_p-1;
// pull the vissprites out by scale
//best = 0; // shut up the compiler warning
vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead;
for (i=0 ; i<count ; i++)
{
bestscale = MAXINT;
for (ds=unsorted.next ; ds!= &unsorted ; ds=ds->next)
{
if (ds->scale < bestscale)
{
bestscale = ds->scale;
best = ds;
}
}
best->next->prev = best->prev;
best->prev->next = best->next;
best->next = &vsprsortedhead;
best->prev = vsprsortedhead.prev;
vsprsortedhead.prev->next = best;
vsprsortedhead.prev = best;
}
}
 
 
 
//
// R_DrawSprite
//
void R_DrawSprite (vissprite_t* spr)
{
drawseg_t* ds;
short clipbot[SCREENWIDTH];
short cliptop[SCREENWIDTH];
int x;
int r1;
int r2;
fixed_t scale;
fixed_t lowscale;
int silhouette;
for (x = spr->x1 ; x<=spr->x2 ; x++)
clipbot[x] = cliptop[x] = -2;
// Scan drawsegs from end to start for obscuring segs.
// The first drawseg that has a greater scale
// is the clip seg.
for (ds=ds_p-1 ; ds >= drawsegs ; ds--)
{
// determine if the drawseg obscures the sprite
if (ds->x1 > spr->x2
|| ds->x2 < spr->x1
|| (!ds->silhouette
&& !ds->maskedtexturecol) )
{
// does not cover sprite
continue;
}
r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1;
r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2;
 
if (ds->scale1 > ds->scale2)
{
lowscale = ds->scale2;
scale = ds->scale1;
}
else
{
lowscale = ds->scale1;
scale = ds->scale2;
}
if (scale < spr->scale
|| ( lowscale < spr->scale
&& !R_PointOnSegSide (spr->gx, spr->gy, ds->curline) ) )
{
// masked mid texture?
if (ds->maskedtexturecol)
R_RenderMaskedSegRange (ds, r1, r2);
// seg is behind sprite
continue;
}
 
// clip this piece of the sprite
silhouette = ds->silhouette;
if (spr->gz >= ds->bsilheight)
silhouette &= ~SIL_BOTTOM;
 
if (spr->gzt <= ds->tsilheight)
silhouette &= ~SIL_TOP;
if (silhouette == 1)
{
// bottom sil
for (x=r1 ; x<=r2 ; x++)
if (clipbot[x] == -2)
clipbot[x] = ds->sprbottomclip[x];
}
else if (silhouette == 2)
{
// top sil
for (x=r1 ; x<=r2 ; x++)
if (cliptop[x] == -2)
cliptop[x] = ds->sprtopclip[x];
}
else if (silhouette == 3)
{
// both
for (x=r1 ; x<=r2 ; x++)
{
if (clipbot[x] == -2)
clipbot[x] = ds->sprbottomclip[x];
if (cliptop[x] == -2)
cliptop[x] = ds->sprtopclip[x];
}
}
}
// all clipping has been performed, so draw the sprite
 
// check for unclipped columns
for (x = spr->x1 ; x<=spr->x2 ; x++)
{
if (clipbot[x] == -2)
clipbot[x] = viewheight;
 
if (cliptop[x] == -2)
cliptop[x] = -1;
}
mfloorclip = clipbot;
mceilingclip = cliptop;
R_DrawVisSprite (spr, spr->x1, spr->x2);
}
 
 
 
 
//
// R_DrawMasked
//
void R_DrawMasked (void)
{
vissprite_t* spr;
drawseg_t* ds;
R_SortVisSprites ();
 
if (vissprite_p > vissprites)
{
// draw all vissprites back to front
for (spr = vsprsortedhead.next ;
spr != &vsprsortedhead ;
spr=spr->next)
{
R_DrawSprite (spr);
}
}
// render any remaining masked mid textures
for (ds=ds_p-1 ; ds >= drawsegs ; ds--)
if (ds->maskedtexturecol)
R_RenderMaskedSegRange (ds, ds->x1, ds->x2);
// draw the psprites on top of everything
// but does not draw on side views
if (!viewangleoffset)
R_DrawPlayerSprites ();
}
 
 
 
/programs/games/doom/trunk/s_sound.c
45,6 → 45,9
 
//#include "qmus2mid.h"
 
 
#include "kolibri.h"
 
void WriteDebug(char *);
 
// Purpose?
112,10 → 115,10
// These are not used, but should be (menu).
// Maximum volume of a sound effect.
// Internal default is max out of 0-15.
int snd_SfxVolume = 80;
int snd_SfxVolume = 15;
 
// Maximum volume of music. Useless so far.
int snd_MusicVolume = 80;
int snd_MusicVolume = 15;
 
 
 
161,6 → 164,10
// Sets channels, SFX and music volume,
// allocates channel buffer, sets S_sfx lookup.
//
 
DWORD hMixBuff[4];
int mix_ptr;
 
void S_Init
( int sfxVolume,
int musicVolume )
169,7 → 176,13
 
printf("S_Init: default sfx volume %d\n", sfxVolume);
 
//I_CreateSound();
InitSound();
 
hMixBuff[0]= CreateBuffer(15);
hMixBuff[1]= CreateBuffer(15);
hMixBuff[2]= CreateBuffer(15);
hMixBuff[3]= CreateBuffer(15);
numChannels = NUM_CHANNELS;
 
// Whatever these did with DMX, these are rather dummies now.
/programs/games/doom/trunk/w_wad.c
151,6 → 151,8
reloadname = filename;
reloadlump = numlumps;
}
 
printf("open file %s\n\r",filename);
if ( (handle = fopen (filename,"rb")) == NULL)
{