ref: d9520b6415f8e373cf759f316094b986e57f0f5a
parent: 57011e785808847273461aaf6d8ed1df76ff1db9
parent: 52f81b4ef175358d1e1f7f9eecab2a1edb7f4b65
author: Simon Howard <[email protected]>
date: Fri Feb 5 22:14:20 EST 2010
Merge from trunk. Subversion-branch: /branches/strife-branch Subversion-revision: 1849
--- a/.gitignore
+++ b/.gitignore
@@ -10,9 +10,12 @@
config.status
config.h
autom4te.cache
+rpm.spec
stamp-h
stamp-h.in
stamp-h1
+tags
+TAGS
# These are the default patterns globally ignored by Subversion:
*.o
--- a/INSTALL
+++ b/INSTALL
@@ -23,7 +23,7 @@
On a Unix system, follow the standard instructions for installing an
autotools-based package:
- 1. Run './configure' to initialise the package.
+ 1. Run './configure' to initialize the package.
2. Run 'make' to compile the package.
3. Run 'make install' to install the package.
--- a/Makefile.am
+++ b/Makefile.am
@@ -32,9 +32,12 @@
codeblocks/setup-res.rc
DATA_FILES= \
+ data/README \
data/doom.ico \
+ data/doom8.ico \
data/doom.png \
data/setup.ico \
+ data/setup8.ico \
data/setup.png \
data/convert-icon
@@ -43,11 +46,13 @@
$(MSVC_FILES) \
$(CODEBLOCKS_FILES) \
$(DATA_FILES) \
+ .lvimrc \
config.h \
CMDLINE \
HACKING \
TODO \
- BUGS
+ BUGS \
+ rpm.spec
MAINTAINERCLEANFILES = $(AUX_DIST_GEN)
@@ -56,6 +61,8 @@
DIST_SUBDIRS=pkg $(SUBDIRS)
if HAVE_PYTHON
+
+noinst_DATA=CMDLINE
CMDLINE : src/
./man/docgen -p man/CMDLINE.template src/ > $@
--- a/NEWS
+++ b/NEWS
@@ -1,35 +1,68 @@
...
* Chocolate Doom now runs on Windows Mobile/Windows CE!
- * It is possible to rebind most/all of the keys that control
- the menu, shortcuts, automap and weapon switching. The
- main reason for this is to support the Windows CE port
- and other platforms where a full keyboard may not be present.
- * Memory-mapped WAD I/O is disabled by default, as it caused
- various issues, including a slowdown/crash with Plutonia 2
- MAP23. It can be explicitly re-enabled using the '-mmap'
- command line parameter.
+ * It is possible to rebind most/all of the keys that control the
+ menu, shortcuts, automap and weapon switching. The main
+ reason for this is to support the Windows CE port and other
+ platforms where a full keyboard may not be present.
+ * Chocolate Doom now includes a proper Mac OS X package; it is
+ no longer necessary to compile binaries for this system by
+ hand. The package includes a simple graphical launcher
+ program and can be installed simply by dragging the "Chocolate
+ Doom" icon to the Applications folder. (thanks to Rikard Lang
+ for extensive testing and feedback)
* The video mode auto-adjust code will automatically choose
windowed mode if no fullscreen video modes are available.
- * The zone memory size is automatically reduced on systems
- with a small amount of memory.
- * There is now a second, small textscreen font, so that the
- ENDOOM screen and setup tool can be used on low resolution
- devices (eg. PDAs/embedded devices)
- * The textscreen library now has a scrollable pane widget.
- * Doxygen documentation was added for the textscreen library.
- * The "join game" window in the setup tool now has an option
- to automatically join a game on the local network.
+ * The zone memory size is automatically reduced on systems with
+ a small amount of memory.
+ * The "join game" window in the setup tool now has an option to
+ automatically join a game on the local network.
+ * Chocolate Doom includes some initial hacks for compiling under
+ SDL 1.3.
+ * Recent versions of SDL_mixer include rewritten MIDI code on Mac
+ OS X. If you are using a version of SDL_mixer with the new
+ code, music will now be enabled by default.
+ * Windows Vista and Windows 7 no longer prompt for elevated
+ privileges when running the setup tool (thanks hobbs and
+ MikeRS).
+ * The Windows binaries now have better looking icons (thanks
+ MikeRS).
+ * Magic values specified using the -spechit command line
+ parameter can now be hexadecimal.
+ * DOOMWADDIR/DOOMWADPATH can now specify the complete path to
+ IWAD files, rather than the path to the directory that contains
+ them.
+ * When recording shorttics demos, errors caused by the reduced
+ turning resolution are carried forward, possibly making turning
+ smoother.
Compatibility:
* The A_BossDeath behavior in v1.9 emulation mode was fixed
(thanks entryway)
+ * The "loading" disk icon is drawn more like how it is drawn in
+ Vanilla Doom, also fixing a bug with chook3.wad.
+ * Desync on 64-bit systems with ep1-0500.lmp has (at long last)
+ been fixed (thanks exp(x)).
+ * Donut overrun emulation code imported from Prboom+ (thanks
+ entryway).
+ * The correct level name should now be shown in the automap for
+ pl2.wad MAP33 (thanks Janizdreg).
+ * In Chex Quest, the green radiation suit colormap is now used
+ instead of the red colormaps normally used when taking damage
+ or using the berserk pack. This matches Vanilla chex.exe
+ behavior (thanks Fuzztooth).
+ * Impassible glass now displays and works the same as in Vanilla,
+ fixing wads such as OTTAWAU.WAD (thanks Never_Again).
Bugs fixed:
+ * Memory-mapped WAD I/O is disabled by default, as it caused
+ various issues, including a slowdown/crash with Plutonia 2
+ MAP23. It can be explicitly re-enabled using the '-mmap'
+ command line parameter.
* Crash when saving games due to the ~/.chocolate-doom/savegames
directory not being created (thanks to everyone who reported
this).
- * Chocolate Doom will now under Win95/98, as the
+ * Chocolate Doom will now run under Win95/98, as the
SetProcessAffinityMask function is looked up dynamically.
* Compilation under Linux with older versions of libc will now
work (the semantics for sched_setaffinity were different in
@@ -36,13 +69,28 @@
older versions)
* Sound clipping when using libsamplerate was improved (thanks
David Flater)
- * The audio buffer size is now calculated based on the sample rate,
- so there is not a noticeable delay when using a lower sample
- rate.
- * The manpage documentation for the DOOMWADPATH variable was fixed
- (thanks MikeRS).
- * Compilation with FEATURE_MULTIPLAYER and FEATURE_SOUND disabled
- was fixed.
+ * The audio buffer size is now calculated based on the sample
+ rate, so there is not a noticeable delay when using a lower
+ sample rate.
+ * The manpage documentation for the DOOMWADPATH variable was
+ fixed (thanks MikeRS).
+ * Compilation with FEATURE_MULTIPLAYER and FEATURE_SOUND
+ disabled was fixed.
+ * Fixed crash when using the donut special type and the joining
+ linedef is one sided (thanks Alexander Waldmann).
+ * Key settings in a configuration file that are out of range
+ do not cause a crash (thanks entryway).
+ * Fix ear-piercing whistle when playing the MAP05 MIDI music
+ using timidity with EAWPATS (thanks entryway / HackNeyed).
+
+ libtextscreen:
+ * There is now a second, small textscreen font, so that the
+ ENDOOM screen and setup tool can be used on low resolution
+ devices (eg. PDAs/embedded devices)
+ * The textscreen library now has a scrollable pane widget. Thanks
+ to LionsPhil for contributing code to scroll up and down using
+ the keyboard.
+ * Doxygen documentation was added for the textscreen library.
1.2.1 (2008-12-10):
--- a/TODO
+++ b/TODO
@@ -1,17 +1,22 @@
+Currently in progress:
+
+* OPL MIDI playback (see: opl-branch)
+* Heretic/Hexen support (see: raven-branch)
+* Strife support (see: strife-branch)
+
To do:
-* Install packages:
- - Debian/Ubuntu .deb packages, Fedora .rpm packages.
- - Windows NSIS installer.
- - MacOS X .dmg packages (should be universal binaries!)
+* Demo hashes for regression testing of this and other ports.
* File selector for chocolate-setup, so that WADs can be selected from
a browser, instead of simply typing the filenames.
* Multiplayer:
- Master server for locating servers automatically - makes setting up
public servers easier.
+ - Use UPnP to automatically configure port forwarding for NATted
+ networks.
- Incorporate local LAN search into setup interface.
- Multiplayer options and configuration file (server name, etc)
-* Improve multiplayer startup:
+* Improve multiplayer startup:
- Select an IWAD automatically from the server's game type rather than
all players having to specify -iwad.
- Send list of WADs to load instead of all clients having to specify -file.
@@ -20,16 +25,14 @@
- Test on and fix for architectures where ((-2) >> 1) != -1
- Use size-specific types (eg. int32_t instead of int)
- Don't make structure packing assumptions when loading levels.
-* Port to every OS and architecture under the sun
+ - Port to every OS and architecture under the sun
Crazy pie in the sky ideas:
* Automatic WAD installer - download and run TCs from a list automatically
(automating the current "instructions on wiki" system).
-* Textscreen interface to the Compet-N database: menu driven system to
+* Textscreen interface to the Compet-N database: menu driven system to
automatically download and play speedruns.
* DWANGO-like interface for finding players and setting up games.
-* Demo hashes for regression testing of this and other ports.
-* OPL emulation
* Video capture mode?
--- a/autogen.sh
+++ b/autogen.sh
@@ -8,5 +8,5 @@
autoconf
automake
-./configure $@
+./configure "$@"
--- a/configure.in
+++ b/configure.in
@@ -1,5 +1,11 @@
AC_INIT(Chocolate Doom, 1.2.1, [email protected], chocolate-doom)
+PACKAGE_SHORTDESC="Conservative Doom source port"
+PACKAGE_COPYRIGHT="Copyright (C) 1993-2010"
+PACKAGE_LICENSE="GNU General Public License, version 2"
+PACKAGE_MAINTAINER="Simon Howard"
+PACKAGE_URL="http://www.chocolate-doom.org/"
+
AC_CONFIG_AUX_DIR(autotools)
orig_CFLAGS="$CFLAGS"
@@ -120,28 +126,36 @@
AC_SUBST(ac_aux_dir)
+AC_SUBST(PACKAGE_SHORTDESC)
+AC_SUBST(PACKAGE_COPYRIGHT)
+AC_SUBST(PACKAGE_LICENSE)
+AC_SUBST(PACKAGE_MAINTAINER)
+AC_SUBST(PACKAGE_URL)
+
dnl Shut up the datarootdir warnings.
AC_DEFUN([AC_DATAROOTDIR_CHECKED])
AC_OUTPUT([
Makefile
-wince/Makefile
-textscreen/Makefile
-textscreen/examples/Makefile
man/Makefile
+pcsound/Makefile
+pkg/Makefile
+pkg/config.make
+pkg/osx/Info-gnustep.plist
+pkg/osx/Info.plist
+rpm.spec
src/Makefile
+src/doom-screensaver.desktop
src/doom/Makefile
src/heretic/Makefile
src/hexen/Makefile
-src/setup/Makefile
-src/strife/Makefile
-pcsound/Makefile
-pkg/Makefile
-pkg/wince/GNUmakefile
-pkg/win32/GNUmakefile
src/resource.rc
src/setup-res.rc
+src/setup/Makefile
src/setup/setup-manifest.xml
-src/doom-screensaver.desktop
+src/strife/Makefile
+textscreen/Makefile
+textscreen/examples/Makefile
+wince/Makefile
])
--- a/data/README
+++ b/data/README
@@ -3,3 +3,10 @@
http://www.flickr.com/photos/laffy4k/448920776/
+The "foo8.ico" files are 8-bit depth only, while the "foo.ico" files
+contain full 32-bit versions, scaled to different sizes and with proper
+alpha masks (as well as the 8-bit versions). The 8-bit versions are
+used when setting the icon within SDL, as SDL under Windows displays
+full color icons in a very poor quality. The full-color versions are
+used in the resource files.
+
binary files a/data/doom.ico b/data/doom.ico differ
binary files /dev/null b/data/doom8.ico differ
binary files a/data/setup.ico b/data/setup.ico differ
binary files /dev/null b/data/setup8.ico differ
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -5,9 +5,9 @@
man_MANS=chocolate-doom.6 \
chocolate-server.6 \
- chocolate-setup.6 \
- default.cfg.5 \
- $(PACKAGE).cfg.5
+ chocolate-setup.6 \
+ default.cfg.5 \
+ $(PACKAGE).cfg.5
chocolate-doom.6: ../src $(MANPAGE_GEN_FILES)
./docgen -m manpage.template ../src > $@
@@ -21,5 +21,6 @@
endif
EXTRA_DIST = $(man_MANS) $(MANPAGE_GEN_FILES) \
- wikipages
+ wikipages \
+ CMDLINE.template
--- a/pcsound/.gitignore
+++ b/pcsound/.gitignore
@@ -3,4 +3,6 @@
.deps
libpcsound.a
*.rc
+tags
+TAGS
--- /dev/null
+++ b/pkg/.gitignore
@@ -1,0 +1,3 @@
+Makefile
+Makefile.in
+config.make
--- a/pkg/Makefile.am
+++ b/pkg/Makefile.am
@@ -1,3 +1,35 @@
-DIST_SUBDIRS=wince win32
+OSX_FILES= \
+osx/Resources/128x128.png \
+osx/Resources/app.icns \
+osx/Resources/app.png \
+osx/Resources/wadfile.icns \
+osx/Resources/wadfile.png \
+osx/Resources/launcher.nib/classes.nib \
+osx/Resources/launcher.nib/info.nib \
+osx/Resources/launcher.nib/keyedobjects.nib \
+osx/GNUmakefile \
+osx/Info.plist.in osx/Info-gnustep.plist.in \
+osx/PkgInfo \
+osx/cp-with-libs \
+osx/main.m \
+osx/AppController.m osx/AppController.h \
+osx/Execute.m osx/Execute.h \
+osx/IWADController.m osx/IWADController.h \
+osx/IWADLocation.m osx/IWADLocation.h \
+osx/LauncherManager.m osx/LauncherManager.h
+
+WINCE_FILES= \
+wince/GNUmakefile \
+wince/common.py \
+wince/doom-cab.cfg \
+wince/heretic-cab.cfg \
+wince/hexen-cab.cfg \
+wince/wince-cabgen
+
+WIN32_FILES= \
+win32/GNUmakefile \
+win32/README
+
+EXTRA_DIST=$(OSX_FILES) $(WINCE_FILES) $(WIN32_FILES)
--- /dev/null
+++ b/pkg/config.make.in
@@ -1,0 +1,29 @@
+# Shared file included by the makefiles used to build packages.
+# This contains various information needed by the makefiles,
+# and is autogenerated by configure to include various
+# necessary details.
+
+# Tools needed:
+
+CC = @CC@
+STRIP = @STRIP@
+
+# Package name and version number:
+
+PROGRAM_PREFIX = @PROGRAM_PREFIX@
+PACKAGE = @PACKAGE@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+
+# Documentation files to distribute with packages.
+
+DOC_FILES = README \
+ COPYING \
+ ChangeLog \
+ NEWS \
+ BUGS \
+ CMDLINE \
+ TODO
+
--- /dev/null
+++ b/pkg/osx/.gitignore
@@ -1,0 +1,7 @@
+Info.plist
+Info-gnustep.plist
+launcher
+*.o
+*.d
+*.dmg
+staging
--- /dev/null
+++ b/pkg/osx/AppController.h
@@ -1,0 +1,53 @@
+/* ... */
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2009 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.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef LAUNCHER_APPCONTROLLER_H
+#define LAUNCHER_APPCONTROLLER_H
+
+#include <AppKit/AppKit.h>
+
+#include "LauncherManager.h"
+
+@interface AppController : NSObject
+{
+ LauncherManager *launcherManager;
+ BOOL filesAdded;
+}
+
++ (void)initialize;
+
+- (id)init;
+- (void)dealloc;
+
+- (void)awakeFromNib;
+
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotif;
+- (BOOL)applicationShouldTerminate:(id)sender;
+- (void)applicationWillTerminate:(NSNotification *)aNotif;
+- (BOOL)application:(NSApplication *)application openFile:(NSString *)fileName;
+
+- (void)showPrefPanel:(id)sender;
+
+@end
+
+#endif
+
--- /dev/null
+++ b/pkg/osx/AppController.m
@@ -1,0 +1,124 @@
+/* ... */
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2009 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.
+//
+//-----------------------------------------------------------------------------
+
+#include "AppController.h"
+
+#include "config.h"
+
+@implementation AppController
+
++ (void)initialize
+{
+ NSMutableDictionary *defaults = [NSMutableDictionary dictionary];
+
+ /*
+ * Register your app's defaults here by adding objects to the
+ * dictionary, eg
+ *
+ * [defaults setObject:anObject forKey:keyForThatObject];
+ *
+ */
+
+ [[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
+ [[NSUserDefaults standardUserDefaults] synchronize];
+}
+
+- (id)init
+{
+ if ((self = [super init]))
+ {
+ }
+
+ self->filesAdded = NO;
+
+ return self;
+}
+
+- (void)dealloc
+{
+ [super dealloc];
+}
+
+- (void)awakeFromNib
+{
+ [[NSApp mainMenu] setTitle:@PACKAGE_NAME];
+}
+
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotif
+{
+// Uncomment if your application is Renaissance-based
+// [NSBundle loadGSMarkupNamed:@"Main" owner:self];
+}
+
+- (BOOL)applicationShouldTerminate:(id)sender
+{
+ return YES;
+}
+
+- (void)applicationWillTerminate:(NSNotification *)aNotif
+{
+}
+
+- (BOOL) application:(NSApplication *) application
+ openFile:(NSString *) fileName
+{
+ NSString *extension;
+
+ // If this is the first file added, clear out the existing
+ // command line. This allows us to select multiple files
+ // in the finder and open them all together (for TCs, etc).
+
+ if (!self->filesAdded)
+ {
+ [self->launcherManager clearCommandLine];
+ }
+
+ // Add file with appropriate command line option based on extension:
+
+ extension = [fileName pathExtension];
+
+ if (![extension caseInsensitiveCompare: @"wad"])
+ {
+ [self->launcherManager addFileToCommandLine: fileName
+ forArgument: @"-merge"];
+ }
+ else if (![extension caseInsensitiveCompare: @"deh"])
+ {
+ [self->launcherManager addFileToCommandLine: fileName
+ forArgument: @"-deh"];
+ }
+ else
+ {
+ return NO;
+ }
+
+ self->filesAdded = YES;
+
+ return YES;
+}
+
+- (void)showPrefPanel:(id)sender
+{
+}
+
+@end
+
--- /dev/null
+++ b/pkg/osx/Execute.h
@@ -1,0 +1,31 @@
+/* ... */
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2009 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.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef LAUNCHER_EXECUTE_H
+#define LAUNCHER_EXECUTE_H
+
+void SetProgramLocation(const char *path);
+void ExecuteProgram(const char *executable, const char *iwad, const char *args);
+void OpenTerminalWindow(const char *doomwadpath);
+
+#endif /* #ifndef LAUNCHER_EXECUTE_H */
+
--- /dev/null
+++ b/pkg/osx/Execute.m
@@ -1,0 +1,208 @@
+/* ... */
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2009 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.
+//
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <AppKit/AppKit.h>
+
+#include "config.h"
+
+#define RESPONSE_FILE "/tmp/launcher.rsp"
+#define TEMP_SCRIPT "/tmp/tempscript.sh"
+
+static char *executable_path;
+
+// Called on startup to save the location of the launcher program
+// (within a package, other executables should be in the same directory)
+
+void SetProgramLocation(const char *path)
+{
+ char *p;
+
+ executable_path = strdup(path);
+
+ p = strrchr(executable_path, '/');
+ *p = '\0';
+}
+
+// Write out the response file containing command line arguments.
+
+static void WriteResponseFile(const char *iwad, const char *args)
+{
+ FILE *fstream;
+
+ fstream = fopen(RESPONSE_FILE, "w");
+
+ if (iwad != NULL)
+ {
+ fprintf(fstream, "-iwad \"%s\"", iwad);
+ }
+
+ if (args != NULL)
+ {
+ fprintf(fstream, "%s", args);
+ }
+
+ fclose(fstream);
+}
+
+static void DoExec(const char *executable, const char *iwad, const char *args)
+{
+ char *argv[3];
+
+ argv[0] = malloc(strlen(executable_path) + strlen(executable) + 3);
+ sprintf(argv[0], "%s/%s", executable_path, executable);
+
+ if (iwad != NULL || args != NULL)
+ {
+ WriteResponseFile(iwad, args);
+
+ argv[1] = "@" RESPONSE_FILE;
+ argv[2] = NULL;
+ }
+ else
+ {
+ argv[1] = NULL;
+ }
+
+ execv(argv[0], argv);
+ exit(-1);
+}
+
+// Execute the specified executable contained in the same directory
+// as the launcher, with the specified arguments.
+
+void ExecuteProgram(const char *executable, const char *iwad, const char *args)
+{
+ pid_t childpid;
+ char *homedir;
+
+ childpid = fork();
+
+ if (childpid == 0)
+ {
+ signal(SIGCHLD, SIG_DFL);
+
+ // Change directory to home dir before launch, so that any demos
+ // are saved somewhere sensible.
+
+ homedir = getenv("HOME");
+
+ if (homedir != NULL)
+ {
+ chdir(homedir);
+ }
+
+ DoExec(executable, iwad, args);
+ }
+ else
+ {
+ signal(SIGCHLD, SIG_IGN);
+ }
+}
+
+// Write a sequence of commands that will display the specified message
+// via shell commands.
+
+static void WriteMessage(FILE *script, char *msg)
+{
+ char *p;
+
+ fprintf(script, "echo \"");
+
+ for (p=msg; *p != '\0'; ++p)
+ {
+ // Start new line?
+
+ if (*p == '\n')
+ {
+ fprintf(script, "\"\necho \"");
+ continue;
+ }
+
+ // Escaped character?
+
+ if (*p == '\\' || *p == '\"')
+ {
+ fprintf(script, "\\");
+ }
+
+ fprintf(script, "%c", *p);
+ }
+
+ fprintf(script, "\"\n");
+}
+
+// Open a terminal window with the PATH set appropriately, and DOOMWADPATH
+// set to the specified value.
+
+void OpenTerminalWindow(const char *doomwadpath)
+{
+ FILE *stream;
+
+ // Generate a shell script that sets the PATH to include the location
+ // where the Doom binaries are, and DOOMWADPATH to include the
+ // IWAD files that have been configured in the launcher interface.
+ // The script then deletes itself and starts a shell.
+
+ stream = fopen(TEMP_SCRIPT, "w");
+
+ fprintf(stream, "#!/bin/sh\n");
+ //fprintf(stream, "set -x\n");
+ fprintf(stream, "PATH=\"%s:$PATH\"\n", executable_path);
+ fprintf(stream, "DOOMWADPATH=\"%s\"\n", doomwadpath);
+ fprintf(stream, "export DOOMWADPATH\n");
+ fprintf(stream, "rm -f \"%s\"\n", TEMP_SCRIPT);
+
+ // Display a useful message:
+
+ fprintf(stream, "clear\n");
+ WriteMessage(stream,
+ "\n"
+ "This command line has the PATH variable configured so that you may\n"
+ "launch the game with whatever parameters you desire.\n"
+ "\n"
+ "For example:\n"
+ "\n"
+ " " PACKAGE_TARNAME " -iwad doom2.wad -file sid.wad -warp 1\n"
+ "\n"
+ "Type 'exit' to exit.\n");
+
+ fprintf(stream, "exec $SHELL\n");
+ fprintf(stream, "\n");
+
+ fclose(stream);
+
+ chmod(TEMP_SCRIPT, 0755);
+
+ // Tell the terminal to open a window to run the script.
+
+ [[NSWorkspace sharedWorkspace] openFile: @TEMP_SCRIPT
+ withApplication: @"Terminal"];
+}
+
--- /dev/null
+++ b/pkg/osx/GNUmakefile
@@ -1,0 +1,105 @@
+
+# Makefile for building the OS X launcher program and DMG package.
+# It is also possible to build and run the launcher under Unix
+# systems using GNUstep, although this is only here for development
+# and debugging purposes.
+
+include ../config.make
+
+STAGING_DIR=staging
+DMG=$(PACKAGE_TARNAME)-$(PACKAGE_VERSION).dmg
+
+TOPLEVEL=../..
+TOPLEVEL_DOCS=$(patsubst %,../../%,$(DOC_FILES))
+
+ifndef GNUSTEP_MAKEFILES
+
+# DMG file containing package:
+
+$(DMG) : $(STAGING_DIR)
+ rm -f $@
+ hdiutil create -volname "$(PACKAGE_STRING)" -srcdir $(STAGING_DIR) $@
+
+endif
+
+# Staging dir build for package:
+
+APP_DIR=$(STAGING_DIR)/$(PACKAGE_NAME).app
+
+# OS X and GNUstep apps have a slightly different internal structure:
+# OS X apps have their files within a containing "Contents" directory
+# that does not exist in GNUstep apps. Similarly, the binaries are
+# installed at the top level, rather than in a "MacOS" directory.
+# Finally, we must install a different Info.plist file.
+
+ifdef GNUSTEP_MAKEFILES
+APP_TOP_DIR=$(APP_DIR)
+APP_BIN_DIR=$(APP_DIR)
+SRC_INFO_PLIST=Info-gnustep.plist
+else
+APP_TOP_DIR=$(APP_DIR)/Contents
+APP_BIN_DIR=$(APP_DIR)/Contents/MacOS
+SRC_INFO_PLIST=Info.plist
+endif
+
+$(STAGING_DIR): launcher $(TOPLEVEL_DOCS)
+ rm -rf $(STAGING_DIR)
+ mkdir $(STAGING_DIR)
+
+ cp $(TOPLEVEL_DOCS) "$(STAGING_DIR)"
+
+ mkdir -p "$(APP_TOP_DIR)"
+ cp -R Resources "$(APP_TOP_DIR)"
+ cp PkgInfo "$(APP_TOP_DIR)"
+ cp $(SRC_INFO_PLIST) "$(APP_TOP_DIR)"
+
+ mkdir -p "$(APP_BIN_DIR)"
+
+ cp launcher "$(APP_BIN_DIR)"
+ $(STRIP) "$(APP_BIN_DIR)/launcher"
+
+ ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)doom "$(APP_BIN_DIR)"
+ $(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)doom"
+ ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)heretic "$(APP_BIN_DIR)"
+ $(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)heretic"
+ ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)hexen "$(APP_BIN_DIR)"
+ $(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)hexen"
+ ./cp-with-libs $(TOPLEVEL)/src/$(PROGRAM_PREFIX)setup "$(APP_BIN_DIR)"
+ $(STRIP) "$(APP_BIN_DIR)/$(PROGRAM_PREFIX)setup"
+
+ find $(STAGING_DIR) -name .svn -delete -exec rm -rf {} \; || true
+
+clean : launcher_clean
+ rm -f $(DMG)
+ rm -rf $(STAGING_DIR)
+
+# Launcher build:
+
+CFLAGS = -Wall -I$(TOPLEVEL)
+
+# Are we building using gs_make?
+
+ifdef GNUSTEP_MAKEFILES
+CFLAGS += $(shell gnustep-config --objc-flags)
+LDFLAGS = $(shell gnustep-config --gui-libs)
+else
+LDFLAGS = -framework Cocoa
+endif
+
+LAUNCHER_OBJS= \
+ AppController.o \
+ Execute.o \
+ IWADController.o \
+ IWADLocation.o \
+ LauncherManager.o \
+ main.o
+
+launcher : $(LAUNCHER_OBJS)
+ $(CC) $(LDFLAGS) $(LAUNCHER_OBJS) -o $@
+
+%.o : %.m
+ $(CC) -c $(CFLAGS) $^ -o $@
+
+launcher_clean :
+ rm -f $(LAUNCHER_OBJS) launcher
+
--- /dev/null
+++ b/pkg/osx/IWADController.h
@@ -1,0 +1,54 @@
+/* ... */
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2009 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.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef LAUNCHER_IWADCONTROLLER_H
+#define LAUNCHER_IWADCONTROLLER_H
+
+#include <AppKit/AppKit.h>
+#include <AppKit/NSNibLoading.h>
+
+@interface IWADController : NSObject
+{
+ id iwadSelector;
+ id configWindow;
+
+ id chex;
+ id doom1;
+ id doom2;
+ id plutonia;
+ id tnt;
+}
+
+- (void) closeConfigWindow: (id)sender;
+- (void) openConfigWindow: (id)sender;
+- (NSString *) getIWADLocation;
+- (void) awakeFromNib;
+- (BOOL) setDropdownList;
+- (void) setDropdownSelection;
+- (void) saveConfig;
+- (char *) doomWadPath;
+- (void) setEnvironment;
+
+@end
+
+#endif /* #ifndef LAUNCHER_IWADCONTROLLER_H */
+
--- /dev/null
+++ b/pkg/osx/IWADController.m
@@ -1,0 +1,347 @@
+/* ... */
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2009 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.
+//
+//-----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include <string.h>
+#include <AppKit/AppKit.h>
+#include "IWADController.h"
+#include "IWADLocation.h"
+
+typedef enum
+{
+ IWAD_DOOM1,
+ IWAD_DOOM2,
+ IWAD_TNT,
+ IWAD_PLUTONIA,
+ IWAD_CHEX,
+ NUM_IWAD_TYPES
+} IWAD;
+
+static NSString *IWADLabels[NUM_IWAD_TYPES] =
+{
+ @"Doom",
+ @"Doom II: Hell on Earth",
+ @"Final Doom: TNT: Evilution",
+ @"Final Doom: Plutonia Experiment",
+ @"Chex Quest"
+};
+
+static NSString *IWADFilenames[NUM_IWAD_TYPES + 1] =
+{
+ @"doom.wad",
+ @"doom2.wad",
+ @"tnt.wad",
+ @"plutonia.wad",
+ @"chex.wad",
+ @"undefined"
+};
+
+@implementation IWADController
+
+- (void) getIWADList: (IWADLocation **) iwadList
+{
+ iwadList[IWAD_DOOM1] = self->doom1;
+ iwadList[IWAD_DOOM2] = self->doom2;
+ iwadList[IWAD_TNT] = self->tnt;
+ iwadList[IWAD_PLUTONIA] = self->plutonia;
+ iwadList[IWAD_CHEX] = self->chex;
+}
+
+- (IWAD) getSelectedIWAD
+{
+ unsigned int i;
+
+ for (i=0; i<NUM_IWAD_TYPES; ++i)
+ {
+ if ([self->iwadSelector titleOfSelectedItem] == IWADLabels[i])
+ {
+ return i;
+ }
+ }
+
+ return NUM_IWAD_TYPES;
+}
+
+// Get the location of the selected IWAD.
+
+- (NSString *) getIWADLocation
+{
+ IWAD selectedIWAD;
+ IWADLocation *iwadList[NUM_IWAD_TYPES];
+
+ selectedIWAD = [self getSelectedIWAD];
+
+ if (selectedIWAD == NUM_IWAD_TYPES)
+ {
+ return nil;
+ }
+ else
+ {
+ [self getIWADList: iwadList];
+
+ return [iwadList[selectedIWAD] getLocation];
+ }
+}
+
+- (void) setIWADConfig
+{
+ IWADLocation *iwadList[NUM_IWAD_TYPES];
+ NSUserDefaults *defaults;
+ NSString *key;
+ NSString *value;
+ unsigned int i;
+
+ [self getIWADList: iwadList];
+
+ // Load IWAD filename paths
+
+ defaults = [NSUserDefaults standardUserDefaults];
+
+ for (i=0; i<NUM_IWAD_TYPES; ++i)
+ {
+ key = IWADFilenames[i];
+ value = [defaults stringForKey:key];
+
+ if (value != nil)
+ {
+ [iwadList[i] setLocation:value];
+ }
+ }
+}
+
+// On startup, set the selected item in the IWAD dropdown
+
+- (void) setDropdownSelection
+{
+ NSUserDefaults *defaults;
+ NSString *selected;
+ unsigned int i;
+
+ defaults = [NSUserDefaults standardUserDefaults];
+ selected = [defaults stringForKey: @"selected_iwad"];
+
+ if (selected == nil)
+ {
+ return;
+ }
+
+ // Find this IWAD in the filenames list, and select it.
+
+ for (i=0; i<NUM_IWAD_TYPES; ++i)
+ {
+ if ([selected isEqualToString:IWADFilenames[i]])
+ {
+ [self->iwadSelector selectItemWithTitle:IWADLabels[i]];
+ break;
+ }
+ }
+}
+
+// Set the dropdown list to include an entry for each IWAD that has
+// been configured. Returns true if at least one IWAD is configured.
+
+- (BOOL) setDropdownList
+{
+ IWADLocation *iwadList[NUM_IWAD_TYPES];
+ BOOL have_wads;
+ id location;
+ unsigned int i;
+ unsigned int enabled_wads;
+
+ // Build the new list.
+
+ [self getIWADList: iwadList];
+ [self->iwadSelector removeAllItems];
+
+ enabled_wads = 0;
+
+ for (i=0; i<NUM_IWAD_TYPES; ++i)
+ {
+ location = [iwadList[i] getLocation];
+
+ if (location != nil && [location length] > 0)
+ {
+ [self->iwadSelector addItemWithTitle: IWADLabels[i]];
+ ++enabled_wads;
+ }
+ }
+
+ // Enable/disable the dropdown depending on whether there
+ // were any configured IWADs.
+
+ have_wads = enabled_wads > 0;
+ [self->iwadSelector setEnabled: have_wads];
+
+ // Restore the old selection.
+
+ [self setDropdownSelection];
+
+ return have_wads;
+}
+
+- (void) saveConfig
+{
+ IWADLocation *iwadList[NUM_IWAD_TYPES];
+ IWAD selectedIWAD;
+ NSUserDefaults *defaults;
+ NSString *key;
+ NSString *value;
+ unsigned int i;
+
+ [self getIWADList: iwadList];
+
+ // Store all IWAD locations to user defaults.
+
+ defaults = [NSUserDefaults standardUserDefaults];
+
+ for (i=0; i<NUM_IWAD_TYPES; ++i)
+ {
+ key = IWADFilenames[i];
+ value = [iwadList[i] getLocation];
+
+ [defaults setObject:value forKey:key];
+ }
+
+ // Save currently selected IWAD.
+
+ selectedIWAD = [self getSelectedIWAD];
+ [defaults setObject:IWADFilenames[selectedIWAD]
+ forKey:@"selected_iwad"];
+}
+
+// Callback method invoked when the configuration button in the main
+// window is clicked.
+
+- (void) openConfigWindow: (id)sender
+{
+ if (![self->configWindow isVisible])
+ {
+ [self->configWindow makeKeyAndOrderFront: sender];
+ }
+}
+
+// Callback method invoked when the close button is clicked.
+
+- (void) closeConfigWindow: (id)sender
+{
+ [self->configWindow orderOut: sender];
+ [self saveConfig];
+ [self setDropdownList];
+}
+
+- (void) awakeFromNib
+{
+ [self->configWindow center];
+
+ // Set configuration for all IWADs from configuration file.
+
+ [self setIWADConfig];
+
+ // Populate the dropdown IWAD list.
+
+ if ([self setDropdownList])
+ {
+ [self setDropdownSelection];
+ }
+}
+
+// Generate a value to set for the DOOMWADPATH environment variable
+// that contains each of the configured IWAD files.
+
+- (char *) doomWadPath
+{
+ IWADLocation *iwadList[NUM_IWAD_TYPES];
+ NSString *location;
+ unsigned int i;
+ unsigned int len;
+ BOOL first;
+ char *env;
+
+ [self getIWADList: iwadList];
+
+ // Calculate length of environment string.
+
+ len = 0;
+
+ for (i=0; i<NUM_IWAD_TYPES; ++i)
+ {
+ location = [iwadList[i] getLocation];
+
+ if (location != nil && [location length] > 0)
+ {
+ len += [location length] + 1;
+ }
+ }
+
+ // Build string.
+
+ env = malloc(len);
+ strcpy(env, "");
+
+ first = YES;
+
+ for (i=0; i<NUM_IWAD_TYPES; ++i)
+ {
+ location = [iwadList[i] getLocation];
+
+ if (location != nil && [location length] > 0)
+ {
+ if (!first)
+ {
+ strcat(env, ":");
+ }
+
+ strcat(env, [location UTF8String]);
+ first = NO;
+ }
+ }
+
+ return env;
+}
+
+// Set the DOOMWADPATH environment variable to contain the path to each
+// of the configured IWAD files.
+
+- (void) setEnvironment
+{
+ char *doomwadpath;
+ char *env;
+
+ // Get the value for the path.
+
+ doomwadpath = [self doomWadPath];
+
+ env = malloc(strlen(doomwadpath) + 15);
+
+ sprintf(env, "DOOMWADPATH=%s", doomwadpath);
+
+ free(doomwadpath);
+
+ // Load into environment:
+
+ putenv(env);
+
+ //free(env);
+}
+
+@end
+
--- /dev/null
+++ b/pkg/osx/IWADLocation.h
@@ -1,0 +1,44 @@
+/* ... */
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2009 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.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef LAUNCHER_IWADLOCATION_H
+#define LAUNCHER_IWADLOCATION_H
+
+#include <AppKit/AppKit.h>
+
+#include "IWADController.h"
+
+@interface IWADLocation : NSObject
+{
+ IWADController *iwadController;
+
+ id locationConfigBox;
+}
+
+- (void) setButtonClicked: (id)sender;
+- (NSString *) getLocation;
+- (void) setLocation: (NSString *) value;
+
+@end
+
+#endif /* #ifndef LAUNCHER_IWADLOCATION_H */
+
--- /dev/null
+++ b/pkg/osx/IWADLocation.m
@@ -1,0 +1,74 @@
+/* ... */
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2009 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.
+//
+//-----------------------------------------------------------------------------
+
+#include <AppKit/AppKit.h>
+#include "IWADLocation.h"
+
+static id WAD_TYPES[] =
+{
+ @"wad", @"WAD"
+};
+
+@implementation IWADLocation
+
+- (void) setButtonClicked: (id)sender
+{
+ NSArray *wadTypes = [NSArray arrayWithObjects: WAD_TYPES count: 2];
+ NSOpenPanel *openPanel;
+ NSArray *filenames;
+ int result;
+
+ [wadTypes retain];
+
+ // Open a file selector for the new file.
+
+ openPanel = [NSOpenPanel openPanel];
+ [openPanel setTitle: @"Add IWAD file"];
+ [openPanel setCanChooseFiles: YES];
+ [openPanel setCanChooseDirectories: NO];
+
+ result = [openPanel runModalForTypes: wadTypes];
+
+ // If the "OK" button was clicked, add the new IWAD file to the list.
+
+ if (result == NSOKButton)
+ {
+ filenames = [openPanel filenames];
+ [self setLocation: [filenames lastObject]];
+
+ [self->iwadController saveConfig];
+ [self->iwadController setDropdownList];
+ }
+}
+
+- (NSString *) getLocation
+{
+ return [self->locationConfigBox stringValue];
+}
+
+- (void) setLocation: (NSString *) filename
+{
+ [self->locationConfigBox setStringValue: filename];
+}
+
+@end
+
--- /dev/null
+++ b/pkg/osx/Info-gnustep.plist.in
@@ -1,0 +1,36 @@
+{
+ ApplicationName = "@PACKAGE_NAME@";
+ ApplicationDescription = "@PACKAGE_SHORTDESC@";
+ ApplicationIcon = app.png;
+ ApplicationRelease = @PACKAGE_VERSION@;
+ ApplicationURL = "@PACKAGE_URL@";
+ Authors = (
+ "@PACKAGE_MAINTAINER@ <@PACKAGE_BUGREPORT@>"
+ );
+ Copyright = "@PACKAGE_COPYRIGHT@";
+ CopyrightDescription = "@PACKAGE_LICENSE@";
+ FullVersionID = @PACKAGE_VERSION@;
+ GSMainMarkupFile = "";
+ NSExecutable = "launcher";
+ NSIcon = app.png;
+ NSMainNibFile = launcher.nib;
+ NSPrincipalClass = NSApplication;
+ NSRole = Application;
+ NSTypes = (
+ {
+ NSHumanReadableName = "Doom WAD file";
+ NSUnixExtensions = ( wad );
+ NSRole = Viewer;
+ NSMimeTypes = (
+ "application/x-doom"
+ );
+ NSIcon = "wadfile.png";
+ },
+ {
+ NSHumanReadableName = "Dehacked patch";
+ NSUnixExtensions = ( deh );
+ NSRole = Viewer;
+ NSIcon = "wadfile.png";
+ }
+ );
+}
--- /dev/null
+++ b/pkg/osx/Info.plist.in
@@ -1,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleDisplayName</key>
+ <string>@PACKAGE_NAME@</string>
+ <key>CFBundleExecutable</key>
+ <string>launcher</string>
+ <key>CFBundleGetInfoString</key>
+ <string>@PACKAGE_STRING@</string>
+ <key>CFBundleIconFile</key>
+ <string>app.icns</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>@PACKAGE_NAME@</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>@PACKAGE_VERSION@</string>
+ <key>CFBundleVersion</key>
+ <string>@PACKAGE_VERSION@</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+ <key>NSMainNibFile</key>
+ <string>launcher</string>
+
+ <!-- file associations: -->
+
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>Doom WAD file</string>
+ <key>CFBundleTypeIconFile</key>
+ <string>wadfile.icns</string>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>wad</string>
+ </array>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>Dehacked patch</string>
+ <key>CFBundleTypeIconFile</key>
+ <string>wadfile.icns</string>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ <key>CFBundleTypeExtensions</key>
+ <array>
+ <string>deh</string>
+ </array>
+ </dict>
+ </array>
+</dict>
+</plist>
--- /dev/null
+++ b/pkg/osx/LauncherManager.h
@@ -1,0 +1,52 @@
+/* ... */
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2009 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.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef LAUNCHER_LAUNCHERMANAGER_H
+#define LAUNCHER_LAUNCHERMANAGER_H
+
+#include <AppKit/AppKit.h>
+#include <AppKit/NSNibLoading.h>
+#include "IWADController.h"
+
+@interface LauncherManager : NSObject
+{
+ IWADController *iwadController;
+
+ id launcherWindow;
+ id launchButton;
+
+ id commandLineArguments;
+ id packageLabel;
+}
+
+- (void) launch: (id)sender;
+- (void) runSetup: (id)sender;
+- (void) awakeFromNib;
+- (void) clearCommandLine;
+- (void) addFileToCommandLine: (NSString *) fileName
+ forArgument: (NSString *) args;
+- (void) openTerminal: (id) sender;
+
+@end
+
+#endif /* #ifndef LAUNCHER_LAUNCHERMANAGER_H */
+
--- /dev/null
+++ b/pkg/osx/LauncherManager.m
@@ -1,0 +1,338 @@
+/* ... */
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2009 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.
+//
+//-----------------------------------------------------------------------------
+
+#include <AppKit/AppKit.h>
+#include "Execute.h"
+#include "LauncherManager.h"
+#include "config.h"
+
+@implementation LauncherManager
+
+// Save configuration. Invoked when we launch the game or quit.
+
+- (void) saveConfig
+{
+ NSUserDefaults *defaults;
+
+ // Save IWAD configuration and selected IWAD.
+
+ [self->iwadController saveConfig];
+
+ // Save command line arguments.
+
+ defaults = [NSUserDefaults standardUserDefaults];
+ [defaults setObject:[self->commandLineArguments stringValue]
+ forKey:@"command_line_args"];
+}
+
+// Load configuration, invoked on startup.
+
+- (void) setConfig
+{
+ NSUserDefaults *defaults;
+ NSString *args;
+
+ defaults = [NSUserDefaults standardUserDefaults];
+
+ args = [defaults stringForKey:@"command_line_args"];
+
+ if (args != nil)
+ {
+ [self->commandLineArguments setStringValue:args];
+ }
+}
+
+// Get the next command line argument from the command line.
+// The position counter used to iterate over arguments is in 'pos'.
+// The index of the argument that was found is saved in arg_pos.
+
+static NSString *GetNextArgument(NSString *commandLine, int *pos, int *arg_pos)
+{
+ NSRange arg_range;
+
+ // Skip past any whitespace
+
+ while (*pos < [commandLine length]
+ && isspace([commandLine characterAtIndex: *pos]))
+ {
+ ++*pos;
+ }
+
+ if (*pos >= [commandLine length])
+ {
+ *arg_pos = *pos;
+ return nil;
+ }
+
+ // We are at the start of the argument. This may be a quoted
+ // string argument, or a "normal" one.
+
+ if ([commandLine characterAtIndex: *pos] == '\"')
+ {
+ // Quoted string, skip past first quote
+
+ ++*pos;
+
+ // Save start position:
+
+ *arg_pos = *pos;
+
+ while (*pos < [commandLine length]
+ && [commandLine characterAtIndex: *pos] != '\"')
+ {
+ ++*pos;
+ }
+
+ // Unexpected end of string?
+
+ if (*pos >= [commandLine length])
+ {
+ return nil;
+ }
+
+ arg_range = NSMakeRange(*arg_pos, *pos - *arg_pos);
+
+ // Skip past last quote
+
+ ++*pos;
+ }
+ else
+ {
+ // Normal argument
+
+ // Save position:
+
+ *arg_pos = *pos;
+
+ // Read until end:
+
+ while (*pos < [commandLine length]
+ && !isspace([commandLine characterAtIndex: *pos]))
+ {
+ ++*pos;
+ }
+
+ arg_range = NSMakeRange(*arg_pos, *pos - *arg_pos);
+ }
+
+ return [commandLine substringWithRange: arg_range];
+}
+
+// Given the specified command line argument, find the index
+// to insert the new file within the command line. Returns -1 if the
+// argument is not already within the arguments string.
+
+static int GetFileInsertIndex(NSString *commandLine, NSString *needle)
+{
+ NSString *arg;
+ int arg_pos;
+ int pos;
+
+ pos = 0;
+
+ // Find the command line parameter we are searching
+ // for (-merge, -deh, etc)
+
+ for (;;)
+ {
+ arg = GetNextArgument(commandLine, &pos, &arg_pos);
+
+ // Searched to end of string and never found?
+
+ if (arg == nil)
+ {
+ return -1;
+ }
+
+ if (![arg caseInsensitiveCompare: needle])
+ {
+ break;
+ }
+ }
+
+ // Now skip over existing files. For example, if we
+ // have -file foo.wad bar.wad, the new file should be appended
+ // to the end of the list.
+
+ for (;;)
+ {
+ arg = GetNextArgument(commandLine, &pos, &arg_pos);
+
+ // If we search to the end of the string now, it is fine;
+ // the new string should be added to the end of the command
+ // line. Otherwise, if we find an argument that begins
+ // with '-', it is a new command line parameter and the end
+ // of the list.
+
+ if (arg == nil || [arg characterAtIndex: 0] == '-')
+ {
+ break;
+ }
+ }
+
+ // arg_pos should now contain the offset to insert the new filename.
+
+ return arg_pos;
+}
+
+// Given the specified string, append a filename, quoted if necessary.
+
+static NSString *AppendQuotedFilename(NSString *str, NSString *fileName)
+{
+ int i;
+
+ // Search the filename for spaces, and quote if necessary.
+
+ for (i=0; i<[fileName length]; ++i)
+ {
+ if (isspace([fileName characterAtIndex: i]))
+ {
+ str = [str stringByAppendingString: @" \""];
+ str = [str stringByAppendingString: fileName];
+ str = [str stringByAppendingString: @"\" "];
+
+ return str;
+ }
+ }
+
+ str = [str stringByAppendingString: @" "];
+ str = [str stringByAppendingString: fileName];
+
+ return str;
+}
+
+// Clear out the existing command line options.
+// Invoked before the first file is added.
+
+- (void) clearCommandLine
+{
+ [self->commandLineArguments setStringValue: @""];
+}
+
+// Add a file to the command line to load with the game.
+
+- (void) addFileToCommandLine: (NSString *) fileName
+ forArgument: (NSString *) arg
+{
+ NSString *commandLine;
+ int insert_pos;
+
+ // Get the current command line
+
+ commandLine = [self->commandLineArguments stringValue];
+
+ // Find the location to insert the new filename:
+
+ insert_pos = GetFileInsertIndex(commandLine, arg);
+
+ // If position < 0, we should add the new argument and filename
+ // to the end. Otherwise, append the new filename to the existing
+ // list of files.
+
+ if (insert_pos < 0)
+ {
+ commandLine = [commandLine stringByAppendingString: @" "];
+ commandLine = [commandLine stringByAppendingString: arg];
+ commandLine = AppendQuotedFilename(commandLine, fileName);
+ }
+ else
+ {
+ NSString *start;
+ NSString *end;
+
+ // Divide existing command line in half:
+
+ start = [commandLine substringToIndex: insert_pos];
+ end = [commandLine substringFromIndex: insert_pos];
+
+ // Construct new command line:
+
+ commandLine = AppendQuotedFilename(start, fileName);
+ commandLine = [commandLine stringByAppendingString: @" "];
+ commandLine = [commandLine stringByAppendingString: end];
+ }
+
+ [self->commandLineArguments setStringValue: commandLine];
+}
+
+- (void) launch: (id)sender
+{
+ NSString *iwad;
+ NSString *args;
+
+ [self saveConfig];
+
+ iwad = [self->iwadController getIWADLocation];
+ args = [self->commandLineArguments stringValue];
+
+ if (iwad == nil)
+ {
+ NSRunAlertPanel(@"No IWAD selected",
+ @"You have not selected an IWAD (game) file.\n\n"
+ "You must configure and select a valid IWAD file "
+ "in order to launch the game.",
+ @"OK", nil, nil);
+ return;
+ }
+
+ ExecuteProgram(PACKAGE_TARNAME, [iwad UTF8String],
+ [args UTF8String]);
+ [NSApp terminate:sender];
+}
+
+// Invoked when the "Setup Tool" button is clicked, to run the setup tool:
+
+- (void) runSetup: (id)sender
+{
+ [self saveConfig];
+
+ [self->iwadController setEnvironment];
+ ExecuteProgram("chocolate-setup", NULL, NULL);
+}
+
+// Invoked when the "Terminal" option is selected from the menu, to open
+// a terminal window.
+
+- (void) openTerminal: (id) sender
+{
+ char *doomwadpath;
+
+ [self saveConfig];
+
+ doomwadpath = [self->iwadController doomWadPath];
+
+ OpenTerminalWindow(doomwadpath);
+
+ free(doomwadpath);
+}
+
+- (void) awakeFromNib
+{
+ [self->packageLabel setStringValue: @PACKAGE_STRING];
+ [self->launcherWindow setTitle: @PACKAGE_NAME " Launcher"];
+ [self->launcherWindow center];
+ [self->launcherWindow setDefaultButtonCell: [self->launchButton cell]];
+ [self setConfig];
+}
+
+@end
+
--- /dev/null
+++ b/pkg/osx/PkgInfo
@@ -1,0 +1,1 @@
+APPL????
binary files /dev/null b/pkg/osx/Resources/128x128.png differ
binary files /dev/null b/pkg/osx/Resources/app.icns differ
binary files /dev/null b/pkg/osx/Resources/app.png differ
--- /dev/null
+++ b/pkg/osx/Resources/launcher.nib/classes.nib
@@ -1,0 +1,47 @@
+{
+ IBClasses = (
+ {
+ CLASS = AppController;
+ LANGUAGE = ObjC;
+ OUTLETS = {launcherManager = id; };
+ SUPERCLASS = NSObject;
+ },
+ {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
+ {
+ ACTIONS = {closeConfigWindow = id; openConfigWindow = id; };
+ CLASS = IWADController;
+ LANGUAGE = ObjC;
+ OUTLETS = {
+ chex = id;
+ configWindow = id;
+ doom1 = id;
+ doom2 = id;
+ iwadSelector = id;
+ plutonia = id;
+ tnt = id;
+ };
+ SUPERCLASS = NSObject;
+ },
+ {
+ ACTIONS = {setButtonClicked = id; };
+ CLASS = IWADLocation;
+ LANGUAGE = ObjC;
+ OUTLETS = {locationConfigBox = id; };
+ SUPERCLASS = NSObject;
+ },
+ {
+ ACTIONS = {launch = id; openTerminal = id; runSetup = id; };
+ CLASS = LauncherManager;
+ LANGUAGE = ObjC;
+ OUTLETS = {
+ commandLineArguments = id;
+ iwadController = id;
+ launchButton = id;
+ launcherWindow = id;
+ packageLabel = id;
+ };
+ SUPERCLASS = NSObject;
+ }
+ );
+ IBVersion = 1;
+}
\ No newline at end of file
--- /dev/null
+++ b/pkg/osx/Resources/launcher.nib/info.nib
@@ -1,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBDocumentLocation</key>
+ <string>325 73 612 260 0 0 1440 878 </string>
+ <key>IBEditorPositions</key>
+ <dict>
+ <key>29</key>
+ <string>221 322 205 44 0 0 1440 878 </string>
+ </dict>
+ <key>IBFramework Version</key>
+ <string>446.1</string>
+ <key>IBOpenObjects</key>
+ <array>
+ <integer>29</integer>
+ <integer>21</integer>
+ <integer>227</integer>
+ </array>
+ <key>IBSystem Version</key>
+ <string>8S2167</string>
+</dict>
+</plist>
binary files /dev/null b/pkg/osx/Resources/launcher.nib/keyedobjects.nib differ
binary files /dev/null b/pkg/osx/Resources/wadfile.icns differ
binary files /dev/null b/pkg/osx/Resources/wadfile.png differ
--- /dev/null
+++ b/pkg/osx/cp-with-libs
@@ -1,0 +1,100 @@
+#!/bin/bash
+#
+# Copy a program to the specified destination, along
+# with libraries it depends upon.
+
+src_bin=$1
+dest_dir=$2
+
+# Returns true if the specified file is a dylib.
+
+is_dylib() {
+ case "$1" in
+ *.dylib)
+ true
+ ;;
+ *)
+ false
+ ;;
+ esac
+}
+
+# Returns true if the specified file is in a system location
+# (/System or /usr):
+
+is_sys_lib() {
+ case "$1" in
+ /System/*)
+ true
+ ;;
+ /usr/*)
+ true
+ ;;
+ *)
+ false
+ ;;
+ esac
+}
+
+# Install the specified file to the location in dest_dir, along with
+# any libraries it depends upon (recursively):
+
+install_with_deps() {
+ local src_file
+ local bin_name
+ local dest_file
+ local lib_name
+
+ src_file=$1
+ bin_name=$(basename "$src_file")
+ dest_file="$dest_dir/$bin_name"
+
+ # Already copied into the package? Don't copy again.
+ # Prevents endless recursion.
+
+ if [ -e "$dest_file" ]; then
+ return
+ fi
+
+ echo "Installing $bin_name..."
+
+ # Copy file into package.
+
+ cp "$src_file" "$dest_file"
+
+ # Copy libraries that this file depends on:
+
+ otool -L "$src_file" | tail -n +2 | sed 's/^.//; s/ (.*//' | while read; do
+
+ # Don't copy system libraries
+
+ if is_sys_lib "$REPLY"; then
+ continue
+ fi
+
+ #echo " - $bin_name depends on $REPLY"
+
+ # Copy this library into the package, and:
+ # recursively install any libraries that _this_ library depends on:
+
+ install_with_deps "$REPLY"
+
+ # Change destination binary to depend on the
+ # copy inside the package:
+
+ lib_name=$(basename "$REPLY")
+ install_name_tool -change "$REPLY" "@executable_path/$lib_name" \
+ "$dest_file"
+ done
+
+ # If this is a library that we have installed, change its id:
+
+ if is_dylib "$dest_file"; then
+ install_name_tool -id "@executable_path/$bin_name" "$dest_file"
+ fi
+}
+
+# Install the file, and recursively install any libraries:
+
+install_with_deps "$src_bin"
+
--- /dev/null
+++ b/pkg/osx/main.m
@@ -1,0 +1,32 @@
+/* ... */
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2009 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.
+//
+//-----------------------------------------------------------------------------
+
+#include <AppKit/AppKit.h>
+#include "Execute.h"
+
+int main(int argc, const char *argv[])
+{
+ SetProgramLocation(argv[0]);
+
+ return NSApplicationMain (argc, argv);
+}
+
--- /dev/null
+++ b/pkg/win32/GNUmakefile
@@ -1,0 +1,34 @@
+
+include ../config.make
+
+TOPLEVEL=../..
+
+EXE_FILES=$(TOPLEVEL)/src/$(PROGRAM_PREFIX)doom.exe \
+ $(TOPLEVEL)/src/$(PROGRAM_PREFIX)heretic.exe \
+ $(TOPLEVEL)/src/$(PROGRAM_PREFIX)hexen.exe \
+ $(TOPLEVEL)/src/$(PROGRAM_PREFIX)server.exe \
+ $(TOPLEVEL)/src/$(PROGRAM_PREFIX)setup.exe
+
+DLL_FILES=$(TOPLEVEL)/src/SDL.dll \
+ $(TOPLEVEL)/src/SDL_mixer.dll \
+ $(TOPLEVEL)/src/SDL_net.dll
+
+ZIP=$(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-win32.zip
+
+$(ZIP) : staging
+ zip -j -r $@ staging/
+
+staging: $(EXE_FILES) $(DLL_FILES) $(patsubst %,../../%,$(DOC_FILES))
+ rm -rf staging
+ mkdir staging
+ cp $(EXE_FILES) $(DLL_FILES) staging/
+ $(STRIP) staging/*.exe
+ for f in $(DOC_FILES); do \
+ cp $(TOPLEVEL)/$$f staging/$$f.txt; \
+ unix2dos staging/$$f.txt; \
+ done
+
+clean:
+ rm -f $(ZIP)
+ rm -rf staging
+
--- a/pkg/win32/GNUmakefile.am
+++ /dev/null
@@ -1,37 +1,0 @@
-
-TOPLEVEL=../..
-
-EXE_FILES=$(TOPLEVEL)/src/@[email protected] \
- $(TOPLEVEL)/src/@[email protected] \
- $(TOPLEVEL)/src/@[email protected] \
- $(TOPLEVEL)/src/@[email protected] \
- $(TOPLEVEL)/src/@[email protected]
-
-DLL_FILES=$(TOPLEVEL)/src/SDL.dll \
- $(TOPLEVEL)/src/SDL_mixer.dll \
- $(TOPLEVEL)/src/SDL_net.dll
-
-DOC_FILES=README \
- COPYING \
- ChangeLog \
- NEWS \
- BUGS \
- CMDLINE \
- HH-TODO \
- TODO
-
-noinst_DATA=@PACKAGE_TARNAME@-@[email protected]
-
-@PACKAGE_TARNAME@-@[email protected] : staging
- zip -j -r $@ staging/
-
-staging: $(EXE_FILES) $(DLL_FILES) $(patsubst %,../../%,$(DOC_FILES))
- rm -rf staging
- mkdir staging
- cp $(EXE_FILES) $(DLL_FILES) staging/
- $(STRIP) staging/*.exe
- for f in $(DOC_FILES); do \
- cp $(TOPLEVEL)/$$f staging/$$f.txt; \
- unix2dos staging/$$f.txt; \
- done
-
--- /dev/null
+++ b/pkg/wince/GNUmakefile
@@ -1,0 +1,35 @@
+
+include ../config.make
+
+# Doom:
+
+DOOM_CAB=$(PROGRAM_PREFIX)doom-$(PACKAGE_VERSION).cab
+DOOM_CFG=doom-cab.cfg
+DOOM_DEPS=$(shell ./wince-cabgen -d $(DOOM_CFG))
+
+# Heretic:
+
+HERETIC_CAB=$(PROGRAM_PREFIX)heretic-$(PACKAGE_VERSION).cab
+HERETIC_CFG=heretic-cab.cfg
+HERETIC_DEPS=$(shell ./wince-cabgen -d $(HERETIC_CFG))
+
+# Hexen:
+
+HEXEN_CAB=$(PROGRAM_PREFIX)hexen-$(PACKAGE_VERSION).cab
+HEXEN_CFG=hexen-cab.cfg
+HEXEN_DEPS=$(shell ./wince-cabgen -d $(HEXEN_CFG))
+
+all: $(DOOM_CAB) $(HERETIC_CAB) $(HEXEN_CAB)
+
+$(DOOM_CAB) : $(DOOM_CFG) $(DOOM_DEPS)
+ ./wince-cabgen $< $@
+
+$(HERETIC_CAB) : $(HERETIC_CFG) $(HERETIC_DEPS)
+ ./wince-cabgen $< $@
+
+$(HEXEN_CAB) : $(HEXEN_CFG) $(HEXEN_DEPS)
+ ./wince-cabgen $< $@
+
+clean:
+ rm -f $(DOOM_CAB) $(HERETIC_CAB) $(HEXEN_CAB)
+
--- a/pkg/wince/GNUmakefile.am
+++ /dev/null
@@ -1,30 +1,0 @@
-
-# Doom:
-
-DOOM_CAB=chocolate-doom-@[email protected]
-DOOM_CFG=doom-cab.cfg
-DOOM_DEPS=$(shell ./wince-cabgen -d $(DOOM_CFG))
-
-$(DOOM_CAB) : $(DOOM_CFG) $(DOOM_DEPS)
- ./wince-cabgen $< $@
-
-# Heretic:
-
-HERETIC_CAB=chocolate-heretic-@[email protected]
-HERETIC_CFG=heretic-cab.cfg
-HERETIC_DEPS=$(shell ./wince-cabgen -d $(HERETIC_CFG))
-
-$(HERETIC_CAB) : $(HERETIC_CFG) $(HERETIC_DEPS)
- ./wince-cabgen $< $@
-
-# Hexen:
-
-HEXEN_CAB=chocolate-hexen-@[email protected]
-HEXEN_CFG=hexen-cab.cfg
-HEXEN_DEPS=$(shell ./wince-cabgen -d $(HEXEN_CFG))
-
-$(HEXEN_CAB) : $(HEXEN_CFG) $(HEXEN_DEPS)
- ./wince-cabgen $< $@
-
-noinst_DATA = $(DOOM_CAB) $(HERETIC_CAB) $(HEXEN_CAB)
-
--- /dev/null
+++ b/rpm.spec.in
@@ -1,0 +1,59 @@
+
+Name: @PACKAGE@
+Summary: @PACKAGE_SHORTDESC@
+Version: @VERSION@
+Release: 1
+Source: http://mesh.dl.sourceforge.net/project/chocolate-doom/@PACKAGE@/@VERSION@/@PACKAGE@-@[email protected]
+URL: @PACKAGE_URL@
+Group: Amusements/Games
+BuildRoot: /var/tmp/@PACKAGE@-buildroot
+License: @PACKAGE_LICENSE@
+Packager: @PACKAGE_MAINTAINER@ <@PACKAGE_BUGREPORT@>
+Prefix: %{_prefix}
+Autoreq: 0
+Requires: libSDL-1.2.so.0, libSDL_mixer-1.2.so.0, libSDL_net-1.2.so.0
+
+%description
+%(sed -n "/==/ q; p " < README)
+
+See @PACKAGE_URL@ for more information.
+
+%prep
+rm -rf $RPM_BUILD_ROOT
+
+%setup -q
+
+%build
+./configure \
+ --prefix=/usr \
+ --exec-prefix=/usr \
+ --bindir=/usr/bin \
+ --sbindir=/usr/sbin \
+ --sysconfdir=/etc \
+ --datadir=/usr/share \
+ --includedir=/usr/include \
+ --libdir=/usr/lib \
+ --libexecdir=/usr/lib \
+ --localstatedir=/var/lib \
+ --sharedstatedir=/usr/com \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info
+make
+
+%install
+%makeinstall
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%doc %{_mandir}/man5/*
+%doc %{_mandir}/man6/*
+%doc NEWS
+%doc AUTHORS
+%doc README
+%doc COPYING
+%doc CMDLINE
+%doc BUGS
+/usr/games/*
+
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -5,3 +5,5 @@
chocolate-doom
chocolate-server
*.exe
+tags
+TAGS
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -51,6 +51,7 @@
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 @@
# 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_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 @@
@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 @@
@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 @@
if HAVE_PYTHON
-icon.c : $(top_builddir)/data/doom.ico
+icon.c : $(top_builddir)/data/doom8.ico
$(top_builddir)/data/convert-icon $^ $@
endif
--- a/src/d_iwad.c
+++ b/src/d_iwad.c
@@ -331,44 +331,85 @@
#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);
+ filename = CheckDirectoryHasIWAD(dir, DEH_String(iwads[i].name));
- if (!strcmp(dir, "."))
+ if (filename != NULL)
{
- strcpy(filename, iwadname);
- }
- else
- {
- sprintf(filename, "%s%c%s", dir, DIR_SEPARATOR, iwadname);
- }
-
- if (M_FileExists(filename))
- {
*mission = iwads[i].mission;
return filename;
}
-
- free(filename);
}
return NULL;
@@ -529,7 +570,6 @@
{
char *buf;
int i;
- boolean exists;
// Absolute path?
@@ -544,14 +584,21 @@
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;
}
--- /dev/null
+++ b/src/deh_defs.h
@@ -1,0 +1,68 @@
+// 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 */
+
+
--- /dev/null
+++ b/src/deh_io.c
@@ -1,0 +1,211 @@
+// 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");
+}
+
+
--- /dev/null
+++ b/src/deh_io.h
@@ -1,0 +1,40 @@
+// 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 */
+
--- /dev/null
+++ b/src/deh_main.c
@@ -1,0 +1,384 @@
+// 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"
+
+extern deh_section_t *deh_section_types[];
+extern char *deh_signatures[];
+
+// 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;
+
+void DEH_Checksum(md5_digest_t digest)
+{
+ md5_context_t md5_context;
+ unsigned int i;
+
+ MD5_Init(&md5_context);
+
+ for (i=0; deh_section_types[i] != NULL; ++i)
+ {
+ if (deh_section_types[i]->md5_hash != NULL)
+ {
+ deh_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; deh_section_types[i] != NULL; ++i)
+ {
+ if (deh_section_types[i]->init != NULL)
+ {
+ deh_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; deh_section_types[i] != NULL; ++i)
+ {
+ if (!strcasecmp(deh_section_types[i]->name, name))
+ {
+ return deh_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; deh_signatures[i] != NULL; ++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;
+ }
+ }
+}
+
+
--- /dev/null
+++ b/src/deh_main.h
@@ -1,0 +1,54 @@
+// 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 */
+
--- /dev/null
+++ b/src/deh_mapping.c
@@ -1,0 +1,133 @@
+// 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;
+ }
+ }
+}
+
--- /dev/null
+++ b/src/deh_mapping.h
@@ -1,0 +1,90 @@
+// 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 */
+
--- /dev/null
+++ b/src/deh_text.c
@@ -1,0 +1,127 @@
+// 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,
+};
+
--- a/src/doom/.gitignore
+++ b/src/doom/.gitignore
@@ -5,3 +5,5 @@
chocolate-doom
chocolate-server
*.exe
+tags
+TAGS
--- a/src/doom/Makefile.am
+++ b/src/doom/Makefile.am
@@ -63,15 +63,11 @@
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
--- a/src/doom/deh_defs.h
+++ /dev/null
@@ -1,68 +1,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 */
-
-
--- /dev/null
+++ b/src/doom/deh_doom.c
@@ -1,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
+};
+
--- a/src/doom/deh_io.c
+++ /dev/null
@@ -1,211 +1,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");
-}
-
-
--- a/src/doom/deh_io.h
+++ /dev/null
@@ -1,40 +1,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 */
-
--- a/src/doom/deh_main.c
+++ /dev/null
@@ -1,423 +1,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;
- }
- }
-}
-
-
--- a/src/doom/deh_main.h
+++ /dev/null
@@ -1,54 +1,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 */
-
--- a/src/doom/deh_mapping.c
+++ /dev/null
@@ -1,133 +1,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;
- }
- }
-}
-
--- a/src/doom/deh_mapping.h
+++ /dev/null
@@ -1,90 +1,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 */
-
--- a/src/doom/deh_text.c
+++ /dev/null
@@ -1,127 +1,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,
-};
-
--- a/src/doom/g_game.c
+++ b/src/doom/g_game.c
@@ -588,10 +588,20 @@
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;
}
}
--- 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 @@
"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 @@
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 @@
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,
--- a/src/doom/p_map.c
+++ b/src/doom/p_map.c
@@ -885,7 +885,17 @@
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 @@
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)
--- a/src/doom/p_setup.c
+++ b/src/doom/p_setup.c
@@ -167,6 +167,7 @@
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 @@
{
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 @@
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);
--- a/src/doom/p_sight.c
+++ b/src/doom/p_sight.c
@@ -173,7 +173,7 @@
continue;
line->validcount = validcount;
-
+
v1 = line->v1;
v2 = line->v2;
s1 = P_DivlineSide (v1->x,v1->y, &strace);
@@ -193,6 +193,14 @@
// line isn't crossed?
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?
--- 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_mypos = CHEAT("idmypos", 0);
-//
-extern char* mapnames[];
-
-
//
// STATUS BAR CODE
//
@@ -984,6 +977,17 @@
palette = RADIATIONPAL;
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)
{
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -503,6 +503,7 @@
{
if (initialized)
{
+ SDL_SetCursor(cursors[1]);
SDL_ShowCursor(1);
SDL_WM_GrabInput(SDL_GRAB_OFF);
--- 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;
+ unsigned int buffer = time & 0x7F;
+ byte writeval;
- while ((time >>= 7) != 0)
- {
- buffer <<= 8;
- buffer |= ((time & 0x7F) | 0x80);
- }
+ while ((time >>= 7) != 0)
+ {
+ buffer <<= 8;
+ buffer |= ((time & 0x7F) | 0x80);
+ }
- for (;;)
- {
- writeval = (byte)(buffer & 0xFF);
+ for (;;)
+ {
+ writeval = (byte)(buffer & 0xFF);
- if (mem_fwrite(&writeval, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (mem_fwrite(&writeval, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- ++tracksize;
+ ++tracksize;
- if ((buffer & 0x80) != 0)
- {
- buffer >>= 8;
- }
- else
- {
- queuedtime = 0;
- return false;
- }
- }
+ 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;
+ byte working = midi_presskey | 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;
- }
-
- working = velocity & 0x7F;
-
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- tracksize += 3;
+ working = velocity & 0x7F;
- return false;
+ 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;
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- return false;
+ 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 (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 = control & 0x7F;
+ working = control & 0x7F;
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
- // Quirk in vanilla DOOM? MUS controller values should be
- // 7-bit, not 8-bit.
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- working = value;// & 0x7F;
+ // Quirk in vanilla DOOM? MUS controller values should be
+ // 7-bit, not 8-bit.
- // Fix on said quirk to stop MIDI players from complaining that
- // the value is out of range:
+ working = value;// & 0x7F;
- if (working & 0x80)
- {
- working = 0x7F;
- }
+ // Fix on said quirk to stop MIDI players from complaining that
+ // the value is out of range:
- if (mem_fwrite(&working, 1, 1, midioutput) != 1)
- {
- return true;
- }
+ if (working & 0x80)
+ {
+ working = 0x7F;
+ }
- tracksize += 3;
+ if (mem_fwrite(&working, 1, 1, midioutput) != 1)
+ {
+ return true;
+ }
- return false;
+ tracksize += 3;
+
+ 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;
+ int result;
+ int max;
+ int i;
- 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);
+ // Find the current highest-allocated channel.
- 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);
- }
+ max = -1;
- return result;
+ 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;
-
+ // 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;
- // 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;
- // Grab the header
+ // Temp working byte
+ byte working;
+ // Used in building up time delays
+ unsigned int timedelay;
- if (!read_musheader(musinput, &musfileheader))
- {
- return true;
- }
+ // Initialise channel map to mark all channels as unused.
+ for (channel=0; channel<NUM_CHANNELS; ++channel)
+ {
+ channel_map[channel] = -1;
+ }
+
+ // Grab the header
+
+ 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;
- }
+ // 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...
+ // 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;
+ mem_fwrite(midiheader, 1, sizeof(midiheader), midioutput);
+ tracksize = 0;
- // Now, process the MUS file:
- while (!hitscoreend)
- {
- // Handle a block of events:
+ // Now, process the MUS file:
+ while (!hitscoreend)
+ {
+ // Handle a block of events:
- while (!hitscoreend)
- {
- // Fetch channel number and event code:
+ while (!hitscoreend)
+ {
+ // Fetch channel number and event code:
- if (mem_fread(&eventdescriptor, 1, 1, musinput) != 1)
- {
- return true;
- }
+ if (mem_fread(&eventdescriptor, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
- channel = eventdescriptor & 0x0F;
- event = eventdescriptor & 0x70;
+ channel = GetMIDIChannel(eventdescriptor & 0x0F);
+ event = eventdescriptor & 0x70;
- // Swap channels 15 and 9.
- // MIDI channel 9 = percussion.
- // MUS channel 15 = percussion.
+ switch (event)
+ {
+ case mus_releasekey:
+ if (mem_fread(&key, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
- 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 (WriteReleaseKey(channel, key, midioutput))
+ {
+ return true;
+ }
- if (midi_writereleasekey(channel, key, midioutput))
- {
- return true;
- }
+ break;
- break;
-
- case mus_presskey:
- if (mem_fread(&key, 1, 1, musinput) != 1)
- {
- return true;
- }
+ 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;
- }
+ if (key & 0x80)
+ {
+ if (mem_fread(&channelvelocities[channel], 1, 1, musinput) != 1)
+ {
+ return true;
+ }
- channelvelocities[channel] &= 0x7F;
- }
+ channelvelocities[channel] &= 0x7F;
+ }
- if (midi_writepresskey(channel, key, channelvelocities[channel], midioutput))
- {
- return true;
- }
+ if (WritePressKey(channel, key,
+ channelvelocities[channel], midioutput))
+ {
+ return true;
+ }
- break;
+ break;
- case mus_pitchwheel:
- if (mem_fread(&key, 1, 1, musinput) != 1)
- {
- break;
- }
- if (midi_writepitchwheel(channel, (short)(key * 64), midioutput))
- {
- return true;
- }
+ 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;
- }
+ break;
- if (midi_writechangecontroller_valueless(channel, mus2midi_translation[controllernumber], midioutput))
- {
- return true;
- }
+ case mus_systemevent:
+ if (mem_fread(&controllernumber, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
+ if (controllernumber < 10 || controllernumber > 14)
+ {
+ return true;
+ }
- break;
-
- case mus_changecontroller:
- if (mem_fread(&controllernumber, 1, 1, musinput) != 1)
- {
- return true;
- }
+ if (WriteChangeController_Valueless(channel,
+ controller_map[controllernumber],
+ midioutput))
+ {
+ return true;
+ }
- if (mem_fread(&controllervalue, 1, 1, musinput) != 1)
- {
- return true;
- }
+ break;
- if (controllernumber == 0)
- {
- if (midi_writechangepatch(channel, controllervalue, midioutput))
- {
- return true;
- }
- }
- else
- {
- if (controllernumber < 1 || controllernumber > 9)
- {
- return true;
- }
+ case mus_changecontroller:
+ if (mem_fread(&controllernumber, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
- if (midi_writechangecontroller_valued(channel, mus2midi_translation[controllernumber], controllervalue, midioutput))
- {
- return true;
- }
- }
+ if (mem_fread(&controllervalue, 1, 1, musinput) != 1)
+ {
+ return true;
+ }
- break;
-
- case mus_scoreend:
- hitscoreend = 1;
- break;
+ if (controllernumber == 0)
+ {
+ if (WriteChangePatch(channel, controllervalue,
+ midioutput))
+ {
+ return true;
+ }
+ }
+ else
+ {
+ if (controllernumber < 1 || controllernumber > 9)
+ {
+ return true;
+ }
- default:
- return true;
- break;
- }
+ if (WriteChangeController_Valued(channel,
+ controller_map[controllernumber],
+ controllervalue,
+ midioutput))
+ {
+ return true;
+ }
+ }
- 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;
- }
+ break;
- timedelay = timedelay * 128 + (working & 0x7F);
- if ((working & 0x80) == 0)
- {
- break;
- }
- }
- queuedtime += timedelay;
- }
- }
+ case mus_scoreend:
+ hitscoreend = 1;
+ break;
- // End of track
- if (midi_writeendtrack(midioutput))
- {
- return true;
- }
+ default:
+ return true;
+ break;
+ }
- // Write the track size into the stream
- if (mem_fseek(midioutput, 18, MEM_SEEK_SET))
- {
- return true;
- }
+ 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;
+ }
- tracksizebuffer[0] = (tracksize >> 24) & 0xff;
- tracksizebuffer[1] = (tracksize >> 16) & 0xff;
- tracksizebuffer[2] = (tracksize >> 8) & 0xff;
- tracksizebuffer[3] = tracksize & 0xff;
+ timedelay = timedelay * 128 + (working & 0x7F);
+ if ((working & 0x80) == 0)
+ {
+ break;
+ }
+ }
+ queuedtime += timedelay;
+ }
+ }
- if (mem_fwrite(tracksizebuffer, 1, 4, midioutput) != 4)
- {
- return true;
- }
+ // End of track
+ if (WriteEndTrack(midioutput))
+ {
+ return true;
+ }
- return false;
+ // 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;
}
--- a/src/resource.rc.in
+++ b/src/resource.rc.in
@@ -13,7 +13,7 @@
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@"
}
--- 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
--- a/src/setup/Makefile.am
+++ b/src/setup/Makefile.am
@@ -27,3 +27,10 @@
EXTRA_DIST= \
setup_icon.c
+if HAVE_PYTHON
+
+setup_icon.c : $(top_builddir)/data/setup8.ico
+ $(top_builddir)/data/convert-icon $^ $@
+
+endif
+
--- a/src/setup/execute.c
+++ b/src/setup/execute.c
@@ -172,29 +172,38 @@
static wchar_t *BuildCommandLine(const char *program, const char *arg)
{
+ wchar_t exe_path[MAX_PATH];
wchar_t *result;
- char *sep;
+ wchar_t *sep;
- result = calloc(strlen(myargv[0]) + strlen(program) + strlen(arg) + 6,
+ // Get the path to this .exe file.
+
+ GetModuleFileNameW(NULL, exe_path, MAX_PATH);
+
+ // 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 @@
execvp(argv[0], (char **) argv);
- exit(-1);
+ exit(0x80);
}
else
{
@@ -299,7 +308,7 @@
waitpid(childpid, &result, 0);
- if (WIFEXITED(result))
+ if (WIFEXITED(result) && WEXITSTATUS(result) != 0x80)
{
return WEXITSTATUS(result);
}
--- a/src/strife/.gitignore
+++ b/src/strife/.gitignore
@@ -5,3 +5,5 @@
chocolate-doom
chocolate-server
*.exe
+tags
+TAGS
--- a/src/strife/Makefile.am
+++ b/src/strife/Makefile.am
@@ -63,15 +63,11 @@
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
--- a/src/strife/deh_defs.h
+++ /dev/null
@@ -1,68 +1,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 */
-
-
--- a/src/strife/deh_io.c
+++ /dev/null
@@ -1,211 +1,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");
-}
-
-
--- a/src/strife/deh_io.h
+++ /dev/null
@@ -1,40 +1,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 */
-
--- a/src/strife/deh_main.c
+++ /dev/null
@@ -1,423 +1,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;
- }
- }
-}
-
-
--- a/src/strife/deh_main.h
+++ /dev/null
@@ -1,54 +1,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 */
-
--- a/src/strife/deh_mapping.c
+++ /dev/null
@@ -1,133 +1,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;
- }
- }
-}
-
--- a/src/strife/deh_mapping.h
+++ /dev/null
@@ -1,90 +1,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 */
-
--- /dev/null
+++ b/src/strife/deh_strife.c
@@ -1,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
+};
+
--- a/src/strife/deh_text.c
+++ /dev/null
@@ -1,127 +1,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,
-};
-
--- a/src/strife/g_game.c
+++ b/src/strife/g_game.c
@@ -588,10 +588,20 @@
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;
}
}
--- 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 @@
"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 @@
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 @@
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,
--- a/src/strife/p_map.c
+++ b/src/strife/p_map.c
@@ -885,7 +885,17 @@
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 @@
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)
--- a/src/strife/p_setup.c
+++ b/src/strife/p_setup.c
@@ -167,6 +167,7 @@
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 @@
{
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 @@
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);
--- a/src/strife/p_sight.c
+++ b/src/strife/p_sight.c
@@ -173,7 +173,7 @@
continue;
line->validcount = validcount;
-
+
v1 = line->v1;
v2 = line->v2;
s1 = P_DivlineSide (v1->x,v1->y, &strace);
@@ -193,6 +193,14 @@
// line isn't crossed?
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?
--- 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_mypos = CHEAT("idmypos", 0);
-//
-extern char* mapnames[];
-
-
//
// STATUS BAR CODE
//
@@ -984,6 +977,17 @@
palette = RADIATIONPAL;
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)
{
--- a/textscreen/.gitignore
+++ b/textscreen/.gitignore
@@ -2,3 +2,5 @@
Makefile.in
.deps
*.a
+tags
+TAGS
--- a/textscreen/examples/.gitignore
+++ b/textscreen/examples/.gitignore
@@ -4,3 +4,5 @@
guitest
calculator
*.exe
+tags
+TAGS
--- a/textscreen/txt_sdl.c
+++ b/textscreen/txt_sdl.c
@@ -289,10 +289,10 @@
int x_end;
int y_end;
- x_end = LimitToRange(x + w, 0, TXT_SCREEN_W - 1);
- y_end = LimitToRange(y + h, 0, TXT_SCREEN_H - 1);
- x = LimitToRange(x, 0, TXT_SCREEN_W - 1);
- y = LimitToRange(y, 0, TXT_SCREEN_H - 1);
+ x_end = LimitToRange(x + w, 0, TXT_SCREEN_W);
+ y_end = LimitToRange(y + h, 0, TXT_SCREEN_H);
+ x = LimitToRange(x, 0, TXT_SCREEN_W);
+ y = LimitToRange(y, 0, TXT_SCREEN_H);
for (y1=y; y1<y_end; ++y1)
{
--- /dev/null
+++ b/wince/.gitignore
@@ -1,0 +1,5 @@
+Makefile
+Makefile.in
+.deps
+tags
+TAGS
--- a/wince/Makefile.am
+++ b/wince/Makefile.am
@@ -4,6 +4,7 @@
if WINDOWS_CE
libc_wince_a_SOURCES = \
+ libc_wince.h \
env.c env.h \
errno.c errno.h \
fileops.c fileops.h