commit 4767ddccafca1a1c50bc097284df1328d478882a
Merge: af48a630 aa35a71b
Author: Simon Howard <fraggle@gmail.com>
AuthorDate: Mon May 3 17:07:45 2010 +0000
Commit: Simon Howard <fraggle@gmail.com>
CommitDate: Mon May 3 17:07:45 2010 +0000
Merge from trunk.
Subversion-branch: /branches/raven-branch
Subversion-revision: 1931
NEWS | 24 ++++++
src/deh_str.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++++++++
src/deh_str.h | 9 +++
src/doom/am_map.c | 6 +-
src/doom/d_main.c | 34 ++++----
src/doom/d_net.c | 10 +--
src/doom/f_finale.c | 2 +-
src/doom/g_game.c | 4 +
src/doom/hu_stuff.c | 2 +-
src/doom/m_menu.c | 4 +-
src/doom/p_saveg.c | 24 +++++-
src/doom/p_saveg.h | 1 +
src/doom/p_setup.c | 4 +-
src/doom/st_stuff.c | 22 ++---
src/doom/wi_stuff.c | 47 +++++------
src/m_argv.c | 2 +-
src/net_client.c | 3 +-
17 files changed, 355 insertions(+), 70 deletions(-)
diff --cc src/deh_str.c
index 0baaa7e8,00000000..9bd429b6
mode 100644,000000..100644
--- a/src/deh_str.c
+++ b/src/deh_str.c
@@@ -1,181 -1,0 +1,408 @@@
+// 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 <stdlib.h>
+#include <string.h>
++#include <stdarg.h>
+
+#include "doomtype.h"
+#include "deh_str.h"
+
+#include "z_zone.h"
+
+typedef struct
+{
+ char *from_text;
+ char *to_text;
+} deh_substitution_t;
+
+static deh_substitution_t **hash_table = NULL;
+static int hash_table_entries;
+static int hash_table_length = -1;
+
+// This is the algorithm used by glib
+
+static unsigned int strhash(char *s)
+{
+ char *p = s;
+ unsigned int h = *p;
+
+ if (h)
+ {
+ for (p += 1; *p; p++)
+ h = (h << 5) - h + *p;
+ }
+
+ return h;
+}
+
+// Look up a string to see if it has been replaced with something else
+// This will be used throughout the program to substitute text
+
+char *DEH_String(char *s)
+{
+ int entry;
+
+ // Fallback if we have not initialized the hash table yet
+
+ if (hash_table_length < 0)
+ return s;
+
+ entry = strhash(s) % hash_table_length;
+
+ while (hash_table[entry] != NULL)
+ {
+ if (!strcmp(hash_table[entry]->from_text, s))
+ {
+ // substitution found!
+
+ return hash_table[entry]->to_text;
+ }
+
+ entry = (entry + 1) % hash_table_length;
+ }
+
+ // no substitution found
+
+ return s;
+}
+
+static void InitHashTable(void)
+{
+ // init hash table
+
+ hash_table_entries = 0;
+ hash_table_length = 16;
+ hash_table = Z_Malloc(sizeof(deh_substitution_t *) * hash_table_length,
+ PU_STATIC, NULL);
+ memset(hash_table, 0, sizeof(deh_substitution_t *) * hash_table_length);
+}
+
+static void DEH_AddToHashtable(deh_substitution_t *sub);
+
+static void IncreaseHashtable(void)
+{
+ deh_substitution_t **old_table;
+ int old_table_length;
+ int i;
+
+ // save the old table
+
+ old_table = hash_table;
+ old_table_length = hash_table_length;
+
+ // double the size
+
+ hash_table_length *= 2;
+ hash_table = Z_Malloc(sizeof(deh_substitution_t *) * hash_table_length,
+ PU_STATIC, NULL);
+ memset(hash_table, 0, sizeof(deh_substitution_t *) * hash_table_length);
+
+ // go through the old table and insert all the old entries
+
+ for (i=0; i<old_table_length; ++i)
+ {
+ if (old_table[i] != NULL)
+ {
+ DEH_AddToHashtable(old_table[i]);
+ }
+ }
+
+ // free the old table
+
+ Z_Free(old_table);
+}
+
+static void DEH_AddToHashtable(deh_substitution_t *sub)
+{
+ int entry;
+
+ // if the hash table is more than 60% full, increase its size
+
+ if ((hash_table_entries * 10) / hash_table_length > 6)
+ {
+ IncreaseHashtable();
+ }
+
+ // find where to insert it
+
+ entry = strhash(sub->from_text) % hash_table_length;
+
+ while (hash_table[entry] != NULL)
+ {
+ entry = (entry + 1) % hash_table_length;
+ }
+
+ hash_table[entry] = sub;
+ ++hash_table_entries;
+}
+
+void DEH_AddStringReplacement(char *from_text, char *to_text)
+{
+ deh_substitution_t *sub;
+
+ // Initialize the hash table if this is the first time
+
+ if (hash_table_length < 0)
+ {
+ InitHashTable();
+ }
+
+ sub = Z_Malloc(sizeof(*sub), PU_STATIC, 0);
+
+ sub->from_text = from_text;
+ sub->to_text = to_text;
+
+ DEH_AddToHashtable(sub);
+}
+
++typedef enum
++{
++ FORMAT_ARG_INVALID,
++ FORMAT_ARG_INT,
++ FORMAT_ARG_FLOAT,
++ FORMAT_ARG_CHAR,
++ FORMAT_ARG_STRING,
++ FORMAT_ARG_PTR,
++ FORMAT_ARG_SAVE_POS
++} format_arg_t;
++
++// Get the type of a format argument.
++// We can mix-and-match different format arguments as long as they
++// are for the same data type.
++
++static format_arg_t FormatArgumentType(char c)
++{
++ switch (c)
++ {
++ case 'd': case 'i': case 'o': case 'u': case 'x': case 'X':
++ return FORMAT_ARG_INT;
++
++ case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
++ case 'a': case 'A':
++ return FORMAT_ARG_FLOAT;
++
++ case 'c': case 'C':
++ return FORMAT_ARG_CHAR;
++
++ case 's': case 'S':
++ return FORMAT_ARG_STRING;
++
++ case 'p':
++ return FORMAT_ARG_PTR;
++
++ case 'n':
++ return FORMAT_ARG_SAVE_POS;
++
++ default:
++ return FORMAT_ARG_INVALID;
++ }
++}
++
++// Given the specified string, get the type of the first format
++// string encountered.
++
++static format_arg_t NextFormatArgument(char **str)
++{
++ format_arg_t argtype;
++
++ // Search for the '%' starting the next string.
++
++ while (**str != '\0')
++ {
++ if (**str == '%')
++ {
++ ++*str;
++
++ // Don't stop for double-%s.
++
++ if (**str != '%')
++ {
++ break;
++ }
++ }
++
++ ++*str;
++ }
++
++ // Find the type of the format string.
++
++ while (**str != '\0')
++ {
++ argtype = FormatArgumentType(**str);
++
++ if (argtype != FORMAT_ARG_INVALID)
++ {
++ ++*str;
++
++ return argtype;
++ }
++
++ ++*str;
++ }
++
++ // Stop searching, we have reached the end.
++
++ *str = NULL;
++
++ return FORMAT_ARG_INVALID;
++}
++
++// Check if the specified argument type is a valid replacement for
++// the original.
++
++static boolean ValidArgumentReplacement(format_arg_t original,
++ format_arg_t replacement)
++{
++ // In general, the original and replacement types should be
++ // identical. However, there are some cases where the replacement
++ // is valid and the types don't match.
++
++ // Characters can be represented as ints.
++
++ if (original == FORMAT_ARG_CHAR && replacement == FORMAT_ARG_INT)
++ {
++ return true;
++ }
++
++ // Strings are pointers.
++
++ if (original == FORMAT_ARG_STRING && replacement == FORMAT_ARG_PTR)
++ {
++ return true;
++ }
++
++ return original == replacement;
++}
++
++// Return true if the specified string contains no format arguments.
++
++static boolean ValidFormatReplacement(char *original, char *replacement)
++{
++ char *rover1;
++ char *rover2;
++ int argtype1, argtype2;
++
++ // Check each argument in turn and compare types.
++
++ rover1 = original; rover2 = replacement;
++
++ for (;;)
++ {
++ argtype1 = NextFormatArgument(&rover1);
++ argtype2 = NextFormatArgument(&rover2);
++
++ if (argtype2 == FORMAT_ARG_INVALID)
++ {
++ // No more arguments left to read from the replacement string.
++
++ break;
++ }
++ else if (argtype1 == FORMAT_ARG_INVALID)
++ {
++ // Replacement string has more arguments than the original.
++
++ return false;
++ }
++ else if (!ValidArgumentReplacement(argtype1, argtype2))
++ {
++ // Not a valid replacement argument.
++
++ return false;
++ }
++ }
++
++ return true;
++}
++
++// Get replacement format string, checking arguments.
++
++static char *FormatStringReplacement(char *s)
++{
++ char *repl;
++
++ repl = DEH_String(s);
++
++ if (!ValidFormatReplacement(s, repl))
++ {
++ printf("WARNING: Unsafe dehacked replacement provided for "
++ "printf format string: %s\n", s);
++
++ return s;
++ }
++
++ return repl;
++}
++
++// printf(), performing a replacement on the format string.
++
++void DEH_printf(char *fmt, ...)
++{
++ va_list args;
++ char *repl;
++
++ repl = FormatStringReplacement(fmt);
++
++ va_start(args, fmt);
++
++ vprintf(repl, args);
++
++ va_end(args);
++}
++
++// fprintf(), performing a replacement on the format string.
++
++void DEH_fprintf(FILE *fstream, char *fmt, ...)
++{
++ va_list args;
++ char *repl;
++
++ repl = FormatStringReplacement(fmt);
++
++ va_start(args, fmt);
++
++ vfprintf(fstream, repl, args);
++
++ va_end(args);
++}
++
++// snprintf(), performing a replacement on the format string.
++
++void DEH_snprintf(char *buffer, size_t len, char *fmt, ...)
++{
++ va_list args;
++ char *repl;
++
++ repl = FormatStringReplacement(fmt);
++
++ va_start(args, fmt);
++
++ vsnprintf(buffer, len, repl, args);
++
++ va_end(args);
++}
++
diff --cc src/deh_str.h
index 986536de,ae9ab917..06bcb420
--- a/src/deh_str.h
+++ b/src/deh_str.h
@@@ -24,23 -24,42 +24,32 @@@
//
//-----------------------------------------------------------------------------
+#ifndef DEH_STR_H
+#define DEH_STR_H
++#include <stdio.h>
+
-#include <string.h>
+#include "doomfeatures.h"
-int myargc;
-char** myargv;
+// Used to do dehacked text substitutions throughout the program
-// From doomdef.h -- no need to include it all!
-#ifdef _WIN32
-#define snprintf _snprintf
-#define vsnprintf _vsnprintf
-#define strcasecmp stricmp
-#define strncasecmp strnicmp
-#else
-#include <strings.h>
-#endif
+#ifdef FEATURE_DEHACKED
-//
-// M_CheckParm
-// Checks for the given parameter
-// in the program's command line arguments.
-// Returns the argument number (1 to argc-1)
-// or 0 if not present
-int M_CheckParm (char *check)
-{
- int i;
+char *DEH_String(char *s);
++void DEH_printf(char *fmt, ...);
++void DEH_fprintf(FILE *fstream, char *fmt, ...);
++void DEH_snprintf(char *buffer, size_t len, char *fmt, ...);
+void DEH_AddStringReplacement(char *from_text, char *to_text);
- for (i = 1;i<myargc;i++)
- {
- if ( !strcasecmp(check, myargv[i]) )
- return i;
- }
+
- return 0;
-}
+#else
+#define DEH_String(x) (x)
++#define DEH_printf printf
++#define DEH_fprintf fprintf
++#define DEH_snprintf snprintf
+#endif
+#endif /* #ifndef DEH_STR_H */
diff --cc src/doom/d_main.c
index c6099da9,671c4e9c..3fee8439
--- a/src/doom/d_main.c
+++ b/src/doom/d_main.c
@@@ -1066,9 -817,9 +1066,9 @@@ void D_DoomMain (void
// print banner
- PrintBanner(PACKAGE_STRING);
+ I_PrintBanner(PACKAGE_STRING);
- printf (DEH_String("Z_Init: Init zone memory allocation daemon. \n"));
+ DEH_printf("Z_Init: Init zone memory allocation daemon. \n");
Z_Init ();
#ifdef FEATURE_MULTIPLAYER
@@@ -1243,21 -970,167 +1243,21 @@@
}
// init subsystems
- printf(DEH_String("V_Init: allocate screens.\n"));
- V_Init();
+ DEH_printf("V_Init: allocate screens.\n");
+ V_Init ();
+ // Load configuration files before initialising other subsystems.
- printf(DEH_String("M_LoadDefaults: Load system defaults.\n"));
+ DEH_printf("M_LoadDefaults: Load system defaults.\n");
- M_ApplyPlatformDefaults();
- M_LoadDefaults (); // load before initing other systems
+ M_SetConfigFilenames("default.cfg", PROGRAM_PREFIX "doom.cfg");
+ D_BindVariables();
+ M_LoadDefaults();
+
+ // Save configuration at exit.
+ I_AtExit(M_SaveDefaults, false);
- printf (DEH_String("W_Init: Init WADfiles.\n"));
+ DEH_printf("W_Init: Init WADfiles.\n");
D_AddFile(iwadfile);
-
-#ifdef FEATURE_WAD_MERGE
-
- // Merged PWADs are loaded first, because they are supposed to be
- // modified IWADs.
-
- //!
- // @arg <files>
- // @category mod
- //
- // Simulates the behavior of deutex's -merge option, merging a PWAD
- // into the main IWAD. Multiple files may be specified.
- //
-
- p = M_CheckParm("-merge");
-
- if (p > 0)
- {
- for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
- {
- char *filename;
-
- filename = D_TryFindWADByName(myargv[p]);
-
- printf(" merging %s\n", filename);
- W_MergeFile(filename);
- }
- }
-
- // NWT-style merging:
-
- // NWT's -merge option:
-
- //!
- // @arg <files>
- // @category mod
- //
- // Simulates the behavior of NWT's -merge option. Multiple files
- // may be specified.
-
- p = M_CheckParm("-nwtmerge");
-
- if (p > 0)
- {
- for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
- {
- char *filename;
-
- filename = D_TryFindWADByName(myargv[p]);
-
- printf(" performing NWT-style merge of %s\n", filename);
- W_NWTDashMerge(filename);
- }
- }
-
- // Add flats
-
- //!
- // @arg <files>
- // @category mod
- //
- // Simulates the behavior of NWT's -af option, merging flats into
- // the main IWAD directory. Multiple files may be specified.
- //
-
- p = M_CheckParm("-af");
-
- if (p > 0)
- {
- for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
- {
- char *filename;
-
- filename = D_TryFindWADByName(myargv[p]);
-
- printf(" merging flats from %s\n", filename);
- W_NWTMergeFile(filename, W_NWT_MERGE_FLATS);
- }
- }
-
- //!
- // @arg <files>
- // @category mod
- //
- // Simulates the behavior of NWT's -as option, merging sprites
- // into the main IWAD directory. Multiple files may be specified.
- //
-
- p = M_CheckParm("-as");
-
- if (p > 0)
- {
- for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
- {
- char *filename;
-
- filename = D_TryFindWADByName(myargv[p]);
-
- printf(" merging sprites from %s\n", filename);
- W_NWTMergeFile(filename, W_NWT_MERGE_SPRITES);
- }
- }
-
- //!
- // @arg <files>
- // @category mod
- //
- // Equivalent to "-af <files> -as <files>".
- //
-
- p = M_CheckParm("-aa");
-
- if (p > 0)
- {
- for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
- {
- char *filename;
-
- filename = D_TryFindWADByName(myargv[p]);
-
- printf(" merging sprites and flats from %s\n", filename);
- W_NWTMergeFile(filename, W_NWT_MERGE_SPRITES | W_NWT_MERGE_FLATS);
- }
- }
-
-#endif
-
- //!
- // @arg <files>
- // @vanilla
- //
- // Load the specified PWAD files.
- //
-
- p = M_CheckParm ("-file");
- if (p)
- {
- // the parms after p are wadfile/lump names,
- // until end of parms or another - preceded parm
- modifiedgame = true; // homebrew levels
- while (++p != myargc && myargv[p][0] != '-')
- {
- char *filename;
-
- filename = D_TryFindWADByName(myargv[p]);
-
- D_AddFile(filename);
- }
- }
-
- // Debug:
-// W_PrintDirectory();
+ modifiedgame = W_ParseCommandLine();
// add any files specified on the command line with -file wadfile
// to the wad list
@@@ -1530,23 -1419,35 +1530,23 @@@
" floor textures. You may want to use the '-merge' command\n"
" line option instead of '-file'.\n");
}
-
- printf ("===========================================================================\n");
-
- PrintBanner(gamedescription);
-
-
- printf (
- "===========================================================================\n"
- " " PACKAGE_NAME " is free software, covered by the GNU General Public\n"
- " License. There is NO warranty; not even for MERCHANTABILITY or FITNESS\n"
- " FOR A PARTICULAR PURPOSE. You are welcome to change and distribute\n"
- " copies under certain conditions. See the source for more information.\n"
-
- "===========================================================================\n"
- );
+ I_PrintStartupBanner(gamedescription);
PrintDehackedBanners();
- printf (DEH_String("M_Init: Init miscellaneous info.\n"));
+ DEH_printf("M_Init: Init miscellaneous info.\n");
M_Init ();
- printf (DEH_String("R_Init: Init DOOM refresh daemon - "));
+ DEH_printf("R_Init: Init DOOM refresh daemon - ");
R_Init ();
- printf (DEH_String("\nP_Init: Init Playloop state.\n"));
+ DEH_printf("\nP_Init: Init Playloop state.\n");
P_Init ();
- printf (DEH_String("I_Init: Setting up machine state.\n"));
+ DEH_printf("I_Init: Setting up machine state.\n");
- I_Init ();
+ I_CheckIsScreensaver();
+ I_InitTimer();
+ I_InitJoystick();
#ifdef FEATURE_MULTIPLAYER
printf ("NET_Init: Init network subsystem.\n");
diff --cc src/doom/f_finale.c
index ece82b43,3f0082cb..dfbeafbe
--- a/src/doom/f_finale.c
+++ b/src/doom/f_finale.c
@@@ -663,10 -663,9 +663,10 @@@ void F_BunnyScroll (void
laststage = stage;
}
- sprintf (name, DEH_String("END%i"), stage);
+ DEH_snprintf(name, 10, "END%i", stage);
- V_DrawPatch ((SCREENWIDTH-13*8)/2, (SCREENHEIGHT-8*8)/2,0,
- W_CacheLumpName (name,PU_CACHE));
+ V_DrawPatch((SCREENWIDTH - 13 * 8) / 2,
+ (SCREENHEIGHT - 8 * 8) / 2,
+ W_CacheLumpName (name,PU_CACHE));
}
static void F_ArtScreenDrawer(void)
diff --cc src/doom/wi_stuff.c
index 83f5052f,7c0ba312..45c09343
--- a/src/doom/wi_stuff.c
+++ b/src/doom/wi_stuff.c
@@@ -1693,24 -1710,6 +1692,26 @@@ static void WI_loadUnloadData(load_call
callback(name, &bp[i]);
}
+ // Background image
+
+ if (gamemode == commercial)
+ {
- strcpy(name, DEH_String("INTERPIC"));
++ strncpy(name, DEH_String("INTERPIC"), 9);
++ name[8] = '\0';
+ }
+ else if (gamemode == retail && wbs->epsd == 3)
+ {
- strcpy(name, DEH_String("INTERPIC"));
++ strncpy(name, DEH_String("INTERPIC"), 9);
++ name[8] = '\0';
+ }
- else
++ else
+ {
- sprintf(name, DEH_String("WIMAP%d"), wbs->epsd);
++ DEH_snprintf(name, 9, "WIMAP%d", wbs->epsd);
+ }
-
++
+ // Draw backdrop and save to a temporary buffer
-
++
+ callback(name, &background);
}
static void WI_loadCallback(char *name, patch_t **variable)
@@@ -1720,9 -1719,12 +1721,9 @@@
void WI_loadData(void)
{
- char bg_lumpname[9];
- patch_t *bg;
-
if (gamemode == commercial)
{
- NUMCMAPS = 32;
+ NUMCMAPS = 32;
lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMCMAPS,
PU_STATIC, NULL);
}
diff --cc src/m_argv.c
index e2b551f1,7fc15863..79702e56
--- a/src/m_argv.c
+++ b/src/m_argv.c
@@@ -101,8 -89,8 +101,8 @@@ static void LoadResponseFile(int argv_i
size = M_FileLength(handle);
// Read in the entire file
- // Allocate one byte extra - this is incase there is an argument
+ // Allocate one byte extra - this is in case there is an argument
- // at the end of the response file, in which case a '\0' will be
+ // at the end of the response file, in which case a '\0' will be
// needed.
file = malloc(size + 1);