-#endif
-#include "../z_zone.h"
-
-#include "../m_swap.h"
-#include "../i_system.h"
-#include "../i_sound.h"
-#include "../m_argv.h"
-#include "../m_misc.h"
-#include "../w_wad.h"
-#include "../screen.h" //vid.WndParent
-#include "../doomdef.h"
-#include "../doomstat.h"
-#include "../s_sound.h"
-
-#include "../d_main.h"
-
-#ifdef HW3SOUND
-#include "../hardware/hw3dsdrv.h"
-#include "../hardware/hw3sound.h"
-#include "hwsym_sdl.h"
-#endif
-
-#ifdef HAVE_LIBGME
-#include "gme/gme.h"
-#endif
-
-// 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.
-#if defined (_WIN32_WCE) || defined (DC) || defined (PSP) || defined(GP2X)
-#define NUM_CHANNELS MIX_CHANNELS
-#else
-#define NUM_CHANNELS MIX_CHANNELS*4
-#endif
-
-#define INDEXOFSFX(x) ((sfxinfo_t *)x - S_sfx)
-
-#if defined (_WIN32_WCE) || defined (DC) || defined (PSP)
-static Uint16 samplecount = 512; //Alam: .5KB samplecount at 11025hz is 46.439909297052154195011337868481ms of buffer
-#elif defined(GP2X)
-static Uint16 samplecount = 128;
-#else
-static Uint16 samplecount = 1024; //Alam: 1KB samplecount at 22050hz is 46.439909297052154195011337868481ms of buffer
-#endif
-
-typedef struct chan_struct
-{
- // The channel data pointers, start and end.
- Uint8 *data; //static unsigned char *channels[NUM_CHANNELS];
- Uint8 *end; //static unsigned char *channelsend[NUM_CHANNELS];
-
- // pitch
- Uint32 realstep; // The channel step amount...
- Uint32 step; //static UINT32 channelstep[NUM_CHANNELS];
- Uint32 stepremainder; //static UINT32 channelstepremainder[NUM_CHANNELS];
- Uint32 samplerate; // ... and a 0.16 bit remainder of last step.
-
- // Time/gametic that the channel started playing,
- // used to determine oldest, which automatically
- // has lowest priority.
- tic_t starttic; //static INT32 channelstart[NUM_CHANNELS];
-
- // The sound handle, determined on registration,
- // used to unregister/stop/modify,
- INT32 handle; //static INT32 channelhandles[NUM_CHANNELS];
-
- // SFX id of the playing sound effect.
- void *id; // Used to catch duplicates (like chainsaw).
- sfxenum_t sfxid; //static INT32 channelids[NUM_CHANNELS];
- INT32 vol; //the channel volume
- INT32 sep; //the channel pan
-
- // Hardware left and right channel volume lookup.
- Sint16* leftvol_lookup; //static INT32 *channelleftvol_lookup[NUM_CHANNELS];
- Sint16* rightvol_lookup; //static INT32 *channelrightvol_lookup[NUM_CHANNELS];
-} chan_t;
-
-static chan_t channels[NUM_CHANNELS];
-
-// Pitch to stepping lookup
-static INT32 steptable[256];
-
-// Volume lookups.
-static Sint16 vol_lookup[128 * 256];
-
-UINT8 sound_started = false;
-static SDL_mutex *Snd_Mutex = NULL;
-
-//SDL's Audio
-static SDL_AudioSpec audio;
-
-static SDL_bool musicStarted = SDL_FALSE;
-#ifdef HAVE_MIXER
-static SDL_mutex *Msc_Mutex = NULL;
-/* FIXME: Make this file instance-specific */
-#ifdef _arch_dreamcast
-#define MIDI_PATH "/ram"
-#elif defined(GP2X)
-#define MIDI_PATH "/mnt/sd/srb2kart-v2"
-#define MIDI_PATH2 "/tmp/mnt/sd/srb2kart-v2"
-#else
-#define MIDI_PATH srb2home
-#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)
-#define MIDI_PATH2 "/tmp"
-#endif
-#endif
-#define MIDI_TMPFILE "srb2kart-v2music"
-#define MIDI_TMPFILE2 "srb2kart-v2wav"
-static INT32 musicvol = 62;
-
-#if SDL_MIXER_VERSION_ATLEAST(1,2,2)
-#define MIXER_POS //Mix_FadeInMusicPos in 1.2.2+
-static void SDLCALL I_FinishMusic(void);
-static double loopstartDig = 0.0l;
-static SDL_bool loopingDig = SDL_FALSE;
-static SDL_bool canlooping = SDL_TRUE;
-#endif
-
-#if SDL_MIXER_VERSION_ATLEAST(1,2,7)
-#define USE_RWOPS // ok, USE_RWOPS is in here
-#if defined (DC) || defined (_WIN32_WCE) || defined (_XBOX) //|| defined(_WIN32) || defined(GP2X)
-#undef USE_RWOPS
-#endif
-#endif
-
-#if SDL_MIXER_VERSION_ATLEAST(1,2,10)
-//#define MIXER_INIT
-#endif
-
-#ifdef USE_RWOPS
-static void * Smidi[2] = { NULL, NULL };
-static SDL_bool canuseRW = SDL_TRUE;
-#endif
-static const char *fmidi[2] = { MIDI_TMPFILE, MIDI_TMPFILE2};
-
-static const INT32 MIDIfade = 500;
-static const INT32 Digfade = 0;
-
-static Mix_Music *music[2] = { NULL, NULL };
-#endif
-
-typedef struct srb2audio_s {
- void *userdata;
-#ifdef HAVE_LIBGME
- Music_Emu *gme_emu;
- UINT8 gme_pause;
- UINT8 gme_loop;
-#endif
-} srb2audio_t;
-
-static srb2audio_t localdata;
-
-static void Snd_LockAudio(void) //Alam: Lock audio data and uninstall audio callback
-{
- if (Snd_Mutex) SDL_LockMutex(Snd_Mutex);
- else if (nosound) return;
- else if (nomidimusic && nodigimusic
-#ifdef HW3SOUND
- && hws_mode == HWS_DEFAULT_MODE
-#endif
- ) SDL_LockAudio();
-#ifdef HAVE_MIXER
- else if (musicStarted) Mix_SetPostMix(NULL, NULL);
-#endif
-}
-
-static void Snd_UnlockAudio(void) //Alam: Unlock audio data and reinstall audio callback
-{
- if (Snd_Mutex) SDL_UnlockMutex(Snd_Mutex);
- else if (nosound) return;
- else if (nomidimusic && nodigimusic
-#ifdef HW3SOUND
- && hws_mode == HWS_DEFAULT_MODE
-#endif
- ) SDL_UnlockAudio();
-#ifdef HAVE_MIXER
- else if (musicStarted) Mix_SetPostMix(audio.callback, audio.userdata);
-#endif
-}
-
-static inline Uint16 Snd_LowerRate(Uint16 sr)
-{
- if (sr <= audio.freq) // already lowered rate?
- return sr; // good then
- for (;sr > audio.freq;) // not good?
- { // then let see...
- if (sr % 2) // can we div by half?
- return sr; // no, just use the currect rate
- sr /= 2; // we can? wonderful
- } // let start over again
- if (sr == audio.freq) // did we drop to the desired rate?
- return sr; // perfect! but if not
- return sr*2; // just keep it just above the output sample rate
-}
-
-#ifdef _MSC_VER
-#pragma warning(disable : 4200)
-#pragma pack(1)
-#endif
-
-typedef struct
-{
- Uint16 header; // 3?
- Uint16 samplerate; // 11025+
- Uint16 samples; // number of samples
- Uint16 dummy; // 0
- Uint8 data[0]; // data;
-} ATTRPACK dssfx_t;
-
-#ifdef _MSC_VER
-#pragma pack()
-#pragma warning(default : 4200)
-#endif
-
-//
-// This function loads the sound data from the WAD lump,
-// for single sound.
-//
-static void *getsfx(lumpnum_t sfxlump, size_t *len)
-{
- dssfx_t *sfx, *paddedsfx;
- Uint16 sr , csr;
- size_t size = *len;
- SDL_AudioCVT sfxcvt;
-
- sfx = (dssfx_t *)malloc(size);
- if (sfx) W_ReadLump(sfxlump, (void *)sfx);
- else return NULL;
- sr = SHORT(sfx->samplerate);
- csr = Snd_LowerRate(sr);
-
- if (sr > csr && SDL_BuildAudioCVT(&sfxcvt, AUDIO_U8, 1, sr, AUDIO_U8, 1, csr))
- {//Alam: Setup the AudioCVT for the SFX
-
- sfxcvt.len = (INT32)size-8; //Alam: Chop off the header
- sfxcvt.buf = malloc(sfxcvt.len * sfxcvt.len_mult); //Alam: make room
- if (sfxcvt.buf) M_Memcpy(sfxcvt.buf, &(sfx->data), sfxcvt.len); //Alam: copy the sfx sample
-
- if (sfxcvt.buf && SDL_ConvertAudio(&sfxcvt) == 0) //Alam: let convert it!
- {
- size = sfxcvt.len_cvt + 8;
- *len = sfxcvt.len_cvt;
-
- // Allocate from zone memory.
- paddedsfx = (dssfx_t *) Z_Malloc(size, PU_SOUND, NULL);
-
- // Now copy and pad.
- M_Memcpy(paddedsfx->data, sfxcvt.buf, sfxcvt.len_cvt);
- free(sfxcvt.buf);
- M_Memcpy(paddedsfx,sfx,8);
- paddedsfx->samplerate = SHORT(csr); // new freq
- }
- else //Alam: the convert failed, not needed or I couldn't malloc the buf
- {
- if (sfxcvt.buf) free(sfxcvt.buf);
- *len = size - 8;
-
- // Allocate from zone memory then copy and pad
- paddedsfx = (dssfx_t *)M_Memcpy(Z_Malloc(size, PU_SOUND, NULL), sfx, size);
- }
- }
- else
- {
- // Pads the sound effect out to the mixing buffer size.
- // The original realloc would interfere with zone memory.
- *len = size - 8;
-
- // Allocate from zone memory then copy and pad
- paddedsfx = (dssfx_t *)M_Memcpy(Z_Malloc(size, PU_SOUND, NULL), sfx, size);
- }
-
- // Remove the cached lump.
- free(sfx);
-
- // Return allocated padded data.
- return paddedsfx;
-}
-
-// used to (re)calculate channel params based on vol, sep, pitch
-static void I_SetChannelParams(chan_t *c, INT32 vol, INT32 sep, INT32 step)
-{
- INT32 leftvol;
- INT32 rightvol;
- c->vol = vol;
- c->sep = sep;
- c->step = c->realstep = step;
-
- if (step != steptable[128])
- c->step += (((c->samplerate<<16)/audio.freq)-65536);
- else if (c->samplerate != (unsigned)audio.freq)
- c->step = ((c->samplerate<<16)/audio.freq);
- // x^2 separation, that is, orientation/stereo.
- // range is: 0 (left) - 255 (right)
-
- // Volume arrives in range 0..255 and it must be in 0..cv_soundvolume...
- vol = (vol * cv_soundvolume.value) >> 7;
- // note: >> 6 would use almost the entire dynamical range, but
- // then there would be no "dynamical room" for other sounds :-/
-
- leftvol = vol - ((vol*sep*sep) >> 16); ///(256*256);
- sep = 255 - sep;
- rightvol = vol - ((vol*sep*sep) >> 16);
-
- // Sanity check, clamp volume.
- if (rightvol < 0)
- rightvol = 0;
- else if (rightvol > 127)
- rightvol = 127;
- if (leftvol < 0)
- leftvol = 0;
- else if (leftvol > 127)
- leftvol = 127;
-
- // Get the proper lookup table piece
- // for this volume level
- c->leftvol_lookup = &vol_lookup[leftvol*256];
- c->rightvol_lookup = &vol_lookup[rightvol*256];
-}
-
-static INT32 FindChannel(INT32 handle)
-{
- INT32 i;
-
- for (i = 0; i < NUM_CHANNELS; i++)
- if (channels[i].handle == handle)
- return i;
-
- // not found
- return -1;
-}
-
-//
-// 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 INT32 addsfx(sfxenum_t sfxid, INT32 volume, INT32 step, INT32 seperation)
-{
- static UINT16 handlenums = 0;
- INT32 i, slot, oldestnum = 0;
- tic_t oldest = gametic;
-
- // Play these sound effects only one at a time.
-#if 1
- if (
-#if 0
- sfxid == sfx_stnmov || sfxid == sfx_sawup || sfxid == sfx_sawidl || sfxid == sfx_sawful || sfxid == sfx_sawhit || sfxid == sfx_pistol
-#else
- ( sfx_litng1 <= sfxid && sfxid >= sfx_litng4 )
- || sfxid == sfx_trfire || sfxid == sfx_alarm || sfxid == sfx_spin
- || sfxid == sfx_athun1 || sfxid == sfx_athun2 || sfxid == sfx_rainin
-#endif
- )
- {
- // Loop all channels, check.
- for (i = 0; i < NUM_CHANNELS; i++)
- {
- // Active, and using the same SFX?
- if ((channels[i].end) && (channels[i].sfxid == sfxid))
- {
- // Reset.
- channels[i].end = NULL;
- // We are sure that iff,
- // there will only be one.
- break;
- }
- }
- }
-#endif
-
- // Loop all channels to find oldest SFX.
- for (i = 0; (i < NUM_CHANNELS) && (channels[i].end); i++)
- {
- if (channels[i].starttic < oldest)
- {
- oldestnum = i;
- oldest = channels[i].starttic;
- }
- }
-
- // 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;
-
- channels[slot].end = NULL;
- // Okay, in the less recent channel,
- // we will handle the new SFX.
- // Set pointer to raw data.
- channels[slot].data = (Uint8 *)S_sfx[sfxid].data;
- channels[slot].samplerate = (channels[slot].data[3]<<8)+channels[slot].data[2];
- channels[slot].data += 8; //Alam: offset of the sound header
-
- while (FindChannel(handlenums)!=-1)
- {
- handlenums++;
- // Reset current handle number, limited to 0..65535.
- if (handlenums == UINT16_MAX)
- handlenums = 0;
- }
-
- // Assign current handle number.
- // Preserved so sounds could be stopped.
- channels[slot].handle = handlenums;
-
- // Restart steper
- channels[slot].stepremainder = 0;
- // Should be gametic, I presume.
- channels[slot].starttic = gametic;
-
- I_SetChannelParams(&channels[slot], volume, seperation, step);
-
- // Preserve sound SFX id,
- // e.g. for avoiding duplicates of chainsaw.
- channels[slot].id = S_sfx[sfxid].data;
-
- channels[slot].sfxid = sfxid;
-
- // Set pointer to end of raw data.
- channels[slot].end = channels[slot].data + S_sfx[sfxid].length;
-
-
- // You tell me.
- return handlenums;
-}
-
-//
-// 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().
-//
-// Well... To keep compatibility with legacy doom, I have to call this in
-// I_InitSound since it is not called in S_Init... (emanne@absysteme.fr)
-
-static inline void I_SetChannels(void)
-{
- // Init internal lookups (raw data, mixing buffer, channels).
- // This function sets up internal lookups used during
- // the mixing process.
- INT32 i;
- INT32 j;
-
- INT32 *steptablemid = steptable + 128;
-
- if (nosound)
- return;
-
- // This table provides step widths for pitch parameters.
- for (i = -128; i < 128; i++)
- {
- const double po = pow((double)(2.0l), (double)(i / 64.0l));
- steptablemid[i] = (INT32)(po * 65536.0l);
- }
-
- // 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++)
- {
- //From PrDoom
- // proff - made this a little bit softer, because with
- // full volume the sound clipped badly
- vol_lookup[i * 256 + j] = (Sint16)((i * (j - 128) * 256) / 127);
- }
-}
-
-void I_SetSfxVolume(UINT8 volume)
-{
- INT32 i;
-
- (void)volume;
- //Snd_LockAudio();
-
- for (i = 0; i < NUM_CHANNELS; i++)
- if (channels[i].end) I_SetChannelParams(&channels[i], channels[i].vol, channels[i].sep, channels[i].realstep);
-
- //Snd_UnlockAudio();
-}
-
-void *I_GetSfx(sfxinfo_t *sfx)
-{
- if (sfx->lumpnum == LUMPERROR)
- sfx->lumpnum = S_GetSfxLumpNum(sfx);
-// else if (sfx->lumpnum != S_GetSfxLumpNum(sfx))
-// I_FreeSfx(sfx);
-
-#ifdef HW3SOUND
- if (hws_mode != HWS_DEFAULT_MODE)
- return HW3S_GetSfx(sfx);
-#endif
-
- if (sfx->data)
- return sfx->data; //Alam: I have it done!
-
- sfx->length = W_LumpLength(sfx->lumpnum);
-
- return getsfx(sfx->lumpnum, &sfx->length);
-
-}
-
-void I_FreeSfx(sfxinfo_t * sfx)
-{
-// if (sfx->lumpnum<0)
-// return;
-
-#ifdef HW3SOUND
- if (hws_mode != HWS_DEFAULT_MODE)
- {
- HW3S_FreeSfx(sfx);
- }
- else
-#endif
- {
- size_t i;
-
- for (i = 1; i < NUMSFX; i++)
- {
- // Alias? Example is the chaingun sound linked to pistol.
- if (S_sfx[i].data == sfx->data)
- {
- if (S_sfx+i != sfx) S_sfx[i].data = NULL;
- S_sfx[i].lumpnum = LUMPERROR;
- S_sfx[i].length = 0;
- }
- }
- //Snd_LockAudio(); //Alam: too much?
- // Loop all channels, check.
- for (i = 0; i < NUM_CHANNELS; i++)
- {
- // Active, and using the same SFX?
- if (channels[i].end && channels[i].id == sfx->data)
- {
- channels[i].end = NULL; // Reset.
- }
- }
- //Snd_UnlockAudio(); //Alam: too much?
- Z_Free(sfx->data);
- }
- sfx->data = NULL;
- sfx->lumpnum = LUMPERROR;
-}
-
-//
-// 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)
-// is set, but currently not used by mixing.
-//
-INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel)
-{
- (void)priority;
- (void)pitch;
- (void)channel;
-
- if (nosound)
- return 0;
-
- if (S_sfx[id].data == NULL) return -1;
-
- Snd_LockAudio();
- id = addsfx(id, vol, steptable[pitch], sep);
- Snd_UnlockAudio();
-
- return id; // Returns a handle (not used).
-}
-
-void I_StopSound(INT32 handle)
-{
- // You need the handle returned by StartSound.
- // Would be looping all channels,
- // tracking down the handle,
- // an setting the channel to zero.
- INT32 i;
-
- i = FindChannel(handle);
-
- if (i != -1)
- {
- //Snd_LockAudio(); //Alam: too much?
- channels[i].end = NULL;
- //Snd_UnlockAudio(); //Alam: too much?
- channels[i].handle = -1;
- channels[i].starttic = 0;
- }
-
-}
-
-boolean I_SoundIsPlaying(INT32 handle)
-{
- boolean isplaying = false;
- int chan = FindChannel(handle);
- if (chan != -1)
- isplaying = (channels[chan].end != NULL);
- return isplaying;
-}
-
-FUNCINLINE static ATTRINLINE void I_UpdateStream8S(Uint8 *stream, int len)
-{
- // Mix current sound data.
- // Data, from raw sound
- register Sint16 dr; // Right 8bit stream
- register Uint8 sample; // Center 8bit sfx
- register Sint16 dl; // Left 8bit stream
-
- // Pointers in audio stream
- Sint8 *rightout = (Sint8 *)stream; // currect right
- Sint8 *leftout = rightout + 1;// currect left
- const Uint8 step = 2; // Step in stream, left and right, thus two.
-
- INT32 chan; // Mixing channel index.
-
- // Determine end of the stream
- len /= 2; // not 8bit mono samples, 8bit stereo ones
-
- if (Snd_Mutex) SDL_LockMutex(Snd_Mutex);
-
- // Mix sounds into the mixing buffer.
- // Loop over len
- while (len--)
- {
- // Reset left/right value.
- dl = *leftout;
- dr = *rightout;
-
- // Love thy L2 cache - 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].end)
- {
-#if 1
- // Get the raw data from the channel.
- sample = channels[chan].data[0];
-#else
- // linear filtering from PrDoom
- sample = (((Uint32)channels[chan].data[0] *(0x10000 - channels[chan].stepremainder))
- + ((Uint32)channels[chan].data[1]) * (channels[chan].stepremainder))) >> 16;
-#endif
- // Add left and right part
- // for this channel (sound)
- // to the current data.
- // Adjust volume accordingly.
- dl = (Sint16)(dl+(channels[chan].leftvol_lookup[sample]>>8));
- dr = (Sint16)(dr+(channels[chan].rightvol_lookup[sample]>>8));
- // Increment stepage
- channels[chan].stepremainder += channels[chan].step;
- // Check whether we are done.
- if (channels[chan].data + (channels[chan].stepremainder >> 16) >= channels[chan].end)
- channels[chan].end = NULL;
- else
- {
- // step to next sample
- channels[chan].data += (channels[chan].stepremainder >> 16);
- // Limit to LSB???
- channels[chan].stepremainder &= 0xffff;
- }
- }
- }
-
- // Clamp to range. Left hardware channel.
- // Has been char instead of short.
-
- if (dl > 0x7f)
- *leftout = 0x7f;
- else if (dl < -0x80)
- *leftout = -0x80;
- else
- *leftout = (Sint8)dl;
-
- // Same for right hardware channel.
- if (dr > 0x7f)
- *rightout = 0x7f;
- else if (dr < -0x80)
- *rightout = -0x80;
- else
- *rightout = (Sint8)dr;
-
- // Increment current pointers in stream
- leftout += step;
- rightout += step;
-
- }
- if (Snd_Mutex) SDL_UnlockMutex(Snd_Mutex);
-}
-
-FUNCINLINE static ATTRINLINE void I_UpdateStream8M(Uint8 *stream, int len)
-{
- // Mix current sound data.
- // Data, from raw sound
- register Sint16 d; // Mono 8bit stream
- register Uint8 sample; // Center 8bit sfx
-
- // Pointers in audio stream
- Sint8 *monoout = (Sint8 *)stream; // currect mono
- const Uint8 step = 1; // Step in stream, left and right, thus two.
-
- INT32 chan; // Mixing channel index.
-
- // Determine end of the stream
- //len /= 1; // not 8bit mono samples, 8bit mono ones?
-
- if (Snd_Mutex) SDL_LockMutex(Snd_Mutex);
-
- // Mix sounds into the mixing buffer.
- // Loop over len
- while (len--)
- {
- // Reset left/right value.
- d = *monoout;
-
- // Love thy L2 cache - 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].end)
- {
-#if 1
- // Get the raw data from the channel.
- sample = channels[chan].data[0];
-#else
- // linear filtering from PrDoom
- sample = (((Uint32)channels[chan].data[0] *(0x10000 - channels[chan].stepremainder))
- + ((Uint32)channels[chan].data[1]) * (channels[chan].stepremainder))) >> 16;
-#endif
- // Add left and right part
- // for this channel (sound)
- // to the current data.
- // Adjust volume accordingly.
- d = (Sint16)(d+((channels[chan].leftvol_lookup[sample] + channels[chan].rightvol_lookup[sample])>>9));
- // Increment stepage
- channels[chan].stepremainder += channels[chan].step;
- // Check whether we are done.
- if (channels[chan].data + (channels[chan].stepremainder >> 16) >= channels[chan].end)
- channels[chan].end = NULL;
- else
- {
- // step to next sample
- channels[chan].data += (channels[chan].stepremainder >> 16);
- // Limit to LSB???
- channels[chan].stepremainder &= 0xffff;
- }
- }
- }
-
- // Clamp to range. Left hardware channel.
- // Has been char instead of short.
-
- if (d > 0x7f)
- *monoout = 0x7f;
- else if (d < -0x80)
- *monoout = -0x80;
- else
- *monoout = (Sint8)d;
-
- // Increment current pointers in stream
- monoout += step;
- }
- if (Snd_Mutex) SDL_UnlockMutex(Snd_Mutex);
-}
-
-FUNCINLINE static ATTRINLINE void I_UpdateStream16S(Uint8 *stream, int len)
-{
- // Mix current sound data.
- // Data, from raw sound
- register Sint32 dr; // Right 16bit stream
- register Uint8 sample; // Center 8bit sfx
- register Sint32 dl; // Left 16bit stream
-
- // Pointers in audio stream
- Sint16 *rightout = (Sint16 *)(void *)stream; // currect right
- Sint16 *leftout = rightout + 1;// currect left
- const Uint8 step = 2; // Step in stream, left and right, thus two.
-
- INT32 chan; // Mixing channel index.
-
- // Determine end of the stream
- len /= 4; // not 8bit mono samples, 16bit stereo ones
-
- if (Snd_Mutex) SDL_LockMutex(Snd_Mutex);
-
- // Mix sounds into the mixing buffer.
- // Loop over len
- while (len--)
- {
- // Reset left/right value.
- dl = *leftout;
- dr = *rightout;
-
- // Love thy L2 cache - 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].end)
- {
-#if 1
- // Get the raw data from the channel.
- sample = channels[chan].data[0];
-#else
- // linear filtering from PrDoom
- sample = (((Uint32)channels[chan].data[0] *(0x10000 - channels[chan].stepremainder))
- + ((Uint32)channels[chan].data[1]) * (channels[chan].stepremainder))) >> 16;
-#endif
- // Add left and right part
- // for this channel (sound)
- // to the current data.
- // Adjust volume accordingly.
- dl += channels[chan].leftvol_lookup[sample];
- dr += channels[chan].rightvol_lookup[sample];
- // Increment stepage
- channels[chan].stepremainder += channels[chan].step;
- // Check whether we are done.
- if (channels[chan].data + (channels[chan].stepremainder >> 16) >= channels[chan].end)
- channels[chan].end = NULL;
- else
- {
- // step to next sample
- channels[chan].data += (channels[chan].stepremainder >> 16);
- // Limit to LSB???
- channels[chan].stepremainder &= 0xffff;
- }
- }
- }
-
- // Clamp to range. Left hardware channel.
- // Has been char instead of short.
-
- if (dl > 0x7fff)
- *leftout = 0x7fff;
- else if (dl < -0x8000)
- *leftout = -0x8000;
- else
- *leftout = (Sint16)dl;
-
- // Same for right hardware channel.
- if (dr > 0x7fff)
- *rightout = 0x7fff;
- else if (dr < -0x8000)
- *rightout = -0x8000;
- else
- *rightout = (Sint16)dr;
-
- // Increment current pointers in stream
- leftout += step;
- rightout += step;
-
- }
- if (Snd_Mutex) SDL_UnlockMutex(Snd_Mutex);
-}
-
-FUNCINLINE static ATTRINLINE void I_UpdateStream16M(Uint8 *stream, int len)
-{
- // Mix current sound data.
- // Data, from raw sound
- register Sint32 d; // Mono 16bit stream
- register Uint8 sample; // Center 8bit sfx
-
- // Pointers in audio stream
- Sint16 *monoout = (Sint16 *)(void *)stream; // currect mono
- const Uint8 step = 1; // Step in stream, left and right, thus two.
-
- INT32 chan; // Mixing channel index.
-
- // Determine end of the stream
- len /= 2; // not 8bit mono samples, 16bit mono ones
-
- if (Snd_Mutex) SDL_LockMutex(Snd_Mutex);
-
- // Mix sounds into the mixing buffer.
- // Loop over len
- while (len--)
- {
- // Reset left/right value.
- d = *monoout;
-
- // Love thy L2 cache - 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].end)
- {
-#if 1
- // Get the raw data from the channel.
- sample = channels[chan].data[0];
-#else
- // linear filtering from PrDoom
- sample = (((Uint32)channels[chan].data[0] *(0x10000 - channels[chan].stepremainder))
- + ((Uint32)channels[chan].data[1]) * (channels[chan].stepremainder))) >> 16;
-#endif
- // Add left and right part
- // for this channel (sound)
- // to the current data.
- // Adjust volume accordingly.
- d += (channels[chan].leftvol_lookup[sample] + channels[chan].rightvol_lookup[sample])>>1;
- // Increment stepage
- channels[chan].stepremainder += channels[chan].step;
- // Check whether we are done.
- if (channels[chan].data + (channels[chan].stepremainder >> 16) >= channels[chan].end)
- channels[chan].end = NULL;
- else
- {
- // step to next sample
- channels[chan].data += (channels[chan].stepremainder >> 16);
- // Limit to LSB???
- channels[chan].stepremainder &= 0xffff;
- }
- }
- }
-
- // Clamp to range. Left hardware channel.
- // Has been char instead of short.
-
- if (d > 0x7fff)
- *monoout = 0x7fff;
- else if (d < -0x8000)
- *monoout = -0x8000;
- else
- *monoout = (Sint16)d;
-
- // Increment current pointers in stream
- monoout += step;
- }
- if (Snd_Mutex) SDL_UnlockMutex(Snd_Mutex);
-}
-
-#ifdef HAVE_LIBGME
-static void I_UpdateSteamGME(Music_Emu *emu, INT16 *stream, int len, UINT8 looping)
-{
- #define GME_BUFFER_LEN 44100*2048
- // Mix current sound data.
- // Data, from raw sound
- register Sint32 da;
-
- static short gme_buffer[GME_BUFFER_LEN]; // a large buffer for gme
- Sint16 *in = gme_buffer;
-
- do
- {
- int out = min(GME_BUFFER_LEN, len);
- if ( gme_play( emu, len, gme_buffer ) ) { } // ignore error
- len -= out;
- while (out--)
- {
- //Left
- da = *in;
- in++;
- da += *stream;
- stream++;
- //Right
- da = *in;
- in++;
- da += *stream;
- stream++;
- }
- if (gme_track_ended( emu ))
- {
- if (looping)
- gme_seek( emu, 0);
- else
- break;
- }
- } while ( len );
- #undef GME_BUFFER_LEN
-}
-#endif
-
-static void SDLCALL I_UpdateStream(void *userdata, Uint8 *stream, int len)
-{
- if (!sound_started || !userdata)
- return;
-
-#if SDL_VERSION_ATLEAST(1,3,0)
- if (musicStarted)
- memset(stream, 0x00, len); // only work in !AUDIO_U8, that needs 0x80
-#endif
-
- if ((audio.channels != 1 && audio.channels != 2) ||
- (audio.format != AUDIO_S8 && audio.format != AUDIO_S16SYS))
- ; // no function to encode this type of stream
- else if (audio.channels == 1 && audio.format == AUDIO_S8)
- I_UpdateStream8M(stream, len);
- else if (audio.channels == 2 && audio.format == AUDIO_S8)
- I_UpdateStream8S(stream, len);
- else if (audio.channels == 1 && audio.format == AUDIO_S16SYS)
- I_UpdateStream16M(stream, len);
- else if (audio.channels == 2 && audio.format == AUDIO_S16SYS)
- {
- I_UpdateStream16S(stream, len);
-#ifdef HAVE_LIBGME
- if (userdata)
- {
- srb2audio_t *sa_userdata = userdata;
- if (!sa_userdata->gme_pause)
- I_UpdateSteamGME(sa_userdata->gme_emu, (INT16 *)stream, len/4, sa_userdata->gme_loop);
- }
-#endif
-
- }
-}
-
-void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch)
-{
- // Would be using the handle to identify
- // on which channel the sound might be active,
- // and resetting the channel parameters.
-
- INT32 i = FindChannel(handle);
-
- if (i != -1 && channels[i].end)
- {
- //Snd_LockAudio(); //Alam: too much?
- I_SetChannelParams(&channels[i], vol, sep, steptable[pitch]);
- //Snd_UnlockAudio(); //Alam: too much?
- }
-
-}
-
-#ifdef HW3SOUND
-
-static void *soundso = NULL;
-
-static INT32 Init3DSDriver(const char *soName)
-{
- if (soName) soundso = hwOpen(soName);
-#if defined (_WIN32) && defined (_X86_) && !defined (STATIC3DS)
- HW3DS.pfnStartup = hwSym("Startup@8",soundso);
- HW3DS.pfnShutdown = hwSym("Shutdown@0",soundso);
- HW3DS.pfnAddSfx = hwSym("AddSfx@4",soundso);
- HW3DS.pfnAddSource = hwSym("AddSource@8",soundso);
- HW3DS.pfnStartSource = hwSym("StartSource@4",soundso);
- HW3DS.pfnStopSource = hwSym("StopSource@4",soundso);
- HW3DS.pfnGetHW3DSVersion = hwSym("GetHW3DSVersion@0",soundso);
- HW3DS.pfnBeginFrameUpdate = hwSym("BeginFrameUpdate@0",soundso);
- HW3DS.pfnEndFrameUpdate = hwSym("EndFrameUpdate@0",soundso);
- HW3DS.pfnIsPlaying = hwSym("IsPlaying@4",soundso);
- HW3DS.pfnUpdateListener = hwSym("UpdateListener@8",soundso);
- HW3DS.pfnUpdateSourceParms = hwSym("UpdateSourceParms@12",soundso);
- HW3DS.pfnSetCone = hwSym("SetCone@8",soundso);
- HW3DS.pfnSetGlobalSfxVolume = hwSym("SetGlobalSfxVolume@4",soundso);
- HW3DS.pfnUpdate3DSource = hwSym("Update3DSource@8",soundso);
- HW3DS.pfnReloadSource = hwSym("ReloadSource@8",soundso);
- HW3DS.pfnKillSource = hwSym("KillSource@4",soundso);
- HW3DS.pfnKillSfx = hwSym("KillSfx@4",soundso);
- HW3DS.pfnGetHW3DSTitle = hwSym("GetHW3DSTitle@8",soundso);
-#else
- HW3DS.pfnStartup = hwSym("Startup",soundso);
- HW3DS.pfnShutdown = hwSym("Shutdown",soundso);
- HW3DS.pfnAddSfx = hwSym("AddSfx",soundso);
- HW3DS.pfnAddSource = hwSym("AddSource",soundso);
- HW3DS.pfnStartSource = hwSym("StartSource",soundso);
- HW3DS.pfnStopSource = hwSym("StopSource",soundso);
- HW3DS.pfnGetHW3DSVersion = hwSym("GetHW3DSVersion",soundso);
- HW3DS.pfnBeginFrameUpdate = hwSym("BeginFrameUpdate",soundso);
- HW3DS.pfnEndFrameUpdate = hwSym("EndFrameUpdate",soundso);
- HW3DS.pfnIsPlaying = hwSym("IsPlaying",soundso);
- HW3DS.pfnUpdateListener = hwSym("UpdateListener",soundso);
- HW3DS.pfnUpdateSourceParms = hwSym("UpdateSourceParms",soundso);
- HW3DS.pfnSetCone = hwSym("SetCone",soundso);
- HW3DS.pfnSetGlobalSfxVolume = hwSym("SetGlobalSfxVolume",soundso);
- HW3DS.pfnUpdate3DSource = hwSym("Update3DSource",soundso);
- HW3DS.pfnReloadSource = hwSym("ReloadSource",soundso);
- HW3DS.pfnKillSource = hwSym("KillSource",soundso);
- HW3DS.pfnKillSfx = hwSym("KillSfx",soundso);
- HW3DS.pfnGetHW3DSTitle = hwSym("GetHW3DSTitle",soundso);
-#endif
-
-// if (HW3DS.pfnUpdateListener2 && HW3DS.pfnUpdateListener2 != soundso)
- return true;
-// else
-// return false;
-}
-#endif
-
-void I_ShutdownSound(void)
-{
- if (nosound || !sound_started)
- return;
-
- CONS_Printf("I_ShutdownSound: ");
-
-#ifdef HW3SOUND
- if (hws_mode != HWS_DEFAULT_MODE)
- {
- HW3S_Shutdown();
- hwClose(soundso);
- return;
- }
-#endif
-
- if (nomidimusic && nodigimusic)
- SDL_CloseAudio();
- CONS_Printf("%s", M_GetText("shut down\n"));
- sound_started = false;
- SDL_QuitSubSystem(SDL_INIT_AUDIO);
- if (Snd_Mutex)
- SDL_DestroyMutex(Snd_Mutex);
- Snd_Mutex = NULL;
-}
-
-void I_UpdateSound(void)
-{
-}
-
-void I_StartupSound(void)
-{
-#ifdef HW3SOUND
- const char *sdrv_name = NULL;
-#endif
-#ifndef HAVE_MIXER
- nomidimusic = nodigimusic = true;
-#endif
-#ifdef DC
- //nosound = true;
-#ifdef HAVE_MIXER
- nomidimusic = true;
- nodigimusic = true;
-#endif
-#endif
-
- memset(channels, 0, sizeof (channels)); //Alam: Clean it
-
- audio.format = AUDIO_S16SYS;
- audio.channels = 2;
- audio.callback = I_UpdateStream;
- audio.userdata = &localdata;
-
- if (dedicated)
- {
- nosound = nomidimusic = nodigimusic = true;
- return;
- }
-
- // Configure sound device
- CONS_Printf("I_StartupSound:\n");
-
- // Open the audio device
- if (M_CheckParm ("-freq") && M_IsNextParm())
- {
- audio.freq = atoi(M_GetNextParm());
- if (!audio.freq) audio.freq = cv_samplerate.value;
- audio.samples = (Uint16)((samplecount/2)*(INT32)(audio.freq/11025)); //Alam: to keep it around the same XX ms
- CONS_Printf (M_GetText(" requested frequency of %d hz\n"), audio.freq);
- }
- else
- {
- audio.samples = samplecount;
- audio.freq = cv_samplerate.value;
- }
-
- if (M_CheckParm ("-mono"))
- {
- audio.channels = 1;
- audio.samples /= 2;
- }
-
-#if defined (_PSP) && defined (HAVE_MIXER) // Bug in PSP's SDL_OpenAudio, can not open twice
- I_SetChannels();
- sound_started = true;
- Snd_Mutex = SDL_CreateMutex();
-#else
- if (nosound)
-#endif
- return;
-
-#ifdef HW3SOUND
-#ifdef STATIC3DS
- if (M_CheckParm("-3dsound") || M_CheckParm("-ds3d"))
- {
- hws_mode = HWS_OPENAL;
- }
-#elif defined (_WIN32)
- if (M_CheckParm("-ds3d"))
- {
- hws_mode = HWS_DS3D;
- sdrv_name = "s_ds3d.dll";
- }
- else if (M_CheckParm("-fmod3d"))
- {
- hws_mode = HWS_FMOD3D;
- sdrv_name = "s_fmod.dll";
- }
- else if (M_CheckParm("-openal"))
- {
- hws_mode = HWS_OPENAL;
- sdrv_name = "s_openal.dll";
- }
-#else
- if (M_CheckParm("-fmod3d"))
- {
- hws_mode = HWS_FMOD3D;
- sdrv_name = "./s_fmod.so";
- }
- else if (M_CheckParm("-openal"))
- {
- hws_mode = HWS_OPENAL;
- sdrv_name = "./s_openal.so";
- }
-#endif
- else if (M_CheckParm("-sounddriver") && M_IsNextParm())
- {
- hws_mode = HWS_OTHER;
- sdrv_name = M_GetNextParm();
- }
- if (hws_mode != HWS_DEFAULT_MODE)
- {
- if (Init3DSDriver(sdrv_name))
- {
- snddev_t snddev;
-
- //nosound = true;
- //I_AddExitFunc(I_ShutdownSound);
- snddev.bps = 16;
- snddev.sample_rate = audio.freq;
- snddev.numsfxs = NUMSFX;
-#if defined (_WIN32) && !defined (_XBOX)
- snddev.cooplevel = 0x00000002;
- snddev.hWnd = vid.WndParent;
-#endif
- if (HW3S_Init(I_Error, &snddev))
- {
- audio.userdata = NULL;
- CONS_Printf("%s", M_GetText(" Using 3D sound driver\n"));
- return;
- }
- CONS_Printf("%s", M_GetText(" Failed loading 3D sound driver\n"));
- // Falls back to default sound system
- HW3S_Shutdown();
- hwClose(soundso);
- }
- CONS_Printf("%s", M_GetText(" Failed loading 3D sound driver\n"));
- hws_mode = HWS_DEFAULT_MODE;
- }
-#endif
- if (!musicStarted && SDL_OpenAudio(&audio, &audio) < 0)
- {
- CONS_Printf("%s", M_GetText(" couldn't open audio with desired format\n"));
- nosound = true;
- return;
- }
- else
- {
- char ad[100];
- CONS_Printf(M_GetText(" Starting up with audio driver : %s\n"), SDL_AudioDriverName(ad, (int)sizeof ad));
- }
- samplecount = audio.samples;
- CV_SetValue(&cv_samplerate, audio.freq);
- CONS_Printf(M_GetText(" configured audio device with %d samples/slice at %ikhz(%dms buffer)\n"), samplecount, audio.freq/1000, (INT32) (((float)audio.samples * 1000.0f) / audio.freq));
- // Finished initialization.
- CONS_Printf("%s", M_GetText(" Sound module ready\n"));
- //[segabor]
- if (!musicStarted) SDL_PauseAudio(0);
- //Mix_Pause(0);
- I_SetChannels();
- sound_started = true;
- Snd_Mutex = SDL_CreateMutex();
-}
-
-//
-// MUSIC API.
-//
-
-void I_ShutdownMIDIMusic(void)
-{
- nomidimusic = false;
- if (nodigimusic) I_ShutdownMusic();
-}
-
-#ifdef HAVE_LIBGME
-static void I_ShutdownGMEMusic(void)
-{
- Snd_LockAudio();
- if (localdata.gme_emu)
- gme_delete(localdata.gme_emu);
- localdata.gme_emu = NULL;
- Snd_UnlockAudio();
-}
-#endif
-
-void I_ShutdownDigMusic(void)
-{
- nodigimusic = false;
- if (nomidimusic) I_ShutdownMusic();
-}
-
-#ifdef HAVE_MIXER
-static boolean LoadSong(void *data, size_t lumplength, size_t selectpos)
-{
- FILE *midfile;
- const char *tempname;
-#ifdef USE_RWOPS
- if (canuseRW)
- {
- SDL_RWops *SDLRW;
- void *olddata = Smidi[selectpos]; //quick shortcut to set
-
- Z_Free(olddata); //free old memory
- Smidi[selectpos] = NULL;
-
- if (!data)
- return olddata != NULL; //was there old data?
-
- SDLRW = SDL_RWFromConstMem(data, (int)lumplength); //new RWops from Z_zone
- if (!SDLRW) //ERROR while making RWops!
- {
- CONS_Printf(M_GetText("Couldn't load music lump: %s\n"), SDL_GetError());
- Z_Free(data);
- return false;
- }
-
- music[selectpos] = Mix_LoadMUS_RW(SDLRW); // new Mix_Chuck from RWops
- if (music[selectpos])
- Smidi[selectpos] = data; //all done
- else //ERROR while making Mix_Chuck
- {
- CONS_Printf(M_GetText("Couldn't load music data: %s\n"), Mix_GetError());
- Z_Free(data);
- SDL_RWclose(SDLRW);
- Smidi[selectpos] = NULL;
- }
- return true;
- }
-#endif
- tempname = va("%s/%s", MIDI_PATH, fmidi[selectpos]);
-
- if (!data)
- {
- if (FIL_FileExists(tempname))
- return unlink(tempname)+1;
-#ifdef MIDI_PATH2
- else if (FIL_FileExists(tempname = va("%s/%s", MIDI_PATH2, fmidi[selectpos])))
- return unlink(tempname)+1;
-#endif
- else
- return false;
- }
-
- midfile = fopen(tempname, "wb");
-
-#ifdef MIDI_PATH2
- if (!midfile)
- {
- tempname = va("%s/%s", MIDI_PATH2, fmidi[selectpos]);
- midfile = fopen(tempname, "wb");
- }
-#endif
-
- if (!midfile)
- {
- CONS_Printf(M_GetText("Couldn't open file %s to write music in\n"), tempname);
- Z_Free(data);
- return false;
- }
-
- if (fwrite(data, lumplength, 1, midfile) == 0)
- {
- CONS_Printf(M_GetText("Couldn't write music into file %s because %s\n"), tempname, M_FileError(midfile));
- Z_Free(data);
- fclose(midfile);
- return false;
- }
-
- fclose(midfile);
-
- Z_Free(data);
-
- music[selectpos] = Mix_LoadMUS(tempname);
- if (!music[selectpos]) //ERROR while making Mix_Chuck
- {
- CONS_Printf(M_GetText("Couldn't load music file %s: %s\n"), tempname, Mix_GetError());
- return false;
- }
- return true;
-}
-#endif
-
-
-void I_ShutdownMusic(void)
-{
-#ifdef HAVE_MIXER
- if ((nomidimusic && nodigimusic) || !musicStarted)
- return;
-
- CONS_Printf("%s", M_GetText("I_ShutdownMusic: "));
-
- I_UnRegisterSong(0);
- I_StopDigSong();
- Mix_CloseAudio();
-#ifdef MIX_INIT
- Mix_Quit();
-#endif
- CONS_Printf("%s", M_GetText("shut down\n"));
- musicStarted = SDL_FALSE;
- if (Msc_Mutex)
- SDL_DestroyMutex(Msc_Mutex);
- Msc_Mutex = NULL;
-#endif
-}
-
-void I_InitMIDIMusic(void)
-{
- if (nodigimusic) I_InitMusic();
-}
-
-void I_InitDigMusic(void)
-{
- if (nomidimusic) I_InitMusic();
-}
-
-void I_InitMusic(void)
-{
-#ifdef HAVE_MIXER
- char ad[100];
- SDL_version MIXcompiled;
- const SDL_version *MIXlinked;
-#ifdef MIXER_INIT
- const int mixstart = MIX_INIT_OGG;
- int mixflags;
-#endif
-#endif
-#ifdef HAVE_LIBGME
- I_AddExitFunc(I_ShutdownGMEMusic);
-#endif
-
- if ((nomidimusic && nodigimusic) || dedicated)
- return;
-
-#ifdef HAVE_MIXER
- MIX_VERSION(&MIXcompiled)
- MIXlinked = Mix_Linked_Version();
- I_OutputMsg("Compiled for SDL_mixer version: %d.%d.%d\n",
- MIXcompiled.major, MIXcompiled.minor, MIXcompiled.patch);
-#ifdef MIXER_POS
-#ifndef _WII
- if (MIXlinked->major == 1 && MIXlinked->minor == 2 && MIXlinked->patch < 7)
-#endif
- canlooping = SDL_FALSE;
-#endif
-#ifdef USE_RWOPS
- if (M_CheckParm("-noRW"))
- canuseRW = SDL_FALSE;
-#endif
- I_OutputMsg("Linked with SDL_mixer version: %d.%d.%d\n",
- MIXlinked->major, MIXlinked->minor, MIXlinked->patch);
-#if !(defined (DC) || defined (PSP) || defined(GP2X) || defined (WII))
- if (audio.freq < 44100 && !M_CheckParm ("-freq")) //I want atleast 44Khz
- {
- audio.samples = (Uint16)(audio.samples*(INT32)(44100/audio.freq));
- audio.freq = 44100; //Alam: to keep it around the same XX ms
- }
-#endif
-
- if (sound_started
-#ifdef HW3SOUND
- && hws_mode == HWS_DEFAULT_MODE
-#endif
- )
- {
- I_OutputMsg("Temp Shutdown of SDL Audio System");
- SDL_CloseAudio();
- I_OutputMsg(" Done\n");
- }
-
- CONS_Printf("%s", M_GetText("I_InitMusic:"));
-
-#ifdef MIXER_INIT
- mixflags = Mix_Init(mixstart);
- if ((mixstart & MIX_INIT_FLAC) != (mixflags & MIX_INIT_FLAC))
- {
- CONS_Printf("%s", M_GetText(" Unable to load FLAC support\n"));
- }
- if ((mixstart & MIX_INIT_MOD ) != (mixflags & MIX_INIT_MOD ))
- {
- CONS_Printf("%s", M_GetText(" Unable to load MOD support\n"));
- }
- if ((mixstart & MIX_INIT_MP3 ) != (mixflags & MIX_INIT_MP3 ))
- {
- CONS_Printf("%s", M_GetText(" Unable to load MP3 support\n"));
- }
- if ((mixstart & MIX_INIT_OGG ) != (mixflags & MIX_INIT_OGG ))
- {
- CONS_Printf("%s", M_GetText(" Unable to load OGG support\n"));
- }
-#endif
-
- if (Mix_OpenAudio(audio.freq, audio.format, audio.channels, audio.samples) < 0) //open_music(&audio)
- {
- CONS_Printf(M_GetText(" Unable to open music: %s\n"), Mix_GetError());
- nomidimusic = nodigimusic = true;
- if (sound_started
-#ifdef HW3SOUND
- && hws_mode == HWS_DEFAULT_MODE
-#endif
- )
- {
- if (SDL_OpenAudio(&audio, NULL) < 0) //retry
- {
- CONS_Printf("%s", M_GetText(" couldn't open audio with desired format\n"));
- nosound = true;
- sound_started = false;
- }
- else
- {
- CONS_Printf(M_GetText(" Starting with audio driver : %s\n"), SDL_AudioDriverName(ad, (int)sizeof ad));
- }
- }
- return;
- }
- else
- CONS_Printf(M_GetText(" Starting up with audio driver : %s with SDL_Mixer\n"), SDL_AudioDriverName(ad, (int)sizeof ad));
-
- samplecount = audio.samples;
- CV_SetValue(&cv_samplerate, audio.freq);
- if (sound_started
-#ifdef HW3SOUND
- && hws_mode == HWS_DEFAULT_MODE
-#endif
- )
- I_OutputMsg(" Reconfigured SDL Audio System");
- else I_OutputMsg(" Configured SDL_Mixer System");
- I_OutputMsg(" with %d samples/slice at %ikhz(%dms buffer)\n", samplecount, audio.freq/1000, (INT32) ((audio.samples * 1000.0f) / audio.freq));
- Mix_SetPostMix(audio.callback, audio.userdata); // after mixing music, add sound effects
- Mix_Resume(-1);
- CONS_Printf("%s", M_GetText("Music initialized\n"));
- musicStarted = SDL_TRUE;
- Msc_Mutex = SDL_CreateMutex();
-#endif
-}
-
-boolean I_PlaySong(INT32 handle, boolean looping)
-{
- (void)handle;
-#ifdef HAVE_MIXER
- if (nomidimusic || !musicStarted || !music[handle])
- return false;
-
-#ifdef MIXER_POS
- if (canlooping)
- Mix_HookMusicFinished(NULL);
-#endif
-
- if (Mix_FadeInMusic(music[handle], looping ? -1 : 0, MIDIfade) == -1)
- CONS_Printf(M_GetText("Couldn't play song because %s\n"), Mix_GetError());
- else
- {
- Mix_VolumeMusic(musicvol);
- return true;
- }
-#else
- (void)looping;
-#endif
- return false;
-}
-
-static void I_PauseGME(void)
-{
-#ifdef HAVE_LIBGME
- localdata.gme_pause = true;
-#endif
-}
-
-void I_PauseSong(INT32 handle)
-{
- (void)handle;
- I_PauseGME();
-#ifdef HAVE_MIXER
- if ((nomidimusic && nodigimusic) || !musicStarted)
- return;
-
- Mix_PauseMusic();
- //I_StopSong(handle);
-#endif
-}
-
-static void I_ResumeGME(void)
-{
-#ifdef HAVE_LIBGME
- localdata.gme_pause = false;
-#endif
-}
-
-void I_ResumeSong(INT32 handle)
-{
- (void)handle;
- I_ResumeGME();
-#ifdef HAVE_MIXER
- if ((nomidimusic && nodigimusic) || !musicStarted)
- return;
-
- Mix_VolumeMusic(musicvol);
- Mix_ResumeMusic();
- //I_PlaySong(handle, true);
-#endif
-}
-
-void I_StopSong(INT32 handle)
-{
- (void)handle;
-#ifdef HAVE_MIXER
- if (nomidimusic || !musicStarted)
- return;
- Mix_FadeOutMusic(MIDIfade);
-#endif
-}
-
-void I_UnRegisterSong(INT32 handle)
-{
-#ifdef HAVE_MIXER
-
- if (nomidimusic || !musicStarted)
- return;
-
- Mix_HaltMusic();
- while (Mix_PlayingMusic())
- ;
-
- if (music[handle])
- Mix_FreeMusic(music[handle]);
- music[handle] = NULL;
- LoadSong(NULL, 0, handle);
-#else
- (void)handle;
-#endif
-}
-
-INT32 I_RegisterSong(void *data, size_t len)
-{
-#ifdef HAVE_MIXER
- if (nomidimusic || !musicStarted)
- return false;
-
- if (!LoadSong(data, len, 0))
- return false;
-
- if (music[0])
- return true;
-
- CONS_Printf(M_GetText("Couldn't load MIDI: %s\n"), Mix_GetError());
-#else
- (void)len;
- (void)data;
-#endif
- return false;
-}
-
-void I_SetMIDIMusicVolume(UINT8 volume)
-{
-#ifdef HAVE_MIXER
- if ((nomidimusic && nodigimusic) || !musicStarted)
- return;
-
- if (Msc_Mutex) SDL_LockMutex(Msc_Mutex);
- musicvol = volume * 2;
- if (Msc_Mutex) SDL_UnlockMutex(Msc_Mutex);
- Mix_VolumeMusic(musicvol);
-#else
- (void)volume;
-#endif
-}
-
-#ifdef HAVE_LIBGME
-static void I_CleanupGME(void *userdata)
-{
- Z_Free(userdata);
-}
-#endif
-
-static boolean I_StartGMESong(const char *musicname, boolean looping)
-{
-#ifdef HAVE_LIBGME
- XBOXSTATIC char filename[9];
- void *data;
- lumpnum_t lumpnum;
- size_t lumplength;
- Music_Emu *emu;
- const char* gme_err;
-
- Snd_LockAudio();
- if (localdata.gme_emu)
- gme_delete(localdata.gme_emu);
- localdata.gme_emu = NULL;
- Snd_UnlockAudio();
-
- snprintf(filename, sizeof filename, "o_%s", musicname);
-
- lumpnum = W_CheckNumForName(filename);
-
- if (lumpnum == LUMPERROR)
- {
- return false; // No music found. Oh well!
- }
- else
- lumplength = W_LumpLength(lumpnum);
-
- data = W_CacheLumpNum(lumpnum, PU_MUSIC);
-
- gme_err = gme_open_data(data, (long)lumplength, &emu, audio.freq);
- if (gme_err != NULL) {
- //I_OutputMsg("I_StartGMESong: error %s\n",gme_err);
- return false;
- }
- gme_set_user_data(emu, data);
- gme_set_user_cleanup(emu, I_CleanupGME);
- gme_start_track(emu, 0);
- gme_set_fade(emu, Digfade);
-
- Snd_LockAudio();
- localdata.gme_emu = emu;
- localdata.gme_pause = false;
- localdata.gme_loop = (UINT8)looping;
- Snd_UnlockAudio();
-
- return true;
-#else
- (void)musicname;
- (void)looping;
-#endif
- return false;
-}
-
-boolean I_StartDigSong(const char *musicname, boolean looping)
-{
-#ifdef HAVE_MIXER
- XBOXSTATIC char filename[9];
- void *data;
- lumpnum_t lumpnum;
- size_t lumplength;
-#endif
-
- if(I_StartGMESong(musicname, looping))
- return true;
-
-#ifdef HAVE_MIXER
- if (nodigimusic)
- return false;
-
- snprintf(filename, sizeof filename, "o_%s", musicname);
-
- lumpnum = W_CheckNumForName(filename);
-
- I_StopDigSong();
-
- if (lumpnum == LUMPERROR)
- {
- // Alam_GBC: like in win32/win_snd.c: Graue 02-29-2004: don't worry about missing music, there might still be a MIDI
- //I_OutputMsg("Music lump %s not found!\n", filename);
- return false; // No music found. Oh well!
- }
- else
- lumplength = W_LumpLength(lumpnum);
-
- data = W_CacheLumpNum(lumpnum, PU_MUSIC);
-
- if (Msc_Mutex) SDL_LockMutex(Msc_Mutex);
-
-#ifdef MIXER_POS
- if (canlooping && (loopingDig = looping) == SDL_TRUE && strcmp(data, "OggS") == 0)
- looping = false; // Only on looping Ogg files, will we will do our own looping
-
- // Scan the Ogg Vorbis file for the COMMENT= field for a custom
- // loop point
- if (!looping && loopingDig)
- {
- size_t scan;
- const char *dataum = data;
- XBOXSTATIC char looplength[64];
- UINT32 loopstart = 0;
- UINT8 newcount = 0;
-
- Mix_HookMusicFinished(I_FinishMusic);
-
- for (scan = 0; scan < lumplength; scan++)
- {
- if (*dataum++ == 'C'){
- if (*dataum++ == 'O'){
- if (*dataum++ == 'M'){
- if (*dataum++ == 'M'){
- if (*dataum++ == 'E'){
- if (*dataum++ == 'N'){
- if (*dataum++ == 'T'){
- if (*dataum++ == '='){
- if (*dataum++ == 'L'){
- if (*dataum++ == 'O'){
- if (*dataum++ == 'O'){
- if (*dataum++ == 'P'){
- if (*dataum++ == 'P'){
- if (*dataum++ == 'O'){
- if (*dataum++ == 'I'){
- if (*dataum++ == 'N'){
- if (*dataum++ == 'T'){
- if (*dataum++ == '=')
- {
-
- while (*dataum != 1 && newcount != 63)
- looplength[newcount++] = *dataum++;
-
- looplength[newcount] = '\0';
-
- loopstart = atoi(looplength);
-
- }
- else
- dataum--;}
- else
- dataum--;}
- else
- dataum--;}
- else
- dataum--;}
- else
- dataum--;}
- else
- dataum--;}
- else
- dataum--;}
- else
- dataum--;}
- else
- dataum--;}
- else
- dataum--;}
- else
- dataum--;}
- else
- dataum--;}
- else
- dataum--;}
- else
- dataum--;}
- else
- dataum--;}
- else
- dataum--;}
- else
- dataum--;}
- }
-
- if (loopstart > 0)
- {
- loopstartDig = (double)((44.1l+loopstart) / 44100.0l); //8 PCM chucks off and PCM to secs
-//#ifdef GP2X//#ifdef PARANOIA
- //I_OutputMsg("I_StartDigSong: setting looping point to %ul PCMs(%f seconds)\n", loopstart, loopstartDig);
-//#endif
- }
- else
- {
- looping = true; // loopingDig true, but couldn't find start loop point
- }
- }
- else
- loopstartDig = 0.0l;
-#else
- if (looping && strcmp(data, "OggS") == 0)
- I_OutputMsg("I_StartDigSong: SRB2Kart was not compiled with looping music support(no Mix_FadeInMusicPos)\n");
-#endif
-
- if (!LoadSong(data, lumplength, 1))
- {
- if (Msc_Mutex) SDL_UnlockMutex(Msc_Mutex);
- return false;
- }
-
- // Note: LoadSong() frees the data. Let's make sure
- // we don't try to use the data again.
- data = NULL;
-
- if (Mix_FadeInMusic(music[1], looping ? -1 : 0, Digfade) == -1)
- {
- if (Msc_Mutex) SDL_UnlockMutex(Msc_Mutex);
- I_OutputMsg("I_StartDigSong: Couldn't play song %s because %s\n", musicname, Mix_GetError());
- return false;
- }
- Mix_VolumeMusic(musicvol);
-
- if (Msc_Mutex) SDL_UnlockMutex(Msc_Mutex);
- return true;
-#else
- (void)looping;
- (void)musicname;
- return false;
-#endif
-}
-
-static void I_StopGME(void)
-{
-#ifdef HAVE_LIBGME
- Snd_LockAudio();
- gme_seek(localdata.gme_emu, 0);
- Snd_UnlockAudio();
-#endif
-}
-
-void I_StopDigSong(void)
-{
- I_StopGME();
-#ifdef HAVE_MIXER
- if (nodigimusic)
- return;
-
-#ifdef MIXER_POS
- if (canlooping)
- Mix_HookMusicFinished(NULL);
-#endif
-
- Mix_HaltMusic();
- while (Mix_PlayingMusic())
- ;
-
- if (music[1])
- Mix_FreeMusic(music[1]);
- music[1] = NULL;
- LoadSong(NULL, 0, 1);
-#endif
-}
-
-void I_SetDigMusicVolume(UINT8 volume)
-{
- I_SetMIDIMusicVolume(volume);
-}
-
-boolean I_SetSongSpeed(float speed)
-{
-
- (void)speed;
- return false;
-}
-
-boolean I_SetSongTrack(int track)
-{
- (void)track;
- return false;
-}
-
-#ifdef MIXER_POS
-static void SDLCALL I_FinishMusic(void)
-{
- if (!music[1])
- return;
- else if (Msc_Mutex) SDL_LockMutex(Msc_Mutex);
-// I_OutputMsg("I_FinishMusic: Loopping song to %g seconds\n", loopstartDig);
-
- if (Mix_FadeInMusicPos(music[1], loopstartDig ? 0 : -1, Digfade, loopstartDig) == 0)
- Mix_VolumeMusic(musicvol);
- else
- I_OutputMsg("I_FinishMusic: Couldn't loop song because %s\n", Mix_GetError());
-
- if (Msc_Mutex) SDL_UnlockMutex(Msc_Mutex);
-}
-#endif
-#endif //HAVE_SDL
diff --git a/src/tmap.nas b/src/tmap.nas
deleted file mode 100644
index 69282d0b4..000000000
--- a/src/tmap.nas
+++ /dev/null
@@ -1,957 +0,0 @@
-;; SONIC ROBO BLAST 2
-;;-----------------------------------------------------------------------------
-;; Copyright (C) 1998-2000 by DooM Legacy Team.
-;; Copyright (C) 1999-2020 by Sonic Team Junior.
-;;
-;; This program is free software distributed under the
-;; terms of the GNU General Public License, version 2.
-;; See the 'LICENSE' file for more details.
-;;-----------------------------------------------------------------------------
-;; FILE:
-;; tmap.nas
-;; DESCRIPTION:
-;; Assembler optimised rendering code for software mode.
-;; Draw wall columns.
-
-
-[BITS 32]
-
-%define FRACBITS 16
-%define TRANSPARENTPIXEL 255
-
-%ifdef LINUX
-%macro cextern 1
-[extern %1]
-%endmacro
-
-%macro cglobal 1
-[global %1]
-%endmacro
-
-%else
-%macro cextern 1
-%define %1 _%1
-[extern %1]
-%endmacro
-
-%macro cglobal 1
-%define %1 _%1
-[global %1]
-%endmacro
-
-%endif
-
-
-; The viddef_s structure. We only need the width field.
-struc viddef_s
- resb 12
-.width: resb 4
- resb 44
-endstruc
-
-;; externs
-;; columns
-cextern dc_x
-cextern dc_yl
-cextern dc_yh
-cextern ylookup
-cextern columnofs
-cextern dc_source
-cextern dc_texturemid
-cextern dc_texheight
-cextern dc_iscale
-cextern dc_hires
-cextern centery
-cextern centeryfrac
-cextern dc_colormap
-cextern dc_transmap
-cextern colormaps
-cextern vid
-cextern topleft
-
-; DELME
-cextern R_DrawColumn_8
-
-; polygon edge rasterizer
-cextern prastertab
-
-[SECTION .data]
-
-;;.align 4
-loopcount dd 0
-pixelcount dd 0
-tystep dd 0
-
-[SECTION .text]
-
-;;----------------------------------------------------------------------
-;;
-;; R_DrawColumn : 8bpp column drawer
-;;
-;; New optimised version 10-01-1998 by D.Fabrice and P.Boris
-;; Revised by G. Dick July 2010 to support the intervening twelve years'
-;; worth of changes to the renderer. Since I only vaguely know what I'm
-;; doing, this is probably rather suboptimal. Help appreciated!
-;;
-;;----------------------------------------------------------------------
-;; fracstep, vid.width in memory
-;; eax = accumulator
-;; ebx = colormap
-;; ecx = count
-;; edx = heightmask
-;; esi = source
-;; edi = dest
-;; ebp = frac
-;;----------------------------------------------------------------------
-
-cglobal R_DrawColumn_8_ASM
-; align 16
-R_DrawColumn_8_ASM:
- push ebp ;; preserve caller's stack frame pointer
- push esi ;; preserve register variables
- push edi
- push ebx
-;;
-;; dest = ylookup[dc_yl] + columnofs[dc_x];
-;;
- mov ebp,[dc_yl]
- mov edi,[ylookup+ebp*4]
- mov ebx,[dc_x]
- add edi,[columnofs+ebx*4] ;; edi = dest
-;;
-;; pixelcount = yh - yl + 1
-;;
- mov ecx,[dc_yh]
- add ecx,1
- sub ecx,ebp ;; pixel count
- jle near .done ;; nothing to scale
-;;
-;; fracstep = dc_iscale; // But we just use [dc_iscale]
-;; frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep));
-;;
- mov eax,ebp ;; dc_yl
- shl eax,FRACBITS
- sub eax,[centeryfrac]
- imul dword [dc_iscale]
- shrd eax,edx,FRACBITS
- add eax,[dc_texturemid]
- mov ebp,eax ;; ebp = frac
-
- mov ebx,[dc_colormap]
-
- mov esi,[dc_source]
-;;
-;; if (dc_hires) frac = 0;
-;;
- test byte [dc_hires],0x01
- jz .texheightcheck
- xor ebp,ebp
-
-;;
-;; Check for power of two
-;;
-.texheightcheck:
- mov edx,[dc_texheight]
- sub edx,1 ;; edx = heightmask
- test edx,[dc_texheight]
- jnz .notpowertwo
-
- test ecx,0x01 ;; Test for odd no. pixels
- jnz .odd
-
-;;
-;; Texture height is a power of two, so we get modular arithmetic by
-;; masking
-;;
-.powertwo:
- mov eax,ebp ;; eax = frac
- sar eax,FRACBITS ;; Integer part
- and eax,edx ;; eax &= heightmask
- movzx eax,byte [esi + eax] ;; eax = texel
- add ebp,[dc_iscale] ;; frac += fracstep
- movzx eax,byte [ebx+eax] ;; Map through colormap
- mov [edi],al ;; Write pixel
- ;; dest += vid.width
- add edi,[vid + viddef_s.width]
-
-.odd:
- mov eax,ebp ;; eax = frac
- sar eax,FRACBITS ;; Integer part
- and eax,edx ;; eax &= heightmask
- movzx eax,byte [esi + eax] ;; eax = texel
- add ebp,[dc_iscale] ;; frac += fracstep
- movzx eax,byte [ebx+eax] ;; Map through colormap
- mov [edi],al ;; Write pixel
- ;; dest += vid.width
- add edi,[vid + viddef_s.width]
-
-
- sub ecx,2 ;; count -= 2
- jg .powertwo
-
- jmp .done
-
-.notpowertwo:
- add edx,1
- shl edx,FRACBITS
- test ebp,ebp
- jns .notpowtwoloop
-
-.makefracpos:
- add ebp,edx ;; frac is negative; make it positive
- js .makefracpos
-
-.notpowtwoloop:
- cmp ebp,edx ;; Reduce mod height
- jl .writenonpowtwo
- sub ebp,edx
- jmp .notpowtwoloop
-
-.writenonpowtwo:
- mov eax,ebp ;; eax = frac
- sar eax,FRACBITS ;; Integer part.
- mov bl,[esi + eax] ;; ebx = colormap + texel
- add ebp,[dc_iscale] ;; frac += fracstep
- movzx eax,byte [ebx] ;; Map through colormap
- mov [edi],al ;; Write pixel
- ;; dest += vid.width
- add edi,[vid + viddef_s.width]
-
- sub ecx,1
- jnz .notpowtwoloop
-
-;;
-
-.done:
- pop ebx ;; restore register variables
- pop edi
- pop esi
- pop ebp ;; restore caller's stack frame pointer
- ret
-
-
-;;----------------------------------------------------------------------
-;;
-;; R_Draw2sMultiPatchColumn : Like R_DrawColumn, but omits transparent
-;; pixels.
-;;
-;; New optimised version 10-01-1998 by D.Fabrice and P.Boris
-;; Revised by G. Dick July 2010 to support the intervening twelve years'
-;; worth of changes to the renderer. Since I only vaguely know what I'm
-;; doing, this is probably rather suboptimal. Help appreciated!
-;;
-;;----------------------------------------------------------------------
-;; fracstep, vid.width in memory
-;; eax = accumulator
-;; ebx = colormap
-;; ecx = count
-;; edx = heightmask
-;; esi = source
-;; edi = dest
-;; ebp = frac
-;;----------------------------------------------------------------------
-
-cglobal R_Draw2sMultiPatchColumn_8_ASM
-; align 16
-R_Draw2sMultiPatchColumn_8_ASM:
- push ebp ;; preserve caller's stack frame pointer
- push esi ;; preserve register variables
- push edi
- push ebx
-;;
-;; dest = ylookup[dc_yl] + columnofs[dc_x];
-;;
- mov ebp,[dc_yl]
- mov edi,[ylookup+ebp*4]
- mov ebx,[dc_x]
- add edi,[columnofs+ebx*4] ;; edi = dest
-;;
-;; pixelcount = yh - yl + 1
-;;
- mov ecx,[dc_yh]
- add ecx,1
- sub ecx,ebp ;; pixel count
- jle near .done ;; nothing to scale
-;;
-;; fracstep = dc_iscale; // But we just use [dc_iscale]
-;; frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep));
-;;
- mov eax,ebp ;; dc_yl
- shl eax,FRACBITS
- sub eax,[centeryfrac]
- imul dword [dc_iscale]
- shrd eax,edx,FRACBITS
- add eax,[dc_texturemid]
- mov ebp,eax ;; ebp = frac
-
- mov ebx,[dc_colormap]
-
- mov esi,[dc_source]
-;;
-;; if (dc_hires) frac = 0;
-;;
- test byte [dc_hires],0x01
- jz .texheightcheck
- xor ebp,ebp
-
-;;
-;; Check for power of two
-;;
-.texheightcheck:
- mov edx,[dc_texheight]
- sub edx,1 ;; edx = heightmask
- test edx,[dc_texheight]
- jnz .notpowertwo
-
- test ecx,0x01 ;; Test for odd no. pixels
- jnz .odd
-
-;;
-;; Texture height is a power of two, so we get modular arithmetic by
-;; masking
-;;
-.powertwo:
- mov eax,ebp ;; eax = frac
- sar eax,FRACBITS ;; Integer part
- and eax,edx ;; eax &= heightmask
- movzx eax,byte [esi + eax] ;; eax = texel
- add ebp,[dc_iscale] ;; frac += fracstep
- cmp al,TRANSPARENTPIXEL ;; Is pixel transparent?
- je .nextpowtwoeven ;; If so, advance.
- movzx eax,byte [ebx+eax] ;; Map through colormap
- mov [edi],al ;; Write pixel
-.nextpowtwoeven:
- ;; dest += vid.width
- add edi,[vid + viddef_s.width]
-
-.odd:
- mov eax,ebp ;; eax = frac
- sar eax,FRACBITS ;; Integer part
- and eax,edx ;; eax &= heightmask
- movzx eax,byte [esi + eax] ;; eax = texel
- add ebp,[dc_iscale] ;; frac += fracstep
- cmp al,TRANSPARENTPIXEL ;; Is pixel transparent?
- je .nextpowtwoodd ;; If so, advance.
- movzx eax,byte [ebx+eax] ;; Map through colormap
- mov [edi],al ;; Write pixel
-.nextpowtwoodd:
- ;; dest += vid.width
- add edi,[vid + viddef_s.width]
-
-
- sub ecx,2 ;; count -= 2
- jg .powertwo
-
- jmp .done
-
-.notpowertwo:
- add edx,1
- shl edx,FRACBITS
- test ebp,ebp
- jns .notpowtwoloop
-
-.makefracpos:
- add ebp,edx ;; frac is negative; make it positive
- js .makefracpos
-
-.notpowtwoloop:
- cmp ebp,edx ;; Reduce mod height
- jl .writenonpowtwo
- sub ebp,edx
- jmp .notpowtwoloop
-
-.writenonpowtwo:
- mov eax,ebp ;; eax = frac
- sar eax,FRACBITS ;; Integer part.
- mov bl,[esi + eax] ;; ebx = colormap + texel
- add ebp,[dc_iscale] ;; frac += fracstep
- cmp bl,TRANSPARENTPIXEL ;; Is pixel transparent?
- je .nextnonpowtwo ;; If so, advance.
- movzx eax,byte [ebx] ;; Map through colormap
- mov [edi],al ;; Write pixel
-.nextnonpowtwo:
- ;; dest += vid.width
- add edi,[vid + viddef_s.width]
-
- sub ecx,1
- jnz .notpowtwoloop
-
-;;
-
-.done:
- pop ebx ;; restore register variables
- pop edi
- pop esi
- pop ebp ;; restore caller's stack frame pointer
- ret
-
-;;----------------------------------------------------------------------
-;; R_DrawTranslucentColumnA_8
-;;
-;; Vertical column texture drawer, with transparency. Replaces Doom2's
-;; 'fuzz' effect, which was not so beautiful.
-;; Transparency is always impressive in some way, don't know why...
-;;----------------------------------------------------------------------
-
-cglobal R_DrawTranslucentColumn_8_ASM
-R_DrawTranslucentColumn_8_ASM:
- push ebp ;; preserve caller's stack frame pointer
- push esi ;; preserve register variables
- push edi
- push ebx
-;;
-;; dest = ylookup[dc_yl] + columnofs[dc_x];
-;;
- mov ebp,[dc_yl]
- mov ebx,ebp
- mov edi,[ylookup+ebx*4]
- mov ebx,[dc_x]
- add edi,[columnofs+ebx*4] ;; edi = dest
-;;
-;; pixelcount = yh - yl + 1
-;;
- mov eax,[dc_yh]
- inc eax
- sub eax,ebp ;; pixel count
- mov [pixelcount],eax ;; save for final pixel
- jle near vtdone ;; nothing to scale
-;;
-;; frac = dc_texturemid - (centery-dc_yl)*fracstep;
-;;
- mov ecx,[dc_iscale] ;; fracstep
- mov eax,[centery]
- sub eax,ebp
- imul eax,ecx
- mov edx,[dc_texturemid]
- sub edx,eax
- mov ebx,edx
-
- shr ebx,16 ;; frac int.
- and ebx,0x7f
- shl edx,16 ;; y frac up
-
- mov ebp,ecx
- shl ebp,16 ;; fracstep f. up
- shr ecx,16 ;; fracstep i. ->cl
- and cl,0x7f
- push cx
- mov ecx,edx
- pop cx
- mov edx,[dc_colormap]
- mov esi,[dc_source]
-;;
-;; lets rock :) !
-;;
- mov eax,[pixelcount]
- shr eax,0x2
- test byte [pixelcount],0x3
- mov ch,al ;; quad count
- mov eax,[dc_transmap]
- je vt4quadloop
-;;
-;; do un-even pixel
-;;
- test byte [pixelcount],0x1
- je trf2
-
- mov ah,[esi+ebx] ;; fetch texel : colormap number
- add ecx,ebp
- adc bl,cl
- mov al,[edi] ;; fetch dest : index into colormap
- and bl,0x7f
- mov dl,[eax]
- mov dl,[edx]
- mov [edi],dl
-pf: add edi,0x12345678
-;;
-;; do two non-quad-aligned pixels
-;;
-trf2: test byte [pixelcount],0x2
- je trf3
-
- mov ah,[esi+ebx] ;; fetch texel : colormap number
- add ecx,ebp
- adc bl,cl
- mov al,[edi] ;; fetch dest : index into colormap
- and bl,0x7f
- mov dl,[eax]
- mov dl,[edx]
- mov [edi],dl
-pg: add edi,0x12345678
-
- mov ah,[esi+ebx] ;; fetch texel : colormap number
- add ecx,ebp
- adc bl,cl
- mov al,[edi] ;; fetch dest : index into colormap
- and bl,0x7f
- mov dl,[eax]
- mov dl,[edx]
- mov [edi],dl
-ph: add edi,0x12345678
-;;
-;; test if there was at least 4 pixels
-;;
-trf3: test ch,0xff ;; test quad count
- je near vtdone
-
-;;
-;; ebp : ystep frac. upper 24 bits
-;; edx : y frac. upper 24 bits
-;; ebx : y i. lower 7 bits, masked for index
-;; ecx : ch = counter, cl = y step i.
-;; eax : colormap aligned 256
-;; esi : source texture column
-;; edi : dest screen
-;;
-vt4quadloop:
- mov ah,[esi+ebx] ;; fetch texel : colormap number
- mov [tystep],ebp
-pi: add edi,0x12345678
- mov al,[edi] ;; fetch dest : index into colormap
-pj: sub edi,0x12345678
- mov ebp,edi
-pk: sub edi,0x12345678
- jmp short inloop
-align 4
-vtquadloop:
- add ecx,[tystep]
- adc bl,cl
-q1: add ebp,0x23456789
- and bl,0x7f
- mov dl,[eax]
- mov ah,[esi+ebx] ;; fetch texel : colormap number
- mov dl,[edx]
- mov [edi],dl
- mov al,[ebp] ;; fetch dest : index into colormap
-inloop:
- add ecx,[tystep]
- adc bl,cl
-q2: add edi,0x23456789
- and bl,0x7f
- mov dl,[eax]
- mov ah,[esi+ebx] ;; fetch texel : colormap number
- mov dl,[edx]
- mov [ebp+0x0],dl
- mov al,[edi] ;; fetch dest : index into colormap
-
- add ecx,[tystep]
- adc bl,cl
-q3: add ebp,0x23456789
- and bl,0x7f
- mov dl,[eax]
- mov ah,[esi+ebx] ;; fetch texel : colormap number
- mov dl,[edx]
- mov [edi],dl
- mov al,[ebp] ;; fetch dest : index into colormap
-
- add ecx,[tystep]
- adc bl,cl
-q4: add edi,0x23456789
- and bl,0x7f
- mov dl,[eax]
- mov ah,[esi+ebx] ;; fetch texel : colormap number
- mov dl,[edx]
- mov [ebp],dl
- mov al,[edi] ;; fetch dest : index into colormap
-
- dec ch
- jne vtquadloop
-vtdone:
- pop ebx
- pop edi
- pop esi
- pop ebp
- ret
-
-;;----------------------------------------------------------------------
-;; R_DrawShadeColumn
-;;
-;; for smoke..etc.. test.
-;;----------------------------------------------------------------------
-cglobal R_DrawShadeColumn_8_ASM
-R_DrawShadeColumn_8_ASM:
- push ebp ;; preserve caller's stack frame pointer
- push esi ;; preserve register variables
- push edi
- push ebx
-
-;;
-;; dest = ylookup[dc_yl] + columnofs[dc_x];
-;;
- mov ebp,[dc_yl]
- mov ebx,ebp
- mov edi,[ylookup+ebx*4]
- mov ebx,[dc_x]
- add edi,[columnofs+ebx*4] ;; edi = dest
-;;
-;; pixelcount = yh - yl + 1
-;;
- mov eax,[dc_yh]
- inc eax
- sub eax,ebp ;; pixel count
- mov [pixelcount],eax ;; save for final pixel
- jle near shdone ;; nothing to scale
-;;
-;; frac = dc_texturemid - (centery-dc_yl)*fracstep;
-;;
- mov ecx,[dc_iscale] ;; fracstep
- mov eax,[centery]
- sub eax,ebp
- imul eax,ecx
- mov edx,[dc_texturemid]
- sub edx,eax
- mov ebx,edx
- shr ebx,16 ;; frac int.
- and ebx,byte +0x7f
- shl edx,16 ;; y frac up
-
- mov ebp,ecx
- shl ebp,16 ;; fracstep f. up
- shr ecx,16 ;; fracstep i. ->cl
- and cl,0x7f
-
- mov esi,[dc_source]
-;;
-;; lets rock :) !
-;;
- mov eax,[pixelcount]
- mov dh,al
- shr eax,2
- mov ch,al ;; quad count
- mov eax,[colormaps]
- test dh,3
- je sh4quadloop
-;;
-;; do un-even pixel
-;;
- test dh,0x1
- je shf2
-
- mov ah,[esi+ebx] ;; fetch texel : colormap number
- add edx,ebp
- adc bl,cl
- mov al,[edi] ;; fetch dest : index into colormap
- and bl,0x7f
- mov dl,[eax]
- mov [edi],dl
-pl: add edi,0x12345678
-;;
-;; do two non-quad-aligned pixels
-;;
-shf2:
- test dh,0x2
- je shf3
-
- mov ah,[esi+ebx] ;; fetch texel : colormap number
- add edx,ebp
- adc bl,cl
- mov al,[edi] ;; fetch dest : index into colormap
- and bl,0x7f
- mov dl,[eax]
- mov [edi],dl
-pm: add edi,0x12345678
-
- mov ah,[esi+ebx] ;; fetch texel : colormap number
- add edx,ebp
- adc bl,cl
- mov al,[edi] ;; fetch dest : index into colormap
- and bl,0x7f
- mov dl,[eax]
- mov [edi],dl
-pn: add edi,0x12345678
-;;
-;; test if there was at least 4 pixels
-;;
-shf3:
- test ch,0xff ;; test quad count
- je near shdone
-
-;;
-;; ebp : ystep frac. upper 24 bits
-;; edx : y frac. upper 24 bits
-;; ebx : y i. lower 7 bits, masked for index
-;; ecx : ch = counter, cl = y step i.
-;; eax : colormap aligned 256
-;; esi : source texture column
-;; edi : dest screen
-;;
-sh4quadloop:
- mov dh,0x7f ;; prep mask
- mov ah,[esi+ebx] ;; fetch texel : colormap number
- mov [tystep],ebp
-po: add edi,0x12345678
- mov al,[edi] ;; fetch dest : index into colormap
-pp: sub edi,0x12345678
- mov ebp,edi
-pq: sub edi,0x12345678
- jmp short shinloop
-
-align 4
-shquadloop:
- add edx,[tystep]
- adc bl,cl
- and bl,dh
-q5: add ebp,0x12345678
- mov dl,[eax]
- mov ah,[esi+ebx] ;; fetch texel : colormap number
- mov [edi],dl
- mov al,[ebp] ;; fetch dest : index into colormap
-shinloop:
- add edx,[tystep]
- adc bl,cl
- and bl,dh
-q6: add edi,0x12345678
- mov dl,[eax]
- mov ah,[esi+ebx] ;; fetch texel : colormap number
- mov [ebp],dl
- mov al,[edi] ;; fetch dest : index into colormap
-
- add edx,[tystep]
- adc bl,cl
- and bl,dh
-q7: add ebp,0x12345678
- mov dl,[eax]
- mov ah,[esi+ebx] ;; fetch texel : colormap number
- mov [edi],dl
- mov al,[ebp] ;; fetch dest : index into colormap
-
- add edx,[tystep]
- adc bl,cl
- and bl,dh
-q8: add edi,0x12345678
- mov dl,[eax]
- mov ah,[esi+ebx] ;; fetch texel : colormap number
- mov [ebp],dl
- mov al,[edi] ;; fetch dest : index into colormap
-
- dec ch
- jne shquadloop
-
-shdone:
- pop ebx ;; restore register variables
- pop edi
- pop esi
- pop ebp ;; restore caller's stack frame pointer
- ret
-
-
-;; ========================================================================
-;; Rasterization of the segments of a LINEAR polygne textur of manire.
-;; It is thus a question of interpolating coordinate them at the edges of texture in
-;; the time that the X-coordinates minx/maxx for each line.
-;; the argument ' dir' indicates which edges of texture are Interpol?:
-;; 0: segments associs at edge TOP? and BOTTOM? (constant TY)
-;; 1: segments associs at the LEFT and RIGHT edge (constant TX)
-;; ========================================================================
-;;
-;; void rasterize_segment_tex( LONG x1, LONG y1, LONG x2, LONG y2, LONG tv1, LONG tv2, LONG tc, LONG dir );
-;; ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 ARG8
-;;
-;; Pour dir = 0, (tv1,tv2) = (tX1,tX2), tc = tY, en effet TY est constant.
-;;
-;; Pour dir = 1, (tv1,tv2) = (tY1,tY2), tc = tX, en effet TX est constant.
-;;
-;;
-;; Uses: extern struct rastery *_rastertab;
-;;
-
-MINX EQU 0
-MAXX EQU 4
-TX1 EQU 8
-TY1 EQU 12
-TX2 EQU 16
-TY2 EQU 20
-RASTERY_SIZEOF EQU 24
-
-cglobal rasterize_segment_tex_asm
-rasterize_segment_tex_asm:
- push ebp
- mov ebp,esp
-
- sub esp,byte +0x8 ;; allocate the local variables
-
- push ebx
- push esi
- push edi
- o16 mov ax,es
- push eax
-
-;; #define DX [ebp-4]
-;; #define TD [ebp-8]
-
- mov eax,[ebp+0xc] ;; y1
- mov ebx,[ebp+0x14] ;; y2
- cmp ebx,eax
- je near .L_finished ;; special (y1==y2) segment horizontal, exit!
-
- jg near .L_rasterize_right
-
-;;rasterize_left: ;; one rasterize a segment LEFT of the polygne
-
- mov ecx,eax
- sub ecx,ebx
- inc ecx ;; y1-y2+1
-
- mov eax,RASTERY_SIZEOF
- mul ebx ;; * y2
- mov esi,[prastertab]
- add esi,eax ;; point into rastertab[y2]
-
- mov eax,[ebp+0x8] ;; ARG1
- sub eax,[ebp+0x10] ;; ARG3
- shl eax,0x10 ;; ((x1-x2)<cl
- andb $0x7f,%cl
-
- movl C(dc_source),%esi
-
-//
-// lets rock :) !
-//
- movl C(pixelcount),%eax
- movb %al,%dh
- shrl $2,%eax
- movb %al,%ch // quad count
- movl C(dc_colormap),%eax
- testb $3,%dh
- jz v4quadloop
-
-//
-// do un-even pixel
-//
- testb $1,%dh
- jz 2f
-
- movb (%esi,%ebx),%al // prep un-even loops
- addl %ebp,%edx // ypos f += ystep f
- adcb %cl,%bl // ypos i += ystep i
- movb (%eax),%dl // colormap texel
- andb $0x7f,%bl // mask 0-127 texture index
- movb %dl,(%edi) // output pixel
- addl C(vidwidth),%edi
-
-//
-// do two non-quad-aligned pixels
-//
-2:
- testb $2,%dh
- jz 3f
-
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx // ypos f += ystep f
- adcb %cl,%bl // ypos i += ystep i
- movb (%eax),%dl // colormap texel
- andb $0x7f,%bl // mask 0-127 texture index
- movb %dl,(%edi) // output pixel
-
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx // ypos f += ystep f
- adcb %cl,%bl // ypos i += ystep i
- movb (%eax),%dl // colormap texel
- andb $0x7f,%bl // mask 0-127 texture index
- addl C(vidwidth),%edi
- movb %dl,(%edi) // output pixel
-
- addl C(vidwidth),%edi
-
-//
-// test if there was at least 4 pixels
-//
-3:
- testb $0xFF,%ch // test quad count
- jz vdone
-
-//
-// ebp : ystep frac. upper 24 bits
-// edx : y frac. upper 24 bits
-// ebx : y i. lower 7 bits, masked for index
-// ecx : ch = counter, cl = y step i.
-// eax : colormap aligned 256
-// esi : source texture column
-// edi : dest screen
-//
-v4quadloop:
- movb $0x7f,%dh // prep mask
-// .align 4
-vquadloop:
- movb (%esi,%ebx),%al // prep loop
- addl %ebp,%edx // ypos f += ystep f
- adcb %cl,%bl // ypos i += ystep i
- movb (%eax),%dl // colormap texel
- movb %dl,(%edi) // output pixel
- andb $0x7f,%bl // mask 0-127 texture index
-
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx
- adcb %cl,%bl
- movb (%eax),%dl
-p1: movb %dl,0x12345678(%edi)
- andb $0x7f,%bl
-
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx
- adcb %cl,%bl
- movb (%eax),%dl
-p2: movb %dl,2*0x12345678(%edi)
- andb $0x7f,%bl
-
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx
- adcb %cl,%bl
- movb (%eax),%dl
-p3: movb %dl,3*0x12345678(%edi)
- andb $0x7f,%bl
-
-p4: addl $4*0x12345678,%edi
-
- decb %ch
- jnz vquadloop
-
-vdone:
- popl %ebx // restore register variables
- popl %edi
- popl %esi
- popl %ebp // restore caller's stack frame pointer
- ret
-
-#ifdef HORIZONTALDRAW
-// --------------------------------------------------------------------------
-// Horizontal Column Drawer Optimisation
-// --------------------------------------------------------------------------
-
-#ifdef LINUX
- .align 2
-#else
- .align 5
-#endif
-.globl C(R_DrawHColumn_8)
-C(R_DrawHColumn_8):
- pushl %ebp
- pushl %esi
- pushl %edi
- pushl %ebx
-
-//
-// dest = yhlookup[dc_x] + hcolumnofs[dc_yl];
-//
- movl C(dc_x),%ebx
- movl C(yhlookup)(,%ebx,4),%edi
- movl C(dc_yl),%ebp
- movl %ebp,%ebx
- addl C(hcolumnofs)(,%ebx,4),%edi // edi = dest
-
-//
-// pixelcount = yh - yl + 1
-//
- movl C(dc_yh),%eax
- incl %eax
- subl %ebp,%eax // pixel count
- movl %eax,C(pixelcount) // save for final pixel
- jle vhdone // nothing to scale
-
-//
-// frac = dc_texturemid - (centery-dc_yl)*fracstep;
-//
- movl C(dc_iscale),%ecx // fracstep
- movl C(centery),%eax
- subl %ebp,%eax
- imul %ecx,%eax
- movl C(dc_texturemid),%edx
- subl %eax,%edx
- movl %edx,%ebx
- shrl $16,%ebx // frac int.
- andl $0x0000007f,%ebx
- shll $16,%edx // y frac up
-
- movl %ecx,%ebp
- shll $16,%ebp // fracstep f. up
- shrl $16,%ecx // fracstep i. ->cl
- andb $0x7f,%cl
-
- movl C(dc_source),%esi
-
-//
-// lets rock :) !
-//
-
- movl C(pixelcount),%eax
- movb %al,%dh
- shrl $2,%eax
- movb %al,%ch // quad count
-
- testb %ch, %ch
- jz vhnearlydone
-
- movl C(dc_colormap),%eax
- decl %edi //-----
-
-vhloop:
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx
- adcb %cl,%bl
- andb $0x7f,%bl
- incl %edi //-----
- movb (%eax),%dh
- movb %dh,(%edi) //-----
-
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx
- incl %edi //-----
- adcb %cl,%bl
- movb (%eax),%dl
- andb $0x7f,%bl
- movb %dl,(%edi) //-----
-
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx
- adcb %cl,%bl
-// shll $16,%edx
- andb $0x7f,%bl
- incl %edi //-----
- movb (%eax),%dh
- movb %dh,(%edi) //-----
-
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx
- incl %edi //-----
- adcb %cl,%bl
- movb (%eax),%dl
- andb $0x7f,%bl
- movb %dl,(%edi)
-// movl %edx,(%edi)
-// addl $4,%edi
-
- decb %ch
- jnz vhloop
-
-vhnearlydone:
-// movl C(pixelcount)
-
-vhdone:
- popl %ebx
- popl %edi
- popl %esi
- popl %ebp
- ret
-
-
-// --------------------------------------------------------------------------
-// Rotate a buffer 90 degree in clockwise order after horiz.col. draws
-// --------------------------------------------------------------------------
-
-#ifdef LINUX
- .align 2
-#else
- .align 5
-#endif
-.globl C(R_RotateBuffer)
-C(R_RotateBuffer):
- pushl %ebp
- pushl %esi
- pushl %edi
- pushl %ebx
-
-
- movl C(dc_source),%esi
- movl C(dc_colormap),%edi
-
-
- movb (%esi),%ah
- addl $200,%esi
- movb (%ebx),%al
- addl $200,%ebx
- bswap %eax
- movb (%esi),%ah
- addl $200,%esi
- movb (%ebx),%al
- addl $200,%ebx
- movl %eax,(%edi)
- addl $4,%edi
-
-
- popl %ebx
- popl %edi
- popl %esi
- popl %ebp
- ret
-#endif
-
-//----------------------------------------------------------------------
-//13-02-98:
-// R_DrawSkyColumn : same as R_DrawColumn but:
-//
-// - wrap around 256 instead of 127.
-// this is needed because we have a higher texture for mouselook,
-// we need at least 200 lines for the sky.
-//
-// NOTE: the sky should never wrap, so it could use a faster method.
-// for the moment, we'll still use a wrapping method...
-//
-// IT S JUST A QUICK CUT N PASTE, WAS NOT OPTIMISED AS IT SHOULD BE !!!
-//
-//----------------------------------------------------------------------
-
-#ifdef LINUX
- .align 2
-#else
- .align 5
-#endif
-.globl C(R_DrawSkyColumn_8)
-C(R_DrawSkyColumn_8):
- pushl %ebp
- pushl %esi
- pushl %edi
- pushl %ebx
-
-//
-// dest = ylookup[dc_yl] + columnofs[dc_x];
-//
- movl C(dc_yl),%ebp
- movl %ebp,%ebx
- movl C(ylookup)(,%ebx,4),%edi
- movl C(dc_x),%ebx
- addl C(columnofs)(,%ebx,4),%edi // edi = dest
-
-//
-// pixelcount = yh - yl + 1
-//
- movl C(dc_yh),%eax
- incl %eax
- subl %ebp,%eax // pixel count
- movl %eax,C(pixelcount) // save for final pixel
- jle vskydone // nothing to scale
-
-//
-// frac = dc_texturemid - (centery-dc_yl)*fracstep;
-//
- movl C(dc_iscale),%ecx // fracstep
- movl C(centery),%eax
- subl %ebp,%eax
- imul %ecx,%eax
- movl C(dc_texturemid),%edx
- subl %eax,%edx
- movl %edx,%ebx
- shrl $16,%ebx // frac int.
- andl $0x000000ff,%ebx
- shll $16,%edx // y frac up
-
- movl %ecx,%ebp
- shll $16,%ebp // fracstep f. up
- shrl $16,%ecx // fracstep i. ->cl
-
- movl C(dc_source),%esi
-
-//
-// lets rock :) !
-//
- movl C(pixelcount),%eax
- movb %al,%dh
- shrl $2,%eax
- movb %al,%ch // quad count
- movl C(dc_colormap),%eax
- testb $3,%dh
- jz v4skyquadloop
-
-//
-// do un-even pixel
-//
- testb $1,%dh
- jz 2f
-
- movb (%esi,%ebx),%al // prep un-even loops
- addl %ebp,%edx // ypos f += ystep f
- adcb %cl,%bl // ypos i += ystep i
- movb (%eax),%dl // colormap texel
- movb %dl,(%edi) // output pixel
- addl C(vidwidth),%edi
-
-//
-// do two non-quad-aligned pixels
-//
-2:
- testb $2,%dh
- jz 3f
-
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx // ypos f += ystep f
- adcb %cl,%bl // ypos i += ystep i
- movb (%eax),%dl // colormap texel
- movb %dl,(%edi) // output pixel
-
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx // ypos f += ystep f
- adcb %cl,%bl // ypos i += ystep i
- movb (%eax),%dl // colormap texel
- addl C(vidwidth),%edi
- movb %dl,(%edi) // output pixel
-
- addl C(vidwidth),%edi
-
-//
-// test if there was at least 4 pixels
-//
-3:
- testb $0xFF,%ch // test quad count
- jz vskydone
-
-//
-// ebp : ystep frac. upper 24 bits
-// edx : y frac. upper 24 bits
-// ebx : y i. lower 7 bits, masked for index
-// ecx : ch = counter, cl = y step i.
-// eax : colormap aligned 256
-// esi : source texture column
-// edi : dest screen
-//
-v4skyquadloop:
-// .align 4
-vskyquadloop:
- movb (%esi,%ebx),%al // prep loop
- addl %ebp,%edx // ypos f += ystep f
- adcb %cl,%bl // ypos i += ystep i
- movb (%eax),%dl // colormap texel
- movb %dl,(%edi) // output pixel
-
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx
- adcb %cl,%bl
- movb (%eax),%dl
-p1b: movb %dl,0x12345678(%edi)
-
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx
- adcb %cl,%bl
- movb (%eax),%dl
-p2b: movb %dl,2*0x12345678(%edi)
-
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx
- adcb %cl,%bl
- movb (%eax),%dl
-p3b: movb %dl,3*0x12345678(%edi)
-
-p4b: addl $4*0x12345678,%edi
-
- decb %ch
- jnz vskyquadloop
-
-vskydone:
- popl %ebx // restore register variables
- popl %edi
- popl %esi
- popl %ebp // restore caller's stack frame pointer
- ret
-
-
-
-//----------------------------------------------------------------------
-//
-// R_DrawSpan
-//
-// Horizontal texture mapping
-//
-//----------------------------------------------------------------------
-
- .data
-
-ystep: .long 0
-xstep: .long 0
-C(texwidth): .long 64 // texture width
-#if !defined( LINUX)
- .text
-#endif
-#ifdef LINUX
- .align 2
-#else
- .align 4
-#endif
-.globl C(R_DrawSpan_8)
-C(R_DrawSpan_8):
- pushl %ebp // preserve caller's stack frame pointer
- pushl %esi // preserve register variables
- pushl %edi
- pushl %ebx
-
-
-//
-// find loop count
-//
- movl C(ds_x2),%eax
- incl %eax
- subl C(ds_x1),%eax // pixel count
- movl %eax,C(pixelcount) // save for final pixel
- js hdone // nothing to scale
- shrl $1,%eax // double pixel count
- movl %eax,C(loopcount)
-
-//
-// build composite position
-//
- movl C(ds_xfrac),%ebp
- shll $10,%ebp
- andl $0x0ffff0000,%ebp
- movl C(ds_yfrac),%eax
- shrl $6,%eax
- andl $0x0ffff,%eax
- movl C(ds_y),%edi
- orl %eax,%ebp
-
- movl C(ds_source),%esi
-
-//
-// calculate screen dest
-//
-
- movl C(ylookup)(,%edi,4),%edi
- movl C(ds_x1),%eax
- addl C(columnofs)(,%eax,4),%edi
-
-//
-// build composite step
-//
- movl C(ds_xstep),%ebx
- shll $10,%ebx
- andl $0x0ffff0000,%ebx
- movl C(ds_ystep),%eax
- shrl $6,%eax
- andl $0x0ffff,%eax
- orl %eax,%ebx
-
- //movl %eax,OFFSET hpatch1+2 // convice tasm to modify code...
- movl %ebx,hpatch1+2
- //movl %eax,OFFSET hpatch2+2 // convice tasm to modify code...
- movl %ebx,hpatch2+2
- movl %esi,hpatch3+2
- movl %esi,hpatch4+2
-// %eax aligned colormap
-// %ebx aligned colormap
-// %ecx,%edx scratch
-// %esi virtual source
-// %edi moving destination pointer
-// %ebp frac
- movl C(ds_colormap),%eax
-// shld $22,%ebp,%ecx // begin calculating third pixel (y units)
-// shld $6,%ebp,%ecx // begin calculating third pixel (x units)
- movl %ebp,%ecx
- addl %ebx,%ebp // advance frac pointer
- shrw $10,%cx
- roll $6,%ecx
- andl $4095,%ecx // finish calculation for third pixel
-// shld $22,%ebp,%edx // begin calculating fourth pixel (y units)
-// shld $6,%ebp,%edx // begin calculating fourth pixel (x units)
- movl %ebp,%edx
- shrw $10,%dx
- roll $6,%edx
- addl %ebx,%ebp // advance frac pointer
- andl $4095,%edx // finish calculation for fourth pixel
- movl %eax,%ebx
- movb (%esi,%ecx),%al // get first pixel
- movb (%esi,%edx),%bl // get second pixel
- testl $0x0fffffffe,C(pixelcount)
- movb (%eax),%dl // color translate first pixel
-
-// jnz hdoubleloop // at least two pixels to map
-// jmp hchecklast
-
-// movw $0xf0f0,%dx //see visplanes start
-
- jz hchecklast
- movb (%ebx),%dh // color translate second pixel
- movl C(loopcount),%esi
-// .align 4
-hdoubleloop:
-// shld $22,%ebp,%ecx // begin calculating third pixel (y units)
-// shld $6,%ebp,%ecx // begin calculating third pixel (x units)
- movl %ebp,%ecx
- shrw $10,%cx
- roll $6,%ecx
-hpatch1:
- addl $0x012345678,%ebp // advance frac pointer
- movw %dx,(%edi) // write first pixel
- andl $4095,%ecx // finish calculation for third pixel
-// shld $22,%ebp,%edx // begin calculating fourth pixel (y units)
-// shld $6,%ebp,%edx // begin calculating fourth pixel (x units)
- movl %ebp,%edx
- shrw $10,%dx
- roll $6,%edx
-hpatch3:
- movb 0x012345678(%ecx),%al // get third pixel
-// movb %bl,1(%edi) // write second pixel
- andl $4095,%edx // finish calculation for fourth pixel
-hpatch2:
- addl $0x012345678,%ebp // advance frac pointer
-hpatch4:
- movb 0x012345678(%edx),%bl // get fourth pixel
- movb (%eax),%dl // color translate third pixel
- addl $2,%edi // advance to third pixel destination
- decl %esi // done with loop?
- movb (%ebx),%dh // color translate fourth pixel
- jnz hdoubleloop
-
-// check for final pixel
-hchecklast:
- testl $1,C(pixelcount)
- jz hdone
- movb %dl,(%edi) // write final pixel
-
-hdone:
- popl %ebx // restore register variables
- popl %edi
- popl %esi
- popl %ebp // restore caller's stack frame pointer
- ret
-
-
-//.endif
-
-
-//----------------------------------------------------------------------
-// R_DrawTransColumn
-//
-// Vertical column texture drawer, with transparency. Replaces Doom2's
-// 'fuzz' effect, which was not so beautiful.
-// Transparency is always impressive in some way, don't know why...
-//----------------------------------------------------------------------
-
-#ifdef LINUX
- .align 2
-#else
- .align 5
-#endif
-
-.globl C(R_DrawTranslucentColumn_8)
-C(R_DrawTranslucentColumn_8):
- pushl %ebp // preserve caller's stack frame pointer
- pushl %esi // preserve register variables
- pushl %edi
- pushl %ebx
-
-//
-// dest = ylookup[dc_yl] + columnofs[dc_x];
-//
- movl C(dc_yl),%ebp
- movl %ebp,%ebx
- movl C(ylookup)(,%ebx,4),%edi
- movl C(dc_x),%ebx
- addl C(columnofs)(,%ebx,4),%edi // edi = dest
-
-//
-// pixelcount = yh - yl + 1
-//
- movl C(dc_yh),%eax
- incl %eax
- subl %ebp,%eax // pixel count
- movl %eax,C(pixelcount) // save for final pixel
- jle vtdone // nothing to scale
-
-//
-// frac = dc_texturemid - (centery-dc_yl)*fracstep;
-//
- movl C(dc_iscale),%ecx // fracstep
- movl C(centery),%eax
- subl %ebp,%eax
- imul %ecx,%eax
- movl C(dc_texturemid),%edx
- subl %eax,%edx
- movl %edx,%ebx
-
- shrl $16,%ebx // frac int.
- andl $0x0000007f,%ebx
- shll $16,%edx // y frac up
-
- movl %ecx,%ebp
- shll $16,%ebp // fracstep f. up
- shrl $16,%ecx // fracstep i. ->cl
- andb $0x7f,%cl
- pushw %cx
- movl %edx,%ecx
- popw %cx
- movl C(dc_colormap),%edx
- movl C(dc_source),%esi
-
-//
-// lets rock :) !
-//
- movl C(pixelcount),%eax
- shrl $2,%eax
- testb $0x03,C(pixelcount)
- movb %al,%ch // quad count
- movl C(dc_transmap),%eax
- jz vt4quadloop
-//
-// do un-even pixel
-//
- testb $1,C(pixelcount)
- jz 2f
-
- movb (%esi,%ebx),%ah // fetch texel : colormap number
- addl %ebp,%ecx
- adcb %cl,%bl
- movb (%edi),%al // fetch dest : index into colormap
- andb $0x7f,%bl
- movb (%eax),%dl
- movb (%edx), %dl // use colormap now !
- movb %dl,(%edi)
- addl C(vidwidth),%edi
-//
-// do two non-quad-aligned pixels
-//
-2:
- testb $2,C(pixelcount)
- jz 3f
-
- movb (%esi,%ebx),%ah // fetch texel : colormap number
- addl %ebp,%ecx
- adcb %cl,%bl
- movb (%edi),%al // fetch dest : index into colormap
- andb $0x7f,%bl
- movb (%eax),%dl
- movb (%edx), %dl // use colormap now !
- movb %dl,(%edi)
- addl C(vidwidth),%edi
-
- movb (%esi,%ebx),%ah // fetch texel : colormap number
- addl %ebp,%ecx
- adcb %cl,%bl
- movb (%edi),%al // fetch dest : index into colormap
- andb $0x7f,%bl
- movb (%eax),%dl
- movb (%edx), %dl // use colormap now !
- movb %dl,(%edi)
- addl C(vidwidth),%edi
-
-//
-// test if there was at least 4 pixels
-//
-3:
- testb $0xFF,%ch // test quad count
- jz vtdone
-
-//
-// tystep : ystep frac. upper 24 bits
-// edx : upper 24 bit : colomap
-// dl : tmp pixel to write
-// ebx : y i. lower 7 bits, masked for index
-// ecx : y frac. upper 16 bits
-// ecx : ch = counter, cl = y step i.
-// eax : transmap aligned 65535 (upper 16 bit)
-// ah : background pixel (from the screen buffer)
-// al : foreground pixel (from the texture)
-// esi : source texture column
-// ebp,edi : dest screen
-//
-vt4quadloop:
- movb (%esi,%ebx),%ah // fetch texel : colormap number
-p5: movb 0x12345678(%edi),%al // fetch dest : index into colormap
-
- movl %ebp,C(tystep)
- movl %edi,%ebp
- subl C(vidwidth),%edi
- jmp inloop
-// .align 4
-vtquadloop:
- addl C(tystep),%ecx
- adcb %cl,%bl
-p6: addl $2*0x12345678,%ebp
- andb $0x7f,%bl
- movb (%eax),%dl
- movb (%esi,%ebx),%ah // fetch texel : colormap number
- movb (%edx), %dl // use colormap now !
- movb %dl,(%edi)
- movb (%ebp),%al // fetch dest : index into colormap
-inloop:
- addl C(tystep),%ecx
- adcb %cl,%bl
-p7: addl $2*0x12345678,%edi
- andb $0x7f,%bl
- movb (%eax),%dl
- movb (%esi,%ebx),%ah // fetch texel : colormap number
- movb (%edx), %dl // use colormap now !
- movb %dl,(%ebp)
- movb (%edi),%al // fetch dest : index into colormap
-
- addl C(tystep),%ecx
- adcb %cl,%bl
-p8: addl $2*0x12345678,%ebp
- andb $0x7f,%bl
- movb (%eax),%dl
- movb (%esi,%ebx),%ah // fetch texel : colormap number
- movb (%edx), %dl // use colormap now !
- movb %dl,(%edi)
- movb (%ebp),%al // fetch dest : index into colormap
-
- addl C(tystep),%ecx
- adcb %cl,%bl
-p9: addl $2*0x12345678,%edi
- andb $0x7f,%bl
- movb (%eax),%dl
- movb (%esi,%ebx),%ah // fetch texel : colormap number
- movb (%edx), %dl // use colormap now !
- movb %dl,(%ebp)
- movb (%edi),%al // fetch dest : index into colormap
-
- decb %ch
- jnz vtquadloop
-
-vtdone:
- popl %ebx // restore register variables
- popl %edi
- popl %esi
- popl %ebp // restore caller's stack frame pointer
- ret
-
-#endif // ifdef USEASM
-
-
-
-//----------------------------------------------------------------------
-// R_DrawShadeColumn
-//
-// for smoke..etc.. test.
-//----------------------------------------------------------------------
-
-#ifdef LINUX
- .align 2
-#else
- .align 5
-#endif
-.globl C(R_DrawShadeColumn_8)
-C(R_DrawShadeColumn_8):
- pushl %ebp // preserve caller's stack frame pointer
- pushl %esi // preserve register variables
- pushl %edi
- pushl %ebx
-
-//
-// dest = ylookup[dc_yl] + columnofs[dc_x];
-//
- movl C(dc_yl),%ebp
- movl %ebp,%ebx
- movl C(ylookup)(,%ebx,4),%edi
- movl C(dc_x),%ebx
- addl C(columnofs)(,%ebx,4),%edi // edi = dest
-
-//
-// pixelcount = yh - yl + 1
-//
- movl C(dc_yh),%eax
- incl %eax
- subl %ebp,%eax // pixel count
- movl %eax,C(pixelcount) // save for final pixel
- jle shdone // nothing to scale
-
-//
-// frac = dc_texturemid - (centery-dc_yl)*fracstep;
-//
- movl C(dc_iscale),%ecx // fracstep
- movl C(centery),%eax
- subl %ebp,%eax
- imul %ecx,%eax
- movl C(dc_texturemid),%edx
- subl %eax,%edx
- movl %edx,%ebx
- shrl $16,%ebx // frac int.
- andl $0x0000007f,%ebx
- shll $16,%edx // y frac up
-
- movl %ecx,%ebp
- shll $16,%ebp // fracstep f. up
- shrl $16,%ecx // fracstep i. ->cl
- andb $0x7f,%cl
-
- movl C(dc_source),%esi
-
-//
-// lets rock :) !
-//
- movl C(pixelcount),%eax
- movb %al,%dh
- shrl $2,%eax
- movb %al,%ch // quad count
- movl C(colormaps),%eax
- testb $0x03,%dh
- jz sh4quadloop
-
-//
-// do un-even pixel
-//
- testb $1,%dh
- jz 2f
-
- movb (%esi,%ebx),%ah // fetch texel : colormap number
- addl %ebp,%edx
- adcb %cl,%bl
- movb (%edi),%al // fetch dest : index into colormap
- andb $0x7f,%bl
- movb (%eax),%dl
- movb %dl,(%edi)
- addl C(vidwidth),%edi
-
-//
-// do two non-quad-aligned pixels
-//
-2:
- testb $2,%dh
- jz 3f
-
- movb (%esi,%ebx),%ah // fetch texel : colormap number
- addl %ebp,%edx
- adcb %cl,%bl
- movb (%edi),%al // fetch dest : index into colormap
- andb $0x7f,%bl
- movb (%eax),%dl
- movb %dl,(%edi)
- addl C(vidwidth),%edi
-
- movb (%esi,%ebx),%ah // fetch texel : colormap number
- addl %ebp,%edx
- adcb %cl,%bl
- movb (%edi),%al // fetch dest : index into colormap
- andb $0x7f,%bl
- movb (%eax),%dl
- movb %dl,(%edi)
- addl C(vidwidth),%edi
-
-//
-// test if there was at least 4 pixels
-//
-3:
- testb $0xFF,%ch // test quad count
- jz shdone
-
-//
-// ebp : ystep frac. upper 24 bits
-// edx : y frac. upper 24 bits
-// ebx : y i. lower 7 bits, masked for index
-// ecx : ch = counter, cl = y step i.
-// eax : colormap aligned 256
-// esi : source texture column
-// edi : dest screen
-//
-sh4quadloop:
- movb $0x7f,%dh // prep mask
-
- movb (%esi,%ebx),%ah // fetch texel : colormap number
-sh5: movb 0x12345678(%edi),%al // fetch dest : index into colormap
-
- movl %ebp,C(tystep)
- movl %edi,%ebp
- subl C(vidwidth),%edi
- jmp shinloop
-// .align 4
-shquadloop:
- addl C(tystep),%edx
- adcb %cl,%bl
- andb %dh,%bl
-sh6: addl $2*0x12345678,%ebp
- movb (%eax),%dl
- movb (%esi,%ebx),%ah // fetch texel : colormap number
- movb %dl,(%edi)
- movb (%ebp),%al // fetch dest : index into colormap
-shinloop:
- addl C(tystep),%edx
- adcb %cl,%bl
- andb %dh,%bl
-sh7: addl $2*0x12345678,%edi
- movb (%eax),%dl
- movb (%esi,%ebx),%ah // fetch texel : colormap number
- movb %dl,(%ebp)
- movb (%edi),%al // fetch dest : index into colormap
-
- addl C(tystep),%edx
- adcb %cl,%bl
- andb %dh,%bl
-sh8: addl $2*0x12345678,%ebp
- movb (%eax),%dl
- movb (%esi,%ebx),%ah // fetch texel : colormap number
- movb %dl,(%edi)
- movb (%ebp),%al // fetch dest : index into colormap
-
- addl C(tystep),%edx
- adcb %cl,%bl
- andb %dh,%bl
-sh9: addl $2*0x12345678,%edi
- movb (%eax),%dl
- movb (%esi,%ebx),%ah // fetch texel : colormap number
- movb %dl,(%ebp)
- movb (%edi),%al // fetch dest : index into colormap
-
- decb %ch
- jnz shquadloop
-
-shdone:
- popl %ebx // restore register variables
- popl %edi
- popl %esi
- popl %ebp // restore caller's stack frame pointer
- ret
-
-
-
-//----------------------------------------------------------------------
-//
-// R_DrawWaterColumn : basically it's just a copy of R_DrawColumn,
-// but it uses dc_colormap from dc_yl to dc_yw-1
-// then it uses dc_wcolormap from dc_yw to dc_yh
-//
-// Thus, the 'underwater' part of the walls is remapped to 'water-like'
-// colors.
-//
-//----------------------------------------------------------------------
-
-#ifdef LINUX
- .align 2
-#else
- .align 5
-#endif
-.globl C(R_DrawWaterColumn)
-C(R_DrawWaterColumn):
- pushl %ebp // preserve caller's stack frame pointer
- pushl %esi // preserve register variables
- pushl %edi
- pushl %ebx
-
-//
-// dest = ylookup[dc_yl] + columnofs[dc_x];
-//
- movl C(dc_yl),%ebp
- movl %ebp,%ebx
- movl C(ylookup)(,%ebx,4),%edi
- movl C(dc_x),%ebx
- addl C(columnofs)(,%ebx,4),%edi // edi = dest
-
-//
-// pixelcount = yh - yl + 1
-//
- movl C(dc_yh),%eax
- incl %eax
- subl %ebp,%eax // pixel count
- movl %eax,C(pixelcount) // save for final pixel
- jle wdone // nothing to scale
-
-//
-// frac = dc_texturemid - (centery-dc_yl)*fracstep;
-//
- movl C(dc_iscale),%ecx // fracstep
- movl C(centery),%eax
- subl %ebp,%eax
- imul %ecx,%eax
- movl C(dc_texturemid),%edx
- subl %eax,%edx
- movl %edx,%ebx
- shrl $16,%ebx // frac int.
- andl $0x0000007f,%ebx
- shll $16,%edx // y frac up
-
- movl %ecx,%ebp
- shll $16,%ebp // fracstep f. up
- shrl $16,%ecx // fracstep i. ->cl
- andb $0x7f,%cl
-
- movl C(dc_source),%esi
-
-//
-// lets rock :) !
-//
- movl C(pixelcount),%eax
- movb %al,%dh
- shrl $2,%eax
- movb %al,%ch // quad count
- movl C(dc_wcolormap),%eax
- testb $3,%dh
- jz w4quadloop
-
-//
-// do un-even pixel
-//
- testb $1,%dh
- jz 2f
-
- movb (%esi,%ebx),%al // prep un-even loops
- addl %ebp,%edx // ypos f += ystep f
- adcb %cl,%bl // ypos i += ystep i
- movb (%eax),%dl // colormap texel
- andb $0x7f,%bl // mask 0-127 texture index
- movb %dl,(%edi) // output pixel
- addl C(vidwidth),%edi
-
-//
-// do two non-quad-aligned pixels
-//
-2:
- testb $2,%dh
- jz 3f
-
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx // ypos f += ystep f
- adcb %cl,%bl // ypos i += ystep i
- movb (%eax),%dl // colormap texel
- andb $0x7f,%bl // mask 0-127 texture index
- movb %dl,(%edi) // output pixel
-
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx // ypos f += ystep f
- adcb %cl,%bl // ypos i += ystep i
- movb (%eax),%dl // colormap texel
- andb $0x7f,%bl // mask 0-127 texture index
- addl C(vidwidth),%edi
- movb %dl,(%edi) // output pixel
-
- addl C(vidwidth),%edi
-
-//
-// test if there was at least 4 pixels
-//
-3:
- testb $0xFF,%ch // test quad count
- jz wdone
-
-//
-// ebp : ystep frac. upper 24 bits
-// edx : y frac. upper 24 bits
-// ebx : y i. lower 7 bits, masked for index
-// ecx : ch = counter, cl = y step i.
-// eax : colormap aligned 256
-// esi : source texture column
-// edi : dest screen
-//
-w4quadloop:
- movb $0x7f,%dh // prep mask
-// .align 4
-wquadloop:
- movb (%esi,%ebx),%al // prep loop
- addl %ebp,%edx // ypos f += ystep f
- adcb %cl,%bl // ypos i += ystep i
- movb (%eax),%dl // colormap texel
- movb %dl,(%edi) // output pixel
- andb $0x7f,%bl // mask 0-127 texture index
-
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx
- adcb %cl,%bl
- movb (%eax),%dl
-w1: movb %dl,0x12345678(%edi)
- andb $0x7f,%bl
-
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx
- adcb %cl,%bl
- movb (%eax),%dl
-w2: movb %dl,2*0x12345678(%edi)
- andb $0x7f,%bl
-
- movb (%esi,%ebx),%al // fetch source texel
- addl %ebp,%edx
- adcb %cl,%bl
- movb (%eax),%dl
-w3: movb %dl,3*0x12345678(%edi)
- andb $0x7f,%bl
-
-w4: addl $4*0x12345678,%edi
-
- decb %ch
- jnz wquadloop
-
-wdone:
- popl %ebx // restore register variables
- popl %edi
- popl %esi
- popl %ebp // restore caller's stack frame pointer
- ret
-
-
-
-
-
-
-
-//----------------------------------------------------------------------
-//
-// R_DrawSpanNoWrap
-//
-// Horizontal texture mapping, does not remap colors,
-// neither needs to wrap around the source texture.
-//
-// Thus, a special optimisation can be used...
-//
-//----------------------------------------------------------------------
-
- .data
-
-advancetable: .long 0, 0
-#if !defined( LINUX)
- .text
-#endif
-#ifdef LINUX
- .align 2
-#else
- .align 4
-#endif
-.globl C(R_DrawSpanNoWrap)
-C(R_DrawSpanNoWrap):
- pushl %ebp // preserve caller's stack frame pointer
- pushl %esi // preserve register variables
- pushl %edi
- pushl %ebx
-
-//
-// find loop count
-//
-
- movl C(ds_x2),%eax
- incl %eax
- subl C(ds_x1),%eax // pixel count
- movl %eax,C(pixelcount) // save for final pixel
- jle htvdone // nothing to scale
-// shrl $1,%eax // double pixel count
-// movl %eax,C(loopcount)
-
-//
-// calculate screen dest
-//
-
- movl C(ds_y),%edi //full destination start address
-
-//
-// set up advancetable
-//
-
- movl C(ds_xstep),%ebp
- movl C(ds_ystep),%ecx
- movl %ecx,%eax
- movl %ebp,%edx
- sarl $16,%edx // xstep >>= 16;
- movl C(vidwidth),%ebx
- sarl $16,%eax // ystep >>= 16;
- jz 0f
- imull %ebx,%eax // (ystep >> 16) * texwidth;
-0:
- addl %edx,%eax // add in xstep
- // (ystep >> 16) * texwidth + (xstep >> 16);
-
- movl %eax,advancetable+4 // advance base in y
- addl %ebx,%eax // ((ystep >> 16) + 1) * texwidth +
- // (xstep >> 16);
- movl %eax,advancetable // advance extra in y
-
- shll $16,%ebp // left-justify xstep fractional part
- movl %ebp,xstep
- shll $16,%ecx // left-justify ystep fractional part
- movl %ecx,ystep
-
-//
-// calculate the texture starting address
-//
- movl C(ds_source),%esi // texture source
-
- movl C(ds_yfrac),%eax
- movl %eax,%edx
- sarl $16,%eax
- movl C(ds_xfrac),%ecx
- imull %ebx,%eax // (yfrac >> 16) * texwidth
- movl %ecx,%ebx
- sarl $16,%ecx
- movl %ecx,%ebp
- addl %eax,%ebp // source = (xfrac >> 16) +
- // ((yfrac >> 16) * texwidth);
-
-//
-// esi : texture source
-// edi : screen dest
-// eax : colormap aligned on 256 boundary, hehehe...
-// ebx : xfrac << 16
-// ecx : used in loop, contains either 0 or -1, *4, offset into advancetable
-// edx : yfrac << 16
-// ebp : offset into texture
-//
-
- shll $16,%edx // yfrac upper word, lower byte will be used
- movl C(ds_colormap),%eax
- shll $16,%ebx // xfrac upper word, lower unused
-
- movl C(pixelcount),%ecx
- shrl $2,%ecx
- movb %cl,%dh // quad pixels count
-
- movl C(pixelcount),%ecx
- andl $3,%ecx
- jz htvquadloop // pixelcount is multiple of 4
- decl %ecx
- jz 1f
- decl %ecx
- jz 2f
-
-//
-// do one to three pixels first
-//
- addl ystep,%edx // yfrac += ystep
- sbbl %ecx,%ecx // turn carry into 0 or -1 if set
- movb (%esi,%ebp),%al // get texture pixel
- addl xstep,%ebx // xfrac += xstep
-// movb (%eax),%dl // pixel goes through colormap
- adcl advancetable+4(,%ecx,4),%ebp // advance source
- movb %al,(%edi) // write pixel dest
-
- incl %edi
-
-2:
- addl ystep,%edx // yfrac += ystep
- sbbl %ecx,%ecx // turn carry into 0 or -1 if set
- movb (%esi,%ebp),%al // get texture pixel
- addl xstep,%ebx // xfrac += xstep
-// movb (%eax),%dl // pixel goes through colormap
- adcl advancetable+4(,%ecx,4),%ebp // advance source
- movb %al,(%edi) // write pixel dest
-
- incl %edi
-
-1:
- addl ystep,%edx // yfrac += ystep
- sbbl %ecx,%ecx // turn carry into 0 or -1 if set
- movb (%esi,%ebp),%al // get texture pixel
- addl xstep,%ebx // xfrac += xstep
-// movb (%eax),%dl // pixel goes through colormap
- adcl advancetable+4(,%ecx,4),%ebp // advance source
- movb %al,(%edi) // write pixel dest
-
- incl %edi
-
-//
-// test if there was at least 4 pixels
-//
- testb $0xFF,%dh
- jz htvdone
-
-//
-// two pixels per loop
-// U
-// V
-htvquadloop:
- addl ystep,%edx // yfrac += ystep
- sbbl %ecx,%ecx // turn carry into 0 or -1 if set
- movb (%esi,%ebp),%al // get texture pixel
- addl xstep,%ebx // xfrac += xstep
-// movb (%eax),%dl // pixel goes through colormap
- adcl advancetable+4(,%ecx,4),%ebp // advance source
- movb %al,(%edi) // write pixel dest
-
- addl ystep,%edx
- sbbl %ecx,%ecx
- movb (%esi,%ebp),%al
- addl xstep,%ebx
-// movb (%eax),%dl
- adcl advancetable+4(,%ecx,4),%ebp
- movb %al,1(%edi)
-
- addl ystep,%edx
- sbbl %ecx,%ecx
- movb (%esi,%ebp),%al
- addl xstep,%ebx
-// movb (%eax),%dl
- adcl advancetable+4(,%ecx,4),%ebp
- movb %al,2(%edi)
-
- addl ystep,%edx
- sbbl %ecx,%ecx
- movb (%esi,%ebp),%al
- addl xstep,%ebx
-// movb (%eax),%dl
- adcl advancetable+4(,%ecx,4),%ebp
- movb %al,3(%edi)
-
- addl $4, %edi
- incl %ecx //dummy
-
- decb %dh
- jnz htvquadloop // paire dans V-pipe
-
-htvdone:
- popl %ebx // restore register variables
- popl %edi
- popl %esi
- popl %ebp // restore caller's stack frame pointer
- ret
-
-
-//.endif
-
-#ifdef HORIZONTALDRAW
-// void R_RotateBuffere (void)
-
-#ifdef LINUX
- .align 2
-#else
- .align 4
-#endif
-.globl C(R_RotateBufferasm)
-C(R_RotateBufferasm):
- pushl %ebp // preserve caller's stack frame pointer
- pushl %esi // preserve register variables
- pushl %edi
- pushl %ebx
-
- movl C(dc_source),%esi
- movl C(dc_colormap),%edi
-
- movl $200,%edx
-ra2:
- movl $40,%ecx
-ra:
- movb -2*200(%esi),%al
- movb -6*200(%esi),%bl
- movb -3*200(%esi),%ah
- movb -7*200(%esi),%bh
- shll $16,%eax
- shll $16,%ebx
- movb (%esi),%al
- movb -4*200(%esi),%bl
- movb -1*200(%esi),%ah
- movb -5*200(%esi),%bh
- movl %eax,(%edi)
- subl $8*200,%esi
- movl %ebx,4(%edi)
- addl $8,%edi
- decl %ecx
- jnz ra
-
- addl $320*200+1,%esi //32*480 passe a la ligne suivante
-// addl 320-32,%edi
-
- decl %edx
- jnz ra2
-
- pop %ebp // preserve caller's stack frame pointer
- pop %esi // preserve register variables
- pop %edi
- pop %ebx
- ret
-#endif
diff --git a/src/tmap_asm.s b/src/tmap_asm.s
deleted file mode 100644
index 3cd0f87cc..000000000
--- a/src/tmap_asm.s
+++ /dev/null
@@ -1,322 +0,0 @@
-// SONIC ROBO BLAST 2
-//-----------------------------------------------------------------------------
-// Copyright (C) 1998-2000 by DooM Legacy Team.
-// Copyright (C) 1999-2020 by Sonic Team Junior.
-//
-// This program is free software distributed under the
-// terms of the GNU General Public License, version 2.
-// See the 'LICENSE' file for more details.
-//-----------------------------------------------------------------------------
-/// \file tmap_asm.s
-/// \brief ???
-
-//.comm _dc_colormap,4
-//.comm _dc_x,4
-//.comm _dc_yl,4
-//.comm _dc_yh,4
-//.comm _dc_iscale,4
-//.comm _dc_texturemid,4
-//.comm _dc_source,4
-//.comm _ylookup,4
-//.comm _columnofs,4
-//.comm _loopcount,4
-//.comm _pixelcount,4
-.data
-_pixelcount:
-.long 0x00000000
-_loopcount:
-.long 0x00000000
-.align 8
-_mmxcomm:
-.long 0x00000000
-.text
-
- .align 4
-.globl _R_DrawColumn8_NOMMX
-_R_DrawColumn8_NOMMX:
- pushl %ebp
- pushl %esi
- pushl %edi
- pushl %ebx
- movl _dc_yl,%edx
- movl _dc_yh,%eax
- subl %edx,%eax
- leal 1(%eax),%ebx
- testl %ebx,%ebx
- jle rdc8ndone
- movl _dc_x,%eax
- movl _ylookup, %edi
- movl (%edi,%edx,4),%esi
- movl _columnofs, %edi
- addl (%edi,%eax,4),%esi
- movl _dc_iscale,%edi
- movl %edx,%eax
- imull %edi,%eax
- movl _dc_texturemid,%ecx
- addl %eax,%ecx
-
- movl _dc_source,%ebp
- xorl %edx, %edx
- subl $0x12345678, %esi
-.globl rdc8nwidth1
-rdc8nwidth1:
- .align 4,0x90
-rdc8nloop:
- movl %ecx,%eax
- shrl $16,%eax
- addl %edi,%ecx
- andl $127,%eax
- addl $0x12345678,%esi
-.globl rdc8nwidth2
-rdc8nwidth2:
- movb (%eax,%ebp),%dl
- movl _dc_colormap,%eax
- movb (%eax,%edx),%al
- movb %al,(%esi)
- decl %ebx
- jne rdc8nloop
-rdc8ndone:
- popl %ebx
- popl %edi
- popl %esi
- popl %ebp
- ret
-
-//
-// Optimised specifically for P54C/P55C (aka Pentium with/without MMX)
-// By ES 1998/08/01
-//
-
-.globl _R_DrawColumn_8_Pentium
-_R_DrawColumn_8_Pentium:
- pushl %ebp
- pushl %ebx
- pushl %esi
- pushl %edi
- movl _dc_yl,%eax // Top pixel
- movl _dc_yh,%ebx // Bottom pixel
- movl _ylookup, %edi
- movl (%edi,%ebx,4),%ecx
- subl %eax,%ebx // ebx=number of pixels-1
- jl rdc8pdone // no pixel to draw, done
- jnz rdc8pmany
- movl _dc_x,%edx // Special case: only one pixel
- movl _columnofs, %edi
- addl (%edi,%edx,4),%ecx // dest pixel at (%ecx)
- movl _dc_iscale,%esi
- imull %esi,%eax
- movl _dc_texturemid,%edi
- addl %eax,%edi // texture index in edi
- movl _dc_colormap,%edx
- shrl $16, %edi
- movl _dc_source,%ebp
- andl $127,%edi
- movb (%edi,%ebp),%dl // read texture pixel
- movb (%edx),%al // lookup for light
- movb %al,0(%ecx) // write it
- jmp rdc8pdone // done!
-.align 4, 0x90
-rdc8pmany: // draw >1 pixel
- movl _dc_x,%edx
- movl _columnofs, %edi
- movl (%edi,%edx,4),%edx
- leal 0x12345678(%edx, %ecx), %edi // edi = two pixels above bottom
-.globl rdc8pwidth5
-rdc8pwidth5: // DeadBeef = -2*SCREENWIDTH
- movl _dc_iscale,%edx // edx = fracstep
- imull %edx,%eax
- shll $9, %edx // fixme: Should get 7.25 fix as input
- movl _dc_texturemid,%ecx
- addl %eax,%ecx // ecx = frac
- movl _dc_colormap,%eax // eax = lighting/special effects LUT
- shll $9, %ecx
- movl _dc_source,%esi // esi = source ptr
-
- imull $0x12345678, %ebx // ebx = negative offset to pixel
-.globl rdc8pwidth6
-rdc8pwidth6: // DeadBeef = -SCREENWIDTH
-
-// Begin the calculation of the two first pixels
- leal (%ecx, %edx), %ebp
- shrl $25, %ecx
- movb (%esi, %ecx), %al
- leal (%edx, %ebp), %ecx
- shrl $25, %ebp
- movb (%eax), %dl
-
-// The main loop
-rdc8ploop:
- movb (%esi,%ebp), %al // load 1
- leal (%ecx, %edx), %ebp // calc frac 3
-
- shrl $25, %ecx // shift frac 2
- movb %dl, 0x12345678(%edi, %ebx)// store 0
-.globl rdc8pwidth1
-rdc8pwidth1: // DeadBeef = 2*SCREENWIDTH
-
- movb (%eax), %al // lookup 1
-
- movb %al, 0x12345678(%edi, %ebx)// store 1
-.globl rdc8pwidth2
-rdc8pwidth2: // DeadBeef = 3*SCREENWIDTH
- movb (%esi, %ecx), %al // load 2
-
- leal (%ebp, %edx), %ecx // calc frac 4
-
- shrl $25, %ebp // shift frac 3
- movb (%eax), %dl // lookup 2
-
- addl $0x12345678, %ebx // counter
-.globl rdc8pwidth3
-rdc8pwidth3: // DeadBeef = 2*SCREENWIDTH
- jl rdc8ploop // loop
-
-// End of loop. Write extra pixel or just exit.
- jnz rdc8pdone
- movb %dl, 0x12345678(%edi, %ebx)// Write odd pixel
-.globl rdc8pwidth4
-rdc8pwidth4: // DeadBeef = 2*SCREENWIDTH
-
-rdc8pdone:
-
- popl %edi
- popl %esi
- popl %ebx
- popl %ebp
- ret
-
-//
-// MMX asm version, optimised for K6
-// By ES 1998/07/05
-//
-
-.globl _R_DrawColumn_8_K6_MMX
-_R_DrawColumn_8_K6_MMX:
- pushl %ebp
- pushl %ebx
- pushl %esi
- pushl %edi
-
- movl %esp, %eax // Push 8 or 12, so that (%esp) gets aligned by 8
- andl $7,%eax
- addl $8,%eax
- movl %eax, _mmxcomm // Temp storage in mmxcomm: (%esp) is used instead
- subl %eax,%esp
-
- movl _dc_yl,%edx // Top pixel
- movl _dc_yh,%ebx // Bottom pixel
- movl _ylookup, %edi
- movl (%edi,%ebx,4),%ecx
- subl %edx,%ebx // ebx=number of pixels-1
- jl 0x12345678 // no pixel to draw, done
-.globl rdc8moffs1
-rdc8moffs1:
- jnz rdc8mmany
- movl _dc_x,%eax // Special case: only one pixel
- movl _columnofs, %edi
- addl (%edi,%eax,4),%ecx // dest pixel at (%ecx)
- movl _dc_iscale,%esi
- imull %esi,%edx
- movl _dc_texturemid,%edi
- addl %edx,%edi // texture index in edi
- movl _dc_colormap,%edx
- shrl $16, %edi
- movl _dc_source,%ebp
- andl $127,%edi
- movb (%edi,%ebp),%dl // read texture pixel
- movb (%edx),%al // lookup for light
- movb %al,0(%ecx) // write it
- jmp rdc8mdone // done!
-.globl rdc8moffs2
-rdc8moffs2:
-.align 4, 0x90
-rdc8mmany: // draw >1 pixel
- movl _dc_x,%eax
- movl _columnofs, %edi
- movl (%edi,%eax,4),%eax
- leal 0x12345678(%eax, %ecx), %esi // esi = two pixels above bottom
-.globl rdc8mwidth3
-rdc8mwidth3: // DeadBeef = -2*SCREENWIDTH
- movl _dc_iscale,%ecx // ecx = fracstep
- imull %ecx,%edx
- shll $9, %ecx // fixme: Should get 7.25 fix as input
- movl _dc_texturemid,%eax
- addl %edx,%eax // eax = frac
- movl _dc_colormap,%edx // edx = lighting/special effects LUT
- shll $9, %eax
- leal (%ecx, %ecx), %edi
- movl _dc_source,%ebp // ebp = source ptr
- movl %edi, 0(%esp) // Start moving frac and fracstep to MMX regs
-
- imull $0x12345678, %ebx // ebx = negative offset to pixel
-.globl rdc8mwidth5
-rdc8mwidth5: // DeadBeef = -SCREENWIDTH
-
- movl %edi, 4(%esp)
- leal (%eax, %ecx), %edi
- movq 0(%esp), %mm1 // fracstep:fracstep in mm1
- movl %eax, 0(%esp)
- shrl $25, %eax
- movl %edi, 4(%esp)
- movzbl (%ebp, %eax), %eax
- movq 0(%esp), %mm0 // frac:frac in mm0
-
- paddd %mm1, %mm0
- shrl $25, %edi
- movq %mm0, %mm2
- psrld $25, %mm2 // texture index in mm2
- paddd %mm1, %mm0
- movq %mm2, 0(%esp)
-
-.globl rdc8mloop
-rdc8mloop: // The main loop
- movq %mm0, %mm2 // move 4-5 to temp reg
- movzbl (%ebp, %edi), %edi // read 1
-
- psrld $25, %mm2 // shift 4-5
- movb (%edx,%eax), %cl // lookup 0
-
- movl 0(%esp), %eax // load 2
- addl $0x12345678, %ebx // counter
-.globl rdc8mwidth2
-rdc8mwidth2: // DeadBeef = 2*SCREENWIDTH
-
- movb %cl, (%esi, %ebx) // write 0
- movb (%edx,%edi), %ch // lookup 1
-
- movb %ch, 0x12345678(%esi, %ebx) // write 1
-.globl rdc8mwidth1
-rdc8mwidth1: // DeadBeef = SCREENWIDTH
- movl 4(%esp), %edi // load 3
-
- paddd %mm1, %mm0 // frac 6-7
- movzbl (%ebp, %eax), %eax // lookup 2
-
- movq %mm2, 0(%esp) // store texture index 4-5
- jl rdc8mloop
-
- jnz rdc8mno_odd
- movb (%edx,%eax), %cl // write the last odd pixel
- movb %cl, 0x12345678(%esi)
-.globl rdc8mwidth4
-rdc8mwidth4: // DeadBeef = 2*SCREENWIDTH
-rdc8mno_odd:
-
-.globl rdc8mdone
-rdc8mdone:
- emms
-
- addl _mmxcomm, %esp
- popl %edi
- popl %esi
- popl %ebx
- popl %ebp
- ret
-
-// Need some extra space to align run-time
-.globl R_DrawColumn_8_K6_MMX_end
-R_DrawColumn_8_K6_MMX_end:
-nop;nop;nop;nop;nop;nop;nop;nop;
-nop;nop;nop;nop;nop;nop;nop;nop;
-nop;nop;nop;nop;nop;nop;nop;nop;
-nop;nop;nop;nop;nop;nop;nop;
diff --git a/src/tmap_mmx.nas b/src/tmap_mmx.nas
deleted file mode 100644
index 15b97499d..000000000
--- a/src/tmap_mmx.nas
+++ /dev/null
@@ -1,674 +0,0 @@
-;; SONIC ROBO BLAST 2
-;;-----------------------------------------------------------------------------
-;; Copyright (C) 1998-2000 by DOSDOOM.
-;; Copyright (C) 2010-2020 by Sonic Team Junior.
-;;
-;; This program is free software distributed under the
-;; terms of the GNU General Public License, version 2.
-;; See the 'LICENSE' file for more details.
-;;-----------------------------------------------------------------------------
-;; FILE:
-;; tmap_mmx.nas
-;; DESCRIPTION:
-;; Assembler optimised rendering code for software mode, using SIMD
-;; instructions.
-;; Draw wall columns.
-
-
-[BITS 32]
-
-%define FRACBITS 16
-%define TRANSPARENTPIXEL 255
-
-%ifdef LINUX
-%macro cextern 1
-[extern %1]
-%endmacro
-
-%macro cglobal 1
-[global %1]
-%endmacro
-
-%else
-%macro cextern 1
-%define %1 _%1
-[extern %1]
-%endmacro
-
-%macro cglobal 1
-%define %1 _%1
-[global %1]
-%endmacro
-
-%endif
-
-
-; The viddef_s structure. We only need the width field.
-struc viddef_s
- resb 12
-.width: resb 4
- resb 44
-endstruc
-
-
-;; externs
-;; columns
-cextern dc_colormap
-cextern dc_x
-cextern dc_yl
-cextern dc_yh
-cextern dc_iscale
-cextern dc_texturemid
-cextern dc_texheight
-cextern dc_source
-cextern dc_hires
-cextern centery
-cextern centeryfrac
-cextern dc_transmap
-
-cextern R_DrawColumn_8_ASM
-cextern R_Draw2sMultiPatchColumn_8_ASM
-
-;; spans
-cextern nflatshiftup
-cextern nflatxshift
-cextern nflatyshift
-cextern nflatmask
-cextern ds_xfrac
-cextern ds_yfrac
-cextern ds_xstep
-cextern ds_ystep
-cextern ds_x1
-cextern ds_x2
-cextern ds_y
-cextern ds_source
-cextern ds_colormap
-
-cextern ylookup
-cextern columnofs
-cextern vid
-
-[SECTION .data]
-
-nflatmask64 dq 0
-
-
-[SECTION .text]
-
-;;----------------------------------------------------------------------
-;;
-;; R_DrawColumn : 8bpp column drawer
-;;
-;; MMX column drawer.
-;;
-;;----------------------------------------------------------------------
-;; eax = accumulator
-;; ebx = colormap
-;; ecx = count
-;; edx = accumulator
-;; esi = source
-;; edi = dest
-;; ebp = vid.width
-;; mm0 = accumulator
-;; mm1 = heightmask, twice
-;; mm2 = 2 * fracstep, twice
-;; mm3 = pair of consecutive fracs
-;;----------------------------------------------------------------------
-
-
-cglobal R_DrawColumn_8_MMX
-R_DrawColumn_8_MMX:
- push ebp ;; preserve caller's stack frame pointer
- push esi ;; preserve register variables
- push edi
- push ebx
-
-;;
-;; Our algorithm requires that the texture height be a power of two.
-;; If not, fall back to the non-MMX drawer.
-;;
-.texheightcheck:
- mov edx, [dc_texheight]
- sub edx, 1 ;; edx = heightmask
- test edx, [dc_texheight]
- jnz near .usenonMMX
-
- mov ebp, edx ;; Keep a copy of heightmask in a
- ;; GPR for the time being.
-
-;;
-;; Fill mm1 with heightmask
-;;
- movd mm1, edx ;; low dword = heightmask
- punpckldq mm1, mm1 ;; copy low dword to high dword
-
-;;
-;; dest = ylookup[dc_yl] + columnofs[dc_x];
-;;
- mov eax, [dc_yl]
- mov edi, [ylookup+eax*4]
- mov ebx, [dc_x]
- add edi, [columnofs+ebx*4] ;; edi = dest
-
-
-;;
-;; pixelcount = yh - yl + 1
-;;
- mov ecx, [dc_yh]
- add ecx, 1
- sub ecx, eax ;; pixel count
- jle near .done ;; nothing to scale
-
-;;
-;; fracstep = dc_iscale;
-;;
- movd mm2, [dc_iscale] ;; fracstep in low dword
- punpckldq mm2, mm2 ;; copy to high dword
-
- mov ebx, [dc_colormap]
- mov esi, [dc_source]
-
-;;
-;; frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep));
-;;
- ;; eax == dc_yl already
- shl eax, FRACBITS
- sub eax, [centeryfrac]
- imul dword [dc_iscale]
- shrd eax, edx, FRACBITS
- add eax, [dc_texturemid]
-
-;;
-;; if (dc_hires) frac = 0;
-;;
- test byte [dc_hires], 0x01
- jz .mod2
- xor eax, eax
-
-
-;;
-;; Do mod-2 pixel.
-;;
-.mod2:
- test ecx, 1
- jz .pairprepare
- mov edx, eax ;; edx = frac
- add eax, [dc_iscale] ;; eax += fracstep
- sar edx, FRACBITS
- and edx, ebp ;; edx &= heightmask
- movzx edx, byte [esi + edx]
- movzx edx, byte [ebx + edx]
- mov [edi], dl
-
- add edi, [vid + viddef_s.width]
- sub ecx, 1
- jz .done
-
-.pairprepare:
-;;
-;; Prepare for the main loop.
-;;
- movd mm3, eax ;; Low dword = frac
- movq mm4, mm3 ;; Copy to intermediate register
- paddd mm4, mm2 ;; dwords of mm4 += fracstep
- punpckldq mm3, mm4 ;; Low dword = first frac, high = second
- pslld mm2, 1 ;; fracstep *= 2
-
-;;
-;; ebp = vid.width
-;;
- mov ebp, [vid + viddef_s.width]
-
- align 16
-.pairloop:
- movq mm0, mm3 ;; 3B 1u.
- psrad mm0, FRACBITS ;; 4B 1u.
- pand mm0, mm1 ;; 3B 1u. frac &= heightmask
- paddd mm3, mm2 ;; 3B 1u. frac += fracstep
-
- movd eax, mm0 ;; 3B 1u. Get first frac
-;; IFETCH boundary
- movzx eax, byte [esi + eax] ;; 4B 1u. Texture map
- movzx eax, byte [ebx + eax] ;; 4B 1u. Colormap
-
- punpckhdq mm0, mm0 ;; 3B 1(2)u. low dword = high dword
- movd edx, mm0 ;; 3B 1u. Get second frac
- mov [edi], al ;; 2B 1(2)u. First pixel
-;; IFETCH boundary
-
- movzx edx, byte [esi + edx] ;; 4B 1u. Texture map
- movzx edx, byte [ebx + edx] ;; 4B 1u. Colormap
- mov [edi + 1*ebp], dl ;; 3B 1(2)u. Second pixel
-
- lea edi, [edi + 2*ebp] ;; 3B 1u. edi += 2 * vid.width
-;; IFETCH boundary
- sub ecx, 2 ;; 3B 1u. count -= 2
- jnz .pairloop ;; 2B 1u. if(count != 0) goto .pairloop
-
-
-.done:
-;;
-;; Clear MMX state, or else FPU operations will go badly awry.
-;;
- emms
-
- pop ebx
- pop edi
- pop esi
- pop ebp
- ret
-
-.usenonMMX:
- call R_DrawColumn_8_ASM
- jmp .done
-
-
-;;----------------------------------------------------------------------
-;;
-;; R_Draw2sMultiPatchColumn : Like R_DrawColumn, but omits transparent
-;; pixels.
-;;
-;; MMX column drawer.
-;;
-;;----------------------------------------------------------------------
-;; eax = accumulator
-;; ebx = colormap
-;; ecx = count
-;; edx = accumulator
-;; esi = source
-;; edi = dest
-;; ebp = vid.width
-;; mm0 = accumulator
-;; mm1 = heightmask, twice
-;; mm2 = 2 * fracstep, twice
-;; mm3 = pair of consecutive fracs
-;;----------------------------------------------------------------------
-
-
-cglobal R_Draw2sMultiPatchColumn_8_MMX
-R_Draw2sMultiPatchColumn_8_MMX:
- push ebp ;; preserve caller's stack frame pointer
- push esi ;; preserve register variables
- push edi
- push ebx
-
-;;
-;; Our algorithm requires that the texture height be a power of two.
-;; If not, fall back to the non-MMX drawer.
-;;
-.texheightcheck:
- mov edx, [dc_texheight]
- sub edx, 1 ;; edx = heightmask
- test edx, [dc_texheight]
- jnz near .usenonMMX
-
- mov ebp, edx ;; Keep a copy of heightmask in a
- ;; GPR for the time being.
-
-;;
-;; Fill mm1 with heightmask
-;;
- movd mm1, edx ;; low dword = heightmask
- punpckldq mm1, mm1 ;; copy low dword to high dword
-
-;;
-;; dest = ylookup[dc_yl] + columnofs[dc_x];
-;;
- mov eax, [dc_yl]
- mov edi, [ylookup+eax*4]
- mov ebx, [dc_x]
- add edi, [columnofs+ebx*4] ;; edi = dest
-
-
-;;
-;; pixelcount = yh - yl + 1
-;;
- mov ecx, [dc_yh]
- add ecx, 1
- sub ecx, eax ;; pixel count
- jle near .done ;; nothing to scale
-;;
-;; fracstep = dc_iscale;
-;;
- movd mm2, [dc_iscale] ;; fracstep in low dword
- punpckldq mm2, mm2 ;; copy to high dword
-
- mov ebx, [dc_colormap]
- mov esi, [dc_source]
-
-;;
-;; frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep));
-;;
- ;; eax == dc_yl already
- shl eax, FRACBITS
- sub eax, [centeryfrac]
- imul dword [dc_iscale]
- shrd eax, edx, FRACBITS
- add eax, [dc_texturemid]
-
-;;
-;; if (dc_hires) frac = 0;
-;;
- test byte [dc_hires], 0x01
- jz .mod2
- xor eax, eax
-
-
-;;
-;; Do mod-2 pixel.
-;;
-.mod2:
- test ecx, 1
- jz .pairprepare
- mov edx, eax ;; edx = frac
- add eax, [dc_iscale] ;; eax += fracstep
- sar edx, FRACBITS
- and edx, ebp ;; edx &= heightmask
- movzx edx, byte [esi + edx]
- cmp dl, TRANSPARENTPIXEL
- je .nextmod2
- movzx edx, byte [ebx + edx]
- mov [edi], dl
-
-.nextmod2:
- add edi, [vid + viddef_s.width]
- sub ecx, 1
- jz .done
-
-.pairprepare:
-;;
-;; Prepare for the main loop.
-;;
- movd mm3, eax ;; Low dword = frac
- movq mm4, mm3 ;; Copy to intermediate register
- paddd mm4, mm2 ;; dwords of mm4 += fracstep
- punpckldq mm3, mm4 ;; Low dword = first frac, high = second
- pslld mm2, 1 ;; fracstep *= 2
-
-;;
-;; ebp = vid.width
-;;
- mov ebp, [vid + viddef_s.width]
-
- align 16
-.pairloop:
- movq mm0, mm3 ;; 3B 1u.
- psrad mm0, FRACBITS ;; 4B 1u.
- pand mm0, mm1 ;; 3B 1u. frac &= heightmask
- paddd mm3, mm2 ;; 3B 1u. frac += fracstep
-
- movd eax, mm0 ;; 3B 1u. Get first frac
-;; IFETCH boundary
- movzx eax, byte [esi + eax] ;; 4B 1u. Texture map
- punpckhdq mm0, mm0 ;; 3B 1(2)u. low dword = high dword
- movd edx, mm0 ;; 3B 1u. Get second frac
- cmp al, TRANSPARENTPIXEL ;; 2B 1u.
- je .secondinpair ;; 2B 1u.
-;; IFETCH boundary
- movzx eax, byte [ebx + eax] ;; 4B 1u. Colormap
- mov [edi], al ;; 2B 1(2)u. First pixel
-
-.secondinpair:
- movzx edx, byte [esi + edx] ;; 4B 1u. Texture map
- cmp dl, TRANSPARENTPIXEL ;; 2B 1u.
- je .nextpair ;; 2B 1u.
-;; IFETCH boundary
- movzx edx, byte [ebx + edx] ;; 4B 1u. Colormap
- mov [edi + 1*ebp], dl ;; 3B 1(2)u. Second pixel
-
-.nextpair:
- lea edi, [edi + 2*ebp] ;; 3B 1u. edi += 2 * vid.width
- sub ecx, 2 ;; 3B 1u. count -= 2
- jnz .pairloop ;; 2B 1u. if(count != 0) goto .pairloop
-
-
-.done:
-;;
-;; Clear MMX state, or else FPU operations will go badly awry.
-;;
- emms
-
- pop ebx
- pop edi
- pop esi
- pop ebp
- ret
-
-.usenonMMX:
- call R_Draw2sMultiPatchColumn_8_ASM
- jmp .done
-
-
-;;----------------------------------------------------------------------
-;;
-;; R_DrawSpan : 8bpp span drawer
-;;
-;; MMX span drawer.
-;;
-;;----------------------------------------------------------------------
-;; eax = accumulator
-;; ebx = colormap
-;; ecx = count
-;; edx = accumulator
-;; esi = source
-;; edi = dest
-;; ebp = two pixels
-;; mm0 = accumulator
-;; mm1 = xposition
-;; mm2 = yposition
-;; mm3 = 2 * xstep
-;; mm4 = 2 * ystep
-;; mm5 = nflatxshift
-;; mm6 = nflatyshift
-;; mm7 = accumulator
-;;----------------------------------------------------------------------
-
-cglobal R_DrawSpan_8_MMX
-R_DrawSpan_8_MMX:
- push ebp ;; preserve caller's stack frame pointer
- push esi ;; preserve register variables
- push edi
- push ebx
-
-;;
-;; esi = ds_source
-;; ebx = ds_colormap
-;;
- mov esi, [ds_source]
- mov ebx, [ds_colormap]
-
-;;
-;; edi = ylookup[ds_y] + columnofs[ds_x1]
-;;
- mov eax, [ds_y]
- mov edi, [ylookup + eax*4]
- mov edx, [ds_x1]
- add edi, [columnofs + edx*4]
-
-;;
-;; ecx = ds_x2 - ds_x1 + 1
-;;
- mov ecx, [ds_x2]
- sub ecx, edx
- add ecx, 1
-
-;;
-;; Needed for fracs and steps
-;;
- movd mm7, [nflatshiftup]
-
-;;
-;; mm3 = xstep
-;;
- movd mm3, [ds_xstep]
- pslld mm3, mm7
- punpckldq mm3, mm3
-
-;;
-;; mm4 = ystep
-;;
- movd mm4, [ds_ystep]
- pslld mm4, mm7
- punpckldq mm4, mm4
-
-;;
-;; mm1 = pair of consecutive xpositions
-;;
- movd mm1, [ds_xfrac]
- pslld mm1, mm7
- movq mm6, mm1
- paddd mm6, mm3
- punpckldq mm1, mm6
-
-;;
-;; mm2 = pair of consecutive ypositions
-;;
- movd mm2, [ds_yfrac]
- pslld mm2, mm7
- movq mm6, mm2
- paddd mm6, mm4
- punpckldq mm2, mm6
-
-;;
-;; mm5 = nflatxshift
-;; mm6 = nflatyshift
-;;
- movd mm5, [nflatxshift]
- movd mm6, [nflatyshift]
-
-;;
-;; Mask is in memory due to lack of registers.
-;;
- mov eax, [nflatmask]
- mov [nflatmask64], eax
- mov [nflatmask64 + 4], eax
-
-
-;;
-;; Go until we reach a dword boundary.
-;;
-.unaligned:
- test edi, 3
- jz .alignedprep
-.stragglers:
- cmp ecx, 0
- je .done ;; If ecx == 0, we're finished.
-
-;;
-;; eax = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)
-;;
- movq mm0, mm1 ;; mm0 = xposition
- movq mm7, mm2 ;; mm7 = yposition
- paddd mm1, mm3 ;; xposition += xstep (once!)
- paddd mm2, mm4 ;; yposition += ystep (once!)
- psrld mm0, mm5 ;; shift
- psrld mm7, mm6 ;; shift
- pand mm7, [nflatmask64] ;; mask
- por mm0, mm7 ;; or x and y together
-
- movd eax, mm0 ;; eax = index of first pixel
- movzx eax, byte [esi + eax] ;; al = source[eax]
- movzx eax, byte [ebx + eax] ;; al = colormap[al]
-
- mov [edi], al
- add edi, 1
-
- sub ecx, 1
- jmp .unaligned
-
-
-.alignedprep:
-;;
-;; We can double the steps now.
-;;
- pslld mm3, 1
- pslld mm4, 1
-
-
-;;
-;; Generate chunks of four pixels.
-;;
-.alignedloop:
-
-;;
-;; Make sure we have at least four pixels.
-;;
- cmp ecx, 4
- jl .prestragglers
-
-;;
-;; First two pixels.
-;;
- movq mm0, mm1 ;; mm0 = xposition
- movq mm7, mm2 ;; mm7 = yposition
- paddd mm1, mm3 ;; xposition += xstep
- paddd mm2, mm4 ;; yposition += ystep
- psrld mm0, mm5 ;; shift
- psrld mm7, mm6 ;; shift
- pand mm7, [nflatmask64] ;; mask
- por mm0, mm7 ;; or x and y together
-
- movd eax, mm0 ;; eax = index of first pixel
- movzx eax, byte [esi + eax] ;; al = source[eax]
- movzx ebp, byte [ebx + eax] ;; ebp = colormap[al]
-
- punpckhdq mm0, mm0 ;; both dwords = high dword
- movd eax, mm0 ;; eax = index of second pixel
- movzx eax, byte [esi + eax] ;; al = source[eax]
- movzx eax, byte [ebx + eax] ;; al = colormap[al]
- shl eax, 8 ;; get pixel in right byte
- or ebp, eax ;; put pixel in ebp
-
-;;
-;; Next two pixels.
-;;
- movq mm0, mm1 ;; mm0 = xposition
- movq mm7, mm2 ;; mm7 = yposition
- paddd mm1, mm3 ;; xposition += xstep
- paddd mm2, mm4 ;; yposition += ystep
- psrld mm0, mm5 ;; shift
- psrld mm7, mm6 ;; shift
- pand mm7, [nflatmask64] ;; mask
- por mm0, mm7 ;; or x and y together
-
- movd eax, mm0 ;; eax = index of third pixel
- movzx eax, byte [esi + eax] ;; al = source[eax]
- movzx eax, byte [ebx + eax] ;; al = colormap[al]
- shl eax, 16 ;; get pixel in right byte
- or ebp, eax ;; put pixel in ebp
-
- punpckhdq mm0, mm0 ;; both dwords = high dword
- movd eax, mm0 ;; eax = index of second pixel
- movzx eax, byte [esi + eax] ;; al = source[eax]
- movzx eax, byte [ebx + eax] ;; al = colormap[al]
- shl eax, 24 ;; get pixel in right byte
- or ebp, eax ;; put pixel in ebp
-
-;;
-;; Write pixels.
-;;
- mov [edi], ebp
- add edi, 4
-
- sub ecx, 4
- jmp .alignedloop
-
-.prestragglers:
-;;
-;; Back to one step at a time.
-;;
- psrad mm3, 1
- psrad mm4, 1
- jmp .stragglers
-
-.done:
-;;
-;; Clear MMX state, or else FPU operations will go badly awry.
-;;
- emms
-
- pop ebx
- pop edi
- pop esi
- pop ebp
- ret
diff --git a/src/tmap_vc.nas b/src/tmap_vc.nas
deleted file mode 100644
index 49eb21a6d..000000000
--- a/src/tmap_vc.nas
+++ /dev/null
@@ -1,48 +0,0 @@
-;; SONIC ROBO BLAST 2
-;;-----------------------------------------------------------------------------
-;; Copyright (C) 1998-2000 by DooM Legacy Team.
-;; Copyright (C) 1999-2020 by Sonic Team Junior.
-;;
-;; This program is free software distributed under the
-;; terms of the GNU General Public License, version 2.
-;; See the 'LICENSE' file for more details.
-;;-----------------------------------------------------------------------------
-;; FILE:
-;; tmap_vc.nas
-;; DESCRIPTION:
-;; Assembler optimised math code for Visual C++.
-
-
-[BITS 32]
-
-%macro cglobal 1
-%define %1 _%1
-[global %1]
-%endmacro
-
-[SECTION .text write]
-
-;----------------------------------------------------------------------------
-;fixed_t FixedMul (fixed_t a, fixed_t b)
-;----------------------------------------------------------------------------
-cglobal FixedMul
-; align 16
-FixedMul:
- mov eax,[esp+4]
- imul dword [esp+8]
- shrd eax,edx,16
- ret
-
-;----------------------------------------------------------------------------
-;fixed_t FixedDiv2 (fixed_t a, fixed_t b);
-;----------------------------------------------------------------------------
-cglobal FixedDiv2
-; align 16
-FixedDiv2:
- mov eax,[esp+4]
- mov edx,eax ;; these two instructions allow the next
- sar edx,31 ;; two to pair, on the Pentium processor.
- shld edx,eax,16
- sal eax,16
- idiv dword [esp+8]
- ret
diff --git a/src/v_video.c b/src/v_video.c
index b372b288c..ff1e6b75c 100644
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -489,12 +489,6 @@ static void CV_palette_OnChange(void)
V_SetPalette(0);
}
-#if defined (__GNUC__) && defined (__i386__) && !defined (NOASM) && !defined (__APPLE__) && !defined (NORUSEASM)
-void VID_BlitLinearScreen_ASM(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT32 height, size_t srcrowbytes,
- size_t destrowbytes);
-#define HAVE_VIDCOPY
-#endif
-
static void CV_constextsize_OnChange(void)
{
if (!con_startup)
@@ -508,9 +502,6 @@ static void CV_constextsize_OnChange(void)
void VID_BlitLinearScreen(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT32 height, size_t srcrowbytes,
size_t destrowbytes)
{
-#ifdef HAVE_VIDCOPY
- VID_BlitLinearScreen_ASM(srcptr,destptr,width,height,srcrowbytes,destrowbytes);
-#else
if ((srcrowbytes == destrowbytes) && (srcrowbytes == (size_t)width))
M_Memcpy(destptr, srcptr, srcrowbytes * height);
else
@@ -523,7 +514,6 @@ void VID_BlitLinearScreen(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT3
srcptr += srcrowbytes;
}
}
-#endif
}
void V_AdjustXYWithSnap(INT32 *x, INT32 *y, UINT32 options, INT32 dupx, INT32 dupy)
diff --git a/src/win32ce/Srb2win.ico b/src/win32ce/Srb2win.ico
deleted file mode 100644
index 4e3f81336..000000000
Binary files a/src/win32ce/Srb2win.ico and /dev/null differ
diff --git a/src/win32ce/win_dbg.c b/src/win32ce/win_dbg.c
deleted file mode 100644
index 45b2fc322..000000000
--- a/src/win32ce/win_dbg.c
+++ /dev/null
@@ -1,629 +0,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) 1998-2000 by DooM Legacy Team.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//-----------------------------------------------------------------------------
-/// \file
-/// \brief Sources from GameDeveloper magazine article, January 1998, by Bruce Dawson.
-/// this source file contains the exception handler for recording error
-/// information after crashes.
-
-#include
-#include "win_main.h"
-#include "../doomdef.h" //just for VERSION
-#include "win_dbg.h"
-#include "../m_argv.h" //print the parameter in the log
-
-
-#define NumCodeBytes 16 // Number of code bytes to record.
-#define MaxStackDump 2048 // Maximum number of DWORDS in stack dumps.
-#define StackColumns 8 // Number of columns in stack dump.
-
-#define ONEK 1024
-#define SIXTYFOURK (64*ONEK)
-#define ONEM (ONEK*ONEK)
-#define ONEG (ONEK*ONEK*ONEK)
-
-
-// --------------------------------------------------------------------------
-// return a description for an ExceptionCode
-// --------------------------------------------------------------------------
-static LPCSTR GetExceptionDescription (DWORD ExceptionCode)
-{
- unsigned int i;
-
- struct ExceptionNames
- {
- DWORD ExceptionCode;
- LPCSTR ExceptionName;
- };
-
- struct ExceptionNames ExceptionMap[] =
- {
- {EXCEPTION_ACCESS_VIOLATION, "an Access Violation"},
- {EXCEPTION_ARRAY_BOUNDS_EXCEEDED, "a Array Bounds Exceeded"},
- {EXCEPTION_BREAKPOINT, "a Breakpoint"},
- {EXCEPTION_DATATYPE_MISALIGNMENT, "a Datatype Misalignment"},
- {EXCEPTION_FLT_DENORMAL_OPERAND, "a Float Denormal Operand"},
- {EXCEPTION_FLT_DIVIDE_BY_ZERO, "a Float Divide By Zero"},
- {EXCEPTION_FLT_INEXACT_RESULT, "a Float Inexact Result"},
- {EXCEPTION_FLT_INVALID_OPERATION, "a Float Invalid Operation"},
- {EXCEPTION_FLT_OVERFLOW, "a Float Overflow"},
- {EXCEPTION_FLT_STACK_CHECK, "a Float Stack Check"},
- {EXCEPTION_FLT_UNDERFLOW, "a Float Underflow"},
- {EXCEPTION_ILLEGAL_INSTRUCTION, "an Illegal Instruction"},
- {EXCEPTION_IN_PAGE_ERROR, "an In Page Error"},
- {EXCEPTION_INT_DIVIDE_BY_ZERO, "an Integer Divide By Zero"},
- {EXCEPTION_INT_OVERFLOW, "an Integer Overflow"},
- {EXCEPTION_INVALID_DISPOSITION, "an Invalid Disposition"},
- {EXCEPTION_NONCONTINUABLE_EXCEPTION, "Noncontinuable Exception"},
- {EXCEPTION_PRIV_INSTRUCTION, "a Privileged Instruction"},
- {EXCEPTION_SINGLE_STEP, "a Single Step"},
- {EXCEPTION_STACK_OVERFLOW, "a Stack Overflow"},
- {0x40010005, "a Control-C"},
- {0x40010008, "a Control-Break"},
- {0xc0000006, "an In Page Error"},
- {0xc0000017, "a No Memory"},
- {0xc000001d, "an Illegal Instruction"},
- {0xc0000025, "a Noncontinuable Exception"},
- {0xc0000142, "a DLL Initialization Failed"},
- {0xe06d7363, "a Microsoft C++ Exception"},
- };
-
- for (i = 0; i < (sizeof (ExceptionMap) / sizeof (ExceptionMap[0])); i++)
- if (ExceptionCode == ExceptionMap[i].ExceptionCode)
- return ExceptionMap[i].ExceptionName;
-
- return "Unknown exception type";
-}
-
-
-// --------------------------------------------------------------------------
-// Directly output a formatted string to the errorlog file, using win32 funcs
-// --------------------------------------------------------------------------
-static VOID FPrintf (HANDLE fileHandle, LPCSTR lpFmt, ...)
-{
- CHAR str[1999];
- va_list arglist;
- DWORD bytesWritten;
-
- va_start (arglist, lpFmt);
- vsprintf (str, lpFmt, arglist);
- va_end (arglist);
-
- WriteFile (fileHandle, str, (DWORD)strlen(str), &bytesWritten, NULL);
-}
-
-// --------------------------------------------------------------------------
-// Print the specified FILETIME to output in a human readable format,
-// without using the C run time.
-// --------------------------------------------------------------------------
-static VOID PrintTime (LPSTR output, FILETIME TimeToPrint)
-{
- WORD Date, Time;
- if (FileTimeToLocalFileTime (&TimeToPrint, &TimeToPrint) &&
- FileTimeToDosDateTime (&TimeToPrint, &Date, &Time))
- {
- // What a silly way to print out the file date/time.
- wsprintfA(output, "%d/%d/%d %02d:%02d:%02d",
- (Date / 32) & 15, Date & 31, (Date / 512) + 1980,
- (Time / 2048), (Time / 32) & 63, (Time & 31) * 2);
- }
- else
- output[0] = 0;
-}
-
-
-static LPTSTR GetFilePart(LPTSTR source)
-{
- LPTSTR result = _tcsrchr(source, '\\');
- if (result)
- result++;
- else
- result = source;
- return result;
-}
-
-// --------------------------------------------------------------------------
-// Print information about a code module (DLL or EXE) such as its size,
-// location, time stamp, etc.
-// --------------------------------------------------------------------------
-static VOID ShowModuleInfo(HANDLE LogFile, HMODULE ModuleHandle)
-{
- CHAR ModName[MAX_PATH];
- IMAGE_DOS_HEADER *DosHeader;
- IMAGE_NT_HEADERS *NTHeader;
- HANDLE ModuleFile;
- CHAR TimeBuffer[100] = "";
- DWORD FileSize = 0;
-#ifdef NO_SEH_MINGW
- __try1(EXCEPTION_EXECUTE_HANDLER)
-#else
- __try
-#endif
- {
- if (GetModuleFileNameA(ModuleHandle, ModName, sizeof (ModName)) > 0)
- {
- // If GetModuleFileName returns greater than zero then this must
- // be a valid code module address. Therefore we can try to walk
- // our way through its structures to find the link time stamp.
- DosHeader = (IMAGE_DOS_HEADER*)ModuleHandle;
- if (IMAGE_DOS_SIGNATURE != DosHeader->e_magic)
- return;
- NTHeader = (IMAGE_NT_HEADERS*)((char *)DosHeader
- + DosHeader->e_lfanew);
- if (IMAGE_NT_SIGNATURE != NTHeader->Signature)
- return;
- // Open the code module file so that we can get its file date
- // and size.
- ModuleFile = CreateFileA(ModName, GENERIC_READ,
- FILE_SHARE_READ, 0, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL, 0);
- if (ModuleFile != INVALID_HANDLE_VALUE)
- {
- FILETIME LastWriteTime;
- FileSize = GetFileSize(ModuleFile, 0);
- if (GetFileTime(ModuleFile, 0, 0, &LastWriteTime))
- {
- wsprintfA(TimeBuffer, " - file date is ");
- PrintTime(TimeBuffer + strlen(TimeBuffer), LastWriteTime);
- }
- CloseHandle(ModuleFile);
- }
- FPrintf (LogFile, "%s, loaded at 0x%08x - %d bytes - %08x%s\r\n",
- ModName, ModuleHandle, FileSize,
- NTHeader->FileHeader.TimeDateStamp, TimeBuffer);
- }
- }
- // Handle any exceptions by continuing from this point.
-#ifdef NO_SEH_MINGW
- __except1
-#else
- __except(EXCEPTION_EXECUTE_HANDLER)
-#endif
- {
- }
-}
-
-// --------------------------------------------------------------------------
-// Scan memory looking for code modules (DLLs or EXEs). VirtualQuery is used
-// to find all the blocks of address space that were reserved or committed,
-// and ShowModuleInfo will display module information if they are code
-// modules.
-// --------------------------------------------------------------------------
-static VOID RecordModuleList(HANDLE LogFile)
-{
- SYSTEM_INFO SystemInfo;
- size_t PageSize;
- size_t NumPages;
- size_t pageNum = 0;
- LPVOID LastAllocationBase = 0;
-
- FPrintf (LogFile, "\r\n"
- "\tModule list: names, addresses, sizes, time stamps "
- "and file times:\r\n");
-
- // Set NumPages to the number of pages in the 4GByte address space,
- // while being careful to avoid overflowing ints.
- GetSystemInfo(&SystemInfo);
- PageSize = SystemInfo.dwPageSize;
- NumPages = 4 * (unsigned int)(ONEG / PageSize);
- while (pageNum < NumPages)
- {
- MEMORY_BASIC_INFORMATION MemInfo;
- if (VirtualQuery((LPVOID)(pageNum * PageSize), &MemInfo,
- sizeof (MemInfo)))
- {
- if (MemInfo.RegionSize > 0)
- {
- // Adjust the page number to skip over this block of memory.
- pageNum += MemInfo.RegionSize / PageSize;
- if (MemInfo.State == MEM_COMMIT && MemInfo.AllocationBase >
- LastAllocationBase)
- {
- // Look for new blocks of committed memory, and try
- // recording their module names - this will fail
- // gracefully if they aren't code modules.
- LastAllocationBase = MemInfo.AllocationBase;
- ShowModuleInfo(LogFile, (HMODULE)LastAllocationBase);
- }
- }
- else
- pageNum += SIXTYFOURK / PageSize;
- }
- else
- pageNum += SIXTYFOURK / PageSize;
- // If VirtualQuery fails we advance by 64K because that is the
- // granularity of address space doled out by VirtualAlloc().
- }
-}
-
-
-// --------------------------------------------------------------------------
-// Record information about the user's system, such as processor type, amount
-// of memory, etc.
-// --------------------------------------------------------------------------
-static VOID RecordSystemInformation(HANDLE fileHandle)
-{
- FILETIME CurrentTime;
- CHAR TimeBuffer[100];
- CHAR ModuleName[MAX_PATH];
- CHAR UserName[200];
- DWORD UserNameSize;
- SYSTEM_INFO SystemInfo;
- MEMORYSTATUS MemInfo;
-
- GetSystemTimeAsFileTime (&CurrentTime);
- PrintTime (TimeBuffer, CurrentTime);
- FPrintf(fileHandle, "Error occurred at %s.\r\n", TimeBuffer);
-
- if (GetModuleFileNameA(NULL, ModuleName, sizeof (ModuleName)) <= 0)
- strcpy (ModuleName, "Unknown");
- UserNameSize = sizeof (UserName);
- if (!GetUserNameA(UserName, &UserNameSize))
- strcpy (UserName, "Unknown");
- FPrintf(fileHandle, "%s, run by %s.\r\n", ModuleName, UserName);
-
- GetSystemInfo (&SystemInfo);
- FPrintf (fileHandle, "%d processor(s), type %d %d.%d.\r\n"
- "Program Memory from 0x%p to 0x%p\r\n",
- SystemInfo.dwNumberOfProcessors,
- SystemInfo.dwProcessorType,
- SystemInfo.wProcessorLevel,
- SystemInfo.wProcessorRevision,
- SystemInfo.lpMinimumApplicationAddress,
- SystemInfo.lpMaximumApplicationAddress);
-
- MemInfo.dwLength = sizeof (MemInfo);
- GlobalMemoryStatus(&MemInfo);
- // Print out the amount of physical memory, rounded up.
- FPrintf(fileHandle, "%d MBytes physical memory.\r\n", (MemInfo.dwTotalPhys +
- ONEM - 1) / ONEM);
-}
-
-// --------------------------------------------------------------------------
-// What we do here is trivial : open a file, write out the register information
-// from the PEXCEPTION_POINTERS structure, then return EXCEPTION_CONTINUE_SEARCH
-// whose magic value tells Win32 to proceed with its normal error handling
-// mechanism. This is important : an error dialog will popup if possible and
-// the debugger will hopefully coexist peacefully with the structured exception
-// handler.
-// --------------------------------------------------------------------------
-int __cdecl RecordExceptionInfo (PEXCEPTION_POINTERS data/*, LPCSTR Message, LPSTR lpCmdLine*/)
-{
- PEXCEPTION_RECORD Exception;
- PCONTEXT Context;
- TCHAR ModuleName[MAX_PATH];
- TCHAR FileName[MAX_PATH] = TEXT("Unknown");
- LPTSTR FilePart, lastperiod;
- TCHAR CrashModulePathName[MAX_PATH];
- LPCTSTR CrashModuleFileName = TEXT("Unknown");
- MEMORY_BASIC_INFORMATION MemInfo;
- static int BeenHere = false;
- HANDLE fileHandle;
- UINT8 *code;
- int codebyte,i;
-
- if (data)
- {
- Exception = data->ExceptionRecord;
- Context = data->ContextRecord;
- }
- else
- {
- return EXCEPTION_CONTINUE_SEARCH;
- }
-
- if (BeenHere) // Going recursive! That must mean this routine crashed!
- return EXCEPTION_CONTINUE_SEARCH;
- BeenHere = true;
-
- // Create a filename to record the error information to.
- // Store it in the executable directory.
- if (GetModuleFileName(NULL, ModuleName, sizeof (ModuleName)) <= 0)
- ModuleName[0] = 0;
- FilePart = GetFilePart(ModuleName);
-
- // Extract the file name portion and remove it's file extension. We'll
- // use that name shortly.
- lstrcpy (FileName, FilePart);
- lastperiod = _tcsrchr (FileName, '.');
- if (lastperiod)
- lastperiod[0] = 0;
- // Replace the executable filename with our error log file name.
- lstrcpy (FilePart, TEXT("errorlog.txt"));
- fileHandle = CreateFile (ModuleName, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);
- if (fileHandle == INVALID_HANDLE_VALUE)
- {
- OutputDebugString (TEXT("Error creating exception report"));
- return EXCEPTION_CONTINUE_SEARCH;
- }
-
- // Append to the error log.
- SetFilePointer (fileHandle, 0, 0, FILE_END);
-
- // Print out some blank lines to separate this error log from any previous ones.
- FPrintf (fileHandle, "Email Sonic Team Junior so we can fix the bugs\r\n"); // Tails
- FPrintf (fileHandle, "Make sure you tell us what you were doing to cause the crash, and if possible, record a demo!\r\n"); // Tails
- FPrintf (fileHandle, "\r\n\r\n\r\n\r\n");
- FPrintf (fileHandle, "SRB2Kart %s -ERROR LOG-\r\n\r\n", VERSIONSTRING);
- FPrintf (fileHandle, "\r\n");
- // VirtualQuery can be used to get the allocation base associated with a
- // code address, which is the same as the ModuleHandle. This can be used
- // to get the filename of the module that the crash happened in.
- if (VirtualQuery ((LPVOID)(size_t)Context->Eip, &MemInfo, sizeof (MemInfo)) &&
- GetModuleFileName ((HMODULE)MemInfo.AllocationBase,
- CrashModulePathName,
- sizeof (CrashModulePathName)) > 0)
- CrashModuleFileName = GetFilePart(CrashModulePathName);
-
- // Print out the beginning of the error log in a Win95 error window
- // compatible format.
- FPrintf (fileHandle, "%s caused an %s in module %s at %04x:%08x.\r\n",
- FileName, GetExceptionDescription(Exception->ExceptionCode),
- CrashModuleFileName, Context->SegCs, Context->Eip);
- //if (&Message = Null)
- FPrintf (fileHandle, "Exception handler called in %s.\r\n", "main thread");
- //else
- //FPrintf (fileHandle, "Exception handler called in %s.\r\n", Message);
-
- RecordSystemInformation (fileHandle);
-
- // If the exception was an access violation, print out some additional
- // information, to the error log and the debugger.
- if (Exception->ExceptionCode == STATUS_ACCESS_VIOLATION &&
- Exception->NumberParameters >= 2)
- {
- TCHAR DebugMessage[1000];
- LPCTSTR readwrite = TEXT("Read from");
- if (Exception->ExceptionInformation[0])
- readwrite = TEXT("Write to");
- wsprintf(DebugMessage, TEXT("%s location %08x caused an access violation.\r\n"),
- readwrite, Exception->ExceptionInformation[1]);
-#ifdef _DEBUG
- // The VisualC++ debugger doesn't actually tell you whether a read
- // or a write caused the access violation, nor does it tell what
- // address was being read or written. So I fixed that.
- OutputDebugString(TEXT("Exception handler: "));
- OutputDebugString(DebugMessage);
-#endif
- FPrintf(fileHandle, "%s", DebugMessage);
- }
-
- FPrintf(fileHandle, "\r\n");
-
- // Print out the register values in a Win95 error window compatible format.
- if ((Context->ContextFlags & CONTEXT_FULL) == CONTEXT_FULL)
- {
- FPrintf (fileHandle, "Registers:\r\n");
- FPrintf (fileHandle, "EAX=%.8lx CS=%.4x EIP=%.8lx EFLGS=%.8lx\r\n",
- Context->Eax,Context->SegCs,Context->Eip,Context->EFlags);
- FPrintf (fileHandle, "EBX=%.8lx SS=%.4x ESP=%.8lx EBP=%.8lx\r\n",
- Context->Ebx,Context->SegSs,Context->Esp,Context->Ebp);
- FPrintf (fileHandle, "ECX=%.8lx DS=%.4x ESI=%.8lx FS=%.4x\r\n",
- Context->Ecx,Context->SegDs,Context->Esi,Context->SegFs);
- FPrintf (fileHandle, "EDX=%.8lx ES=%.4x EDI=%.8lx GS=%.4x\r\n",
- Context->Edx,Context->SegEs,Context->Edi,Context->SegGs);
- }
-
- // moved down because it was causing the printout to stop
- FPrintf (fileHandle, "Command Line parameters: ");
- for (i = 1;i < myargc;i++)
- FPrintf (fileHandle, "%s ", myargv[i]);
-
- FPrintf (fileHandle, "Bytes at CS : EIP:\r\n");
-
- // Print out the bytes of code at the instruction pointer. Since the
- // crash may have been caused by an instruction pointer that was bad,
- // this code needs to be wrapped in an exception handler, in case there
- // is no memory to read. If the dereferencing of code[] fails, the
- // exception handler will print '??'.
- code = (UINT8 *)(size_t)Context->Eip;
- for (codebyte = 0; codebyte < NumCodeBytes; codebyte++)
- {
-#ifdef NO_SEH_MINGW
- __try1(EXCEPTION_EXECUTE_HANDLER)
-#else
- __try
-#endif
- {
- FPrintf (fileHandle, "%02x ", code[codebyte]);
- }
-#ifdef NO_SEH_MINGW
- __except1
-#else
- __except(EXCEPTION_EXECUTE_HANDLER)
-#endif
- {
- FPrintf (fileHandle, "?? ");
- }
- }
-
- // Time to print part or all of the stack to the error log. This allows
- // us to figure out the call stack, parameters, local variables, etc.
- FPrintf (fileHandle, "\r\n"
- "Stack dump:\r\n");
-#ifdef NO_SEH_MINGW
- __try1(EXCEPTION_EXECUTE_HANDLER)
-#else
- __try
-#endif
- {
- // Esp contains the bottom of the stack, or at least the bottom of
- // the currently used area.
- DWORD* pStack = (DWORD *)(size_t)Context->Esp;
- DWORD* pStackTop = NULL;
- size_t Count = 0;
- TCHAR buffer[1000] = TEXT("");
- const int safetyzone = 50;
- LPTSTR nearend = buffer + sizeof (buffer) - safetyzone*sizeof (TCHAR);
- LPTSTR output = buffer;
- const void *Suffix;
-
- // Load the top (highest address) of the stack from the
- // thread information block. It will be found there in
- // Win9x and Windows NT.
-#ifdef __GNUC__
- __asm__("movl %%fs : 4, %%eax": "=a"(pStackTop));
-#else
- __asm
- {
- mov eax, fs:[4]
- mov pStackTop, eax
- }
-#endif
- if (pStackTop == NULL)
- goto StackSkip;
- else if (pStackTop > pStack + MaxStackDump)
- pStackTop = pStack + MaxStackDump;
- // Too many calls to WriteFile can take a long time, causing
- // confusing delays when programs crash. Therefore I implemented
- // simple buffering for the stack dumping code instead of calling
- // FPrintf directly.
- while (pStack + 1 <= pStackTop)
- {
- if ((Count % StackColumns) == 0)
- output += wsprintf(output, TEXT("%08x: "), pStack);
- if ((++Count % StackColumns) == 0 || pStack + 2 > pStackTop)
- Suffix = TEXT("\r\n");
- else
- Suffix = TEXT(" ");
- output += wsprintf(output, TEXT("%08x%s"), *pStack, Suffix);
- pStack++;
- // Check for when the buffer is almost full, and flush it to disk.
- if (output > nearend)
- {
- FPrintf (fileHandle, "%s", buffer);
- buffer[0] = 0;
- output = buffer;
- }
- }
- // Print out any final characters from the cache.
- StackSkip:
- FPrintf (fileHandle, "%s", buffer);
- }
-#ifdef NO_SEH_MINGW
- __except1
-#else
- __except(EXCEPTION_EXECUTE_HANDLER)
-#endif
- {
- FPrintf(fileHandle, "Exception encountered during stack dump.\r\n");
- }
-
- RecordModuleList (fileHandle);
-
- CloseHandle (fileHandle);
-
- // Return the magic value which tells Win32 that this handler didn't
- // actually handle the exception - so that things will proceed as per
- // normal.
- //BP: should put message for end user to send this file to fix any bug
- return EXCEPTION_CONTINUE_SEARCH;
-}
-
- /*
- //
- //FPrintf ("e-mail this file to legacy@newdoom.com, so that we can fix the problem.\r\n\r\n");
-
- FPrintf ("Exception handler called in %s.\r\n", Message);
-
- GetSystemTime (&systemTime);
- FPrintf ("Error occured at %02d/%02d/%04d %02d:%02d:%02d.\r\n",
- systemTime.wMonth, systemTime.wDay, systemTime.wYear,
- systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
-
-
- FPrintf ("%s\r\n", filename);
- FPrintf ("Cmd-line: %s\r\n", lpCmdLine);
-
- // Nested exceptions can occur, get info for each one
-
- nER = 1;
- while (ER)
- {
- if (nER++>1)
- FPrintf ("Exception Record %d.\r\n", nER);
-
- FPrintf ("application caused an %s", GetExceptionCodeStr(Exception->ExceptionCode));
-
- if (Context->ContextFlags & CONTEXT_CONTROL)
- FPrintf (" at %.4x:%.8x.\r\n", Context->SegCs, Context->Eip);
-
- // in case of..
- if (Context->Eip != (unsigned long)Exception->ExceptionAddress)
- FPrintf ("Exception Address = %.8x\r\n", Exception->ExceptionAddress);
-
- if (Exception->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
- {
- FPrintf ("\r\n%s location 0x%x caused an access violation.\r\n",
- (Exception->ExceptionInformation[0] ? "Write to" : "Read from"),
- Exception->ExceptionInformation[1]);
- }
-
- ER = Exception->ExceptionRecord;
- }
-
-
- if (Context->ContextFlags & CONTEXT_DEBUG_REGISTERS)
- {
- FPrintf ("\r\nDebug Registers:\r\n");
- FPrintf ("Dr0=%.8x Dr1=%.8x Dr2=%.8x\r\n"
- "Dr3=%.8x Dr6=%.8x Dr7=%.8x\r\n",
- Context->Dr0, Context->Dr1, Context->Dr2,
- Context->Dr3, Context->Dr6, Context->Dr7);
- }
-
- if (Context->ContextFlags & CONTEXT_FLOATING_POINT)
- {
- FPrintf ("\r\nFloating Save Area:\r\n");
- FPrintf ("ControlWord =%.8x TagWord =%.8x ErrorSelector=%.8x DataSelector =%.8x\r\n"
- "StatusWord =%.8x ErrorOffset =%.8x DataOffset =%.8x Cr0NpxState =%.8x\r\n",
- Context->FloatSave.ControlWord, Context->FloatSave.TagWord, Context->FloatSave.ErrorSelector, Context->FloatSave.DataSelector,
- Context->FloatSave.StatusWord, Context->FloatSave.ErrorOffset, Context->FloatSave.DataOffset, Context->FloatSave.Cr0NpxState
- );
-
- //BYTE RegisterArea[SIZE_OF_80387_REGISTERS];
- }
-
-
- // in case of...
- if ((Context->ContextFlags & CONTEXT_FULL) != CONTEXT_FULL)
- {
- if (!(Context->ContextFlags & CONTEXT_SEGMENTS))
- FPrintf ("Note! GS,FS,ES,DS are unspecified\r\n");
- if (!(Context->ContextFlags & CONTEXT_INTEGER))
- FPrintf ("Note! EDI,ESI,EBX,EDX,ECX,EAX are unspecified\r\n");
- if (!(Context->ContextFlags & CONTEXT_CONTROL))
- FPrintf ("Note! EBP,CS : EIP,EFlags,SS : ESP are unspecified\r\n");
- }
-
- FPrintf ("\r\nBytes at CS : EIP:\r\n");
- ucptr = (UINT8 *)Context->Eip;
- for (i = 0; i < 16; i++)
- FPrintf ("%.2x ", *ucptr++);
-
- FPrintf ("\r\n\r\nStack dump:\r\n");
- ulptr = (unsigned long*)Context->Esp;
- for (i = 0; i < 16; i++)
- FPrintf ("%.8x ", *ulptr++);
-
- //FPrintf ("Bytes at CS : EIP:\r\n");
- //FPrintf ("%.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x ");
-
- for (i = 0; i < 16; i++)
- {
- FPrintf ("%x
- }
-*/
diff --git a/src/win32ce/win_dll.c b/src/win32ce/win_dll.c
deleted file mode 100644
index 2bda7126d..000000000
--- a/src/win32ce/win_dll.c
+++ /dev/null
@@ -1,118 +0,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) 1998-2000 by DooM Legacy Team.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//-----------------------------------------------------------------------------
-/// \file
-/// \brief load and initialise the 3D driver DLL
-
-#include "../doomdef.h"
-
-#ifdef HW3SOUND
-#include "../hardware/hw3dsdrv.h" // get the 3D sound driver DLL export prototypes
-#endif
-
-#include "win_dll.h"
-#include "win_main.h" // I_GetLastErrorMsgBox()
-
-#if defined(HW3SOUND)
-typedef struct loadfunc_s {
- LPCSTR fnName;
- LPVOID fnPointer;
-} loadfunc_t;
-
-// --------------------------------------------------------------------------
-// Load a DLL, returns the HMODULE handle or NULL
-// --------------------------------------------------------------------------
-static inline HMODULE LoadDLL (LPCSTR dllName, loadfunc_t *funcTable)
-{
- LPVOID funcPtr;
- loadfunc_t *loadfunc;
- HMODULE hModule;
-
- if ((hModule = LoadLibraryA(dllName)) != NULL)
- {
- // get function pointers for all functions we use
- for (loadfunc = funcTable; loadfunc->fnName != NULL; loadfunc++)
- {
- funcPtr = GetProcAddress(hModule, loadfunc->fnName);
- if (!funcPtr) {
- //I_GetLastErrorMsgBox ();
- MessageBoxA(NULL, va("The '%s' haven't the good specification (function %s missing)\n\n"
- "You must use dll from the same zip of this exe\n", dllName, loadfunc->fnName),
- "Error", MB_OK|MB_ICONINFORMATION);
- return FALSE;
- }
- // store function address
- *((LPVOID*)loadfunc->fnPointer) = funcPtr;
- }
- }
- else
- {
- MessageBoxA(NULL, va("LoadLibrary() FAILED : couldn't load '%s'\r\n", dllName), "Warning", MB_OK|MB_ICONINFORMATION);
- //I_GetLastErrorMsgBox ();
- }
-
- return hModule;
-}
-
-
-// --------------------------------------------------------------------------
-// Unload the DLL
-// --------------------------------------------------------------------------
-static inline VOID UnloadDLL (HMODULE* pModule)
-{
- if (FreeLibrary(*pModule))
- *pModule = NULL;
- else
- I_GetLastErrorMsgBox ();
-}
-#endif
-
-#ifdef HW3SOUND
-static HMODULE hwsModule = NULL;
-
-static loadfunc_t hwsFuncTable[] = {
- {"_Startup@8", &hw3ds_driver.pfnStartup},
- {"_Shutdown@0", &hw3ds_driver.pfnShutdown},
- {"_AddSfx@4", &hw3ds_driver.pfnAddSfx},
- {"_AddSource@8", &hw3ds_driver.pfnAddSource},
- {"_StartSource@4", &hw3ds_driver.pfnStartSource},
- {"_StopSource@4", &hw3ds_driver.pfnStopSource},
- {"_GetHW3DSVersion@0", &hw3ds_driver.pfnGetHW3DSVersion},
- {"_BeginFrameUpdate@0", &hw3ds_driver.pfnBeginFrameUpdate},
- {"_EndFrameUpdate@0", &hw3ds_driver.pfnEndFrameUpdate},
- {"_IsPlaying@4", &hw3ds_driver.pfnIsPlaying},
- {"_UpdateListener@8", &hw3ds_driver.pfnUpdateListener},
- {"_UpdateSourceParms@12", &hw3ds_driver.pfnUpdateSourceParms},
- {"_SetCone@8", &hw3ds_driver.pfnSetCone},
- {"_SetGlobalSfxVolume@4", &hw3ds_driver.pfnSetGlobalSfxVolume},
- {"_Update3DSource@8", &hw3ds_driver.pfnUpdate3DSource},
- {"_ReloadSource@8", &hw3ds_driver.pfnReloadSource},
- {"_KillSource@4", &hw3ds_driver.pfnKillSource},
- {"_KillSfx@4", &hw3ds_driver.pfnKillSfx},
- {"_GetHW3DSTitle@8", &hw3ds_driver.pfnGetHW3DSTitle},
- {NULL, NULL}
-};
-
-BOOL Init3DSDriver(LPCSTR dllName)
-{
- hwsModule = LoadDLL(dllName, hwsFuncTable);
- return (hwsModule != NULL);
-}
-
-VOID Shutdown3DSDriver (VOID)
-{
- UnloadDLL(&hwsModule);
-}
-#endif
diff --git a/src/win32ce/win_dll.h b/src/win32ce/win_dll.h
deleted file mode 100644
index f69a8c21f..000000000
--- a/src/win32ce/win_dll.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) 1998-2000 by DooM Legacy Team.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//-----------------------------------------------------------------------------
-/// \file
-/// \brief load/unload a DLL at run-time
-
-//#define WIN32_LEAN_AND_MEAN
-#define RPC_NO_WINDOWS_H
-#include
-
-#ifdef HW3SOUND
-BOOL Init3DSDriver(LPCSTR dllName);
-VOID Shutdown3DSDriver(VOID);
-#endif
diff --git a/src/win32ce/win_main.c b/src/win32ce/win_main.c
deleted file mode 100644
index fe4147291..000000000
--- a/src/win32ce/win_main.c
+++ /dev/null
@@ -1,539 +0,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) 1998-2000 by DooM Legacy Team.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//-----------------------------------------------------------------------------
-/// \file
-/// \brief Win32 WinMain Entry Point
-///
-/// Win32 Sonic Robo Blast 2
-///
-/// NOTE:
-/// To compile WINDOWS SRB2 version : define a '_WINDOWS' symbol.
-/// to do this go to Project/Settings/ menu, click C/C++ tab, in
-/// 'Preprocessor definitions:' add '_WINDOWS'
-
-#include "../doomdef.h"
-#include
-
-#include "../doomstat.h" // netgame
-#include "resource.h"
-
-#include "../m_argv.h"
-#include "../d_main.h"
-#include "../i_system.h"
-
-#include "../keys.h" //hack quick test
-
-#include "../console.h"
-
-#include "fabdxlib.h"
-#include "win_main.h"
-#include "win_dbg.h"
-#include "../i_sound.h" // midi pause/unpause
-#include "../g_input.h" // KEY_MOUSEWHEELxxx
-
-// MSWheel support for Win95/NT3.51
-#include
-
-#ifndef WM_XBUTTONDOWN
-#define WM_XBUTTONDOWN 523
-#endif
-#ifndef WM_XBUTTONUP
-#define WM_XBUTTONUP 524
-#endif
-#ifndef MK_XBUTTON1
-#define MK_XBUTTON1 32
-#endif
-#ifndef MK_XBUTTON2
-#define MK_XBUTTON2 64
-#endif
-
-typedef BOOL (WINAPI *MyFunc)(VOID);
-
-HINSTANCE myInstance = NULL;
-HWND hWndMain = NULL;
-static HCURSOR windowCursor = NULL; // main window cursor
-
-boolean appActive = false; // app window is active
-
-#ifdef LOGMESSAGES
-// this is were I log debug text, cons_printf, I_error ect for window port debugging
-HANDLE logstream;
-#endif
-
-BOOL nodinput = FALSE;
-
-static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- event_t ev; //Doom input event
- int mouse_keys;
-
- // judgecutor:
- // Response MSH Mouse Wheel event
-
- if (message == MSHWheelMessage)
- {
- message = WM_MOUSEWHEEL;
- if (win9x)
- wParam <<= 16;
- }
-
-
- switch (message)
- {
- case WM_CREATE:
- nodinput = M_CheckParm("-nodinput");
- break;
-
- case WM_ACTIVATEAPP: // Handle task switching
- appActive = (int)wParam;
- // pause music when alt-tab
- if (appActive && !paused)
- I_ResumeSong(0);
- else if (!paused)
- I_PauseSong(0);
- {
- HANDLE ci = GetStdHandle(STD_INPUT_HANDLE);
- if (ci != INVALID_HANDLE_VALUE && GetFileType(ci) == FILE_TYPE_CHAR)
- appActive = true;
- }
- InvalidateRect (hWnd, NULL, TRUE);
- break;
-
- //for MIDI music
- case WM_MSTREAM_UPDATEVOLUME:
- I_SetMidiChannelVolume((DWORD)wParam, dwVolumePercent);
- break;
-
- case WM_PAINT:
- if (!appActive && !bAppFullScreen && !netgame)
- // app becomes inactive (if windowed)
- {
- // Paint "Game Paused" in the middle of the screen
- PAINTSTRUCT ps;
- RECT rect;
- HDC hdc = BeginPaint (hWnd, &ps);
- GetClientRect (hWnd, &rect);
- DrawText (hdc, TEXT("Game Paused"), -1, &rect,
- DT_SINGLELINE | DT_CENTER | DT_VCENTER);
- EndPaint (hWnd, &ps);
- return 0;
- }
- break;
-
- //case WM_RBUTTONDOWN:
- //case WM_LBUTTONDOWN:
-
- case WM_MOVE:
- if (bAppFullScreen)
- {
- SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
- return 0;
- }
- else
- {
- windowPosX = (SHORT) LOWORD(lParam); // horizontal position
- windowPosY = (SHORT) HIWORD(lParam); // vertical position
- break;
- }
- break;
-
- // This is where switching windowed/fullscreen is handled. DirectDraw
- // objects must be destroyed, recreated, and artwork reloaded.
-
- case WM_DISPLAYCHANGE:
- case WM_SIZE:
- break;
-
- case WM_SETCURSOR:
- if (bAppFullScreen)
- SetCursor(NULL);
- else
- SetCursor(windowCursor);
- return TRUE;
-
- case WM_KEYUP:
- ev.type = ev_keyup;
- goto handleKeyDoom;
- break;
-
- case WM_KEYDOWN:
- ev.type = ev_keydown;
-
- handleKeyDoom:
- ev.data1 = 0;
- if (wParam == VK_PAUSE)
- // intercept PAUSE key
- {
- ev.data1 = KEY_PAUSE;
- }
- else if (!keyboard_started)
- // post some keys during the game startup
- // (allow escaping from network synchronization, or pressing enter after
- // an error message in the console)
- {
- switch (wParam)
- {
- case VK_ESCAPE: ev.data1 = KEY_ESCAPE; break;
- case VK_RETURN: ev.data1 = KEY_ENTER; break;
- default: ev.data1 = MapVirtualKey((DWORD)wParam,2); // convert in to char
- }
- }
-
- if (ev.data1)
- D_PostEvent (&ev);
-
- return 0;
- break;
-
- // judgecutor:
- // Handle mouse events
- case WM_LBUTTONDOWN:
- case WM_LBUTTONUP:
- case WM_RBUTTONDOWN:
- case WM_RBUTTONUP:
- case WM_MBUTTONDOWN:
- case WM_MBUTTONUP:
- case WM_XBUTTONDOWN:
- case WM_XBUTTONUP:
- case WM_MOUSEMOVE:
- if (nodinput)
- {
- mouse_keys = 0;
- if (wParam & MK_LBUTTON)
- mouse_keys |= 1;
- if (wParam & MK_RBUTTON)
- mouse_keys |= 2;
- if (wParam & MK_MBUTTON)
- mouse_keys |= 4;
- if (wParam & MK_XBUTTON1)
- mouse_keys |= 8;
- if (wParam & MK_XBUTTON2)
- mouse_keys |= 16;
- I_GetSysMouseEvents(mouse_keys);
- }
- break;
-
-
- case WM_MOUSEWHEEL:
- //CONS_Printf("MW_WHEEL dispatched.\n");
- ev.type = ev_keydown;
- if ((INT16)HIWORD(wParam) > 0)
- ev.data1 = KEY_MOUSEWHEELUP;
- else
- ev.data1 = KEY_MOUSEWHEELDOWN;
- D_PostEvent(&ev);
- break;
-
- case WM_SETTEXT:
- COM_BufAddText((LPCSTR)lParam);
- return TRUE;
- break;
-
- case WM_CLOSE:
- PostQuitMessage(0); //to quit while in-game
- ev.data1 = KEY_ESCAPE; //to exit network synchronization
- ev.type = ev_keydown;
- D_PostEvent (&ev);
- return 0;
- case WM_DESTROY:
- //faB: main app loop will exit the loop and proceed with I_Quit()
- PostQuitMessage(0);
- break;
-
- default:
- break;
- }
-
- return DefWindowProc(hWnd, message, wParam, lParam);
-}
-
-
-static inline VOID OpenTextConsole(void)
-{
- HANDLE ci, co;
- const BOOL tco = M_CheckParm("-console") != 0;
- dedicated = M_CheckParm("-dedicated") != 0;
- if (!(dedicated || tco))
- return;
- FreeConsole();
- AllocConsole(); //Let get the real console HANDLE, because Mingw's Bash is bad!
- ci = CreateFile(TEXT("CONIN$") , GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- co = CreateFile(TEXT("CONOUT$"), GENERIC_WRITE|GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (ci != (HANDLE)-1)
- {
- const DWORD CM = ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT;
- SetStdHandle(STD_INPUT_HANDLE,ci);
- if(GetFileType(ci) == FILE_TYPE_CHAR)
- SetConsoleMode(ci,CM); //default mode but no ENABLE_MOUSE_INPUT
- }
- if(co != (HANDLE)-1)
- {
- SetStdHandle(STD_OUTPUT_HANDLE,co);
- SetStdHandle(STD_ERROR_HANDLE,co); //maybe logstream?
- }
-}
-
-//
-// Do that Windows initialization stuff...
-//
-static HWND OpenMainWindow (HINSTANCE hInstance, int nCmdShow, LPSTR wTitle)
-{
- HWND hWnd;
- WNDCLASS wc;
-
- // Set up and register window class
- nCmdShow = 0;
- wc.style = CS_HREDRAW | CS_VREDRAW /*| CS_DBLCLKS*/;
- wc.lpfnWndProc = MainWndproc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = hInstance;
- wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DLICON1));
- windowCursor = LoadCursor(NULL, IDC_WAIT); //LoadCursor(hInstance, MAKEINTRESOURCE(IDC_DLCURSOR1));
- wc.hCursor = windowCursor;
- wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = TEXT("SRB2WC");
- if (!RegisterClass(&wc))
- return (HANDLE)-1;
-
- // Create a window
- // CreateWindowEx - seems to create just the interior, not the borders
-
- hWnd = CreateWindowExA(
-#ifdef _DEBUG
- 0, //ExStyle
-#else
- dedicated ? 0:WS_EX_TOPMOST, //ExStyle
-#endif
- "SRB2WC", //Classname
- wTitle, //Windowname
- WS_CAPTION|WS_POPUP|WS_SYSMENU, //dwStyle //WS_VISIBLE|WS_POPUP for bAppFullScreen
- 0,
- 0,
- dedicated ? 0:BASEVIDWIDTH, //GetSystemMetrics(SM_CXSCREEN),
- dedicated ? 0:BASEVIDHEIGHT, //GetSystemMetrics(SM_CYSCREEN),
- NULL, //hWnd Parent
- NULL, //hMenu Menu
- hInstance,
- NULL);
-
- return hWnd;
-}
-
-
-static inline BOOL tlErrorMessage(const TCHAR *err)
-{
- /* make the cursor visible */
- SetCursor(LoadCursor(NULL, IDC_ARROW));
-
- //
- // warn user if there is one
- //
- printf("Error %s..\n", err);
- fflush(stdout);
-
- MessageBox(hWndMain, err, TEXT("ERROR"), MB_OK);
- return FALSE;
-}
-
-
-// ------------------
-// Command line stuff
-// ------------------
-#define MAXCMDLINEARGS 64
-static char * myWargv[MAXCMDLINEARGS+1];
-static char myCmdline[512];
-
-static VOID GetArgcArgv (LPSTR cmdline)
-{
- LPSTR token;
- size_t i = 0, len;
- char cSep = ' ';
- BOOL bCvar = FALSE, prevCvar = FALSE;
-
- // split arguments of command line into argv
- strncpy (myCmdline, cmdline, 511); // in case window's cmdline is in protected memory..for strtok
- len = strlen (myCmdline);
-
- myargc = 0;
- while (myargc < MAXCMDLINEARGS)
- {
- // get token
- while (myCmdline[i] == cSep)
- i++;
- if (i >= len)
- break;
- token = myCmdline + i;
- if (myCmdline[i] == '"')
- {
- cSep = '"';
- i++;
- if (!prevCvar) //cvar leave the "" in
- token++;
- }
- else
- cSep = ' ';
-
- //cvar
- if (myCmdline[i] == '+' && cSep == ' ') //a + begins a cvarname, but not after quotes
- bCvar = TRUE;
- else
- bCvar = FALSE;
-
- while (myCmdline[i] &&
- myCmdline[i] != cSep)
- i++;
-
- if (myCmdline[i] == '"')
- {
- cSep = ' ';
- if (prevCvar)
- i++; // get ending " quote in arg
- }
-
- prevCvar = bCvar;
-
- if (myCmdline + i > token)
- {
- myWargv[myargc++] = token;
- }
-
- if (!myCmdline[i] || i >= len)
- break;
-
- myCmdline[i++] = '\0';
- }
- myWargv[myargc] = NULL;
-
- // m_argv.c uses myargv[], we used myWargv because we fill the arguments ourselves
- // and myargv is just a pointer, so we set it to point myWargv
- myargv = myWargv;
-}
-
-
-static inline VOID MakeCodeWritable(VOID)
-{
-#ifdef USEASM
- // Disable write-protection of code segment
- DWORD OldRights;
- BYTE *pBaseOfImage = (BYTE *)GetModuleHandle(NULL);
- IMAGE_OPTIONAL_HEADER *pHeader = (IMAGE_OPTIONAL_HEADER *)
- (pBaseOfImage + ((IMAGE_DOS_HEADER*)pBaseOfImage)->e_lfanew +
- sizeof (IMAGE_NT_SIGNATURE) + sizeof (IMAGE_FILE_HEADER));
- if (!VirtualProtect(pBaseOfImage+pHeader->BaseOfCode,pHeader->SizeOfCode,PAGE_EXECUTE_READWRITE,&OldRights))
- I_Error("Could not make code writable\n");
-#endif
-}
-
-
-
-
-// -----------------------------------------------------------------------------
-// HandledWinMain : called by exception handler
-// -----------------------------------------------------------------------------
-static int WINAPI HandledWinMain(HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpCmdLine,
- int nCmdShow)
-{
- int i;
- LPSTR args;
-
- lpCmdLine = NULL;
- hPrevInstance = NULL;
-#ifdef LOGMESSAGES
- // DEBUG!!! - set logstream to NULL to disable debug log
- logstream = INVALID_HANDLE_VALUE;
-
- logstream = CreateFile (TEXT("log.txt"), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL, NULL); //file flag writethrough?
-#endif
-
- // fill myargc,myargv for m_argv.c retrieval of cmdline arguments
- CONS_Printf("GetArgcArgv() ...\n");
- args = GetCommandLineA();
- CONS_Printf("lpCmdLine is '%s'\n", args);
- GetArgcArgv(args);
- // Create a text console window
- OpenTextConsole();
-
- CONS_Printf("Myargc: %d\n", myargc);
- for (i = 0; i < myargc; i++)
- CONS_Printf("myargv[%d] : '%s'\n", i, myargv[i]);
-
- // store for later use, will we need it ?
- myInstance = hInstance;
-
- // open a dummy window, both OpenGL and DirectX need one.
- if ((hWndMain = OpenMainWindow(hInstance,nCmdShow,
- va("SRB2Kart "VERSIONSTRING))) == (HANDLE)-1)
- {
- tlErrorMessage(TEXT("Couldn't open window"));
- return FALSE;
- }
-
- // currently starts DirectInput
- CONS_Printf("I_StartupSystem() ...\n");
- I_StartupSystem();
- MakeCodeWritable();
-
- // startup SRB2
- CONS_Printf("D_SRB2Main() ...\n");
- D_SRB2Main();
- CONS_Printf("Entering main app loop...\n");
- // never return
- D_SRB2Loop();
-
- // back to Windoze
- return 0;
-}
-
-// -----------------------------------------------------------------------------
-// Exception handler calls WinMain for catching exceptions
-// -----------------------------------------------------------------------------
-int WINAPI WinMain (HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpCmdLine,
- int nCmdShow)
-{
- int Result = -1;
-#if 1
- HMODULE h = GetModuleHandleA("kernel32.dll");
- MyFunc pfnIsDebuggerPresent = NULL;
- if (h)
- pfnIsDebuggerPresent = (MyFunc)GetProcAddress(h,"IsDebuggerPresent");
- if (!pfnIsDebuggerPresent || !pfnIsDebuggerPresent())
- LoadLibrary("exchndl.dll");
-#endif
-#ifdef NO_SEH_MINGW
- __try1(RecordExceptionInfo(GetExceptionInformation()/*, "main thread", lpCmdLine*/))
-#else
- __try
-#endif
- {
- Result = HandledWinMain (hInstance, hPrevInstance, lpCmdLine, nCmdShow);
- }
-#ifdef NO_SEH_MINGW
- __except1
-#else
- __except (RecordExceptionInfo(GetExceptionInformation()/*, "main thread", lpCmdLine*/))
-#endif
- {
- SetUnhandledExceptionFilter(EXCEPTION_CONTINUE_SEARCH); //Do nothing here.
- }
-
- return Result;
-}
diff --git a/src/win32ce/win_sys.c b/src/win32ce/win_sys.c
deleted file mode 100644
index 1ffcc7020..000000000
--- a/src/win32ce/win_sys.c
+++ /dev/null
@@ -1,3505 +0,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) 1998-2000 by DooM Legacy Team.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//-----------------------------------------------------------------------------
-/// \file
-/// \brief win32 system i/o
-///
-/// Startup & Shutdown routines for music,sound,timer,keyboard,...
-/// Signal handler to trap errors and exit cleanly.
-
-#include "../doomdef.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-
-#include "../m_misc.h"
-#include "../i_video.h"
-#include "../i_sound.h"
-#include "../i_system.h"
-
-#include "../d_net.h"
-#include "../g_game.h"
-
-#include "../d_main.h"
-
-#include "../m_argv.h"
-
-#include "../w_wad.h"
-#include "../z_zone.h"
-#include "../g_input.h"
-
-#include "../keys.h"
-
-#include "../screen.h"
-
-// Wheel support for Win95/WinNT3.51
-#include
-
-// Taken from Win98/NT4.0
-#ifndef SM_MOUSEWHEELPRESENT
-#define SM_MOUSEWHEELPRESENT 75
-#endif
-
-#ifndef MSH_MOUSEWHEEL
-#ifdef UNICODE
-#define MSH_MOUSEWHEEL L"MSWHEEL_ROLLMSG"
-#else
-#define MSH_MOUSEWHEEL "MSWHEEL_ROLLMSG"
-#endif
-#endif
-
-#include "win_main.h"
-#include "../i_joy.h"
-
-#define DIRECTINPUT_VERSION 0x700
-// Force dinput.h to generate old DX3 headers.
-#define DXVERSION_NTCOMPATIBLE 0x0300
-#include
-
-#include "fabdxlib.h"
-
-#ifdef __DEBUG__
-#undef NDEBUG
-#endif
-
-/// \brief max number of joystick buttons
-#define JOYBUTTONS_MAX 32 // rgbButtons[32]
-/// \brief max number of joystick button events
-#define JOYBUTTONS_MIN min((JOYBUTTONS),(JOYBUTTONS_MAX))
-
-/// \brief max number of joysick axies
-#define JOYAXISSET_MAX 4 // (lX, lY), (lZ,lRx), (lRy, lRz), rglSlider[2] is very diff
-/// \brief max number ofjoystick axis events
-#define JOYAXISSET_MIN min((JOYAXISSET),(JOYAXISSET_MAX))
-
-/// \brief max number of joystick hats
-#define JOYHATS_MAX 4 // rgdwPOV[4];
-/// \brief max number of joystick hat events
-#define JOYHATS_MIN min((JOYHATS),(JOYHATS_MAX))
-
-/// \brief max number of mouse buttons
-#define MOUSEBUTTONS_MAX 8 // 8 bit of BYTE and DIMOFS_BUTTON7
-/// \brief max number of muse button events
-#define MOUSEBUTTONS_MIN min((MOUSEBUTTONS),(MOUSEBUTTONS_MAX))
-
-// ==================
-// DIRECT INPUT STUFF
-// ==================
-BOOL bDX0300; // if true, we created a DirectInput 0x0300 version
-static LPDIRECTINPUT lpDI = NULL;
-static LPDIRECTINPUTDEVICE lpDIK = NULL; // Keyboard
-static LPDIRECTINPUTDEVICE lpDIM = NULL; // mice
-static LPDIRECTINPUTDEVICE lpDIJ = NULL; // joystick 1P
-static LPDIRECTINPUTEFFECT lpDIE[NumberofForces]; // joystick 1Es
-static LPDIRECTINPUTDEVICE2 lpDIJA = NULL; // joystick 1I
-static LPDIRECTINPUTDEVICE lpDIJ2 = NULL; // joystick 2P
-static LPDIRECTINPUTEFFECT lpDIE2[NumberofForces]; // joystick 1Es
-static LPDIRECTINPUTDEVICE2 lpDIJ2A = NULL;// joystick 2I
-
-// Do not execute cleanup code more than once. See Shutdown_xxx() routines.
-UINT8 graphics_started = 0;
-UINT8 keyboard_started = 0;
-UINT8 sound_started = 0;
-static boolean mouse_enabled = false;
-static boolean joystick_detected = false;
-static boolean joystick2_detected = false;
-
-static void I_ShutdownKeyboard(void);
-static void I_GetKeyboardEvents(void);
-static void I_ShutdownJoystick(void);
-static void I_ShutdownJoystick2 (void);
-
-static boolean entering_con_command = false;
-
-//
-// Why would this be system specific?? hmmmm....
-//
-// it is for virtual reality system, next incoming feature :)
-static ticcmd_t emptycmd;
-ticcmd_t *I_BaseTiccmd(void)
-{
- return &emptycmd;
-}
-
-static ticcmd_t emptycmd2;
-ticcmd_t *I_BaseTiccmd2(void)
-{
- return &emptycmd2;
-}
-
-// Allocates the base zone memory,
-// this function returns a valid pointer and size,
-// else it should interrupt the program immediately.
-//
-// now checks if mem could be allocated, this is still
-// prehistoric... there's a lot to do here: memory locking, detection
-// of win95 etc...
-//
-
-BOOL win9x;
-
-/** \brief WinNT system platform
-*/
-static BOOL winnt;
-
-static void I_DetectWin9x(void)
-{
- OSVERSIONINFO osvi;
-
- osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
- GetVersionEx(&osvi);
-
- winnt = (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT);
- // 95 or 98 what the hell
- win9x = true;
-}
-
-// return free and total memory in the system
-UINT32 I_GetFreeMem(UINT32* total)
-{
- MEMORYSTATUS info;
-
- info.dwLength = sizeof (MEMORYSTATUS);
- GlobalMemoryStatus(&info);
- if (total)
- *total = (ULONG)info.dwTotalPhys;
- return (ULONG)info.dwAvailPhys;
-}
-
-// ---------
-// I_Profile
-// Two little functions to profile our code using the high resolution timer
-// ---------
-static LARGE_INTEGER ProfileCount;
-void I_BeginProfile(void)
-{
- if (!QueryPerformanceCounter(&ProfileCount))
- I_Error("I_BeginProfile failed"); // can't profile without the high res timer
-}
-
-// we're supposed to use this to measure very small amounts of time,
-// that's why we return a DWORD and not a 64bit value
-DWORD I_EndProfile(void)
-{
- LARGE_INTEGER CurrTime;
- DWORD ret;
- if (!QueryPerformanceCounter (&CurrTime))
- I_Error("I_EndProfile failed");
- if (CurrTime.QuadPart - ProfileCount.QuadPart > (LONGLONG)0xFFFFFFFFUL)
- I_Error("I_EndProfile overflow");
- ret = (DWORD)(CurrTime.QuadPart - ProfileCount.QuadPart);
- // we can call I_EndProfile() several time, I_BeginProfile() need be called just once
- ProfileCount = CurrTime;
-
- return ret;
-}
-
-// ---------
-// I_GetTime
-// Use the High Resolution Timer if available,
-// else use the multimedia timer which has 1 millisecond precision on Windowz 95,
-// but lower precision on Windows NT
-// ---------
-static long hacktics = 0; // used locally for keyboard repeat keys
-static DWORD starttickcount = 0; // hack for win2k time bug
-
-tic_t I_GetTime(void)
-{
- tic_t newtics = 0;
-
- if (!starttickcount) // high precision timer
- {
- LARGE_INTEGER currtime; // use only LowPart if high resolution counter is not available
- static LARGE_INTEGER basetime = {{0, 0}};
-
- // use this if High Resolution timer is found
- static LARGE_INTEGER frequency;
-
- if (!basetime.LowPart)
- {
- if (!QueryPerformanceFrequency(&frequency))
- frequency.QuadPart = 0;
- else
- QueryPerformanceCounter(&basetime);
- }
-
- if (frequency.LowPart && QueryPerformanceCounter(&currtime))
- {
- newtics = (int)((currtime.QuadPart - basetime.QuadPart) * TICRATE
- / frequency.QuadPart);
- }
- else
- {
- currtime.LowPart = timeGetTime();
- if (!basetime.LowPart)
- basetime.LowPart = currtime.LowPart;
- newtics = ((currtime.LowPart - basetime.LowPart)/(1000/TICRATE));
- }
- }
- else
- newtics = (GetTickCount() - starttickcount)/(1000/TICRATE);
-
- hacktics = newtics; // a local counter for keyboard repeat key
- return newtics;
-}
-
-
-void I_Sleep(void)
-{
- if (cv_sleep.value > 0)
- Sleep(cv_sleep.value);
-}
-
-
-// should move to i_video
-void I_WaitVBL(INT32 count)
-{
- count = 0;
-}
-
-// this is probably to activate the 'loading' disc icon
-// it should set a flag, that I_FinishUpdate uses to know
-// whether it draws a small 'loading' disc icon on the screen or not
-//
-// also it should explicitly draw the disc because the screen is
-// possibly not refreshed while loading
-//
-void I_BeginRead(void) {}
-
-// see above, end the 'loading' disc icon, set the flag false
-//
-void I_EndRead(void) {}
-
-// ===========================================================================================
-// EVENTS
-// ===========================================================================================
-static inline BOOL I_ReadyConsole(HANDLE ci)
-{
- DWORD gotinput;
- if (ci == (HANDLE)-1) return FALSE;
- if (WaitForSingleObject(ci,0) != WAIT_OBJECT_0) return FALSE;
- if (GetFileType(ci) != FILE_TYPE_CHAR) return FALSE;
- return (GetNumberOfConsoleInputEvents(ci, &gotinput) && gotinput);
-}
-
-static inline VOID I_GetConsoleEvents(VOID)
-{
- event_t ev = {0,0,0,0,0};
- HANDLE ci = GetStdHandle(STD_INPUT_HANDLE);
- HANDLE co = GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_SCREEN_BUFFER_INFO CSBI;
- INPUT_RECORD input;
- DWORD t;
-
- while (I_ReadyConsole(ci) && ReadConsoleInput(ci, &input, 1, &t) && t)
- {
- memset(&ev,0x00,sizeof (ev));
- switch (input.EventType)
- {
- case KEY_EVENT:
- if (input.Event.KeyEvent.bKeyDown)
- {
- ev.type = ev_console;
- entering_con_command = true;
- switch (input.Event.KeyEvent.wVirtualKeyCode)
- {
- case VK_ESCAPE:
- case VK_TAB:
- ev.data1 = KEY_NULL;
- break;
- case VK_SHIFT:
- ev.data1 = KEY_SHIFT;
- break;
- case VK_RETURN:
- entering_con_command = false;
- // Fall through.
- default:
- ev.data1 = MapVirtualKey(input.Event.KeyEvent.wVirtualKeyCode,2); // convert in to char
- }
- if (co != (HANDLE)-1 && GetFileType(co) == FILE_TYPE_CHAR)
- {
- if (ev.data1 && ev.data1 != KEY_SHIFT)
- {
-#ifdef _UNICODE
- WriteConsole(co, &input.Event.KeyEvent.uChar.UnicodeChar, 1, &t, NULL);
-#else
- WriteConsole(co, &input.Event.KeyEvent.uChar.AsciiChar, 1, &t, NULL);
-#endif
- }
- if (input.Event.KeyEvent.wVirtualKeyCode == VK_BACK
- && GetConsoleScreenBufferInfo(co,&CSBI))
- {
- WriteConsoleOutputCharacterA(co, " ",1, CSBI.dwCursorPosition, &t);
- }
- }
- }
- else
- {
- ev.type = ev_keyup;
- switch (input.Event.KeyEvent.wVirtualKeyCode)
- {
- case VK_SHIFT:
- ev.data1 = KEY_SHIFT;
- break;
- default:
- break;
- }
- }
- if (ev.data1) D_PostEvent(&ev);
- break;
- case MOUSE_EVENT:
- case WINDOW_BUFFER_SIZE_EVENT:
- case MENU_EVENT:
- case FOCUS_EVENT:
- break;
- }
- }
-}
-
-// ----------
-// I_GetEvent
-// Post new events for all sorts of user-input
-// ----------
-void I_GetEvent(void)
-{
- I_GetConsoleEvents();
- I_GetKeyboardEvents();
- I_GetMouseEvents();
- I_GetJoystickEvents();
- I_GetJoystick2Events();
-}
-
-// ----------
-// I_OsPolling
-// ----------
-void I_OsPolling(void)
-{
- MSG msg;
- HANDLE ci = GetStdHandle(STD_INPUT_HANDLE);
-
- // we need to dispatch messages to the window
- // so the window procedure can respond to messages and PostEvent() for keys
- // during D_SRB2Main startup.
- // this one replaces the main loop of windows since I_OsPolling is called in the main loop
- do
- {
- while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
- {
- if (GetMessage(&msg, NULL, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- else // winspec : this is quit message
- I_Quit();
- }
- if (!appActive && !netgame && !I_ReadyConsole(ci))
- WaitMessage();
- } while (!appActive && !netgame && !I_ReadyConsole(ci));
-
- // this is called by the network synchronization,
- // check keys and allow escaping
- I_GetEvent();
-
- // reset "emulated keys"
- gamekeydown[KEY_MOUSEWHEELUP] = 0;
- gamekeydown[KEY_MOUSEWHEELDOWN] = 0;
-}
-
-// ===========================================================================================
-// TIMER
-// ===========================================================================================
-
-static void I_ShutdownTimer(void)
-{
- timeEndPeriod(1);
-}
-
-//
-// Installs the timer interrupt handler with timer speed as TICRATE.
-//
-#define TIMER_ID 1
-#define TIMER_RATE (1000/TICRATE)
-void I_StartupTimer(void)
-{
- // for win2k time bug
- if (M_CheckParm("-gettickcount"))
- {
- starttickcount = GetTickCount();
- CONS_Printf("Using GetTickCount()\n");
- }
- timeBeginPeriod(1);
- I_AddExitFunc(I_ShutdownTimer);
-}
-
-// ===========================================================================================
-// EXIT CODE, ERROR HANDLING
-// ===========================================================================================
-
-static int errorcount = 0; // phuck recursive errors
-static int shutdowning = false;
-
-//
-// Used to trap various signals, to make sure things get shut down cleanly.
-//
-#ifdef NDEBUG
-static void signal_handler(int num)
-{
- //static char msg[] = "oh no! back to reality!\r\n";
- const char *sigmsg;
- char sigdef[64];
-
- D_QuitNetGame(); // Fix server freezes
- I_ShutdownSystem();
-
- switch (num)
- {
- case SIGINT:
- sigmsg = "interrupt";
- break;
- case SIGILL:
- sigmsg = "illegal instruction - invalid function image";
- break;
- case SIGFPE:
- sigmsg = "floating point exception";
- break;
- case SIGSEGV:
- sigmsg = "segment violation";
- break;
- case SIGTERM:
- sigmsg = "software termination signal from kill";
- break;
- case SIGBREAK:
- sigmsg = "Ctrl-Break sequence";
- break;
- case SIGABRT:
- sigmsg = "abnormal termination triggered by abort call";
- break;
- default:
- sprintf(sigdef, "signal number %d", num);
- sigmsg = sigdef;
- }
-
-#ifdef LOGMESSAGES
- if (logstream != INVALID_HANDLE_VALUE)
- {
- I_OutputMsg("signal_handler() error: %s\r\n", sigmsg);
- CloseHandle(logstream);
- logstream = INVALID_HANDLE_VALUE;
- }
-#endif
-
- MessageBoxA(hWndMain, va("signal_handler(): %s", sigmsg), "SRB2 error", MB_OK|MB_ICONERROR);
-
- signal(num, SIG_DFL); // default signal action
- raise(num);
-}
-#endif
-
-//
-// put an error message (with format) on stderr
-//
-void I_OutputMsg(const char *fmt, ...)
-{
- HANDLE co = GetStdHandle(STD_OUTPUT_HANDLE);
- DWORD bytesWritten;
- va_list argptr;
- char txt[8192];
-
- va_start(argptr,fmt);
- vsprintf(txt, fmt, argptr);
- va_end(argptr);
-
- OutputDebugStringA(txt);
- if (co != (HANDLE)-1)
- {
- if (GetFileType(co) == FILE_TYPE_CHAR)
- {
- static COORD coordNextWrite = {0,0};
- char *oldLines = NULL;
- DWORD oldLength = 0;
- CONSOLE_SCREEN_BUFFER_INFO csbi;
-
- // Save the lines that we're going to obliterate.
- GetConsoleScreenBufferInfo(co, &csbi);
- oldLength = csbi.dwSize.X * (csbi.dwCursorPosition.Y - coordNextWrite.Y) + csbi.dwCursorPosition.X - coordNextWrite.X;
-
- if(oldLength > 0)
- {
- char *blank = malloc(oldLength);
- oldLines = malloc(oldLength);
- if(!oldLines || !blank) return;
-
- ReadConsoleOutputCharacterA(co, oldLines, oldLength, coordNextWrite, &bytesWritten);
-
- // Move to where we what to print - which is where we would've been,
- // had console input not been in the way,
- SetConsoleCursorPosition(co, coordNextWrite);
-
- // Blank out.
- memset(blank, ' ', oldLength);
- WriteConsoleA(co, blank, oldLength, &bytesWritten, NULL);
- free(blank);
-
- // And back to where we want to print again.
- SetConsoleCursorPosition(co, coordNextWrite);
- }
-
- // Actually write the string now!
- WriteConsoleA(co, txt, (DWORD)strlen(txt), &bytesWritten, NULL);
-
- // Next time, output where we left off.
- GetConsoleScreenBufferInfo(co, &csbi);
- coordNextWrite = csbi.dwCursorPosition;
-
- // Restore what was overwritten.
- if(oldLines && entering_con_command)
- {
- WriteConsoleA(co, oldLines, oldLength, &bytesWritten, NULL);
- free(oldLines);
- }
- }
- else // Redirected to a file.
- WriteFile(co, txt, (DWORD)strlen(txt), &bytesWritten, NULL);
- }
-
-#ifdef LOGMESSAGES
- if (logstream != (HANDLE)-1)
- WriteFile (logstream, txt, (DWORD)strlen(txt), &bytesWritten, NULL);
-#endif
-}
-
-// display error messy after shutdowngfx
-//
-void I_Error(const char *error, ...)
-{
- va_list argptr;
- char txt[8192];
-
- // added 11-2-98 recursive error detecting
- if (shutdowning)
- {
- errorcount++;
- // try to shutdown each subsystem separately
- if (errorcount == 5)
- I_ShutdownGraphics();
- if (errorcount == 6)
- I_ShutdownSystem();
- if (errorcount == 7)
- {
- M_SaveConfig(NULL);
- G_SaveGameData();
- }
- if (errorcount > 20)
- {
- // Don't print garbage
- va_start(argptr,error);
- vsprintf(txt, error, argptr);
- va_end(argptr);
-
- MessageBoxA(hWndMain, txt, "SRB2 Recursive Error", MB_OK|MB_ICONERROR);
- exit(-1); // recursive errors detected
- }
- }
- shutdowning = true;
-
- // put message to stderr
- va_start(argptr, error);
- wvsprintfA(txt, error, argptr);
- va_end(argptr);
-
- CONS_Printf("I_Error(): %s\n", txt);
-
- // uncomment this line to print to stderr as well
- //wsprintf(stderr, "I_Error(): %s\n", txt);
-
- // saving one time is enough!
- if (!errorcount)
- {
- M_SaveConfig(NULL); // save game config, cvars..
- G_SaveGameData();
- }
-
- // save demo, could be useful for debug
- // NOTE: demos are normally not saved here.
- if (demorecording)
- G_CheckDemoStatus();
-
- D_QuitNetGame();
-
- // shutdown everything that was started
- I_ShutdownSystem();
-
-#ifdef LOGMESSAGES
- if (logstream != INVALID_HANDLE_VALUE)
- {
- CloseHandle(logstream);
- logstream = INVALID_HANDLE_VALUE;
- }
-#endif
-
- MessageBoxA(hWndMain, txt, "SRB2 Error", MB_OK|MB_ICONERROR);
-
- exit(-1);
-}
-
-static inline VOID ShowEndTxt(HANDLE co)
-{
- int i;
- UINT16 j, att = 0;
- int nlflag = 1;
- CONSOLE_SCREEN_BUFFER_INFO backupcon;
- COORD resizewin = {80,-1};
- DWORD bytesWritten;
- CHAR let = 0;
- UINT16 *text;
- void *data;
- int endoomnum = W_GetNumForName("ENDOOM");
- //HANDLE ci = GetStdHandle(STD_INPUT_HANDLE);
-
- /* get the lump with the text */
- data = text = W_CacheLumpNum(endoomnum, PU_CACHE);
-
- backupcon.wAttributes = FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE; // Just in case
- GetConsoleScreenBufferInfo(co, &backupcon); //Store old state
- resizewin.Y = backupcon.dwSize.Y;
- if (backupcon.dwSize.X < resizewin.X)
- SetConsoleScreenBufferSize(co, resizewin);
-
- for (i = 1; i <= 80*25; i++) // print 80x25 text and deal with the attributes too
- {
- j = (UINT16)(*text >> 8); // attribute first
- if (j != att) // attribute changed?
- {
- att = j; // save current attribute
- SetConsoleTextAttribute(co, j); //set fg and bg color for buffer
- }
-
- let = (char)(*text++ & 0xff); // now the text
- WriteConsoleA(co, &let, 1, &bytesWritten, NULL);
-
- if (nlflag && !(i % 80) && backupcon.dwSize.X > resizewin.X) // do we need a nl?
- {
- att = backupcon.wAttributes;
- SetConsoleTextAttribute(co, att); // all attributes off
- WriteConsoleA(co, "\n", 1, &bytesWritten, NULL);
- }
- }
- SetConsoleTextAttribute(co, backupcon.wAttributes); // all attributes off
- //if (nlflag)
- // WriteConsoleA(co, "\n", 1, &bytesWritten, NULL);
-
- getchar(); //pause!
-
- Z_Free(data);
-}
-
-
-//
-// I_Quit: shutdown everything cleanly, in reverse order of Startup.
-//
-void I_Quit(void)
-{
- HANDLE co = GetStdHandle(STD_OUTPUT_HANDLE);
- // when recording a demo, should exit using 'q',
- // but sometimes we forget and use Alt+F4, so save here too.
- if (demorecording)
- G_CheckDemoStatus();
-
- M_SaveConfig(NULL); // save game config, cvars..
- G_SaveGameData();
-
- // maybe it needs that the ticcount continues,
- // or something else that will be finished by I_ShutdownSystem(),
- // so do it before.
- D_QuitNetGame();
-
- // shutdown everything that was started
- I_ShutdownSystem();
-
- if (shutdowning || errorcount)
- I_Error("Error detected (%d)", errorcount);
-
-#ifdef LOGMESSAGES
- if (logstream != INVALID_HANDLE_VALUE)
- {
- I_OutputMsg("I_Quit(): end of logstream.\r\n");
- CloseHandle(logstream);
- logstream = INVALID_HANDLE_VALUE;
- }
-#endif
- if (!M_CheckParm("-noendtxt") && W_CheckNumForName("ENDOOM")!=-1
- && co != INVALID_HANDLE_VALUE && GetFileType(co) == FILE_TYPE_CHAR)
- {
- printf("\r");
- ShowEndTxt(co);
- }
- fflush(stderr);
- exit(0);
-}
-
-// --------------------------------------------------------------------------
-// I_ShowLastError
-// Displays a GetLastError() error message in a MessageBox
-// --------------------------------------------------------------------------
-void I_GetLastErrorMsgBox(void)
-{
- LPSTR lpMsgBuf = NULL;
-
- FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
- lpMsgBuf, 0, NULL);
-
- // Display the string.
- MessageBoxA(NULL, lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION);
-
- // put it in console too and log if any
- CONS_Printf("Error: %s\n", lpMsgBuf);
-
- // Free the buffer.
- LocalFree(lpMsgBuf);
-}
-
-// ===========================================================================================
-// CLEAN STARTUP & SHUTDOWN HANDLING, JUST CLOSE EVERYTHING YOU OPENED.
-// ===========================================================================================
-//
-//
-static quitfuncptr quit_funcs[MAX_QUIT_FUNCS] =
-{
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
-};
-
-// Adds a function to the list that need to be called by I_SystemShutdown().
-//
-void I_AddExitFunc(void (*func)())
-{
- int c;
-
- for (c = 0; c < MAX_QUIT_FUNCS; c++)
- {
- if (!quit_funcs[c])
- {
- quit_funcs[c] = func;
- break;
- }
- }
-}
-
-// Removes a function from the list that need to be called by I_SystemShutdown().
-//
-void I_RemoveExitFunc(void (*func)())
-{
- int c;
-
- for (c = 0; c < MAX_QUIT_FUNCS; c++)
- {
- if (quit_funcs[c] == func)
- {
- while (c < MAX_QUIT_FUNCS - 1)
- {
- quit_funcs[c] = quit_funcs[c+1];
- c++;
- }
- quit_funcs[MAX_QUIT_FUNCS-1] = NULL;
- break;
- }
- }
-}
-
-// ===========================================================================================
-// DIRECT INPUT HELPER CODE
-// ===========================================================================================
-
-// Create a DirectInputDevice interface,
-// create a DirectInputDevice2 interface if possible
-static void CreateDevice2(LPDIRECTINPUT di, REFGUID pguid, LPDIRECTINPUTDEVICE* lpDEV,
- LPDIRECTINPUTDEVICE2* lpDEV2)
-{
- HRESULT hr, hr2;
- LPDIRECTINPUTDEVICE lpdid1;
- LPDIRECTINPUTDEVICE2 lpdid2 = NULL;
-
- hr = IDirectInput_CreateDevice(di, pguid, &lpdid1, NULL);
-
- if (SUCCEEDED(hr))
- {
- // get Device2 but only if we are not in DirectInput version 3
- if (!bDX0300 && lpDEV2)
- {
- LPDIRECTINPUTDEVICE2 *rp = &lpdid2;
- LPVOID *tp = (LPVOID *)rp;
- hr2 = IDirectInputDevice_QueryInterface(lpdid1, &IID_IDirectInputDevice2, tp);
- if (FAILED(hr2))
- {
- CONS_Printf("\2Could not create IDirectInput device 2");
- lpdid2 = NULL;
- }
- }
- }
- else
- I_Error("Could not create IDirectInput device");
-
- *lpDEV = lpdid1;
- if (lpDEV2) // only if we requested it
- *lpDEV2 = lpdid2;
-}
-
-// ===========================================================================================
-// DIRECT INPUT MOUSE
-// ===========================================================================================
-
-#define DI_MOUSE_BUFFERSIZE 16 // number of data elements in mouse buffer
-
-//
-// Initialise the mouse.
-//
-static void I_ShutdownMouse(void);
-
-void I_StartupMouse(void)
-{
- // this gets called when cv_usemouse is initted
- // for the win32 version, we want to startup the mouse later
-}
-
-static HANDLE mouse2filehandle = INVALID_HANDLE_VALUE;
-
-static void I_ShutdownMouse2(void)
-{
- if (mouse2filehandle != INVALID_HANDLE_VALUE)
- {
- event_t event;
- int i;
-
- SetCommMask(mouse2filehandle, 0);
-
- EscapeCommFunction(mouse2filehandle, CLRDTR);
- EscapeCommFunction(mouse2filehandle, CLRRTS);
-
- PurgeComm(mouse2filehandle, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
-
- CloseHandle(mouse2filehandle);
-
- // emulate the up of all mouse buttons
- for (i = 0; i < MOUSEBUTTONS; i++)
- {
- event.type = ev_keyup;
- event.data1 = KEY_2MOUSE1 + i;
- D_PostEvent(&event);
- }
-
- mouse2filehandle = INVALID_HANDLE_VALUE;
- }
-}
-
-#define MOUSECOMBUFFERSIZE 256
-static int handlermouse2x, handlermouse2y, handlermouse2buttons;
-
-static void I_PoolMouse2(void)
-{
- UINT8 buffer[MOUSECOMBUFFERSIZE];
- COMSTAT ComStat;
- DWORD dwErrorFlags, dwLength;
- char dx, dy;
-
- static int bytenum;
- static UINT8 combytes[4];
- DWORD i;
-
- ClearCommError(mouse2filehandle, &dwErrorFlags, &ComStat);
- dwLength = min(MOUSECOMBUFFERSIZE, ComStat.cbInQue);
-
- if (dwLength > 0)
- {
- if (!ReadFile(mouse2filehandle, buffer, dwLength, &dwLength, NULL))
- {
- CONS_Printf("\2Read Error on secondary mouse port\n");
- return;
- }
-
- // parse the mouse packets
- for (i = 0; i < dwLength; i++)
- {
- if ((buffer[i] & 64) == 64)
- bytenum = 0;
-
- if (bytenum < 4)
- combytes[bytenum] = buffer[i];
- bytenum++;
-
- if (bytenum == 1)
- {
- handlermouse2buttons &= ~3;
- handlermouse2buttons |= ((combytes[0] & (32+16)) >>4);
- }
- else if (bytenum == 3)
- {
- dx = (char)((combytes[0] & 3) << 6);
- dy = (char)((combytes[0] & 12) << 4);
- dx = (char)(dx + combytes[1]);
- dy = (char)(dy + combytes[2]);
- handlermouse2x += dx;
- handlermouse2y += dy;
- }
- else if (bytenum == 4) // fourth byte (logitech mouses)
- {
- if (buffer[i] & 32)
- handlermouse2buttons |= 4;
- else
- handlermouse2buttons &= ~4;
- }
- }
- }
-}
-
-// secondary mouse doesn't use DirectX, therefore forget all about grabbing, acquire, etc.
-void I_StartupMouse2(void)
-{
- DCB dcb;
-
- if (mouse2filehandle != INVALID_HANDLE_VALUE)
- I_ShutdownMouse2();
-
- if (!cv_usemouse2.value)
- return;
-
- if (mouse2filehandle != INVALID_HANDLE_VALUE)
- {
- // COM file handle
- mouse2filehandle = CreateFileA(cv_mouse2port.string, GENERIC_READ|GENERIC_WRITE,
- 0, // exclusive access
- NULL, // no security attrs
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (mouse2filehandle == INVALID_HANDLE_VALUE)
- {
- int e = GetLastError();
- if (e == 5)
- CONS_Printf("\2Can't open %s: Access denied\n"
- "The port is probably already used by another device (mouse, modem,...)\n",
- cv_mouse2port.string);
- else
- CONS_Printf("\2Can't open %s: error %d\n", cv_mouse2port.string, e);
- return;
- }
- }
-
- // buffers
- SetupComm(mouse2filehandle, MOUSECOMBUFFERSIZE, MOUSECOMBUFFERSIZE);
-
- // purge buffers
- PurgeComm(mouse2filehandle, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
-
- // setup port to 1200 7N1
- dcb.DCBlength = sizeof (DCB);
-
- GetCommState(mouse2filehandle, &dcb);
-
- dcb.BaudRate = CBR_1200;
- dcb.ByteSize = 7;
- dcb.Parity = NOPARITY;
- dcb.StopBits = ONESTOPBIT;
-
- dcb.fDtrControl = DTR_CONTROL_ENABLE;
- dcb.fRtsControl = RTS_CONTROL_ENABLE;
-
- dcb.fBinary = dcb.fParity = TRUE;
-
- SetCommState(mouse2filehandle, &dcb);
-
- I_AddExitFunc(I_ShutdownMouse2);
-}
-
-#define MAX_MOUSE_BTNS 5
-static int center_x, center_y;
-static int old_mparms[3], new_mparms[3] = {0, 0, 1};
-static boolean restore_mouse = FALSE;
-static int old_mouse_state = 0;
-unsigned int MSHWheelMessage = 0;
-
-static void I_DoStartupSysMouse(void)
-{
- boolean valid;
- RECT w_rect;
-
- valid = SystemParametersInfo(SPI_GETMOUSE, 0, old_mparms, 0);
- if (valid)
- {
- new_mparms[2] = old_mparms[2];
- restore_mouse = SystemParametersInfo(SPI_SETMOUSE, 0, new_mparms, 0);
- }
-
- if (bAppFullScreen)
- {
- w_rect.top = 0;
- w_rect.left = 0;
- }
- else
- {
- w_rect.top = windowPosY;
- w_rect.left = windowPosX;
- }
-
- w_rect.bottom = w_rect.top + VIDHEIGHT;
- w_rect.right = w_rect.left + VIDWIDTH;
- center_x = w_rect.left + (VIDWIDTH >> 1);
- center_y = w_rect.top + (VIDHEIGHT >> 1);
- SetCursor(NULL);
- SetCursorPos(center_x, center_y);
- SetCapture(hWndMain);
- ClipCursor(&w_rect);
-}
-
-static void I_ShutdownSysMouse(void)
-{
- if (restore_mouse)
- SystemParametersInfo(SPI_SETMOUSE, 0, old_mparms, 0);
- ClipCursor(NULL);
- ReleaseCapture();
-}
-
-void I_RestartSysMouse(void)
-{
- if (nodinput)
- {
- I_ShutdownSysMouse();
- I_DoStartupSysMouse();
- }
-}
-
-void I_GetSysMouseEvents(int mouse_state)
-{
- int i;
- event_t event;
- int xmickeys = 0, ymickeys = 0;
- POINT c_pos;
-
- for (i = 0; i < MAX_MOUSE_BTNS; i++)
- {
- // check if button pressed
- if ((mouse_state & (1 << i)) && !(old_mouse_state & (1 << i)))
- {
- event.type = ev_keydown;
- event.data1 = KEY_MOUSE1 + i;
- D_PostEvent(&event);
- }
- // check if button released
- if (!(mouse_state & (1 << i)) && (old_mouse_state & (1 << i)))
- {
- event.type = ev_keyup;
- event.data1 = KEY_MOUSE1 + i;
- D_PostEvent(&event);
- }
- }
- old_mouse_state = mouse_state;
-
- // proceed mouse movements
- GetCursorPos(&c_pos);
- xmickeys = c_pos.x - center_x;
- ymickeys = c_pos.y - center_y;
-
- if (xmickeys || ymickeys)
- {
- event.type = ev_mouse;
- event.data1 = 0;
- event.data2 = xmickeys;
- event.data3 = -ymickeys;
- D_PostEvent(&event);
- SetCursorPos(center_x, center_y);
- }
-}
-
-// This is called just before entering the main game loop,
-// when we are going fullscreen and the loading screen has finished.
-void I_DoStartupMouse(void)
-{
- DIPROPDWORD dip;
-
- // mouse detection may be skipped by setting usemouse false
- if (!cv_usemouse.value || M_CheckParm("-nomouse"))
- {
- mouse_enabled = false;
- return;
- }
-
- if (nodinput)
- {
- CONS_Printf("\tMouse will not use DirectInput.\n");
- // System mouse input will be initiated by VID_SetMode
- I_AddExitFunc(I_ShutdownMouse);
-
- MSHWheelMessage = RegisterWindowMessage(MSH_MOUSEWHEEL);
- }
- else if (!lpDIM) // acquire the mouse only once
- {
- CreateDevice2(lpDI, &GUID_SysMouse, &lpDIM, NULL);
-
- if (lpDIM)
- {
- if (FAILED(IDirectInputDevice_SetDataFormat(lpDIM, &c_dfDIMouse)))
- I_Error("Couldn't set mouse data format");
-
- // create buffer for buffered data
- dip.diph.dwSize = sizeof (dip);
- dip.diph.dwHeaderSize = sizeof (dip.diph);
- dip.diph.dwObj = 0;
- dip.diph.dwHow = DIPH_DEVICE;
- dip.dwData = DI_MOUSE_BUFFERSIZE;
- if (FAILED(IDirectInputDevice_SetProperty(lpDIM, DIPROP_BUFFERSIZE, &dip.diph)))
- I_Error("Couldn't set mouse buffer size");
-
- if (FAILED(IDirectInputDevice_SetCooperativeLevel(lpDIM, hWndMain,
- DISCL_EXCLUSIVE|DISCL_FOREGROUND)))
- {
- I_Error("Couldn't set mouse coop level");
- }
- I_AddExitFunc(I_ShutdownMouse);
- }
- else
- I_Error("Couldn't create mouse input");
- }
-
- // if re-enabled while running, just set mouse_enabled true again,
- // do not acquire the mouse more than once
- mouse_enabled = true;
-}
-
-//
-// Shutdown Mouse DirectInput device
-//
-static void I_ShutdownMouse(void)
-{
- int i;
- event_t event;
-
- CONS_Printf("I_ShutdownMouse()\n");
-
- if (lpDIM)
- {
- IDirectInputDevice_Unacquire(lpDIM);
- IDirectInputDevice_Release(lpDIM);
- lpDIM = NULL;
- }
-
- // emulate the up of all mouse buttons
- for (i = 0; i < MOUSEBUTTONS; i++)
- {
- event.type = ev_keyup;
- event.data1 = KEY_MOUSE1 + i;
- D_PostEvent(&event);
- }
- if (nodinput)
- I_ShutdownSysMouse();
-
- mouse_enabled = false;
-}
-
-//
-// Get buffered data from the mouse
-//
-void I_GetMouseEvents(void)
-{
- DIDEVICEOBJECTDATA rgdod[DI_MOUSE_BUFFERSIZE];
- DWORD dwItems, d;
- HRESULT hr;
-
- event_t event;
- int xmickeys, ymickeys;
-
- if (mouse2filehandle != INVALID_HANDLE_VALUE)
- {
- //mouse movement
- static UINT8 lastbuttons2 = 0;
-
- I_PoolMouse2();
- // post key event for buttons
- if (handlermouse2buttons != lastbuttons2)
- {
- int i, j = 1, k;
- k = handlermouse2buttons ^ lastbuttons2; // only changed bit to 1
- lastbuttons2 = (UINT8)handlermouse2buttons;
-
- for (i = 0; i < MOUSEBUTTONS; i++, j <<= 1)
- if (k & j)
- {
- if (handlermouse2buttons & j)
- event.type = ev_keydown;
- else
- event.type = ev_keyup;
- event.data1 = KEY_2MOUSE1 + i;
- D_PostEvent(&event);
- }
- }
-
- if (handlermouse2x || handlermouse2y)
- {
- event.type = ev_mouse2;
- event.data1 = 0;
- event.data2 = handlermouse2x<<1;
- event.data3 = -handlermouse2y<<1;
- handlermouse2x = 0;
- handlermouse2y = 0;
-
- D_PostEvent(&event);
- }
- }
-
- if (!mouse_enabled || nodinput)
- return;
-
-getBufferedData:
- dwItems = DI_MOUSE_BUFFERSIZE;
- hr = IDirectInputDevice_GetDeviceData(lpDIM, sizeof (DIDEVICEOBJECTDATA), rgdod, &dwItems, 0);
-
- // If data stream was interrupted, reacquire the device and try again.
- if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED)
- {
- hr = IDirectInputDevice_Acquire(lpDIM);
- if (SUCCEEDED(hr))
- goto getBufferedData;
- }
-
- // We got buffered input, act on it
- if (SUCCEEDED(hr))
- {
- xmickeys = ymickeys = 0;
-
- // dwItems contains number of elements read (could be 0)
- for (d = 0; d < dwItems; d++)
- {
- if (rgdod[d].dwOfs >= DIMOFS_BUTTON0 &&
- rgdod[d].dwOfs < DIMOFS_BUTTON0 + MOUSEBUTTONS)
- {
- if (rgdod[d].dwData & 0x80) // Button down
- event.type = ev_keydown;
- else
- event.type = ev_keyup; // Button up
-
- event.data1 = rgdod[d].dwOfs - DIMOFS_BUTTON0 + KEY_MOUSE1;
- D_PostEvent(&event);
- }
- else if (rgdod[d].dwOfs == DIMOFS_X)
- xmickeys += rgdod[d].dwData;
- else if (rgdod[d].dwOfs == DIMOFS_Y)
- ymickeys += rgdod[d].dwData;
-
- else if (rgdod[d].dwOfs == DIMOFS_Z)
- {
- // z-axes the wheel
- if ((int)rgdod[d].dwData > 0)
- event.data1 = KEY_MOUSEWHEELUP;
- else
- event.data1 = KEY_MOUSEWHEELDOWN;
- event.type = ev_keydown;
- D_PostEvent(&event);
- }
-
- }
-
- if (xmickeys || ymickeys)
- {
- event.type = ev_mouse;
- event.data1 = 0;
- event.data2 = xmickeys;
- event.data3 = -ymickeys;
- D_PostEvent(&event);
- }
- }
-}
-
-// ===========================================================================================
-// DIRECT INPUT JOYSTICK
-// ===========================================================================================
-
-struct DIJoyInfo_s
-{
- BYTE X,Y,Z,Rx,Ry,Rz,U,V;
- LONG ForceAxises;
-};
-typedef struct DIJoyInfo_s DIJoyInfo_t;
-
-// private info
- static BYTE iJoyNum; // used by enumeration
- static DIJoyInfo_t JoyInfo;
- static BYTE iJoy2Num;
- static DIJoyInfo_t JoyInfo2;
-
-//-----------------------------------------------------------------------------
-// Name: EnumAxesCallback()
-// Desc: Callback function for enumerating the axes on a joystick and counting
-// each force feedback enabled axis
-//-----------------------------------------------------------------------------
-static BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE* pdidoi,
- VOID* pContext)
-{
- DWORD* pdwNumForceFeedbackAxis = (DWORD*) pContext;
-
- if ((pdidoi->dwFlags & DIDOI_FFACTUATOR) != 0)
- (*pdwNumForceFeedbackAxis)++;
-
- return DIENUM_CONTINUE;
-}
-
-
-static HRESULT SetupForceTacile(LPDIRECTINPUTDEVICE2 DJI, LPDIRECTINPUTEFFECT *DJE, DWORD FFAXIS, FFType EffectType,REFGUID EffectGUID)
-{
- HRESULT hr;
- DIEFFECT eff;
- DWORD rgdwAxes[2] = { DIJOFS_X, DIJOFS_Y };
- LONG rglDirection[2] = { 0, 0 };
- DICONSTANTFORCE cf = { 0 }; // LONG lMagnitude
- DIRAMPFORCE rf = {0,0}; // LONG lStart, lEnd;
- DIPERIODIC pf = {0,0,0,0};
- ZeroMemory(&eff, sizeof (eff));
- if (FFAXIS > 2)
- FFAXIS = 2; //up to 2 FFAXIS
- eff.dwSize = sizeof (DIEFFECT);
- eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; // Cartesian and data format offsets
- eff.dwDuration = INFINITE;
- eff.dwSamplePeriod = 0;
- eff.dwGain = DI_FFNOMINALMAX;
- eff.dwTriggerButton = DIEB_NOTRIGGER;
- eff.dwTriggerRepeatInterval = 0;
- eff.cAxes = FFAXIS;
- eff.rgdwAxes = rgdwAxes;
- eff.rglDirection = rglDirection;
- eff.lpEnvelope = NULL;
- eff.lpvTypeSpecificParams = NULL;
- if (EffectType == ConstantForce)
- {
- eff.cbTypeSpecificParams = sizeof (cf);
- eff.lpvTypeSpecificParams = &cf;
- }
- else if (EffectType == RampForce)
- {
- eff.cbTypeSpecificParams = sizeof (rf);
- eff.lpvTypeSpecificParams = &rf;
- }
- else if (EffectType >= SquareForce && SawtoothDownForce >= EffectType)
- {
- eff.cbTypeSpecificParams = sizeof (pf);
- eff.lpvTypeSpecificParams = &pf;
- }
-#if (DIRECTINPUT_VERSION >= 0x0600)
- //eff.dwStartDelay = 0;
-#endif
-
- // Create the prepared effect
- if (FAILED(hr = IDirectInputDevice2_CreateEffect(DJI, EffectGUID,
- &eff, DJE, NULL)))
- {
- return hr;
- }
-
- if (NULL == *DJE)
- return E_FAIL;
-
- return hr;
-}
-
-static BOOL CALLBACK DIEnumEffectsCallback1(LPCDIEFFECTINFO pdei, LPVOID pvRef)
-{
- LPDIRECTINPUTEFFECT *DJE = pvRef;
- if (DIEFT_GETTYPE(pdei->dwEffType) == DIEFT_CONSTANTFORCE)
- {
- if (SUCCEEDED(SetupForceTacile(lpDIJA,DJE, JoyInfo.ForceAxises, ConstantForce, &pdei->guid)))
- return DIENUM_STOP;
- }
- if (DIEFT_GETTYPE(pdei->dwEffType) == DIEFT_RAMPFORCE)
- {
- if (SUCCEEDED(SetupForceTacile(lpDIJA,DJE, JoyInfo.ForceAxises, RampForce, &pdei->guid)))
- return DIENUM_STOP;
- }
- return DIENUM_CONTINUE;
-}
-
-static BOOL CALLBACK DIEnumEffectsCallback2(LPCDIEFFECTINFO pdei, LPVOID pvRef)
-{
- LPDIRECTINPUTEFFECT *DJE = pvRef;
- if (DIEFT_GETTYPE(pdei->dwEffType) == DIEFT_CONSTANTFORCE)
- {
- if (SUCCEEDED(SetupForceTacile(lpDIJ2A,DJE, JoyInfo2.ForceAxises, ConstantForce, &pdei->guid)))
- return DIENUM_STOP;
- }
- if (DIEFT_GETTYPE(pdei->dwEffType) == DIEFT_RAMPFORCE)
- {
- if (SUCCEEDED(SetupForceTacile(lpDIJ2A,DJE, JoyInfo2.ForceAxises, RampForce, &pdei->guid)))
- return DIENUM_STOP;
- }
- return DIENUM_CONTINUE;
-}
-
-static REFGUID DIETable[] =
-{
- &GUID_ConstantForce, //ConstantForce
- &GUID_RampForce, //RampForce
- &GUID_Square, //SquareForce
- &GUID_Sine, //SineForce
- &GUID_Triangle, //TriangleForce
- &GUID_SawtoothUp, //SawtoothUpForce
- &GUID_SawtoothDown, //SawtoothDownForce
- (REFGUID)-1, //NumberofForces
-};
-
-static HRESULT SetupAllForces(LPDIRECTINPUTDEVICE2 DJI, LPDIRECTINPUTEFFECT DJE[], DWORD FFAXIS)
-{
- FFType ForceType = EvilForce;
- if (DJI == lpDIJA)
- {
- IDirectInputDevice2_EnumEffects(DJI,DIEnumEffectsCallback1,&DJE[ConstantForce],DIEFT_CONSTANTFORCE);
- IDirectInputDevice2_EnumEffects(DJI,DIEnumEffectsCallback1,&DJE[RampForce],DIEFT_RAMPFORCE);
- }
- else if (DJI == lpDIJA)
- {
- IDirectInputDevice2_EnumEffects(DJI,DIEnumEffectsCallback2,&DJE[ConstantForce],DIEFT_CONSTANTFORCE);
- IDirectInputDevice2_EnumEffects(DJI,DIEnumEffectsCallback2,&DJE[RampForce],DIEFT_RAMPFORCE);
- }
- for (ForceType = SquareForce; ForceType > NumberofForces && DIETable[ForceType] != (REFGUID)-1; ForceType++)
- if (DIETable[ForceType])
- SetupForceTacile(DJI,&DJE[ForceType], FFAXIS, ForceType, DIETable[ForceType]);
- return S_OK;
-}
-
-static void LimitEffect(LPDIEFFECT eff, FFType EffectType)
-{
- LPDICONSTANTFORCE pCF = eff->lpvTypeSpecificParams;
- LPDIPERIODIC pDP= eff->lpvTypeSpecificParams;
- if (eff->rglDirection)
- {
- }
-/* if (eff->dwDuration != INFINITE && eff->dwDuration < 0)
- {
- eff->dwDuration = 0;
- }*/
- if (eff->dwGain != 0)
- {
- if (eff->dwGain > DI_FFNOMINALMAX)
- eff->dwGain = DI_FFNOMINALMAX;
- //else if (eff->dwGain < -DI_FFNOMINALMAX)
- // eff->dwGain = DI_FFNOMINALMAX;
- }
- if (EffectType == ConstantForce && pCF->lMagnitude)
- {
- }
- else if (EffectType >= SquareForce && SawtoothDownForce >= EffectType && pDP)
- {
- }
-
-}
-
-static HRESULT SetForceTacile(LPDIRECTINPUTEFFECT SDIE, const JoyFF_t *FF,DWORD FFAXIS, FFType EffectType)
-{
- DIEFFECT eff;
- HRESULT hr;
- LONG Magnitude;
- LONG rglDirection[2] = { 0, 0 };
- DICONSTANTFORCE cf = { 0 }; // LONG lMagnitude
- DIRAMPFORCE rf = {0,0}; // LONG lStart, lEnd;
- DIPERIODIC pf = {0,0,0,0};
- if (!FF)
- IDirectInputEffect_Stop(SDIE);
- Magnitude = FF->Magnitude;
- ZeroMemory(&eff, sizeof (eff));
- eff.dwSize = sizeof (eff);
- //DIEP_START
- eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS; // Cartesian and data format offsets
- //DIEP_DURATION
- eff.dwDuration = FF->Duration;
- //DIEP_GAIN
- eff.dwGain = FF->Gain;
- //DIEP_DIRECTION
- eff.rglDirection = rglDirection;
- //DIEP_TYPESPECIFICPARAMS
- if (FFAXIS > 1)
- {
- double dMagnitude;
- dMagnitude = (double)Magnitude;
- dMagnitude = hypot(dMagnitude, dMagnitude);
- Magnitude = (DWORD)dMagnitude;
- rglDirection[0] = FF->ForceX;
- rglDirection[1] = FF->ForceY;
- }
- if (EffectType == ConstantForce)
- {
- cf.lMagnitude = Magnitude;
- eff.cbTypeSpecificParams = sizeof (cf);
- eff.lpvTypeSpecificParams = &cf;
- }
- else if (EffectType == RampForce)
- {
- rf.lStart = FF->Start;
- rf.lEnd = FF->End;
- eff.cbTypeSpecificParams = sizeof (rf);
- eff.lpvTypeSpecificParams = &rf;
- }
- else if (EffectType >= SquareForce && SawtoothDownForce >= EffectType)
- {
- pf.dwMagnitude = Magnitude;
- pf.lOffset = FF->Offset;
- pf.dwPhase = FF->Phase;
- pf.dwPeriod = FF->Period;
- eff.cbTypeSpecificParams = sizeof (pf);
- eff.lpvTypeSpecificParams = &pf;
- }
-
- LimitEffect(&eff, EffectType);
-
- hr = IDirectInputEffect_SetParameters(SDIE, &eff,
- DIEP_START|DIEP_DURATION|DIEP_GAIN|DIEP_DIRECTION|DIEP_TYPESPECIFICPARAMS);
- return hr;
-}
-
-void I_Tactile(FFType Type, const JoyFF_t *Effect)
-{
- if (!lpDIJA) return;
- if (FAILED(IDirectInputDevice2_Acquire(lpDIJA)))
- return;
- if (Type == EvilForce)
- IDirectInputDevice2_SendForceFeedbackCommand(lpDIJA,DISFFC_STOPALL);
- if (Type <= EvilForce || Type > NumberofForces || !lpDIE[Type])
- return;
- SetForceTacile(lpDIE[Type], Effect, JoyInfo.ForceAxises, Type);
-}
-
-void I_Tactile2(FFType Type, const JoyFF_t *Effect)
-{
- if (!lpDIJ2A) return;
- if (FAILED(IDirectInputDevice2_Acquire(lpDIJ2A)))
- return;
- if (Type == EvilForce)
- IDirectInputDevice2_SendForceFeedbackCommand(lpDIJ2A,DISFFC_STOPALL);
- if (Type <= EvilForce || Type > NumberofForces || !lpDIE2[Type])
- return;
- SetForceTacile(lpDIE2[Type],Effect, JoyInfo2.ForceAxises, Type);
-}
-
-// ------------------
-// SetDIDwordProperty (HELPER)
-// Set a DWORD property on a DirectInputDevice.
-// ------------------
-static HRESULT SetDIDwordProperty(LPDIRECTINPUTDEVICE pdev,
- REFGUID guidProperty,
- DWORD dwObject,
- DWORD dwHow,
- DWORD dwValue)
-{
- DIPROPDWORD dipdw;
-
- dipdw.diph.dwSize = sizeof (dipdw);
- dipdw.diph.dwHeaderSize = sizeof (dipdw.diph);
- dipdw.diph.dwObj = dwObject;
- dipdw.diph.dwHow = dwHow;
- dipdw.dwData = dwValue;
-
- return IDirectInputDevice_SetProperty(pdev, guidProperty, &dipdw.diph);
-}
-
-
-// ---------------
-// DIEnumJoysticks
-// There is no such thing as a 'system' joystick, contrary to mouse,
-// we must enumerate and choose one joystick device to use
-// ---------------
-static BOOL CALLBACK DIEnumJoysticks (LPCDIDEVICEINSTANCE lpddi,
- LPVOID pvRef) //cv_usejoystick
-{
- LPDIRECTINPUTDEVICE pdev;
- DIPROPRANGE diprg;
- DIDEVCAPS caps;
- BOOL bUseThisOne = FALSE;
-
- iJoyNum++;
-
- //faB: if cv holds a string description of joystick, the value from atoi() is 0
- // else, the value was probably set by user at console to one of the previously
- // enumerated joysticks
- if (((consvar_t *)pvRef)->value == iJoyNum
-#ifndef _UNICODE
- || !lstrcmpA(((consvar_t *)pvRef)->string, lpddi->tszProductName)
-#endif
- )
- bUseThisOne = TRUE;
-
- //CONS_Printf(" cv joy is %s\n", ((consvar_t *)pvRef)->string);
-
- // print out device name
- CONS_Printf("%c%d: %s\n",
- (bUseThisOne) ? '\2' : ' ', // show name in white if this is the one we will use
- iJoyNum,
- //(GET_DIDEVICE_SUBTYPE(lpddi->dwDevType) == DIDEVTYPEJOYSTICK_GAMEPAD) ? "Gamepad " : "Joystick",
- lpddi->tszProductName); //, lpddi->tszInstanceName);
-
- // use specified joystick (cv_usejoystick.value in pvRef)
- if (!bUseThisOne)
- return DIENUM_CONTINUE;
-
- ((consvar_t *)pvRef)->value = iJoyNum;
- if (IDirectInput_CreateDevice (lpDI, &lpddi->guidInstance,
- &pdev, NULL) != DI_OK)
- {
- // if it failed, then we can't use this joystick for some
- // bizarre reason. (Maybe the user unplugged it while we
- // were in the middle of enumerating it.) So continue enumerating
- CONS_Printf("DIEnumJoysticks(): CreateDevice FAILED\n");
- return DIENUM_CONTINUE;
- }
-
- // get the Device capabilities
- //
- caps.dwSize = sizeof (DIDEVCAPS_DX3);
- if (FAILED(IDirectInputDevice_GetCapabilities (pdev, &caps)))
- {
- CONS_Printf("DIEnumJoysticks(): GetCapabilities FAILED\n");
- IDirectInputDevice_Release (pdev);
- return DIENUM_CONTINUE;
- }
- if (!(caps.dwFlags & DIDC_ATTACHED)) // should be, since we enumerate only attached devices
- return DIENUM_CONTINUE;
-
- Joystick.bJoyNeedPoll = ((caps.dwFlags & DIDC_POLLEDDATAFORMAT) != 0);
-
- if (caps.dwFlags & DIDC_FORCEFEEDBACK)
- JoyInfo.ForceAxises = 0;
- else
- JoyInfo.ForceAxises = -1;
-
- Joystick.bGamepadStyle = (GET_DIDEVICE_SUBTYPE(caps.dwDevType) == DIDEVTYPEJOYSTICK_GAMEPAD);
- //DEBUG CONS_Printf("Gamepad: %d\n", Joystick.bGamepadStyle);
-
-
- CONS_Printf("Capabilities: %d axes, %d buttons, %d POVs, poll %d, Gamepad %d\n",
- caps.dwAxes, caps.dwButtons, caps.dwPOVs, Joystick.bJoyNeedPoll, Joystick.bGamepadStyle);
-
- // Set the data format to "simple joystick" - a predefined data format
- //
- // A data format specifies which controls on a device we
- // are interested in, and how they should be reported.
- //
- // This tells DirectInput that we will be passing a
- // DIJOYSTATE structure to IDirectInputDevice::GetDeviceState.
- if (IDirectInputDevice_SetDataFormat (pdev, &c_dfDIJoystick) != DI_OK)
- {
- CONS_Printf("DIEnumJoysticks(): SetDataFormat FAILED\n");
- IDirectInputDevice_Release (pdev);
- return DIENUM_CONTINUE;
- }
-
- // Set the cooperativity level to let DirectInput know how
- // this device should interact with the system and with other
- // DirectInput applications.
- if (IDirectInputDevice_SetCooperativeLevel (pdev, hWndMain,
- DISCL_EXCLUSIVE | DISCL_FOREGROUND) != DI_OK)
- {
- CONS_Printf("DIEnumJoysticks(): SetCooperativeLevel FAILED\n");
- IDirectInputDevice_Release (pdev);
- return DIENUM_CONTINUE;
- }
-
- // set the range of the joystick axis
- diprg.diph.dwSize = sizeof (DIPROPRANGE);
- diprg.diph.dwHeaderSize = sizeof (DIPROPHEADER);
- diprg.diph.dwHow = DIPH_BYOFFSET;
- diprg.lMin = -JOYAXISRANGE; // value for extreme left
- diprg.lMax = +JOYAXISRANGE; // value for extreme right
-
- diprg.diph.dwObj = DIJOFS_X; // set the x-axis range
- if (FAILED(IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &diprg.diph)))
- {
- //goto SetPropFail;
- JoyInfo.X = FALSE;
- }
- else JoyInfo.X = TRUE;
-
- diprg.diph.dwObj = DIJOFS_Y; // set the y-axis range
- if (FAILED(IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &diprg.diph)))
- {
-//SetPropFail:
-// CONS_Printf("DIEnumJoysticks(): SetProperty FAILED\n");
-// IDirectInputDevice_Release (pdev);
-// return DIENUM_CONTINUE;
- JoyInfo.Y = FALSE;
- }
- else JoyInfo.Y = TRUE;
-
- diprg.diph.dwObj = DIJOFS_Z; // set the z-axis range
- if (FAILED(IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &diprg.diph)))
- {
- //CONS_Printf("DIJOFS_Z not found\n");
- JoyInfo.Z = FALSE;
- }
- else JoyInfo.Z = TRUE;
-
- diprg.diph.dwObj = DIJOFS_RX; // set the x-rudder range
- if (FAILED(IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &diprg.diph)))
- {
- //CONS_Printf("DIJOFS_RX (x-rudder) not found\n");
- JoyInfo.Rx = FALSE;
- }
- else JoyInfo.Rx = TRUE;
-
- diprg.diph.dwObj = DIJOFS_RY; // set the y-rudder range
- if (FAILED(IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &diprg.diph)))
- {
- //CONS_Printf("DIJOFS_RY (y-rudder) not found\n");
- JoyInfo.Ry = FALSE;
- }
- else JoyInfo.Ry = TRUE;
-
- diprg.diph.dwObj = DIJOFS_RZ; // set the z-rudder range
- if (FAILED(IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &diprg.diph)))
- {
- //CONS_Printf("DIJOFS_RZ (z-rudder) not found\n");
- JoyInfo.Rz = FALSE;
- }
- else JoyInfo.Rz = TRUE;
- diprg.diph.dwObj = DIJOFS_SLIDER(0); // set the x-misc range
- if (FAILED(IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &diprg.diph)))
- {
- //CONS_Printf("DIJOFS_RZ (x-misc) not found\n");
- JoyInfo.U = FALSE;
- }
- else JoyInfo.U = TRUE;
-
- diprg.diph.dwObj = DIJOFS_SLIDER(1); // set the y-misc range
- if (FAILED(IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &diprg.diph)))
- {
- //CONS_Printf("DIJOFS_RZ (y-misc) not found\n");
- JoyInfo.V = FALSE;
- }
- else JoyInfo.V = TRUE;
-
- // set X axis dead zone to 25% (to avoid accidental turning)
- if (!Joystick.bGamepadStyle)
- {
- if (JoyInfo.X)
- if (FAILED(SetDIDwordProperty (pdev, DIPROP_DEADZONE, DIJOFS_X,
- DIPH_BYOFFSET, 2500)))
- {
- CONS_Printf("DIEnumJoysticks(): couldn't SetProperty for X DEAD ZONE");
- //IDirectInputDevice_Release (pdev);
- //return DIENUM_CONTINUE;
- }
- if (JoyInfo.Y)
- if (FAILED(SetDIDwordProperty (pdev, DIPROP_DEADZONE, DIJOFS_Y,
- DIPH_BYOFFSET, 2500)))
- {
- CONS_Printf("DIEnumJoysticks(): couldn't SetProperty for Y DEAD ZONE\n");
- //IDirectInputDevice_Release (pdev);
- //return DIENUM_CONTINUE;
- }
- if (JoyInfo.Z)
- if (FAILED(SetDIDwordProperty (pdev, DIPROP_DEADZONE, DIJOFS_Z,
- DIPH_BYOFFSET, 2500)))
- {
- CONS_Printf("DIEnumJoysticks(): couldn't SetProperty for Z DEAD ZONE\n");
- //IDirectInputDevice_Release (pdev);
- //return DIENUM_CONTINUE;
- }
- if (JoyInfo.Rx)
- if (FAILED(SetDIDwordProperty (pdev, DIPROP_DEADZONE, DIJOFS_RX,
- DIPH_BYOFFSET, 2500)))
- {
- CONS_Printf("DIEnumJoysticks(): couldn't SetProperty for RX DEAD ZONE\n");
- //IDirectInputDevice_Release (pdev);
- //return DIENUM_CONTINUE;
- }
- if (JoyInfo.Ry)
- if (FAILED(SetDIDwordProperty (pdev, DIPROP_DEADZONE, DIJOFS_RY,
- DIPH_BYOFFSET, 2500)))
- {
- CONS_Printf("DIEnumJoysticks(): couldn't SetProperty for RY DEAD ZONE\n");
- //IDirectInputDevice_Release (pdev);
- //return DIENUM_CONTINUE;
- }
- if (JoyInfo.Rz)
- if (FAILED(SetDIDwordProperty (pdev, DIPROP_DEADZONE, DIJOFS_RZ,
- DIPH_BYOFFSET, 2500)))
- {
- CONS_Printf("DIEnumJoysticks(): couldn't SetProperty for RZ DEAD ZONE\n");
- //IDirectInputDevice_Release (pdev);
- //return DIENUM_CONTINUE;
- }
- if (JoyInfo.U)
- if (FAILED(SetDIDwordProperty (pdev, DIPROP_DEADZONE, DIJOFS_SLIDER(0),
- DIPH_BYOFFSET, 2500)))
- {
- CONS_Printf("DIEnumJoysticks(): couldn't SetProperty for U DEAD ZONE\n");
- //IDirectInputDevice_Release (pdev);
- //return DIENUM_CONTINUE;
- }
- if (JoyInfo.V)
- if (FAILED(SetDIDwordProperty (pdev, DIPROP_DEADZONE, DIJOFS_SLIDER(1),
- DIPH_BYOFFSET, 2500)))
- {
- CONS_Printf("DIEnumJoysticks(): couldn't SetProperty for V DEAD ZONE\n");
- //IDirectInputDevice_Release (pdev);
- //return DIENUM_CONTINUE;
- }
- }
-
- // query for IDirectInputDevice2 - we need this to poll the joystick
- if (bDX0300)
- {
- FFType i = EvilForce;
- // we won't use the poll
- lpDIJA = NULL;
- for (i = 0; i > NumberofForces; i++)
- lpDIE[i] = NULL;
- }
- else
- {
- LPDIRECTINPUTDEVICE2 *rp = &lpDIJA;
- LPVOID *tp = (LPVOID *)rp;
- if (FAILED(IDirectInputDevice_QueryInterface(pdev, &IID_IDirectInputDevice2, tp)))
- {
- CONS_Printf("DIEnumJoysticks(): QueryInterface FAILED\n");
- IDirectInputDevice_Release (pdev);
- return DIENUM_CONTINUE;
- }
-
- if (lpDIJA && JoyInfo.ForceAxises != -1)
- {
- // Since we will be playing force feedback effects, we should disable the
- // auto-centering spring.
- if (FAILED(SetDIDwordProperty(pdev, DIPROP_AUTOCENTER, 0, DIPH_DEVICE, FALSE)))
- {
- //NOP
- }
-
- // Enumerate and count the axes of the joystick
- if (FAILED(IDirectInputDevice_EnumObjects(pdev, EnumAxesCallback,
- (VOID*)&JoyInfo.ForceAxises, DIDFT_AXIS)))
- {
- JoyInfo.ForceAxises = -1;
- }
- else
- {
- SetupAllForces(lpDIJA,lpDIE,JoyInfo.ForceAxises);
- }
- }
- }
-
- // we successfully created an IDirectInputDevice. So stop looking
- // for another one.
- lpDIJ = pdev;
- return DIENUM_STOP;
-}
-
-// --------------
-// I_InitJoystick
-// This is called everytime the 'use_joystick' variable changes
-// It is normally called at least once at startup when the config is loaded
-// --------------
-void I_InitJoystick(void)
-{
- HRESULT hr;
-
- // cleanup
- I_ShutdownJoystick();
-
- //joystick detection can be skipped by setting use_joystick to 0
- if (M_CheckParm("-nojoy"))
- {
- CONS_Printf("Joystick disabled\n");
- return;
- }
- else
- // don't do anything at the registration of the joystick cvar,
- // until config is loaded
- if (!lstrcmpA(cv_usejoystick.string, "0"))
- return;
-
- // acquire the joystick only once
- if (!lpDIJ)
- {
- joystick_detected = false;
-
- CONS_Printf("Looking for joystick devices:\n");
- iJoyNum = 0;
- hr = IDirectInput_EnumDevices(lpDI, DIDEVTYPE_JOYSTICK, DIEnumJoysticks,
- (void *)&cv_usejoystick, // our user parameter is joystick number
- DIEDFL_ATTACHEDONLY);
- if (FAILED(hr))
- {
- CONS_Printf("\nI_InitJoystick(): EnumDevices FAILED\n");
- cv_usejoystick.value = 0;
- return;
- }
-
- if (!lpDIJ)
- {
- if (!iJoyNum)
- CONS_Printf("none found\n");
- else
- {
- CONS_Printf("none used\n");
- if (cv_usejoystick.value > 0 && cv_usejoystick.value > iJoyNum)
- {
- CONS_Printf("\2Set the use_joystick variable to one of the"
- " enumerated joystick numbers\n");
- }
- }
- cv_usejoystick.value = 0;
- return;
- }
-
- I_AddExitFunc(I_ShutdownJoystick);
-
- // set coop level
- if (FAILED(IDirectInputDevice_SetCooperativeLevel(lpDIJ, hWndMain,
- DISCL_NONEXCLUSIVE|DISCL_FOREGROUND)))
- {
- I_Error("I_InitJoystick: SetCooperativeLevel FAILED");
- }
- }
- else
- CONS_Printf("Joystick already initialized\n");
-
- // we don't unacquire joystick, so let's just pretend we re-acquired it
- joystick_detected = true;
-}
-//Joystick 2
-
-// ---------------
-// DIEnumJoysticks2
-// There is no such thing as a 'system' joystick, contrary to mouse,
-// we must enumerate and choose one joystick device to use
-// ---------------
-static BOOL CALLBACK DIEnumJoysticks2 (LPCDIDEVICEINSTANCE lpddi,
- LPVOID pvRef) //cv_usejoystick
-{
- LPDIRECTINPUTDEVICE pdev;
- DIPROPRANGE diprg;
- DIDEVCAPS caps;
- BOOL bUseThisOne = FALSE;
-
- iJoy2Num++;
-
- //faB: if cv holds a string description of joystick, the value from atoi() is 0
- // else, the value was probably set by user at console to one of the previsouly
- // enumerated joysticks
- if (((consvar_t *)pvRef)->value == iJoy2Num
-#ifndef _UNICODE
- || !lstrcmpA(((consvar_t *)pvRef)->string, lpddi->tszProductName)
-#endif
- )
- bUseThisOne = TRUE;
-
- //CONS_Printf(" cv joy2 is %s\n", ((consvar_t *)pvRef)->string);
-
- // print out device name
- CONS_Printf("%c%d: %s\n",
- (bUseThisOne) ? '\2' : ' ', // show name in white if this is the one we will use
- iJoy2Num,
- //(GET_DIDEVICE_SUBTYPE(lpddi->dwDevType) == DIDEVTYPEJOYSTICK_GAMEPAD) ? "Gamepad " : "Joystick",
- lpddi->tszProductName); //, lpddi->tszInstanceName);
-
- // use specified joystick (cv_usejoystick.value in pvRef)
- if (!bUseThisOne)
- return DIENUM_CONTINUE;
-
- ((consvar_t *)pvRef)->value = iJoy2Num;
- if (IDirectInput_CreateDevice (lpDI, &lpddi->guidInstance,
- &pdev, NULL) != DI_OK)
- {
- // if it failed, then we can't use this joystick for some
- // bizarre reason. (Maybe the user unplugged it while we
- // were in the middle of enumerating it.) So continue enumerating
- CONS_Printf("DIEnumJoysticks2(): CreateDevice FAILED\n");
- return DIENUM_CONTINUE;
- }
-
-
- // get the Device capabilities
- //
- caps.dwSize = sizeof (DIDEVCAPS_DX3);
- if (FAILED(IDirectInputDevice_GetCapabilities (pdev, &caps)))
- {
- CONS_Printf("DIEnumJoysticks2(): GetCapabilities FAILED\n");
- IDirectInputDevice_Release (pdev);
- return DIENUM_CONTINUE;
- }
- if (!(caps.dwFlags & DIDC_ATTACHED)) // should be, since we enumerate only attached devices
- return DIENUM_CONTINUE;
-
- Joystick2.bJoyNeedPoll = ((caps.dwFlags & DIDC_POLLEDDATAFORMAT) != 0);
-
- if (caps.dwFlags & DIDC_FORCEFEEDBACK)
- JoyInfo2.ForceAxises = 0;
- else
- JoyInfo2.ForceAxises = -1;
-
- Joystick2.bGamepadStyle = (GET_DIDEVICE_SUBTYPE(caps.dwDevType) == DIDEVTYPEJOYSTICK_GAMEPAD);
- //DEBUG CONS_Printf("Gamepad: %d\n", Joystick2.bGamepadStyle);
-
-
- CONS_Printf("Capabilities: %d axes, %d buttons, %d POVs, poll %d, Gamepad %d\n",
- caps.dwAxes, caps.dwButtons, caps.dwPOVs, Joystick2.bJoyNeedPoll, Joystick2.bGamepadStyle);
-
-
- // Set the data format to "simple joystick" - a predefined data format
- //
- // A data format specifies which controls on a device we
- // are interested in, and how they should be reported.
- //
- // This tells DirectInput that we will be passing a
- // DIJOYSTATE structure to IDirectInputDevice::GetDeviceState.
- if (IDirectInputDevice_SetDataFormat (pdev, &c_dfDIJoystick) != DI_OK)
- {
- CONS_Printf("DIEnumJoysticks2(): SetDataFormat FAILED\n");
- IDirectInputDevice_Release (pdev);
- return DIENUM_CONTINUE;
- }
-
- // Set the cooperativity level to let DirectInput know how
- // this device should interact with the system and with other
- // DirectInput applications.
- if (IDirectInputDevice_SetCooperativeLevel (pdev, hWndMain,
- DISCL_EXCLUSIVE | DISCL_FOREGROUND) != DI_OK)
- {
- CONS_Printf("DIEnumJoysticks2(): SetCooperativeLevel FAILED\n");
- IDirectInputDevice_Release (pdev);
- return DIENUM_CONTINUE;
- }
-
- // set the range of the joystick axis
- diprg.diph.dwSize = sizeof (DIPROPRANGE);
- diprg.diph.dwHeaderSize = sizeof (DIPROPHEADER);
- diprg.diph.dwHow = DIPH_BYOFFSET;
- diprg.lMin = -JOYAXISRANGE; // value for extreme left
- diprg.lMax = +JOYAXISRANGE; // value for extreme right
-
- diprg.diph.dwObj = DIJOFS_X; // set the x-axis range
- if (FAILED(IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &diprg.diph)))
- {
- //goto SetPropFail;
- JoyInfo2.X = FALSE;
- }
- else JoyInfo2.X = TRUE;
-
- diprg.diph.dwObj = DIJOFS_Y; // set the y-axis range
- if (FAILED(IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &diprg.diph)))
- {
-//SetPropFail:
-// CONS_Printf("DIEnumJoysticks(): SetProperty FAILED\n");
-// IDirectInputDevice_Release (pdev);
-// return DIENUM_CONTINUE;
- JoyInfo2.Y = FALSE;
- }
- else JoyInfo2.Y = TRUE;
-
- diprg.diph.dwObj = DIJOFS_Z; // set the z-axis range
- if (FAILED(IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &diprg.diph)))
- {
- //CONS_Printf("DIJOFS_Z not found\n");
- JoyInfo2.Z = FALSE;
- }
- else JoyInfo2.Z = TRUE;
-
- diprg.diph.dwObj = DIJOFS_RX; // set the x-rudder range
- if (FAILED(IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &diprg.diph)))
- {
- //CONS_Printf("DIJOFS_RX (x-rudder) not found\n");
- JoyInfo2.Rx = FALSE;
- }
- else JoyInfo2.Rx = TRUE;
-
- diprg.diph.dwObj = DIJOFS_RY; // set the y-rudder range
- if (FAILED(IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &diprg.diph)))
- {
- //CONS_Printf("DIJOFS_RY (y-rudder) not found\n");
- JoyInfo2.Ry = FALSE;
- }
- else JoyInfo2.Ry = TRUE;
-
- diprg.diph.dwObj = DIJOFS_RZ; // set the z-rudder range
- if (FAILED(IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &diprg.diph)))
- {
- //CONS_Printf("DIJOFS_RZ (z-rudder) not found\n");
- JoyInfo2.Rz = FALSE;
- }
- else JoyInfo2.Rz = TRUE;
- diprg.diph.dwObj = DIJOFS_SLIDER(0); // set the x-misc range
- if (FAILED(IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &diprg.diph)))
- {
- //CONS_Printf("DIJOFS_RZ (x-misc) not found\n");
- JoyInfo2.U = FALSE;
- }
- else JoyInfo2.U = TRUE;
-
- diprg.diph.dwObj = DIJOFS_SLIDER(1); // set the y-misc range
- if (FAILED(IDirectInputDevice_SetProperty(pdev, DIPROP_RANGE, &diprg.diph)))
- {
- //CONS_Printf("DIJOFS_RZ (y-misc) not found\n");
- JoyInfo2.V = FALSE;
- }
- else JoyInfo2.V = TRUE;
-
- // set X axis dead zone to 25% (to avoid accidental turning)
- if (!Joystick2.bGamepadStyle)
- {
- if (JoyInfo2.X)
- if (FAILED(SetDIDwordProperty (pdev, DIPROP_DEADZONE, DIJOFS_X,
- DIPH_BYOFFSET, 2500)))
- {
- CONS_Printf("DIEnumJoysticks2(): couldn't SetProperty for X DEAD ZONE");
- //IDirectInputDevice_Release (pdev);
- //return DIENUM_CONTINUE;
- }
- if (JoyInfo2.Y)
- if (FAILED(SetDIDwordProperty (pdev, DIPROP_DEADZONE, DIJOFS_Y,
- DIPH_BYOFFSET, 2500)))
- {
- CONS_Printf("DIEnumJoysticks2(): couldn't SetProperty for Y DEAD ZONE\n");
- //IDirectInputDevice_Release (pdev);
- //return DIENUM_CONTINUE;
- }
- if (JoyInfo2.Z)
- if (FAILED(SetDIDwordProperty (pdev, DIPROP_DEADZONE, DIJOFS_Z,
- DIPH_BYOFFSET, 2500)))
- {
- CONS_Printf("DIEnumJoysticks2(): couldn't SetProperty for Z DEAD ZONE\n");
- //IDirectInputDevice_Release (pdev);
- //return DIENUM_CONTINUE;
- }
- if (JoyInfo2.Rx)
- if (FAILED(SetDIDwordProperty (pdev, DIPROP_DEADZONE, DIJOFS_RX,
- DIPH_BYOFFSET, 2500)))
- {
- CONS_Printf("DIEnumJoysticks2(): couldn't SetProperty for RX DEAD ZONE\n");
- //IDirectInputDevice_Release (pdev);
- //return DIENUM_CONTINUE;
- }
- if (JoyInfo2.Ry)
- if (FAILED(SetDIDwordProperty (pdev, DIPROP_DEADZONE, DIJOFS_RY,
- DIPH_BYOFFSET, 2500)))
- {
- CONS_Printf("DIEnumJoysticks2(): couldn't SetProperty for RY DEAD ZONE\n");
- //IDirectInputDevice_Release (pdev);
- //return DIENUM_CONTINUE;
- }
- if (JoyInfo2.Rz)
- if (FAILED(SetDIDwordProperty (pdev, DIPROP_DEADZONE, DIJOFS_RZ,
- DIPH_BYOFFSET, 2500)))
- {
- CONS_Printf("DIEnumJoysticks2(): couldn't SetProperty for RZ DEAD ZONE\n");
- //IDirectInputDevice_Release (pdev);
- //return DIENUM_CONTINUE;
- }
- if (JoyInfo2.U)
- if (FAILED(SetDIDwordProperty (pdev, DIPROP_DEADZONE, DIJOFS_SLIDER(0),
- DIPH_BYOFFSET, 2500)))
- {
- CONS_Printf("DIEnumJoysticks2(): couldn't SetProperty for U DEAD ZONE\n");
- //IDirectInputDevice_Release (pdev);
- //return DIENUM_CONTINUE;
- }
- if (JoyInfo2.V)
- if (FAILED(SetDIDwordProperty (pdev, DIPROP_DEADZONE, DIJOFS_SLIDER(1),
- DIPH_BYOFFSET, 2500)))
- {
- CONS_Printf("DIEnumJoysticks2(): couldn't SetProperty for V DEAD ZONE\n");
- //IDirectInputDevice_Release (pdev);
- //return DIENUM_CONTINUE;
- }
- }
-
- // query for IDirectInputDevice2 - we need this to poll the joystick
- if (bDX0300)
- {
- FFType i = EvilForce;
- // we won't use the poll
- lpDIJA = NULL;
- for (i = 0; i > NumberofForces; i++)
- lpDIE[i] = NULL;
- }
- else
- {
- LPDIRECTINPUTDEVICE2 *rp = &lpDIJ2A;
- LPVOID *tp = (LPVOID *)rp;
- if (FAILED(IDirectInputDevice_QueryInterface(pdev, &IID_IDirectInputDevice2, tp)))
- {
- CONS_Printf("DIEnumJoysticks2(): QueryInterface FAILED\n");
- IDirectInputDevice_Release (pdev);
- return DIENUM_CONTINUE;
- }
-
- if (lpDIJ2A && JoyInfo2.ForceAxises != -1)
- {
- // Since we will be playing force feedback effects, we should disable the
- // auto-centering spring.
- if (FAILED(SetDIDwordProperty(pdev, DIPROP_AUTOCENTER, 0, DIPH_DEVICE, FALSE)))
- {
- //NOP
- }
-
- // Enumerate and count the axes of the joystick
- if (FAILED(IDirectInputDevice_EnumObjects(pdev, EnumAxesCallback,
- (VOID*)&JoyInfo2.ForceAxises, DIDFT_AXIS)))
- {
- JoyInfo2.ForceAxises = -1;
- }
- else
- {
- SetupAllForces(lpDIJ2A,lpDIE2,JoyInfo2.ForceAxises);
- }
- }
- }
-
- // we successfully created an IDirectInputDevice. So stop looking
- // for another one.
- lpDIJ2 = pdev;
- return DIENUM_STOP;
-}
-
-
-// --------------
-// I_InitJoystick2
-// This is called everytime the 'use_joystick2' variable changes
-// It is normally called at least once at startup when the config is loaded
-// --------------
-void I_InitJoystick2 (void)
-{
- HRESULT hr;
-
- // cleanup
- I_ShutdownJoystick2 ();
-
- joystick2_detected = false;
-
- // joystick detection can be skipped by setting use_joystick to 0
- if (M_CheckParm("-nojoy"))
- {
- CONS_Printf("Joystick2 disabled\n");
- return;
- }
- else
- // don't do anything at the registration of the joystick cvar,
- // until config is loaded
- if (!lstrcmpA(cv_usejoystick2.string, "0"))
- return;
-
- // acquire the joystick only once
- if (!lpDIJ2)
- {
- joystick2_detected = false;
-
- CONS_Printf("Looking for joystick devices:\n");
- iJoy2Num = 0;
- hr = IDirectInput_EnumDevices(lpDI, DIDEVTYPE_JOYSTICK,
- DIEnumJoysticks2,
- (void *)&cv_usejoystick2, // our user parameter is joystick number
- DIEDFL_ATTACHEDONLY);
- if (FAILED(hr))
- {
- CONS_Printf("\nI_InitJoystick2(): EnumDevices FAILED\n");
- cv_usejoystick2.value = 0;
- return;
- }
-
- if (!lpDIJ2)
- {
- if (iJoy2Num == 0)
- CONS_Printf("none found\n");
- else
- {
- CONS_Printf("none used\n");
- if (cv_usejoystick2.value > 0 &&
- cv_usejoystick2.value > iJoy2Num)
- {
- CONS_Printf("\2Set the use_joystick2 variable to one of the"
- " enumerated joysticks number\n");
- }
- }
- cv_usejoystick2.value = 0;
- return;
- }
-
- I_AddExitFunc (I_ShutdownJoystick2);
-
- // set coop level
- if (FAILED(IDirectInputDevice_SetCooperativeLevel (lpDIJ2, hWndMain, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND)))
- I_Error("I_InitJoystick2: SetCooperativeLevel FAILED");
-
- // later
- //if (FAILED(IDirectInputDevice_Acquire (lpDIJ2)))
- // I_Error("Couldn't acquire Joystick2");
-
- joystick2_detected = true;
- }
- else
- CONS_Printf("Joystick2 already initialized\n");
-
- //faB: we don't unacquire joystick, so let's just pretend we re-acquired it
- joystick2_detected = true;
-}
-
-/** \brief Joystick 1 buttons states
-*/
-static INT64 lastjoybuttons = 0;
-
-/** \brief Joystick 1 hats state
-*/
-static INT64 lastjoyhats = 0;
-
-static void I_ShutdownJoystick(void)
-{
- int i;
- event_t event;
-
- lastjoybuttons = lastjoyhats = 0;
-
- event.type = ev_keyup;
-
- // emulate the up of all joystick buttons
- for (i = 0;i < JOYBUTTONS;i++)
- {
- event.data1 = KEY_JOY1+i;
- D_PostEvent(&event);
- }
-
- // emulate the up of all joystick hats
- for (i = 0;i < JOYHATS*4;i++)
- {
- event.data1 = KEY_HAT1+i;
- D_PostEvent(&event);
- }
-
- // reset joystick position
- event.type = ev_joystick;
- for (i = 0;i < JOYAXISSET; i++)
- {
- event.data1 = i;
- D_PostEvent(&event);
- }
-
- if (joystick_detected)
- CONS_Printf("I_ShutdownJoystick()\n");
-
- for (i = 0; i > NumberofForces; i++)
- {
- if (lpDIE[i])
- {
- IDirectInputEffect_Release(lpDIE[i]);
- lpDIE[i] = NULL;
-
- }
- }
- if (lpDIJ)
- {
- IDirectInputDevice_Unacquire(lpDIJ);
- IDirectInputDevice_Release(lpDIJ);
- lpDIJ = NULL;
- }
- if (lpDIJA)
- {
- IDirectInputDevice2_Release(lpDIJA);
- lpDIJA = NULL;
- }
- joystick_detected = false;
-}
-
-/** \brief Joystick 2 buttons states
-*/
-static INT64 lastjoy2buttons = 0;
-
-/** \brief Joystick 2 hats state
-*/
-static INT64 lastjoy2hats = 0;
-
-static void I_ShutdownJoystick2(void)
-{
- int i;
- event_t event;
-
- lastjoy2buttons = lastjoy2hats = 0;
-
- event.type = ev_keyup;
-
- // emulate the up of all joystick buttons
- for (i = 0;i < JOYBUTTONS;i++)
- {
- event.data1 = KEY_2JOY1+i;
- D_PostEvent(&event);
- }
-
- // emulate the up of all joystick hats
- for (i = 0;i < JOYHATS*4;i++)
- {
- event.data1 = KEY_2HAT1+i;
- D_PostEvent(&event);
- }
-
- // reset joystick position
- event.type = ev_joystick2;
- for (i = 0;i < JOYAXISSET; i++)
- {
- event.data1 = i;
- D_PostEvent(&event);
- }
-
- if (joystick2_detected)
- CONS_Printf("I_ShutdownJoystick2()\n");
-
- for (i = 0; i > NumberofForces; i++)
- {
- if (lpDIE2[i])
- {
- IDirectInputEffect_Release(lpDIE2[i]);
- lpDIE2[i] = NULL;
- }
- }
- if (lpDIJ2)
- {
- IDirectInputDevice_Unacquire(lpDIJ2);
- IDirectInputDevice_Release(lpDIJ2);
- lpDIJ2 = NULL;
- }
- if (lpDIJ2A)
- {
- IDirectInputDevice2_Release(lpDIJ2A);
- lpDIJ2A = NULL;
- }
- joystick2_detected = false;
-}
-
-// -------------------
-// I_GetJoystickEvents
-// Get current joystick axis and button states
-// -------------------
-void I_GetJoystickEvents(void)
-{
- HRESULT hr;
- DIJOYSTATE js; // DirectInput joystick state
- int i;
- INT64 joybuttons = 0;
- INT64 joyhats = 0;
- event_t event;
-
- if (!lpDIJ)
- return;
-
- // if input is lost then acquire and keep trying
- for (;;)
- {
- // poll the joystick to read the current state
- // if the device doesn't require polling, this function returns almost instantly
- if (lpDIJA)
- {
- hr = IDirectInputDevice2_Poll(lpDIJA);
- if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED)
- goto acquire;
- else if (FAILED(hr))
- {
- CONS_Printf("I_GetJoystickEvents(): Poll FAILED\n");
- return;
- }
- }
-
- // get the input's device state, and put the state in dims
- hr = IDirectInputDevice_GetDeviceState(lpDIJ, sizeof (DIJOYSTATE), &js);
-
- if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED)
- {
- // DirectInput is telling us that the input stream has
- // been interrupted. We aren't tracking any state
- // between polls, so we don't have any special reset
- // that needs to be done. We just re-acquire and
- // try again.
- goto acquire;
- }
- else if (FAILED(hr))
- {
- CONS_Printf("I_GetJoystickEvents(): GetDeviceState FAILED\n");
- return;
- }
-
- break;
-acquire:
- if (FAILED(IDirectInputDevice_Acquire(lpDIJ)))
- return;
- }
-
- // look for as many buttons as g_input code supports, we don't use the others
- for (i = JOYBUTTONS_MIN - 1; i >= 0; i--)
- {
- joybuttons <<= 1;
- if (js.rgbButtons[i])
- joybuttons |= 1;
- }
-
- for (i = JOYHATS_MIN -1; i >=0; i--)
- {
- if (js.rgdwPOV[i] != 0xffff && js.rgdwPOV[i] != 0xffffffff)
- {
- if (js.rgdwPOV[i] > 270 * DI_DEGREES || js.rgdwPOV[i] < 90 * DI_DEGREES)
- joyhats |= 1<<(0 + 4*i); // UP
- else if (js.rgdwPOV[i] > 90 * DI_DEGREES && js.rgdwPOV[i] < 270 * DI_DEGREES)
- joyhats |= 1<<(1 + 4*i); // DOWN
- if (js.rgdwPOV[i] > 0 * DI_DEGREES && js.rgdwPOV[i] < 180 * DI_DEGREES)
- joyhats |= 1<<(3 + 4*i); // LEFT
- else if (js.rgdwPOV[i] > 180 * DI_DEGREES && js.rgdwPOV[i] < 360 * DI_DEGREES)
- joyhats |= 1<<(2 + 4*i); // RIGHT
- }
- }
-
- if (joybuttons != lastjoybuttons)
- {
- INT64 j = 1; // keep only bits that changed since last time
- INT64 newbuttons = joybuttons ^ lastjoybuttons;
- lastjoybuttons = joybuttons;
-
- for (i = 0; i < JOYBUTTONS && i < JOYBUTTONS_MAX; i++, j <<= 1)
- {
- if (newbuttons & j) // button changed state?
- {
- if (joybuttons & j)
- event.type = ev_keydown;
- else
- event.type = ev_keyup;
- event.data1 = KEY_JOY1 + i;
- D_PostEvent(&event);
- }
- }
- }
-
- if (joyhats != lastjoyhats)
- {
- INT64 j = 1; // keep only bits that changed since last time
- INT64 newhats = joyhats ^ lastjoyhats;
- lastjoyhats = joyhats;
-
- for (i = 0; i < JOYHATS*4 && i < JOYHATS_MAX*4; i++, j <<= 1)
- {
- if (newhats & j) // button changed state?
- {
- if (joyhats & j)
- event.type = ev_keydown;
- else
- event.type = ev_keyup;
- event.data1 = KEY_HAT1 + i;
- D_PostEvent(&event);
- }
- }
-
- }
-
- // send joystick axis positions
- event.type = ev_joystick;
- event.data1 = event.data2 = event.data3 = 0;
-
- if (Joystick.bGamepadStyle)
- {
- // gamepad control type, on or off, live or die
- if (JoyInfo.X)
- {
- if (js.lX < -(JOYAXISRANGE/2))
- event.data2 = -1;
- else if (js.lX > JOYAXISRANGE/2)
- event.data2 = 1;
- }
- if (JoyInfo.Y)
- {
- if (js.lY < -(JOYAXISRANGE/2))
- event.data3 = -1;
- else if (js.lY > JOYAXISRANGE/2)
- event.data3 = 1;
- }
- }
- else
- {
- // analog control style, just send the raw data
- if (JoyInfo.X) event.data2 = js.lX; // x axis
- if (JoyInfo.Y) event.data3 = js.lY; // y axis
- }
-
- D_PostEvent(&event);
-#if JOYAXISSET > 1
- event.data1 = 1;
- event.data2 = event.data3 = 0;
-
- if (Joystick.bGamepadStyle)
- {
- // gamepad control type, on or off, live or die
- if (JoyInfo.Z)
- {
- if (js.lZ < -(JOYAXISRANGE/2))
- event.data2 = -1;
- else if (js.lZ > JOYAXISRANGE/2)
- event.data2 = 1;
- }
- if (JoyInfo.Rx)
- {
- if (js.lRx < -(JOYAXISRANGE/2))
- event.data3 = -1;
- else if (js.lRx > JOYAXISRANGE/2)
- event.data3 = 1;
- }
- }
- else
- {
- // analog control style, just send the raw data
- if (JoyInfo.Z) event.data2 = js.lZ; // z axis
- if (JoyInfo.Rx) event.data3 = js.lRx; // rx axis
- }
-
- D_PostEvent(&event);
-#endif
-#if JOYAXISSET > 2
- event.data1 = 2;
- event.data2 = event.data3 = 0;
-
- if (Joystick.bGamepadStyle)
- {
- // gamepad control type, on or off, live or die
- if (JoyInfo.Rx)
- {
- if (js.lRy < -(JOYAXISRANGE/2))
- event.data2 = -1;
- else if (js.lRy > JOYAXISRANGE/2)
- event.data2 = 1;
- }
- if (JoyInfo.Rz)
- {
- if (js.lRz < -(JOYAXISRANGE/2))
- event.data3 = -1;
- else if (js.lRz > JOYAXISRANGE/2)
- event.data3 = 1;
- }
- }
- else
- {
- // analog control style, just send the raw data
- if (JoyInfo.Ry) event.data2 = js.lRy; // ry axis
- if (JoyInfo.Rz) event.data3 = js.lRz; // rz axis
- }
-
- D_PostEvent(&event);
-#endif
-#if JOYAXISSET > 3
- event.data1 = 3;
- event.data2 = event.data3 = 0;
- if (Joystick.bGamepadStyle)
- {
- // gamepad control type, on or off, live or die
- if (JoyInfo.U)
- {
- if (js.rglSlider[0] < -(JOYAXISRANGE/2))
- event.data2 = -1;
- else if (js.rglSlider[0] > JOYAXISRANGE/2)
- event.data2 = 1;
- }
- if (JoyInfo.V)
- {
- if (js.rglSlider[1] < -(JOYAXISRANGE/2))
- event.data3 = -1;
- else if (js.rglSlider[1] > JOYAXISRANGE/2)
- event.data3 = 1;
- }
- }
- else
- {
- // analog control style, just send the raw data
- if (JoyInfo.U) event.data2 = js.rglSlider[0]; // U axis
- if (JoyInfo.V) event.data3 = js.rglSlider[1]; // V axis
- }
- D_PostEvent(&event);
-#endif
-}
-
-// -------------------
-// I_GetJoystickEvents
-// Get current joystick axis and button states
-// -------------------
-void I_GetJoystick2Events(void)
-{
- HRESULT hr;
- DIJOYSTATE js; // DirectInput joystick state
- int i;
- INT64 joybuttons = 0;
- INT64 joyhats = 0;
- event_t event;
-
- if (!lpDIJ2)
- return;
-
- // if input is lost then acquire and keep trying
- for (;;)
- {
- // poll the joystick to read the current state
- // if the device doesn't require polling, this function returns almost instantly
- if (lpDIJ2A)
- {
- hr = IDirectInputDevice2_Poll(lpDIJ2A);
- if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED)
- goto acquire;
- else if (FAILED(hr))
- {
- CONS_Printf("I_GetJoystick2Events(): Poll FAILED\n");
- return;
- }
- }
-
- // get the input's device state, and put the state in dims
- hr = IDirectInputDevice_GetDeviceState(lpDIJ2, sizeof (DIJOYSTATE), &js);
-
- if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED)
- {
- // DirectInput is telling us that the input stream has
- // been interrupted. We aren't tracking any state
- // between polls, so we don't have any special reset
- // that needs to be done. We just re-acquire and
- // try again.
- goto acquire;
- }
- else if (FAILED(hr))
- {
- CONS_Printf("I_GetJoystickEvents2(): GetDeviceState FAILED\n");
- return;
- }
-
- break;
-acquire:
- if (FAILED(IDirectInputDevice_Acquire(lpDIJ2)))
- return;
- }
-
- // look for as many buttons as g_input code supports, we don't use the others
- for (i = JOYBUTTONS_MIN - 1; i >= 0; i--)
- {
- joybuttons <<= 1;
- if (js.rgbButtons[i])
- joybuttons |= 1;
- }
-
- for (i = JOYHATS_MIN -1; i >=0; i--)
- {
- if (js.rgdwPOV[i] != 0xffff && js.rgdwPOV[i] != 0xffffffff)
- {
- if (js.rgdwPOV[i] > 270 * DI_DEGREES || js.rgdwPOV[i] < 90 * DI_DEGREES)
- joyhats |= 1<<(0 + 4*i); // UP
- else if (js.rgdwPOV[i] > 90 * DI_DEGREES && js.rgdwPOV[i] < 270 * DI_DEGREES)
- joyhats |= 1<<(1 + 4*i); // DOWN
- if (js.rgdwPOV[i] > 0 * DI_DEGREES && js.rgdwPOV[i] < 180 * DI_DEGREES)
- joyhats |= 1<<(3 + 4*i); // LEFT
- else if (js.rgdwPOV[i] > 180 * DI_DEGREES && js.rgdwPOV[i] < 360 * DI_DEGREES)
- joyhats |= 1<<(2 + 4*i); // RIGHT
- }
- }
-
- if (joybuttons != lastjoy2buttons)
- {
- INT64 j = 1; // keep only bits that changed since last time
- INT64 newbuttons = joybuttons ^ lastjoy2buttons;
- lastjoy2buttons = joybuttons;
-
- for (i = 0; i < JOYBUTTONS && i < JOYBUTTONS_MAX; i++, j <<= 1)
- {
- if (newbuttons & j) // button changed state?
- {
- if (joybuttons & j)
- event.type = ev_keydown;
- else
- event.type = ev_keyup;
- event.data1 = KEY_2JOY1 + i;
- D_PostEvent(&event);
- }
- }
- }
-
- if (joyhats != lastjoy2hats)
- {
- INT64 j = 1; // keep only bits that changed since last time
- INT64 newhats = joyhats ^ lastjoy2hats;
- lastjoy2hats = joyhats;
-
- for (i = 0; i < JOYHATS*4 && i < JOYHATS_MAX*4; i++, j <<= 1)
- {
- if (newhats & j) // button changed state?
- {
- if (joyhats & j)
- event.type = ev_keydown;
- else
- event.type = ev_keyup;
- event.data1 = KEY_2HAT1 + i;
- D_PostEvent(&event);
- }
- }
-
- }
-
- // send joystick axis positions
- event.type = ev_joystick2;
- event.data1 = event.data2 = event.data3 = 0;
-
- if (Joystick2.bGamepadStyle)
- {
- // gamepad control type, on or off, live or die
- if (JoyInfo2.X)
- {
- if (js.lX < -(JOYAXISRANGE/2))
- event.data2 = -1;
- else if (js.lX > JOYAXISRANGE/2)
- event.data2 = 1;
- }
- if (JoyInfo2.Y)
- {
- if (js.lY < -(JOYAXISRANGE/2))
- event.data3 = -1;
- else if (js.lY > JOYAXISRANGE/2)
- event.data3 = 1;
- }
- }
- else
- {
- // analog control style, just send the raw data
- if (JoyInfo2.X) event.data2 = js.lX; // x axis
- if (JoyInfo2.Y) event.data3 = js.lY; // y axis
- }
-
- D_PostEvent(&event);
-#if JOYAXISSET > 1
- event.data1 = 1;
- event.data2 = event.data3 = 0;
-
- if (Joystick2.bGamepadStyle)
- {
- // gamepad control type, on or off, live or die
- if (JoyInfo2.Z)
- {
- if (js.lZ < -(JOYAXISRANGE/2))
- event.data2 = -1;
- else if (js.lZ > JOYAXISRANGE/2)
- event.data2 = 1;
- }
- if (JoyInfo2.Rx)
- {
- if (js.lRx < -(JOYAXISRANGE/2))
- event.data3 = -1;
- else if (js.lRx > JOYAXISRANGE/2)
- event.data3 = 1;
- }
- }
- else
- {
- // analog control style, just send the raw data
- if (JoyInfo2.Z) event.data2 = js.lZ; // z axis
- if (JoyInfo2.Rx) event.data3 = js.lRx; // rx axis
- }
-
- D_PostEvent(&event);
-#endif
-#if JOYAXISSET > 2
- event.data1 = 2;
- event.data2 = event.data3 = 0;
-
- if (Joystick2.bGamepadStyle)
- {
- // gamepad control type, on or off, live or die
- if (JoyInfo2.Rx)
- {
- if (js.lRy < -(JOYAXISRANGE/2))
- event.data2 = -1;
- else if (js.lRy > JOYAXISRANGE/2)
- event.data2 = 1;
- }
- if (JoyInfo2.Rz)
- {
- if (js.lRz < -(JOYAXISRANGE/2))
- event.data3 = -1;
- else if (js.lRz > JOYAXISRANGE/2)
- event.data3 = 1;
- }
- }
- else
- {
- // analog control style, just send the raw data
- if (JoyInfo2.Ry) event.data2 = js.lRy; // ry axis
- if (JoyInfo2.Rz) event.data3 = js.lRz; // rz axis
- }
-
- D_PostEvent(&event);
-#endif
-#if JOYAXISSET > 3
- event.data1 = 3;
- event.data2 = event.data3 = 0;
- if (Joystick2.bGamepadStyle)
- {
- // gamepad control type, on or off, live or die
- if (JoyInfo2.U)
- {
- if (js.rglSlider[0] < -(JOYAXISRANGE/2))
- event.data2 = -1;
- else if (js.rglSlider[0] > JOYAXISRANGE/2)
- event.data2 = 1;
- }
- if (JoyInfo2.V)
- {
- if (js.rglSlider[1] < -(JOYAXISRANGE/2))
- event.data3 = -1;
- else if (js.rglSlider[1] > JOYAXISRANGE/2)
- event.data3 = 1;
- }
- }
- else
- {
- // analog control style, just send the raw data
- if (JoyInfo2.U) event.data2 = js.rglSlider[0]; // U axis
- if (JoyInfo2.V) event.data3 = js.rglSlider[1]; // V axis
- }
- D_PostEvent(&event);
-#endif
-}
-
-static int numofjoy = 0;
-static char joyname[MAX_PATH];
-static int needjoy = -1;
-
-static BOOL CALLBACK DIEnumJoysticksCount (LPCDIDEVICEINSTANCE lpddi,
- LPVOID pvRef) //joyname
-{
- numofjoy++;
- if (needjoy == numofjoy && pvRef && pvRef == (void *)joyname && lpddi
- && lpddi->tszProductName)
- {
- sprintf(joyname,"%s",lpddi->tszProductName);
- return DIENUM_STOP;
- }
- //else if (devparm) CONS_Printf("DIEnumJoysticksCount need help!");
- return DIENUM_CONTINUE;
-}
-
-INT32 I_NumJoys(void)
-{
- HRESULT hr;
- needjoy = -1;
- numofjoy = 0;
- hr = IDirectInput_EnumDevices(lpDI, DIDEVTYPE_JOYSTICK,
- DIEnumJoysticksCount, (void *)&numofjoy, DIEDFL_ATTACHEDONLY);
- if (FAILED(hr))
- CONS_Printf("\nI_NumJoys(): EnumDevices FAILED\n");
- return numofjoy;
-
-}
-
-const char *I_GetJoyName(INT32 joyindex)
-{
- HRESULT hr;
- needjoy = joyindex;
- numofjoy = 0;
- ZeroMemory(joyname,sizeof (joyname));
- hr = IDirectInput_EnumDevices(lpDI, DIDEVTYPE_JOYSTICK,
- DIEnumJoysticksCount, (void *)joyname, DIEDFL_ATTACHEDONLY);
- if (FAILED(hr))
- CONS_Printf("\nI_GetJoyName(): EnumDevices FAILED\n");
- if (joyname[0] == 0) return NULL;
- return joyname;
-}
-
-// ===========================================================================================
-// DIRECT INPUT KEYBOARD
-// ===========================================================================================
-
-static UINT8 ASCIINames[256] =
-{
- // 0 1 2 3 4 5 6 7
- // 8 9 A B C D E F
- 0, 27, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', KEY_MINUS,KEY_EQUALS,KEY_BACKSPACE, KEY_TAB,
- 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
- 'o', 'p', '[', ']', KEY_ENTER,KEY_CTRL,'a', 's',
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
- '\'', '`', KEY_SHIFT, '\\', 'z', 'x', 'c', 'v',
- 'b', 'n', 'm', ',', '.', '/', KEY_SHIFT, '*',
- KEY_ALT,KEY_SPACE,KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5,
- KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10,KEY_NUMLOCK,KEY_SCROLLLOCK,KEY_KEYPAD7,
- KEY_KEYPAD8,KEY_KEYPAD9,KEY_MINUSPAD,KEY_KEYPAD4,KEY_KEYPAD5,KEY_KEYPAD6,KEY_PLUSPAD,KEY_KEYPAD1,
- KEY_KEYPAD2,KEY_KEYPAD3,KEY_KEYPAD0,KEY_KPADDEL,0,0,0, KEY_F11,
- KEY_F12,0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-
- // 0 1 2 3 4 5 6 7
- // 8 9 A B C D E F
-
- 0, 0, 0, 0, 0, 0, 0, 0, // 0x80
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, KEY_ENTER,KEY_CTRL, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, // 0xa0
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, KEY_KPADDEL, 0,KEY_KPADSLASH,0, 0,
- KEY_ALT,0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, KEY_HOME, // 0xc0
- KEY_UPARROW,KEY_PGUP,0,KEY_LEFTARROW,0,KEY_RIGHTARROW,0,KEY_END,
- KEY_DOWNARROW,KEY_PGDN, KEY_INS,KEY_DEL,0,0,0,0,
- 0, 0, 0,KEY_LEFTWIN,KEY_RIGHTWIN,KEY_MENU, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, // 0xe0
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-// Return a key that has been pushed, or 0 (replace getchar() at game startup)
-//
-INT32 I_GetKey(void)
-{
- event_t *ev;
-
- if (eventtail != eventhead)
- {
- ev = &events[eventtail];
- eventtail = (eventtail+1) & (MAXEVENTS-1);
- if (ev->type == ev_keydown || ev->type == ev_console)
- return ev->data1;
- else
- return 0;
- }
- return 0;
-}
-
-// -----------------
-// I_StartupKeyboard
-// Installs DirectInput keyboard
-// -----------------
-#define DI_KEYBOARD_BUFFERSIZE 32 // number of data elements in keyboard buffer
-
-void I_StartupKeyboard(void)
-{
- DIPROPDWORD dip;
-
- if (dedicated)
- return;
-
- // make sure the app window has the focus or DirectInput acquire keyboard won't work
- if (hWndMain)
- {
- SetFocus(hWndMain);
- ShowWindow(hWndMain, SW_SHOW);
- UpdateWindow(hWndMain);
- }
-
- // detect error
- if (lpDIK)
- {
- CONS_Printf("\2I_StartupKeyboard(): called twice\n");
- return;
- }
-
- CreateDevice2(lpDI, &GUID_SysKeyboard, &lpDIK, NULL);
-
- if (lpDIK)
- {
- if (FAILED(IDirectInputDevice_SetDataFormat(lpDIK, &c_dfDIKeyboard)))
- I_Error("Couldn't set keyboard data format");
-
- // create buffer for buffered data
- dip.diph.dwSize = sizeof (dip);
- dip.diph.dwHeaderSize = sizeof (dip.diph);
- dip.diph.dwObj = 0;
- dip.diph.dwHow = DIPH_DEVICE;
- dip.dwData = DI_KEYBOARD_BUFFERSIZE;
- if (FAILED(IDirectInputDevice_SetProperty(lpDIK, DIPROP_BUFFERSIZE, &dip.diph)))
- I_Error("Couldn't set keyboard buffer size");
-
- if (FAILED(IDirectInputDevice_SetCooperativeLevel(lpDIK, hWndMain,
- DISCL_NONEXCLUSIVE|DISCL_FOREGROUND)))
- {
- I_Error("Couldn't set keyboard coop level");
- }
- }
- else
- I_Error("Couldn't create keyboard input");
-
- I_AddExitFunc(I_ShutdownKeyboard);
- hacktics = 0; // see definition
- keyboard_started = true;
-}
-
-// ------------------
-// I_ShutdownKeyboard
-// Release DirectInput keyboard.
-// ------------------
-static void I_ShutdownKeyboard(void)
-{
- if (!keyboard_started)
- return;
-
- CONS_Printf("I_ShutdownKeyboard()\n");
-
- if (lpDIK)
- {
- IDirectInputDevice_Unacquire(lpDIK);
- IDirectInputDevice_Release(lpDIK);
- lpDIK = NULL;
- }
-
- keyboard_started = false;
-}
-
-// -------------------
-// I_GetKeyboardEvents
-// Get buffered data from the keyboard
-// -------------------
-static void I_GetKeyboardEvents(void)
-{
- static boolean KeyboardLost = false;
-
- // simply repeat the last pushed key every xx tics,
- // make more user friendly input for Console and game Menus
-#define KEY_REPEAT_DELAY (TICRATE/17) // TICRATE tics, repeat every 1/3 second
- static long RepeatKeyTics = 0;
- static int RepeatKeyCode;
-
- DIDEVICEOBJECTDATA rgdod[DI_KEYBOARD_BUFFERSIZE];
- DWORD dwItems, d;
- HRESULT hr;
- int ch;
-
- event_t event;
- ZeroMemory(&event,sizeof (event));
-
- if (!keyboard_started)
- return;
-
- if (!appActive && RepeatKeyCode) // Stop when lost focus
- {
- event.type = ev_keyup;
- event.data1 = RepeatKeyCode;
- D_PostEvent(&event);
- RepeatKeyCode = 0;
- }
-getBufferedData:
- dwItems = DI_KEYBOARD_BUFFERSIZE;
- hr = IDirectInputDevice_GetDeviceData(lpDIK, sizeof (DIDEVICEOBJECTDATA), rgdod, &dwItems, 0);
-
- // If data stream was interrupted, reacquire the device and try again.
- if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED)
- {
- // why it succeeds to acquire just after I don't understand.. so I set the flag BEFORE
- KeyboardLost = true;
-
- hr = IDirectInputDevice_Acquire(lpDIK);
- if (SUCCEEDED(hr))
- goto getBufferedData;
- return;
- }
-
- // we lost data, get device actual state to recover lost information
- if (hr == DI_BUFFEROVERFLOW)
- {
- /// \note either uncomment or delete block
- //I_Error("DI buffer overflow (keyboard)");
- //I_RecoverKeyboardState ();
-
- //hr = IDirectInputDevice_GetDeviceState (lpDIM, sizeof (keys), &diMouseState);
- }
-
- // We got buffered input, act on it
- if (SUCCEEDED(hr))
- {
- // if we previously lost keyboard data, recover its current state
- if (KeyboardLost)
- {
- /// \bug hack simply clears the keys so we don't have the last pressed keys
- /// still active.. to have to re-trigger it is not much trouble for the user.
- ZeroMemory(gamekeydown, NUMKEYS);
- KeyboardLost = false;
- }
-
- // dwItems contains number of elements read (could be 0)
- for (d = 0; d < dwItems; d++)
- {
- // dwOfs member is DIK_* value
- // dwData member 0x80 bit set press down, clear is release
-
- if (rgdod[d].dwData & 0x80)
- event.type = ev_keydown;
- else
- event.type = ev_keyup;
-
- ch = rgdod[d].dwOfs & UINT8_MAX;
- if (ASCIINames[ch])
- event.data1 = ASCIINames[ch];
- else
- event.data1 = 0x80;
-
- D_PostEvent(&event);
- }
-
- // Key Repeat
- if (dwItems)
- {
- // new key events, so stop repeating key
- RepeatKeyCode = 0;
- // delay is tripled for first repeating key
- RepeatKeyTics = hacktics + (KEY_REPEAT_DELAY*2);
- if (event.type == ev_keydown) // use the last event!
- RepeatKeyCode = event.data1;
- }
- else
- {
- // no new keys, repeat last pushed key after some time
- if (RepeatKeyCode && hacktics - RepeatKeyTics > KEY_REPEAT_DELAY)
- {
- event.type = ev_keydown;
- event.data1 = RepeatKeyCode;
- D_PostEvent(&event);
-
- RepeatKeyTics = hacktics;
- }
- }
- }
-}
-
-//
-// Closes DirectInput
-//
-static void I_ShutdownDirectInput(void)
-{
- if (lpDI)
- IDirectInput_Release(lpDI);
- lpDI = NULL;
-}
-
-// This stuff should get rid of the exception and page faults when
-// SRB2 bugs out with an error. Now it should exit cleanly.
-//
-INT32 I_StartupSystem(void)
-{
- HRESULT hr;
-
- // some 'more global than globals' things to initialize here ?
- graphics_started = keyboard_started = sound_started = cdaudio_started = false;
-
- I_DetectWin9x();
-
- // check for OS type and version here?
-#ifdef NDEBUG
- signal(SIGABRT, signal_handler);
- signal(SIGFPE, signal_handler);
- signal(SIGILL, signal_handler);
- signal(SIGSEGV, signal_handler);
- signal(SIGTERM, signal_handler);
- signal(SIGINT, signal_handler);
-#endif
-
- // create DirectInput - so that I_StartupKeyboard/Mouse can be called later on
- // from D_SRB2Main just like DOS version
- hr = DirectInputCreate(myInstance, DIRECTINPUT_VERSION, &lpDI, NULL);
-
- if (SUCCEEDED(hr))
- bDX0300 = FALSE;
- else
- {
- // try opening DirectX3 interface for NT compatibility
- hr = DirectInputCreate(myInstance, DXVERSION_NTCOMPATIBLE, &lpDI, NULL);
-
- if (FAILED(hr))
- {
- const char *sErr;
- switch (hr)
- {
- case DIERR_BETADIRECTINPUTVERSION:
- sErr = "DIERR_BETADIRECTINPUTVERSION";
- break;
- case DIERR_INVALIDPARAM:
- sErr = "DIERR_INVALIDPARAM";
- break;
- case DIERR_OLDDIRECTINPUTVERSION :
- sErr = "DIERR_OLDDIRECTINPUTVERSION";
- break;
- case DIERR_OUTOFMEMORY:
- sErr = "DIERR_OUTOFMEMORY";
- break;
- default:
- sErr = "UNKNOWN";
- break;
- }
- I_Error("Couldn't create DirectInput (reason: %s)", sErr);
- }
- else
- CONS_Printf("\2Using DirectX3 interface\n");
-
- // only use DirectInput3 compatible structures and calls
- bDX0300 = TRUE;
- }
- I_AddExitFunc(I_ShutdownDirectInput);
- return 0;
-}
-
-// Closes down everything. This includes restoring the initial
-// palette and video mode, and removing whatever mouse, keyboard, and
-// timer routines have been installed.
-//
-/// \bug doesn't restore wave/midi device volume
-//
-// Shutdown user funcs are effectively called in reverse order.
-//
-void I_ShutdownSystem(void)
-{
- int c;
-
- for (c = MAX_QUIT_FUNCS - 1; c >= 0; c--)
- if (quit_funcs[c])
- (*quit_funcs[c])();
-}
-
-// ---------------
-// I_SaveMemToFile
-// Save as much as iLength bytes starting at pData, to
-// a new file of given name. The file is overwritten if it is present.
-// ---------------
-BOOL I_SaveMemToFile(const void *pData, size_t iLength, const char *sFileName)
-{
- HANDLE fileHandle;
- DWORD bytesWritten;
-
- fileHandle = CreateFileA(sFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH, NULL);
- if (fileHandle == (HANDLE)-1)
- {
- CONS_Printf("SaveMemToFile: Error opening file %s",sFileName);
- return FALSE;
- }
- WriteFile(fileHandle, pData, (DWORD)iLength, &bytesWritten, NULL);
- CloseHandle(fileHandle);
- return TRUE;
-}
-
-// my god how win32 suck
-typedef BOOL (WINAPI *MyFunc)(LPCSTR RootName, PULARGE_INTEGER pulA, PULARGE_INTEGER pulB, PULARGE_INTEGER pulFreeBytes);
-
-void I_GetDiskFreeSpace(INT64* freespace)
-{
- static MyFunc pfnGetDiskFreeSpaceEx = NULL;
- static boolean testwin95 = false;
- ULARGE_INTEGER usedbytes, lfrespace;
-
- if (!testwin95)
- {
- HMODULE h = GetModuleHandleA("kernel32.dll");
-
- if (h)
- pfnGetDiskFreeSpaceEx = (MyFunc)GetProcAddress(h, "GetDiskFreeSpaceExA");
- testwin95 = true;
- }
- if (pfnGetDiskFreeSpaceEx)
- {
- if (pfnGetDiskFreeSpaceEx(NULL, &lfreespace, &usedbytes, NULL))
- *freespace = lfreespace.QuadPart;
- else
- *freespace = INT32_MAX;
- }
- else
- {
- DWORD SectorsPerCluster, BytesPerSector, NumberOfFreeClusters, TotalNumberOfClusters;
- GetDiskFreeSpace(NULL, &SectorsPerCluster, &BytesPerSector,
- &NumberOfFreeClusters, &TotalNumberOfClusters);
- *freespace = BytesPerSector * SectorsPerCluster * NumberOfFreeClusters;
- }
-}
-
-char *I_GetUserName(void)
-{
- static char username[MAXPLAYERNAME+1];
- char *p;
- DWORD i = MAXPLAYERNAME;
-
- if (!GetUserNameA(username, &i))
- {
- p = getenv("USER");
- if (!p)
- {
- p = getenv("user");
- if (!p)
- {
- p = getenv("USERNAME");
- if (!p)
- {
- p = getenv("username");
- if (!p)
- {
- return NULL;
- }
- }
- }
- }
- strncpy(username, p, MAXPLAYERNAME);
- }
-
- if (!strlen(username))
- return NULL;
- return username;
-}
-
-INT32 I_mkdir(const char *dirname, INT32 unixright)
-{
- (void)unixright; /// \todo should implement ntright under nt...
- return CreateDirectoryA(dirname, NULL);
-}
-
-char * I_GetEnv(const char *name)
-{
- return getenv(name);
-}
-
-INT32 I_PutEnv(char *variable)
-{
- return putenv(variable);
-}
-
-INT32 I_ClipboardCopy(const char *data, size_t size)
-{
- (void)data;
- (void)size;
- return -1;
-}
-
-char *I_ClipboardPaste(void)
-{
- return NULL;
-}
-
-typedef BOOL (WINAPI *MyFunc3) (DWORD);
-
-UINT64 I_FileSize(const char *filename)
-{
- HANDLE fileHandle;
- DWORD dwSizeHigh, dwSizeLow;
- UINT64 fileSize = (UINT64)-1;
-
- fileHandle = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
- 0, NULL);
- if (fileHandle == (HANDLE)-1)
- goto erroropening;
- dwSizeLow = GetFileSize(fileHandle,&dwSizeHigh);
- if (dwSizeLow == 0xFFFFFFFF && GetLastError() != NO_ERROR)
- goto errorsizing;
- fileSize = ((UINT64)(dwSizeHigh)<<32) + dwSizeLow;
-errorsizing:
- CloseHandle(fileHandle);
-erroropening:
- return fileSize;
-}
diff --git a/src/win32ce/win_vid.c b/src/win32ce/win_vid.c
deleted file mode 100644
index 439103f38..000000000
--- a/src/win32ce/win_vid.c
+++ /dev/null
@@ -1,781 +0,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright (C) 1998-2000 by DooM Legacy Team.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//-----------------------------------------------------------------------------
-/// \file
-/// \brief win32 video driver for Doom Legacy
-
-#include "../doomdef.h"
-
-#include
-#include
-
-#include "../d_clisrv.h"
-#include "../i_system.h"
-#include "../m_argv.h"
-#include "../v_video.h"
-#include "../st_stuff.h"
-#include "../i_video.h"
-#include "../z_zone.h"
-#include "fabdxlib.h"
-
-#include "win_main.h"
-#include "../command.h"
-#include "../screen.h"
-
-// -------
-// Globals
-// -------
-
-// this is the CURRENT rendermode!! very important: used by w_wad, and much other code
-rendermode_t rendermode = render_soft;
-
-// synchronize page flipping with screen refresh
-consvar_t cv_vidwait = {"vid_wait", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
-static consvar_t cv_stretch = {"stretch", "On", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
-
-boolean highcolor;
-
-static BOOL bDIBMode; // means we are using DIB instead of DirectDraw surfaces
-static BITMAPINFO* bmiMain = NULL;
-static HDC hDCMain = NULL;
-
-// -----------------
-// Video modes stuff
-// -----------------
-
-#define MAX_EXTRA_MODES 36
-static vmode_t extra_modes[MAX_EXTRA_MODES] = {{NULL, NULL, 0, 0, 0, 0, 0, 0, NULL, NULL, 0}};
-static char names[MAX_EXTRA_MODES][10];
-
-static int numvidmodes; // total number of DirectDraw display modes
-static vmode_t *pvidmodes; // start of videomodes list.
-static vmode_t *pcurrentmode; // the current active videomode.
-static BOOL bWinParm;
-static int WINAPI VID_SetWindowedDisplayMode(viddef_t *lvid, vmode_t *pcurrentmode);
-
-// this holds description of the startup video mode,
-// the resolution is 320x200, windowed on the desktop
-#define NUMSPECIALMODES 1
-static char winmode1[] ="320x200W"; // W to make sure it's the windowed mode
-static vmode_t specialmodes[NUMSPECIALMODES] =
-{
- {
- NULL,
- winmode1, // hehe
- 320, 200, //(200.0/320.0)*(320.0/240.0),
- 320, 1, // rowbytes, bytes per pixel
- 1, 2, // windowed (TRUE), numpages
- NULL,
- VID_SetWindowedDisplayMode, 0
- }
-};
-
-// ------
-// Protos
-// ------
-static void VID_Command_NumModes_f(void);
-static void VID_Command_ModeInfo_f(void);
-static void VID_Command_ModeList_f(void);
-static void VID_Command_Mode_f(void);
-static int WINAPI VID_SetDirectDrawMode(viddef_t *lvid, vmode_t *pcurrentmode);
-static vmode_t *VID_GetModePtr(int modenum);
-static void VID_Init(void);
-static BOOL VID_FreeAndAllocVidbuffer(viddef_t *lvid);
-
-// -----------------
-// I_StartupGraphics
-// Initialize video mode, setup dynamic screen size variables,
-// and allocate screens.
-// -----------------
-void I_StartupGraphics(void)
-{
- if (graphics_started)
- return;
-
- if (dedicated)
- rendermode = render_none;
- else
- VID_Init();
-
- // register exit code for graphics
- I_AddExitFunc(I_ShutdownGraphics);
- if (!dedicated) graphics_started = true;
-}
-
-// ------------------
-// I_ShutdownGraphics
-// Close the screen, restore previous video mode.
-// ------------------
-void I_ShutdownGraphics(void)
-{
- if (!graphics_started)
- return;
-
- CONS_Printf("I_ShutdownGraphics()\n");
-
- //FreeConsole();
-
- // release windowed startup stuff
- if (hDCMain)
- {
- ReleaseDC(hWndMain, hDCMain);
- hDCMain = NULL;
- }
- if (bmiMain)
- {
- GlobalFree(bmiMain);
- bmiMain = NULL;
- }
-
- // free the last video mode screen buffers
- if (vid.buffer)
- {
- GlobalFree(vid.buffer);
- vid.buffer = NULL;
- }
-
- CloseDirectDraw();
-
- graphics_started = false;
-}
-
-// --------------
-// I_UpdateNoBlit
-// --------------
-void I_UpdateNoBlit(void)
-{
- // what is this?
-}
-
-// --------------
-// I_FinishUpdate
-// --------------
-void I_FinishUpdate(void)
-{
- int i;
-
- if (rendermode == render_none)
- return;
-
- // display a graph of ticrate
- if (cv_ticrate.value)
- SCR_DisplayTicRate();
-
- if (cv_showping.value && netgame && consoleplayer != serverplayer)
- SCR_DisplayLocalPing();
-
- //
- if (bDIBMode)
- {
- // paranoia
- if (!hDCMain || !bmiMain || !vid.buffer)
- return;
- // main game loop, still in a window (-win parm)
- SetDIBitsToDevice(hDCMain, 0, 0, 320, 200, 0, 0, 0, 200, vid.buffer, bmiMain,
- DIB_RGB_COLORS);
- }
- else
- {
- // DIRECT DRAW
- // copy virtual screen to real screen
- // can fail when not active (alt-tab)
- if (LockScreen())
- {
- /// \todo use directX blit here!!? a blit might use hardware with access
- /// to main memory on recent hardware, and software blit of directX may be
- /// optimized for p2 or mmx??
- VID_BlitLinearScreen(screens[0], ScreenPtr, vid.width*vid.bpp, vid.height,
- vid.width*vid.bpp, ScreenPitch);
-
- UnlockScreen();
-
- // swap screens
- ScreenFlip(cv_vidwait.value);
- }
- }
-}
-
-//
-// This is meant to be called only by CONS_Printf() while game startup
-//
-void I_LoadingScreen(LPCSTR msg)
-{
- RECT rect;
-
- // paranoia
- if (!hDCMain || !bmiMain || !vid.buffer)
- return;
-
- GetClientRect(vid.WndParent, &rect);
-
- SetDIBitsToDevice(hDCMain, 0, 0, 320, 200, 0, 0, 0, 200, vid.buffer, bmiMain, DIB_RGB_COLORS);
-
- if (msg)
- {
- if (rect.bottom - rect.top > 32)
- rect.top = rect.bottom - 32; // put msg on bottom of window
- SetBkMode(hDCMain, TRANSPARENT);
- SetTextColor(hDCMain, RGB(0x00, 0x00, 0x00));
- DrawTextA(hDCMain, msg, -1, &rect, DT_WORDBREAK|DT_CENTER);
- }
-}
-
-// ------------
-// I_ReadScreen
-// ------------
-void I_ReadScreen(UINT8 *scr)
-{
- // DEBUGGING
- if (rendermode != render_soft)
- I_Error("I_ReadScreen: called while in non-software mode");
- VID_BlitLinearScreen(screens[0], scr, vid.width*vid.bpp, vid.height, vid.width*vid.bpp,
- vid.rowbytes);
-}
-
-// ------------
-// I_SetPalette
-// ------------
-void I_SetPalette(RGBA_t *palette)
-{
- int i;
-
- if (bDIBMode)
- {
- // set palette in RGBQUAD format, NOT THE SAME ORDER as PALETTEENTRY, grmpf!
- RGBQUAD *pColors;
- pColors = (RGBQUAD *)((char *)bmiMain + bmiMain->bmiHeader.biSize);
- ZeroMemory(pColors, sizeof (RGBQUAD)*256);
- for (i = 0; i < 256; i++, pColors++, palette++)
- {
- pColors->rgbRed = palette->s.red;
- pColors->rgbGreen = palette->s.green;
- pColors->rgbBlue = palette->s.blue;
- }
- }
- else
- {
- PALETTEENTRY mainpal[256];
-
- // this clears the 'flag' for each color in palette
- ZeroMemory(mainpal, sizeof mainpal);
-
- // set palette in PALETTEENTRY format
- for (i = 0; i < 256; i++, palette++)
- {
- mainpal[i].peRed = palette->s.red;
- mainpal[i].peGreen = palette->s.green;
- mainpal[i].peBlue = palette->s.blue;
- }
- SetDDPalette(mainpal); // set DirectDraw palette
- }
-}
-
-//
-// return number of video modes in pvidmodes list
-//
-INT32 VID_NumModes(void)
-{
- return numvidmodes - NUMSPECIALMODES; //faB: dont accept the windowed mode 0
-}
-
-// return a video mode number from the dimensions
-// returns any available video mode if the mode was not found
-INT32 VID_GetModeForSize(INT32 w, INT32 h)
-{
- vmode_t *pv = pvidmodes;
- int modenum = 0;
-
- // skip the special modes so that it finds only fullscreen modes
- for (; pv && modenum < NUMSPECIALMODES; pv = pv->pnext, ++modenum);
- for (; pv; pv = pv->pnext, ++modenum)
- if (pv->width == (unsigned)w && pv->height == (unsigned)h)
- return modenum;
-
- // if not found, return the first mode available,
- // preferably a full screen mode (all modes after the 'specialmodes')
- if (numvidmodes > NUMSPECIALMODES)
- return NUMSPECIALMODES; // use first full screen mode
-
- return 0; // no fullscreen mode, use windowed mode
-}
-
-//
-// Enumerate DirectDraw modes available
-//
-static int nummodes = 0;
-static BOOL GetExtraModesCallback(int width, int height, int bpp)
-{
- CONS_Printf("mode %d x %d x %d bpp\n", width, height, bpp);
-
- // skip all unwanted modes
- if (highcolor && bpp != 15)
- goto skip;
- if (!highcolor && bpp != 8)
- goto skip;
-
- if (bpp > 16 || width > MAXVIDWIDTH || height > MAXVIDHEIGHT)
- goto skip;
-
- // check if we have space for this mode
- if (nummodes >= MAX_EXTRA_MODES)
- {
- CONS_Printf("mode skipped (too many)\n");
- return FALSE;
- }
-
- // store mode info
- extra_modes[nummodes].pnext = &extra_modes[nummodes+1];
- memset(names[nummodes], 0, 10);
- snprintf(names[nummodes], 9, "%dx%d", width, height);
-
- extra_modes[nummodes].name = names[nummodes];
- extra_modes[nummodes].width = width;
- extra_modes[nummodes].height = height;
-
- // exactly, the current FinishUdpate() gets the rowbytes itself after locking the video buffer
- // so for now we put anything here
- extra_modes[nummodes].rowbytes = width;
- extra_modes[nummodes].windowed = false;
- extra_modes[nummodes].misc = 0; // unused
- extra_modes[nummodes].pextradata = NULL;
- extra_modes[nummodes].setmode = VID_SetDirectDrawMode;
-
- extra_modes[nummodes].numpages = 2; // double-buffer (but this value is unused)
-
- extra_modes[nummodes].bytesperpixel = (bpp+1)>>3;
-
- nummodes++;
-skip:
- return TRUE;
-}
-
-//
-// Collect info about DirectDraw display modes we use
-//
-static inline void VID_GetExtraModes(void)
-{
- nummodes = 0;
- EnumDirectDrawDisplayModes(GetExtraModesCallback);
-
- // add the extra modes (not 320x200) at the start of the mode list (if there are any)
- if (nummodes)
- {
- extra_modes[nummodes-1].pnext = NULL;
- pvidmodes = &extra_modes[0];
- numvidmodes += nummodes;
- }
-}
-
-// ---------------
-// WindowMode_Init
-// Add windowed modes to the start of the list,
-// mode 0 is used for windowed console startup (works on all computers with no DirectX)
-// ---------------
-static void WindowMode_Init(void)
-{
- specialmodes[NUMSPECIALMODES-1].pnext = pvidmodes;
- pvidmodes = &specialmodes[0];
- numvidmodes += NUMSPECIALMODES;
-}
-
-// *************************************************************************************
-// VID_Init
-// Initialize Video modes subsystem
-// *************************************************************************************
-static void VID_Init(void)
-{
- vmode_t *pv;
- int iMode;
-
- // if '-win' is specified on the command line, do not add DirectDraw modes
- bWinParm = M_CheckParm("-win");
-
- COM_AddCommand("vid_nummodes", VID_Command_NumModes_f);
- COM_AddCommand("vid_modeinfo", VID_Command_ModeInfo_f);
- COM_AddCommand("vid_modelist", VID_Command_ModeList_f);
- COM_AddCommand("vid_mode", VID_Command_Mode_f);
-
- CV_RegisterVar(&cv_vidwait);
- CV_RegisterVar(&cv_stretch);
-
- // setup the videmodes list,
- // note that mode 0 must always be VGA mode 0x13
- pvidmodes = pcurrentmode = NULL;
- numvidmodes = 0;
-
- // store the main window handle in viddef struct
- SetWindowPos(hWndMain, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE|SWP_NOSENDCHANGING|SWP_NOSIZE|SWP_NOMOVE);
- vid.WndParent = hWndMain;
- vid.buffer = NULL;
-
- // we startup in windowed mode using DIB bitmap
- // we will use DirectDraw when switching fullScreen and entering main game loop
- bDIBMode = TRUE;
- bAppFullScreen = FALSE;
-
- if (!bWinParm)
- {
- if (!CreateDirectDrawInstance())
- I_Error("Error initializing DirectDraw");
- // get available display modes for the device
- VID_GetExtraModes();
- }
-
- // the game boots in 320x200 standard VGA, but
- // we need a highcolor mode to run the game in highcolor
- if (highcolor && !numvidmodes)
- I_Error("Cannot run in highcolor - No 15bit highcolor DirectX video mode found.");
-
- // add windowed mode at the start of the list, very important!
- WindowMode_Init();
-
- if (!numvidmodes)
- I_Error("No display modes available.");
-
- // DEBUG
- for (iMode = 0, pv = pvidmodes; pv; pv = pv->pnext, iMode++)
- CONS_Printf("#%02d: %dx%dx%dbpp (desc: '%s')\n", iMode, pv->width, pv->height,
- pv->bytesperpixel, pv->name);
-
- // set the startup screen in a window
- VID_SetMode(0);
-}
-
-// --------------------------
-// VID_SetWindowedDisplayMode
-// Display the startup 320x200 console screen into a window on the desktop,
-// switching to fullscreen display only when we will enter the main game loop.
-// - we can display error message boxes for startup errors
-// - we can set the last used resolution only once, when entering the main game loop
-// --------------------------
-static int WINAPI VID_SetWindowedDisplayMode(viddef_t *lvid, vmode_t *pcurrentmode)
-{
- int iScrWidth, iScrHeight, iWinWidth, iWinHeight;
-
- pcurrentmode = NULL;
-#ifdef DEBUG
- CONS_Printf("VID_SetWindowedDisplayMode()\n");
-#endif
-
- lvid->u.numpages = 1; // not used
- lvid->direct = NULL; // DOS remains
- lvid->buffer = NULL;
-
- // allocate screens
- if (!VID_FreeAndAllocVidbuffer(lvid))
- return -1;
-
- // lvid->buffer should be NULL here!
-
- bmiMain = (void *)GlobalAlloc(GPTR, sizeof (BITMAPINFO) + (sizeof (RGBQUAD)*256));
- if (!bmiMain)
- I_Error("VID_SWDM(): No mem");
-
- // setup a BITMAPINFO to allow copying our video buffer to the desktop,
- // with color conversion as needed
- bmiMain->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
- bmiMain->bmiHeader.biWidth = lvid->width;
- bmiMain->bmiHeader.biHeight= -(lvid->height);
- bmiMain->bmiHeader.biPlanes = 1;
- bmiMain->bmiHeader.biBitCount = 8;
- bmiMain->bmiHeader.biCompression = BI_RGB;
-
- // center window on the desktop
- iScrWidth = GetSystemMetrics(SM_CXFULLSCREEN);
- iScrHeight = GetSystemMetrics(SM_CYFULLSCREEN);
-
- iWinWidth = lvid->width;
- iWinWidth += GetSystemMetrics(SM_CXFIXEDFRAME) * 2;
-
- iWinHeight = lvid->height;
- iWinHeight += GetSystemMetrics(SM_CYCAPTION);
- iWinHeight += GetSystemMetrics(SM_CYFIXEDFRAME) * 2;
-
- if (devparm)
- MoveWindow(hWndMain, (iScrWidth - iWinWidth), (iScrHeight - iWinHeight), iWinWidth, iWinHeight, TRUE);
- else
- MoveWindow(hWndMain, (iScrWidth - iWinWidth)>>1, (iScrHeight - iWinHeight)>>1, iWinWidth, iWinHeight, TRUE);
-
- SetFocus(hWndMain);
- ShowWindow(hWndMain, SW_SHOW);
-
- hDCMain = GetDC(hWndMain);
- if (!hDCMain)
- I_Error("VID_SWDM(): GetDC FAILED");
-
- return 1;
-}
-
-// ========================================================================
-// Returns a vmode_t from the video modes list, given a video mode number.
-// ========================================================================
-vmode_t *VID_GetModePtr(int modenum)
-{
- vmode_t *pv;
-
- pv = pvidmodes;
- if (!pv)
- I_Error("VID_error: No video mode found\n");
-
- while (modenum--)
- {
- pv = pv->pnext;
- if (!pv)
- I_Error("VID_error: Mode not available\n");
- }
- return pv;
-}
-
-//
-// return the name of a video mode
-//
-const char *VID_GetModeName(INT32 modenum)
-{
- return (VID_GetModePtr(modenum))->name;
-}
-
-// ========================================================================
-// Sets a video mode
-// ========================================================================
-INT32 VID_SetMode(INT32 modenum)
-{
- int stat;
- vmode_t *pnewmode;
- vmode_t *poldmode;
-
- if (dedicated)
- return 0;
-
- CONS_Printf("VID_SetMode(%d)\n", modenum);
-
- // if mode 0 (windowed) we must not be fullscreen already,
- // if other mode, check it is not mode 0 and existing
- if (modenum >= numvidmodes)
- {
- if (!pcurrentmode)
- modenum = 0; // revert to the default base vid mode
- else
- I_Error("Unknown video mode: %d\n", modenum);
- }
- else if (bAppFullScreen && modenum < NUMSPECIALMODES)
- I_Error("Tried to switch from fullscreen back to windowed mode %d\n", modenum);
-
- pnewmode = VID_GetModePtr(modenum);
-
- // dont switch to the same display mode
- if (pnewmode == pcurrentmode)
- return 1;
-
- // initialize the new mode
- poldmode = pcurrentmode;
- pcurrentmode = pnewmode;
-
- // initialize vidbuffer size for setmode
- vid.width = pcurrentmode->width;
- vid.height = pcurrentmode->height;
- vid.rowbytes = pcurrentmode->rowbytes;
- vid.bpp = pcurrentmode->bytesperpixel;
- if (modenum) // if not 320x200 windowed mode, it's actually a hack
- {
- if (rendermode == render_opengl)
- {
- // don't accept depth < 16 for OpenGL mode (too much ugly)
- if (cv_scr_depth.value < 16)
- CV_SetValue(&cv_scr_depth, 16);
- vid.bpp = cv_scr_depth.value/8;
- vid.u.windowed = (bWinParm || !cv_fullscreen.value);
- pcurrentmode->bytesperpixel = vid.bpp;
- pcurrentmode->windowed = vid.u.windowed;
- }
- }
-
- stat = (*pcurrentmode->setmode)(&vid, pcurrentmode);
-
- if (stat == -1)
- I_Error("Not enough mem for VID_SetMode\n");
- else if (stat == -2)
- I_Error("Couldn't set video mode because it failed the test\n");
- else if (stat == -3)
- I_Error("Couldn't set video mode because it failed the change?\n");
- else if (!stat)
- I_Error("Couldn't set video mode %d (%dx%d %d bits)\n", modenum, vid.width, vid.height, (vid.bpp*8));// hardware could not setup mode
- else
- CONS_Printf(M_GetText("Mode changed to %d (%s)\n"), modenum, pcurrentmode->name);
-
- vid.modenum = modenum;
-
- // tell game engine to recalc all tables and realloc buffers based on new values
- vid.recalc = 1;
-
- if (modenum < NUMSPECIALMODES)
- {
- // we are in startup windowed mode
- bAppFullScreen = FALSE;
- bDIBMode = TRUE;
- }
- else
- {
- // we switch to fullscreen
- bAppFullScreen = TRUE;
- bDIBMode = FALSE;
- }
-
- I_RestartSysMouse();
- return 1;
-}
-
-// ========================================================================
-// Free the video buffer of the last video mode,
-// allocate a new buffer for the video mode to set.
-// ========================================================================
-static BOOL VID_FreeAndAllocVidbuffer(viddef_t *lvid)
-{
- const DWORD vidbuffersize = (lvid->width * lvid->height * lvid->bpp * NUMSCREENS);
-
- // free allocated buffer for previous video mode
- if (lvid->buffer)
- GlobalFree(lvid->buffer);
-
- // allocate & clear the new screen buffer
- lvid->buffer = GlobalAlloc(GPTR, vidbuffersize);
- if (!lvid->buffer)
- return FALSE;
-
- ZeroMemory(lvid->buffer, vidbuffersize);
-#ifdef DEBUG
- CONS_Printf("VID_FreeAndAllocVidbuffer done, vidbuffersize: %x\n",vidbuffersize);
-#endif
- return TRUE;
-}
-
-// ========================================================================
-// Set video mode routine for DirectDraw display modes
-// Out: 1 ok,
-// 0 hardware could not set mode,
-// -1 no mem
-// ========================================================================
-static int WINAPI VID_SetDirectDrawMode(viddef_t *lvid, vmode_t *pcurrentmode)
-{
- pcurrentmode = NULL;
-#ifdef DEBUG
- CONS_Printf("VID_SetDirectDrawMode...\n");
-#endif
-
- // DD modes do double-buffer page flipping, but the game engine doesn't need this..
- lvid->u.numpages = 2;
-
- // release ddraw surfaces etc..
- ReleaseChtuff();
-
- // clean up any old vid buffer lying around, alloc new if needed
- if (!VID_FreeAndAllocVidbuffer(lvid))
- return -1; // no mem
-
- // should clear video mem here
-
- // note use lvid->bpp instead of 8...will this be needed? will we support other than 256color
- // in software ?
- if (!InitDirectDrawe(hWndMain, lvid->width, lvid->height, 8, TRUE)) // TRUE currently always full screen
- return 0; // could not set mode
-
- // this is NOT used with DirectDraw modes, game engine should never use this directly
- // but rather render to memory bitmap buffer
- lvid->direct = NULL;
-
- if (!cv_stretch.value && (float)vid.width/vid.height != ((float)BASEVIDWIDTH/BASEVIDHEIGHT))
- vid.height = (int)(vid.width * ((float)BASEVIDHEIGHT/BASEVIDWIDTH));// Adjust the height to match
-
- return 1;
-}
-
-// ========================================================================
-// VIDEO MODE CONSOLE COMMANDS
-// ========================================================================
-
-// vid_nummodes
-//
-static void VID_Command_NumModes_f(void)
-{
- CONS_Printf(M_GetText("%d video mode(s) available(s)\n"), VID_NumModes());
-}
-
-// vid_modeinfo
-//
-static void VID_Command_ModeInfo_f(void)
-{
- vmode_t *pv;
- int modenum;
-
- if (COM_Argc() != 2)
- modenum = vid.modenum; // describe the current mode
- else
- modenum = atoi(COM_Argv(1)); // the given mode number
-
- if (modenum >= VID_NumModes() || modenum < NUMSPECIALMODES) // don't accept the windowed mode 0
- {
- CONS_Printf(M_GetText("Video mode not present\n"));
- return;
- }
-
- pv = VID_GetModePtr(modenum);
-
- CONS_Printf("%s\n", VID_GetModeName(modenum));
- CONS_Printf(M_GetText("width: %d\nheight: %d\n"),
- pv->width, pv->height);
- if (rendermode == render_soft)
- CONS_Printf(M_GetText("bytes per scanline: %d\nbytes per pixel: %d\nnumpages: %d\n"),
- pv->rowbytes, pv->bytesperpixel, pv->numpages);
-}
-
-// vid_modelist
-//
-static void VID_Command_ModeList_f(void)
-{
- int i, nummodes;
- const char *pinfo;
- vmode_t *pv;
-
- nummodes = VID_NumModes();
- for (i = NUMSPECIALMODES; i <= nummodes; i++)
- {
- pv = VID_GetModePtr(i);
- pinfo = VID_GetModeName(i);
-
- if (pv->bytesperpixel == 1)
- CONS_Printf("%d: %s\n", i, pinfo);
- else
- CONS_Printf("%d: %s (hicolor)\n", i, pinfo);
- }
-}
-
-// vid_mode
-//
-static void VID_Command_Mode_f(void)
-{
- int modenum;
-
- if (COM_Argc() != 2)
- {
- CONS_Printf(M_GetText("vid_mode : set video mode, current video mode %i\n"), vid.modenum);
- return;
- }
-
- modenum = atoi(COM_Argv(1));
-
- if (modenum >= VID_NumModes() || modenum < NUMSPECIALMODES) // don't accept the windowed mode 0
- CONS_Printf(M_GetText("Video mode not present\n"));
- else
- setmodeneeded = modenum + 1; // request vid mode change
-}
diff --git a/tools/anglechk.c b/tools/anglechk.c
new file mode 100644
index 000000000..7f56abff7
--- /dev/null
+++ b/tools/anglechk.c
@@ -0,0 +1,364 @@
+/*
+ * anglechk.c
+ *
+ * Copyright 2007 Alam Arias
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include
+#ifdef _MSC_VER
+#include
+#endif
+#include "../src/tables.h"
+#define NO_M
+#include "../src/m_fixed.c"
+#define FIXEDPOINTCONV
+
+// With angle_t,
+// 360 deg = 2^32
+// 45 deg = 2^29
+// 1 deg = 2^29 / 45
+// To convert an angle to a fixed-point number of degrees, then, use
+// fixed = angle * FRACUNIT / ((1<<29) / 45)
+// But, done literally like that, this will overflow.
+// It's mathematically equivalent to
+// fixed = angle * (1<>(29-FRACBITS))
+// fixed = (angle>>(29-FRACBITS)) * 45
+
+#define ANGLE_TO_FIXED(a) (fixed_t)(((a)>>(29-FRACBITS))*45)
+#define FIXED_TO_ANGLE(x) (angle_t)(((x)/45)<<(29-FRACBITS))
+
+/*
+Old code that failed if FRACBITS was not 16.
+In particular, the use of FRACUNIT in the definition of ANGLE_F is completely
+wrong. The value wanted actually happens to be 65536 due to the definition
+of angle_t (it's specified so that 360 degrees = 2^32, to take advantage of
+modular arithmetic). That 65536 has nothing whatsoever to do with the setting
+of FRACUNIT.
+
+#define ANGF_D 8192
+#define ANGF_N 45
+#define ANGLE_F (ANGF_N*FRACUNIT/ANGF_D)
+#define FIXED_TO_ANGLE(x) (angle_t)FixedDiv(x, ANGLE_F) // angle_t = FixedDiv(fixed_t, ANGLE_F)
+#define ANGLE_TO_FIXED(x) FixedMul((fixed_t)(x), ANGLE_F) // fixed_t = FixedMul(angle_t, ANGLE_F)
+*/
+
+static fixed_t AngleFixed204(angle_t af)
+{
+ const fixed_t cfn = 180*FRACUNIT;
+ if (af == 0)
+ return 0;
+ else if (af > ANGLE_180)
+ return cfn + ANGLE_TO_FIXED(af - ANGLE_180);
+ else if (af < ANGLE_180)
+ return ANGLE_TO_FIXED(af);
+ else return cfn;
+}
+
+static inline angle_t FixedAngleC204(fixed_t fa, fixed_t factor)
+{
+#if 0 //FixedMod off?
+ const boolean neqda = da < 0, neqfa = fa < 0;
+ const fixed_t afactor = abs(factor);
+ angle_t ra = ANGLE_180;
+
+ if (factor == 0)
+ return FixedAngle204(fa);
+ else if (fa == 0)
+ return 0;
+
+ if (neqfactor)
+ {
+ const fixed_t maf = FixedDiv(afactor, ANGLE_F);
+ const fixed_t cfn = FixedMul(360*FRACUNIT, afactor), hcfn = (cfn/2);
+ const fixed_t fam = FixedMod(fa, cfn);
+
+ if (fam > hcfn)
+ ra = ANGLE_180 + (angle_t)FixedMul(fam - hcfn, maf);
+ else if (fam < hcfn)
+ ra = (angle_t)FixedMul(fam, maf);
+ }
+ else
+ {
+ const fixed_t maf = FixedMul(afactor, ANGLE_F);
+ const fixed_t cfn = FixedDiv(360*FRACUNIT, afactor), hcfn = (cfn/2);
+ const fixed_t fam = FixedMod(fa, cfn);
+
+ if (fam > hcfn)
+ ra = ANGLE_180 + (angle_t)FixedDiv(fam - hcfn, maf);
+ else if (fam < hcfn)
+ ra = (angle_t)FixedDiv(fam, maf);
+ }
+
+ if (neqfa)
+ ra = ANGLE_MAX-ra;
+
+ return ra;
+#else
+ if (factor == 0)
+ return FixedAngle(fa);
+ else if (factor > 0)
+ return (angle_t)((FIXED_TO_FLOAT(fa)/FIXED_TO_FLOAT(factor))*(ANGLE_45/45));
+ else
+ return (angle_t)((FIXED_TO_FLOAT(fa)*FIXED_TO_FLOAT(-factor))*(ANGLE_45/45));
+#endif
+}
+
+angle_t FixedAngle(fixed_t fa)
+{
+#if 0 //FixedMod off?
+ const boolean neqfa = fa < 0;
+ const fixed_t cfn = 180*FRACUNIT;
+ const fixed_t fam = FixedMod(fa, 360*FRACUNIT);
+ angle_t ra = ANGLE_180;
+
+ if (fa == 0)
+ return 0;
+
+ if (fam > cfn)
+ ra = ANGLE_180+FIXED_TO_ANGLE(fam-cfn);
+ else if (fam < cfn)
+ ra = FIXED_TO_ANGLE(fam);
+
+ if (neqfa)
+ ra = ANGLE_MAX-ra;
+
+ return ra;
+#else
+ return (angle_t)(FIXED_TO_FLOAT(fa)*(ANGLE_45/45));
+#endif
+}
+
+fixed_t AngleFixed205(angle_t af)
+{
+#ifdef FIXEDPOINTCONV
+ angle_t wa = ANGLE_180;
+ fixed_t wf = 180*FRACUNIT;
+ fixed_t rf = 0*FRACUNIT;
+ //const angle_t adj = 0x2000;
+
+ //if (af < adj) // too small to notice
+ //return rf;
+
+ while (af)
+ {
+ while (af < wa)
+ {
+ wa /= 2;
+ wf /= 2;
+ }
+ rf += wf;
+ af -= wa;
+ }
+
+ return rf;
+#else
+ const fixed_t cfn = 180*FRACUNIT;
+ if (af == 0)
+ return 0;
+ else if (af > ANGLE_180)
+ return cfn + ANGLE_TO_FIXED(af - ANGLE_180);
+ else if (af < ANGLE_180)
+ return ANGLE_TO_FIXED(af);
+ else return cfn;
+#endif
+}
+
+#ifdef FIXEDPOINTCONV
+static FUNCMATH angle_t AngleAdj(const fixed_t fa, const fixed_t wf,
+ angle_t ra)
+{
+ const angle_t adj = 0x77;
+ const boolean fan = fa < 0;
+ const fixed_t sl = FixedDiv(fa, wf*2);
+ const fixed_t lb = FixedRem(fa, wf*2);
+ const fixed_t lo = (wf*2)-lb;
+
+ if (ra == 0)
+ {
+ if (lb == 0)
+ {
+ ra = FixedMul(FRACUNIT/512, sl);
+ if (ra > FRACUNIT/64)
+ return ANGLE_MAX-ra+1;
+ return ra;
+ }
+ else if (lb > 0)
+ return ANGLE_MAX-FixedMul(lo*FRACUNIT, adj)+1;
+ else
+ return ANGLE_MAX-FixedMul(lo*FRACUNIT, adj)+1;
+ }
+
+ if (fan)
+ return ANGLE_MAX-ra+1;
+ else
+ return ra;
+}
+#endif
+
+angle_t FixedAngleC205(fixed_t fa, fixed_t factor)
+{
+#ifdef FIXEDPOINTCONV
+ angle_t wa = ANGLE_180;
+ fixed_t wf = 180*FRACUNIT;
+ angle_t ra = 0;
+ const fixed_t cfa = fa;
+ fixed_t cwf = wf;
+
+ if (fa == 0)
+ return 0;
+
+ if (factor == 0)
+ return FixedAngle(fa);
+ else if (factor > 0)
+ cwf = wf = FixedMul(wf, factor);
+ else if (factor < 0)
+ cwf = wf = FixedDiv(wf, -factor);
+
+ fa = abs(fa);
+
+ while (fa)
+ {
+ while (fa < wf)
+ {
+ wa /= 2;
+ wf /= 2;
+ }
+ ra = ra + wa;
+ fa = fa - wf;
+ }
+
+ return AngleAdj(cfa, cwf, ra);
+#else
+ if (factor == 0)
+ return FixedAngle(fa);
+
+ //fa = FixedMod(fa, 360*FRACUNIT);
+
+ if (factor > 0)
+ return (angle_t)((FIXED_TO_FLOAT(fa)/FIXED_TO_FLOAT(factor))*(ANGLE_45/45));
+ else
+ return (angle_t)((FIXED_TO_FLOAT(fa)*FIXED_TO_FLOAT(-factor))*(ANGLE_45/45));
+#endif
+}
+
+angle_t FixedAngle205(fixed_t fa)
+{
+#ifdef FIXEDPOINTCONV
+ angle_t wa = ANGLE_180;
+ fixed_t wf = 180*FRACUNIT;
+ angle_t ra = 0;
+ const fixed_t cfa = fa;
+ const fixed_t cwf = wf;
+
+ if (fa == 0)
+ return 0;
+
+ fa = abs(fa);
+
+ while (fa)
+ {
+ while (fa < wf)
+ {
+ wa /= 2;
+ wf /= 2;
+ }
+ ra = ra + wa;
+ fa = fa - wf;
+ }
+
+ return AngleAdj(cfa, cwf, ra);
+#else
+ //fa = FixedMod(fa, 360*FRACUNIT);
+
+ if (fa == 0)
+ return 0;
+
+ return (angle_t)(FIXED_TO_FLOAT(fa)*(ANGLE_45/45));
+#endif
+}
+
+int main(int argc, char** argv)
+{
+ fixed_t f, f204, f205;
+ INT64 a;
+ angle_t a204, a205;
+ fixed_t CF = 40*FRACUNIT;
+ int err = 0;
+ (void)argc;
+ (void)argv;
+
+ err = 0x29; //41
+
+ if (1)
+ for (a = 0; a < ANGLE_MAX; a += 0x1)
+ {
+ f204 = AngleFixed204((angle_t)a);
+ f205 = AngleFixed205((angle_t)a);
+ if (f204 != f205 && (abs(f204-f205) > err || f204 == 0 || f205 == 0))
+ {
+ printf("Angle: %u, %d, %d, %d\n", (angle_t)a, f204, f205, f204-f205);
+ //err = abs(f204-f205);
+ }
+ }
+
+ //err = FixedDiv(FRACUNIT, 120*FRACUNIT); // 547
+ err = FixedDiv(FRACUNIT, 62*FRACUNIT); //1059
+
+ if (1)
+ for (f = FRACUNIT*-720; f < FRACUNIT*720; f += 1)
+ {
+ a204 = FixedAngle(f);
+ a205 = FixedAngle205(f);
+ if (a204 != a205 && (abs(a204-a205) > err || a204 == 0 || a205 == 0))
+ {
+ printf("Fixed: %f, %u, %u, %d\n", FIXED_TO_FLOAT(f), a204, a205, a204-a205);
+ err = abs(a204-a205);
+ }
+ }
+
+ //err = FixedDiv(FRACUNIT, 316*FRACUNIT); //207
+ err = FixedDiv(FRACUNIT, 125*FRACUNIT); //526
+
+ if (1)
+ for (f = FixedMul(FRACUNIT*-720, CF); f < FixedMul(FRACUNIT*720, CF); f += FRACUNIT/16)
+ {
+ a204 = FixedAngleC204(f, CF);
+ a205 = FixedAngleC205(f, CF);
+ if (a204 != a205 && (abs(a204-a205) > err || a204 == 0 || a205 == 0))
+ {
+ printf("FixedC: %f, %u, %u, %d\n", FIXED_TO_FLOAT(f), a204, a205, a204-a205);
+ //err = abs(a204-a205);
+ }
+ }
+
+ return 0;
+}
+
+static void *cpu_cpy(void *dest, const void *src, size_t n)
+{
+ return memcpy(dest, src, n);
+}
+
+void *(*M_Memcpy)(void* dest, const void* src, size_t n) = cpu_cpy;
+
+void I_Error(const char *error, ...)
+{
+ (void)error;
+ exit(-1);
+}