summaryrefslogtreecommitdiff
path: root/src/doom
diff options
context:
space:
mode:
Diffstat (limited to 'src/doom')
-rw-r--r--src/doom/.gitignore4
-rw-r--r--src/doom/am_map.c6
-rw-r--r--src/doom/d_main.c196
-rw-r--r--src/doom/d_net.c10
-rw-r--r--src/doom/f_finale.c2
-rw-r--r--src/doom/g_game.c188
-rw-r--r--src/doom/hu_stuff.c14
-rw-r--r--src/doom/m_menu.c4
-rw-r--r--src/doom/p_saveg.c24
-rw-r--r--src/doom/p_saveg.h1
-rw-r--r--src/doom/p_setup.c100
-rw-r--r--src/doom/r_draw.c111
-rw-r--r--src/doom/s_sound.c9
-rw-r--r--src/doom/st_stuff.c22
-rw-r--r--src/doom/wi_stuff.c47
15 files changed, 425 insertions, 313 deletions
diff --git a/src/doom/.gitignore b/src/doom/.gitignore
index 973a0073..d4e88e5a 100644
--- a/src/doom/.gitignore
+++ b/src/doom/.gitignore
@@ -1,9 +1,5 @@
Makefile
Makefile.in
.deps
-*.rc
-chocolate-doom
-chocolate-server
-*.exe
tags
TAGS
diff --git a/src/doom/am_map.c b/src/doom/am_map.c
index 89a5dffc..d957ea67 100644
--- a/src/doom/am_map.c
+++ b/src/doom/am_map.c
@@ -500,7 +500,7 @@ void AM_loadPics(void)
for (i=0;i<10;i++)
{
- sprintf(namebuf, DEH_String("AMMNUM%d"), i);
+ DEH_snprintf(namebuf, 9, "AMMNUM%d", i);
marknums[i] = W_CacheLumpName(namebuf, PU_STATIC);
}
@@ -513,7 +513,7 @@ void AM_unloadPics(void)
for (i=0;i<10;i++)
{
- sprintf(namebuf, DEH_String("AMMNUM%d"), i);
+ DEH_snprintf(namebuf, 9, "AMMNUM%d", i);
W_ReleaseLumpName(namebuf);
}
}
@@ -1020,7 +1020,7 @@ AM_drawFline
|| fl->b.x < 0 || fl->b.x >= f_w
|| fl->b.y < 0 || fl->b.y >= f_h)
{
- fprintf(stderr, DEH_String("fuck %d \r"), fuck++);
+ DEH_fprintf(stderr, "fuck %d \r", fuck++);
return;
}
diff --git a/src/doom/d_main.c b/src/doom/d_main.c
index 4e7812cc..f3a4b037 100644
--- a/src/doom/d_main.c
+++ b/src/doom/d_main.c
@@ -45,8 +45,8 @@
#include "d_iwad.h"
#include "z_zone.h"
+#include "w_main.h"
#include "w_wad.h"
-#include "w_merge.h"
#include "s_sound.h"
#include "v_video.h"
@@ -358,6 +358,12 @@ void D_BindVariables(void)
M_BindWeaponControls();
M_BindMapControls();
M_BindMenuControls();
+ M_BindChatControls(MAXPLAYERS);
+
+ key_multi_msgplayer[0] = HUSTR_KEYGREEN;
+ key_multi_msgplayer[1] = HUSTR_KEYINDIGO;
+ key_multi_msgplayer[2] = HUSTR_KEYBROWN;
+ key_multi_msgplayer[3] = HUSTR_KEYRED;
#ifdef FEATURE_MULTIPLAYER
NET_BindVariables();
@@ -827,7 +833,6 @@ static boolean CheckChex(char *iwadname)
// print title for every printed line
char title[128];
-
static boolean D_AddFile(char *filename)
{
wad_file_t *handle;
@@ -1069,7 +1074,7 @@ void D_DoomMain (void)
I_PrintBanner(PACKAGE_STRING);
- printf (DEH_String("Z_Init: Init zone memory allocation daemon. \n"));
+ DEH_printf("Z_Init: Init zone memory allocation daemon. \n");
Z_Init ();
#ifdef FEATURE_MULTIPLAYER
@@ -1188,7 +1193,7 @@ void D_DoomMain (void)
deathmatch = 2;
if (devparm)
- printf(DEH_String(D_DEVSTR));
+ DEH_printf(D_DEVSTR);
// find which dir to use for config files
@@ -1236,7 +1241,7 @@ void D_DoomMain (void)
scale = 10;
if (scale > 400)
scale = 400;
- printf (DEH_String("turbo scale: %i%%\n"),scale);
+ DEH_printf("turbo scale: %i%%\n", scale);
forwardmove[0] = forwardmove[0]*scale/100;
forwardmove[1] = forwardmove[1]*scale/100;
sidemove[0] = sidemove[0]*scale/100;
@@ -1244,11 +1249,11 @@ void D_DoomMain (void)
}
// init subsystems
- printf(DEH_String("V_Init: allocate screens.\n"));
- V_Init();
+ DEH_printf("V_Init: allocate screens.\n");
+ V_Init ();
// Load configuration files before initialising other subsystems.
- printf(DEH_String("M_LoadDefaults: Load system defaults.\n"));
+ DEH_printf("M_LoadDefaults: Load system defaults.\n");
M_SetConfigFilenames("default.cfg", PROGRAM_PREFIX "doom.cfg");
D_BindVariables();
M_LoadDefaults();
@@ -1256,160 +1261,9 @@ void D_DoomMain (void)
// Save configuration at exit.
I_AtExit(M_SaveDefaults, false);
- printf (DEH_String("W_Init: Init WADfiles.\n"));
+ DEH_printf("W_Init: Init WADfiles.\n");
D_AddFile(iwadfile);
-
-#ifdef FEATURE_WAD_MERGE
-
- // Merged PWADs are loaded first, because they are supposed to be
- // modified IWADs.
-
- //!
- // @arg <files>
- // @category mod
- //
- // Simulates the behavior of deutex's -merge option, merging a PWAD
- // into the main IWAD. Multiple files may be specified.
- //
-
- p = M_CheckParm("-merge");
-
- if (p > 0)
- {
- for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
- {
- char *filename;
-
- filename = D_TryFindWADByName(myargv[p]);
-
- printf(" merging %s\n", filename);
- W_MergeFile(filename);
- }
- }
-
- // NWT-style merging:
-
- // NWT's -merge option:
-
- //!
- // @arg <files>
- // @category mod
- //
- // Simulates the behavior of NWT's -merge option. Multiple files
- // may be specified.
-
- p = M_CheckParm("-nwtmerge");
-
- if (p > 0)
- {
- for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
- {
- char *filename;
-
- filename = D_TryFindWADByName(myargv[p]);
-
- printf(" performing NWT-style merge of %s\n", filename);
- W_NWTDashMerge(filename);
- }
- }
-
- // Add flats
-
- //!
- // @arg <files>
- // @category mod
- //
- // Simulates the behavior of NWT's -af option, merging flats into
- // the main IWAD directory. Multiple files may be specified.
- //
-
- p = M_CheckParm("-af");
-
- if (p > 0)
- {
- for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
- {
- char *filename;
-
- filename = D_TryFindWADByName(myargv[p]);
-
- printf(" merging flats from %s\n", filename);
- W_NWTMergeFile(filename, W_NWT_MERGE_FLATS);
- }
- }
-
- //!
- // @arg <files>
- // @category mod
- //
- // Simulates the behavior of NWT's -as option, merging sprites
- // into the main IWAD directory. Multiple files may be specified.
- //
-
- p = M_CheckParm("-as");
-
- if (p > 0)
- {
- for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
- {
- char *filename;
-
- filename = D_TryFindWADByName(myargv[p]);
-
- printf(" merging sprites from %s\n", filename);
- W_NWTMergeFile(filename, W_NWT_MERGE_SPRITES);
- }
- }
-
- //!
- // @arg <files>
- // @category mod
- //
- // Equivalent to "-af <files> -as <files>".
- //
-
- p = M_CheckParm("-aa");
-
- if (p > 0)
- {
- for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
- {
- char *filename;
-
- filename = D_TryFindWADByName(myargv[p]);
-
- printf(" merging sprites and flats from %s\n", filename);
- W_NWTMergeFile(filename, W_NWT_MERGE_SPRITES | W_NWT_MERGE_FLATS);
- }
- }
-
-#endif
-
- //!
- // @arg <files>
- // @vanilla
- //
- // Load the specified PWAD files.
- //
-
- p = M_CheckParm ("-file");
- if (p)
- {
- // the parms after p are wadfile/lump names,
- // until end of parms or another - preceded parm
- modifiedgame = true; // homebrew levels
- while (++p != myargc && myargv[p][0] != '-')
- {
- char *filename;
-
- filename = D_TryFindWADByName(myargv[p]);
-
- D_AddFile(filename);
- }
- }
-
- // Debug:
-// W_PrintDirectory();
+ modifiedgame = W_ParseCommandLine();
// add any files specified on the command line with -file wadfile
// to the wad list
@@ -1603,8 +1457,8 @@ void D_DoomMain (void)
if (p && p < myargc-1 && deathmatch)
{
- printf(DEH_String("Austin Virtual Gaming: Levels will end "
- "after 20 minutes\n"));
+ DEH_printf("Austin Virtual Gaming: Levels will end "
+ "after 20 minutes\n");
timelimit = 20;
}
@@ -1686,16 +1540,16 @@ void D_DoomMain (void)
I_PrintStartupBanner(gamedescription);
PrintDehackedBanners();
- printf (DEH_String("M_Init: Init miscellaneous info.\n"));
+ DEH_printf("M_Init: Init miscellaneous info.\n");
M_Init ();
- printf (DEH_String("R_Init: Init DOOM refresh daemon - "));
+ DEH_printf("R_Init: Init DOOM refresh daemon - ");
R_Init ();
- printf (DEH_String("\nP_Init: Init Playloop state.\n"));
+ DEH_printf("\nP_Init: Init Playloop state.\n");
P_Init ();
- printf (DEH_String("I_Init: Setting up machine state.\n"));
+ DEH_printf("I_Init: Setting up machine state.\n");
I_CheckIsScreensaver();
I_InitTimer();
I_InitJoystick();
@@ -1705,18 +1559,18 @@ void D_DoomMain (void)
NET_Init ();
#endif
- printf (DEH_String("S_Init: Setting up sound.\n"));
+ DEH_printf("S_Init: Setting up sound.\n");
S_Init (sfxVolume * 8, musicVolume * 8);
- printf (DEH_String("D_CheckNetGame: Checking network game status.\n"));
+ DEH_printf("D_CheckNetGame: Checking network game status.\n");
D_CheckNetGame ();
PrintGameVersion();
- printf (DEH_String("HU_Init: Setting up heads up display.\n"));
+ DEH_printf("HU_Init: Setting up heads up display.\n");
HU_Init ();
- printf (DEH_String("ST_Init: Init status bar.\n"));
+ DEH_printf("ST_Init: Init status bar.\n");
ST_Init ();
// If Doom II without a MAP01 lump, this is a store demo.
diff --git a/src/doom/d_net.c b/src/doom/d_net.c
index e30ead83..464922d4 100644
--- a/src/doom/d_net.c
+++ b/src/doom/d_net.c
@@ -374,17 +374,17 @@ void D_CheckNetGame (void)
++num_players;
}
- printf (DEH_String("startskill %i deathmatch: %i startmap: %i startepisode: %i\n"),
- startskill, deathmatch, startmap, startepisode);
+ DEH_printf("startskill %i deathmatch: %i startmap: %i startepisode: %i\n",
+ startskill, deathmatch, startmap, startepisode);
- printf(DEH_String("player %i of %i (%i nodes)\n"),
- consoleplayer+1, num_players, num_players);
+ DEH_printf("player %i of %i (%i nodes)\n",
+ consoleplayer+1, num_players, num_players);
// Show players here; the server might have specified a time limit
if (timelimit > 0)
{
- printf(DEH_String("Levels will end after %d minute"),timelimit);
+ DEH_printf("Levels will end after %d minute", timelimit);
if (timelimit > 1)
printf("s");
printf(".\n");
diff --git a/src/doom/f_finale.c b/src/doom/f_finale.c
index ece82b43..dfbeafbe 100644
--- a/src/doom/f_finale.c
+++ b/src/doom/f_finale.c
@@ -663,7 +663,7 @@ void F_BunnyScroll (void)
laststage = stage;
}
- sprintf (name, DEH_String("END%i"), stage);
+ DEH_snprintf(name, 10, "END%i", stage);
V_DrawPatch((SCREENWIDTH - 13 * 8) / 2,
(SCREENHEIGHT - 8 * 8) / 2,
W_CacheLumpName (name,PU_CACHE));
diff --git a/src/doom/g_game.c b/src/doom/g_game.c
index 8d0e4503..ad7155a0 100644
--- a/src/doom/g_game.c
+++ b/src/doom/g_game.c
@@ -176,14 +176,37 @@ static int *weapon_keys[] = {
&key_weapon8
};
+// Set to -1 or +1 to switch to the previous or next weapon.
+
+static int next_weapon = 0;
+
+// Used for prev/next weapon keys.
+
+static const struct
+{
+ weapontype_t weapon;
+ weapontype_t weapon_num;
+} weapon_order_table[] = {
+ { wp_fist, wp_fist },
+ { wp_chainsaw, wp_fist },
+ { wp_pistol, wp_pistol },
+ { wp_shotgun, wp_shotgun },
+ { wp_supershotgun, wp_shotgun },
+ { wp_chaingun, wp_chaingun },
+ { wp_missile, wp_missile },
+ { wp_plasma, wp_plasma },
+ { wp_bfg, wp_bfg }
+};
+
#define SLOWTURNTICS 6
#define NUMKEYS 256
+#define MAX_JOY_BUTTONS 20
static boolean gamekeydown[NUMKEYS];
static int turnheld; // for accelerative turning
-static boolean mousearray[4];
+static boolean mousearray[MAX_MOUSE_BUTTONS + 1];
static boolean *mousebuttons = &mousearray[1]; // allow [-1]
// mouse values are used once
@@ -197,8 +220,6 @@ static int dclicktime2;
static boolean dclickstate2;
static int dclicks2;
-#define MAX_JOY_BUTTONS 20
-
// joystick values are repeated
static int joyxmove;
static int joyymove;
@@ -337,7 +358,63 @@ int G_CmdChecksum (ticcmd_t* cmd)
return sum;
}
-
+
+static boolean WeaponSelectable(weapontype_t weapon)
+{
+ // Can't select a weapon if we don't own it.
+
+ if (!players[consoleplayer].weaponowned[weapon])
+ {
+ return false;
+ }
+
+ // Can't select the fist if we have the chainsaw, unless
+ // we also have the berserk pack.
+
+ if (weapon == wp_fist
+ && players[consoleplayer].weaponowned[wp_chainsaw]
+ && !players[consoleplayer].powers[pw_strength])
+ {
+ return false;
+ }
+
+ return true;
+}
+
+static int G_NextWeapon(int direction)
+{
+ weapontype_t weapon;
+ int i;
+
+ // Find index in the table.
+
+ if (players[consoleplayer].pendingweapon == wp_nochange)
+ {
+ weapon = players[consoleplayer].readyweapon;
+ }
+ else
+ {
+ weapon = players[consoleplayer].pendingweapon;
+ }
+
+ for (i=0; i<arrlen(weapon_order_table); ++i)
+ {
+ if (weapon_order_table[i].weapon == weapon)
+ {
+ break;
+ }
+ }
+
+ // Switch weapon.
+
+ do
+ {
+ i += direction;
+ i = (i + arrlen(weapon_order_table)) % arrlen(weapon_order_table);
+ } while (!WeaponSelectable(weapon_order_table[i].weapon));
+
+ return weapon_order_table[i].weapon_num;
+}
//
// G_BuildTiccmd
@@ -465,20 +542,34 @@ void G_BuildTiccmd (ticcmd_t* cmd)
dclicks = 0;
}
- // chainsaw overrides
+ // If the previous or next weapon button is pressed, the
+ // next_weapon variable is set to change weapons when
+ // we generate a ticcmd. Choose a new weapon.
- for (i=0; i<arrlen(weapon_keys); ++i)
+ if (next_weapon != 0)
+ {
+ i = G_NextWeapon(next_weapon);
+ cmd->buttons |= BT_CHANGE;
+ cmd->buttons |= i << BT_WEAPONSHIFT;
+ next_weapon = 0;
+ }
+ else
{
- int key = *weapon_keys[i];
+ // Check weapon keys.
- if (gamekeydown[key])
+ for (i=0; i<arrlen(weapon_keys); ++i)
{
- cmd->buttons |= BT_CHANGE;
- cmd->buttons |= i<<BT_WEAPONSHIFT;
- break;
+ int key = *weapon_keys[i];
+
+ if (gamekeydown[key])
+ {
+ cmd->buttons |= BT_CHANGE;
+ cmd->buttons |= i<<BT_WEAPONSHIFT;
+ break;
+ }
}
}
-
+
// mouse
if (mousebuttons[mousebforward])
{
@@ -657,7 +748,6 @@ void G_DoLoadLevel (void)
players[consoleplayer].message = "Press escape to quit.";
}
}
-
static void SetJoyButtons(unsigned int buttons_mask)
{
@@ -665,10 +755,54 @@ static void SetJoyButtons(unsigned int buttons_mask)
for (i=0; i<MAX_JOY_BUTTONS; ++i)
{
- joybuttons[i] = (buttons_mask & (1 << i)) != 0;
+ int button_on = (buttons_mask & (1 << i)) != 0;
+
+ // Detect button press:
+
+ if (!joybuttons[i] && button_on)
+ {
+ // Weapon cycling:
+
+ if (i == joybprevweapon)
+ {
+ next_weapon = -1;
+ }
+ else if (i == joybnextweapon)
+ {
+ next_weapon = 1;
+ }
+ }
+
+ joybuttons[i] = button_on;
}
}
-
+
+static void SetMouseButtons(unsigned int buttons_mask)
+{
+ int i;
+
+ for (i=0; i<MAX_MOUSE_BUTTONS; ++i)
+ {
+ unsigned int button_on = (buttons_mask & (1 << i)) != 0;
+
+ // Detect button press:
+
+ if (!mousebuttons[i] && button_on)
+ {
+ if (i == mousebprevweapon)
+ {
+ next_weapon = -1;
+ }
+ else if (i == mousebnextweapon)
+ {
+ next_weapon = 1;
+ }
+ }
+
+ mousebuttons[i] = button_on;
+ }
+}
+
//
// G_Responder
// Get info needed to make ticcmd_ts for the players.
@@ -677,7 +811,7 @@ boolean G_Responder (event_t* ev)
{
// allow spy mode changes even during the demo
if (gamestate == GS_LEVEL && ev->type == ev_keydown
- && ev->data1 == KEY_F12 && (singledemo || !deathmatch) )
+ && ev->data1 == key_spy && (singledemo || !deathmatch) )
{
// spy mode
do
@@ -737,6 +871,18 @@ boolean G_Responder (event_t* ev)
testcontrols_mousespeed = abs(ev->data2);
}
+ // If the next/previous weapon keys are pressed, set the next_weapon
+ // variable to change weapons when the next ticcmd is generated.
+
+ if (ev->type == ev_keydown && ev->data1 == key_prevweapon)
+ {
+ next_weapon = -1;
+ }
+ else if (ev->type == ev_keydown && ev->data1 == key_nextweapon)
+ {
+ next_weapon = 1;
+ }
+
switch (ev->type)
{
case ev_keydown:
@@ -757,9 +903,7 @@ boolean G_Responder (event_t* ev)
return false; // always let key up events filter down
case ev_mouse:
- mousebuttons[0] = ev->data1 & 1;
- mousebuttons[1] = ev->data1 & 2;
- mousebuttons[2] = ev->data1 & 4;
+ SetMouseButtons(ev->data1);
mousex = ev->data2*(mouseSensitivity+5)/10;
mousey = ev->data3*(mouseSensitivity+5)/10;
return true; // eat events
@@ -1428,6 +1572,8 @@ void G_DoLoadGame (void)
return;
}
+ savegame_error = false;
+
if (!P_ReadSaveGameHeader())
{
fclose(save_stream);
@@ -1495,6 +1641,8 @@ void G_DoSaveGame (void)
return;
}
+ savegame_error = false;
+
P_WriteSaveGameHeader(savedescription);
P_ArchivePlayers ();
@@ -1780,7 +1928,7 @@ void G_WriteDemoTiccmd (ticcmd_t* cmd)
{
byte *demo_start;
- if (gamekeydown['q']) // press q to end demo recording
+ if (gamekeydown[key_demo_quit]) // press q to end demo recording
G_CheckDemoStatus ();
demo_start = demo_p;
diff --git a/src/doom/hu_stuff.c b/src/doom/hu_stuff.c
index ca74ce92..f9271b3d 100644
--- a/src/doom/hu_stuff.c
+++ b/src/doom/hu_stuff.c
@@ -302,7 +302,7 @@ void HU_Init(void)
j = HU_FONTSTART;
for (i=0;i<HU_FONTSIZE;i++)
{
- sprintf(buffer, DEH_String("STCFN%.3d"), j++);
+ DEH_snprintf(buffer, 9, "STCFN%.3d", j++);
hu_font[i] = (patch_t *) W_CacheLumpName(buffer, PU_STATIC);
}
@@ -529,14 +529,6 @@ boolean HU_Responder(event_t *ev)
int i;
int numplayers;
- static char destination_keys[MAXPLAYERS] =
- {
- HUSTR_KEYGREEN,
- HUSTR_KEYINDIGO,
- HUSTR_KEYBROWN,
- HUSTR_KEYRED
- };
-
static int num_nobrainers = 0;
numplayers = 0;
@@ -565,7 +557,7 @@ boolean HU_Responder(event_t *ev)
message_counter = HU_MSGTIMEOUT;
eatkey = true;
}
- else if (netgame && ev->data2 == HU_INPUTTOGGLE)
+ else if (netgame && ev->data2 == key_multi_msg)
{
eatkey = chat_on = true;
HUlib_resetIText(&w_chat);
@@ -575,7 +567,7 @@ boolean HU_Responder(event_t *ev)
{
for (i=0; i<MAXPLAYERS ; i++)
{
- if (ev->data2 == destination_keys[i])
+ if (ev->data2 == key_multi_msgplayer[i])
{
if (playeringame[i] && i!=consoleplayer)
{
diff --git a/src/doom/m_menu.c b/src/doom/m_menu.c
index a0d66dd4..a6f7bbfb 100644
--- a/src/doom/m_menu.c
+++ b/src/doom/m_menu.c
@@ -707,7 +707,7 @@ void M_QuickSave(void)
quickSaveSlot = -2; // means to pick a slot now
return;
}
- sprintf(tempstring,DEH_String(QSPROMPT),savegamestrings[quickSaveSlot]);
+ DEH_snprintf(tempstring, 80, QSPROMPT, savegamestrings[quickSaveSlot]);
M_StartMessage(tempstring,M_QuickSaveResponse,true);
}
@@ -739,7 +739,7 @@ void M_QuickLoad(void)
M_StartMessage(DEH_String(QSAVESPOT),NULL,false);
return;
}
- sprintf(tempstring,DEH_String(QLPROMPT),savegamestrings[quickSaveSlot]);
+ DEH_snprintf(tempstring, 80, QLPROMPT, savegamestrings[quickSaveSlot]);
M_StartMessage(tempstring,M_QuickLoadResponse,true);
}
diff --git a/src/doom/p_saveg.c b/src/doom/p_saveg.c
index e557e494..968120c0 100644
--- a/src/doom/p_saveg.c
+++ b/src/doom/p_saveg.c
@@ -44,6 +44,7 @@
FILE *save_stream;
int savegamelength;
+boolean savegame_error;
// Get the filename of a temporary file to write the savegame to. After
// the file has been successfully saved, it will be renamed to the
@@ -75,7 +76,7 @@ char *P_SaveGameFile(int slot)
filename = malloc(strlen(savegamedir) + 32);
}
- sprintf(basename, DEH_String(SAVEGAMENAME "%d.dsg"), slot);
+ DEH_snprintf(basename, 32, SAVEGAMENAME "%d.dsg", slot);
sprintf(filename, "%s%s", savegamedir, basename);
@@ -88,14 +89,31 @@ static byte saveg_read8(void)
{
byte result;
- fread(&result, 1, 1, save_stream);
+ if (fread(&result, 1, 1, save_stream) < 1)
+ {
+ if (!savegame_error)
+ {
+ fprintf(stderr, "saveg_read8: Unexpected end of file while "
+ "reading save game\n");
+
+ savegame_error = true;
+ }
+ }
return result;
}
static void saveg_write8(byte value)
{
- fwrite(&value, 1, 1, save_stream);
+ if (fwrite(&value, 1, 1, save_stream) < 1)
+ {
+ if (!savegame_error)
+ {
+ fprintf(stderr, "saveg_write8: Error while writing save game\n");
+
+ savegame_error = true;
+ }
+ }
}
static short saveg_read16(void)
diff --git a/src/doom/p_saveg.h b/src/doom/p_saveg.h
index 3a96cc3e..5488289c 100644
--- a/src/doom/p_saveg.h
+++ b/src/doom/p_saveg.h
@@ -64,6 +64,7 @@ void P_ArchiveSpecials (void);
void P_UnArchiveSpecials (void);
extern FILE *save_stream;
+extern boolean savegame_error;
#endif
diff --git a/src/doom/p_setup.c b/src/doom/p_setup.c
index 2a3a8f85..7d9d4318 100644
--- a/src/doom/p_setup.c
+++ b/src/doom/p_setup.c
@@ -33,6 +33,7 @@
#include "deh_main.h"
#include "i_swap.h"
+#include "m_argv.h"
#include "m_bbox.h"
#include "g_game.h"
@@ -76,6 +77,7 @@ line_t* lines;
int numsides;
side_t* sides;
+static int totallines;
// BLOCKMAP
// Created from axis aligned bounding box
@@ -534,7 +536,6 @@ void P_GroupLines (void)
line_t** linebuffer;
int i;
int j;
- int total;
line_t* li;
sector_t* sector;
subsector_t* ss;
@@ -552,21 +553,21 @@ void P_GroupLines (void)
// count number of lines in each sector
li = lines;
- total = 0;
+ totallines = 0;
for (i=0 ; i<numlines ; i++, li++)
{
- total++;
+ totallines++;
li->frontsector->linecount++;
if (li->backsector && li->backsector != li->frontsector)
{
li->backsector->linecount++;
- total++;
+ totallines++;
}
}
// build line tables for each sector
- linebuffer = Z_Malloc (total*sizeof(line_t *), PU_LEVEL, 0);
+ linebuffer = Z_Malloc (totallines*sizeof(line_t *), PU_LEVEL, 0);
for (i=0; i<numsectors; ++i)
{
@@ -643,6 +644,87 @@ void P_GroupLines (void)
}
+// Pad the REJECT lump with extra data when the lump is too small,
+// to simulate a REJECT buffer overflow in Vanilla Doom.
+
+static void PadRejectArray(byte *array, unsigned int len)
+{
+ unsigned int i;
+ unsigned int byte_num;
+ byte *dest;
+ unsigned int padvalue;
+
+ // Values to pad the REJECT array with:
+
+ unsigned int rejectpad[4] =
+ {
+ ((totallines * 4 + 3) & ~3) + 24, // Size
+ 0, // Part of z_zone block header
+ 50, // PU_LEVEL
+ 0x1d4a11 // DOOM_CONST_ZONEID
+ };
+
+ // Copy values from rejectpad into the destination array.
+
+ dest = array;
+
+ for (i=0; i<len && i<sizeof(rejectpad); ++i)
+ {
+ byte_num = i % 4;
+ *dest = (rejectpad[i / 4] >> (byte_num * 8)) & 0xff;
+ ++dest;
+ }
+
+ // We only have a limited pad size. Print a warning if the
+ // REJECT lump is too small.
+
+ if (len > sizeof(rejectpad))
+ {
+ fprintf(stderr, "PadRejectArray: REJECT lump too short to pad! (%i > %i)\n",
+ len, sizeof(rejectpad));
+
+ // Pad remaining space with 0 (or 0xff, if specified on command line).
+
+ if (M_CheckParm("-reject_pad_with_ff"))
+ {
+ padvalue = 0xff;
+ }
+ else
+ {
+ padvalue = 0xf00;
+ }
+
+ memset(array + sizeof(rejectpad), padvalue, len - sizeof(rejectpad));
+ }
+}
+
+static void P_LoadReject(int lumpnum)
+{
+ int minlength;
+ int lumplen;
+
+ // Calculate the size that the REJECT lump *should* be.
+
+ minlength = (numsectors * numsectors + 7) / 8;
+
+ // If the lump meets the minimum length, it can be loaded directly.
+ // Otherwise, we need to allocate a buffer of the correct size
+ // and pad it with appropriate data.
+
+ lumplen = W_LumpLength(lumpnum);
+
+ if (lumplen >= minlength)
+ {
+ rejectmatrix = W_CacheLumpNum(lumpnum, PU_LEVEL);
+ }
+ else
+ {
+ rejectmatrix = Z_Malloc(minlength, PU_LEVEL, &rejectmatrix);
+ W_ReadLump(lumpnum, rejectmatrix);
+
+ PadRejectArray(rejectmatrix + lumplen, minlength - lumplen);
+ }
+}
//
// P_SetupLevel
@@ -692,9 +774,9 @@ P_SetupLevel
if ( gamemode == commercial)
{
if (map<10)
- sprintf (lumpname, DEH_String("map0%i"), map);
+ DEH_snprintf(lumpname, 9, "map0%i", map);
else
- sprintf (lumpname, DEH_String("map%i"), map);
+ DEH_snprintf(lumpname, 9, "map%i", map);
}
else
{
@@ -719,9 +801,9 @@ P_SetupLevel
P_LoadSubsectors (lumpnum+ML_SSECTORS);
P_LoadNodes (lumpnum+ML_NODES);
P_LoadSegs (lumpnum+ML_SEGS);
-
- rejectmatrix = W_CacheLumpNum (lumpnum+ML_REJECT,PU_LEVEL);
+
P_GroupLines ();
+ P_LoadReject (lumpnum+ML_REJECT);
bodyqueslot = 0;
deathmatch_p = deathmatchstarts;
diff --git a/src/doom/r_draw.c b/src/doom/r_draw.c
index 1b6420d9..80362208 100644
--- a/src/doom/r_draw.c
+++ b/src/doom/r_draw.c
@@ -597,48 +597,54 @@ int dscount;
// Draws the actual span.
void R_DrawSpan (void)
{
- fixed_t xfrac;
- fixed_t yfrac;
- byte* dest;
- int count;
- int spot;
-
-#ifdef RANGECHECK
+ unsigned int position, step;
+ byte *dest;
+ int count;
+ int spot;
+ unsigned int xtemp, ytemp;
+
+#ifdef RANGECHECK
if (ds_x2 < ds_x1
|| ds_x1<0
- || ds_x2>=SCREENWIDTH
+ || ds_x2>=SCREENWIDTH
|| (unsigned)ds_y>SCREENHEIGHT)
{
I_Error( "R_DrawSpan: %i to %i at %i",
ds_x1,ds_x2,ds_y);
}
-// dscount++;
-#endif
+// dscount++;
+#endif
+
+ // Pack position and step variables into a single 32-bit integer,
+ // with x in the top 16 bits and y in the bottom 16 bits. For
+ // each 16-bit part, the top 6 bits are the integer part and the
+ // bottom 10 bits are the fractional part of the pixel position.
+
+ position = ((ds_xfrac << 10) & 0xffff0000)
+ | ((ds_yfrac >> 6) & 0x0000ffff);
+ step = ((ds_xstep << 10) & 0xffff0000)
+ | ((ds_ystep >> 6) & 0x0000ffff);
-
- xfrac = ds_xfrac;
- yfrac = ds_yfrac;
-
dest = ylookup[ds_y] + columnofs[ds_x1];
// We do not check for zero spans here?
- count = ds_x2 - ds_x1;
+ count = ds_x2 - ds_x1;
- do
+ do
{
- // Current texture index in u,v.
- spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
+ // Calculate current texture index in u,v.
+ ytemp = (position >> 4) & 0x0fc0;
+ xtemp = (position >> 26);
+ spot = xtemp | ytemp;
// Lookup pixel from flat texture tile,
// re-index using light/colormap.
*dest++ = ds_colormap[ds_source[spot]];
- // Next step in u,v.
- xfrac += ds_xstep;
- yfrac += ds_ystep;
-
- } while (count--);
-}
+ position += step;
+
+ } while (count--);
+}
@@ -718,49 +724,54 @@ void R_DrawSpan (void)
//
// Again..
//
-void R_DrawSpanLow (void)
-{
- fixed_t xfrac;
- fixed_t yfrac;
- byte* dest;
- int count;
- int spot;
-
-#ifdef RANGECHECK
+void R_DrawSpanLow (void)
+{
+ unsigned int position, step;
+ unsigned int xtemp, ytemp;
+ byte *dest;
+ int count;
+ int spot;
+
+#ifdef RANGECHECK
if (ds_x2 < ds_x1
|| ds_x1<0
- || ds_x2>=SCREENWIDTH
+ || ds_x2>=SCREENWIDTH
|| (unsigned)ds_y>SCREENHEIGHT)
{
I_Error( "R_DrawSpan: %i to %i at %i",
ds_x1,ds_x2,ds_y);
}
// dscount++;
-#endif
-
- xfrac = ds_xfrac;
- yfrac = ds_yfrac;
-
- count = (ds_x2 - ds_x1);
+#endif
+
+ position = ((ds_xfrac << 10) & 0xffff0000)
+ | ((ds_yfrac >> 6) & 0x0000ffff);
+ step = ((ds_xstep << 10) & 0xffff0000)
+ | ((ds_ystep >> 6) & 0x0000ffff);
+
+ count = (ds_x2 - ds_x1);
// Blocky mode, need to multiply by 2.
ds_x1 <<= 1;
ds_x2 <<= 1;
-
+
dest = ylookup[ds_y] + columnofs[ds_x1];
-
- do
- {
- spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
+
+ do
+ {
+ // Calculate current texture index in u,v.
+ ytemp = (position >> 4) & 0x0fc0;
+ xtemp = (position >> 26);
+ spot = xtemp | ytemp;
+
// Lowres/blocky mode does it twice,
// while scale is adjusted appropriately.
- *dest++ = ds_colormap[ds_source[spot]];
*dest++ = ds_colormap[ds_source[spot]];
-
- xfrac += ds_xstep;
- yfrac += ds_ystep;
+ *dest++ = ds_colormap[ds_source[spot]];
- } while (count--);
+ position += step;
+
+ } while (count--);
}
//
diff --git a/src/doom/s_sound.c b/src/doom/s_sound.c
index f829956c..7f4411dd 100644
--- a/src/doom/s_sound.c
+++ b/src/doom/s_sound.c
@@ -618,6 +618,15 @@ void S_ChangeMusic(int musicnum, int looping)
char namebuf[9];
void *handle;
+ // The Doom IWAD file has two versions of the intro music: d_intro
+ // and d_introa. The latter is used for OPL playback.
+
+ if (musicnum == mus_intro && (snd_musicdevice == SNDDEVICE_ADLIB
+ || snd_musicdevice == SNDDEVICE_SB))
+ {
+ musicnum = mus_introa;
+ }
+
if (musicnum <= mus_None || musicnum >= NUMMUSIC)
{
I_Error("Bad music number %d", musicnum);
diff --git a/src/doom/st_stuff.c b/src/doom/st_stuff.c
index 160244ce..7e5e225c 100644
--- a/src/doom/st_stuff.c
+++ b/src/doom/st_stuff.c
@@ -1085,10 +1085,10 @@ static void ST_loadUnloadGraphics(load_callback_t callback)
// Load the numbers, tall and short
for (i=0;i<10;i++)
{
- sprintf(namebuf, DEH_String("STTNUM%d"), i);
+ DEH_snprintf(namebuf, 9, "STTNUM%d", i);
callback(namebuf, &tallnum[i]);
- sprintf(namebuf, DEH_String("STYSNUM%d"), i);
+ DEH_snprintf(namebuf, 9, "STYSNUM%d", i);
callback(namebuf, &shortnum[i]);
}
@@ -1100,7 +1100,7 @@ static void ST_loadUnloadGraphics(load_callback_t callback)
// key cards
for (i=0;i<NUMCARDS;i++)
{
- sprintf(namebuf, DEH_String("STKEYS%d"), i);
+ DEH_snprintf(namebuf, 9, "STKEYS%d", i);
callback(namebuf, &keys[i]);
}
@@ -1110,7 +1110,7 @@ static void ST_loadUnloadGraphics(load_callback_t callback)
// arms ownership widgets
for (i=0; i<6; i++)
{
- sprintf(namebuf, DEH_String("STGNUM%d"), i+2);
+ DEH_snprintf(namebuf, 9, "STGNUM%d", i+2);
// gray #
callback(namebuf, &arms[i][0]);
@@ -1120,7 +1120,7 @@ static void ST_loadUnloadGraphics(load_callback_t callback)
}
// face backgrounds for different color players
- sprintf(namebuf, DEH_String("STFB%d"), consoleplayer);
+ DEH_snprintf(namebuf, 9, "STFB%d", consoleplayer);
callback(namebuf, &faceback);
// status bar background bits
@@ -1132,23 +1132,23 @@ static void ST_loadUnloadGraphics(load_callback_t callback)
{
for (j=0; j<ST_NUMSTRAIGHTFACES; j++)
{
- sprintf(namebuf, DEH_String("STFST%d%d"), i, j);
+ DEH_snprintf(namebuf, 9, "STFST%d%d", i, j);
callback(namebuf, &faces[facenum]);
++facenum;
}
- sprintf(namebuf, DEH_String("STFTR%d0"), i); // turn right
+ DEH_snprintf(namebuf, 9, "STFTR%d0", i); // turn right
callback(namebuf, &faces[facenum]);
++facenum;
- sprintf(namebuf, DEH_String("STFTL%d0"), i); // turn left
+ DEH_snprintf(namebuf, 9, "STFTL%d0", i); // turn left
callback(namebuf, &faces[facenum]);
++facenum;
- sprintf(namebuf, DEH_String("STFOUCH%d"), i); // ouch!
+ DEH_snprintf(namebuf, 9, "STFOUCH%d", i); // ouch!
callback(namebuf, &faces[facenum]);
++facenum;
- sprintf(namebuf, DEH_String("STFEVL%d"), i); // evil grin ;)
+ DEH_snprintf(namebuf, 9, "STFEVL%d", i); // evil grin ;)
callback(namebuf, &faces[facenum]);
++facenum;
- sprintf(namebuf, DEH_String("STFKILL%d"), i); // pissed off
+ DEH_snprintf(namebuf, 9, "STFKILL%d", i); // pissed off
callback(namebuf, &faces[facenum]);
++facenum;
}
diff --git a/src/doom/wi_stuff.c b/src/doom/wi_stuff.c
index 83f5052f..45c09343 100644
--- a/src/doom/wi_stuff.c
+++ b/src/doom/wi_stuff.c
@@ -1571,16 +1571,16 @@ static void WI_loadUnloadData(load_callback_t callback)
if (gamemode == commercial)
{
for (i=0 ; i<NUMCMAPS ; i++)
- {
- sprintf(name, DEH_String("CWILV%2.2d"), i);
+ {
+ DEH_snprintf(name, 9, "CWILV%2.2d", i);
callback(name, &lnames[i]);
- }
+ }
}
else
{
for (i=0 ; i<NUMMAPS ; i++)
{
- sprintf(name, DEH_String("WILV%d%d"), wbs->epsd, i);
+ DEH_snprintf(name, 9, "WILV%d%d", wbs->epsd, i);
callback(name, &lnames[i]);
}
@@ -1592,7 +1592,7 @@ static void WI_loadUnloadData(load_callback_t callback)
// splat
callback(DEH_String("WISPLAT"), &splat[0]);
-
+
if (wbs->epsd < 3)
{
for (j=0;j<NUMANIMS[wbs->epsd];j++)
@@ -1601,17 +1601,16 @@ static void WI_loadUnloadData(load_callback_t callback)
for (i=0;i<a->nanims;i++)
{
// MONDO HACK!
- if (wbs->epsd != 1 || j != 8)
+ if (wbs->epsd != 1 || j != 8)
{
// animations
- sprintf(name, DEH_String("WIA%d%.2d%.2d"),
- wbs->epsd, j, i);
+ DEH_snprintf(name, 9, "WIA%d%.2d%.2d", wbs->epsd, j, i);
callback(name, &a->p[i]);
}
else
{
// HACK ALERT!
- a->p[i] = anims[1][4].p[i];
+ a->p[i] = anims[1][4].p[i];
}
}
}
@@ -1624,7 +1623,7 @@ static void WI_loadUnloadData(load_callback_t callback)
for (i=0;i<10;i++)
{
// numbers 0-9
- sprintf(name, DEH_String("WINUM%d"), i);
+ DEH_snprintf(name, 9, "WINUM%d", i);
callback(name, &num[i]);
}
@@ -1665,13 +1664,13 @@ static void WI_loadUnloadData(load_callback_t callback)
callback(DEH_String("WICOLON"), &colon);
// "time"
- callback(DEH_String("WITIME"), &timepatch);
+ callback(DEH_String("WITIME"), &timepatch);
// "sucks"
- callback(DEH_String("WISUCKS"), &sucks);
+ callback(DEH_String("WISUCKS"), &sucks);
// "par"
- callback(DEH_String("WIPAR"), &par);
+ callback(DEH_String("WIPAR"), &par);
// "killers" (vertical)
callback(DEH_String("WIKILRS"), &killers);
@@ -1680,16 +1679,16 @@ static void WI_loadUnloadData(load_callback_t callback)
callback(DEH_String("WIVCTMS"), &victims);
// "total"
- callback(DEH_String("WIMSTT"), &total);
+ callback(DEH_String("WIMSTT"), &total);
for (i=0 ; i<MAXPLAYERS ; i++)
{
// "1,2,3,4"
- sprintf(name, DEH_String("STPB%d"), i);
+ DEH_snprintf(name, 9, "STPB%d", i);
callback(name, &p[i]);
// "1,2,3,4"
- sprintf(name, DEH_String("WIBP%d"), i+1);
+ DEH_snprintf(name, 9, "WIBP%d", i+1);
callback(name, &bp[i]);
}
@@ -1697,19 +1696,21 @@ static void WI_loadUnloadData(load_callback_t callback)
if (gamemode == commercial)
{
- strcpy(name, DEH_String("INTERPIC"));
+ strncpy(name, DEH_String("INTERPIC"), 9);
+ name[8] = '\0';
}
else if (gamemode == retail && wbs->epsd == 3)
{
- strcpy(name, DEH_String("INTERPIC"));
+ strncpy(name, DEH_String("INTERPIC"), 9);
+ name[8] = '\0';
}
- else
+ else
{
- sprintf(name, DEH_String("WIMAP%d"), wbs->epsd);
+ DEH_snprintf(name, 9, "WIMAP%d", wbs->epsd);
}
-
+
// Draw backdrop and save to a temporary buffer
-
+
callback(name, &background);
}
@@ -1722,7 +1723,7 @@ void WI_loadData(void)
{
if (gamemode == commercial)
{
- NUMCMAPS = 32;
+ NUMCMAPS = 32;
lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMCMAPS,
PU_STATIC, NULL);
}