summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSimon Howard2010-02-06 03:14:20 +0000
committerSimon Howard2010-02-06 03:14:20 +0000
commitd9520b6415f8e373cf759f316094b986e57f0f5a (patch)
treed256f7d4f1941ec33ae3c956449c70349de7297d /src
parent57011e785808847273461aaf6d8ed1df76ff1db9 (diff)
parent52f81b4ef175358d1e1f7f9eecab2a1edb7f4b65 (diff)
downloadchocolate-doom-d9520b6415f8e373cf759f316094b986e57f0f5a.tar.gz
chocolate-doom-d9520b6415f8e373cf759f316094b986e57f0f5a.tar.bz2
chocolate-doom-d9520b6415f8e373cf759f316094b986e57f0f5a.zip
Merge from trunk.
Subversion-branch: /branches/strife-branch Subversion-revision: 1849
Diffstat (limited to 'src')
-rw-r--r--src/.gitignore2
-rw-r--r--src/Makefile.am24
-rw-r--r--src/d_iwad.c91
-rw-r--r--src/deh_defs.h (renamed from src/doom/deh_defs.h)0
-rw-r--r--src/deh_io.c (renamed from src/doom/deh_io.c)0
-rw-r--r--src/deh_io.h (renamed from src/doom/deh_io.h)0
-rw-r--r--src/deh_main.c (renamed from src/strife/deh_main.c)63
-rw-r--r--src/deh_main.h (renamed from src/doom/deh_main.h)0
-rw-r--r--src/deh_mapping.c (renamed from src/doom/deh_mapping.c)0
-rw-r--r--src/deh_mapping.h (renamed from src/doom/deh_mapping.h)0
-rw-r--r--src/deh_text.c (renamed from src/doom/deh_text.c)0
-rw-r--r--src/doom/.gitignore2
-rw-r--r--src/doom/Makefile.am6
-rw-r--r--src/doom/deh_doom.c74
-rw-r--r--src/doom/deh_main.c423
-rw-r--r--src/doom/g_game.c14
-rw-r--r--src/doom/hu_stuff.c30
-rw-r--r--src/doom/p_map.c21
-rw-r--r--src/doom/p_setup.c27
-rw-r--r--src/doom/p_sight.c10
-rw-r--r--src/doom/st_stuff.c18
-rw-r--r--src/i_video.c1
-rw-r--r--src/mus2mid.c1019
-rw-r--r--src/resource.rc.in2
-rw-r--r--src/setup/.gitignore7
-rw-r--r--src/setup/Makefile.am7
-rw-r--r--src/setup/execute.c33
-rw-r--r--src/strife/.gitignore2
-rw-r--r--src/strife/Makefile.am6
-rw-r--r--src/strife/deh_defs.h68
-rw-r--r--src/strife/deh_io.c211
-rw-r--r--src/strife/deh_io.h40
-rw-r--r--src/strife/deh_main.h54
-rw-r--r--src/strife/deh_mapping.c133
-rw-r--r--src/strife/deh_mapping.h90
-rw-r--r--src/strife/deh_strife.c74
-rw-r--r--src/strife/deh_text.c127
-rw-r--r--src/strife/g_game.c14
-rw-r--r--src/strife/hu_stuff.c30
-rw-r--r--src/strife/p_map.c21
-rw-r--r--src/strife/p_setup.c27
-rw-r--r--src/strife/p_sight.c10
-rw-r--r--src/strife/st_stuff.c18
43 files changed, 1013 insertions, 1786 deletions
diff --git a/src/.gitignore b/src/.gitignore
index d7e732ad..973a0073 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -5,3 +5,5 @@ Makefile.in
chocolate-doom
chocolate-server
*.exe
+tags
+TAGS
diff --git a/src/Makefile.am b/src/Makefile.am
index 82a7697f..51baa567 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -51,6 +51,7 @@ d_event.c d_event.h \
d_iwad.c d_iwad.h \
d_mode.c d_mode.h \
d_ticcmd.h \
+deh_str.c deh_str.h \
i_cdmus.c i_cdmus.h \
i_endoom.c i_endoom.h \
i_joystick.c i_joystick.h \
@@ -80,8 +81,12 @@ z_zone.c z_zone.h
# source files needed for FEATURE_DEHACKED
-FEATURE_DEHACKED_SOURCE_FILES= \
-deh_str.c deh_str.h
+FEATURE_DEHACKED_SOURCE_FILES = \
+deh_defs.h \
+deh_io.c deh_io.h \
+deh_main.c deh_main.h \
+deh_mapping.c deh_mapping.h \
+deh_text.c
# source files needed for FEATURE_MULTIPLAYER
@@ -112,12 +117,15 @@ i_sdlsound.c \
i_sdlmusic.c \
mus2mid.c mus2mid.h
+# Some games support dehacked patches, some don't:
+
SOURCE_FILES = $(COMMON_SOURCE_FILES) \
$(GAME_SOURCE_FILES) \
- $(FEATURE_DEHACKED_SOURCE_FILES) \
$(FEATURE_WAD_MERGE_SOURCE_FILES) \
$(FEATURE_SOUND_SOURCE_FILES)
+SOURCE_FILES_WITH_DEH = $(SOURCE_FILES) \
+ $(FEATURE_DEHACKED_SOURCE_FILES)
EXTRA_LIBS = \
$(top_builddir)/wince/libc_wince.a \
@@ -129,9 +137,9 @@ EXTRA_LIBS = \
@SDLNET_LIBS@
if HAVE_WINDRES
-@PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES) resource.rc
+@PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES_WITH_DEH) resource.rc
else
-@PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES)
+@PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES_WITH_DEH)
endif
@PROGRAM_PREFIX@doom_LDADD = doom/libdoom.a $(EXTRA_LIBS)
@@ -153,9 +161,9 @@ endif
@PROGRAM_PREFIX@hexen_LDADD = hexen/libhexen.a $(EXTRA_LIBS)
if HAVE_WINDRES
-@PROGRAM_PREFIX@strife_SOURCES=$(SOURCE_FILES) resource.rc
+@PROGRAM_PREFIX@strife_SOURCES=$(SOURCE_FILES_WITH_DEH) resource.rc
else
-@PROGRAM_PREFIX@strife_SOURCES=$(SOURCE_FILES)
+@PROGRAM_PREFIX@strife_SOURCES=$(SOURCE_FILES_WITH_DEH)
endif
@PROGRAM_PREFIX@strife_LDADD = strife/libstrife.a $(EXTRA_LIBS)
@@ -191,7 +199,7 @@ EXTRA_DIST = \
if HAVE_PYTHON
-icon.c : $(top_builddir)/data/doom.ico
+icon.c : $(top_builddir)/data/doom8.ico
$(top_builddir)/data/convert-icon $^ $@
endif
diff --git a/src/d_iwad.c b/src/d_iwad.c
index fe60866b..0e3220a8 100644
--- a/src/d_iwad.c
+++ b/src/d_iwad.c
@@ -331,44 +331,85 @@ static void CheckDOSDefaults(void)
#endif
+// Returns true if the specified path is a path to a file
+// of the specified name.
+
+static boolean DirIsFile(char *path, char *filename)
+{
+ size_t path_len;
+ size_t filename_len;
+
+ path_len = strlen(path);
+ filename_len = strlen(filename);
+
+ return path_len >= filename_len + 1
+ && path[path_len - filename_len - 1] == DIR_SEPARATOR
+ && !strcasecmp(&path[path_len - filename_len], filename);
+}
+
+// Check if the specified directory contains the specified IWAD
+// file, returning the full path to the IWAD if found, or NULL
+// if not found.
+
+static char *CheckDirectoryHasIWAD(char *dir, char *iwadname)
+{
+ char *filename;
+
+ // As a special case, the "directory" may refer directly to an
+ // IWAD file if the path comes from DOOMWADDIR or DOOMWADPATH.
+
+ if (DirIsFile(dir, iwadname) && M_FileExists(dir))
+ {
+ return strdup(dir);
+ }
+
+ // Construct the full path to the IWAD if it is located in
+ // this directory, and check if it exists.
+
+ filename = malloc(strlen(dir) + strlen(iwadname) + 3);
+
+ if (!strcmp(dir, "."))
+ {
+ strcpy(filename, iwadname);
+ }
+ else
+ {
+ sprintf(filename, "%s%c%s", dir, DIR_SEPARATOR, iwadname);
+ }
+
+ if (M_FileExists(filename))
+ {
+ return filename;
+ }
+
+ free(filename);
+
+ return NULL;
+}
+
// Search a directory to try to find an IWAD
// Returns the location of the IWAD if found, otherwise NULL.
static char *SearchDirectoryForIWAD(char *dir, int mask, GameMission_t *mission)
{
+ char *filename;
size_t i;
for (i=0; i<arrlen(iwads); ++i)
{
- char *filename;
- char *iwadname;
-
if (((1 << iwads[i].mission) & mask) == 0)
{
continue;
}
- iwadname = DEH_String(iwads[i].name);
-
- filename = malloc(strlen(dir) + strlen(iwadname) + 3);
-
- if (!strcmp(dir, "."))
- {
- strcpy(filename, iwadname);
- }
- else
- {
- sprintf(filename, "%s%c%s", dir, DIR_SEPARATOR, iwadname);
- }
+ filename = CheckDirectoryHasIWAD(dir, DEH_String(iwads[i].name));
- if (M_FileExists(filename))
+ if (filename != NULL)
{
*mission = iwads[i].mission;
return filename;
}
-
- free(filename);
}
return NULL;
@@ -529,7 +570,6 @@ char *D_FindWADByName(char *name)
{
char *buf;
int i;
- boolean exists;
// Absolute path?
@@ -544,14 +584,21 @@ char *D_FindWADByName(char *name)
for (i=0; i<num_iwad_dirs; ++i)
{
+ // As a special case, if this is in DOOMWADDIR or DOOMWADPATH,
+ // the "directory" may actually refer directly to an IWAD
+ // file.
+
+ if (DirIsFile(iwad_dirs[i], name) && M_FileExists(iwad_dirs[i]))
+ {
+ return strdup(iwad_dirs[i]);
+ }
+
// Construct a string for the full path
buf = malloc(strlen(iwad_dirs[i]) + strlen(name) + 5);
sprintf(buf, "%s%c%s", iwad_dirs[i], DIR_SEPARATOR, name);
- exists = M_FileExists(buf);
-
- if (exists)
+ if (M_FileExists(buf))
{
return buf;
}
diff --git a/src/doom/deh_defs.h b/src/deh_defs.h
index e7b76182..e7b76182 100644
--- a/src/doom/deh_defs.h
+++ b/src/deh_defs.h
diff --git a/src/doom/deh_io.c b/src/deh_io.c
index 3386a6fa..3386a6fa 100644
--- a/src/doom/deh_io.c
+++ b/src/deh_io.c
diff --git a/src/doom/deh_io.h b/src/deh_io.h
index 061a5a0e..061a5a0e 100644
--- a/src/doom/deh_io.h
+++ b/src/deh_io.h
diff --git a/src/strife/deh_main.c b/src/deh_main.c
index 63cae460..3f0a6f29 100644
--- a/src/strife/deh_main.c
+++ b/src/deh_main.c
@@ -36,30 +36,8 @@
#include "deh_defs.h"
#include "deh_io.h"
-static char *deh_signatures[] =
-{
- "Patch File for DeHackEd v2.3",
- "Patch File for DeHackEd v3.0",
-};
-
-// deh_ammo.c:
-extern deh_section_t deh_section_ammo;
-// deh_cheat.c:
-extern deh_section_t deh_section_cheat;
-// deh_frame.c:
-extern deh_section_t deh_section_frame;
-// deh_misc.c:
-extern deh_section_t deh_section_misc;
-// deh_ptr.c:
-extern deh_section_t deh_section_pointer;
-// deh_sound.c
-extern deh_section_t deh_section_sound;
-// deh_text.c:
-extern deh_section_t deh_section_text;
-// deh_thing.c:
-extern deh_section_t deh_section_thing;
-// deh_weapon.c:
-extern deh_section_t deh_section_weapon;
+extern deh_section_t *deh_section_types[];
+extern char *deh_signatures[];
// If true, we can do long string replacements.
@@ -73,23 +51,6 @@ boolean deh_allow_long_cheats = false;
boolean deh_apply_cheats = true;
-//
-// List of section types:
-//
-
-static deh_section_t *section_types[] =
-{
- &deh_section_ammo,
- &deh_section_cheat,
- &deh_section_frame,
- &deh_section_misc,
- &deh_section_pointer,
- &deh_section_sound,
- &deh_section_text,
- &deh_section_thing,
- &deh_section_weapon,
-};
-
void DEH_Checksum(md5_digest_t digest)
{
md5_context_t md5_context;
@@ -97,11 +58,11 @@ void DEH_Checksum(md5_digest_t digest)
MD5_Init(&md5_context);
- for (i=0; i<arrlen(section_types); ++i)
+ for (i=0; deh_section_types[i] != NULL; ++i)
{
- if (section_types[i]->md5_hash != NULL)
+ if (deh_section_types[i]->md5_hash != NULL)
{
- section_types[i]->md5_hash(&md5_context);
+ deh_section_types[i]->md5_hash(&md5_context);
}
}
@@ -114,11 +75,11 @@ static void InitializeSections(void)
{
unsigned int i;
- for (i=0; i<arrlen(section_types); ++i)
+ for (i=0; deh_section_types[i] != NULL; ++i)
{
- if (section_types[i]->init != NULL)
+ if (deh_section_types[i]->init != NULL)
{
- section_types[i]->init();
+ deh_section_types[i]->init();
}
}
}
@@ -129,11 +90,11 @@ static deh_section_t *GetSectionByName(char *name)
{
unsigned int i;
- for (i=0; i<arrlen(section_types); ++i)
+ for (i=0; deh_section_types[i] != NULL; ++i)
{
- if (!strcasecmp(section_types[i]->name, name))
+ if (!strcasecmp(deh_section_types[i]->name, name))
{
- return section_types[i];
+ return deh_section_types[i];
}
}
@@ -229,7 +190,7 @@ static boolean CheckSignatures(deh_context_t *context)
// Check all signatures to see if one matches
- for (i=0; i<arrlen(deh_signatures); ++i)
+ for (i=0; deh_signatures[i] != NULL; ++i)
{
if (!strcmp(deh_signatures[i], line))
{
diff --git a/src/doom/deh_main.h b/src/deh_main.h
index f9cb44ca..f9cb44ca 100644
--- a/src/doom/deh_main.h
+++ b/src/deh_main.h
diff --git a/src/doom/deh_mapping.c b/src/deh_mapping.c
index b215b128..b215b128 100644
--- a/src/doom/deh_mapping.c
+++ b/src/deh_mapping.c
diff --git a/src/doom/deh_mapping.h b/src/deh_mapping.h
index 4862dec9..4862dec9 100644
--- a/src/doom/deh_mapping.h
+++ b/src/deh_mapping.h
diff --git a/src/doom/deh_text.c b/src/deh_text.c
index 31e23db2..31e23db2 100644
--- a/src/doom/deh_text.c
+++ b/src/deh_text.c
diff --git a/src/doom/.gitignore b/src/doom/.gitignore
index d7e732ad..973a0073 100644
--- a/src/doom/.gitignore
+++ b/src/doom/.gitignore
@@ -5,3 +5,5 @@ Makefile.in
chocolate-doom
chocolate-server
*.exe
+tags
+TAGS
diff --git a/src/doom/Makefile.am b/src/doom/Makefile.am
index 7b7073b6..596e42eb 100644
--- a/src/doom/Makefile.am
+++ b/src/doom/Makefile.am
@@ -63,15 +63,11 @@ wi_stuff.c wi_stuff.h
FEATURE_DEHACKED_SOURCE_FILES = \
deh_ammo.c \
deh_cheat.c \
-deh_defs.h \
+deh_doom.c \
deh_frame.c \
-deh_io.c deh_io.h \
-deh_main.c deh_main.h \
-deh_mapping.c deh_mapping.h \
deh_misc.c deh_misc.h \
deh_ptr.c \
deh_sound.c \
-deh_text.c \
deh_thing.c \
deh_weapon.c
diff --git a/src/doom/deh_doom.c b/src/doom/deh_doom.c
new file mode 100644
index 00000000..7549e09e
--- /dev/null
+++ b/src/doom/deh_doom.c
@@ -0,0 +1,74 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Top-level dehacked definitions for Doom dehacked.
+//
+//-----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include "deh_defs.h"
+#include "deh_main.h"
+
+char *deh_signatures[] =
+{
+ "Patch File for DeHackEd v2.3",
+ "Patch File for DeHackEd v3.0",
+ NULL
+};
+
+// deh_ammo.c:
+extern deh_section_t deh_section_ammo;
+// deh_cheat.c:
+extern deh_section_t deh_section_cheat;
+// deh_frame.c:
+extern deh_section_t deh_section_frame;
+// deh_misc.c:
+extern deh_section_t deh_section_misc;
+// deh_ptr.c:
+extern deh_section_t deh_section_pointer;
+// deh_sound.c
+extern deh_section_t deh_section_sound;
+// deh_text.c:
+extern deh_section_t deh_section_text;
+// deh_thing.c:
+extern deh_section_t deh_section_thing;
+// deh_weapon.c:
+extern deh_section_t deh_section_weapon;
+
+//
+// List of section types:
+//
+
+deh_section_t *deh_section_types[] =
+{
+ &deh_section_ammo,
+ &deh_section_cheat,
+ &deh_section_frame,
+ &deh_section_misc,
+ &deh_section_pointer,
+ &deh_section_sound,
+ &deh_section_text,
+ &deh_section_thing,
+ &deh_section_weapon,
+ NULL
+};
+
diff --git a/src/doom/deh_main.c b/src/doom/deh_main.c
deleted file mode 100644
index 63cae460..00000000
--- a/src/doom/deh_main.c
+++ /dev/null
@@ -1,423 +0,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-//-----------------------------------------------------------------------------
-//
-// Main dehacked code
-//
-//-----------------------------------------------------------------------------
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "doomtype.h"
-#include "d_iwad.h"
-#include "m_argv.h"
-
-#include "deh_defs.h"
-#include "deh_io.h"
-
-static char *deh_signatures[] =
-{
- "Patch File for DeHackEd v2.3",
- "Patch File for DeHackEd v3.0",
-};
-
-// deh_ammo.c:
-extern deh_section_t deh_section_ammo;
-// deh_cheat.c:
-extern deh_section_t deh_section_cheat;
-// deh_frame.c:
-extern deh_section_t deh_section_frame;
-// deh_misc.c:
-extern deh_section_t deh_section_misc;
-// deh_ptr.c:
-extern deh_section_t deh_section_pointer;
-// deh_sound.c
-extern deh_section_t deh_section_sound;
-// deh_text.c:
-extern deh_section_t deh_section_text;
-// deh_thing.c:
-extern deh_section_t deh_section_thing;
-// deh_weapon.c:
-extern deh_section_t deh_section_weapon;
-
-// If true, we can do long string replacements.
-
-boolean deh_allow_long_strings = false;
-
-// If true, we can do cheat replacements longer than the originals.
-
-boolean deh_allow_long_cheats = false;
-
-// If false, dehacked cheat replacements are ignored.
-
-boolean deh_apply_cheats = true;
-
-//
-// List of section types:
-//
-
-static deh_section_t *section_types[] =
-{
- &deh_section_ammo,
- &deh_section_cheat,
- &deh_section_frame,
- &deh_section_misc,
- &deh_section_pointer,
- &deh_section_sound,
- &deh_section_text,
- &deh_section_thing,
- &deh_section_weapon,
-};
-
-void DEH_Checksum(md5_digest_t digest)
-{
- md5_context_t md5_context;
- unsigned int i;
-
- MD5_Init(&md5_context);
-
- for (i=0; i<arrlen(section_types); ++i)
- {
- if (section_types[i]->md5_hash != NULL)
- {
- section_types[i]->md5_hash(&md5_context);
- }
- }
-
- MD5_Final(digest, &md5_context);
-}
-
-// Called on startup to call the Init functions
-
-static void InitializeSections(void)
-{
- unsigned int i;
-
- for (i=0; i<arrlen(section_types); ++i)
- {
- if (section_types[i]->init != NULL)
- {
- section_types[i]->init();
- }
- }
-}
-
-// Given a section name, get the section structure which corresponds
-
-static deh_section_t *GetSectionByName(char *name)
-{
- unsigned int i;
-
- for (i=0; i<arrlen(section_types); ++i)
- {
- if (!strcasecmp(section_types[i]->name, name))
- {
- return section_types[i];
- }
- }
-
- return NULL;
-}
-
-// Is the string passed just whitespace?
-
-static boolean IsWhitespace(char *s)
-{
- for (; *s; ++s)
- {
- if (!isspace(*s))
- return false;
- }
-
- return true;
-}
-
-// Strip whitespace from the start and end of a string
-
-static char *CleanString(char *s)
-{
- char *strending;
-
- // Leading whitespace
-
- while (*s && isspace(*s))
- ++s;
-
- // Trailing whitespace
-
- strending = s + strlen(s) - 1;
-
- while (strlen(s) > 0 && isspace(*strending))
- {
- *strending = '\0';
- --strending;
- }
-
- return s;
-}
-
-// This pattern is used a lot of times in different sections,
-// an assignment is essentially just a statement of the form:
-//
-// Variable Name = Value
-//
-// The variable name can include spaces or any other characters.
-// The string is split on the '=', essentially.
-//
-// Returns true if read correctly
-
-boolean DEH_ParseAssignment(char *line, char **variable_name, char **value)
-{
- char *p;
-
- // find the equals
-
- p = strchr(line, '=');
-
- if (p == NULL && p-line > 2)
- {
- return false;
- }
-
- // variable name at the start
- // turn the '=' into a \0 to terminate the string here
-
- *p = '\0';
- *variable_name = CleanString(line);
-
- // value immediately follows the '='
-
- *value = CleanString(p+1);
-
- return true;
-}
-
-static boolean CheckSignatures(deh_context_t *context)
-{
- size_t i;
- char *line;
-
- // Read the first line
-
- line = DEH_ReadLine(context);
-
- if (line == NULL)
- {
- return false;
- }
-
- // Check all signatures to see if one matches
-
- for (i=0; i<arrlen(deh_signatures); ++i)
- {
- if (!strcmp(deh_signatures[i], line))
- {
- return true;
- }
- }
-
- return false;
-}
-
-// Parses a comment string in a dehacked file.
-
-static void DEH_ParseComment(char *comment)
-{
- // Allow comments containing this special value to allow string
- // replacements longer than those permitted by DOS dehacked.
- // This allows us to use a dehacked patch for doing string
- // replacements for emulating Chex Quest.
- //
- // If you use this, your dehacked patch may not work in Vanilla
- // Doom.
-
- if (strstr(comment, "*allow-long-strings*") != NULL)
- {
- deh_allow_long_strings = true;
- }
-
- // Allow magic comments to allow longer cheat replacements than
- // those permitted by DOS dehacked. This is also for Chex
- // Quest.
-
- if (strstr(comment, "*allow-long-cheats*") != NULL)
- {
- deh_allow_long_cheats = true;
- }
-}
-
-// Parses a dehacked file by reading from the context
-
-static void DEH_ParseContext(deh_context_t *context)
-{
- deh_section_t *current_section = NULL;
- char section_name[20];
- void *tag = NULL;
- char *line;
-
- // Read the header and check it matches the signature
-
- if (!CheckSignatures(context))
- {
- DEH_Error(context, "This is not a valid dehacked patch file!");
- }
-
- deh_allow_long_strings = false;
- deh_allow_long_cheats = false;
-
- // Read the file
-
- for (;;)
- {
- // read a new line
-
- line = DEH_ReadLine(context);
-
- // end of file?
-
- if (line == NULL)
- return;
-
- while (line[0] != '\0' && isspace(line[0]))
- ++line;
-
- if (line[0] == '#')
- {
- // comment
-
- DEH_ParseComment(line);
- continue;
- }
-
- if (IsWhitespace(line))
- {
- if (current_section != NULL)
- {
- // end of section
-
- if (current_section->end != NULL)
- {
- current_section->end(context, tag);
- }
-
- //printf("end %s tag\n", current_section->name);
- current_section = NULL;
- }
- }
- else
- {
- if (current_section != NULL)
- {
- // parse this line
-
- current_section->line_parser(context, line, tag);
- }
- else
- {
- // possibly the start of a new section
-
- sscanf(line, "%19s", section_name);
-
- current_section = GetSectionByName(section_name);
-
- if (current_section != NULL)
- {
- tag = current_section->start(context, line);
- //printf("started %s tag\n", section_name);
- }
- else
- {
- //printf("unknown section name %s\n", section_name);
- }
- }
- }
- }
-}
-
-// Parses a dehacked file
-
-int DEH_LoadFile(char *filename)
-{
- deh_context_t *context;
-
- printf(" loading %s\n", filename);
-
- context = DEH_OpenFile(filename);
-
- if (context == NULL)
- {
- fprintf(stderr, "DEH_LoadFile: Unable to open %s\n", filename);
- return 0;
- }
-
- DEH_ParseContext(context);
-
- DEH_CloseFile(context);
-
- return 1;
-}
-
-// Checks the command line for -deh argument
-
-void DEH_Init(void)
-{
- char *filename;
- int p;
-
- InitializeSections();
-
- //!
- // @category mod
- //
- // Ignore cheats in dehacked files.
- //
-
- if (M_CheckParm("-nocheats") > 0)
- {
- deh_apply_cheats = false;
- }
-
- //!
- // @arg <files>
- // @category mod
- //
- // Load the given dehacked patch(es)
- //
-
- p = M_CheckParm("-deh");
-
- if (p > 0)
- {
- ++p;
-
- while (p < myargc && myargv[p][0] != '-')
- {
- filename = D_TryFindWADByName(myargv[p]);
- DEH_LoadFile(filename);
- ++p;
- }
- }
-}
-
-
diff --git a/src/doom/g_game.c b/src/doom/g_game.c
index 35bf4d74..8d0e4503 100644
--- a/src/doom/g_game.c
+++ b/src/doom/g_game.c
@@ -588,10 +588,20 @@ void G_BuildTiccmd (ticcmd_t* cmd)
if (lowres_turn)
{
- // round angleturn to the nearest 256 boundary
+ static signed short carry = 0;
+ signed short desired_angleturn;
+
+ desired_angleturn = cmd->angleturn + carry;
+
+ // round angleturn to the nearest 256 unit boundary
// for recording demos with single byte values for turn
- cmd->angleturn = (cmd->angleturn + 128) & 0xff00;
+ cmd->angleturn = (desired_angleturn + 128) & 0xff00;
+
+ // Carry forward the error from the reduced resolution to the
+ // next tic, so that successive small movements can accumulate.
+
+ carry = desired_angleturn - cmd->angleturn;
}
}
diff --git a/src/doom/hu_stuff.c b/src/doom/hu_stuff.c
index a106978e..ca74ce92 100644
--- a/src/doom/hu_stuff.c
+++ b/src/doom/hu_stuff.c
@@ -52,9 +52,9 @@
// Locally used constants, shortcuts.
//
#define HU_TITLE (mapnames[(gameepisode-1)*9+gamemap-1])
-#define HU_TITLE2 (mapnames2[gamemap-1])
-#define HU_TITLEP (mapnamesp[gamemap-1])
-#define HU_TITLET (mapnamest[gamemap-1])
+#define HU_TITLE2 (mapnames_commercial[gamemap-1])
+#define HU_TITLEP (mapnames_commercial[gamemap-1 + 32])
+#define HU_TITLET (mapnames_commercial[gamemap-1 + 64])
#define HU_TITLE_CHEX (mapnames[gamemap - 1])
#define HU_TITLEHEIGHT 1
#define HU_TITLEX 0
@@ -171,8 +171,16 @@ char* mapnames[] = // DOOM shareware/registered/retail (Ultimate) names.
"NEWLEVEL"
};
-char* mapnames2[] = // DOOM 2 map names.
+// List of names for levels in commercial IWADs
+// (doom2.wad, plutonia.wad, tnt.wad). These are stored in a
+// single large array; WADs like pl2.wad have a MAP33, and rely on
+// the layout in the Vanilla executable, where it is possible to
+// overflow the end of one array into the next.
+
+char *mapnames_commercial[] =
{
+ // DOOM 2 map names.
+
HUSTR_1,
HUSTR_2,
HUSTR_3,
@@ -206,12 +214,10 @@ char* mapnames2[] = // DOOM 2 map names.
HUSTR_29,
HUSTR_30,
HUSTR_31,
- HUSTR_32
-};
+ HUSTR_32,
+ // Plutonia WAD map names.
-char* mapnamesp[] = // Plutonia WAD map names.
-{
PHUSTR_1,
PHUSTR_2,
PHUSTR_3,
@@ -245,12 +251,10 @@ char* mapnamesp[] = // Plutonia WAD map names.
PHUSTR_29,
PHUSTR_30,
PHUSTR_31,
- PHUSTR_32
-};
-
+ PHUSTR_32,
+
+ // TNT WAD map names.
-char *mapnamest[] = // TNT WAD map names.
-{
THUSTR_1,
THUSTR_2,
THUSTR_3,
diff --git a/src/doom/p_map.c b/src/doom/p_map.c
index 3f88aabc..925e4398 100644
--- a/src/doom/p_map.c
+++ b/src/doom/p_map.c
@@ -885,7 +885,17 @@ PTR_AimTraverse (intercept_t* in)
dist = FixedMul (attackrange, in->frac);
- if (li->frontsector->floorheight != li->backsector->floorheight)
+ // Return false if there is no back sector. This should never
+ // be the case if the line is two-sided; however, some WADs
+ // (eg. ottawau.wad) use this as an "impassible glass" trick
+ // and rely on Vanilla Doom's (unintentional) support for this.
+
+ if (li->backsector == NULL)
+ {
+ return false;
+ }
+
+ if (li->frontsector->floorheight != li->backsector->floorheight)
{
slope = FixedDiv (openbottom - shootz , dist);
if (slope > bottomslope)
@@ -973,7 +983,14 @@ boolean PTR_ShootTraverse (intercept_t* in)
dist = FixedMul (attackrange, in->frac);
- if (li->frontsector->floorheight != li->backsector->floorheight)
+ // Check if backsector is NULL. See comment in PTR_AimTraverse.
+
+ if (li->backsector == NULL)
+ {
+ goto hitline;
+ }
+
+ if (li->frontsector->floorheight != li->backsector->floorheight)
{
slope = FixedDiv (openbottom - shootz , dist);
if (slope > aimslope)
diff --git a/src/doom/p_setup.c b/src/doom/p_setup.c
index 5cf7a628..2a3a8f85 100644
--- a/src/doom/p_setup.c
+++ b/src/doom/p_setup.c
@@ -167,6 +167,7 @@ void P_LoadSegs (int lump)
line_t* ldef;
int linedef;
int side;
+ int sidenum;
numsegs = W_LumpLength (lump) / sizeof(mapseg_t);
segs = Z_Malloc (numsegs*sizeof(seg_t),PU_LEVEL,0);
@@ -179,7 +180,7 @@ void P_LoadSegs (int lump)
{
li->v1 = &vertexes[SHORT(ml->v1)];
li->v2 = &vertexes[SHORT(ml->v2)];
-
+
li->angle = (SHORT(ml->angle))<<16;
li->offset = (SHORT(ml->offset))<<16;
linedef = SHORT(ml->linedef);
@@ -188,10 +189,28 @@ void P_LoadSegs (int lump)
side = SHORT(ml->side);
li->sidedef = &sides[ldef->sidenum[side]];
li->frontsector = sides[ldef->sidenum[side]].sector;
- if (ldef-> flags & ML_TWOSIDED)
- li->backsector = sides[ldef->sidenum[side^1]].sector;
- else
+
+ if (ldef-> flags & ML_TWOSIDED)
+ {
+ sidenum = ldef->sidenum[side ^ 1];
+
+ // If the sidenum is out of range, this may be a "glass hack"
+ // impassible window. Point at side #0 (this may not be
+ // the correct Vanilla behavior; however, it seems to work for
+ // OTTAWAU.WAD, which is the one place I've seen this trick
+ // used).
+
+ if (sidenum < 0 || sidenum >= numsides)
+ {
+ sidenum = 0;
+ }
+
+ li->backsector = sides[sidenum].sector;
+ }
+ else
+ {
li->backsector = 0;
+ }
}
W_ReleaseLumpNum(lump);
diff --git a/src/doom/p_sight.c b/src/doom/p_sight.c
index e192567b..79c1bb1d 100644
--- a/src/doom/p_sight.c
+++ b/src/doom/p_sight.c
@@ -173,7 +173,7 @@ boolean P_CrossSubsector (int num)
continue;
line->validcount = validcount;
-
+
v1 = line->v1;
v2 = line->v2;
s1 = P_DivlineSide (v1->x,v1->y, &strace);
@@ -194,6 +194,14 @@ boolean P_CrossSubsector (int num)
if (s1 == s2)
continue;
+ // Backsector may be NULL if this is an "impassible
+ // glass" hack line.
+
+ if (line->backsector == NULL)
+ {
+ return false;
+ }
+
// stop because it is not two sided anyway
// might do this after updating validcount?
if ( !(line->flags & ML_TWOSIDED) )
diff --git a/src/doom/st_stuff.c b/src/doom/st_stuff.c
index e6ef0828..160244ce 100644
--- a/src/doom/st_stuff.c
+++ b/src/doom/st_stuff.c
@@ -260,9 +260,6 @@
// Height, in lines.
#define ST_OUTHEIGHT 1
-#define ST_MAPWIDTH \
- (strlen(mapnames[(gameepisode-1)*9+(gamemap-1)]))
-
#define ST_MAPTITLEX \
(SCREENWIDTH - ST_MAPWIDTH * ST_CHATFONTWIDTH)
@@ -418,10 +415,6 @@ cheatseq_t cheat_clev = CHEAT("idclev", 2);
cheatseq_t cheat_mypos = CHEAT("idmypos", 0);
-//
-extern char* mapnames[];
-
-
//
// STATUS BAR CODE
//
@@ -985,6 +978,17 @@ void ST_doPaletteStuff(void)
else
palette = 0;
+ // In Chex Quest, the player never sees red. Instead, the
+ // radiation suit palette is used to tint the screen green,
+ // as though the player is being covered in goo by an
+ // attacking flemoid.
+
+ if (gameversion == exe_chex
+ && palette >= STARTREDPALS && palette < STARTREDPALS + NUMREDPALS)
+ {
+ palette = RADIATIONPAL;
+ }
+
if (palette != st_palette)
{
st_palette = palette;
diff --git a/src/i_video.c b/src/i_video.c
index 64a2e8eb..a370fc08 100644
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -503,6 +503,7 @@ void I_ShutdownGraphics(void)
{
if (initialized)
{
+ SDL_SetCursor(cursors[1]);
SDL_ShowCursor(1);
SDL_WM_GrabInput(SDL_GRAB_OFF);
diff --git a/src/mus2mid.c b/src/mus2mid.c
index 8ba1a5ff..88d24c97 100644
--- a/src/mus2mid.c
+++ b/src/mus2mid.c
@@ -1,4 +1,4 @@
-// Emacs style mode select -*- C++ -*-
+// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// Copyright(C) 1993-1996 Id Software, Inc.
@@ -31,594 +31,663 @@
#include "memio.h"
#include "mus2mid.h"
+#define NUM_CHANNELS 16
+
+#define MIDI_PERCUSSION_CHAN 9
+#define MUS_PERCUSSION_CHAN 15
+
// MUS event codes
-typedef enum
+typedef enum
{
- mus_releasekey = 0x00,
- mus_presskey = 0x10,
- mus_pitchwheel = 0x20,
- mus_systemevent = 0x30,
- mus_changecontroller = 0x40,
- mus_scoreend = 0x60
+ mus_releasekey = 0x00,
+ mus_presskey = 0x10,
+ mus_pitchwheel = 0x20,
+ mus_systemevent = 0x30,
+ mus_changecontroller = 0x40,
+ mus_scoreend = 0x60
} musevent;
// MIDI event codes
-typedef enum
+typedef enum
{
- midi_releasekey = 0x80,
- midi_presskey = 0x90,
- midi_aftertouchkey = 0xA0,
- midi_changecontroller = 0xB0,
- midi_changepatch = 0xC0,
- midi_aftertouchchannel = 0xD0,
- midi_pitchwheel = 0xE0
+ midi_releasekey = 0x80,
+ midi_presskey = 0x90,
+ midi_aftertouchkey = 0xA0,
+ midi_changecontroller = 0xB0,
+ midi_changepatch = 0xC0,
+ midi_aftertouchchannel = 0xD0,
+ midi_pitchwheel = 0xE0
} midievent;
-
// Structure to hold MUS file header
-typedef struct
+typedef struct
{
- byte id[4];
- unsigned short scorelength;
- unsigned short scorestart;
- unsigned short primarychannels;
- unsigned short secondarychannels;
- unsigned short instrumentcount;
+ byte id[4];
+ unsigned short scorelength;
+ unsigned short scorestart;
+ unsigned short primarychannels;
+ unsigned short secondarychannels;
+ unsigned short instrumentcount;
} PACKEDATTR musheader;
// Standard MIDI type 0 header + track header
-static byte midiheader[] =
+static const byte midiheader[] =
{
- 'M', 'T', 'h', 'd', // Main header
- 0x00, 0x00, 0x00, 0x06, // Header size
- 0x00, 0x00, // MIDI type (0)
- 0x00, 0x01, // Number of tracks
- 0x00, 0x46, // Resolution
- 'M', 'T', 'r', 'k', // Start of track
- 0x00, 0x00, 0x00, 0x00 // Placeholder for track length
+ 'M', 'T', 'h', 'd', // Main header
+ 0x00, 0x00, 0x00, 0x06, // Header size
+ 0x00, 0x00, // MIDI type (0)
+ 0x00, 0x01, // Number of tracks
+ 0x00, 0x46, // Resolution
+ 'M', 'T', 'r', 'k', // Start of track
+ 0x00, 0x00, 0x00, 0x00 // Placeholder for track length
};
// Cached channel velocities
-static byte channelvelocities[] =
-{
- 127, 127, 127, 127, 127, 127, 127, 127,
- 127, 127, 127, 127, 127, 127, 127, 127
+static byte channelvelocities[] =
+{
+ 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127
};
// Timestamps between sequences of MUS events
-static unsigned int queuedtime = 0;
+static unsigned int queuedtime = 0;
// Counter for the length of the track
static unsigned int tracksize;
-static byte mus2midi_translation[] =
-{
- 0x00, 0x20, 0x01, 0x07, 0x0A, 0x0B, 0x5B, 0x5D,
- 0x40, 0x43, 0x78, 0x7B, 0x7E, 0x7F, 0x79
+static const byte controller_map[] =
+{
+ 0x00, 0x20, 0x01, 0x07, 0x0A, 0x0B, 0x5B, 0x5D,
+ 0x40, 0x43, 0x78, 0x7B, 0x7E, 0x7F, 0x79
};
+static int channel_map[NUM_CHANNELS];
+
// Write timestamp to a MIDI file.
-static boolean midi_writetime(unsigned int time, MEMFILE *midioutput)
+static boolean WriteTime(unsigned int time, MEMFILE *midioutput)
{
- unsigned int buffer = time & 0x7F;
- byte writeval;
-
- while ((time >>= 7) != 0)
- {
- buffer <<= 8;
- buffer |= ((time & 0x7F) | 0x80);
- }
-
- for (;;)
- {
- writeval = (byte)(buffer & 0xFF);
-
- if (mem_fwrite(&writeval, 1, 1, midioutput) != 1)
- {
- return true;
- }
-
- ++tracksize;
-
- if ((buffer & 0x80) != 0)
- {
- buffer >>= 8;
- }
- else
- {
- queuedtime = 0;
- return false;
- }
- }
+ unsigned int buffer = time & 0x7F;
+ byte writeval;
+
+ while ((time >>= 7) != 0)
+ {
+ buffer <<= 8;
+ buffer |= ((time & 0x7F) | 0x80);
+ }
+
+ for (;;)
+ {
+ writeval = (byte)(buffer & 0xFF);
+
+ if (mem_fwrite(&writeval, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
+
+ ++tracksize;
+
+ if ((buffer & 0x80) != 0)
+ {
+ buffer >>= 8;
+ }
+ else
+ {
+ queuedtime = 0;
+ return false;
+ }
+ }
}
// Write the end of track marker
-static boolean midi_writeendtrack(MEMFILE *midioutput)
+static boolean WriteEndTrack(MEMFILE *midioutput)
{
- byte endtrack[] = {0xFF, 0x2F, 0x00};
+ byte endtrack[] = {0xFF, 0x2F, 0x00};
- if (midi_writetime(queuedtime, midioutput))
- {
- return true;
- }
+ if (WriteTime(queuedtime, midioutput))
+ {
+ return true;
+ }
- if (mem_fwrite(endtrack, 1, 3, midioutput) != 3)
- {
- return true;
- }
+ if (mem_fwrite(endtrack, 1, 3, midioutput) != 3)
+ {
+ return true;
+ }
- tracksize += 3;
- return false;
+ tracksize += 3;
+ return false;
}
// Write a key press event
-static boolean midi_writepresskey(byte channel, byte key,
- byte velocity, MEMFILE *midioutput)
+static boolean WritePressKey(byte channel, byte key,
+ byte velocity, MEMFILE *midioutput)
{
- byte working = midi_presskey | channel;
-
- if (midi_writetime(queuedtime, midioutput))
- {
- return true;
- }
-
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
-
- working = key & 0x7F;
-
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
-
- working = velocity & 0x7F;
-
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
-
- tracksize += 3;
-
- return false;
+ byte working = midi_presskey | channel;
+
+ if (WriteTime(queuedtime, midioutput))
+ {
+ return true;
+ }
+
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
+
+ working = key & 0x7F;
+
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
+
+ working = velocity & 0x7F;
+
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
+
+ tracksize += 3;
+
+ return false;
}
// Write a key release event
-static boolean midi_writereleasekey(byte channel, byte key,
- MEMFILE *midioutput)
+static boolean WriteReleaseKey(byte channel, byte key,
+ MEMFILE *midioutput)
{
- byte working = midi_releasekey | channel;
+ byte working = midi_releasekey | channel;
- if (midi_writetime(queuedtime, midioutput))
- {
- return true;
- }
+ if (WriteTime(queuedtime, midioutput))
+ {
+ return true;
+ }
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- working = key & 0x7F;
+ working = key & 0x7F;
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- working = 0;
+ working = 0;
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- tracksize += 3;
+ tracksize += 3;
- return false;
+ return false;
}
// Write a pitch wheel/bend event
-static boolean midi_writepitchwheel(byte channel, short wheel,
- MEMFILE *midioutput)
+static boolean WritePitchWheel(byte channel, short wheel,
+ MEMFILE *midioutput)
{
- byte working = midi_pitchwheel | channel;
+ byte working = midi_pitchwheel | channel;
- if (midi_writetime(queuedtime, midioutput))
- {
- return true;
- }
+ if (WriteTime(queuedtime, midioutput))
+ {
+ return true;
+ }
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- working = wheel & 0x7F;
+ working = wheel & 0x7F;
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- working = (wheel >> 7) & 0x7F;
+ working = (wheel >> 7) & 0x7F;
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- tracksize += 3;
- return false;
+ tracksize += 3;
+ return false;
}
// Write a patch change event
-static boolean midi_writechangepatch(byte channel, byte patch,
- MEMFILE *midioutput)
+static boolean WriteChangePatch(byte channel, byte patch,
+ MEMFILE *midioutput)
{
- byte working = midi_changepatch | channel;
-
- if (midi_writetime(queuedtime, midioutput))
- {
- return true;
- }
+ byte working = midi_changepatch | channel;
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (WriteTime(queuedtime, midioutput))
+ {
+ return true;
+ }
- working = patch & 0x7F;
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ working = patch & 0x7F;
- tracksize += 2;
-
- return false;
-}
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
+ tracksize += 2;
+ return false;
+}
// Write a valued controller change event
-static boolean midi_writechangecontroller_valued(byte channel,
- byte control,
- byte value,
- MEMFILE *midioutput)
+
+static boolean WriteChangeController_Valued(byte channel,
+ byte control,
+ byte value,
+ MEMFILE *midioutput)
{
- byte working = midi_changecontroller | channel;
+ byte working = midi_changecontroller | channel;
+
+ if (WriteTime(queuedtime, midioutput))
+ {
+ return true;
+ }
- if (midi_writetime(queuedtime, midioutput))
- {
- return true;
- }
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ working = control & 0x7F;
- working = control & 0x7F;
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
- // Quirk in vanilla DOOM? MUS controller values should be
- // 7-bit, not 8-bit.
+ // Quirk in vanilla DOOM? MUS controller values should be
+ // 7-bit, not 8-bit.
- working = value;// & 0x7F;
+ working = value;// & 0x7F;
- // Fix on said quirk to stop MIDI players from complaining that
- // the value is out of range:
+ // Fix on said quirk to stop MIDI players from complaining that
+ // the value is out of range:
- if (working & 0x80)
- {
- working = 0x7F;
- }
+ if (working & 0x80)
+ {
+ working = 0x7F;
+ }
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- tracksize += 3;
+ tracksize += 3;
- return false;
+ return false;
}
// Write a valueless controller change event
-static boolean midi_writechangecontroller_valueless(byte channel,
- byte control,
- MEMFILE *midioutput)
+static boolean WriteChangeController_Valueless(byte channel,
+ byte control,
+ MEMFILE *midioutput)
{
- return midi_writechangecontroller_valued(channel, control, 0,
- midioutput);
+ return WriteChangeController_Valued(channel, control, 0,
+ midioutput);
}
-static boolean read_musheader(MEMFILE *file, musheader *header)
+// Allocate a free MIDI channel.
+
+static int AllocateMIDIChannel(void)
{
- boolean result;
-
- result = (mem_fread(&header->id, sizeof(byte), 4, file) == 4)
- && (mem_fread(&header->scorelength, sizeof(short), 1, file) == 1)
- && (mem_fread(&header->scorestart, sizeof(short), 1, file) == 1)
- && (mem_fread(&header->primarychannels, sizeof(short), 1, file) == 1)
- && (mem_fread(&header->secondarychannels, sizeof(short), 1, file) == 1)
- && (mem_fread(&header->instrumentcount, sizeof(short), 1, file) == 1);
-
- if (result)
- {
- header->scorelength = SHORT(header->scorelength);
- header->scorestart = SHORT(header->scorestart);
- header->primarychannels = SHORT(header->primarychannels);
- header->secondarychannels = SHORT(header->secondarychannels);
- header->instrumentcount = SHORT(header->instrumentcount);
- }
-
- return result;
+ int result;
+ int max;
+ int i;
+
+ // Find the current highest-allocated channel.
+
+ max = -1;
+
+ for (i=0; i<NUM_CHANNELS; ++i)
+ {
+ if (channel_map[i] > max)
+ {
+ max = channel_map[i];
+ }
+ }
+
+ // max is now equal to the highest-allocated MIDI channel. We can
+ // now allocate the next available channel. This also works if
+ // no channels are currently allocated (max=-1)
+
+ result = max + 1;
+
+ // Don't allocate the MIDI percussion channel!
+
+ if (result == MIDI_PERCUSSION_CHAN)
+ {
+ ++result;
+ }
+
+ return result;
}
+// Given a MUS channel number, get the MIDI channel number to use
+// in the outputted file.
-// Read a MUS file from a stream (musinput) and output a MIDI file to
+static int GetMIDIChannel(int mus_channel)
+{
+ // Find the MIDI channel to use for this MUS channel.
+ // MUS channel 15 is the percusssion channel.
+
+ if (mus_channel == MUS_PERCUSSION_CHAN)
+ {
+ return MIDI_PERCUSSION_CHAN;
+ }
+ else
+ {
+ // If a MIDI channel hasn't been allocated for this MUS channel
+ // yet, allocate the next free MIDI channel.
+
+ if (channel_map[mus_channel] == -1)
+ {
+ channel_map[mus_channel] = AllocateMIDIChannel();
+ }
+
+ return channel_map[mus_channel];
+ }
+}
+
+static boolean ReadMusHeader(MEMFILE *file, musheader *header)
+{
+ boolean result;
+
+ result = mem_fread(&header->id, sizeof(byte), 4, file) == 4
+ && mem_fread(&header->scorelength, sizeof(short), 1, file) == 1
+ && mem_fread(&header->scorestart, sizeof(short), 1, file) == 1
+ && mem_fread(&header->primarychannels, sizeof(short), 1, file) == 1
+ && mem_fread(&header->secondarychannels, sizeof(short), 1, file) == 1
+ && mem_fread(&header->instrumentcount, sizeof(short), 1, file) == 1;
+
+ if (result)
+ {
+ header->scorelength = SHORT(header->scorelength);
+ header->scorestart = SHORT(header->scorestart);
+ header->primarychannels = SHORT(header->primarychannels);
+ header->secondarychannels = SHORT(header->secondarychannels);
+ header->instrumentcount = SHORT(header->instrumentcount);
+ }
+
+ return result;
+}
+
+
+// Read a MUS file from a stream (musinput) and output a MIDI file to
// a stream (midioutput).
//
// Returns 0 on success or 1 on failure.
-boolean mus2mid(MEMFILE *musinput, MEMFILE *midioutput)
+boolean mus2mid(MEMFILE *musinput, MEMFILE *midioutput)
{
- // Header for the MUS file
- musheader musfileheader;
+ // Header for the MUS file
+ musheader musfileheader;
+
+ // Descriptor for the current MUS event
+ byte eventdescriptor;
+ int channel; // Channel number
+ musevent event;
+
+
+ // Bunch of vars read from MUS lump
+ byte key;
+ byte controllernumber;
+ byte controllervalue;
- // Descriptor for the current MUS event
- byte eventdescriptor;
- int channel; // Channel number
- musevent event;
-
+ // Buffer used for MIDI track size record
+ byte tracksizebuffer[4];
- // Bunch of vars read from MUS lump
- byte key;
- byte controllernumber;
- byte controllervalue;
+ // Flag for when the score end marker is hit.
+ int hitscoreend = 0;
- // Buffer used for MIDI track size record
- byte tracksizebuffer[4];
+ // Temp working byte
+ byte working;
+ // Used in building up time delays
+ unsigned int timedelay;
- // Flag for when the score end marker is hit.
- int hitscoreend = 0;
+ // Initialise channel map to mark all channels as unused.
- // Temp working byte
- byte working;
- // Used in building up time delays
- unsigned int timedelay;
+ for (channel=0; channel<NUM_CHANNELS; ++channel)
+ {
+ channel_map[channel] = -1;
+ }
- // Grab the header
+ // Grab the header
- if (!read_musheader(musinput, &musfileheader))
- {
- return true;
- }
+ if (!ReadMusHeader(musinput, &musfileheader))
+ {
+ return true;
+ }
#ifdef CHECK_MUS_HEADER
- // Check MUS header
- if (musfileheader.id[0] != 'M'
- || musfileheader.id[1] != 'U'
- || musfileheader.id[2] != 'S'
- || musfileheader.id[3] != 0x1A)
- {
- return true;
- }
+ // Check MUS header
+ if (musfileheader.id[0] != 'M'
+ || musfileheader.id[1] != 'U'
+ || musfileheader.id[2] != 'S'
+ || musfileheader.id[3] != 0x1A)
+ {
+ return true;
+ }
#endif
- // Seek to where the data is held
- if (mem_fseek(musinput, (long)musfileheader.scorestart,
- MEM_SEEK_SET) != 0)
- {
- return true;
- }
-
- // So, we can assume the MUS file is faintly legit. Let's start
- // writing MIDI data...
-
- mem_fwrite(midiheader, 1, sizeof(midiheader), midioutput);
- tracksize = 0;
-
- // Now, process the MUS file:
- while (!hitscoreend)
- {
- // Handle a block of events:
-
- while (!hitscoreend)
- {
- // Fetch channel number and event code:
-
- if (mem_fread(&eventdescriptor, 1, 1, musinput) != 1)
- {
- return true;
- }
-
- channel = eventdescriptor & 0x0F;
- event = eventdescriptor & 0x70;
-
- // Swap channels 15 and 9.
- // MIDI channel 9 = percussion.
- // MUS channel 15 = percussion.
-
- if (channel == 15)
- {
- channel = 9;
- }
- else if (channel == 9)
- {
- channel = 15;
- }
-
- switch (event)
- {
- case mus_releasekey:
- if (mem_fread(&key, 1, 1, musinput) != 1)
- {
- return true;
- }
-
- if (midi_writereleasekey(channel, key, midioutput))
- {
- return true;
- }
-
- break;
-
- case mus_presskey:
- if (mem_fread(&key, 1, 1, musinput) != 1)
- {
- return true;
- }
-
- if (key & 0x80)
- {
- if (mem_fread(&channelvelocities[channel], 1, 1, musinput) != 1)
- {
- return true;
- }
-
- channelvelocities[channel] &= 0x7F;
- }
-
- if (midi_writepresskey(channel, key, channelvelocities[channel], midioutput))
- {
- return true;
- }
-
- break;
-
- case mus_pitchwheel:
- if (mem_fread(&key, 1, 1, musinput) != 1)
- {
- break;
- }
- if (midi_writepitchwheel(channel, (short)(key * 64), midioutput))
- {
- return true;
- }
-
- break;
-
- case mus_systemevent:
- if (mem_fread(&controllernumber, 1, 1, musinput) != 1)
- {
- return true;
- }
- if (controllernumber < 10 || controllernumber > 14)
- {
- return true;
- }
-
- if (midi_writechangecontroller_valueless(channel, mus2midi_translation[controllernumber], midioutput))
- {
- return true;
- }
-
- break;
-
- case mus_changecontroller:
- if (mem_fread(&controllernumber, 1, 1, musinput) != 1)
- {
- return true;
- }
-
- if (mem_fread(&controllervalue, 1, 1, musinput) != 1)
- {
- return true;
- }
-
- if (controllernumber == 0)
- {
- if (midi_writechangepatch(channel, controllervalue, midioutput))
- {
- return true;
- }
- }
- else
- {
- if (controllernumber < 1 || controllernumber > 9)
- {
- return true;
- }
-
- if (midi_writechangecontroller_valued(channel, mus2midi_translation[controllernumber], controllervalue, midioutput))
- {
- return true;
- }
- }
-
- break;
-
- case mus_scoreend:
- hitscoreend = 1;
- break;
-
- default:
- return true;
- break;
- }
-
- if (eventdescriptor & 0x80)
- {
- break;
- }
- }
- // Now we need to read the time code:
- if (!hitscoreend)
- {
- timedelay = 0;
- for (;;)
- {
- if (mem_fread(&working, 1, 1, musinput) != 1)
- {
- return true;
- }
-
- timedelay = timedelay * 128 + (working & 0x7F);
- if ((working & 0x80) == 0)
- {
- break;
- }
- }
- queuedtime += timedelay;
- }
- }
-
- // End of track
- if (midi_writeendtrack(midioutput))
- {
- return true;
- }
-
- // Write the track size into the stream
- if (mem_fseek(midioutput, 18, MEM_SEEK_SET))
- {
- return true;
- }
-
- tracksizebuffer[0] = (tracksize >> 24) & 0xff;
- tracksizebuffer[1] = (tracksize >> 16) & 0xff;
- tracksizebuffer[2] = (tracksize >> 8) & 0xff;
- tracksizebuffer[3] = tracksize & 0xff;
-
- if (mem_fwrite(tracksizebuffer, 1, 4, midioutput) != 4)
- {
- return true;
- }
-
- return false;
+ // Seek to where the data is held
+ if (mem_fseek(musinput, (long)musfileheader.scorestart,
+ MEM_SEEK_SET) != 0)
+ {
+ return true;
+ }
+
+ // So, we can assume the MUS file is faintly legit. Let's start
+ // writing MIDI data...
+
+ mem_fwrite(midiheader, 1, sizeof(midiheader), midioutput);
+ tracksize = 0;
+
+ // Now, process the MUS file:
+ while (!hitscoreend)
+ {
+ // Handle a block of events:
+
+ while (!hitscoreend)
+ {
+ // Fetch channel number and event code:
+
+ if (mem_fread(&eventdescriptor, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
+
+ channel = GetMIDIChannel(eventdescriptor & 0x0F);
+ event = eventdescriptor & 0x70;
+
+ switch (event)
+ {
+ case mus_releasekey:
+ if (mem_fread(&key, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
+
+ if (WriteReleaseKey(channel, key, midioutput))
+ {
+ return true;
+ }
+
+ break;
+
+ case mus_presskey:
+ if (mem_fread(&key, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
+
+ if (key & 0x80)
+ {
+ if (mem_fread(&channelvelocities[channel], 1, 1, musinput) != 1)
+ {
+ return true;
+ }
+
+ channelvelocities[channel] &= 0x7F;
+ }
+
+ if (WritePressKey(channel, key,
+ channelvelocities[channel], midioutput))
+ {
+ return true;
+ }
+
+ break;
+
+ case mus_pitchwheel:
+ if (mem_fread(&key, 1, 1, musinput) != 1)
+ {
+ break;
+ }
+ if (WritePitchWheel(channel, (short)(key * 64), midioutput))
+ {
+ return true;
+ }
+
+ break;
+
+ case mus_systemevent:
+ if (mem_fread(&controllernumber, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
+ if (controllernumber < 10 || controllernumber > 14)
+ {
+ return true;
+ }
+
+ if (WriteChangeController_Valueless(channel,
+ controller_map[controllernumber],
+ midioutput))
+ {
+ return true;
+ }
+
+ break;
+
+ case mus_changecontroller:
+ if (mem_fread(&controllernumber, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
+
+ if (mem_fread(&controllervalue, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
+
+ if (controllernumber == 0)
+ {
+ if (WriteChangePatch(channel, controllervalue,
+ midioutput))
+ {
+ return true;
+ }
+ }
+ else
+ {
+ if (controllernumber < 1 || controllernumber > 9)
+ {
+ return true;
+ }
+
+ if (WriteChangeController_Valued(channel,
+ controller_map[controllernumber],
+ controllervalue,
+ midioutput))
+ {
+ return true;
+ }
+ }
+
+ break;
+
+ case mus_scoreend:
+ hitscoreend = 1;
+ break;
+
+ default:
+ return true;
+ break;
+ }
+
+ if (eventdescriptor & 0x80)
+ {
+ break;
+ }
+ }
+ // Now we need to read the time code:
+ if (!hitscoreend)
+ {
+ timedelay = 0;
+ for (;;)
+ {
+ if (mem_fread(&working, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
+
+ timedelay = timedelay * 128 + (working & 0x7F);
+ if ((working & 0x80) == 0)
+ {
+ break;
+ }
+ }
+ queuedtime += timedelay;
+ }
+ }
+
+ // End of track
+ if (WriteEndTrack(midioutput))
+ {
+ return true;
+ }
+
+ // Write the track size into the stream
+ if (mem_fseek(midioutput, 18, MEM_SEEK_SET))
+ {
+ return true;
+ }
+
+ tracksizebuffer[0] = (tracksize >> 24) & 0xff;
+ tracksizebuffer[1] = (tracksize >> 16) & 0xff;
+ tracksizebuffer[2] = (tracksize >> 8) & 0xff;
+ tracksizebuffer[3] = tracksize & 0xff;
+
+ if (mem_fwrite(tracksizebuffer, 1, 4, midioutput) != 4)
+ {
+ return true;
+ }
+
+ return false;
}
diff --git a/src/resource.rc.in b/src/resource.rc.in
index 7eb5d00f..f8b64331 100644
--- a/src/resource.rc.in
+++ b/src/resource.rc.in
@@ -13,7 +13,7 @@ FILETYPE 1
VALUE "FileDescription", "@PACKAGE_STRING@"
VALUE "InternalName", "@PACKAGE_TARNAME@"
VALUE "CompanyName", "@PACKAGE_BUGREPORT@"
- VALUE "LegalCopyright", "GNU General Public License"
+ VALUE "LegalCopyright", "@PACKAGE_COPYRIGHT@. Licensed under @PACKAGE_LICENSE@"
VALUE "ProductName", "@PACKAGE_NAME@"
VALUE "ProductVersion", "@PACKAGE_VERSION@"
}
diff --git a/src/setup/.gitignore b/src/setup/.gitignore
index d7e732ad..37c8e4c1 100644
--- a/src/setup/.gitignore
+++ b/src/setup/.gitignore
@@ -1,7 +1,8 @@
-Makefile
Makefile.in
+Makefile
.deps
+chocolate-setup
*.rc
-chocolate-doom
-chocolate-server
*.exe
+tags
+TAGS
diff --git a/src/setup/Makefile.am b/src/setup/Makefile.am
index 07d7c936..25ab38e3 100644
--- a/src/setup/Makefile.am
+++ b/src/setup/Makefile.am
@@ -27,3 +27,10 @@ libsetup_a_SOURCES = $(SOURCE_FILES)
EXTRA_DIST= \
setup_icon.c
+if HAVE_PYTHON
+
+setup_icon.c : $(top_builddir)/data/setup8.ico
+ $(top_builddir)/data/convert-icon $^ $@
+
+endif
+
diff --git a/src/setup/execute.c b/src/setup/execute.c
index be7214f5..4be44149 100644
--- a/src/setup/execute.c
+++ b/src/setup/execute.c
@@ -172,29 +172,38 @@ static void ConcatWCString(wchar_t *buf, const char *value)
static wchar_t *BuildCommandLine(const char *program, const char *arg)
{
+ wchar_t exe_path[MAX_PATH];
wchar_t *result;
- char *sep;
+ wchar_t *sep;
+
+ // Get the path to this .exe file.
+
+ GetModuleFileNameW(NULL, exe_path, MAX_PATH);
- result = calloc(strlen(myargv[0]) + strlen(program) + strlen(arg) + 6,
+ // Allocate buffer to contain result string.
+
+ result = calloc(wcslen(exe_path) + strlen(program) + strlen(arg) + 6,
sizeof(wchar_t));
wcscpy(result, L"\"");
- sep = strrchr(myargv[0], DIR_SEPARATOR);
+ // Copy the path part of the filename (including ending \)
+ // into the result buffer:
+
+ sep = wcsrchr(exe_path, DIR_SEPARATOR);
if (sep != NULL)
{
- ConcatWCString(result, myargv[0]);
-
- // Cut off the string after the last directory separator,
- // before appending the actual program.
-
- result[sep - myargv[0] + 2] = '\0';
-
+ wcsncpy(result + 1, exe_path, sep - exe_path + 1);
+ result[sep - exe_path + 2] = '\0';
}
+ // Concatenate the name of the program:
+
ConcatWCString(result, program);
+ // End of program name, start of argument:
+
wcscat(result, L"\" \"");
ConcatWCString(result, arg);
@@ -290,7 +299,7 @@ static int ExecuteCommand(const char *program, const char *arg)
execvp(argv[0], (char **) argv);
- exit(-1);
+ exit(0x80);
}
else
{
@@ -299,7 +308,7 @@ static int ExecuteCommand(const char *program, const char *arg)
waitpid(childpid, &result, 0);
- if (WIFEXITED(result))
+ if (WIFEXITED(result) && WEXITSTATUS(result) != 0x80)
{
return WEXITSTATUS(result);
}
diff --git a/src/strife/.gitignore b/src/strife/.gitignore
index d7e732ad..973a0073 100644
--- a/src/strife/.gitignore
+++ b/src/strife/.gitignore
@@ -5,3 +5,5 @@ Makefile.in
chocolate-doom
chocolate-server
*.exe
+tags
+TAGS
diff --git a/src/strife/Makefile.am b/src/strife/Makefile.am
index 85f8b764..c0e930cb 100644
--- a/src/strife/Makefile.am
+++ b/src/strife/Makefile.am
@@ -63,15 +63,11 @@ wi_stuff.c wi_stuff.h
FEATURE_DEHACKED_SOURCE_FILES = \
deh_ammo.c \
deh_cheat.c \
-deh_defs.h \
+deh_strife.c \
deh_frame.c \
-deh_io.c deh_io.h \
-deh_main.c deh_main.h \
-deh_mapping.c deh_mapping.h \
deh_misc.c deh_misc.h \
deh_ptr.c \
deh_sound.c \
-deh_text.c \
deh_thing.c \
deh_weapon.c
diff --git a/src/strife/deh_defs.h b/src/strife/deh_defs.h
deleted file mode 100644
index e7b76182..00000000
--- a/src/strife/deh_defs.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-//-----------------------------------------------------------------------------
-//
-// Definitions for use in the dehacked code
-//
-//-----------------------------------------------------------------------------
-
-#ifndef DEH_DEFS_H
-#define DEH_DEFS_H
-
-#include "md5.h"
-
-typedef struct deh_context_s deh_context_t;
-typedef struct deh_section_s deh_section_t;
-typedef void (*deh_section_init_t)(void);
-typedef void *(*deh_section_start_t)(deh_context_t *context, char *line);
-typedef void (*deh_section_end_t)(deh_context_t *context, void *tag);
-typedef void (*deh_line_parser_t)(deh_context_t *context, char *line, void *tag);
-typedef void (*deh_md5_hash_t)(md5_context_t *context);
-
-struct deh_section_s
-{
- char *name;
-
- // Called on startup to initialize code
-
- deh_section_init_t init;
-
- // This is called when a new section is started. The pointer
- // returned is used as a tag for the following calls.
-
- deh_section_start_t start;
-
- // This is called for each line in the section
-
- deh_line_parser_t line_parser;
-
- // This is called at the end of the section for any cleanup
-
- deh_section_end_t end;
-
- // Called when generating an MD5 sum of the dehacked state
-
- deh_md5_hash_t md5_hash;
-};
-
-#endif /* #ifndef DEH_DEFS_H */
-
-
diff --git a/src/strife/deh_io.c b/src/strife/deh_io.c
deleted file mode 100644
index 3386a6fa..00000000
--- a/src/strife/deh_io.c
+++ /dev/null
@@ -1,211 +0,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-//-----------------------------------------------------------------------------
-//
-// Dehacked I/O code (does all reads from dehacked files)
-//
-//-----------------------------------------------------------------------------
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "i_system.h"
-#include "z_zone.h"
-
-#include "deh_defs.h"
-#include "deh_io.h"
-
-struct deh_context_s
-{
- FILE *stream;
- char *filename;
- int linenum;
- boolean last_was_newline;
- char *readbuffer;
- int readbuffer_size;
-};
-
-// Open a dehacked file for reading
-// Returns NULL if open failed
-
-deh_context_t *DEH_OpenFile(char *filename)
-{
- FILE *fstream;
- deh_context_t *context;
-
- fstream = fopen(filename, "r");
-
- if (fstream == NULL)
- return NULL;
-
- context = Z_Malloc(sizeof(*context), PU_STATIC, NULL);
- context->stream = fstream;
-
- // Initial read buffer size of 128 bytes
-
- context->readbuffer_size = 128;
- context->readbuffer = Z_Malloc(context->readbuffer_size, PU_STATIC, NULL);
- context->filename = filename;
- context->linenum = 0;
- context->last_was_newline = true;
-
- return context;
-}
-
-// Close dehacked file
-
-void DEH_CloseFile(deh_context_t *context)
-{
- fclose(context->stream);
- Z_Free(context->readbuffer);
- Z_Free(context);
-}
-
-// Reads a single character from a dehacked file
-
-int DEH_GetChar(deh_context_t *context)
-{
- int result;
-
- // Read characters, but ignore carriage returns
- // Essentially this is a DOS->Unix conversion
-
- do
- {
- if (feof(context->stream))
- {
- // end of file
-
- result = -1;
- }
- else
- {
- result = fgetc(context->stream);
- }
-
- } while (result == '\r');
-
- // Track the current line number
-
- if (context->last_was_newline)
- {
- ++context->linenum;
- }
-
- context->last_was_newline = result == '\n';
-
- return result;
-}
-
-// Increase the read buffer size
-
-static void IncreaseReadBuffer(deh_context_t *context)
-{
- char *newbuffer;
- int newbuffer_size;
-
- newbuffer_size = context->readbuffer_size * 2;
- newbuffer = Z_Malloc(newbuffer_size, PU_STATIC, NULL);
-
- memcpy(newbuffer, context->readbuffer, context->readbuffer_size);
-
- Z_Free(context->readbuffer);
-
- context->readbuffer = newbuffer;
- context->readbuffer_size = newbuffer_size;
-}
-
-// Read a whole line
-
-char *DEH_ReadLine(deh_context_t *context)
-{
- int c;
- int pos;
-
- for (pos = 0;;)
- {
- c = DEH_GetChar(context);
-
- if (c < 0)
- {
- // end of file
-
- return NULL;
- }
-
- // cope with lines of any length: increase the buffer size
-
- if (pos >= context->readbuffer_size)
- {
- IncreaseReadBuffer(context);
- }
-
- if (c == '\n')
- {
- // end of line: a full line has been read
-
- context->readbuffer[pos] = '\0';
- break;
- }
- else if (c != '\0')
- {
- // normal character; don't allow NUL characters to be
- // added.
-
- context->readbuffer[pos] = (char) c;
- ++pos;
- }
- }
-
- return context->readbuffer;
-}
-
-void DEH_Warning(deh_context_t *context, char *msg, ...)
-{
- va_list args;
-
- va_start(args, msg);
-
- fprintf(stderr, "%s:%i: warning: ", context->filename, context->linenum);
- vfprintf(stderr, msg, args);
- fprintf(stderr, "\n");
-
- va_end(args);
-}
-
-void DEH_Error(deh_context_t *context, char *msg, ...)
-{
- va_list args;
-
- va_start(args, msg);
-
- fprintf(stderr, "%s:%i: ", context->filename, context->linenum);
- vfprintf(stderr, msg, args);
- fprintf(stderr, "\n");
-
- va_end(args);
-
- I_Error("Error parsing dehacked file");
-}
-
-
diff --git a/src/strife/deh_io.h b/src/strife/deh_io.h
deleted file mode 100644
index 061a5a0e..00000000
--- a/src/strife/deh_io.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-//-----------------------------------------------------------------------------
-//
-// Dehacked I/O code (does all reads from dehacked files)
-//
-//-----------------------------------------------------------------------------
-
-#ifndef DEH_IO_H
-#define DEH_IO_H
-
-#include "deh_defs.h"
-
-deh_context_t *DEH_OpenFile(char *filename);
-void DEH_CloseFile(deh_context_t *context);
-int DEH_GetChar(deh_context_t *context);
-char *DEH_ReadLine(deh_context_t *context);
-void DEH_Error(deh_context_t *context, char *msg, ...);
-void DEH_Warning(deh_context_t *context, char *msg, ...);
-
-#endif /* #ifndef DEH_IO_H */
-
diff --git a/src/strife/deh_main.h b/src/strife/deh_main.h
deleted file mode 100644
index f9cb44ca..00000000
--- a/src/strife/deh_main.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-//-----------------------------------------------------------------------------
-//
-// Dehacked entrypoint and common code
-//
-//-----------------------------------------------------------------------------
-
-#ifndef DEH_MAIN_H
-#define DEH_MAIN_H
-
-#include "doomtype.h"
-#include "doomfeatures.h"
-#include "md5.h"
-#include "deh_str.h"
-
-// These are the limits that dehacked uses (from dheinit.h in the dehacked
-// source). If these limits are exceeded, it does not generate an error, but
-// a warning is displayed.
-
-#define DEH_VANILLA_NUMSTATES 966
-#define DEH_VANILLA_NUMSFX 107
-
-void DEH_Init(void);
-int DEH_LoadFile(char *filename);
-
-boolean DEH_ParseAssignment(char *line, char **variable_name, char **value);
-
-void DEH_Checksum(md5_digest_t digest);
-
-extern boolean deh_allow_long_strings;
-extern boolean deh_allow_long_cheats;
-extern boolean deh_apply_cheats;
-
-#endif /* #ifndef DEH_MAIN_H */
-
diff --git a/src/strife/deh_mapping.c b/src/strife/deh_mapping.c
deleted file mode 100644
index b215b128..00000000
--- a/src/strife/deh_mapping.c
+++ /dev/null
@@ -1,133 +0,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-//-----------------------------------------------------------------------------
-//
-// Dehacked "mapping" code
-// Allows the fields in structures to be mapped out and accessed by
-// name
-//
-//-----------------------------------------------------------------------------
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "doomtype.h"
-#include "i_system.h"
-#include "deh_mapping.h"
-
-//
-// Set the value of a particular field in a structure by name
-//
-
-boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping,
- void *structptr, char *name, int value)
-{
- int i;
-
- for (i=0; mapping->entries[i].name != NULL; ++i)
- {
- deh_mapping_entry_t *entry = &mapping->entries[i];
-
- if (!strcasecmp(entry->name, name))
- {
- void *location;
-
- if (entry->location == NULL)
- {
- DEH_Warning(context, "Field '%s' is unsupported", name);
- return false;
- }
-
- location = (uint8_t *)structptr + ((uint8_t *)entry->location - (uint8_t *)mapping->base);
-
- // printf("Setting %p::%s to %i (%i bytes)\n",
- // structptr, name, value, entry->size);
-
- switch (entry->size)
- {
- case 1:
- * ((uint8_t *) location) = value;
- break;
- case 2:
- * ((uint16_t *) location) = value;
- break;
- case 4:
- * ((uint32_t *) location) = value;
- break;
- default:
- DEH_Error(context, "Unknown field type for '%s' (BUG)", name);
- return false;
- }
-
- return true;
- }
- }
-
- // field with this name not found
-
- DEH_Warning(context, "Field named '%s' not found", name);
-
- return false;
-}
-
-void DEH_StructMD5Sum(md5_context_t *context, deh_mapping_t *mapping,
- void *structptr)
-{
- int i;
-
- // Go through each mapping
-
- for (i=0; mapping->entries[i].name != NULL; ++i)
- {
- deh_mapping_entry_t *entry = &mapping->entries[i];
- void *location;
-
- if (entry->location == NULL)
- {
- // Unsupported field
-
- continue;
- }
-
- // Add in data for this field
-
- location = (uint8_t *)structptr + ((uint8_t *)entry->location - (uint8_t *)mapping->base);
-
- switch (entry->size)
- {
- case 1:
- MD5_UpdateInt32(context, *((uint8_t *) location));
- break;
- case 2:
- MD5_UpdateInt32(context, *((uint16_t *) location));
- break;
- case 4:
- MD5_UpdateInt32(context, *((uint32_t *) location));
- break;
- default:
- I_Error("Unknown dehacked mapping field type for '%s' (BUG)",
- entry->name);
- break;
- }
- }
-}
-
diff --git a/src/strife/deh_mapping.h b/src/strife/deh_mapping.h
deleted file mode 100644
index 4862dec9..00000000
--- a/src/strife/deh_mapping.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-//-----------------------------------------------------------------------------
-//
-// Dehacked "mapping" code
-// Allows the fields in structures to be mapped out and accessed by
-// name
-//
-//-----------------------------------------------------------------------------
-
-#ifndef DEH_MAPPING_H
-#define DEH_MAPPING_H
-
-#include "doomtype.h"
-#include "deh_io.h"
-#include "md5.h"
-
-#define DEH_BEGIN_MAPPING(mapping_name, structname) \
- static structname deh_mapping_base; \
- static deh_mapping_t mapping_name = \
- { \
- &deh_mapping_base, \
- {
-
-#define DEH_MAPPING(deh_name, fieldname) \
- {deh_name, &deh_mapping_base.fieldname, \
- sizeof(deh_mapping_base.fieldname)},
-
-#define DEH_UNSUPPORTED_MAPPING(deh_name) \
- {deh_name, NULL, -1},
-
-#define DEH_END_MAPPING \
- {NULL, NULL, -1} \
- } \
- };
-
-
-
-#define MAX_MAPPING_ENTRIES 32
-
-typedef struct deh_mapping_s deh_mapping_t;
-typedef struct deh_mapping_entry_s deh_mapping_entry_t;
-
-struct deh_mapping_entry_s
-{
- // field name
-
- char *name;
-
- // location relative to the base in the deh_mapping_t struct
- // If this is NULL, it is an unsupported mapping
-
- void *location;
-
- // field size
-
- int size;
-};
-
-struct deh_mapping_s
-{
- void *base;
- deh_mapping_entry_t entries[MAX_MAPPING_ENTRIES];
-};
-
-boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping,
- void *structptr, char *name, int value);
-void DEH_StructMD5Sum(md5_context_t *context, deh_mapping_t *mapping,
- void *structptr);
-
-#endif /* #ifndef DEH_MAPPING_H */
-
diff --git a/src/strife/deh_strife.c b/src/strife/deh_strife.c
new file mode 100644
index 00000000..c9a7a73b
--- /dev/null
+++ b/src/strife/deh_strife.c
@@ -0,0 +1,74 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Top-level dehacked definitions for Strife dehacked (sehacked)
+//
+//-----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include "deh_defs.h"
+#include "deh_main.h"
+
+char *deh_signatures[] =
+{
+ "Patch File for DeHackEd v2.3",
+ "Patch File for DeHackEd v3.0",
+ NULL
+};
+
+// deh_ammo.c:
+extern deh_section_t deh_section_ammo;
+// deh_cheat.c:
+extern deh_section_t deh_section_cheat;
+// deh_frame.c:
+extern deh_section_t deh_section_frame;
+// deh_misc.c:
+extern deh_section_t deh_section_misc;
+// deh_ptr.c:
+extern deh_section_t deh_section_pointer;
+// deh_sound.c
+extern deh_section_t deh_section_sound;
+// deh_text.c:
+extern deh_section_t deh_section_text;
+// deh_thing.c:
+extern deh_section_t deh_section_thing;
+// deh_weapon.c:
+extern deh_section_t deh_section_weapon;
+
+//
+// List of section types:
+//
+
+deh_section_t *deh_section_types[] =
+{
+ &deh_section_ammo,
+ &deh_section_cheat,
+ &deh_section_frame,
+ &deh_section_misc,
+ &deh_section_pointer,
+ &deh_section_sound,
+ &deh_section_text,
+ &deh_section_thing,
+ &deh_section_weapon,
+ NULL
+};
+
diff --git a/src/strife/deh_text.c b/src/strife/deh_text.c
deleted file mode 100644
index 31e23db2..00000000
--- a/src/strife/deh_text.c
+++ /dev/null
@@ -1,127 +0,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 2005 Simon Howard
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-// 02111-1307, USA.
-//
-//-----------------------------------------------------------------------------
-//
-// Parses Text substitution sections in dehacked files
-//
-//-----------------------------------------------------------------------------
-
-#include <stdio.h>
-#include <string.h>
-
-#include "doomtype.h"
-
-#include "z_zone.h"
-
-#include "deh_defs.h"
-#include "deh_io.h"
-#include "deh_main.h"
-
-// Given a string length, find the maximum length of a
-// string that can replace it.
-
-static int TXT_MaxStringLength(int len)
-{
- // Enough bytes for the string and the NUL terminator
-
- len += 1;
-
- // All strings in doom.exe are on 4-byte boundaries, so we may be able
- // to support a slightly longer string.
- // Extend up to the next 4-byte boundary
-
- len += (4 - (len % 4)) % 4;
-
- // Less one for the NUL terminator.
-
- return len - 1;
-}
-
-static void *DEH_TextStart(deh_context_t *context, char *line)
-{
- char *from_text, *to_text;
- int fromlen, tolen;
- int i;
-
- if (sscanf(line, "Text %i %i", &fromlen, &tolen) != 2)
- {
- DEH_Warning(context, "Parse error on section start");
- return NULL;
- }
-
- // Only allow string replacements that are possible in Vanilla Doom.
- // Chocolate Doom is unforgiving!
-
- if (!deh_allow_long_strings && tolen > TXT_MaxStringLength(fromlen))
- {
- DEH_Error(context, "Replacement string is longer than the maximum "
- "possible in doom.exe");
- return NULL;
- }
-
- from_text = Z_Malloc(fromlen + 1, PU_STATIC, NULL);
- to_text = Z_Malloc(tolen + 1, PU_STATIC, NULL);
-
- // read in the "from" text
-
- for (i=0; i<fromlen; ++i)
- {
- int c;
-
- c = DEH_GetChar(context);
-
- from_text[i] = c;
- }
-
- from_text[fromlen] = '\0';
-
- // read in the "to" text
-
- for (i=0; i<tolen; ++i)
- {
- int c;
-
- c = DEH_GetChar(context);
-
- to_text[i] = c;
- }
- to_text[tolen] = '\0';
-
- DEH_AddStringReplacement(from_text, to_text);
-
- return NULL;
-}
-
-static void DEH_TextParseLine(deh_context_t *context, char *line, void *tag)
-{
- // not used
-}
-
-deh_section_t deh_section_text =
-{
- "Text",
- NULL,
- DEH_TextStart,
- DEH_TextParseLine,
- NULL,
- NULL,
-};
-
diff --git a/src/strife/g_game.c b/src/strife/g_game.c
index 35bf4d74..8d0e4503 100644
--- a/src/strife/g_game.c
+++ b/src/strife/g_game.c
@@ -588,10 +588,20 @@ void G_BuildTiccmd (ticcmd_t* cmd)
if (lowres_turn)
{
- // round angleturn to the nearest 256 boundary
+ static signed short carry = 0;
+ signed short desired_angleturn;
+
+ desired_angleturn = cmd->angleturn + carry;
+
+ // round angleturn to the nearest 256 unit boundary
// for recording demos with single byte values for turn
- cmd->angleturn = (cmd->angleturn + 128) & 0xff00;
+ cmd->angleturn = (desired_angleturn + 128) & 0xff00;
+
+ // Carry forward the error from the reduced resolution to the
+ // next tic, so that successive small movements can accumulate.
+
+ carry = desired_angleturn - cmd->angleturn;
}
}
diff --git a/src/strife/hu_stuff.c b/src/strife/hu_stuff.c
index a106978e..ca74ce92 100644
--- a/src/strife/hu_stuff.c
+++ b/src/strife/hu_stuff.c
@@ -52,9 +52,9 @@
// Locally used constants, shortcuts.
//
#define HU_TITLE (mapnames[(gameepisode-1)*9+gamemap-1])
-#define HU_TITLE2 (mapnames2[gamemap-1])
-#define HU_TITLEP (mapnamesp[gamemap-1])
-#define HU_TITLET (mapnamest[gamemap-1])
+#define HU_TITLE2 (mapnames_commercial[gamemap-1])
+#define HU_TITLEP (mapnames_commercial[gamemap-1 + 32])
+#define HU_TITLET (mapnames_commercial[gamemap-1 + 64])
#define HU_TITLE_CHEX (mapnames[gamemap - 1])
#define HU_TITLEHEIGHT 1
#define HU_TITLEX 0
@@ -171,8 +171,16 @@ char* mapnames[] = // DOOM shareware/registered/retail (Ultimate) names.
"NEWLEVEL"
};
-char* mapnames2[] = // DOOM 2 map names.
+// List of names for levels in commercial IWADs
+// (doom2.wad, plutonia.wad, tnt.wad). These are stored in a
+// single large array; WADs like pl2.wad have a MAP33, and rely on
+// the layout in the Vanilla executable, where it is possible to
+// overflow the end of one array into the next.
+
+char *mapnames_commercial[] =
{
+ // DOOM 2 map names.
+
HUSTR_1,
HUSTR_2,
HUSTR_3,
@@ -206,12 +214,10 @@ char* mapnames2[] = // DOOM 2 map names.
HUSTR_29,
HUSTR_30,
HUSTR_31,
- HUSTR_32
-};
+ HUSTR_32,
+ // Plutonia WAD map names.
-char* mapnamesp[] = // Plutonia WAD map names.
-{
PHUSTR_1,
PHUSTR_2,
PHUSTR_3,
@@ -245,12 +251,10 @@ char* mapnamesp[] = // Plutonia WAD map names.
PHUSTR_29,
PHUSTR_30,
PHUSTR_31,
- PHUSTR_32
-};
-
+ PHUSTR_32,
+
+ // TNT WAD map names.
-char *mapnamest[] = // TNT WAD map names.
-{
THUSTR_1,
THUSTR_2,
THUSTR_3,
diff --git a/src/strife/p_map.c b/src/strife/p_map.c
index 3f88aabc..925e4398 100644
--- a/src/strife/p_map.c
+++ b/src/strife/p_map.c
@@ -885,7 +885,17 @@ PTR_AimTraverse (intercept_t* in)
dist = FixedMul (attackrange, in->frac);
- if (li->frontsector->floorheight != li->backsector->floorheight)
+ // Return false if there is no back sector. This should never
+ // be the case if the line is two-sided; however, some WADs
+ // (eg. ottawau.wad) use this as an "impassible glass" trick
+ // and rely on Vanilla Doom's (unintentional) support for this.
+
+ if (li->backsector == NULL)
+ {
+ return false;
+ }
+
+ if (li->frontsector->floorheight != li->backsector->floorheight)
{
slope = FixedDiv (openbottom - shootz , dist);
if (slope > bottomslope)
@@ -973,7 +983,14 @@ boolean PTR_ShootTraverse (intercept_t* in)
dist = FixedMul (attackrange, in->frac);
- if (li->frontsector->floorheight != li->backsector->floorheight)
+ // Check if backsector is NULL. See comment in PTR_AimTraverse.
+
+ if (li->backsector == NULL)
+ {
+ goto hitline;
+ }
+
+ if (li->frontsector->floorheight != li->backsector->floorheight)
{
slope = FixedDiv (openbottom - shootz , dist);
if (slope > aimslope)
diff --git a/src/strife/p_setup.c b/src/strife/p_setup.c
index 5cf7a628..2a3a8f85 100644
--- a/src/strife/p_setup.c
+++ b/src/strife/p_setup.c
@@ -167,6 +167,7 @@ void P_LoadSegs (int lump)
line_t* ldef;
int linedef;
int side;
+ int sidenum;
numsegs = W_LumpLength (lump) / sizeof(mapseg_t);
segs = Z_Malloc (numsegs*sizeof(seg_t),PU_LEVEL,0);
@@ -179,7 +180,7 @@ void P_LoadSegs (int lump)
{
li->v1 = &vertexes[SHORT(ml->v1)];
li->v2 = &vertexes[SHORT(ml->v2)];
-
+
li->angle = (SHORT(ml->angle))<<16;
li->offset = (SHORT(ml->offset))<<16;
linedef = SHORT(ml->linedef);
@@ -188,10 +189,28 @@ void P_LoadSegs (int lump)
side = SHORT(ml->side);
li->sidedef = &sides[ldef->sidenum[side]];
li->frontsector = sides[ldef->sidenum[side]].sector;
- if (ldef-> flags & ML_TWOSIDED)
- li->backsector = sides[ldef->sidenum[side^1]].sector;
- else
+
+ if (ldef-> flags & ML_TWOSIDED)
+ {
+ sidenum = ldef->sidenum[side ^ 1];
+
+ // If the sidenum is out of range, this may be a "glass hack"
+ // impassible window. Point at side #0 (this may not be
+ // the correct Vanilla behavior; however, it seems to work for
+ // OTTAWAU.WAD, which is the one place I've seen this trick
+ // used).
+
+ if (sidenum < 0 || sidenum >= numsides)
+ {
+ sidenum = 0;
+ }
+
+ li->backsector = sides[sidenum].sector;
+ }
+ else
+ {
li->backsector = 0;
+ }
}
W_ReleaseLumpNum(lump);
diff --git a/src/strife/p_sight.c b/src/strife/p_sight.c
index e192567b..79c1bb1d 100644
--- a/src/strife/p_sight.c
+++ b/src/strife/p_sight.c
@@ -173,7 +173,7 @@ boolean P_CrossSubsector (int num)
continue;
line->validcount = validcount;
-
+
v1 = line->v1;
v2 = line->v2;
s1 = P_DivlineSide (v1->x,v1->y, &strace);
@@ -194,6 +194,14 @@ boolean P_CrossSubsector (int num)
if (s1 == s2)
continue;
+ // Backsector may be NULL if this is an "impassible
+ // glass" hack line.
+
+ if (line->backsector == NULL)
+ {
+ return false;
+ }
+
// stop because it is not two sided anyway
// might do this after updating validcount?
if ( !(line->flags & ML_TWOSIDED) )
diff --git a/src/strife/st_stuff.c b/src/strife/st_stuff.c
index e6ef0828..160244ce 100644
--- a/src/strife/st_stuff.c
+++ b/src/strife/st_stuff.c
@@ -260,9 +260,6 @@
// Height, in lines.
#define ST_OUTHEIGHT 1
-#define ST_MAPWIDTH \
- (strlen(mapnames[(gameepisode-1)*9+(gamemap-1)]))
-
#define ST_MAPTITLEX \
(SCREENWIDTH - ST_MAPWIDTH * ST_CHATFONTWIDTH)
@@ -418,10 +415,6 @@ cheatseq_t cheat_clev = CHEAT("idclev", 2);
cheatseq_t cheat_mypos = CHEAT("idmypos", 0);
-//
-extern char* mapnames[];
-
-
//
// STATUS BAR CODE
//
@@ -985,6 +978,17 @@ void ST_doPaletteStuff(void)
else
palette = 0;
+ // In Chex Quest, the player never sees red. Instead, the
+ // radiation suit palette is used to tint the screen green,
+ // as though the player is being covered in goo by an
+ // attacking flemoid.
+
+ if (gameversion == exe_chex
+ && palette >= STARTREDPALS && palette < STARTREDPALS + NUMREDPALS)
+ {
+ palette = RADIATIONPAL;
+ }
+
if (palette != st_palette)
{
st_palette = palette;