commit 993315afc4b1fddaf8952e7e55d1373b5052dd7c
Merge: a1b2ce54 ad11652d
Author: Simon Howard <fraggle@gmail.com>
AuthorDate: Sun Oct 28 23:45:08 2012 +0000
Commit: Simon Howard <fraggle@gmail.com>
CommitDate: Sun Oct 28 23:45:08 2012 +0000
Merge from trunk.
Subversion-branch: /branches/v2-branch
Subversion-revision: 2537
ChangeLog | 2944 +++++++++++++++++++++-------------------
NEWS | 40 +-
configure.in | 2 +-
data/Makefile.am | 4 +-
src/Makefile.am | 7 +-
src/aes_prng.c | 1048 ++++++++++++++
src/aes_prng.h | 40 +
src/d_iwad.c | 6 +-
src/deh_defs.h | 8 +-
src/deh_main.c | 12 +-
src/deh_main.h | 4 +-
src/deh_mapping.c | 10 +-
src/deh_mapping.h | 6 +-
src/doom/d_main.c | 26 +-
src/doom/d_net.c | 4 +-
src/doom/deh_ammo.c | 8 +-
src/doom/deh_frame.c | 6 +-
src/doom/deh_misc.c | 6 +-
src/doom/deh_ptr.c | 6 +-
src/doom/deh_thing.c | 6 +-
src/doom/deh_weapon.c | 6 +-
src/doom/g_game.c | 8 +
src/doom/hu_stuff.c | 5 +-
src/doom/m_menu.c | 43 +-
src/doom/p_spec.c | 5 +
src/heretic/d_net.c | 4 +-
src/heretic/deh_ammo.c | 8 +-
src/heretic/deh_frame.c | 6 +-
src/heretic/deh_thing.c | 6 +-
src/heretic/deh_weapon.c | 8 +-
src/hexen/d_net.c | 4 +-
src/i_oplmusic.c | 107 ++
src/i_video.c | 45 +-
src/m_misc.c | 23 +-
src/m_misc.h | 1 +
src/md5.c | 264 ----
src/md5.h | 45 -
src/net_client.c | 19 +-
src/net_client.h | 10 +-
src/net_defs.h | 18 +-
src/net_gui.c | 32 +-
src/net_query.c | 127 ++
src/net_sdl.c | 13 +-
src/net_server.c | 70 +-
src/net_structrw.c | 48 +-
src/net_structrw.h | 10 +-
src/setup/Makefile.am | 2 +-
src/setup/multiplayer.c | 34 +-
src/sha1.c | 319 +++++
src/sha1.h | 48 +
src/strife/d_net.c | 4 +-
src/strife/deh_ammo.c | 8 +-
src/strife/deh_frame.c | 6 +-
src/strife/deh_misc.c | 6 +-
src/strife/deh_ptr.c | 6 +-
src/strife/deh_thing.c | 6 +-
src/strife/deh_weapon.c | 6 +-
src/w_checksum.c | 24 +-
src/w_checksum.h | 2 +-
textscreen/Makefile.am | 1 +
textscreen/examples/guitest.c | 4 +
textscreen/txt_button.c | 2 -
textscreen/txt_checkbox.c | 8 +-
textscreen/txt_dropdown.c | 1 -
textscreen/txt_gui.c | 131 +-
textscreen/txt_gui.h | 7 +-
textscreen/txt_inputbox.c | 67 +-
textscreen/txt_io.c | 106 +-
textscreen/txt_io.h | 8 +
textscreen/txt_label.c | 33 +-
textscreen/txt_label.h | 4 +-
textscreen/txt_main.h | 30 +-
textscreen/txt_radiobutton.c | 7 +-
textscreen/txt_sdl.c | 12 +-
textscreen/txt_separator.c | 1 -
textscreen/txt_spinctrl.c | 13 +-
textscreen/txt_utf8.c | 160 +++
textscreen/txt_utf8.h | 31 +
textscreen/txt_widget.c | 12 +-
textscreen/txt_window.c | 14 +-
textscreen/txt_window_action.c | 4 -
81 files changed, 4194 insertions(+), 2061 deletions(-)
diff --cc configure.in
index 094a87c3,175a355f..77a7e6e9
--- a/configure.in
+++ b/configure.in
@@@ -1,7 -1,7 +1,7 @@@
-AC_INIT(Chocolate Doom, 1.7.0, fraggle@gmail.com, chocolate-doom)
+AC_INIT(Chocolate Doom, 1.99.0, fraggle@gmail.com, chocolate-doom)
PACKAGE_SHORTDESC="Conservative Doom source port"
- PACKAGE_COPYRIGHT="Copyright (C) 1993-2011"
+ PACKAGE_COPYRIGHT="Copyright (C) 1993-2012"
PACKAGE_LICENSE="GNU General Public License, version 2"
PACKAGE_MAINTAINER="Simon Howard"
PACKAGE_URL="http://www.chocolate-doom.org/"
diff --cc src/Makefile.am
index af7a43a2,25766ca0..8f393089
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@@ -67,15 -60,51 +67,15 @@@ i_videohr.c i_videohr.
m_bbox.c m_bbox.h \
m_cheat.c m_cheat.h \
m_config.c m_config.h \
+m_controls.c m_controls.h \
m_fixed.c m_fixed.h \
- md5.c md5.h \
-m_menu.c m_menu.h \
-m_misc.c m_misc.h \
+ sha1.c sha1.h \
memio.c memio.h \
-m_random.c m_random.h \
-p_ceilng.c \
-p_doors.c \
-p_enemy.c \
-p_floor.c \
-p_inter.c p_inter.h \
-p_lights.c \
-p_local.h \
-p_map.c \
-p_maputl.c \
-p_mobj.c p_mobj.h \
-p_plats.c \
-p_pspr.c p_pspr.h \
-p_saveg.c p_saveg.h \
-p_setup.c p_setup.h \
-p_sight.c \
-p_spec.c p_spec.h \
-p_switch.c \
-p_telept.c \
-p_tick.c p_tick.h \
-p_user.c \
-r_bsp.c r_bsp.h \
-r_data.c r_data.h \
-r_defs.h \
-r_draw.c r_draw.h \
-r_local.h \
-r_main.c r_main.h \
-r_plane.c r_plane.h \
-r_segs.c r_segs.h \
-r_sky.c r_sky.h \
-r_state.h \
-r_things.c r_things.h \
-sounds.c sounds.h \
-s_sound.c s_sound.h \
-st_lib.c st_lib.h \
-st_stuff.c st_stuff.h \
tables.c tables.h \
v_video.c v_video.h \
-wi_stuff.c wi_stuff.h \
+ v_patch.h \
w_checksum.c w_checksum.h \
+w_main.c w_main.h \
w_wad.c w_wad.h \
w_file.c w_file.h \
w_file_stdc.c \
diff --cc src/d_iwad.c
index 8c29352b,6d0ade26..aefb6872
--- a/src/d_iwad.c
+++ b/src/d_iwad.c
@@@ -173,8 -157,10 +173,12 @@@ static char *steam_install_subdirs[]
"steamapps\\common\\doom 2\\base",
"steamapps\\common\\final doom\\base",
"steamapps\\common\\ultimate doom\\base",
+ "steamapps\\common\\hexen\\base",
+ "steamapps\\common\\heretic shadow of the serpent riders\\base"
+
+ // From Doom 3: BFG Edition:
+
+ "steamapps\\common\\DOOM 3 BFG Edition\\base\\wads",
};
static char *GetRegistryString(registry_value_t *reg_val)
diff --cc src/deh_main.c
index 39d59e8c,e61933fa..4bb3e383
--- a/src/deh_main.c
+++ b/src/deh_main.c
@@@ -54,18 -72,35 +54,18 @@@ boolean deh_allow_long_cheats = false
boolean deh_apply_cheats = true;
- void DEH_Checksum(md5_digest_t digest)
-//
-// 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(sha1_digest_t digest)
{
- md5_context_t md5_context;
+ sha1_context_t sha1_context;
unsigned int i;
- MD5_Init(&md5_context);
+ SHA1_Init(&sha1_context);
- for (i=0; i<arrlen(section_types); ++i)
+ for (i=0; deh_section_types[i] != NULL; ++i)
{
- if (deh_section_types[i]->md5_hash != NULL)
- if (section_types[i]->sha1_hash != NULL)
++ if (deh_section_types[i]->sha1_hash != NULL)
{
- deh_section_types[i]->md5_hash(&md5_context);
- section_types[i]->sha1_hash(&sha1_context);
++ deh_section_types[i]->sha1_hash(&sha1_context);
}
}
diff --cc src/deh_main.h
index 9ac2c6c7,ad31af7d..ea9e42da
--- a/src/deh_main.h
+++ b/src/deh_main.h
@@@ -27,10 -27,11 +27,10 @@@
#ifndef DEH_MAIN_H
#define DEH_MAIN_H
-#include <stdio.h>
-
#include "doomtype.h"
#include "doomfeatures.h"
- #include "md5.h"
+#include "deh_str.h"
+ #include "sha1.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
@@@ -46,8 -47,28 +46,8 @@@ int DEH_LoadLumpByName(char *name)
boolean DEH_ParseAssignment(char *line, char **variable_name, char **value);
- void DEH_Checksum(md5_digest_t digest);
+ void DEH_Checksum(sha1_digest_t digest);
-// deh_text.c:
-//
-// Used to do dehacked text substitutions throughout the program
-
-#ifdef FEATURE_DEHACKED
-
-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, ...);
-
-#else
-
-#define DEH_String(x) (x)
-#define DEH_printf printf
-#define DEH_fprintf fprintf
-#define DEH_snprintf snprintf
-
-#endif
-
extern boolean deh_allow_long_strings;
extern boolean deh_allow_long_cheats;
extern boolean deh_apply_cheats;
diff --cc src/deh_mapping.c
index f061c298,d73cda96..85c675b4
--- a/src/deh_mapping.c
+++ b/src/deh_mapping.c
@@@ -60,111 -86,11 +60,111 @@@ static deh_mapping_entry_t *GetMappingE
DEH_Warning(context, "Field named '%s' not found", name);
- return false;
+ return NULL;
+}
+
+//
+// Get the location of the specified field in the specified structure.
+//
+
+static void *GetStructField(void *structptr,
+ deh_mapping_t *mapping,
+ deh_mapping_entry_t *entry)
+{
+ unsigned int offset;
+
+ offset = (uint8_t *)entry->location - (uint8_t *)mapping->base;
+
+ return (uint8_t *)structptr + offset;
+}
+
+//
+// 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)
+{
+ deh_mapping_entry_t *entry;
+ void *location;
+
+ entry = GetMappingEntryByName(context, mapping, name);
+
+ if (entry == NULL)
+ {
+ return false;
+ }
+
+ // Sanity check:
+
+ if (entry->is_string)
+ {
+ DEH_Error(context, "Tried to set '%s' as integer (BUG)", name);
+ return false;
+ }
+
+ location = GetStructField(structptr, mapping, entry);
+
+ // printf("Setting %p::%s to %i (%i bytes)\n",
+ // structptr, name, value, entry->size);
+
+ // Set field content based on its type:
+
+ 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;
+}
+
+//
+// Set the value of a string field in a structure by name
+//
+
+boolean DEH_SetStringMapping(deh_context_t *context, deh_mapping_t *mapping,
+ void *structptr, char *name, char *value)
+{
+ deh_mapping_entry_t *entry;
+ void *location;
+
+ entry = GetMappingEntryByName(context, mapping, name);
+
+ if (entry == NULL)
+ {
+ return false;
+ }
+
+ // Sanity check:
+
+ if (!entry->is_string)
+ {
+ DEH_Error(context, "Tried to set '%s' as string (BUG)", name);
+ return false;
+ }
+
+ location = GetStructField(structptr, mapping, entry);
+
+ // Copy value into field:
+
+ strncpy(location, value, entry->size);
+
+ return true;
}
- void DEH_StructMD5Sum(md5_context_t *context, deh_mapping_t *mapping,
- void *structptr)
+ void DEH_StructSHA1Sum(sha1_context_t *context, deh_mapping_t *mapping,
+ void *structptr)
{
int i;
diff --cc src/deh_mapping.h
index 129ddcfd,31e8aea3..91e34323
--- a/src/deh_mapping.h
+++ b/src/deh_mapping.h
@@@ -91,12 -81,10 +91,12 @@@ struct deh_mapping_
deh_mapping_entry_t entries[MAX_MAPPING_ENTRIES];
};
-boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping,
+boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping,
void *structptr, char *name, int value);
+boolean DEH_SetStringMapping(deh_context_t *context, deh_mapping_t *mapping,
+ void *structptr, char *name, char *value);
- void DEH_StructMD5Sum(md5_context_t *context, deh_mapping_t *mapping,
- void *structptr);
+ void DEH_StructSHA1Sum(sha1_context_t *context, deh_mapping_t *mapping,
+ void *structptr);
#endif /* #ifndef DEH_MAPPING_H */
diff --cc src/doom/d_main.c
index d91649a8,025c31eb..0746a579
--- a/src/doom/d_main.c
+++ b/src/doom/d_main.c
@@@ -1546,12 -1509,20 +1554,26 @@@ void D_DoomMain (void
if (gamemode == commercial && W_CheckNumForName("map01") < 0)
storedemo = true;
+ // Doom 3: BFG Edition includes modified versions of the classic
+ // IWADs. The modified version of doom2.wad does not have a
+ // TITLEPIC lump, so detect this so we can apply a workaround.
+ // We specifically check for TITLEPIC here, after PWADs have been
+ // loaded - this means that we can play with the BFG Edition with
+ // PWADs that change the title screen and still see the modified
+ // titles.
+
+ if (gamemode == commercial && W_CheckNumForName("titlepic") < 0)
+ {
+ printf("BFG Edition: Using INTERPIC instead of TITLEPIC.\n");
+ bfgedition = true;
+ }
+
+ if (M_CheckParmWithArgs("-statdump", 1))
+ {
+ I_AtExit(StatDump, true);
+ DEH_printf("External statistics registered.\n");
+ }
+
//!
// @arg <x>
// @category demo
diff --cc src/doom/d_net.c
index 74893724,00000000..4ab61425
mode 100644,000000..100644
--- a/src/doom/d_net.c
+++ b/src/doom/d_net.c
@@@ -1,304 -1,0 +1,304 @@@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// 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.
+//
+// DESCRIPTION:
+// DOOM Network game communication and protocol,
+// all OS independend parts.
+//
+//-----------------------------------------------------------------------------
+
+#include <stdlib.h>
+
+#include "doomfeatures.h"
+
+#include "d_main.h"
+#include "m_argv.h"
+#include "m_menu.h"
+#include "i_system.h"
+#include "i_timer.h"
+#include "i_video.h"
+#include "g_game.h"
+#include "doomdef.h"
+#include "doomstat.h"
+#include "w_checksum.h"
+#include "w_wad.h"
+
+#include "deh_main.h"
+
+#include "d_loop.h"
+
+ticcmd_t *netcmds;
+
+// Called when a player leaves the game
+
+static void PlayerQuitGame(player_t *player)
+{
+ static char exitmsg[80];
+ unsigned int player_num;
+
+ player_num = player - players;
+
+ // Do this the same way as Vanilla Doom does, to allow dehacked
+ // replacements of this message
+
+ strncpy(exitmsg, DEH_String("Player 1 left the game"), sizeof(exitmsg));
+ exitmsg[sizeof(exitmsg) - 1] = '\0';
+
+ exitmsg[7] += player_num;
+
+ playeringame[player_num] = false;
+ players[consoleplayer].message = exitmsg;
+
+ // TODO: check if it is sensible to do this:
+
+ if (demorecording)
+ {
+ G_CheckDemoStatus ();
+ }
+}
+
+static void RunTic(ticcmd_t *cmds, boolean *ingame)
+{
+ extern boolean advancedemo;
+ unsigned int i;
+
+ // Check for player quits.
+
+ for (i = 0; i < MAXPLAYERS; ++i)
+ {
+ if (!demoplayback && playeringame[i] && !ingame[i])
+ {
+ PlayerQuitGame(&players[i]);
+ }
+ }
+
+ netcmds = cmds;
+
+ // check that there are players in the game. if not, we cannot
+ // run a tic.
+
+ if (advancedemo)
+ D_DoAdvanceDemo ();
+
+ G_Ticker ();
+}
+
+static loop_interface_t doom_loop_interface = {
+ D_ProcessEvents,
+ G_BuildTiccmd,
+ RunTic,
+ M_Ticker
+};
+
+
+// Load game settings from the specified structure and
+// set global variables.
+
+static void LoadGameSettings(net_gamesettings_t *settings,
+ net_connect_data_t *connect_data)
+{
+ unsigned int i;
+
+ deathmatch = settings->deathmatch;
+ ticdup = settings->ticdup;
+ startepisode = settings->episode;
+ startmap = settings->map;
+ startskill = settings->skill;
+ startloadgame = settings->loadgame;
+ lowres_turn = settings->lowres_turn;
+ nomonsters = settings->nomonsters;
+ fastparm = settings->fast_monsters;
+ respawnparm = settings->respawn_monsters;
+ timelimit = settings->timelimit;
+
+ if (lowres_turn)
+ {
+ printf("NOTE: Turning resolution is reduced; this is probably "
+ "because there is a client recording a Vanilla demo.\n");
+ }
+
+ if (!connect_data->drone)
+ {
+ consoleplayer = settings->consoleplayer;
+ }
+ else
+ {
+ consoleplayer = 0;
+ }
+
+ for (i=0; i<MAXPLAYERS; ++i)
+ {
+ playeringame[i] = i < settings->num_players;
+ }
+}
+
+// Save the game settings from global variables to the specified
+// game settings structure.
+
+static void SaveGameSettings(net_gamesettings_t *settings,
+ net_connect_data_t *connect_data)
+{
+ // Fill in game settings structure with appropriate parameters
+ // for the new game
+
+ settings->deathmatch = deathmatch;
+ settings->episode = startepisode;
+ settings->map = startmap;
+ settings->skill = startskill;
+ settings->loadgame = startloadgame;
+ settings->gameversion = gameversion;
+ settings->nomonsters = nomonsters;
+ settings->fast_monsters = fastparm;
+ settings->respawn_monsters = respawnparm;
+ settings->timelimit = timelimit;
+
+ settings->lowres_turn = M_CheckParm("-record") > 0
+ && M_CheckParm("-longtics") == 0;
+
+ connect_data->drone = false;
+ connect_data->max_players = MAXPLAYERS;
+
+ //!
+ // @category net
+ //
+ // Run as the left screen in three screen mode.
+ //
+
+ if (M_CheckParm("-left") > 0)
+ {
+ viewangleoffset = ANG90;
+ connect_data->drone = true;
+ }
+
+ //!
+ // @category net
+ //
+ // Run as the right screen in three screen mode.
+ //
+
+ if (M_CheckParm("-right") > 0)
+ {
+ viewangleoffset = ANG270;
+ connect_data->drone = true;
+ }
+
+ //
+ // Connect data
+ //
+
+ // Game type fields:
+
+ connect_data->gamemode = gamemode;
+ connect_data->gamemission = gamemission;
+
+ // Are we recording a demo? Possibly set lowres turn mode
+
+ connect_data->lowres_turn = settings->lowres_turn;
+
+ // Read checksums of our WAD directory and dehacked information
+
- W_Checksum(connect_data->wad_md5sum);
- DEH_Checksum(connect_data->deh_md5sum);
++ W_Checksum(connect_data->wad_sha1sum);
++ DEH_Checksum(connect_data->deh_sha1sum);
+
+ // Are we playing with the Freedoom IWAD?
+
+ connect_data->is_freedoom = W_CheckNumForName("FREEDOOM") >= 0;
+}
+
+void D_InitSinglePlayerGame(net_gamesettings_t *settings)
+{
+ // default values for single player
+
+ settings->consoleplayer = 0;
+ settings->num_players = 1;
+
+ netgame = false;
+
+ //!
+ // @category net
+ //
+ // Start the game playing as though in a netgame with a single
+ // player. This can also be used to play back single player netgame
+ // demos.
+ //
+
+ if (M_CheckParm("-solo-net") > 0)
+ {
+ netgame = true;
+ }
+}
+
+//
+// D_CheckNetGame
+// Works out player numbers among the net participants
+//
+void D_CheckNetGame (void)
+{
+ net_connect_data_t connect_data;
+ net_gamesettings_t settings;
+
+ D_RegisterLoopCallbacks(&doom_loop_interface);
+
+ // Call D_QuitNetGame on exit
+
+ I_AtExit(D_QuitNetGame, true);
+
+ SaveGameSettings(&settings, &connect_data);
+
+ if (D_InitNetGame(&connect_data, &settings))
+ {
+ netgame = true;
+ autostart = true;
+ }
+ else
+ {
+ D_InitSinglePlayerGame(&settings);
+ }
+
+ LoadGameSettings(&settings, &connect_data);
+
+ DEH_printf("startskill %i deathmatch: %i startmap: %i startepisode: %i\n",
+ startskill, deathmatch, startmap, startepisode);
+
+ DEH_printf("player %i of %i (%i nodes)\n",
+ consoleplayer+1, settings.num_players, settings.num_players);
+
+ // Show players here; the server might have specified a time limit
+
+ if (timelimit > 0 && deathmatch)
+ {
+ // Gross hack to work like Vanilla:
+
+ if (timelimit == 20 && M_CheckParm("-avg"))
+ {
+ DEH_printf("Austin Virtual Gaming: Levels will end "
+ "after 20 minutes\n");
+ }
+ else
+ {
+ DEH_printf("Levels will end after %d minute", timelimit);
+ if (timelimit > 1)
+ printf("s");
+ printf(".\n");
+ }
+ }
+}
+
diff --cc src/doom/hu_stuff.c
index 9b67a1a5,8547f34a..3aaa5a33
--- a/src/doom/hu_stuff.c
+++ b/src/doom/hu_stuff.c
@@@ -621,6 -674,16 +620,8 @@@ boolean HU_Responder(event_t *ev
}
else
{
+ c = ev->data2;
+
- if (vanilla_keyboard_mapping)
- {
- if (shiftdown || (c >= 'a' && c <= 'z'))
- {
- c = shiftxform[c];
- }
- }
-
eatkey = HUlib_keyInIText(&w_chat, c);
if (eatkey)
{
diff --cc src/doom/m_menu.c
index e54ac7ff,cd2634a2..b0eeee06
--- a/src/doom/m_menu.c
+++ b/src/doom/m_menu.c
@@@ -1962,10 -2000,9 +2001,9 @@@ void M_Drawer (void
// DRAW SKULL
- V_DrawPatchDirect(x + SKULLXOFF,currentMenu->y - 5 + itemOn*LINEHEIGHT, 0,
+ V_DrawPatchDirect(x + SKULLXOFF, currentMenu->y - 5 + itemOn*LINEHEIGHT,
W_CacheLumpName(DEH_String(skullName[whichSkull]),
PU_CACHE));
-
}
diff --cc src/heretic/d_net.c
index 6a6a8abb,00000000..73a09ec6
mode 100644,000000..100644
--- a/src/heretic/d_net.c
+++ b/src/heretic/d_net.c
@@@ -1,238 -1,0 +1,238 @@@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// 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.
+//
+// DESCRIPTION:
+// DOOM Network game communication and protocol,
+// all OS independend parts.
+//
+//-----------------------------------------------------------------------------
+
+#include <stdlib.h>
+
+#include "doomfeatures.h"
+
+#include "m_argv.h"
+#include "i_system.h"
+#include "i_timer.h"
+#include "i_video.h"
+#include "doomdef.h"
+#include "w_checksum.h"
+
+#include "deh_main.h"
+
+#include "d_loop.h"
+
+ticcmd_t *netcmds;
+
+extern void D_DoAdvanceDemo(void);
+extern void D_ProcessEvents(void);
+extern void G_BuildTiccmd(ticcmd_t *cmd, int maketic);
+extern boolean G_CheckDemoStatus(void);
+
+// Called when a player leaves the game
+
+static void PlayerQuitGame(player_t *player)
+{
+ static char exitmsg[80];
+ unsigned int player_num;
+
+ player_num = player - players;
+
+ // Note:
+ // The Heretic source code does this, which doesn't actually work.
+ // As a result, the exit message is never seen.
+
+ strcpy(exitmsg, "PLAYER 1 LEFT THE GAME");
+ exitmsg[7] += player_num;
+ players[consoleplayer].message = exitmsg;
+
+ playeringame[player_num] = false;
+ players[consoleplayer].message = exitmsg;
+
+ // TODO: check if it is sensible to do this:
+
+ if (demorecording)
+ {
+ G_CheckDemoStatus ();
+ }
+}
+
+static void RunTic(ticcmd_t *cmds, boolean *ingame)
+{
+ extern boolean advancedemo;
+ unsigned int i;
+
+ // Check for player quits.
+
+ for (i = 0; i < MAXPLAYERS; ++i)
+ {
+ if (!demoplayback && playeringame[i] && !ingame[i])
+ {
+ PlayerQuitGame(&players[i]);
+ }
+ }
+
+ netcmds = cmds;
+
+ // check that there are players in the game. if not, we cannot
+ // run a tic.
+
+ if (advancedemo)
+ D_DoAdvanceDemo ();
+
+ G_Ticker ();
+}
+
+static loop_interface_t doom_loop_interface = {
+ D_ProcessEvents,
+ G_BuildTiccmd,
+ RunTic,
+ MN_Ticker
+};
+
+
+// Load game settings from the specified structure and
+// set global variables.
+
+static void LoadGameSettings(net_gamesettings_t *settings,
+ net_connect_data_t *connect_data)
+{
+ unsigned int i;
+
+ deathmatch = settings->deathmatch;
+ ticdup = settings->ticdup;
+ startepisode = settings->episode;
+ startmap = settings->map;
+ startskill = settings->skill;
+ // TODO startloadgame = settings->loadgame;
+ nomonsters = settings->nomonsters;
+ respawnparm = settings->respawn_monsters;
+
+ if (!connect_data->drone)
+ {
+ consoleplayer = settings->consoleplayer;
+ }
+ else
+ {
+ consoleplayer = 0;
+ }
+
+ for (i=0; i<MAXPLAYERS; ++i)
+ {
+ playeringame[i] = i < settings->num_players;
+ }
+}
+
+// Save the game settings from global variables to the specified
+// game settings structure.
+
+static void SaveGameSettings(net_gamesettings_t *settings,
+ net_connect_data_t *connect_data)
+{
+ // Fill in game settings structure with appropriate parameters
+ // for the new game
+
+ settings->deathmatch = deathmatch;
+ settings->episode = startepisode;
+ settings->map = startmap;
+ settings->skill = startskill;
+ // TODO settings->loadgame = startloadgame;
+ settings->gameversion = exe_heretic_1_3;
+ settings->nomonsters = nomonsters;
+ settings->respawn_monsters = respawnparm;
+ settings->timelimit = 0;
+ settings->lowres_turn = false;
+
+ connect_data->drone = false;
+ connect_data->max_players = MAXPLAYERS;
+
+ //
+ // Connect data
+ //
+
+ // Game type fields:
+
+ connect_data->gamemode = gamemode;
+ connect_data->gamemission = gamemission;
+
+ connect_data->lowres_turn = false;
+
+ // Read checksums of our WAD directory and dehacked information
+
- W_Checksum(connect_data->wad_md5sum);
- DEH_Checksum(connect_data->deh_md5sum);
++ W_Checksum(connect_data->wad_sha1sum);
++ DEH_Checksum(connect_data->deh_sha1sum);
+
+ connect_data->is_freedoom = 0;
+}
+
+void D_InitSinglePlayerGame(net_gamesettings_t *settings)
+{
+ // default values for single player
+
+ settings->consoleplayer = 0;
+ settings->num_players = 1;
+
+ netgame = false;
+
+ //!
+ // @category net
+ //
+ // Start the game playing as though in a netgame with a single
+ // player. This can also be used to play back single player netgame
+ // demos.
+ //
+
+ if (M_CheckParm("-solo-net") > 0)
+ {
+ netgame = true;
+ }
+}
+
+//
+// D_CheckNetGame
+// Works out player numbers among the net participants
+//
+
+void D_CheckNetGame (void)
+{
+ net_connect_data_t connect_data;
+ net_gamesettings_t settings;
+
+ D_RegisterLoopCallbacks(&doom_loop_interface);
+
+ // Call D_QuitNetGame on exit
+
+ I_AtExit(D_QuitNetGame, true);
+
+ SaveGameSettings(&settings, &connect_data);
+
+ if (D_InitNetGame(&connect_data, &settings))
+ {
+ netgame = true;
+ autostart = true;
+ }
+ else
+ {
+ D_InitSinglePlayerGame(&settings);
+ }
+
+ LoadGameSettings(&settings, &connect_data);
+}
diff --cc src/heretic/deh_ammo.c
index fe86c757,00000000..08241863
mode 100644,000000..100644
--- a/src/heretic/deh_ammo.c
+++ b/src/heretic/deh_ammo.c
@@@ -1,122 -1,0 +1,122 @@@
+// 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 "Ammo" sections in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "doomdef.h"
+#include "doomtype.h"
+#include "deh_defs.h"
+#include "deh_io.h"
+#include "deh_main.h"
+#include "p_local.h"
+
+static void *DEH_AmmoStart(deh_context_t *context, char *line)
+{
+ int ammo_number = 0;
+
+ if (sscanf(line, "Ammo %i", &ammo_number) != 1)
+ {
+ DEH_Warning(context, "Parse error on section start");
+ return NULL;
+ }
+
+ if (ammo_number < 0 || ammo_number >= NUMAMMO)
+ {
+ DEH_Warning(context, "Invalid ammo number: %i", ammo_number);
+ return NULL;
+ }
+
+ return &maxammo[ammo_number];
+}
+
+static void DEH_AmmoParseLine(deh_context_t *context, char *line, void *tag)
+{
+ char *variable_name, *value;
+ int ivalue;
+ int ammo_number;
+
+ if (tag == NULL)
+ return;
+
+ ammo_number = ((int *) tag) - maxammo;
+
+ // Parse the assignment
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {
+ // Failed to parse
+
+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+ ivalue = atoi(value);
+
+ if (!strcasecmp(variable_name, "Per ammo"))
+ {
+ // Heretic doesn't have a "per clip" ammo array, instead
+ // it is per weapon. However, the weapon number lines
+ // up with the ammo number if we add one.
+
+ GetWeaponAmmo[ammo_number + 1] = ivalue;
+ }
+ else if (!strcasecmp(variable_name, "Max ammo"))
+ {
+ maxammo[ammo_number] = ivalue;
+ }
+ else
+ {
+ DEH_Warning(context, "Field named '%s' not found", variable_name);
+ }
+}
+
- static void DEH_AmmoMD5Hash(md5_context_t *context)
++static void DEH_AmmoSHA1Hash(sha1_context_t *context)
+{
+ int i;
+
+ for (i=0; i<NUMAMMO; ++i)
+ {
- MD5_UpdateInt32(context, maxammo[i]);
++ SHA1_UpdateInt32(context, maxammo[i]);
+ }
+
+ for (i=0; i<NUMWEAPONS; ++i)
+ {
- MD5_UpdateInt32(context, GetWeaponAmmo[i]);
++ SHA1_UpdateInt32(context, GetWeaponAmmo[i]);
+ }
+}
+
+deh_section_t deh_section_ammo =
+{
+ "Ammo",
+ NULL,
+ DEH_AmmoStart,
+ DEH_AmmoParseLine,
+ NULL,
- DEH_AmmoMD5Hash,
++ DEH_AmmoSHA1Hash,
+};
+
diff --cc src/heretic/deh_frame.c
index 8623ab0c,00000000..4a1581a7
mode 100644,000000..100644
--- a/src/heretic/deh_frame.c
+++ b/src/heretic/deh_frame.c
@@@ -1,344 -1,0 +1,344 @@@
+// 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 "Frame" sections in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "doomtype.h"
+#include "info.h"
+
+#include "deh_defs.h"
+#include "deh_io.h"
+#include "deh_main.h"
+#include "deh_mapping.h"
+#include "deh_htic.h"
+
+#include "p_action.h"
+
+typedef struct
+{
+ int offsets[deh_hhe_num_versions];
+ void (*func)();
+} hhe_action_pointer_t;
+
+// Offsets of action pointers within the Heretic executables.
+// Different versions have different offsets.
+// (Seriously Greg, was this really necessary? What was wrong with the
+// "copying action pointer from another frame" technique used in dehacked?)
+
+// Offset Action function
+// v1.0 v1.2 v1.3
+
+static const hhe_action_pointer_t action_pointers[] =
+{
+ { { 77680, 80144, 80208 }, A_AccTeleGlitter },
+ { { 78608, 81104, 81168 }, A_AddPlayerCorpse },
+ { { 115808, 118000, 118240 }, A_AddPlayerRain },
+ { { 112272, 114480, 114720 }, A_BeakAttackPL1 },
+ { { 112448, 114656, 114896 }, A_BeakAttackPL2 },
+ { { 111856, 114176, 114416 }, A_BeakRaise },
+ { { 111568, 113888, 114128 }, A_BeakReady },
+ { { 74640, 77120, 77184 }, A_BeastAttack },
+ { { 70480, 72992, 73056 }, A_BeastPuff },
+ { { 73120, 75600, 75664 }, A_BlueSpark },
+ { { 115456, 117648, 117888 }, A_BoltSpark },
+ { { 77344, 79808, 79872 }, A_BossDeath },
+ { { 69328, 71856, 71920 }, A_Chase },
+ { { 0, 80976, 81040 }, A_CheckBurnGone },
+ { { 78480, 80944, 81008 }, A_CheckSkullDone },
+ { { 78448, 80912, 80976 }, A_CheckSkullFloor },
+ { { 71376, 73888, 73952 }, A_ChicAttack },
+ { { 71488, 74000, 74064 }, A_ChicChase },
+ { { 71456, 73968, 74032 }, A_ChicLook },
+ { { 71520, 74032, 74096 }, A_ChicPain },
+ { { 75792, 78208, 78272 }, A_ClinkAttack },
+ { { 108432, 110816, 111056 }, A_ContMobjSound },
+ { { 114752, 116944, 117184 }, A_DeathBallImpact },
+ { { 70016, 72528, 72592 }, A_DripBlood },
+ { { 77472, 79936, 80000 }, A_ESound },
+ { { 76784, 79248, 79312 }, A_Explode },
+ { { 69872, 72400, 72464 }, A_FaceTarget },
+ { { 71568, 74080, 74144 }, A_Feathers },
+ { { 112928, 115136, 115376 }, A_FireBlasterPL1 },
+ { { 113072, 115280, 115520 }, A_FireBlasterPL2 },
+ { { 115232, 117424, 117664 }, A_FireCrossbowPL1 },
+ { { 115312, 117504, 117744 }, A_FireCrossbowPL2 },
+ { { 113152, 115360, 115600 }, A_FireGoldWandPL1 },
+ { { 113296, 115504, 115744 }, A_FireGoldWandPL2 },
+ { { 113760, 115968, 116208 }, A_FireMacePL1 },
+ { { 114624, 116816, 117056 }, A_FireMacePL2 },
+ { { 116368, 118544, 118784 }, A_FirePhoenixPL1 },
+ { { 116736, 118896, 119136 }, A_FirePhoenixPL2 },
+ { { 115568, 117760, 118000 }, A_FireSkullRodPL1 },
+ { { 115648, 117840, 118080 }, A_FireSkullRodPL2 },
+ { { 117120, 119280, 119520 }, A_FlameEnd },
+ { { 78704, 81200, 81264 }, A_FlameSnd },
+ { { 117152, 119312, 119552 }, A_FloatPuff },
+ { { 78512, 81008, 81072 }, A_FreeTargMobj },
+ { { 117184, 119344, 119584 }, A_GauntletAttack },
+ { { 73232, 75712, 75776 }, A_GenWizard },
+ { { 75872, 78304, 78368 }, A_GhostOff },
+ { { 74752, 77232, 77296 }, A_HeadAttack },
+ { { 75488, 77984, 78048 }, A_HeadFireGrow },
+ { { 75328, 77824, 77888 }, A_HeadIceImpact },
+ { { 116336, 118512, 118752 }, A_HideInCeiling },
+ { { 78736, 81232, 81296 }, A_HideThing },
+ { { 70976, 73488, 73552 }, A_ImpDeath },
+ { { 70304, 72816, 72880 }, A_ImpExplode },
+ { { 70592, 73104, 73168 }, A_ImpMeAttack },
+ { { 70672, 73184, 73248 }, A_ImpMsAttack },
+ { { 70880, 73392, 73456 }, A_ImpMsAttack2 },
+ { { 71024, 73536, 73600 }, A_ImpXDeath1 },
+ { { 71072, 73584, 73648 }, A_ImpXDeath2 },
+ { { 77728, 80192, 80256 }, A_InitKeyGizmo },
+ { { 116720, 118880, 119120 }, A_InitPhoenixPL2 },
+ { { 70160, 72672, 72736 }, A_KnightAttack },
+ { { 117648, 119824, 120064 }, A_Light0 },
+ { { 69200, 71728, 71792 }, A_Look },
+ { { 111760, 114080, 114320 }, A_Lower },
+ { { 114032, 116224, 116464 }, A_MaceBallImpact },
+ { { 114192, 116384, 116624 }, A_MaceBallImpact2 },
+ { { 113904, 116112, 116352 }, A_MacePL1Check },
+ { { 77104, 79568, 79632 }, A_MakePod },
+ { { 73648, 76128, 76192 }, A_MinotaurAtk1 },
+ { { 74112, 76592, 76656 }, A_MinotaurAtk2 },
+ { { 74352, 76832, 76896 }, A_MinotaurAtk3 },
+ { { 74032, 76512, 76576 }, A_MinotaurCharge },
+ { { 73760, 76240, 76304 }, A_MinotaurDecide },
+ { { 74528, 77008, 77072 }, A_MntrFloorFire },
+ { { 71808, 74288, 74352 }, A_MummyAttack },
+ { { 71920, 74400, 74464 }, A_MummyAttack2 },
+ { { 72016, 74496, 74560 }, A_MummyFX1Seek },
+ { { 72048, 74528, 74592 }, A_MummySoul },
+ { { 76400, 78832, 78896 }, A_NoBlocking },
+ { { 69984, 72496, 72560 }, A_Pain },
+ { { 116496, 118656, 118896 }, A_PhoenixPuff },
+ { { 76896, 79360, 79424 }, A_PodPain },
+ { { 116272, 118448, 118688 }, A_RainImpact },
+ { { 111920, 114240, 114480 }, A_Raise },
+ { { 111696, 114016, 114256 }, A_ReFire },
+ { { 77056, 79520, 79584 }, A_RemovePod },
+ { { 116480, 0, 0 }, A_RemovedPhoenixFunc },
+ { { 81952, 84464, 84528 }, A_RestoreArtifact },
+ { { 82048, 84544, 84608 }, A_RestoreSpecialThing1 },
+ { { 82128, 84592, 84656 }, A_RestoreSpecialThing2 },
+ { { 76144, 78576, 78640 }, A_Scream },
+ { { 117104, 119264, 119504 }, A_ShutdownPhoenixPL2 },
+ { { 78288, 80752, 80816 }, A_SkullPop },
+ { { 115776, 117968, 118208 }, A_SkullRodPL2Seek },
+ { { 115984, 118176, 118416 }, A_SkullRodStorm },
+ { { 75632, 78048, 78112 }, A_SnakeAttack },
+ { { 75712, 78128, 78192 }, A_SnakeAttack2 },
+ { { 72144, 74624, 74688 }, A_Sor1Chase },
+ { { 72096, 74576, 74640 }, A_Sor1Pain },
+ { { 73392, 75872, 75936 }, A_Sor2DthInit },
+ { { 73424, 75904, 75968 }, A_Sor2DthLoop },
+ { { 73584, 76064, 76128 }, A_SorDBon },
+ { { 73552, 76032, 76096 }, A_SorDExp },
+ { { 73520, 76000, 76064 }, A_SorDSph },
+ { { 73488, 75968, 76032 }, A_SorRise },
+ { { 73616, 76096, 76160 }, A_SorSightSnd },
+ { { 73456, 75936, 76000 }, A_SorZap },
+ { { 72480, 74960, 75024 }, A_SorcererRise },
+ { { 115088, 117280, 117520 }, A_SpawnRippers },
+ { { 77520, 79984, 80048 }, A_SpawnTeleGlitter },
+ { { 77600, 80064, 80128 }, A_SpawnTeleGlitter2 },
+ { { 72192, 74672, 74736 }, A_Srcr1Attack },
+ { { 72896, 75376, 75440 }, A_Srcr2Attack },
+ { { 72816, 75296, 75360 }, A_Srcr2Decide },
+ { { 112640, 114848, 115088 }, A_StaffAttackPL1 },
+ { { 112784, 114992, 115232 }, A_StaffAttackPL2 },
+ { { 78752, 81248, 81312 }, A_UnHideThing },
+ { { 78080, 80544, 80608 }, A_VolcBallImpact },
+ { { 77856, 80320, 80384 }, A_VolcanoBlast },
+ { { 77824, 80288, 80352 }, A_VolcanoSet },
+ { { 111168, 113488, 113728 }, A_WeaponReady },
+ { { 75168, 77664, 77728 }, A_WhirlwindSeek },
+ { { 75888, 78320, 78384 }, A_WizAtk1 },
+ { { 75920, 78352, 78416 }, A_WizAtk2 },
+ { { 75952, 78384, 78448 }, A_WizAtk3 },
+};
+
+DEH_BEGIN_MAPPING(state_mapping, state_t)
+ DEH_MAPPING("Sprite number", sprite)
+ DEH_MAPPING("Sprite subnumber", frame)
+ DEH_MAPPING("Duration", tics)
+ DEH_MAPPING("Next frame", nextstate)
+ DEH_MAPPING("Unknown 1", misc1)
+ DEH_MAPPING("Unknown 2", misc2)
+DEH_END_MAPPING
+
+static void DEH_FrameInit(void)
+{
+ // Bit of a hack here:
+ DEH_HereticInit();
+}
+
+static void *DEH_FrameStart(deh_context_t *context, char *line)
+{
+ int frame_number = 0;
+ int mapped_frame_number;
+ state_t *state;
+
+ if (sscanf(line, "Frame %i", &frame_number) != 1)
+ {
+ DEH_Warning(context, "Parse error on section start");
+ return NULL;
+ }
+
+ // Map the HHE frame number (which assumes a Heretic 1.0 state table)
+ // to the internal frame number (which is is the Heretic 1.3 state table):
+
+ mapped_frame_number = DEH_MapHereticFrameNumber(frame_number);
+
+ if (mapped_frame_number < 0 || mapped_frame_number >= DEH_HERETIC_NUMSTATES)
+ {
+ DEH_Warning(context, "Invalid frame number: %i", frame_number);
+ return NULL;
+ }
+
+ state = &states[mapped_frame_number];
+
+ return state;
+}
+
+static boolean GetActionPointerForOffset(int offset, void **result)
+{
+ int i;
+
+ // Special case.
+
+ if (offset == 0)
+ {
+ *result = NULL;
+ return true;
+ }
+
+ for (i=0; i<arrlen(action_pointers); ++i)
+ {
+ if (action_pointers[i].offsets[deh_hhe_version] == offset)
+ {
+ *result = action_pointers[i].func;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// If an invalid action pointer is specified, the patch may be for a
+// different version from the version we are currently set to. Try to
+// suggest a different version to use.
+
+static void SuggestOtherVersions(unsigned int offset)
+{
+ unsigned int i, v;
+
+ for (i=0; i<arrlen(action_pointers); ++i)
+ {
+ for (v=0; v<deh_hhe_num_versions; ++v)
+ {
+ if (action_pointers[i].offsets[v] == offset)
+ {
+ DEH_SuggestHereticVersion(v);
+ }
+ }
+ }
+}
+
+static void DEH_FrameParseLine(deh_context_t *context, char *line, void *tag)
+{
+ state_t *state;
+ char *variable_name, *value;
+ int ivalue;
+
+ if (tag == NULL)
+ return;
+
+ state = (state_t *) tag;
+
+ // Parse the assignment
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {
+ // Failed to parse
+
+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+ // all values are integers
+
+ ivalue = atoi(value);
+
+ // Action pointer field is a special case:
+
+ if (!strcasecmp(variable_name, "Action pointer"))
+ {
+ void *func;
+
+ if (!GetActionPointerForOffset(ivalue, &func))
+ {
+ SuggestOtherVersions(ivalue);
+ DEH_Error(context, "Unknown action pointer: %i", ivalue);
+ return;
+ }
+
+ state->action = func;
+ }
+ else
+ {
+ // "Next frame" numbers need to undergo mapping.
+
+ if (!strcasecmp(variable_name, "Next frame"))
+ {
+ ivalue = DEH_MapHereticFrameNumber(ivalue);
+ }
+
+ DEH_SetMapping(context, &state_mapping, state, variable_name, ivalue);
+ }
+}
+
- static void DEH_FrameMD5Sum(md5_context_t *context)
++static void DEH_FrameSHA1Sum(sha1_context_t *context)
+{
+ int i;
+
+ for (i=0; i<NUMSTATES; ++i)
+ {
- DEH_StructMD5Sum(context, &state_mapping, &states[i]);
++ DEH_StructSHA1Sum(context, &state_mapping, &states[i]);
+ }
+}
+
+deh_section_t deh_section_frame =
+{
+ "Frame",
+ DEH_FrameInit,
+ DEH_FrameStart,
+ DEH_FrameParseLine,
+ NULL,
- DEH_FrameMD5Sum,
++ DEH_FrameSHA1Sum,
+};
+
diff --cc src/heretic/deh_thing.c
index ffededf2,00000000..dbb239e4
mode 100644,000000..100644
--- a/src/heretic/deh_thing.c
+++ b/src/heretic/deh_thing.c
@@@ -1,150 -1,0 +1,150 @@@
+// 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 "Thing" sections in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "doomtype.h"
+#include "m_misc.h"
+
+#include "deh_defs.h"
+#include "deh_main.h"
+#include "deh_mapping.h"
+#include "deh_htic.h"
+
+#include "info.h"
+
+DEH_BEGIN_MAPPING(thing_mapping, mobjinfo_t)
+ DEH_MAPPING("ID #", doomednum)
+ DEH_MAPPING("Initial frame", spawnstate)
+ DEH_MAPPING("Hit points", spawnhealth)
+ DEH_MAPPING("First moving frame", seestate)
+ DEH_MAPPING("Alert sound", seesound)
+ DEH_MAPPING("Reaction time", reactiontime)
+ DEH_MAPPING("Attack sound", attacksound)
+ DEH_MAPPING("Injury frame", painstate)
+ DEH_MAPPING("Pain chance", painchance)
+ DEH_MAPPING("Pain sound", painsound)
+ DEH_MAPPING("Close attack frame", meleestate)
+ DEH_MAPPING("Far attack frame", missilestate)
+ DEH_MAPPING("Burning frame", crashstate)
+ DEH_MAPPING("Death frame", deathstate)
+ DEH_MAPPING("Exploding frame", xdeathstate)
+ DEH_MAPPING("Death sound", deathsound)
+ DEH_MAPPING("Speed", speed)
+ DEH_MAPPING("Width", radius)
+ DEH_MAPPING("Height", height)
+ DEH_MAPPING("Mass", mass)
+ DEH_MAPPING("Missile damage", damage)
+ DEH_MAPPING("Action sound", activesound)
+ DEH_MAPPING("Bits 1", flags)
+ DEH_MAPPING("Bits 2", flags2)
+DEH_END_MAPPING
+
+static void *DEH_ThingStart(deh_context_t *context, char *line)
+{
+ int thing_number = 0;
+ mobjinfo_t *mobj;
+
+ if (sscanf(line, "Thing %i", &thing_number) != 1)
+ {
+ DEH_Warning(context, "Parse error on section start");
+ return NULL;
+ }
+
+ // HHE thing numbers are indexed from 1
+ --thing_number;
+
+ if (thing_number < 0 || thing_number >= DEH_HERETIC_NUMMOBJTYPES)
+ {
+ DEH_Warning(context, "Invalid thing number: %i", thing_number);
+ return NULL;
+ }
+
+ mobj = &mobjinfo[thing_number];
+
+ return mobj;
+}
+
+static void DEH_ThingParseLine(deh_context_t *context, char *line, void *tag)
+{
+ mobjinfo_t *mobj;
+ char *variable_name, *value;
+ int ivalue;
+
+ if (tag == NULL)
+ return;
+
+ mobj = (mobjinfo_t *) tag;
+
+ // Parse the assignment
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {
+ // Failed to parse
+
+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+ // all values are integers
+
+ ivalue = atoi(value);
+
+ // If the value to be set is a frame, the frame number must
+ // undergo transformation from a Heretic 1.0 index to a
+ // Heretic 1.3 index.
+
+ if (M_StrCaseStr(variable_name, "frame") != NULL)
+ {
+ ivalue = DEH_MapHereticFrameNumber(ivalue);
+ }
+
+ // Set the field value
+
+ DEH_SetMapping(context, &thing_mapping, mobj, variable_name, ivalue);
+}
+
- static void DEH_ThingMD5Sum(md5_context_t *context)
++static void DEH_ThingSHA1Sum(sha1_context_t *context)
+{
+ int i;
+
+ for (i=0; i<NUMMOBJTYPES; ++i)
+ {
- DEH_StructMD5Sum(context, &thing_mapping, &mobjinfo[i]);
++ DEH_StructSHA1Sum(context, &thing_mapping, &mobjinfo[i]);
+ }
+}
+
+deh_section_t deh_section_thing =
+{
+ "Thing",
+ NULL,
+ DEH_ThingStart,
+ DEH_ThingParseLine,
+ NULL,
- DEH_ThingMD5Sum,
++ DEH_ThingSHA1Sum,
+};
+
diff --cc src/heretic/deh_weapon.c
index 28a90c68,00000000..0c417e2b
mode 100644,000000..100644
--- a/src/heretic/deh_weapon.c
+++ b/src/heretic/deh_weapon.c
@@@ -1,131 -1,0 +1,131 @@@
+// 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 "Weapon" sections in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "doomtype.h"
+#include "m_misc.h"
+
+#include "doomdef.h"
+
+#include "deh_defs.h"
+#include "deh_main.h"
+#include "deh_mapping.h"
+#include "deh_htic.h"
+
+DEH_BEGIN_MAPPING(weapon_mapping, weaponinfo_t)
+ DEH_MAPPING("Ammo type", ammo)
+ DEH_MAPPING("Deselect frame", upstate)
+ DEH_MAPPING("Select frame", downstate)
+ DEH_MAPPING("Bobbing frame", readystate)
+ DEH_MAPPING("Shooting frame", atkstate)
+ DEH_MAPPING("Firing frame", holdatkstate)
+ DEH_MAPPING("Unknown frame", flashstate)
+DEH_END_MAPPING
+
+static void *DEH_WeaponStart(deh_context_t *context, char *line)
+{
+ int weapon_number = 0;
+
+ if (sscanf(line, "Weapon %i", &weapon_number) != 1)
+ {
+ DEH_Warning(context, "Parse error on section start");
+ return NULL;
+ }
+
+ if (weapon_number < 0 || weapon_number >= NUMWEAPONS * 2)
+ {
+ DEH_Warning(context, "Invalid weapon number: %i", weapon_number);
+ return NULL;
+ }
+
+ // Because of the tome of power, we have two levels of weapons:
+
+ if (weapon_number < NUMWEAPONS)
+ {
+ return &wpnlev1info[weapon_number];
+ }
+ else
+ {
+ return &wpnlev2info[weapon_number - NUMWEAPONS];
+ }
+}
+
+static void DEH_WeaponParseLine(deh_context_t *context, char *line, void *tag)
+{
+ char *variable_name, *value;
+ weaponinfo_t *weapon;
+ int ivalue;
+
+ if (tag == NULL)
+ return;
+
+ weapon = (weaponinfo_t *) tag;
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {
+ // Failed to parse
+
+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+ ivalue = atoi(value);
+
+ // If this is a frame field, we need to map from Heretic 1.0 frame
+ // numbers to Heretic 1.3 frame numbers.
+
+ if (M_StrCaseStr(variable_name, "frame") != NULL)
+ {
+ ivalue = DEH_MapHereticFrameNumber(ivalue);
+ }
+
+ DEH_SetMapping(context, &weapon_mapping, weapon, variable_name, ivalue);
+}
+
- static void DEH_WeaponMD5Sum(md5_context_t *context)
++static void DEH_WeaponSHA1Sum(sha1_context_t *context)
+{
+ int i;
+
+ for (i=0; i<NUMWEAPONS ;++i)
+ {
- DEH_StructMD5Sum(context, &weapon_mapping, &wpnlev1info[i]);
- DEH_StructMD5Sum(context, &weapon_mapping, &wpnlev2info[i]);
++ DEH_StructSHA1Sum(context, &weapon_mapping, &wpnlev1info[i]);
++ DEH_StructSHA1Sum(context, &weapon_mapping, &wpnlev2info[i]);
+ }
+}
+
+deh_section_t deh_section_weapon =
+{
+ "Weapon",
+ NULL,
+ DEH_WeaponStart,
+ DEH_WeaponParseLine,
+ NULL,
- DEH_WeaponMD5Sum,
++ DEH_WeaponSHA1Sum,
+};
+
diff --cc src/hexen/d_net.c
index 0fe5ed1e,00000000..7d663154
mode 100644,000000..100644
--- a/src/hexen/d_net.c
+++ b/src/hexen/d_net.c
@@@ -1,280 -1,0 +1,280 @@@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// 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.
+//
+// DESCRIPTION:
+// DOOM Network game communication and protocol,
+// all OS independend parts.
+//
+//-----------------------------------------------------------------------------
+
+#include <stdlib.h>
+
+#include "doomfeatures.h"
+
+#include "m_argv.h"
+#include "i_system.h"
+#include "i_timer.h"
+#include "i_video.h"
+#include "h2def.h"
+#include "p_local.h"
+#include "s_sound.h"
+#include "w_checksum.h"
+
+#include "deh_main.h"
+
+#include "d_loop.h"
+
+ticcmd_t *netcmds;
+
+extern void H2_DoAdvanceDemo(void);
+extern void H2_ProcessEvents(void);
+extern void G_BuildTiccmd(ticcmd_t *cmd, int maketic);
+extern boolean G_CheckDemoStatus(void);
+
+extern boolean demorecording;
+
+// Called when a player leaves the game
+
+static void PlayerQuitGame(player_t *player)
+{
+ static char exitmsg[80];
+ unsigned int player_num;
+
+ player_num = player - players;
+
+ strcpy(exitmsg, "PLAYER 1 LEFT THE GAME");
+ exitmsg[7] += player_num;
+ P_SetMessage(&players[consoleplayer], exitmsg, true);
+ S_StartSound(NULL, SFX_CHAT);
+
+ playeringame[player_num] = false;
+
+ // TODO: check if it is sensible to do this:
+
+ if (demorecording)
+ {
+ G_CheckDemoStatus ();
+ }
+}
+
+static void RunTic(ticcmd_t *cmds, boolean *ingame)
+{
+ extern boolean advancedemo;
+ unsigned int i;
+
+ // Check for player quits.
+
+ for (i = 0; i < MAXPLAYERS; ++i)
+ {
+ if (!demoplayback && playeringame[i] && !ingame[i])
+ {
+ PlayerQuitGame(&players[i]);
+ }
+ }
+
+ netcmds = cmds;
+
+ // check that there are players in the game. if not, we cannot
+ // run a tic.
+
+ if (advancedemo)
+ H2_DoAdvanceDemo ();
+
+ G_Ticker ();
+}
+
+static loop_interface_t hexen_loop_interface = {
+ H2_ProcessEvents,
+ G_BuildTiccmd,
+ RunTic,
+ MN_Ticker
+};
+
+
+// Load game settings from the specified structure and
+// set global variables.
+
+static void LoadGameSettings(net_gamesettings_t *settings,
+ net_connect_data_t *connect_data)
+{
+ unsigned int i;
+
+ deathmatch = settings->deathmatch;
+ ticdup = settings->ticdup;
+ startepisode = settings->episode;
+ startmap = settings->map;
+ startskill = settings->skill;
+ // TODO startloadgame = settings->loadgame;
+ nomonsters = settings->nomonsters;
+ respawnparm = settings->respawn_monsters;
+
+ if (!connect_data->drone)
+ {
+ consoleplayer = settings->consoleplayer;
+ }
+ else
+ {
+ consoleplayer = 0;
+ }
+
+ for (i=0; i<MAXPLAYERS; ++i)
+ {
+ playeringame[i] = i < settings->num_players;
+ PlayerClass[i] = settings->player_classes[i];
+
+ if (PlayerClass[i] >= NUMCLASSES)
+ {
+ PlayerClass[i] = PCLASS_FIGHTER;
+ }
+ }
+}
+
+// Save the game settings from global variables to the specified
+// game settings structure.
+
+static void SaveGameSettings(net_gamesettings_t *settings,
+ net_connect_data_t *connect_data)
+{
+ int i;
+
+ // jhaley 20120715: Some parts of the structure are being left
+ // uninitialized. If -class is not used on the command line, this
+ // can lead to a crash in SB_Init due to player class == 0xCCCCCCCC.
+ memset(settings, 0, sizeof(*settings));
+
+ // Fill in game settings structure with appropriate parameters
+ // for the new game
+
+ settings->deathmatch = deathmatch;
+ settings->episode = startepisode;
+ settings->map = startmap;
+ settings->skill = startskill;
+ // TODO settings->loadgame = startloadgame;
+ settings->gameversion = exe_hexen_1_1;
+ settings->nomonsters = nomonsters;
+ settings->respawn_monsters = respawnparm;
+ settings->timelimit = 0;
+ settings->lowres_turn = false;
+
+ //
+ // Connect data
+ //
+
+ // Game type fields:
+
+ connect_data->gamemode = gamemode;
+ connect_data->gamemission = gamemission;
+
+ connect_data->lowres_turn = false;
+ connect_data->drone = false;
+ connect_data->max_players = MAXPLAYERS;
+
+ //!
+ // @category net
+ // @arg <n>
+ //
+ // Specify player class: 0=fighter, 1=cleric, 2=mage, 3=pig.
+ //
+
+ i = M_CheckParmWithArgs("-class", 1);
+
+ if (i > 0)
+ {
+ connect_data->player_class = atoi(myargv[i + 1]);
+ }
+ else
+ {
+ connect_data->player_class = PCLASS_FIGHTER;
+ }
+
+ // Read checksums of our WAD directory and dehacked information
+
- W_Checksum(connect_data->wad_md5sum);
- memset(connect_data->deh_md5sum, 0, sizeof(md5_digest_t));
++ W_Checksum(connect_data->wad_sha1sum);
++ memset(connect_data->deh_sha1sum, 0, sizeof(sha1_digest_t));
+
+ connect_data->is_freedoom = 0;
+}
+
+void D_InitSinglePlayerGame(net_gamesettings_t *settings)
+{
+ // default values for single player
+
+ settings->consoleplayer = 0;
+ settings->num_players = 1;
+
+ netgame = false;
+
+ //!
+ // @category net
+ //
+ // Start the game playing as though in a netgame with a single
+ // player. This can also be used to play back single player netgame
+ // demos.
+ //
+
+ if (M_CheckParm("-solo-net") > 0)
+ {
+ netgame = true;
+ }
+}
+
+//
+// D_CheckNetGame
+// Works out player numbers among the net participants
+//
+
+void D_CheckNetGame (void)
+{
+ net_connect_data_t connect_data;
+ net_gamesettings_t settings;
+
+ D_RegisterLoopCallbacks(&hexen_loop_interface);
+
+ // Call D_QuitNetGame on exit
+
+ I_AtExit(D_QuitNetGame, true);
+
+ SaveGameSettings(&settings, &connect_data);
+
+ if (D_InitNetGame(&connect_data, &settings))
+ {
+ netgame = true;
+ autostart = true;
+ }
+ else
+ {
+ D_InitSinglePlayerGame(&settings);
+ }
+
+ LoadGameSettings(&settings, &connect_data);
+}
+
+//==========================================================================
+//
+// NET_SendFrags
+//
+//==========================================================================
+
+void NET_SendFrags(player_t * player)
+{
+ // Not sure what this is intended for. Unused?
+}
+
diff --cc src/i_video.c
index 7ba4c8cd,895043da..959a1472
--- a/src/i_video.c
+++ b/src/i_video.c
@@@ -378,12 -276,44 +378,43 @@@ static void UpdateFocus(void
screenvisible = (state & SDL_APPACTIVE) != 0;
}
+ // Show or hide the mouse cursor. We have to use different techniques
+ // depending on the OS.
+
+ static void ShowCursor(boolean show)
+ {
+ // On Windows, using SDL_ShowCursor() adds lag to the mouse input,
+ // so work around this by setting an invisible cursor instead. On
+ // other systems, it isn't possible to change the cursor, so this
+ // hack has to be Windows-only. (Thanks to entryway for this)
+
+ #ifdef _WIN32
+ if (show)
+ {
+ SDL_SetCursor(cursors[1]);
+ }
+ else
+ {
+ SDL_SetCursor(cursors[0]);
+ }
+ #else
+ SDL_ShowCursor(show);
+ #endif
+
+ // When the cursor is hidden, grab the input.
+
+ if (!screensaver_mode)
+ {
+ SDL_WM_GrabInput(!show);
+ }
+ }
+
-static void LoadDiskImage(void)
+void I_EnableLoadingDisk(void)
{
patch_t *disk;
+ byte *tmpbuf;
char *disk_name;
int y;
- int xoffset = SCREENWIDTH - LOADING_DISK_W;
- int yoffset = SCREENHEIGHT - LOADING_DISK_H;
char buf[20];
SDL_VideoDriverName(buf, 15);
diff --cc src/m_misc.c
index e14436a3,31c87898..47aea8b9
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@@ -207,92 -206,22 +207,111 @@@ boolean M_StrToInt(const char *str, in
|| sscanf(str, " %d", result) == 1;
}
+void M_ExtractFileBase(char *path, char *dest)
+{
+ char *src;
+ char *filename;
+ int length;
+
+ src = path + strlen(path) - 1;
+
+ // back up until a \ or the start
+ while (src != path && *(src - 1) != DIR_SEPARATOR)
+ {
+ src--;
+ }
+
+ filename = src;
+
+ // Copy up to eight characters
+ // Note: Vanilla Doom exits with an error if a filename is specified
+ // with a base of more than eight characters. To remove the 8.3
+ // filename limit, instead we simply truncate the name.
+
+ length = 0;
+ memset(dest, 0, 8);
+
+ while (*src != '\0' && *src != '.')
+ {
+ if (length >= 8)
+ {
+ printf("Warning: Truncated '%s' lump name to '%.8s'.\n",
+ filename, dest);
+ break;
+ }
+
+ dest[length++] = toupper((int)*src++);
+ }
+}
+
+//---------------------------------------------------------------------------
+//
+// PROC M_ForceUppercase
+//
+// Change string to uppercase.
+//
+//---------------------------------------------------------------------------
+
+void M_ForceUppercase(char *text)
+{
+ char *p;
+
+ for (p = text; *p != '\0'; ++p)
+ {
+ *p = toupper(*p);
+ }
+}
+
+//
+// M_StrCaseStr
+//
+// Case-insensitive version of strstr()
+//
+
+char *M_StrCaseStr(char *haystack, char *needle)
+{
+ unsigned int haystack_len;
+ unsigned int needle_len;
+ unsigned int len;
+ unsigned int i;
+
+ haystack_len = strlen(haystack);
+ needle_len = strlen(needle);
+
+ if (haystack_len < needle_len)
+ {
+ return NULL;
+ }
+
+ len = haystack_len - needle_len;
+
+ for (i = 0; i <= len; ++i)
+ {
+ if (!strncasecmp(haystack + i, needle, needle_len))
+ {
+ return haystack + i;
+ }
+ }
+
+ return NULL;
+}
+
+ #ifdef _WIN32
+
+ char *M_OEMToUTF8(const char *oem)
+ {
+ unsigned int len = strlen(oem) + 1;
+ wchar_t *tmp;
+ char *result;
+
+ tmp = malloc(len * sizeof(wchar_t));
+ MultiByteToWideChar(CP_OEMCP, 0, oem, len, tmp, len);
+ result = malloc(len * 4);
+ WideCharToMultiByte(CP_UTF8, 0, tmp, len, result, len * 4, NULL, NULL);
+ free(tmp);
+
+ return result;
+ }
+
+ #endif
+
diff --cc src/m_misc.h
index c6be6ccb,6c2da4b1..ac5b5164
--- a/src/m_misc.h
+++ b/src/m_misc.h
@@@ -40,9 -40,7 +40,10 @@@ char *M_TempFile(char *s)
boolean M_FileExists(char *file);
long M_FileLength(FILE *handle);
boolean M_StrToInt(const char *str, int *result);
+void M_ExtractFileBase(char *path, char *dest);
+void M_ForceUppercase(char *text);
+char *M_StrCaseStr(char *haystack, char *needle);
+ char *M_OEMToUTF8(const char *ansi);
#endif
diff --cc src/net_client.c
index 083dca8b,24fb7f6c..abd94145
--- a/src/net_client.c
+++ b/src/net_client.c
@@@ -905,9 -1133,21 +905,9 @@@ boolean NET_CL_Connect(net_addr_t *addr
server_addr = addr;
- memcpy(net_local_wad_md5sum, data->wad_md5sum, sizeof(md5_digest_t));
- memcpy(net_local_deh_md5sum, data->deh_md5sum, sizeof(md5_digest_t));
- // Are we recording a demo? Possibly set lowres turn mode
-
- if (M_CheckParm("-record") > 0 && M_CheckParm("-longtics") == 0)
- {
- lowres_turn = true;
- }
-
- // Read checksums of our WAD directory and dehacked information
-
- W_Checksum(net_local_wad_sha1sum);
- DEH_Checksum(net_local_deh_sha1sum);
-
- // Are we playing with the Freedoom IWAD?
-
- net_local_is_freedoom = W_CheckNumForName("FREEDOOM") >= 0;
++ memcpy(net_local_wad_sha1sum, data->wad_sha1sum, sizeof(sha1_digest_t));
++ memcpy(net_local_deh_sha1sum, data->deh_sha1sum, sizeof(sha1_digest_t));
+ net_local_is_freedoom = data->is_freedoom;
// create a new network I/O context and add just the
// necessary module
diff --cc src/net_client.h
index 242bf958,a752b747..3914849d
--- a/src/net_client.h
+++ b/src/net_client.h
@@@ -24,35 -24,40 +24,35 @@@
#ifndef NET_CLIENT_H
#define NET_CLIENT_H
-#include "doomdef.h"
#include "doomtype.h"
#include "d_ticcmd.h"
- #include "md5.h"
+ #include "sha1.h"
#include "net_defs.h"
-#define MAXPLAYERNAME 30
-
-boolean NET_CL_Connect(net_addr_t *addr);
+boolean NET_CL_Connect(net_addr_t *addr, net_connect_data_t *data);
void NET_CL_Disconnect(void);
void NET_CL_Run(void);
void NET_CL_Init(void);
-void NET_CL_StartGame();
+void NET_CL_StartGame(net_gamesettings_t *settings);
void NET_CL_SendTiccmd(ticcmd_t *ticcmd, int maketic);
+boolean NET_CL_GetSettings(net_gamesettings_t *_settings);
void NET_Init(void);
+void NET_BindVariables(void);
+
extern boolean net_client_connected;
extern boolean net_client_received_wait_data;
-extern boolean net_client_controller;
-extern unsigned int net_clients_in_game;
-extern unsigned int net_drones_in_game;
+extern net_waitdata_t net_client_wait_data;
extern boolean net_waiting_for_start;
-extern char net_player_names[MAXPLAYERS][MAXPLAYERNAME];
-extern char net_player_addresses[MAXPLAYERS][MAXPLAYERNAME];
-extern int net_player_number;
extern char *net_player_name;
- extern md5_digest_t net_server_wad_md5sum;
- extern md5_digest_t net_server_deh_md5sum;
+ extern sha1_digest_t net_server_wad_sha1sum;
+ extern sha1_digest_t net_server_deh_sha1sum;
extern unsigned int net_server_is_freedoom;
- extern md5_digest_t net_local_wad_md5sum;
- extern md5_digest_t net_local_deh_md5sum;
+ extern sha1_digest_t net_local_wad_sha1sum;
+ extern sha1_digest_t net_local_deh_sha1sum;
extern unsigned int net_local_is_freedoom;
+extern boolean drone;
#endif /* #ifndef NET_CLIENT_H */
-
diff --cc src/net_defs.h
index aa7b6f6e,c2d4d561..ba50f48e
--- a/src/net_defs.h
+++ b/src/net_defs.h
@@@ -26,31 -26,9 +26,31 @@@
#ifndef NET_DEFS_H
#define NET_DEFS_H
-#include "doomdef.h"
+#include <stdio.h>
+
#include "doomtype.h"
#include "d_ticcmd.h"
- #include "md5.h"
++#include "sha1.h"
+
+// Absolute maximum number of "nodes" in the game. This is different to
+// NET_MAXPLAYERS, as there may be observers that are not participating
+// (eg. left/right monitors)
+
+#define MAXNETNODES 16
+
+// The maximum number of players, multiplayer/networking.
+// This is the maximum supported by the networking code; individual games
+// have their own values for MAXPLAYERS that can be smaller.
+
+#define NET_MAXPLAYERS 8
+
+// Maximum length of a player's name.
+
+#define MAXPLAYERNAME 30
+
+// Networking and tick handling related.
+
+#define BACKUPTICS 128
typedef struct _net_module_s net_module_t;
typedef struct _net_packet_s net_packet_t;
@@@ -140,27 -118,15 +140,33 @@@ typedef enu
NET_MASTER_PACKET_TYPE_ADD,
NET_MASTER_PACKET_TYPE_ADD_RESPONSE,
NET_MASTER_PACKET_TYPE_QUERY,
- NET_MASTER_PACKET_TYPE_QUERY_RESPONSE
+ NET_MASTER_PACKET_TYPE_QUERY_RESPONSE,
+ NET_MASTER_PACKET_TYPE_GET_METADATA,
+ NET_MASTER_PACKET_TYPE_GET_METADATA_RESPONSE,
+ NET_MASTER_PACKET_TYPE_SIGN_START,
+ NET_MASTER_PACKET_TYPE_SIGN_START_RESPONSE,
+ NET_MASTER_PACKET_TYPE_SIGN_END,
+ NET_MASTER_PACKET_TYPE_SIGN_END_RESPONSE,
} net_master_packet_type_t;
+// Settings specified when the client connects to the server.
+
+typedef struct
+{
+ int gamemode;
+ int gamemission;
+ int lowres_turn;
+ int drone;
+ int max_players;
+ int is_freedoom;
- md5_digest_t wad_md5sum;
- md5_digest_t deh_md5sum;
++ sha1_digest_t wad_sha1sum;
++ sha1_digest_t deh_sha1sum;
+ int player_class;
+} net_connect_data_t;
+
+// Game settings sent by client to server when initiating game start,
+// and received from the server by clients when the game starts.
+
typedef struct
{
int ticdup;
@@@ -228,20 -181,5 +234,20 @@@ typedef struc
char *description;
} net_querydata_t;
-#endif /* #ifndef NET_DEFS_H */
+// Data sent by the server while waiting for the game to start.
+typedef struct
+{
+ int num_players;
+ int num_drones;
+ int max_players;
+ int is_controller;
+ int consoleplayer;
+ char player_names[NET_MAXPLAYERS][MAXPLAYERNAME];
+ char player_addrs[NET_MAXPLAYERS][MAXPLAYERNAME];
- md5_digest_t wad_md5sum;
- md5_digest_t deh_md5sum;
++ sha1_digest_t wad_sha1sum;
++ sha1_digest_t deh_sha1sum;
+ int is_freedoom;
+} net_waitdata_t;
+
+#endif /* #ifndef NET_DEFS_H */
diff --cc src/net_gui.c
index 7fff33f6,0ff9e55b..14d0d943
--- a/src/net_gui.c
+++ b/src/net_gui.c
@@@ -209,13 -178,11 +209,13 @@@ static void CheckSHA1Sums(void
return;
}
- correct_wad = memcmp(net_local_wad_md5sum,
- net_client_wait_data.wad_md5sum,
- sizeof(md5_digest_t)) == 0;
- correct_deh = memcmp(net_local_deh_md5sum,
- net_client_wait_data.deh_md5sum,
- sizeof(md5_digest_t)) == 0;
- correct_wad = memcmp(net_local_wad_sha1sum, net_server_wad_sha1sum,
++ correct_wad = memcmp(net_local_wad_sha1sum,
++ net_client_wait_data.wad_sha1sum,
+ sizeof(sha1_digest_t)) == 0;
- correct_deh = memcmp(net_local_deh_sha1sum, net_server_deh_sha1sum,
++ correct_deh = memcmp(net_local_deh_sha1sum,
++ net_client_wait_data.deh_sha1sum,
+ sizeof(sha1_digest_t)) == 0;
- same_freedoom = net_server_is_freedoom == net_local_is_freedoom;
+ same_freedoom = net_client_wait_data.is_freedoom == net_local_is_freedoom;
if (correct_wad && correct_deh && same_freedoom)
{
@@@ -224,9 -191,9 +224,9 @@@
if (!correct_wad)
{
- printf("Warning: WAD MD5 does not match server:\n");
- PrintMD5Digest("Local", net_local_wad_md5sum);
- PrintMD5Digest("Server", net_client_wait_data.wad_md5sum);
+ printf("Warning: WAD SHA1 does not match server:\n");
+ PrintSHA1Digest("Local", net_local_wad_sha1sum);
- PrintSHA1Digest("Server", net_server_wad_sha1sum);
++ PrintSHA1Digest("Server", net_client_wait_data.wad_sha1sum);
}
if (!same_freedoom)
@@@ -239,9 -206,9 +239,9 @@@
if (!correct_deh)
{
- printf("Warning: Dehacked MD5 does not match server:\n");
- PrintMD5Digest("Local", net_local_deh_md5sum);
- PrintMD5Digest("Server", net_client_wait_data.deh_md5sum);
+ printf("Warning: Dehacked SHA1 does not match server:\n");
+ PrintSHA1Digest("Local", net_local_deh_sha1sum);
- PrintSHA1Digest("Server", net_server_deh_sha1sum);
++ PrintSHA1Digest("Server", net_client_wait_data.deh_sha1sum);
}
window = TXT_NewWindow("WARNING");
@@@ -307,8 -273,8 +307,8 @@@ void NET_WaitForStart(net_gamesettings_
while (net_waiting_for_start)
{
- UpdateGUI();
+ UpdateGUI(settings);
- CheckMD5Sums();
+ CheckSHA1Sums();
TXT_DispatchEvents();
TXT_DrawDesktop();
diff --cc src/net_server.c
index b837bd70,189e824f..585f0eac
--- a/src/net_server.c
+++ b/src/net_server.c
@@@ -640,18 -622,17 +645,18 @@@ static void NET_SV_ParseSYN(net_packet_
// Adopt the game mode and mission of the first connecting client
- if (num_players == 0 && !cl_drone)
+ if (num_players == 0 && !data.drone)
{
- sv_gamemode = cl_gamemode;
- sv_gamemission = cl_gamemission;
+ sv_gamemode = data.gamemode;
+ sv_gamemission = data.gamemission;
}
- // Save the MD5 checksums
+ // Save the SHA1 checksums
- memcpy(client->wad_md5sum, data.wad_md5sum, sizeof(md5_digest_t));
- memcpy(client->deh_md5sum, data.deh_md5sum, sizeof(md5_digest_t));
- memcpy(client->wad_sha1sum, wad_sha1sum, sizeof(sha1_digest_t));
- memcpy(client->deh_sha1sum, deh_sha1sum, sizeof(sha1_digest_t));
- client->is_freedoom = is_freedoom;
++ memcpy(client->wad_sha1sum, data.wad_sha1sum, sizeof(sha1_digest_t));
++ memcpy(client->deh_sha1sum, data.deh_sha1sum, sizeof(sha1_digest_t));
+ client->is_freedoom = data.is_freedoom;
+ client->max_players = data.max_players;
// Check the connecting client is playing the same game as all
// the other clients
@@@ -1272,49 -1236,62 +1277,49 @@@ static void NET_SV_SendWaitingData(net_
controller = NET_SV_Controller();
- num_players = NET_SV_NumPlayers();
+ wait_data.num_players = NET_SV_NumPlayers();
+ wait_data.num_drones = NET_SV_NumDrones();
+ wait_data.max_players = NET_SV_MaxPlayers();
+ wait_data.is_controller = (client == controller);
+ wait_data.consoleplayer = client->player_number;
- // time to send the client another status packet
-
- packet = NET_NewPacket(10);
- NET_WriteInt16(packet, NET_PACKET_TYPE_WAITING_DATA);
-
- // include the number of players waiting
-
- NET_WriteInt8(packet, num_players);
-
- // send the number of drone clients
-
- NET_WriteInt8(packet, NET_SV_NumDrones());
-
- // indicate whether the client is the controller
-
- NET_WriteInt8(packet, client == controller);
-
- // send the player number of this client
-
- NET_WriteInt8(packet, client->player_number);
-
- // send the addresses of all players
+ // Send the WAD and dehacked checksums of the controlling client.
+ // If no controller found (?), send the details that the client
+ // is expecting anyway.
- for (i=0; i<num_players; ++i)
+ if (controller != NULL)
{
- char *addr;
-
- // name
+ controller = client;
+ }
- memcpy(&wait_data.wad_md5sum, &controller->wad_md5sum,
- sizeof(md5_digest_t));
- memcpy(&wait_data.deh_md5sum, &controller->deh_md5sum,
- sizeof(md5_digest_t));
- NET_WriteString(packet, sv_players[i]->name);
++ memcpy(&wait_data.wad_sha1sum, &controller->wad_sha1sum,
++ sizeof(sha1_digest_t));
++ memcpy(&wait_data.deh_sha1sum, &controller->deh_sha1sum,
++ sizeof(sha1_digest_t));
+ wait_data.is_freedoom = controller->is_freedoom;
- // address
+ // set name and address of each player:
- addr = NET_AddrToString(sv_players[i]->addr);
+ for (i = 0; i < wait_data.num_players; ++i)
+ {
+ strncpy(wait_data.player_names[i],
+ sv_players[i]->name,
+ MAXPLAYERNAME);
+ wait_data.player_names[i][MAXPLAYERNAME-1] = '\0';
- NET_WriteString(packet, addr);
+ strncpy(wait_data.player_addrs[i],
+ NET_AddrToString(sv_players[i]->addr),
+ MAXPLAYERNAME);
+ wait_data.player_addrs[i][MAXPLAYERNAME-1] = '\0';
}
- // Send the WAD and dehacked checksums of the controlling client.
+ // Construct packet:
- if (controller != NULL)
- {
- NET_WriteSHA1Sum(packet, controller->wad_sha1sum);
- NET_WriteSHA1Sum(packet, controller->deh_sha1sum);
- NET_WriteInt8(packet, controller->is_freedoom);
- }
- else
- {
- NET_WriteSHA1Sum(packet, client->wad_sha1sum);
- NET_WriteSHA1Sum(packet, client->deh_sha1sum);
- NET_WriteInt8(packet, client->is_freedoom);
- }
+ packet = NET_NewPacket(10);
+ NET_WriteInt16(packet, NET_PACKET_TYPE_WAITING_DATA);
+ NET_WriteWaitData(packet, &wait_data);
- // send packet to client and free
+ // Send packet to client and free
NET_Conn_SendPacket(&client->connection, packet);
NET_FreePacket(packet);
diff --cc src/net_structrw.c
index f68a6130,818766e4..8f6f8d57
--- a/src/net_structrw.c
+++ b/src/net_structrw.c
@@@ -31,36 -29,8 +31,36 @@@
#include "net_packet.h"
#include "net_structrw.h"
+void NET_WriteConnectData(net_packet_t *packet, net_connect_data_t *data)
+{
+ NET_WriteInt8(packet, data->gamemode);
+ NET_WriteInt8(packet, data->gamemission);
+ NET_WriteInt8(packet, data->lowres_turn);
+ NET_WriteInt8(packet, data->drone);
+ NET_WriteInt8(packet, data->max_players);
+ NET_WriteInt8(packet, data->is_freedoom);
- NET_WriteMD5Sum(packet, data->wad_md5sum);
- NET_WriteMD5Sum(packet, data->deh_md5sum);
++ NET_WriteSHA1Sum(packet, data->wad_sha1sum);
++ NET_WriteSHA1Sum(packet, data->deh_sha1sum);
+ NET_WriteInt8(packet, data->player_class);
+}
+
+boolean NET_ReadConnectData(net_packet_t *packet, net_connect_data_t *data)
+{
+ return NET_ReadInt8(packet, (unsigned int *) &data->gamemode)
+ && NET_ReadInt8(packet, (unsigned int *) &data->gamemission)
+ && NET_ReadInt8(packet, (unsigned int *) &data->lowres_turn)
+ && NET_ReadInt8(packet, (unsigned int *) &data->drone)
+ && NET_ReadInt8(packet, (unsigned int *) &data->max_players)
+ && NET_ReadInt8(packet, (unsigned int *) &data->is_freedoom)
- && NET_ReadMD5Sum(packet, data->wad_md5sum)
- && NET_ReadMD5Sum(packet, data->deh_md5sum)
++ && NET_ReadSHA1Sum(packet, data->wad_sha1sum)
++ && NET_ReadSHA1Sum(packet, data->deh_sha1sum)
+ && NET_ReadInt8(packet, (unsigned int *) &data->player_class);
+}
+
void NET_WriteSettings(net_packet_t *packet, net_gamesettings_t *settings)
{
+ int i;
+
NET_WriteInt8(packet, settings->ticdup);
NET_WriteInt8(packet, settings->extratics);
NET_WriteInt8(packet, settings->deathmatch);
@@@ -445,68 -321,7 +445,68 @@@ void NET_WriteFullTiccmd(net_packet_t *
}
}
+void NET_WriteWaitData(net_packet_t *packet, net_waitdata_t *data)
+{
+ int i;
+
+ NET_WriteInt8(packet, data->num_players);
+ NET_WriteInt8(packet, data->num_drones);
+ NET_WriteInt8(packet, data->max_players);
+ NET_WriteInt8(packet, data->is_controller);
+ NET_WriteInt8(packet, data->consoleplayer);
+
+ for (i = 0; i < data->num_players && i < NET_MAXPLAYERS; ++i)
+ {
+ NET_WriteString(packet, data->player_names[i]);
+ NET_WriteString(packet, data->player_addrs[i]);
+ }
+
- NET_WriteMD5Sum(packet, data->wad_md5sum);
- NET_WriteMD5Sum(packet, data->deh_md5sum);
++ NET_WriteSHA1Sum(packet, data->wad_sha1sum);
++ NET_WriteSHA1Sum(packet, data->deh_sha1sum);
+ NET_WriteInt8(packet, data->is_freedoom);
+}
+
+boolean NET_ReadWaitData(net_packet_t *packet, net_waitdata_t *data)
+{
+ int i;
+ char *s;
+
+ if (!NET_ReadInt8(packet, (unsigned int *) &data->num_players)
+ || !NET_ReadInt8(packet, (unsigned int *) &data->num_drones)
+ || !NET_ReadInt8(packet, (unsigned int *) &data->max_players)
+ || !NET_ReadInt8(packet, (unsigned int *) &data->is_controller)
+ || !NET_ReadSInt8(packet, &data->consoleplayer))
+ {
+ return false;
+ }
+
+ for (i = 0; i < data->num_players && i < NET_MAXPLAYERS; ++i)
+ {
+ s = NET_ReadString(packet);
+
+ if (s == NULL || strlen(s) >= MAXPLAYERNAME)
+ {
+ return false;
+ }
+
+ strcpy(data->player_names[i], s);
+
+ s = NET_ReadString(packet);
+
+ if (s == NULL || strlen(s) >= MAXPLAYERNAME)
+ {
+ return false;
+ }
+
+ strcpy(data->player_addrs[i], s);
+ }
+
- return NET_ReadMD5Sum(packet, data->wad_md5sum)
- && NET_ReadMD5Sum(packet, data->deh_md5sum)
++ return NET_ReadSHA1Sum(packet, data->wad_sha1sum)
++ && NET_ReadSHA1Sum(packet, data->deh_sha1sum)
+ && NET_ReadInt8(packet, (unsigned int *) &data->is_freedoom);
+}
+
- boolean NET_ReadMD5Sum(net_packet_t *packet, md5_digest_t digest)
+ static boolean NET_ReadBlob(net_packet_t *packet, uint8_t *buf, size_t len)
{
unsigned int b;
int i;
@@@ -534,22 -349,23 +534,42 @@@ static void NET_WriteBlob(net_packet_t
}
}
+ boolean NET_ReadSHA1Sum(net_packet_t *packet, sha1_digest_t digest)
+ {
+ return NET_ReadBlob(packet, digest, sizeof(sha1_digest_t));
+ }
+
+ void NET_WriteSHA1Sum(net_packet_t *packet, sha1_digest_t digest)
+ {
+ NET_WriteBlob(packet, digest, sizeof(sha1_digest_t));
+ }
+
+ boolean NET_ReadPRNGSeed(net_packet_t *packet, prng_seed_t seed)
+ {
+ return NET_ReadBlob(packet, seed, sizeof(prng_seed_t));
+ }
+
+ void NET_WritePRNGSeed(net_packet_t *packet, prng_seed_t seed)
+ {
+ NET_WriteBlob(packet, seed, sizeof(prng_seed_t));
+ }
+
+// "Safe" version of puts, for displaying messages received from the
+// network.
+
+void NET_SafePuts(char *s)
+{
+ char *p;
+
+ // Do not do a straight "puts" of the string, as this could be
+ // dangerous (sending control codes to terminals can do all
+ // kinds of things)
+
+ for (p=s; *p; ++p)
+ {
+ if (isprint(*p))
+ putchar(*p);
+ }
+
+ putchar('\n');
+}
diff --cc src/net_structrw.h
index e894e170,23bd67a1..3d446841
--- a/src/net_structrw.h
+++ b/src/net_structrw.h
@@@ -43,12 -41,11 +44,15 @@@ extern void NET_TiccmdPatch(ticcmd_t *s
boolean NET_ReadFullTiccmd(net_packet_t *packet, net_full_ticcmd_t *cmd, boolean lowres_turn);
void NET_WriteFullTiccmd(net_packet_t *packet, net_full_ticcmd_t *cmd, boolean lowres_turn);
- boolean NET_ReadMD5Sum(net_packet_t *packet, md5_digest_t digest);
- void NET_WriteMD5Sum(net_packet_t *packet, md5_digest_t digest);
+ boolean NET_ReadSHA1Sum(net_packet_t *packet, sha1_digest_t digest);
+ void NET_WriteSHA1Sum(net_packet_t *packet, sha1_digest_t digest);
+void NET_WriteWaitData(net_packet_t *packet, net_waitdata_t *data);
+boolean NET_ReadWaitData(net_packet_t *packet, net_waitdata_t *data);
+
+void NET_SafePuts(char *msg);
+
+ boolean NET_ReadPRNGSeed(net_packet_t *packet, prng_seed_t seed);
+ void NET_WritePRNGSeed(net_packet_t *packet, prng_seed_t seed);
+
#endif /* #ifndef NET_STRUCTRW_H */
-
diff --cc src/setup/Makefile.am
index 7fe051ee,9263a3a8..f58c6294
--- a/src/setup/Makefile.am
+++ b/src/setup/Makefile.am
@@@ -31,12 -40,17 +31,12 @@@ appdir = $(prefix)/share/application
app_DATA = @PROGRAM_PREFIX@setup.desktop
@PROGRAM_PREFIX@setup.desktop : setup.desktop
- cp $^ $@
+ cp setup.desktop $@
-.rc.o:
- $(WINDRES) $^ -o $@
-%.o : %.rc
- $(WINDRES) $^ -o $@
-
if HAVE_PYTHON
-setup_icon.c : ../data/setup8.ico
- ../data/convert-icon ../data/setup8.ico $@
+setup_icon.c : $(top_builddir)/data/setup8.ico
+ $(top_builddir)/data/convert-icon $^ $@
endif
diff --cc src/setup/multiplayer.c
index d9bda1fe,e8977763..dc0643e3
--- a/src/setup/multiplayer.c
+++ b/src/setup/multiplayer.c
@@@ -1010,12 -824,22 +1032,22 @@@ void SetPlayerNameDefault(void
if (net_player_name == NULL)
{
- net_player_name = getenv("USERNAME");
+ net_player_name = strdup(getenv("USERNAME"));
}
+ // On Windows, environment variables are in OEM codepage
+ // encoding, so convert to UTF8:
+
+ #ifdef _WIN32
+ if (net_player_name != NULL)
+ {
+ net_player_name = M_OEMToUTF8(net_player_name);
+ }
+ #endif
+
if (net_player_name == NULL)
{
- net_player_name = "player";
+ net_player_name = strdup("player");
}
}
diff --cc src/strife/d_net.c
index cd0a5e66,00000000..a3f5513c
mode 100644,000000..100644
--- a/src/strife/d_net.c
+++ b/src/strife/d_net.c
@@@ -1,316 -1,0 +1,316 @@@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 1993-1996 Id Software, Inc.
+// 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.
+//
+// DESCRIPTION:
+// DOOM Network game communication and protocol,
+// all OS independend parts.
+//
+//-----------------------------------------------------------------------------
+
+#include <stdlib.h>
+
+#include "doomfeatures.h"
+
+#include "d_main.h"
+#include "m_argv.h"
+#include "m_menu.h"
+#include "i_system.h"
+#include "i_timer.h"
+#include "i_video.h"
+#include "g_game.h"
+#include "doomdef.h"
+#include "doomstat.h"
+#include "w_checksum.h"
+
+#include "deh_main.h"
+
+#include "d_loop.h"
+
+ticcmd_t *netcmds;
+
+// Called when a player leaves the game
+
+static void PlayerQuitGame(player_t *player)
+{
+ static char exitmsg[80];
+ unsigned int player_num;
+
+ player_num = player - players;
+
+ // Do this the same way as Vanilla Doom does, to allow dehacked
+ // replacements of this message
+
+ strncpy(exitmsg, DEH_String("Player 1 left the game"), sizeof(exitmsg));
+ exitmsg[sizeof(exitmsg) - 1] = '\0';
+
+ exitmsg[7] += player_num;
+
+ playeringame[player_num] = false;
+ players[consoleplayer].message = exitmsg;
+
+ // TODO: check if it is sensible to do this:
+
+ if (demorecording)
+ {
+ G_CheckDemoStatus ();
+ }
+}
+
+static void RunTic(ticcmd_t *cmds, boolean *ingame)
+{
+ extern boolean advancedemo;
+ unsigned int i;
+
+ // Check for player quits.
+
+ for (i = 0; i < MAXPLAYERS; ++i)
+ {
+ if (!demoplayback && playeringame[i] && !ingame[i])
+ {
+ PlayerQuitGame(&players[i]);
+ }
+ }
+
+ netcmds = cmds;
+
+ // check that there are players in the game. if not, we cannot
+ // run a tic.
+
+ if (advancedemo)
+ D_DoAdvanceDemo ();
+
+ M_Ticker();
+ G_Ticker();
+}
+
+static void NullMenuTicker()
+{
+ // no-op.
+}
+
+static loop_interface_t strife_loop_interface = {
+ D_ProcessEvents,
+ G_BuildTiccmd,
+ RunTic,
+ NullMenuTicker
+};
+
+
+// Load game settings from the specified structure and
+// set global variables.
+
+static void LoadGameSettings(net_gamesettings_t *settings,
+ net_connect_data_t *connect_data)
+{
+ unsigned int i;
+
+ deathmatch = settings->deathmatch;
+ ticdup = settings->ticdup;
+ startepisode = settings->episode;
+ startmap = settings->map;
+ startskill = settings->skill;
+ startloadgame = settings->loadgame;
+ lowres_turn = settings->lowres_turn;
+ nomonsters = settings->nomonsters;
+ fastparm = settings->fast_monsters;
+ respawnparm = settings->respawn_monsters;
+ timelimit = settings->timelimit;
+
+ if (lowres_turn)
+ {
+ printf("NOTE: Turning resolution is reduced; this is probably "
+ "because there is a client recording a Vanilla demo.\n");
+ }
+
+ if (!connect_data->drone)
+ {
+ consoleplayer = settings->consoleplayer;
+ }
+ else
+ {
+ consoleplayer = 0;
+ }
+
+ for (i=0; i<MAXPLAYERS; ++i)
+ {
+ playeringame[i] = i < settings->num_players;
+ }
+}
+
+// Save the game settings from global variables to the specified
+// game settings structure.
+
+static void SaveGameSettings(net_gamesettings_t *settings,
+ net_connect_data_t *connect_data)
+{
+ // Fill in game settings structure with appropriate parameters
+ // for the new game
+
+ settings->deathmatch = deathmatch;
+ settings->episode = startepisode;
+ settings->map = startmap;
+ settings->skill = startskill;
+ settings->loadgame = startloadgame;
+ settings->gameversion = gameversion;
+ settings->nomonsters = nomonsters;
+ settings->fast_monsters = fastparm;
+ settings->respawn_monsters = respawnparm;
+ settings->timelimit = timelimit;
+
+ settings->lowres_turn = M_CheckParm("-record") > 0
+ && M_CheckParm("-longtics") == 0;
+
+ connect_data->drone = false;
+ connect_data->max_players = MAXPLAYERS;
+
+ //!
+ // @category net
+ //
+ // Run as the left screen in three screen mode.
+ //
+
+ if (M_CheckParm("-left") > 0)
+ {
+ viewangleoffset = ANG90;
+ connect_data->drone = true;
+ }
+
+ //!
+ // @category net
+ //
+ // Run as the right screen in three screen mode.
+ //
+
+ if (M_CheckParm("-right") > 0)
+ {
+ viewangleoffset = ANG270;
+ connect_data->drone = true;
+ }
+
+ //
+ // Connect data
+ //
+
+ // Game type fields:
+
+ connect_data->gamemode = gamemode;
+ connect_data->gamemission = gamemission;
+
+ // Are we recording a demo? Possibly set lowres turn mode
+
+ connect_data->lowres_turn = settings->lowres_turn;
+
+ // Read checksums of our WAD directory and dehacked information
+
- W_Checksum(connect_data->wad_md5sum);
- DEH_Checksum(connect_data->deh_md5sum);
++ W_Checksum(connect_data->wad_sha1sum);
++ DEH_Checksum(connect_data->deh_sha1sum);
+
+ connect_data->is_freedoom = 0;
+}
+
+void D_InitSinglePlayerGame(net_gamesettings_t *settings)
+{
+ // default values for single player
+
+ settings->consoleplayer = 0;
+ settings->num_players = 1;
+
+ netgame = false;
+
+ //!
+ // @category net
+ //
+ // Start the game playing as though in a netgame with a single
+ // player. This can also be used to play back single player netgame
+ // demos.
+ //
+
+ if (M_CheckParm("-solo-net") > 0)
+ {
+ netgame = true;
+ }
+}
+
+//
+// D_CheckNetGame
+// Works out player numbers among the net participants
+//
+void D_CheckNetGame (void)
+{
+ net_connect_data_t connect_data;
+ net_gamesettings_t settings;
+
+ D_RegisterLoopCallbacks(&strife_loop_interface);
+
+ // Call D_QuitNetGame on exit
+
+ I_AtExit(D_QuitNetGame, true);
+
+ SaveGameSettings(&settings, &connect_data);
+
+ if (D_InitNetGame(&connect_data, &settings))
+ {
+ netgame = true;
+ autostart = true;
+ }
+ else
+ {
+ D_InitSinglePlayerGame(&settings);
+ }
+
+ LoadGameSettings(&settings, &connect_data);
+
+ // Strife games are always deathmatch, though -altdeath is
+ // supported for respawning items.
+
+ if (netgame && deathmatch == 0)
+ {
+ deathmatch = 1;
+ }
+
+ DEH_printf("startmap: %i, skill: %i, enemies: %i, random: %i\n",
+ startmap, startskill, !nomonsters, 0 /* ??? */);
+
+
+ DEH_printf("player %i of %i (%i nodes)\n",
+ consoleplayer+1, settings.num_players, settings.num_players);
+
+ // Show players here; the server might have specified a time limit
+
+ if (timelimit > 0 && deathmatch)
+ {
+ // Gross hack to work like Vanilla:
+
+ if (timelimit == 20 && M_CheckParm("-avg"))
+ {
+ DEH_printf("Austin Virtual Gaming: Levels will end "
+ "after 20 minutes\n");
+ }
+ else
+ {
+ DEH_printf("Levels will end after %d minute", timelimit);
+ if (timelimit > 1)
+ printf("s");
+ printf(".\n");
+ }
+ }
+}
+
diff --cc src/strife/deh_ammo.c
index 2c6a9022,00000000..952d8df3
mode 100644,000000..100644
--- a/src/strife/deh_ammo.c
+++ b/src/strife/deh_ammo.c
@@@ -1,112 -1,0 +1,112 @@@
+// 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 "Ammo" sections in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "doomdef.h"
+#include "doomtype.h"
+#include "deh_defs.h"
+#include "deh_io.h"
+#include "deh_main.h"
+#include "p_local.h"
+
+static void *DEH_AmmoStart(deh_context_t *context, char *line)
+{
+ int ammo_number = 0;
+
+ if (sscanf(line, "Ammo %i", &ammo_number) != 1)
+ {
+ DEH_Warning(context, "Parse error on section start");
+ return NULL;
+ }
+
+ if (ammo_number < 0 || ammo_number >= NUMAMMO)
+ {
+ DEH_Warning(context, "Invalid ammo number: %i", ammo_number);
+ return NULL;
+ }
+
+ return &maxammo[ammo_number];
+}
+
+static void DEH_AmmoParseLine(deh_context_t *context, char *line, void *tag)
+{
+ char *variable_name, *value;
+ int ivalue;
+ int ammo_number;
+
+ if (tag == NULL)
+ return;
+
+ ammo_number = ((int *) tag) - maxammo;
+
+ // Parse the assignment
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {
+ // Failed to parse
+
+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+ ivalue = atoi(value);
+
+ // maxammo
+
+ if (!strcasecmp(variable_name, "Per ammo"))
+ clipammo[ammo_number] = ivalue;
+ else if (!strcasecmp(variable_name, "Max ammo"))
+ maxammo[ammo_number] = ivalue;
+ else
+ {
+ DEH_Warning(context, "Field named '%s' not found", variable_name);
+ }
+}
+
- static void DEH_AmmoMD5Hash(md5_context_t *context)
++static void DEH_AmmoSHA1Hash(sha1_context_t *context)
+{
+ int i;
+
+ for (i=0; i<NUMAMMO; ++i)
+ {
- MD5_UpdateInt32(context, clipammo[i]);
- MD5_UpdateInt32(context, maxammo[i]);
++ SHA1_UpdateInt32(context, clipammo[i]);
++ SHA1_UpdateInt32(context, maxammo[i]);
+ }
+}
+
+deh_section_t deh_section_ammo =
+{
+ "Ammo",
+ NULL,
+ DEH_AmmoStart,
+ DEH_AmmoParseLine,
+ NULL,
- DEH_AmmoMD5Hash,
++ DEH_AmmoSHA1Hash,
+};
+
diff --cc src/strife/deh_frame.c
index 9383b94f,00000000..dc68fde5
mode 100644,000000..100644
--- a/src/strife/deh_frame.c
+++ b/src/strife/deh_frame.c
@@@ -1,168 -1,0 +1,168 @@@
+// 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 "Frame" sections in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "doomtype.h"
+#include "d_items.h"
+#include "info.h"
+
+#include "deh_defs.h"
+#include "deh_io.h"
+#include "deh_main.h"
+#include "deh_mapping.h"
+
+DEH_BEGIN_MAPPING(state_mapping, state_t)
+ DEH_MAPPING("Sprite number", sprite)
+ DEH_MAPPING("Sprite subnumber", frame)
+ DEH_MAPPING("Duration", tics)
+ DEH_MAPPING("Next frame", nextstate)
+ DEH_UNSUPPORTED_MAPPING("Action pointer")
+DEH_END_MAPPING
+
+static void *DEH_FrameStart(deh_context_t *context, char *line)
+{
+ int frame_number = 0;
+ state_t *state;
+
+ if (sscanf(line, "Frame %i", &frame_number) != 1)
+ {
+ DEH_Warning(context, "Parse error on section start");
+ return NULL;
+ }
+
+ if (frame_number < 0 || frame_number >= NUMSTATES)
+ {
+ DEH_Warning(context, "Invalid frame number: %i", frame_number);
+ return NULL;
+ }
+
+ if (frame_number >= DEH_VANILLA_NUMSTATES)
+ {
+ DEH_Warning(context, "Attempt to modify frame %i: this will cause "
+ "problems in Vanilla dehacked.", frame_number);
+ }
+
+ state = &states[frame_number];
+
+ return state;
+}
+
+// Simulate a frame overflow: Doom has 967 frames in the states[] array, but
+// DOS dehacked internally only allocates memory for 966. As a result,
+// attempts to set frame 966 (the last frame) will overflow the dehacked
+// array and overwrite the weaponinfo[] array instead.
+//
+// This is noticable in Batman Doom where it is impossible to switch weapons
+// away from the fist once selected.
+
+static void DEH_FrameOverflow(deh_context_t *context, char *varname, int value)
+{
+ if (!strcasecmp(varname, "Duration"))
+ {
+ weaponinfo[0].ammo = value;
+ }
+ else if (!strcasecmp(varname, "Codep frame"))
+ {
+ weaponinfo[0].upstate = value;
+ }
+ else if (!strcasecmp(varname, "Next frame"))
+ {
+ weaponinfo[0].downstate = value;
+ }
+ else if (!strcasecmp(varname, "Unknown 1"))
+ {
+ weaponinfo[0].readystate = value;
+ }
+ else if (!strcasecmp(varname, "Unknown 2"))
+ {
+ weaponinfo[0].atkstate = value;
+ }
+ else
+ {
+ DEH_Error(context, "Unable to simulate frame overflow: field '%s'",
+ varname);
+ }
+}
+
+static void DEH_FrameParseLine(deh_context_t *context, char *line, void *tag)
+{
+ state_t *state;
+ char *variable_name, *value;
+ int ivalue;
+
+ if (tag == NULL)
+ return;
+
+ state = (state_t *) tag;
+
+ // Parse the assignment
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {
+ // Failed to parse
+
+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+ // all values are integers
+
+ ivalue = atoi(value);
+
+ if (state == &states[NUMSTATES - 1])
+ {
+ DEH_FrameOverflow(context, variable_name, ivalue);
+ }
+ else
+ {
+ // set the appropriate field
+
+ DEH_SetMapping(context, &state_mapping, state, variable_name, ivalue);
+ }
+}
+
- static void DEH_FrameMD5Sum(md5_context_t *context)
++static void DEH_FrameSHA1Sum(sha1_context_t *context)
+{
+ int i;
+
+ for (i=0; i<NUMSTATES; ++i)
+ {
- DEH_StructMD5Sum(context, &state_mapping, &states[i]);
++ DEH_StructSHA1Sum(context, &state_mapping, &states[i]);
+ }
+}
+
+deh_section_t deh_section_frame =
+{
+ "Frame",
+ NULL,
+ DEH_FrameStart,
+ DEH_FrameParseLine,
+ NULL,
- DEH_FrameMD5Sum,
++ DEH_FrameSHA1Sum,
+};
+
diff --cc src/strife/deh_misc.c
index e3f2606c,00000000..aaebbadd
mode 100644,000000..100644
--- a/src/strife/deh_misc.c
+++ b/src/strife/deh_misc.c
@@@ -1,237 -1,0 +1,237 @@@
+// 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 "Misc" sections in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "doomtype.h"
+#include "deh_defs.h"
+#include "deh_io.h"
+#include "deh_main.h"
+#include "deh_misc.h"
+
+// Dehacked: "Initial Health"
+// This is the initial health a player has when starting anew.
+// See G_PlayerReborn in g_game.c
+
+int deh_initial_health = DEH_DEFAULT_INITIAL_HEALTH;
+
+// Dehacked: "Initial bullets"
+// This is the number of bullets the player has when starting anew.
+// See G_PlayerReborn in g_game.c
+
+int deh_initial_bullets = DEH_DEFAULT_INITIAL_BULLETS;
+
+// Dehacked: "Max Health"
+// This is the maximum health that can be reached using medikits
+// alone. See P_TouchSpecialThing in p_inter.c
+
+int deh_max_health = DEH_DEFAULT_MAX_HEALTH;
+
+// Dehacked: "Max Armor"
+// This is the maximum armor which can be reached by picking up
+// armor helmets. See P_TouchSpecialThing in p_inter.c
+
+int deh_max_armor = DEH_DEFAULT_MAX_ARMOR;
+
+// Dehacked: "Green Armor Class"
+// This is the armor class that is given when picking up the green
+// armor or an armor helmet. See P_TouchSpecialThing in p_inter.c
+//
+// DOS dehacked only modifies the behavior of the green armor shirt,
+// the armor class set by armor helmets is not affected.
+
+int deh_green_armor_class = DEH_DEFAULT_GREEN_ARMOR_CLASS;
+
+// Dehacked: "Blue Armor Class"
+// This is the armor class that is given when picking up the blue
+// armor or a megasphere. See P_TouchSpecialThing in p_inter.c
+//
+// DOS dehacked only modifies the MegaArmor behavior and not
+// the MegaSphere, which always gives armor type 2.
+
+int deh_blue_armor_class = DEH_DEFAULT_BLUE_ARMOR_CLASS;
+
+// Dehacked: "Max soulsphere"
+// The maximum health which can be reached by picking up the
+// soulsphere. See P_TouchSpecialThing in p_inter.c
+
+int deh_max_soulsphere = DEH_DEFAULT_MAX_SOULSPHERE;
+
+// Dehacked: "Soulsphere health"
+// The amount of health bonus that picking up a soulsphere
+// gives. See P_TouchSpecialThing in p_inter.c
+
+int deh_soulsphere_health = DEH_DEFAULT_SOULSPHERE_HEALTH;
+
+// Dehacked: "Megasphere health"
+// This is what the health is set to after picking up a
+// megasphere. See P_TouchSpecialThing in p_inter.c
+
+int deh_megasphere_health = DEH_DEFAULT_MEGASPHERE_HEALTH;
+
+// Dehacked: "God mode health"
+// This is what the health value is set to when cheating using
+// the IDDQD god mode cheat. See ST_Responder in st_stuff.c
+
+int deh_god_mode_health = DEH_DEFAULT_GOD_MODE_HEALTH;
+
+// Dehacked: "IDFA Armor"
+// This is what the armor is set to when using the IDFA cheat.
+// See ST_Responder in st_stuff.c
+
+int deh_idfa_armor = DEH_DEFAULT_IDFA_ARMOR;
+
+// Dehacked: "IDFA Armor Class"
+// This is what the armor class is set to when using the IDFA cheat.
+// See ST_Responder in st_stuff.c
+
+int deh_idfa_armor_class = DEH_DEFAULT_IDFA_ARMOR_CLASS;
+
+// Dehacked: "IDKFA Armor"
+// This is what the armor is set to when using the IDKFA cheat.
+// See ST_Responder in st_stuff.c
+
+int deh_idkfa_armor = DEH_DEFAULT_IDKFA_ARMOR;
+
+// Dehacked: "IDKFA Armor Class"
+// This is what the armor class is set to when using the IDKFA cheat.
+// See ST_Responder in st_stuff.c
+
+int deh_idkfa_armor_class = DEH_DEFAULT_IDKFA_ARMOR_CLASS;
+
+// Dehacked: "BFG Cells/Shot"
+// This is the number of CELLs firing the BFG uses up.
+// See P_CheckAmmo and A_FireBFG in p_pspr.c
+
+int deh_bfg_cells_per_shot = DEH_DEFAULT_BFG_CELLS_PER_SHOT;
+
+// Dehacked: "Monsters infight"
+// This controls whether monsters can harm other monsters of the same
+// species. For example, whether an imp fireball will damage other
+// imps. The value of this in dehacked patches is weird - '202' means
+// off, while '221' means on.
+//
+// See PIT_CheckThing in p_map.c
+
+int deh_species_infighting = DEH_DEFAULT_SPECIES_INFIGHTING;
+
+static struct
+{
+ char *deh_name;
+ int *value;
+} misc_settings[] = {
+ {"Initial Health", &deh_initial_health},
+ {"Initial Bullets", &deh_initial_bullets},
+ {"Max Health", &deh_max_health},
+ {"Max Armor", &deh_max_armor},
+ {"LeatherArmorClass", &deh_green_armor_class},
+ {"Metal Armor Class", &deh_blue_armor_class},
+ {"Max Soulsphere", &deh_max_soulsphere},
+ {"Soulsphere Health", &deh_soulsphere_health},
+ {"Megasphere Health", &deh_megasphere_health},
+ {"God Mode Health", &deh_god_mode_health},
+ {"IDFA Armor", &deh_idfa_armor},
+ {"IDFA Armor Class", &deh_idfa_armor_class},
+ {"IDKFA Armor", &deh_idkfa_armor},
+ {"IDKFA Armor Class", &deh_idkfa_armor_class},
+ {"Mauler Cells/Shot", &deh_bfg_cells_per_shot},
+};
+
+static void *DEH_MiscStart(deh_context_t *context, char *line)
+{
+ return NULL;
+}
+
+static void DEH_MiscParseLine(deh_context_t *context, char *line, void *tag)
+{
+ char *variable_name, *value;
+ int ivalue;
+ size_t i;
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {
+ // Failed to parse
+
+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+ ivalue = atoi(value);
+
+ if (!strcasecmp(variable_name, "Monsters Infight"))
+ {
+ // See notes above.
+
+ if (ivalue == 202)
+ {
+ deh_species_infighting = 0;
+ }
+ else if (ivalue == 221)
+ {
+ deh_species_infighting = 1;
+ }
+ else
+ {
+ DEH_Warning(context,
+ "Invalid value for 'Monsters Infight': %i", ivalue);
+ }
+
+ return;
+ }
+
+ for (i=0; i<arrlen(misc_settings); ++i)
+ {
+ if (!strcasecmp(variable_name, misc_settings[i].deh_name))
+ {
+ *misc_settings[i].value = ivalue;
+ return;
+ }
+ }
+
+ DEH_Warning(context, "Unknown Misc variable '%s'", variable_name);
+}
+
- static void DEH_MiscMD5Sum(md5_context_t *context)
++static void DEH_MiscSHA1Sum(sha1_context_t *context)
+{
+ unsigned int i;
+
+ for (i=0; i<arrlen(misc_settings); ++i)
+ {
- MD5_UpdateInt32(context, *misc_settings[i].value);
++ SHA1_UpdateInt32(context, *misc_settings[i].value);
+ }
+}
+
+deh_section_t deh_section_misc =
+{
+ "Misc",
+ NULL,
+ DEH_MiscStart,
+ DEH_MiscParseLine,
+ NULL,
- DEH_MiscMD5Sum,
++ DEH_MiscSHA1Sum,
+};
+
diff --cc src/strife/deh_ptr.c
index d757a178,00000000..0d1764c9
mode 100644,000000..100644
--- a/src/strife/deh_ptr.c
+++ b/src/strife/deh_ptr.c
@@@ -1,151 -1,0 +1,151 @@@
+// 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 Action Pointer entries in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "doomtype.h"
+#include "info.h"
+
+#include "deh_defs.h"
+#include "deh_io.h"
+#include "deh_main.h"
+
+static actionf_t codeptrs[NUMSTATES];
+
+static int CodePointerIndex(actionf_t *ptr)
+{
+ int i;
+
+ for (i=0; i<NUMSTATES; ++i)
+ {
+ if (!memcmp(&codeptrs[i], ptr, sizeof(actionf_t)))
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+static void DEH_PointerInit(void)
+{
+ int i;
+
+ // Initialize list of dehacked pointers
+
+ for (i=0; i<NUMSTATES; ++i)
+ codeptrs[i] = states[i].action;
+}
+
+static void *DEH_PointerStart(deh_context_t *context, char *line)
+{
+ int frame_number = 0;
+
+ // FIXME: can the third argument here be something other than "Frame"
+ // or are we ok?
+
+ if (sscanf(line, "Pointer %*i (%*s %i)", &frame_number) != 1)
+ {
+ DEH_Warning(context, "Parse error on section start");
+ return NULL;
+ }
+
+ if (frame_number < 0 || frame_number >= NUMSTATES)
+ {
+ DEH_Warning(context, "Invalid frame number: %i", frame_number);
+ return NULL;
+ }
+
+ return &states[frame_number];
+}
+
+static void DEH_PointerParseLine(deh_context_t *context, char *line, void *tag)
+{
+ state_t *state;
+ char *variable_name, *value;
+ int ivalue;
+
+ if (tag == NULL)
+ return;
+
+ state = (state_t *) tag;
+
+ // Parse the assignment
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {
+ // Failed to parse
+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+// printf("Set %s to %s for state\n", variable_name, value);
+
+ // all values are integers
+
+ ivalue = atoi(value);
+
+ // set the appropriate field
+
+ if (!strcasecmp(variable_name, "Codep frame"))
+ {
+ if (ivalue < 0 || ivalue >= NUMSTATES)
+ {
+ DEH_Warning(context, "Invalid state '%i'", ivalue);
+ }
+ else
+ {
+ state->action = codeptrs[ivalue];
+ }
+ }
+ else
+ {
+ DEH_Warning(context, "Unknown variable name '%s'", variable_name);
+ }
+}
+
- static void DEH_PointerMD5Sum(md5_context_t *context)
++static void DEH_PointerSHA1Sum(sha1_context_t *context)
+{
+ int i;
+
+ for (i=0; i<NUMSTATES; ++i)
+ {
- MD5_UpdateInt32(context, CodePointerIndex(&states[i].action));
++ SHA1_UpdateInt32(context, CodePointerIndex(&states[i].action));
+ }
+}
+
+deh_section_t deh_section_pointer =
+{
+ "Pointer",
+ DEH_PointerInit,
+ DEH_PointerStart,
+ DEH_PointerParseLine,
+ NULL,
- DEH_PointerMD5Sum,
++ DEH_PointerSHA1Sum,
+};
+
diff --cc src/strife/deh_thing.c
index 14b23b0a,00000000..a1c1f94d
mode 100644,000000..100644
--- a/src/strife/deh_thing.c
+++ b/src/strife/deh_thing.c
@@@ -1,141 -1,0 +1,141 @@@
+// 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 "Thing" sections in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "doomtype.h"
+
+#include "deh_defs.h"
+#include "deh_main.h"
+#include "deh_mapping.h"
+
+#include "info.h"
+
+DEH_BEGIN_MAPPING(thing_mapping, mobjinfo_t)
+ DEH_MAPPING("ID #", doomednum)
+ DEH_MAPPING("Initial frame", spawnstate)
+ DEH_MAPPING("Hit points", spawnhealth)
+ DEH_MAPPING("First moving frame", seestate)
+ DEH_MAPPING("Alert sound", seesound)
+ DEH_MAPPING("Reaction time", reactiontime)
+ DEH_MAPPING("Attack sound", attacksound)
+ DEH_MAPPING("Injury frame", painstate)
+ DEH_MAPPING("Pain chance", painchance)
+ DEH_MAPPING("Pain sound", painsound)
+ DEH_MAPPING("Close attack frame", meleestate)
+ DEH_MAPPING("Far attack frame", missilestate)
+ DEH_MAPPING("Crash frame", crashstate)
+ DEH_MAPPING("Death frame", deathstate)
+ DEH_MAPPING("Exploding frame", xdeathstate)
+ DEH_MAPPING("Death sound", deathsound)
+ DEH_MAPPING("Speed", speed)
+ DEH_MAPPING("Width", radius)
+ DEH_MAPPING("Height", height)
+ DEH_MAPPING("Mass", mass)
+ DEH_MAPPING("Missile damage", damage)
+ DEH_MAPPING("Action sound", activesound)
+ DEH_MAPPING("Bits", flags)
+ DEH_UNSUPPORTED_MAPPING("Name pointer")
+DEH_END_MAPPING
+
+static void *DEH_ThingStart(deh_context_t *context, char *line)
+{
+ int thing_number = 0;
+ mobjinfo_t *mobj;
+
+ if (sscanf(line, "Thing %i", &thing_number) != 1)
+ {
+ DEH_Warning(context, "Parse error on section start");
+ return NULL;
+ }
+
+ // dehacked files are indexed from 1
+ --thing_number;
+
+ if (thing_number < 0 || thing_number >= NUMMOBJTYPES)
+ {
+ DEH_Warning(context, "Invalid thing number: %i", thing_number);
+ return NULL;
+ }
+
+ mobj = &mobjinfo[thing_number];
+
+ return mobj;
+}
+
+static void DEH_ThingParseLine(deh_context_t *context, char *line, void *tag)
+{
+ mobjinfo_t *mobj;
+ char *variable_name, *value;
+ int ivalue;
+
+ if (tag == NULL)
+ return;
+
+ mobj = (mobjinfo_t *) tag;
+
+ // Parse the assignment
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {
+ // Failed to parse
+
+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+// printf("Set %s to %s for mobj\n", variable_name, value);
+
+ // all values are integers
+
+ ivalue = atoi(value);
+
+ // Set the field value
+
+ DEH_SetMapping(context, &thing_mapping, mobj, variable_name, ivalue);
+}
+
- static void DEH_ThingMD5Sum(md5_context_t *context)
++static void DEH_ThingSHA1Sum(sha1_context_t *context)
+{
+ int i;
+
+ for (i=0; i<NUMMOBJTYPES; ++i)
+ {
- DEH_StructMD5Sum(context, &thing_mapping, &mobjinfo[i]);
++ DEH_StructSHA1Sum(context, &thing_mapping, &mobjinfo[i]);
+ }
+}
+
+deh_section_t deh_section_thing =
+{
+ "Thing",
+ NULL,
+ DEH_ThingStart,
+ DEH_ThingParseLine,
+ NULL,
- DEH_ThingMD5Sum,
++ DEH_ThingSHA1Sum,
+};
+
diff --cc src/strife/deh_weapon.c
index 8e89b93e,00000000..67cbe5b6
mode 100644,000000..100644
--- a/src/strife/deh_weapon.c
+++ b/src/strife/deh_weapon.c
@@@ -1,111 -1,0 +1,111 @@@
+// 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 "Weapon" sections in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "doomtype.h"
+
+#include "d_items.h"
+
+#include "deh_defs.h"
+#include "deh_main.h"
+#include "deh_mapping.h"
+
+DEH_BEGIN_MAPPING(weapon_mapping, weaponinfo_t)
+ DEH_MAPPING("Ammo type", ammo)
+ DEH_MAPPING("Deselect frame", upstate)
+ DEH_MAPPING("Select frame", downstate)
+ DEH_MAPPING("Bobbing frame", readystate)
+ DEH_MAPPING("Shooting frame", atkstate)
+ DEH_MAPPING("Firing frame", flashstate)
+ DEH_UNSUPPORTED_MAPPING("? Unknown")
+DEH_END_MAPPING
+
+static void *DEH_WeaponStart(deh_context_t *context, char *line)
+{
+ int weapon_number = 0;
+
+ if (sscanf(line, "Weapon %i", &weapon_number) != 1)
+ {
+ DEH_Warning(context, "Parse error on section start");
+ return NULL;
+ }
+
+ if (weapon_number < 0 || weapon_number >= NUMWEAPONS)
+ {
+ DEH_Warning(context, "Invalid weapon number: %i", weapon_number);
+ return NULL;
+ }
+
+ return &weaponinfo[weapon_number];
+}
+
+static void DEH_WeaponParseLine(deh_context_t *context, char *line, void *tag)
+{
+ char *variable_name, *value;
+ weaponinfo_t *weapon;
+ int ivalue;
+
+ if (tag == NULL)
+ return;
+
+ weapon = (weaponinfo_t *) tag;
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {
+ // Failed to parse
+
+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+ ivalue = atoi(value);
+
+ DEH_SetMapping(context, &weapon_mapping, weapon, variable_name, ivalue);
+}
+
- static void DEH_WeaponMD5Sum(md5_context_t *context)
++static void DEH_WeaponSHA1Sum(sha1_context_t *context)
+{
+ int i;
+
+ for (i=0; i<NUMWEAPONS ;++i)
+ {
- DEH_StructMD5Sum(context, &weapon_mapping, &weaponinfo[i]);
++ DEH_StructSHA1Sum(context, &weapon_mapping, &weaponinfo[i]);
+ }
+}
+
+deh_section_t deh_section_weapon =
+{
+ "Weapon",
+ NULL,
+ DEH_WeaponStart,
+ DEH_WeaponParseLine,
+ NULL,
- DEH_WeaponMD5Sum,
++ DEH_WeaponSHA1Sum,
+};
+
diff --cc textscreen/txt_window.c
index 67543735,b08ac658..9ab6da9b
--- a/textscreen/txt_window.c
+++ b/textscreen/txt_window.c
@@@ -25,9 -24,9 +25,10 @@@
#include "doomkeys.h"
+#include "txt_label.h"
#include "txt_desktop.h"
#include "txt_gui.h"
+ #include "txt_io.h"
#include "txt_main.h"
#include "txt_separator.h"
#include "txt_window.h"