summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am3
-rw-r--r--src/am_map.c210
-rw-r--r--src/d_iwad.c11
-rw-r--r--src/d_main.c4
-rw-r--r--src/d_net.c2
-rw-r--r--src/doomtype.h7
-rw-r--r--src/g_game.c45
-rw-r--r--src/hu_stuff.c3
-rw-r--r--src/hu_stuff.h1
-rw-r--r--src/i_main.c42
-rw-r--r--src/i_sdlsound.c407
-rw-r--r--src/i_system.c142
-rw-r--r--src/i_video.c237
-rw-r--r--src/m_config.c411
-rw-r--r--src/m_config.h1
-rw-r--r--src/m_menu.c234
-rw-r--r--src/p_enemy.c122
-rw-r--r--src/w_file_win32.c24
-rw-r--r--src/z_native.c5
-rw-r--r--src/z_zone.c5
-rw-r--r--src/z_zone.h2
21 files changed, 1365 insertions, 553 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 3874c35f..7deed766 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,7 +21,7 @@ net_structrw.c net_structrw.h \
z_native.c z_zone.h
chocolate_server_SOURCES=$(DEDSERV_FILES)
-chocolate_server_LDADD = @LDFLAGS@ @SDLNET_LIBS@
+chocolate_server_LDADD = ../wince/libc_wince.a @LDFLAGS@ @SDLNET_LIBS@
MAIN_SOURCE_FILES=\
am_map.c am_map.h \
@@ -172,6 +172,7 @@ chocolate_doom_SOURCES=$(SOURCE_FILES)
endif
chocolate_doom_LDADD = \
+ ../wince/libc_wince.a \
../textscreen/libtextscreen.a \
../pcsound/libpcsound.a \
../opl/libopl.a \
diff --git a/src/am_map.c b/src/am_map.c
index 5fbe748a..9a81d62c 100644
--- a/src/am_map.c
+++ b/src/am_map.c
@@ -90,19 +90,18 @@
// drawing stuff
#define FB 0
-#define AM_PANDOWNKEY KEY_DOWNARROW
-#define AM_PANUPKEY KEY_UPARROW
-#define AM_PANRIGHTKEY KEY_RIGHTARROW
-#define AM_PANLEFTKEY KEY_LEFTARROW
-#define AM_ZOOMINKEY '='
-#define AM_ZOOMOUTKEY '-'
-#define AM_STARTKEY KEY_TAB
-#define AM_ENDKEY KEY_TAB
-#define AM_GOBIGKEY '0'
-#define AM_FOLLOWKEY 'f'
-#define AM_GRIDKEY 'g'
-#define AM_MARKKEY 'm'
-#define AM_CLEARMARKKEY 'c'
+int key_map_north = KEY_UPARROW;
+int key_map_south = KEY_DOWNARROW;
+int key_map_east = KEY_RIGHTARROW;
+int key_map_west = KEY_LEFTARROW;
+int key_map_zoomin = '=';
+int key_map_zoomout = '-';
+int key_map_toggle = KEY_TAB;
+int key_map_maxzoom = '0';
+int key_map_follow = 'f';
+int key_map_grid = 'g';
+int key_map_mark = 'm';
+int key_map_clearmark = 'c';
#define AM_NUMMARKPOINTS 10
@@ -632,121 +631,136 @@ AM_Responder
static int cheatstate=0;
static int bigstate=0;
static char buffer[20];
+ int key;
rc = false;
if (!automapactive)
{
- if (ev->type == ev_keydown && ev->data1 == AM_STARTKEY)
+ if (ev->type == ev_keydown && ev->data1 == key_map_toggle)
{
AM_Start ();
viewactive = false;
rc = true;
}
}
-
else if (ev->type == ev_keydown)
{
-
rc = true;
- switch(ev->data1)
- {
- case AM_PANRIGHTKEY: // pan right
- if (!followplayer) m_paninc.x = FTOM(F_PANINC);
- else rc = false;
- break;
- case AM_PANLEFTKEY: // pan left
- if (!followplayer) m_paninc.x = -FTOM(F_PANINC);
- else rc = false;
- break;
- case AM_PANUPKEY: // pan up
- if (!followplayer) m_paninc.y = FTOM(F_PANINC);
- else rc = false;
- break;
- case AM_PANDOWNKEY: // pan down
- if (!followplayer) m_paninc.y = -FTOM(F_PANINC);
- else rc = false;
- break;
- case AM_ZOOMOUTKEY: // zoom out
- mtof_zoommul = M_ZOOMOUT;
- ftom_zoommul = M_ZOOMIN;
- break;
- case AM_ZOOMINKEY: // zoom in
- mtof_zoommul = M_ZOOMIN;
- ftom_zoommul = M_ZOOMOUT;
- break;
- case AM_ENDKEY:
- bigstate = 0;
- viewactive = true;
- AM_Stop ();
- break;
- case AM_GOBIGKEY:
- bigstate = !bigstate;
- if (bigstate)
- {
- AM_saveScaleAndLoc();
- AM_minOutWindowScale();
- }
- else AM_restoreScaleAndLoc();
- break;
- case AM_FOLLOWKEY:
- followplayer = !followplayer;
- f_oldloc.x = INT_MAX;
+ key = ev->data1;
+
+ if (key == key_map_east) // pan right
+ {
+ if (!followplayer) m_paninc.x = FTOM(F_PANINC);
+ else rc = false;
+ }
+ else if (key == key_map_west) // pan left
+ {
+ if (!followplayer) m_paninc.x = -FTOM(F_PANINC);
+ else rc = false;
+ }
+ else if (key == key_map_north) // pan up
+ {
+ if (!followplayer) m_paninc.y = FTOM(F_PANINC);
+ else rc = false;
+ }
+ else if (key == key_map_south) // pan down
+ {
+ if (!followplayer) m_paninc.y = -FTOM(F_PANINC);
+ else rc = false;
+ }
+ else if (key == key_map_zoomout) // zoom out
+ {
+ mtof_zoommul = M_ZOOMOUT;
+ ftom_zoommul = M_ZOOMIN;
+ }
+ else if (key == key_map_zoomin) // zoom in
+ {
+ mtof_zoommul = M_ZOOMIN;
+ ftom_zoommul = M_ZOOMOUT;
+ }
+ else if (key == key_map_toggle)
+ {
+ bigstate = 0;
+ viewactive = true;
+ AM_Stop ();
+ }
+ else if (key == key_map_maxzoom)
+ {
+ bigstate = !bigstate;
+ if (bigstate)
+ {
+ AM_saveScaleAndLoc();
+ AM_minOutWindowScale();
+ }
+ else AM_restoreScaleAndLoc();
+ }
+ else if (key == key_map_follow)
+ {
+ followplayer = !followplayer;
+ f_oldloc.x = INT_MAX;
if (followplayer)
plr->message = DEH_String(AMSTR_FOLLOWON);
else
plr->message = DEH_String(AMSTR_FOLLOWOFF);
- break;
- case AM_GRIDKEY:
- grid = !grid;
+ }
+ else if (key == key_map_grid)
+ {
+ grid = !grid;
if (grid)
plr->message = DEH_String(AMSTR_GRIDON);
else
plr->message = DEH_String(AMSTR_GRIDOFF);
- break;
- case AM_MARKKEY:
- sprintf(buffer, "%s %d", DEH_String(AMSTR_MARKEDSPOT), markpointnum);
- plr->message = buffer;
- AM_addMark();
- break;
- case AM_CLEARMARKKEY:
- AM_clearMarks();
- plr->message = DEH_String(AMSTR_MARKSCLEARED);
- break;
- default:
- cheatstate=0;
- rc = false;
- }
+ }
+ else if (key == key_map_mark)
+ {
+ sprintf(buffer, "%s %d", DEH_String(AMSTR_MARKEDSPOT), markpointnum);
+ plr->message = buffer;
+ AM_addMark();
+ }
+ else if (key == key_map_clearmark)
+ {
+ AM_clearMarks();
+ plr->message = DEH_String(AMSTR_MARKSCLEARED);
+ }
+ else
+ {
+ cheatstate=0;
+ rc = false;
+ }
+
if (!deathmatch && cht_CheckCheat(&cheat_amap, ev->data2))
{
rc = false;
cheating = (cheating+1) % 3;
}
}
-
else if (ev->type == ev_keyup)
{
- rc = false;
- switch (ev->data1)
- {
- case AM_PANRIGHTKEY:
- if (!followplayer) m_paninc.x = 0;
- break;
- case AM_PANLEFTKEY:
- if (!followplayer) m_paninc.x = 0;
- break;
- case AM_PANUPKEY:
- if (!followplayer) m_paninc.y = 0;
- break;
- case AM_PANDOWNKEY:
- if (!followplayer) m_paninc.y = 0;
- break;
- case AM_ZOOMOUTKEY:
- case AM_ZOOMINKEY:
- mtof_zoommul = FRACUNIT;
- ftom_zoommul = FRACUNIT;
- break;
- }
+ rc = false;
+ key = ev->data1;
+
+ if (key == key_map_east)
+ {
+ if (!followplayer) m_paninc.x = 0;
+ }
+ else if (key == key_map_west)
+ {
+ if (!followplayer) m_paninc.x = 0;
+ }
+ else if (key == key_map_north)
+ {
+ if (!followplayer) m_paninc.y = 0;
+ }
+ else if (key == key_map_south)
+ {
+ if (!followplayer) m_paninc.y = 0;
+ }
+ else if (key == key_map_zoomout || key == key_map_zoomin)
+ {
+ mtof_zoommul = FRACUNIT;
+ ftom_zoommul = FRACUNIT;
+ }
}
return rc;
diff --git a/src/d_iwad.c b/src/d_iwad.c
index 4fcaafcb..d1c2f0bf 100644
--- a/src/d_iwad.c
+++ b/src/d_iwad.c
@@ -63,7 +63,7 @@ static void AddIWADDir(char *dir)
// keys installed by the Windows installers for various CD versions
// of Doom. From these keys we can deduce where to find an IWAD.
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(_WIN32_WCE)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@@ -487,7 +487,14 @@ static void BuildIWADDirList(void)
AddDoomWadPath();
-#ifdef _WIN32
+#if defined(_WIN32_WCE)
+
+ // Windows CE locations:
+
+ AddIWADDir("\\Storage Card");
+ AddIWADDir(getenv("HOME"));
+
+#elif defined(_WIN32)
// Search the registry and find where IWADs have been installed.
diff --git a/src/d_main.c b/src/d_main.c
index 849897fe..c59a8fb7 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -878,8 +878,7 @@ void D_DoomMain (void)
I_Error("Game mode indeterminate. No IWAD file was found. Try\n"
"specifying one with the '-iwad' command line parameter.\n");
}
-
- setbuf (stdout, NULL);
+
modifiedgame = false;
//!
@@ -975,6 +974,7 @@ void D_DoomMain (void)
V_Init ();
printf (DEH_String("M_LoadDefaults: Load system defaults.\n"));
+ M_ApplyPlatformDefaults();
M_LoadDefaults (); // load before initing other systems
printf (DEH_String("W_Init: Init WADfiles.\n"));
diff --git a/src/d_net.c b/src/d_net.c
index 4e87a813..f5890769 100644
--- a/src/d_net.c
+++ b/src/d_net.c
@@ -429,6 +429,7 @@ static int GetLowTic(void)
int i;
int lowtic;
+#ifdef FEATURE_MULTIPLAYER
if (net_client_connected)
{
lowtic = INT_MAX;
@@ -443,6 +444,7 @@ static int GetLowTic(void)
}
}
else
+#endif
{
lowtic = maketic;
}
diff --git a/src/doomtype.h b/src/doomtype.h
index 2c9680b3..0a5b5e38 100644
--- a/src/doomtype.h
+++ b/src/doomtype.h
@@ -29,6 +29,13 @@
#ifndef __DOOMTYPE__
#define __DOOMTYPE__
+// Windows CE is missing some vital ANSI C functions. We have to
+// use our own replacements.
+
+#ifdef _WIN32_WCE
+#include "libc_wince.h"
+#endif
+
// C99 integer types; with gcc we just use this. Other compilers
// should add conditional statements that define the C99 types.
diff --git a/src/g_game.c b/src/g_game.c
index 44e77a74..8255fdd0 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -173,6 +173,17 @@ int key_fire = KEY_RCTRL;
int key_use = ' ';
int key_strafe = KEY_RALT;
int key_speed = KEY_RSHIFT;
+
+int key_weapon1 = '1';
+int key_weapon2 = '2';
+int key_weapon3 = '3';
+int key_weapon4 = '4';
+int key_weapon5 = '5';
+int key_weapon6 = '6';
+int key_weapon7 = '7';
+int key_weapon8 = '8';
+
+int key_pause = KEY_PAUSE;
int mousebfire = 0;
int mousebstrafe = 1;
@@ -211,6 +222,17 @@ fixed_t forwardmove[2] = {0x19, 0x32};
fixed_t sidemove[2] = {0x18, 0x28};
fixed_t angleturn[3] = {640, 1280, 320}; // + slow turn
+static int *weapon_keys[] = {
+ &key_weapon1,
+ &key_weapon2,
+ &key_weapon3,
+ &key_weapon4,
+ &key_weapon5,
+ &key_weapon6,
+ &key_weapon7,
+ &key_weapon8
+};
+
#define SLOWTURNTICS 6
#define NUMKEYS 256
@@ -501,13 +523,18 @@ void G_BuildTiccmd (ticcmd_t* cmd)
}
// chainsaw overrides
- for (i=0 ; i<NUMWEAPONS-1 ; i++)
- if (gamekeydown['1'+i])
- {
+
+ for (i=0; i<arrlen(weapon_keys); ++i)
+ {
+ int key = *weapon_keys[i];
+
+ if (gamekeydown[key])
+ {
cmd->buttons |= BT_CHANGE;
cmd->buttons |= i<<BT_WEAPONSHIFT;
break;
- }
+ }
+ }
// mouse
if (mousebuttons[mousebforward])
@@ -765,13 +792,15 @@ boolean G_Responder (event_t* ev)
switch (ev->type)
{
case ev_keydown:
- if (ev->data1 == KEY_PAUSE)
+ if (ev->data1 == key_pause)
{
sendpause = true;
- return true;
- }
- if (ev->data1 <NUMKEYS)
+ }
+ else if (ev->data1 <NUMKEYS)
+ {
gamekeydown[ev->data1] = true;
+ }
+
return true; // eat key down events
case ev_keyup:
diff --git a/src/hu_stuff.c b/src/hu_stuff.c
index 886236ba..0ab750fb 100644
--- a/src/hu_stuff.c
+++ b/src/hu_stuff.c
@@ -88,6 +88,7 @@ char* player_names[] =
HUSTR_PLRRED
};
+int key_message_refresh = KEY_ENTER;
char chat_char; // remove later.
static player_t* plr;
@@ -597,7 +598,7 @@ boolean HU_Responder(event_t *ev)
if (!chat_on)
{
- if (ev->data1 == HU_MSGREFRESH)
+ if (ev->data1 == key_message_refresh)
{
message_on = true;
message_counter = HU_MSGTIMEOUT;
diff --git a/src/hu_stuff.h b/src/hu_stuff.h
index 310201f6..9b1618c1 100644
--- a/src/hu_stuff.h
+++ b/src/hu_stuff.h
@@ -40,7 +40,6 @@
#define HU_BROADCAST 5
-#define HU_MSGREFRESH KEY_ENTER
#define HU_MSGX 0
#define HU_MSGY 0
#define HU_MSGWIDTH 64 // in characters
diff --git a/src/i_main.c b/src/i_main.c
index 7c5b16e7..03f8a5ac 100644
--- a/src/i_main.c
+++ b/src/i_main.c
@@ -29,24 +29,23 @@
#include "SDL.h"
-#include <signal.h>
-
-#ifdef _WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#endif
-
-#ifdef HAVE_SCHED_SETAFFINITY
-#include <unistd.h>
-#include <sched.h>
-#endif
-
#include "doomdef.h"
#include "i_system.h"
#include "m_argv.h"
#include "d_main.h"
-#if defined(_WIN32)
+#if defined(_WIN32_WCE)
+
+// Windows CE? I doubt it even supports SMP..
+
+static void LockCPUAffinity(void)
+{
+}
+
+#elif defined(_WIN32)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
typedef BOOL WINAPI (*SetAffinityFunc)(HANDLE hProcess, DWORD_PTR mask);
@@ -93,16 +92,24 @@ static void LockCPUAffinity(void)
#elif defined(HAVE_SCHED_SETAFFINITY)
+#include <unistd.h>
+#include <sched.h>
+
// Unix (Linux) version:
static void LockCPUAffinity(void)
{
+#ifdef CPU_SET
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(0, &set);
sched_setaffinity(getpid(), sizeof(set), &set);
+#else
+ unsigned long mask = 1;
+ sched_setaffinity(getpid(), sizeof(mask), &mask);
+#endif
}
#else
@@ -126,6 +133,15 @@ int main(int argc, char **argv)
myargc = argc;
myargv = argv;
+#ifdef _WIN32_WCE
+
+ // Windows CE has no environment, but SDL provides an implementation.
+ // Populate the environment with the values we normally find.
+
+ PopulateEnvironment();
+
+#endif
+
// Only schedule on a single core, if we have multiple
// cores. This is to work around a bug in SDL_mixer.
diff --git a/src/i_sdlsound.c b/src/i_sdlsound.c
index b6fc9787..bb8229e4 100644
--- a/src/i_sdlsound.c
+++ b/src/i_sdlsound.c
@@ -31,6 +31,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
+#include <math.h>
#include "SDL.h"
#include "SDL_mixer.h"
@@ -48,6 +49,7 @@
#include "doomdef.h"
#define LOW_PASS_FILTER
+#define MAX_SOUND_SLICE_TIME 70 /* ms */
#define NUM_CHANNELS 16
static boolean sound_initialised = false;
@@ -58,8 +60,6 @@ static int channels_playing[NUM_CHANNELS];
static int mixer_freq;
static Uint16 mixer_format;
static int mixer_channels;
-static uint32_t (*ExpandSoundData)(byte *data, int samplerate, int length,
- Mix_Chunk *destination) = NULL;
int use_libsamplerate = 0;
@@ -79,6 +79,12 @@ static void ReleaseSoundOnChannel(int channel)
channels_playing[channel] = sfx_None;
+#ifdef HAVE_LIBSAMPLERATE
+ // Don't allow precached sounds to be swapped out.
+ if (use_libsamplerate)
+ return;
+#endif
+
for (i=0; i<NUM_CHANNELS; ++i)
{
// Playing on this channel? if so, don't release.
@@ -92,6 +98,7 @@ static void ReleaseSoundOnChannel(int channel)
Z_ChangeTag(sound_chunks[id].abuf, PU_CACHE);
}
+
#ifdef HAVE_LIBSAMPLERATE
// Returns the conversion mode for libsamplerate to use.
@@ -121,101 +128,6 @@ static int SRC_ConversionMode(void)
}
}
-// libsamplerate-based generic sound expansion function for any sample rate
-// unsigned 8 bits --> signed 16 bits
-// mono --> stereo
-// samplerate --> mixer_freq
-// Returns number of clipped samples.
-// DWF 2008-02-10 with cleanups by Simon Howard.
-
-static uint32_t ExpandSoundData_SRC(byte *data,
- int samplerate,
- int length,
- Mix_Chunk *destination)
-{
- SRC_DATA src_data;
- uint32_t i, abuf_index=0, clipped=0;
- int retn;
- int16_t *expanded;
-
- src_data.input_frames = length;
- src_data.data_in = malloc(length * sizeof(float));
- src_data.src_ratio = (double)mixer_freq / samplerate;
-
- // We include some extra space here in case of rounding-up.
- src_data.output_frames = src_data.src_ratio * length + (mixer_freq / 4);
- src_data.data_out = malloc(src_data.output_frames * sizeof(float));
-
- assert(src_data.data_in != NULL && src_data.data_out != NULL);
-
- // Convert input data to floats
-
- for (i=0; i<length; ++i)
- {
- // Unclear whether 128 should be interpreted as "zero" or whether a
- // symmetrical range should be assumed. The following assumes a
- // symmetrical range.
- src_data.data_in[i] = data[i] / 127.5 - 1;
- }
-
- // Do the sound conversion
-
- retn = src_simple(&src_data, SRC_ConversionMode(), 1);
- assert(retn == 0);
-
- // Convert the result back into 16-bit integers.
-
- destination->alen = src_data.output_frames_gen * 4;
- destination->abuf = Z_Malloc(destination->alen, PU_STATIC,
- &destination->abuf);
- expanded = (int16_t *) destination->abuf;
-
- for (i=0; i<src_data.output_frames_gen; ++i)
- {
- // libsamplerate does not limit itself to the -1.0 .. 1.0 range on
- // output, so a multiplier less than INT16_MAX (32767) is required
- // to avoid overflows or clipping. However, the smaller the
- // multiplier, the quieter the sound effects get, and the more you
- // have to turn down the music to keep it in balance.
-
- // 22265 is the largest multiplier that can be used to resample all
- // of the Vanilla DOOM sound effects to 48 kHz without clipping
- // using SRC_SINC_BEST_QUALITY. It is close enough (only slightly
- // too conservative) for SRC_SINC_MEDIUM_QUALITY and
- // SRC_SINC_FASTEST. PWADs with interestingly different sound
- // effects or target rates other than 48 kHz might still result in
- // clipping--I don't know if there's a limit to it.
-
- // As the number of clipped samples increases, the signal is
- // gradually overtaken by noise, with the loudest parts going first.
- // However, a moderate amount of clipping is often tolerated in the
- // quest for the loudest possible sound overall. The results of
- // using INT16_MAX as the multiplier are not all that bad, but
- // artifacts are noticeable during the loudest parts.
-
- float cvtval_f = src_data.data_out[i] * 22265;
- int32_t cvtval_i = cvtval_f + (cvtval_f < 0 ? -0.5 : 0.5);
-
- // Asymmetrical sound worries me, so we won't use -32768.
- if (cvtval_i < -INT16_MAX) {
- cvtval_i = -INT16_MAX;
- ++clipped;
- } else if (cvtval_i > INT16_MAX) {
- cvtval_i = INT16_MAX;
- ++clipped;
- }
-
- // Left and right channels
-
- expanded[abuf_index++] = cvtval_i;
- expanded[abuf_index++] = cvtval_i;
- }
-
- free(src_data.data_in);
- free(src_data.data_out);
- return clipped;
-}
-
#endif
static boolean ConvertibleRatio(int freq1, int freq2)
@@ -248,12 +160,11 @@ static boolean ConvertibleRatio(int freq1, int freq2)
}
// Generic sound expansion function for any sample rate.
-// Returns number of clipped samples (always 0).
-static uint32_t ExpandSoundData_SDL(byte *data,
- int samplerate,
- int length,
- Mix_Chunk *destination)
+static void ExpandSoundData_SDL(byte *data,
+ int samplerate,
+ uint32_t length,
+ Mix_Chunk *destination)
{
SDL_AudioCVT convertor;
uint32_t expanded_length;
@@ -265,7 +176,6 @@ static uint32_t ExpandSoundData_SDL(byte *data,
// Double up twice: 8 -> 16 bit and mono -> stereo
expanded_length *= 4;
-
destination->alen = expanded_length;
destination->abuf
= Z_Malloc(expanded_length, PU_STATIC, &destination->abuf);
@@ -344,69 +254,92 @@ static uint32_t ExpandSoundData_SDL(byte *data,
}
#endif /* #ifdef LOW_PASS_FILTER */
}
-
- return 0;
}
-// Load and convert a sound effect
-// Returns true if successful
-static boolean CacheSFX(int sound)
+// Load and validate a sound effect lump.
+// Preconditions:
+// S_sfx[sound].lumpnum has been set
+// Postconditions if sound is valid:
+// returns true
+// starred parameters are set, with data_ref pointing to start of sound
+// caller is responsible for releasing the identified lump
+// Postconditions if sound is invalid:
+// returns false
+// starred parameters are garbage
+// lump already released
+
+static boolean LoadSoundLump(int sound,
+ int *lumpnum,
+ int *samplerate,
+ uint32_t *length,
+ byte **data_ref)
{
- int lumpnum;
- unsigned int lumplen;
- int samplerate;
- int clipped;
- unsigned int length;
- byte *data;
+ // Load the sound
- // need to load the sound
+ *lumpnum = S_sfx[sound].lumpnum;
+ *data_ref = W_CacheLumpNum(*lumpnum, PU_STATIC);
+ int lumplen = W_LumpLength(*lumpnum);
+ byte *data = *data_ref;
- lumpnum = S_sfx[sound].lumpnum;
- data = W_CacheLumpNum(lumpnum, PU_STATIC);
- lumplen = W_LumpLength(lumpnum);
+ // Ensure this is a valid sound
- // Check the header, and ensure this is a valid sound
-
- if (lumplen < 8
- || data[0] != 0x03 || data[1] != 0x00)
+ if (lumplen < 8 || data[0] != 0x03 || data[1] != 0x00)
{
- // Invalid sound
-
- return false;
+ // Invalid sound
+ W_ReleaseLumpNum(*lumpnum);
+ return false;
}
// 16 bit sample rate field, 32 bit length field
- samplerate = (data[3] << 8) | data[2];
- length = (data[7] << 24) | (data[6] << 16) | (data[5] << 8) | data[4];
+ *samplerate = (data[3] << 8) | data[2];
+ *length = (data[7] << 24) | (data[6] << 16) | (data[5] << 8) | data[4];
- // If the header specifies that the length of the sound is greater than
- // the length of the lump itself, this is an invalid sound lump
+ // If the header specifies that the length of the sound is
+ // greater than the length of the lump itself, this is an invalid
+ // sound lump.
- if (length > lumplen - 8)
+ if (*length > lumplen - 8)
{
- return false;
+ W_ReleaseLumpNum(*lumpnum);
+ return false;
}
+ // Prune header
+ *data_ref += 8;
+
+ return true;
+}
+
+
+// Load and convert a sound effect
+// Returns true if successful
+
+static boolean CacheSFX_SDL(int sound)
+{
+ int lumpnum;
+ int samplerate;
+ uint32_t length;
+ byte *data;
+
+#ifdef HAVE_LIBSAMPLERATE
+ assert(!use_libsamplerate); // Should be using I_PrecacheSounds_SRC instead
+#endif
+
+ if (!LoadSoundLump(sound, &lumpnum, &samplerate, &length, &data))
+ return false;
+
// Sample rate conversion
- // DWF 2008-02-10: sound_chunks[sound].alen and abuf are determined
- // by ExpandSoundData.
+ // sound_chunks[sound].alen and abuf are determined by ExpandSoundData.
sound_chunks[sound].allocated = 1;
sound_chunks[sound].volume = MIX_MAX_VOLUME;
- clipped = ExpandSoundData(data + 8,
- samplerate,
- length,
- &sound_chunks[sound]);
-
- if (clipped)
- {
- fprintf(stderr, "Sound %d: clipped %u samples (%0.2f %%)\n",
- sound, clipped,
- 400.0 * clipped / sound_chunks[sound].alen);
- }
+ ExpandSoundData_SDL(data,
+ samplerate,
+ length,
+ &sound_chunks[sound]);
// don't need the original lump any more
@@ -415,50 +348,172 @@ static boolean CacheSFX(int sound)
return true;
}
+
#ifdef HAVE_LIBSAMPLERATE
-// Preload all the sound effects - stops nasty ingame freezes
+// Preload and resample all sound effects with libsamplerate.
-static void I_PrecacheSounds(void)
+static void I_PrecacheSounds_SRC(void)
{
char namebuf[9];
- int i;
+ uint32_t sound_i, sample_i;
+ boolean good_sound[NUMSFX];
+ float *resampled_sound[NUMSFX];
+ uint32_t resampled_sound_length[NUMSFX];
+ float norm_factor;
+ float max_amp = 0;
+ unsigned int zone_size;
+
+ assert(use_libsamplerate);
+
+ zone_size = Z_ZoneSize();
+
+ if (zone_size < 32 * 1024 * 1024)
+ {
+ fprintf(stderr,
+ "WARNING: low memory. Heap size is only %d MiB.\n"
+ "WARNING: use_libsamplerate needs more heap!\n"
+ "WARNING: put -mb 64 on the command line to avoid "
+ "\"Error: Z_Malloc: failed on allocation of X bytes\" !\n",
+ zone_size / (1024 * 1024));
+ }
- printf("I_PrecacheSounds: Precaching all sound effects..");
+ printf("I_PrecacheSounds_SRC: Precaching all sound effects..");
- for (i=sfx_pistol; i<NUMSFX; ++i)
+ // Pass 1: resample all sounds and determine maximum amplitude.
+
+ for (sound_i=sfx_pistol; sound_i<NUMSFX; ++sound_i)
{
- if ((i % 6) == 0)
+ good_sound[sound_i] = false;
+
+ if ((sound_i % 6) == 0)
{
printf(".");
fflush(stdout);
}
- sprintf(namebuf, "ds%s", DEH_String(S_sfx[i].name));
+ sprintf(namebuf, "ds%s", DEH_String(S_sfx[sound_i].name));
+ S_sfx[sound_i].lumpnum = W_CheckNumForName(namebuf);
+ if (S_sfx[sound_i].lumpnum != -1)
+ {
+ int lumpnum;
+ int samplerate;
+ uint32_t length;
+ byte *data;
+ double of_temp;
+ int retn;
+ float *rsound;
+ uint32_t rlen;
+ SRC_DATA src_data;
+
+ if (!LoadSoundLump(sound_i, &lumpnum, &samplerate, &length, &data))
+ continue;
+
+ assert(length <= LONG_MAX);
+ src_data.input_frames = length;
+ src_data.data_in = malloc(length * sizeof(float));
+ src_data.src_ratio = (double)mixer_freq / samplerate;
+
+ // mixer_freq / 4 adds a quarter-second safety margin.
+
+ of_temp = src_data.src_ratio * length + (mixer_freq / 4);
+ assert(of_temp <= LONG_MAX);
+ src_data.output_frames = of_temp;
+ src_data.data_out = malloc(src_data.output_frames * sizeof(float));
+ assert(src_data.data_in != NULL && src_data.data_out != NULL);
+
+ // Convert input data to floats
+
+ for (sample_i=0; sample_i<length; ++sample_i)
+ {
+ // Unclear whether 128 should be interpreted as "zero" or
+ // whether a symmetrical range should be assumed. The
+ // following assumes a symmetrical range.
+
+ src_data.data_in[sample_i] = data[sample_i] / 127.5 - 1;
+ }
+
+ // don't need the original lump any more
+
+ W_ReleaseLumpNum(lumpnum);
+
+ // Resample
+
+ retn = src_simple(&src_data, SRC_ConversionMode(), 1);
+ assert(retn == 0);
+ assert(src_data.output_frames_gen > 0);
+ resampled_sound[sound_i] = src_data.data_out;
+ resampled_sound_length[sound_i] = src_data.output_frames_gen;
+ free(src_data.data_in);
+ good_sound[sound_i] = true;
+
+ // Track maximum amplitude for later normalization
+
+ rsound = resampled_sound[sound_i];
+ rlen = resampled_sound_length[sound_i];
+ for (sample_i=0; sample_i<rlen; ++sample_i)
+ {
+ float fabs_amp = fabsf(rsound[sample_i]);
+ if (fabs_amp > max_amp)
+ max_amp = fabs_amp;
+ }
+ }
+ }
- S_sfx[i].lumpnum = W_CheckNumForName(namebuf);
+ // Pass 2: normalize and convert to signed 16-bit stereo.
- if (S_sfx[i].lumpnum != -1)
- {
- CacheSFX(i);
+ if (max_amp <= 0)
+ max_amp = 1;
+ norm_factor = INT16_MAX / max_amp;
- if (sound_chunks[i].abuf != NULL)
+ for (sound_i=sfx_pistol; sound_i<NUMSFX; ++sound_i)
+ {
+ if (good_sound[sound_i])
+ {
+ uint32_t rlen = resampled_sound_length[sound_i];
+ int16_t *expanded;
+ uint32_t abuf_index;
+ float *rsound;
+
+ sound_chunks[sound_i].allocated = 1;
+ sound_chunks[sound_i].volume = MIX_MAX_VOLUME;
+ sound_chunks[sound_i].alen = rlen * 4;
+ sound_chunks[sound_i].abuf = Z_Malloc(sound_chunks[sound_i].alen,
+ PU_STATIC,
+ &sound_chunks[sound_i].abuf);
+ expanded = (int16_t *) sound_chunks[sound_i].abuf;
+ abuf_index=0;
+
+ rsound = resampled_sound[sound_i];
+ for (sample_i=0; sample_i<rlen; ++sample_i)
{
- Z_ChangeTag(sound_chunks[i].abuf, PU_CACHE);
+ float cvtval_f = norm_factor * rsound[sample_i];
+ int16_t cvtval_i = cvtval_f + (cvtval_f < 0 ? -0.5 : 0.5);
+
+ // Left and right channels
+
+ expanded[abuf_index++] = cvtval_i;
+ expanded[abuf_index++] = cvtval_i;
}
+ free(rsound);
}
}
- printf("\n");
+ printf(" norm factor = %f\n", norm_factor);
}
#endif
+
static Mix_Chunk *GetSFXChunk(int sound_id)
{
if (sound_chunks[sound_id].abuf == NULL)
{
- if (!CacheSFX(sound_id))
+#ifdef HAVE_LIBSAMPLERATE
+ if (use_libsamplerate != 0)
+ return NULL; /* If valid, it should have been precached */
+#endif
+ if (!CacheSFX_SDL(sound_id))
return NULL;
}
else
@@ -612,6 +667,32 @@ static void I_SDL_ShutdownSound(void)
sound_initialised = false;
}
+// Calculate slice size, based on MAX_SOUND_SLICE_TIME.
+// The result must be a power of two.
+
+static int GetSliceSize(void)
+{
+ int limit;
+ int n;
+
+ limit = (snd_samplerate * MAX_SOUND_SLICE_TIME) / 1000;
+
+ // Try all powers of two, not exceeding the limit.
+
+ for (n=0;; ++n)
+ {
+ // 2^n <= limit < 2^n+1 ?
+
+ if ((1 << (n + 1)) > limit)
+ {
+ return (1 << n);
+ }
+ }
+
+ // Should never happen?
+
+ return 1024;
+}
static boolean I_SDL_InitSound(void)
{
@@ -635,14 +716,12 @@ static boolean I_SDL_InitSound(void)
return false;
}
- if (Mix_OpenAudio(snd_samplerate, AUDIO_S16SYS, 2, 1024) < 0)
+ if (Mix_OpenAudio(snd_samplerate, AUDIO_S16SYS, 2, GetSliceSize()) < 0)
{
fprintf(stderr, "Error initialising SDL_mixer: %s\n", Mix_GetError());
return false;
}
- ExpandSoundData = ExpandSoundData_SDL;
-
Mix_QuerySpec(&mixer_freq, &mixer_format, &mixer_channels);
#ifdef HAVE_LIBSAMPLERATE
@@ -654,9 +733,7 @@ static boolean I_SDL_InitSound(void)
use_libsamplerate);
}
- ExpandSoundData = ExpandSoundData_SRC;
-
- I_PrecacheSounds();
+ I_PrecacheSounds_SRC();
}
#else
if (use_libsamplerate != 0)
diff --git a/src/i_system.c b/src/i_system.c
index fe596a60..f37b5bec 100644
--- a/src/i_system.c
+++ b/src/i_system.c
@@ -59,7 +59,9 @@
#include "w_wad.h"
#include "z_zone.h"
-int mb_used = 16;
+#define DEFAULT_RAM 16 /* MiB */
+#define MIN_RAM 4 /* MiB */
+
int show_endoom = 1;
// Tactile feedback function, probably used for the Logitech Cyberman
@@ -68,8 +70,99 @@ void I_Tactile(int on, int off, int total)
{
}
-int I_GetHeapSize (void)
+#ifdef _WIN32_WCE
+
+// Windows CE-specific auto-allocation function that allocates the zone
+// size based on the amount of memory reported free by the OS.
+
+static byte *AutoAllocMemory(int *size, int default_ram, int min_ram)
{
+ MEMORYSTATUS memory_status;
+ byte *zonemem;
+ size_t available;
+
+ // Get available physical RAM. We leave one megabyte extra free
+ // for the OS to keep running (my PDA becomes unstable if too
+ // much RAM is allocated)
+
+ GlobalMemoryStatus(&memory_status);
+ available = memory_status.dwAvailPhys - 2 * 1024 * 1024;
+
+ // Limit to default_ram if we have more than that available:
+
+ if (available > default_ram * 1024 * 1024)
+ {
+ available = default_ram * 1024 * 1024;
+ }
+
+ if (available < min_ram * 1024 * 1024)
+ {
+ I_Error("Unable to allocate %i MiB of RAM for zone", min_ram);
+ }
+
+ // Allocate zone:
+
+ *size = available;
+ zonemem = malloc(*size);
+
+ if (zonemem == NULL)
+ {
+ I_Error("Failed when allocating %i bytes", *size);
+ }
+
+ return zonemem;
+}
+
+#else
+
+// Zone memory auto-allocation function that allocates the zone size
+// by trying progressively smaller zone sizes until one is found that
+// works.
+
+static byte *AutoAllocMemory(int *size, int default_ram, int min_ram)
+{
+ byte *zonemem;
+
+ // Allocate the zone memory. This loop tries progressively smaller
+ // zone sizes until a size is found that can be allocated.
+ // If we used the -mb command line parameter, only the parameter
+ // provided is accepted.
+
+ zonemem = NULL;
+
+ while (zonemem == NULL)
+ {
+ // We need a reasonable minimum amount of RAM to start.
+
+ if (default_ram < min_ram)
+ {
+ I_Error("Unable to allocate %i MiB of RAM for zone", default_ram);
+ }
+
+ // Try to allocate the zone memory.
+
+ *size = default_ram * 1024 * 1024;
+
+ zonemem = malloc(*size);
+
+ // Failed to allocate? Reduce zone size until we reach a size
+ // that is acceptable.
+
+ if (zonemem == NULL)
+ {
+ default_ram -= 1;
+ }
+ }
+
+ return zonemem;
+}
+
+#endif
+
+byte *I_ZoneBase (int *size)
+{
+ byte *zonemem;
+ int min_ram, default_ram;
int p;
//!
@@ -79,30 +172,27 @@ int I_GetHeapSize (void)
//
p = M_CheckParm("-mb");
-
+
if (p > 0)
{
- mb_used = atoi(myargv[p+1]);
+ default_ram = atoi(myargv[p+1]);
+ min_ram = default_ram;
+ }
+ else
+ {
+ default_ram = DEFAULT_RAM;
+ min_ram = MIN_RAM;
}
-
- return mb_used*1024*1024;
-}
-
-byte *I_ZoneBase (int *size)
-{
- byte *zonemem;
- *size = I_GetHeapSize();
+ zonemem = AutoAllocMemory(size, default_ram, min_ram);
- zonemem = malloc(*size);
-
printf("zone memory: %p, %x allocated for zone\n",
zonemem, *size);
return zonemem;
}
-//
+//
// I_ConsoleStdout
//
// Returns true if stdout is a real console, false if it is a file
@@ -128,6 +218,9 @@ void I_Init (void)
I_InitJoystick();
}
+#define ENDOOM_W 80
+#define ENDOOM_H 25
+
//
// Displays the text mode ending screen after the game quits
//
@@ -136,6 +229,8 @@ void I_Endoom(void)
{
unsigned char *endoom_data;
unsigned char *screendata;
+ int y;
+ int indent;
endoom_data = W_CacheLumpName(DEH_String("ENDOOM"), PU_STATIC);
@@ -151,7 +246,15 @@ void I_Endoom(void)
// Write the data to the screen memory
screendata = TXT_GetScreenData();
- memcpy(screendata, endoom_data, 4000);
+
+ indent = (ENDOOM_W - TXT_SCREEN_W) / 2;
+
+ for (y=0; y<TXT_SCREEN_H; ++y)
+ {
+ memcpy(screendata + (y * TXT_SCREEN_W * 2),
+ endoom_data + (y * ENDOOM_W + indent) * 2,
+ TXT_SCREEN_W * 2);
+ }
// Wait for a keypress
@@ -246,13 +349,18 @@ void I_Error (char *error, ...)
// On Windows, pop up a dialog box with the error message.
{
char msgbuf[512];
+ wchar_t wmsgbuf[512];
va_start(argptr, error);
memset(msgbuf, 0, sizeof(msgbuf));
vsnprintf(msgbuf, sizeof(msgbuf) - 1, error, argptr);
va_end(argptr);
- MessageBox(NULL, msgbuf, "Error", MB_OK);
+ MultiByteToWideChar(CP_ACP, 0,
+ msgbuf, strlen(msgbuf) + 1,
+ wmsgbuf, sizeof(wmsgbuf));
+
+ MessageBoxW(NULL, wmsgbuf, L"Error", MB_OK);
}
#endif
diff --git a/src/i_video.c b/src/i_video.c
index 0ed4d716..3412051b 100644
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -182,7 +182,7 @@ static boolean MouseShouldBeGrabbed()
if (screensaver_mode)
return false;
- // if the window doesnt have focus, never grab it
+ // if the window doesn't have focus, never grab it
if (!window_focused)
return false;
@@ -193,6 +193,17 @@ static boolean MouseShouldBeGrabbed()
if (fullscreen)
return true;
+#ifdef _WIN32_WCE
+
+ // On Windows CE, always grab input. This is because hardware
+ // button events are only acquired by SDL when the input is grabbed.
+ // Almost all Windows CE devices should have touch screens anyway,
+ // so this shouldn't affect mouse grabbing behavior.
+
+ return true;
+
+#else
+
// Don't grab the mouse if mouse input is disabled
if (!usemouse || nomouse)
@@ -204,18 +215,20 @@ static boolean MouseShouldBeGrabbed()
return false;
// if we specify not to grab the mouse, never grab
-
+
if (!grabmouse)
return false;
// when menu is active or game is paused, release the mouse
-
+
if (menuactive || paused)
return false;
// only grab mouse when playing levels (but not demos)
return (gamestate == GS_LEVEL) && !demoplayback;
+
+#endif /* #ifndef _WIN32_WCE */
}
// Update the value of window_focused when we get a focus event
@@ -362,6 +375,15 @@ static int TranslateKey(SDL_keysym *sym)
case SDLK_PAGEUP: return KEY_PGUP;
case SDLK_PAGEDOWN: return KEY_PGDN;
+#ifdef SDL_HAVE_APP_KEYS
+ case SDLK_APP1: return KEY_F1;
+ case SDLK_APP2: return KEY_F2;
+ case SDLK_APP3: return KEY_F3;
+ case SDLK_APP4: return KEY_F4;
+ case SDLK_APP5: return KEY_F5;
+ case SDLK_APP6: return KEY_F6;
+#endif
+
default:
return tolower(sym->sym);
}
@@ -480,13 +502,20 @@ void I_GetEvent(void)
event.data2 = sdlevent.key.keysym.unicode;
}
- D_PostEvent(&event);
+ if (event.data1 != 0)
+ {
+ D_PostEvent(&event);
+ }
break;
case SDL_KEYUP:
event.type = ev_keyup;
event.data1 = TranslateKey(&sdlevent.key.keysym);
- D_PostEvent(&event);
+
+ if (event.data1 != 0)
+ {
+ D_PostEvent(&event);
+ }
break;
/*
@@ -964,125 +993,155 @@ static screen_mode_t *I_FindScreenMode(int w, int h)
return best_mode;
}
-// If the video mode set in the configuration file is not available,
-// try to choose a different mode.
+// Adjust to an appropriate fullscreen mode.
+// Returns true if successful.
-static void I_AutoAdjustSettings(void)
+static boolean AutoAdjustFullscreen(void)
{
- if (fullscreen)
- {
- SDL_Rect **modes;
- SDL_Rect *best_mode;
- screen_mode_t *screen_mode;
- int target_pixels, diff, best_diff;
- int i;
-
- modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
-
- // Find the best mode that matches the mode specified in the
- // configuration file
-
- best_mode = NULL;
- best_diff = INT_MAX;
- target_pixels = screen_width * screen_height;
+ SDL_Rect **modes;
+ SDL_Rect *best_mode;
+ screen_mode_t *screen_mode;
+ int target_pixels, diff, best_diff;
+ int i;
- for (i=0; modes[i] != NULL; ++i)
- {
- //printf("%ix%i?\n", modes[i]->w, modes[i]->h);
+ modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
- // What screen_mode_t would be used for this video mode?
+ // No fullscreen modes available at all?
- screen_mode = I_FindScreenMode(modes[i]->w, modes[i]->h);
+ if (modes == NULL || modes == (SDL_Rect **) -1 || *modes == NULL)
+ {
+ return false;
+ }
- // Never choose a screen mode that we cannot run in, or
- // is poor quality for fullscreen
+ // Find the best mode that matches the mode specified in the
+ // configuration file
- if (screen_mode == NULL || screen_mode->poor_quality)
- {
- // printf("\tUnsupported / poor quality\n");
- continue;
- }
+ best_mode = NULL;
+ best_diff = INT_MAX;
+ target_pixels = screen_width * screen_height;
- // Do we have the exact mode?
- // If so, no autoadjust needed
+ for (i=0; modes[i] != NULL; ++i)
+ {
+ //printf("%ix%i?\n", modes[i]->w, modes[i]->h);
- if (screen_width == modes[i]->w && screen_height == modes[i]->h)
- {
- // printf("\tExact mode!\n");
- return;
- }
+ // What screen_mode_t would be used for this video mode?
- // Is this mode better than the current mode?
+ screen_mode = I_FindScreenMode(modes[i]->w, modes[i]->h);
- diff = (screen_width - modes[i]->w)
- * (screen_width - modes[i]->w)
- + (screen_height - modes[i]->h)
- * (screen_height - modes[i]->h);
+ // Never choose a screen mode that we cannot run in, or
+ // is poor quality for fullscreen
- if (diff < best_diff)
- {
- // printf("\tA valid mode\n");
- best_mode = modes[i];
- best_diff = diff;
- }
+ if (screen_mode == NULL || screen_mode->poor_quality)
+ {
+ // printf("\tUnsupported / poor quality\n");
+ continue;
}
- if (best_mode == NULL)
- {
- // Unable to find a valid mode!
+ // Do we have the exact mode?
+ // If so, no autoadjust needed
- I_Error("Unable to find any valid video mode at all!");
+ if (screen_width == modes[i]->w && screen_height == modes[i]->h)
+ {
+ // printf("\tExact mode!\n");
+ return true;
}
- printf("I_InitGraphics: %ix%i mode not supported on this machine.\n",
- screen_width, screen_height);
+ // Is this mode better than the current mode?
- screen_width = best_mode->w;
- screen_height = best_mode->h;
+ diff = (screen_width - modes[i]->w) * (screen_width - modes[i]->w)
+ + (screen_height - modes[i]->h) * (screen_height - modes[i]->h);
+ if (diff < best_diff)
+ {
+ // printf("\tA valid mode\n");
+ best_mode = modes[i];
+ best_diff = diff;
+ }
}
- else
+
+ if (best_mode == NULL)
{
- screen_mode_t *best_mode;
+ // Unable to find a valid mode!
+
+ return false;
+ }
- //
- // Windowed mode.
- //
- // Find a screen_mode_t to fit within the current settings
- //
+ printf("I_InitGraphics: %ix%i mode not supported on this machine.\n",
+ screen_width, screen_height);
- best_mode = I_FindScreenMode(screen_width, screen_height);
+ screen_width = best_mode->w;
+ screen_height = best_mode->h;
- if (best_mode == NULL)
- {
- // Nothing fits within the current settings.
- // Pick the closest to 320x200 possible.
+ return true;
+}
- best_mode = I_FindScreenMode(SCREENWIDTH, SCREENHEIGHT_4_3);
- }
+// Auto-adjust to a valid windowed mode.
+
+static void AutoAdjustWindowed(void)
+{
+ screen_mode_t *best_mode;
- // Do we have the exact mode already?
+ // Find a screen_mode_t to fit within the current settings
- if (best_mode->width == screen_width
- && best_mode->height == screen_height)
- {
- return;
- }
+ best_mode = I_FindScreenMode(screen_width, screen_height);
+
+ if (best_mode == NULL)
+ {
+ // Nothing fits within the current settings.
+ // Pick the closest to 320x200 possible.
+
+ best_mode = I_FindScreenMode(SCREENWIDTH, SCREENHEIGHT_4_3);
+ }
+
+ // Switch to the best mode if necessary.
+ if (best_mode->width != screen_width || best_mode->height != screen_height)
+ {
printf("I_InitGraphics: Cannot run at specified mode: %ix%i\n",
screen_width, screen_height);
screen_width = best_mode->width;
screen_height = best_mode->height;
}
+}
- printf("I_InitGraphics: Auto-adjusted to %ix%i.\n",
- screen_width, screen_height);
+// If the video mode set in the configuration file is not available,
+// try to choose a different mode.
+
+static void I_AutoAdjustSettings(void)
+{
+ int old_screen_w, old_screen_h;
+
+ old_screen_w = screen_width;
+ old_screen_h = screen_height;
+
+ // If we are running fullscreen, try to autoadjust to a valid fullscreen
+ // mode. If this is impossible, switch to windowed.
- printf("NOTE: Your video settings have been adjusted. "
- "To disable this behavior,\n"
- "set autoadjust_video_settings to 0 in your "
- "configuration file.\n");
+ if (fullscreen && !AutoAdjustFullscreen())
+ {
+ fullscreen = 0;
+ }
+
+ // If we are running windowed, pick a valid window size.
+
+ if (!fullscreen)
+ {
+ AutoAdjustWindowed();
+ }
+
+ // Have the settings changed? Show a message.
+
+ if (screen_width != old_screen_w || screen_height != old_screen_h)
+ {
+ printf("I_InitGraphics: Auto-adjusted to %ix%i.\n",
+ screen_width, screen_height);
+
+ printf("NOTE: Your video settings have been adjusted. "
+ "To disable this behavior,\n"
+ "set autoadjust_video_settings to 0 in your "
+ "configuration file.\n");
+ }
}
// Set video size to a particular scale factor (1x, 2x, 3x, etc.)
@@ -1353,7 +1412,7 @@ static void SetSDLVideoDriver(void)
free(env_string);
}
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(_WIN32_WCE)
// Allow -gdi as a shortcut for using the windib driver.
diff --git a/src/m_config.c b/src/m_config.c
index c54b3774..0d0faea0 100644
--- a/src/m_config.c
+++ b/src/m_config.c
@@ -31,6 +31,11 @@
#include <ctype.h>
#include <errno.h>
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
#include "config.h"
#include "deh_main.h"
#include "doomdef.h"
@@ -87,6 +92,61 @@ extern int key_use;
extern int key_strafe;
extern int key_speed;
+extern int key_pause;
+
+// Menu control keys:
+
+extern int key_menu_activate;
+extern int key_menu_up;
+extern int key_menu_down;
+extern int key_menu_left;
+extern int key_menu_right;
+extern int key_menu_back;
+extern int key_menu_forward;
+extern int key_menu_confirm;
+extern int key_menu_abort;
+
+// Keyboard shortcuts:
+
+extern int key_menu_help;
+extern int key_menu_save;
+extern int key_menu_load;
+extern int key_menu_volume;
+extern int key_menu_detail;
+extern int key_menu_qsave;
+extern int key_menu_endgame;
+extern int key_menu_messages;
+extern int key_menu_qload;
+extern int key_menu_quit;
+extern int key_menu_gamma;
+
+extern int key_menu_incscreen;
+extern int key_menu_decscreen;
+
+extern int key_map_north;
+extern int key_map_south;
+extern int key_map_east;
+extern int key_map_west;
+extern int key_map_zoomin;
+extern int key_map_zoomout;
+extern int key_map_toggle;
+extern int key_map_maxzoom;
+extern int key_map_follow;
+extern int key_map_grid;
+extern int key_map_mark;
+extern int key_map_clearmark;
+
+extern int key_weapon1;
+extern int key_weapon2;
+extern int key_weapon3;
+extern int key_weapon4;
+extern int key_weapon5;
+extern int key_weapon6;
+extern int key_weapon7;
+extern int key_weapon8;
+
+extern int key_message_refresh;
+
extern int mousebfire;
extern int mousebstrafe;
extern int mousebforward;
@@ -696,6 +756,8 @@ static default_t extra_defaults_list[] =
CONFIG_VARIABLE_INT(dclick_use, dclick_use),
+#ifdef FEATURE_SOUND
+
//!
// Controls whether libsamplerate support is used for performing
// sample rate conversions of sound effects. Support for this
@@ -710,6 +772,272 @@ static default_t extra_defaults_list[] =
//
CONFIG_VARIABLE_INT(use_libsamplerate, use_libsamplerate),
+
+#endif
+
+ //!
+ // Key to pause or unpause the game.
+ //
+
+ CONFIG_VARIABLE_KEY(key_pause, key_pause),
+
+ //!
+ // Key that activates the menu when pressed.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_activate, key_menu_activate),
+
+ //!
+ // Key that moves the cursor up on the menu.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_up, key_menu_up),
+
+ //!
+ // Key that moves the cursor down on the menu.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_down, key_menu_down),
+
+ //!
+ // Key that moves the currently selected slider on the menu left.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_left, key_menu_left),
+
+ //!
+ // Key that moves the currently selected slider on the menu right.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_right, key_menu_right),
+
+ //!
+ // Key to go back to the previous menu.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_back, key_menu_back),
+
+ //!
+ // Key to activate the currently selected menu item.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_forward, key_menu_forward),
+
+ //!
+ // Key to answer 'yes' to a question in the menu.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_confirm, key_menu_confirm),
+
+ //!
+ // Key to answer 'no' to a question in the menu.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_abort, key_menu_abort),
+
+ //!
+ // Keyboard shortcut to bring up the help screen.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_help, key_menu_help),
+
+ //!
+ // Keyboard shortcut to bring up the save game menu.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_save, key_menu_save),
+
+ //!
+ // Keyboard shortcut to bring up the load game menu.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_load, key_menu_load),
+
+ //!
+ // Keyboard shortcut to bring up the sound volume menu.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_volume, key_menu_volume),
+
+ //!
+ // Keyboard shortcut to toggle the detail level.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_detail, key_menu_detail),
+
+ //!
+ // Keyboard shortcut to quicksave the current game.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_qsave, key_menu_qsave),
+
+ //!
+ // Keyboard shortcut to end the game.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_endgame, key_menu_endgame),
+
+ //!
+ // Keyboard shortcut to toggle heads-up messages.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_messages, key_menu_messages),
+
+ //!
+ // Keyboard shortcut to load the last quicksave.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_qload, key_menu_qload),
+
+ //!
+ // Keyboard shortcut to quit the game.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_quit, key_menu_quit),
+
+ //!
+ // Keyboard shortcut to toggle the gamma correction level.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_gamma, key_menu_gamma),
+
+ //!
+ // Keyboard shortcut to increase the screen size.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_incscreen, key_menu_incscreen),
+
+ //!
+ // Keyboard shortcut to decrease the screen size.
+ //
+
+ CONFIG_VARIABLE_KEY(key_menu_decscreen, key_menu_decscreen),
+
+ //!
+ // Key to toggle the map view.
+ //
+
+ CONFIG_VARIABLE_KEY(key_map_toggle, key_map_toggle),
+
+ //!
+ // Key to pan north when in the map view.
+ //
+
+ CONFIG_VARIABLE_KEY(key_map_north, key_map_north),
+
+ //!
+ // Key to pan south when in the map view.
+ //
+
+ CONFIG_VARIABLE_KEY(key_map_south, key_map_south),
+
+ //!
+ // Key to pan east when in the map view.
+ //
+
+ CONFIG_VARIABLE_KEY(key_map_east, key_map_east),
+
+ //!
+ // Key to pan west when in the map view.
+ //
+
+ CONFIG_VARIABLE_KEY(key_map_west, key_map_west),
+
+ //!
+ // Key to zoom in when in the map view.
+ //
+
+ CONFIG_VARIABLE_KEY(key_map_zoomin, key_map_zoomin),
+
+ //!
+ // Key to zoom out when in the map view.
+ //
+
+ CONFIG_VARIABLE_KEY(key_map_zoomout, key_map_zoomout),
+
+ //!
+ // Key to zoom out the maximum amount when in the map view.
+ //
+
+ CONFIG_VARIABLE_KEY(key_map_maxzoom, key_map_maxzoom),
+
+ //!
+ // Key to toggle follow mode when in the map view.
+ //
+
+ CONFIG_VARIABLE_KEY(key_map_follow, key_map_follow),
+
+ //!
+ // Key to toggle the grid display when in the map view.
+ //
+
+ CONFIG_VARIABLE_KEY(key_map_grid, key_map_grid),
+
+ //!
+ // Key to set a mark when in the map view.
+ //
+
+ CONFIG_VARIABLE_KEY(key_map_mark, key_map_mark),
+
+ //!
+ // Key to clear all marks when in the map view.
+ //
+
+ CONFIG_VARIABLE_KEY(key_map_clearmark, key_map_clearmark),
+
+ //!
+ // Key to select weapon 1.
+ //
+
+ CONFIG_VARIABLE_KEY(key_weapon1, key_weapon1),
+
+ //!
+ // Key to select weapon 2.
+ //
+
+ CONFIG_VARIABLE_KEY(key_weapon2, key_weapon2),
+
+ //!
+ // Key to select weapon 3.
+ //
+
+ CONFIG_VARIABLE_KEY(key_weapon3, key_weapon3),
+
+ //!
+ // Key to select weapon 4.
+ //
+
+ CONFIG_VARIABLE_KEY(key_weapon4, key_weapon4),
+
+ //!
+ // Key to select weapon 5.
+ //
+
+ CONFIG_VARIABLE_KEY(key_weapon5, key_weapon5),
+
+ //!
+ // Key to select weapon 6.
+ //
+
+ CONFIG_VARIABLE_KEY(key_weapon6, key_weapon6),
+
+ //!
+ // Key to select weapon 7.
+ //
+
+ CONFIG_VARIABLE_KEY(key_weapon7, key_weapon7),
+
+ //!
+ // Key to select weapon 8.
+ //
+
+ CONFIG_VARIABLE_KEY(key_weapon8, key_weapon8),
+
+ //!
+ // Key to re-display last message.
+ //
+
+ CONFIG_VARIABLE_KEY(key_message_refresh, key_message_refresh),
};
static default_collection_t extra_defaults =
@@ -1006,9 +1334,11 @@ void M_LoadDefaults (void)
void M_SetConfigDir(void)
{
-#ifndef _WIN32
- // Ignore the HOME environment variable on Windows - just behave
- // like Vanilla Doom.
+#if !defined(_WIN32) || defined(_WIN32_WCE)
+
+ // Configuration settings are stored in ~/.chocolate-doom/,
+ // except on Windows, where we behave like Vanilla Doom and
+ // save in the current directory.
char *homedir;
@@ -1031,7 +1361,7 @@ void M_SetConfigDir(void)
else
#endif /* #ifndef _WIN32 */
{
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(_WIN32_WCE)
//!
// @platform windows
// @vanilla
@@ -1055,3 +1385,76 @@ void M_SetConfigDir(void)
}
}
+#ifdef _WIN32_WCE
+
+static int SystemHasKeyboard(void)
+{
+ HKEY key;
+ DWORD valtype;
+ DWORD valsize;
+ DWORD result;
+
+ if (RegOpenKeyExW(HKEY_CURRENT_USER,
+ L"\\Software\\Microsoft\\Shell", 0,
+ KEY_READ, &key) != ERROR_SUCCESS)
+ {
+ return 0;
+ }
+
+ valtype = REG_SZ;
+ valsize = sizeof(DWORD);
+
+ if (RegQueryValueExW(key, L"HasKeyboard", NULL, &valtype,
+ (LPBYTE) &result, &valsize) != ERROR_SUCCESS)
+ {
+ result = 0;
+ }
+
+ // Close the key
+
+ RegCloseKey(key);
+
+ return result;
+}
+
+//
+// Apply custom defaults for Windows CE.
+//
+
+static void M_ApplyWindowsCEDefaults(void)
+{
+ // If the system doesn't have a keyboard, patch the default
+ // configuration to use the hardware keys.
+
+ if (!SystemHasKeyboard())
+ {
+ key_use = KEY_F1;
+ key_fire = KEY_F2;
+ key_menu_activate = KEY_F3;
+ key_map_toggle = KEY_F4;
+
+ key_menu_help = 0;
+ key_menu_save = 0;
+ key_menu_load = 0;
+ key_menu_volume = 0;
+
+ key_menu_confirm = KEY_ENTER;
+ key_menu_back = KEY_F2;
+ key_menu_abort = KEY_F2;
+ }
+}
+
+#endif
+
+//
+// Apply custom patches to the default values depending on the
+// platform we are running on.
+//
+
+void M_ApplyPlatformDefaults(void)
+{
+#ifdef _WIN32_WCE
+ M_ApplyWindowsCEDefaults();
+#endif
+}
+
diff --git a/src/m_config.h b/src/m_config.h
index 747569cd..ff11e6d6 100644
--- a/src/m_config.h
+++ b/src/m_config.h
@@ -31,6 +31,7 @@
void M_LoadDefaults(void);
void M_SaveDefaults(void);
void M_SetConfigDir(void);
+void M_ApplyPlatformDefaults(void);
extern char *configdir;
diff --git a/src/m_menu.c b/src/m_menu.c
index aab2afce..1ced1d16 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -72,6 +72,35 @@ extern boolean message_dontfuckwithme;
extern boolean chat_on; // in heads-up code
//
+// menu keys:
+//
+
+int key_menu_activate = KEY_ESCAPE;
+int key_menu_up = KEY_UPARROW;
+int key_menu_down = KEY_DOWNARROW;
+int key_menu_left = KEY_LEFTARROW;
+int key_menu_right = KEY_RIGHTARROW;
+int key_menu_back = KEY_BACKSPACE;
+int key_menu_forward = KEY_ENTER;
+int key_menu_confirm = 'y';
+int key_menu_abort = 'n';
+
+int key_menu_help = KEY_F1;
+int key_menu_save = KEY_F2;
+int key_menu_load = KEY_F3;
+int key_menu_volume = KEY_F4;
+int key_menu_detail = KEY_F5;
+int key_menu_qsave = KEY_F6;
+int key_menu_endgame = KEY_F7;
+int key_menu_messages = KEY_F8;
+int key_menu_qload = KEY_F9;
+int key_menu_quit = KEY_F10;
+int key_menu_gamma = KEY_F11;
+
+int key_menu_incscreen = KEY_EQUALS;
+int key_menu_decscreen = KEY_MINUS;
+
+//
// defaulted values
//
int mouseSensitivity = 5;
@@ -672,9 +701,9 @@ void M_SaveGame (int choice)
//
char tempstring[80];
-void M_QuickSaveResponse(int ch)
+void M_QuickSaveResponse(int key)
{
- if (ch == 'y')
+ if (key == key_menu_confirm)
{
M_DoSave(quickSaveSlot);
S_StartSound(NULL,sfx_swtchx);
@@ -709,9 +738,9 @@ void M_QuickSave(void)
//
// M_QuickLoad
//
-void M_QuickLoadResponse(int ch)
+void M_QuickLoadResponse(int key)
{
- if (ch == 'y')
+ if (key == key_menu_confirm)
{
M_LoadSelect(quickSaveSlot);
S_StartSound(NULL,sfx_swtchx);
@@ -924,9 +953,9 @@ void M_DrawEpisode(void)
V_DrawPatchDirect (54,38,0,W_CacheLumpName(DEH_String("M_EPISOD"),PU_CACHE));
}
-void M_VerifyNightmare(int ch)
+void M_VerifyNightmare(int key)
{
- if (ch != 'y')
+ if (key != key_menu_confirm)
return;
G_DeferedInitNew(nightmare,epi+1,1);
@@ -1024,9 +1053,9 @@ void M_ChangeMessages(int choice)
//
// M_EndGame
//
-void M_EndGameResponse(int ch)
+void M_EndGameResponse(int key)
{
- if (ch != 'y')
+ if (key != key_menu_confirm)
return;
currentMenu->lastOn = itemOn;
@@ -1120,9 +1149,9 @@ int quitsounds2[8] =
-void M_QuitResponse(int ch)
+void M_QuitResponse(int key)
{
- if (ch != 'y')
+ if (key != key_menu_confirm)
return;
if (!netgame)
{
@@ -1421,34 +1450,34 @@ boolean M_Responder (event_t* ev)
{
if (ev->data3 == -1)
{
- key = KEY_UPARROW;
+ key = key_menu_up;
joywait = I_GetTime() + 5;
}
else if (ev->data3 == 1)
{
- key = KEY_DOWNARROW;
+ key = key_menu_down;
joywait = I_GetTime() + 5;
}
if (ev->data2 == -1)
{
- key = KEY_LEFTARROW;
+ key = key_menu_left;
joywait = I_GetTime() + 2;
}
else if (ev->data2 == 1)
{
- key = KEY_RIGHTARROW;
+ key = key_menu_right;
joywait = I_GetTime() + 2;
}
if (ev->data1&1)
{
- key = KEY_ENTER;
+ key = key_menu_forward;
joywait = I_GetTime() + 5;
}
if (ev->data1&2)
{
- key = KEY_BACKSPACE;
+ key = key_menu_back;
joywait = I_GetTime() + 5;
}
}
@@ -1459,13 +1488,13 @@ boolean M_Responder (event_t* ev)
mousey += ev->data3;
if (mousey < lasty-30)
{
- key = KEY_DOWNARROW;
+ key = key_menu_down;
mousewait = I_GetTime() + 5;
mousey = lasty -= 30;
}
else if (mousey > lasty+30)
{
- key = KEY_UPARROW;
+ key = key_menu_up;
mousewait = I_GetTime() + 5;
mousey = lasty += 30;
}
@@ -1473,26 +1502,26 @@ boolean M_Responder (event_t* ev)
mousex += ev->data2;
if (mousex < lastx-30)
{
- key = KEY_LEFTARROW;
+ key = key_menu_left;
mousewait = I_GetTime() + 5;
mousex = lastx -= 30;
}
else if (mousex > lastx+30)
{
- key = KEY_RIGHTARROW;
+ key = key_menu_right;
mousewait = I_GetTime() + 5;
mousex = lastx += 30;
}
if (ev->data1&1)
{
- key = KEY_ENTER;
+ key = key_menu_forward;
mousewait = I_GetTime() + 15;
}
if (ev->data1&2)
{
- key = KEY_BACKSPACE;
+ key = key_menu_back;
mousewait = I_GetTime() + 15;
}
}
@@ -1514,7 +1543,7 @@ boolean M_Responder (event_t* ev)
if (testcontrols)
{
- if (key == KEY_ESCAPE || key == KEY_F10)
+ if (key == key_menu_activate || key == key_menu_quit)
{
I_Quit();
return true;
@@ -1574,121 +1603,136 @@ boolean M_Responder (event_t* ev)
// Take care of any messages that need input
if (messageToPrint)
{
- if (messageNeedsInput == true &&
- !(ch == ' ' || ch == 'n' || ch == 'y' || key == KEY_ESCAPE))
- return false;
-
+ if (messageNeedsInput)
+ {
+ if (key != ' ' && key != KEY_ESCAPE
+ && key != key_menu_confirm && key != key_menu_abort)
+ {
+ return false;
+ }
+ }
+
menuactive = messageLastMenuActive;
messageToPrint = 0;
if (messageRoutine)
- messageRoutine(ch);
-
+ messageRoutine(key);
+
menuactive = false;
S_StartSound(NULL,sfx_swtchx);
return true;
}
-
- if (devparm && key == KEY_F1)
+
+ if (devparm && key == key_menu_help)
{
G_ScreenShot ();
return true;
}
-
-
+
// F-Keys
if (!menuactive)
- switch(key)
- {
- case KEY_MINUS: // Screen size down
+ {
+ if (key == key_menu_decscreen) // Screen size down
+ {
if (automapactive || chat_on)
return false;
M_SizeDisplay(0);
S_StartSound(NULL,sfx_stnmov);
return true;
-
- case KEY_EQUALS: // Screen size up
+ }
+ else if (key == key_menu_incscreen) // Screen size up
+ {
if (automapactive || chat_on)
return false;
M_SizeDisplay(1);
S_StartSound(NULL,sfx_stnmov);
return true;
-
- case KEY_F1: // Help key
+ }
+ else if (key == key_menu_help) // Help key
+ {
M_StartControlPanel ();
if ( gamemode == retail )
currentMenu = &ReadDef2;
else
currentMenu = &ReadDef1;
-
+
itemOn = 0;
S_StartSound(NULL,sfx_swtchn);
return true;
-
- case KEY_F2: // Save
+ }
+ else if (key == key_menu_save) // Save
+ {
M_StartControlPanel();
S_StartSound(NULL,sfx_swtchn);
M_SaveGame(0);
return true;
-
- case KEY_F3: // Load
+ }
+ else if (key == key_menu_load) // Load
+ {
M_StartControlPanel();
S_StartSound(NULL,sfx_swtchn);
M_LoadGame(0);
return true;
-
- case KEY_F4: // Sound Volume
+ }
+ else if (key == key_menu_volume) // Sound Volume
+ {
M_StartControlPanel ();
currentMenu = &SoundDef;
itemOn = sfx_vol;
S_StartSound(NULL,sfx_swtchn);
return true;
-
- case KEY_F5: // Detail toggle
+ }
+ else if (key == key_menu_detail) // Detail toggle
+ {
M_ChangeDetail(0);
S_StartSound(NULL,sfx_swtchn);
return true;
-
- case KEY_F6: // Quicksave
+ }
+ else if (key == key_menu_qsave) // Quicksave
+ {
S_StartSound(NULL,sfx_swtchn);
M_QuickSave();
return true;
-
- case KEY_F7: // End game
+ }
+ else if (key == key_menu_endgame) // End game
+ {
S_StartSound(NULL,sfx_swtchn);
M_EndGame(0);
return true;
-
- case KEY_F8: // Toggle messages
+ }
+ else if (key == key_menu_messages) // Toggle messages
+ {
M_ChangeMessages(0);
S_StartSound(NULL,sfx_swtchn);
return true;
-
- case KEY_F9: // Quickload
+ }
+ else if (key == key_menu_qload) // Quickload
+ {
S_StartSound(NULL,sfx_swtchn);
M_QuickLoad();
return true;
-
- case KEY_F10: // Quit DOOM
+ }
+ else if (key == key_menu_quit) // Quit DOOM
+ {
S_StartSound(NULL,sfx_swtchn);
M_QuitDOOM(0);
return true;
-
- case KEY_F11: // gamma toggle
+ }
+ else if (key == key_menu_gamma) // gamma toggle
+ {
usegamma++;
if (usegamma > 4)
usegamma = 0;
players[consoleplayer].message = DEH_String(gammamsg[usegamma]);
I_SetPalette (W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE));
return true;
-
}
+ }
-
// Pop-up menu?
if (!menuactive)
{
- if (key == KEY_ESCAPE)
+ if (key == key_menu_activate)
{
M_StartControlPanel ();
S_StartSound(NULL,sfx_swtchn);
@@ -1699,19 +1743,25 @@ boolean M_Responder (event_t* ev)
// Keys usable within menu
- switch (key)
+
+ if (key == key_menu_down)
{
- case KEY_DOWNARROW:
- do
+ // Move down to next item
+
+ do
{
if (itemOn+1 > currentMenu->numitems-1)
itemOn = 0;
else itemOn++;
S_StartSound(NULL,sfx_pstop);
} while(currentMenu->menuitems[itemOn].status==-1);
+
return true;
-
- case KEY_UPARROW:
+ }
+ else if (key == key_menu_up)
+ {
+ // Move back up to previous item
+
do
{
if (!itemOn)
@@ -1719,9 +1769,13 @@ boolean M_Responder (event_t* ev)
else itemOn--;
S_StartSound(NULL,sfx_pstop);
} while(currentMenu->menuitems[itemOn].status==-1);
+
return true;
+ }
+ else if (key == key_menu_left)
+ {
+ // Slide slider left
- case KEY_LEFTARROW:
if (currentMenu->menuitems[itemOn].routine &&
currentMenu->menuitems[itemOn].status == 2)
{
@@ -1729,8 +1783,11 @@ boolean M_Responder (event_t* ev)
currentMenu->menuitems[itemOn].routine(0);
}
return true;
-
- case KEY_RIGHTARROW:
+ }
+ else if (key == key_menu_right)
+ {
+ // Slide slider right
+
if (currentMenu->menuitems[itemOn].routine &&
currentMenu->menuitems[itemOn].status == 2)
{
@@ -1738,8 +1795,11 @@ boolean M_Responder (event_t* ev)
currentMenu->menuitems[itemOn].routine(1);
}
return true;
+ }
+ else if (key == key_menu_forward)
+ {
+ // Activate menu item
- case KEY_ENTER:
if (currentMenu->menuitems[itemOn].routine &&
currentMenu->menuitems[itemOn].status)
{
@@ -1756,14 +1816,20 @@ boolean M_Responder (event_t* ev)
}
}
return true;
-
- case KEY_ESCAPE:
+ }
+ else if (key == key_menu_activate)
+ {
+ // Deactivate menu
+
currentMenu->lastOn = itemOn;
M_ClearMenus ();
S_StartSound(NULL,sfx_swtchx);
return true;
-
- case KEY_BACKSPACE:
+ }
+ else if (key == key_menu_back)
+ {
+ // Go back to previous menu
+
currentMenu->lastOn = itemOn;
if (currentMenu->prevMenu)
{
@@ -1772,24 +1838,30 @@ boolean M_Responder (event_t* ev)
S_StartSound(NULL,sfx_swtchn);
}
return true;
-
- default:
+ }
+ else if (ch != 0)
+ {
+ // Keyboard shortcut?
+
for (i = itemOn+1;i < currentMenu->numitems;i++)
+ {
if (currentMenu->menuitems[i].alphaKey == ch)
{
itemOn = i;
S_StartSound(NULL,sfx_pstop);
return true;
}
+ }
+
for (i = 0;i <= itemOn;i++)
+ {
if (currentMenu->menuitems[i].alphaKey == ch)
{
itemOn = i;
S_StartSound(NULL,sfx_pstop);
return true;
}
- break;
-
+ }
}
return false;
diff --git a/src/p_enemy.c b/src/p_enemy.c
index 4729dbc5..760bbbc8 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -1612,6 +1612,57 @@ void A_Explode (mobj_t* thingy)
P_RadiusAttack(thingy, thingy->target, 128);
}
+// Check whether the death of the specified monster type is allowed
+// to trigger the end of episode special action.
+//
+// This behavior changed in v1.9, the most notable effect of which
+// was to break uac_dead.wad
+
+static boolean CheckBossEnd(mobjtype_t motype)
+{
+ if (gameversion < exe_ultimate)
+ {
+ if (gamemap != 8)
+ {
+ return false;
+ }
+
+ // Baron death on later episodes is nothing special.
+
+ if (motype == MT_BRUISER && gameepisode != 1)
+ {
+ return false;
+ }
+
+ return true;
+ }
+ else
+ {
+ // New logic that appeared in Ultimate Doom.
+ // Looks like the logic was overhauled while adding in the
+ // episode 4 support. Now bosses only trigger on their
+ // specific episode.
+
+ switch(gameepisode)
+ {
+ case 1:
+ return gamemap == 8 && motype == MT_BRUISER;
+
+ case 2:
+ return gamemap == 8 && motype == MT_CYBORG;
+
+ case 3:
+ return gamemap == 8 && motype == MT_SPIDER;
+
+ case 4:
+ return (gamemap == 6 && motype == MT_CYBORG)
+ || (gamemap == 8 && motype == MT_SPIDER);
+
+ default:
+ return gamemap == 8;
+ }
+ }
+}
//
// A_BossDeath
@@ -1636,75 +1687,12 @@ void A_BossDeath (mobj_t* mo)
}
else
{
- switch(gameepisode)
- {
- case 1:
- if (gamemap != 8)
- return;
-
- // fraggle: disable this as it breaks uac_dead.wad.
- // There is at least one version of Doom 1.9 which it is
- // possible to play uac_dead through on. I think this was
- // added here for Ultimate Doom.
- //
- // See lmps/doom/ultimate/uac_dead.zip in idgames for
- // an example of a demo which goes out of sync if this
- // is left in here.
- //
- // For the time being, I'm making the assumption that
- // doing this is not going to break anything else.
- //
- // 2005/10/24: Modify this to test the gameversion setting
-
- if (gameversion >= exe_ultimate && mo->type != MT_BRUISER)
- return;
- break;
-
- case 2:
- if (gamemap != 8)
- return;
-
- if (mo->type != MT_CYBORG)
- return;
- break;
-
- case 3:
- if (gamemap != 8)
- return;
-
- if (mo->type != MT_SPIDER)
- return;
-
- break;
-
- case 4:
- switch(gamemap)
- {
- case 6:
- if (mo->type != MT_CYBORG)
- return;
- break;
-
- case 8:
- if (mo->type != MT_SPIDER)
- return;
- break;
-
- default:
- return;
- break;
- }
- break;
-
- default:
- if (gamemap != 8)
- return;
- break;
- }
-
+ if (!CheckBossEnd(mo->type))
+ {
+ return;
+ }
}
-
// make sure there is a player alive for victory
for (i=0 ; i<MAXPLAYERS ; i++)
if (playeringame[i] && players[i].health > 0)
diff --git a/src/w_file_win32.c b/src/w_file_win32.c
index 05d3c445..ec17cf6c 100644
--- a/src/w_file_win32.c
+++ b/src/w_file_win32.c
@@ -35,6 +35,12 @@
#include "w_file.h"
#include "z_zone.h"
+// This constant doesn't exist in VC6:
+
+#ifndef INVALID_SET_FILE_POINTER
+#define INVALID_SET_FILE_POINTER 0xffffffff
+#endif
+
typedef struct
{
wad_file_t wad;
@@ -88,12 +94,24 @@ unsigned int GetFileLength(HANDLE handle)
static wad_file_t *W_Win32_OpenFile(char *path)
{
win32_wad_file_t *result;
+ wchar_t wpath[MAX_PATH + 1];
HANDLE handle;
- OFSTRUCT fileinfo;
- handle = (HANDLE) OpenFile(path, &fileinfo, OF_READ);
+ // Open the file:
+
+ MultiByteToWideChar(CP_OEMCP, 0,
+ path, strlen(path) + 1,
+ wpath, sizeof(wpath));
+
+ handle = CreateFileW(wpath,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
- if (handle == (HANDLE) HFILE_ERROR)
+ if (handle == INVALID_HANDLE_VALUE)
{
return NULL;
}
diff --git a/src/z_native.c b/src/z_native.c
index 199c9426..37bdc02a 100644
--- a/src/z_native.c
+++ b/src/z_native.c
@@ -483,3 +483,8 @@ int Z_FreeMemory(void)
return -1;
}
+unsigned int Z_ZoneSize(void)
+{
+ return 0;
+}
+
diff --git a/src/z_zone.c b/src/z_zone.c
index f0b8ad53..975f41e5 100644
--- a/src/z_zone.c
+++ b/src/z_zone.c
@@ -473,3 +473,8 @@ int Z_FreeMemory (void)
return free;
}
+unsigned int Z_ZoneSize(void)
+{
+ return mainzone->size;
+}
+
diff --git a/src/z_zone.h b/src/z_zone.h
index 44eb365b..a00630cf 100644
--- a/src/z_zone.h
+++ b/src/z_zone.h
@@ -67,7 +67,7 @@ void Z_FileDumpHeap (FILE *f);
void Z_CheckHeap (void);
void Z_ChangeTag2 (void *ptr, int tag, char *file, int line);
int Z_FreeMemory (void);
-
+unsigned int Z_ZoneSize(void);
//
// This is used to get the local FILE:LINE info from CPP