demo playback QOL features (#545)

* implement demo progress bar

* implement demoskip and skipsec

* implement game speed keys

* fix gcc warning

* fix music if -skipsec is used

* fix game speed keys

* initialize basetime

* restore I_GetTime_RealTime()

* rename GetTimeMS()->GetTimeMS_Scaled()

* use fastdemo for demo skipping

* rename skip to fast-forward

* compensate fastdemo tic

* refactor i_system.h

* move timer functions to i_timer.c
* remove unused code

* remove redundant redeclaration

* fix timer declaration

* rename I_SetFastdemo->I_SetFastdemoTimer

* fix menu game speed option

* simplify I_SetFastdemoTimer

* move the timer initialization parts to I_InitTimer

* fix typo

* restore noblit

* add demo_skipping macro
This commit is contained in:
Roman Fomin 2022-05-09 13:19:21 +07:00 committed by GitHub
parent c27abe1300
commit a54abbec31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 552 additions and 268 deletions

View File

@ -38,6 +38,7 @@ set(WOOF_SOURCES
i_winmusic.c
i_sound.c i_sound.h
i_system.c i_system.h
i_timer.c i_timer.h
i_video.c i_video.h
info.c info.h
m_argv.c m_argv.h

View File

@ -145,6 +145,8 @@ boolean main_loop_started = false;
boolean coop_spawns = false;
boolean demobar;
//jff 4/19/98 list of standard IWAD names
typedef struct
{
@ -232,6 +234,15 @@ void D_Display (void)
int wipestart;
boolean done, wipe, redrawsbar;
if (demobar && demo_skipping)
{
if (HU_DemoProgressBar(false))
{
I_FinishUpdate();
return;
}
}
if (nodrawers) // for comparative timing / profiling
return;
@ -279,9 +290,6 @@ void D_Display (void)
break;
}
// draw buffered stuff to screen
I_UpdateNoBlit();
// draw the view directly
if (gamestate == GS_LEVEL && !automapactive && gametic)
R_RenderPlayerView (&players[displayplayer]);
@ -344,6 +352,9 @@ void D_Display (void)
M_Drawer(); // menu is drawn even on top of everything
NetUpdate(); // send out any new accumulation
if (demobar && demoplayback)
HU_DemoProgressBar(true);
// normal update
if (!wipe)
{
@ -367,7 +378,6 @@ void D_Display (void)
while (!tics);
wipestart = nowtime;
done = wipe_ScreenWipe(wipe_Melt,0,0,SCREENWIDTH,SCREENHEIGHT,tics);
I_UpdateNoBlit();
M_Drawer(); // menu is drawn even on top of wipes
I_FinishUpdate(); // page flip or blit buffer
}
@ -2038,7 +2048,7 @@ void D_DoomMain(void)
}
//jff end of sound/music command line parms
// killough 3/2/98: allow -nodraw -noblit generally
// killough 3/2/98: allow -nodraw generally
nodrawers = M_CheckParm ("-nodraw");
noblit = M_CheckParm ("-noblit");
@ -2193,6 +2203,23 @@ void D_DoomMain(void)
coop_spawns = true;
}
p = M_CheckParmWithArgs("-skipsec", 1);
if (p)
{
float min, sec;
if (sscanf(myargv[p+1], "%f:%f", &min, &sec) == 2)
{
demoskip_tics = (int) ((60 * min + sec) * TICRATE);
}
else if (sscanf(myargv[p+1], "%f", &sec) == 1)
{
demoskip_tics = (int) (sec * TICRATE);
}
demoskip_tics = abs(demoskip_tics);
}
// start the apropriate game based on parms
// killough 12/98:
@ -2232,8 +2259,11 @@ void D_DoomMain(void)
singledemo = true; // quit after one demo
}
else
// [FG] no demo playback
demowarp = -1;
{
// [FG] no demo playback
demowarp = -1;
demoskip_tics = -1;
}
if (slot && ++slot < myargc)
{

View File

@ -50,9 +50,6 @@ extern boolean clfastparm; // checkparm of -fast
extern boolean pistolstart;
extern boolean nosfxparm;
extern boolean nomusicparm;
// Called by IO functions when input is detected.
void D_PostEvent(event_t* ev);

View File

@ -220,6 +220,8 @@ extern boolean paused; // Game Pause?
extern boolean viewactive;
extern boolean nodrawers;
extern boolean noblit;
extern boolean nosfxparm;
extern boolean nomusicparm;
// This one is related to the 3-screen display mode.
// ANG90 = left side, ANG270 = right
@ -267,7 +269,11 @@ extern boolean fastdemo;
// [FG] fast-forward demo to the desired map
extern int demowarp;
// fast-forward demo to the next map
extern boolean demoskip;
extern boolean demonext;
// skipping demo
extern int demoskip_tics;
#define demo_skipping (demowarp >= 0 || demoskip_tics > 0 || demonext)
extern gamestate_t gamestate;

View File

@ -273,6 +273,30 @@ static int G_NextWeapon(int direction)
return weapon_order_table[i].weapon_num;
}
int demoskip_tics = -1;
static void G_DemoSkipTics(void)
{
static boolean warp = false;
if (demoskip_tics == -1)
return;
if (demowarp >= 0)
warp = true;
if (demowarp == -1)
{
if ((warp && demoskip_tics < gametic - levelstarttic) ||
(!warp && demoskip_tics < gametic))
{
I_EnableWarp(false);
S_RestartMusic();
demoskip_tics = -1;
}
}
}
//
// G_BuildTiccmd
// Builds a ticcmd from all of the available inputs
@ -290,6 +314,8 @@ void G_BuildTiccmd(ticcmd_t* cmd)
int newweapon; // phares
ticcmd_t *base;
G_DemoSkipTics();
base = I_BaseTiccmd(); // empty, or external driver
memcpy(cmd, base, sizeof *cmd);
@ -878,6 +904,9 @@ boolean G_Responder(event_t* ev)
// DEMO RECORDING
//
// [crispy] demo progress bar
int defdemotics = 0, deftotaldemotics;
#define DEMOMARKER 0x80
static void G_ReadDemoTiccmd(ticcmd_t *cmd)
@ -907,6 +936,8 @@ static void G_ReadDemoTiccmd(ticcmd_t *cmd)
cmd->buttons &= ~BTS_SAVEGAME;
players[consoleplayer].message = "Game Saved (Suppressed)";
}
defdemotics++;
}
}
@ -1259,16 +1290,20 @@ static void G_DoPlayDemo(void)
char basename[9];
int demover;
byte *option_p = NULL; // killough 11/98
int lumpnum, lumplength;
if (gameaction != ga_loadgame) // killough 12/98: support -loadgame
basetic = gametic; // killough 9/29/98
ExtractFileBase(defdemoname,basename); // killough
demobuffer = demo_p = W_CacheLumpName (basename, PU_STATIC); // killough
lumpnum = W_GetNumForName(basename);
lumplength = W_LumpLength(lumpnum);
demobuffer = demo_p = W_CacheLumpNum(lumpnum, PU_STATIC); // killough
// [FG] ignore too short demo lumps
if (W_LumpLength(W_GetNumForName(basename)) < 0xd)
if (lumplength < 0xd)
{
INVALID_DEMO("Short demo lump %s.\n", basename);
}
@ -1468,6 +1503,24 @@ static void G_DoPlayDemo(void)
gameaction = ga_nothing;
// [crispy] demo progress bar
{
int i, numplayersingame = 0;
byte *demo_ptr = demo_p;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
numplayersingame++;
deftotaldemotics = defdemotics = 0;
while (*demo_ptr != DEMOMARKER && (demo_ptr - demobuffer) < lumplength)
{
demo_ptr += numplayersingame * (longtics ? 5 : 4);
deftotaldemotics++;
}
}
// [FG] report compatibility mode
fprintf(stderr, "G_DoPlayDemo: Playing demo with %s (%d) compatibility.\n",
mbf21 ? "MBF21" :
@ -2851,6 +2904,7 @@ void G_InitNew(skill_t skill, int episode, int map)
// [FG] total time for all completed levels
totalleveltimes = 0;
defdemotics = 0;
//jff 4/16/98 force marks on automap cleared every new level start
AM_clearMarks();
@ -3310,7 +3364,7 @@ void G_DeferedPlayDemo(char* name)
gameaction = ga_playdemo;
// [FG] fast-forward demo to the desired map
if (demowarp >= 0)
if (demowarp >= 0 || demoskip_tics > 0)
{
I_EnableWarp(true);
}

View File

@ -854,12 +854,12 @@ static void HU_widget_build_sttime(void)
{
char *s;
int offset = 0;
extern int clock_rate;
extern int time_scale;
if (clock_rate != 100)
if (time_scale != 100)
{
offset += sprintf(hud_timestr, "SPEED \x1b%c%d \x1b%c",
'0'+CR_GREEN, clock_rate, '0'+CR_GRAY);
'0'+CR_GREEN, time_scale, '0'+CR_GRAY);
}
offset += sprintf(hud_timestr + offset, "TIME");
@ -969,6 +969,27 @@ static void HU_DrawCrosshair(void)
0, crosshair.patch, crosshair.cr, 0);
}
// [crispy] print a bar indicating demo progress at the bottom of the screen
boolean HU_DemoProgressBar(boolean force)
{
const int progress = SCREENWIDTH * defdemotics / deftotaldemotics;
static int old_progress = 0;
if (progress - old_progress)
{
old_progress = progress;
}
else if (!force)
{
return false;
}
V_DrawHorizLine(0, SCREENHEIGHT - 2, FG, progress, colormaps[0][0]); // [crispy] black
V_DrawHorizLine(0, SCREENHEIGHT - 1, FG, progress, colormaps[0][4]); // [crispy] white
return true;
}
// [FG] level stats and level time widgets
int map_player_coords, map_level_stats, map_level_time;

View File

@ -60,6 +60,8 @@ void HU_Drawer(void);
char HU_dequeueChatChar(void);
void HU_Erase(void);
boolean HU_DemoProgressBar(boolean force);
// killough 5/2/98: moved from m_misc.c:
//jff 2/16/98 hud supported automap colors added
@ -88,6 +90,8 @@ extern int hud_secret_message; // "A secret is revealed!" message
extern int map_player_coords, map_level_stats, map_level_time; // [FG] level stats and level time widgets
extern int hud_timests; // Time/STS above status bar
extern int defdemotics, deftotaldemotics;
extern int crispy_hud;
extern int hud_crosshair;

View File

@ -44,7 +44,6 @@
#include "m_misc.h"
#include "g_game.h"
#include "w_wad.h"
#include "v_video.h"
#include "m_argv.h"
#include "i_endoom.h"
@ -54,101 +53,10 @@ ticcmd_t *I_BaseTiccmd(void)
return &emptycmd;
}
void I_WaitVBL(int count)
{
// haleyjd
SDL_Delay((count*500)/TICRATE);
}
// [FG] let the CPU sleep if there is no tic to proceed
void I_Sleep(int ms)
{
SDL_Delay(ms);
}
// Same as I_GetTime, but returns time in milliseconds
static Uint32 basetime = 0;
int I_GetTimeMS(void)
{
return SDL_GetTicks() - basetime;
}
// Most of the following has been rewritten by Lee Killough
//
// I_GetTime
//
int I_GetTime_RealTime(void)
{
return (int64_t)I_GetTimeMS() * TICRATE / 1000;
}
// killough 4/13/98: Make clock rate adjustable by scale factor
int realtic_clock_rate = 100;
int clock_rate;
static int I_GetTime_Scaled(void)
{
return (int64_t)I_GetTimeMS() * clock_rate * TICRATE / 100000;
}
static int I_GetTime_FastDemo(void)
{
static int fasttic;
return fasttic++;
}
static int I_GetTime_Error(void)
{
I_Error("Error: GetTime() used before initialization");
return 0;
}
int (*I_GetTime)() = I_GetTime_Error; // killough
// During a fast demo, no time elapses in between ticks
static int I_GetFracTimeFastDemo(void)
{
return 0;
}
static int I_GetFracRealTime(void)
{
return (int64_t)I_GetTimeMS() * TICRATE % 1000 * FRACUNIT / 1000;
}
static int I_GetFracScaledTime(void)
{
return (int64_t)I_GetTimeMS() * clock_rate * TICRATE / 100 % 1000 * FRACUNIT / 1000;
}
int (*I_GetFracTime)(void) = I_GetFracRealTime;
int leds_always_off; // Tells it not to update LEDs
// pointer to current joystick device information
SDL_GameController *controller = NULL;
static int controller_index = -1;
static SDL_Keymod oldmod; // haleyjd: save old modifier key state
static void I_ShutdownJoystick(void)
{
I_CloseController(controller_index);
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
}
void I_Shutdown(void)
{
SDL_SetModState(oldmod);
I_ShutdownJoystick();
}
void I_OpenController(int which)
{
if (controller)
@ -184,6 +92,18 @@ void I_CloseController(int which)
}
}
static void I_ShutdownJoystick(void)
{
I_CloseController(controller_index);
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
}
void I_Shutdown(void)
{
I_ShutdownJoystick();
}
void I_InitJoystick(void)
{
if (SDL_Init(SDL_INIT_GAMECONTROLLER) < 0)
@ -198,105 +118,17 @@ void I_InitJoystick(void)
printf("I_InitJoystick: Initialize game controller.\n");
}
// haleyjd
void I_InitKeyboard(void)
{
SDL_Keymod mod;
oldmod = SDL_GetModState();
if (M_InputMatchKey(input_autorun, KEYD_CAPSLOCK))
mod = KMOD_CAPS;
else if (M_InputMatchKey(input_autorun, KEYD_NUMLOCK))
mod = KMOD_NUM;
else if (M_InputMatchKey(input_autorun, KEYD_SCROLLLOCK))
mod = KMOD_MODE;
else
mod = KMOD_NONE;
if(autorun)
SDL_SetModState(mod);
else
SDL_SetModState(KMOD_NONE);
}
extern boolean nomusicparm, nosfxparm;
void I_Init(void)
{
int p;
I_InitTimer();
clock_rate = realtic_clock_rate;
if((p = M_CheckParm("-speed")) && p < myargc-1 &&
(p = atoi(myargv[p+1])) >= 10 && p <= 1000)
clock_rate = p;
// init timer
basetime = SDL_GetTicks();
I_InitJoystick();
// killough 4/14/98: Adjustable speedup based on realtic_clock_rate
if(fastdemo)
{
I_GetTime = I_GetTime_FastDemo;
I_GetFracTime = I_GetFracTimeFastDemo;
}
else
if(clock_rate != 100)
{
I_GetTime = I_GetTime_Scaled;
I_GetFracTime = I_GetFracScaledTime;
}
else
{
I_GetTime = I_GetTime_RealTime;
I_GetFracTime = I_GetFracRealTime;
}
I_AtExit(I_Shutdown, true);
I_InitJoystick();
// killough 3/6/98: save keyboard state, initialize shift state and LEDs:
// killough 3/6/98: end of keyboard / autorun state changes
I_AtExit(I_Shutdown, true);
// killough 2/21/98: avoid sound initialization if no sound & no music
{
if(!(nomusicparm && nosfxparm))
I_InitSound();
}
}
// [FG] toggle demo warp mode
void I_EnableWarp (boolean warp)
{
static int (*I_GetTime_old)() = I_GetTime_Error;
static boolean nodrawers_old, noblit_old;
static boolean nomusicparm_old, nosfxparm_old;
if (warp)
{
I_GetTime_old = I_GetTime;
nodrawers_old = nodrawers;
noblit_old = noblit;
nomusicparm_old = nomusicparm;
nosfxparm_old = nosfxparm;
I_GetTime = I_GetTime_FastDemo;
nodrawers = true;
noblit = true;
nomusicparm = true;
nosfxparm = true;
}
else
{
I_GetTime = I_GetTime_old;
D_StartGameLoop();
nodrawers = nodrawers_old;
noblit = noblit_old;
nomusicparm = nomusicparm_old;
nosfxparm = nosfxparm_old;
}
// killough 2/21/98: avoid sound initialization if no sound & no music
if (!(nomusicparm && nosfxparm))
I_InitSound();
}
//

View File

@ -30,6 +30,7 @@
#define __I_SYSTEM__
#include "d_ticcmd.h"
#include "i_timer.h"
// Called by DoomMain.
void I_Init(void);
@ -38,22 +39,6 @@ void I_InitJoystick(void);
void I_OpenController(int which);
void I_CloseController(int which);
// Called by D_DoomLoop,
// returns current time in tics.
// int I_GetTime (void);
extern int (*I_GetTime)(); // killough
int I_GetTime_RealTime(); // killough
int I_GetTime_Adaptive(void); // killough 4/10/98
extern int GetTime_Scale;
extern int (*I_GetFracTime)(void);
// [FG] Same as I_GetTime, but returns time in milliseconds
int I_GetTimeMS();
// [FG] toggle demo warp mode
extern void I_EnableWarp (boolean warp);
//
// Called by D_DoomLoop,
// called before processing any tics in a frame
@ -90,19 +75,12 @@ void I_Quit (void);
void I_QuitFirst (void);
void I_QuitLast (void);
// Allocates from low memory under dos, just mallocs under unix
#define I_AllocLow(length) calloc((length),1) /* killough */
#define I_Tactile(on, off, total)
// killough 3/20/98: add const
// killough 4/25/98: add gcc attributes
void I_Error(const char *error, ...) PRINTF_ATTR(1, 2);
extern int leds_always_off; // killough 10/98
void I_ResetLEDs(void); // killough 10/98
void I_EndDoom(void); // killough 2/22/98: endgame screen
// Schedule a function to be called when the program exits.

209
Source/i_timer.c Normal file
View File

@ -0,0 +1,209 @@
//
// Copyright (C) 1999 by
// id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
// Copyright (C) 2022 Roman Fomin
//
// 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.
//
// DESCRIPTION:
// Timer functions.
//
#include "SDL.h"
#include "i_timer.h"
#include "m_fixed.h"
#include "doomstat.h"
#include "m_argv.h"
static int MSToTic(Uint32 time)
{
return time * TICRATE / 1000;
}
static Uint32 TicToMS(int tic)
{
return (Uint32)tic * 1000 / TICRATE;
}
static Uint32 basetime = 0;
int I_GetTimeMS(void)
{
Uint32 time;
time = SDL_GetTicks();
if (basetime == 0)
basetime = time;
return time - basetime;
}
int time_scale = 100;
static Uint32 GetTimeMS_Scaled(void)
{
Uint32 time;
if (time_scale == 100)
{
time = SDL_GetTicks();
}
else
{
time = SDL_GetTicks() * time_scale / 100;
}
if (basetime == 0)
basetime = time;
return time - basetime;
}
int I_GetTime_RealTime(void)
{
return MSToTic(I_GetTimeMS());
}
static int I_GetTime_Scaled(void)
{
return MSToTic(GetTimeMS_Scaled());
}
static int fasttic;
static int I_GetTime_FastDemo(void)
{
return fasttic++;
}
int (*I_GetTime)() = I_GetTime_Scaled;
static int I_GetFracTime_Scaled(void)
{
return GetTimeMS_Scaled() * TICRATE % 1000 * FRACUNIT / 1000;
}
// During a fast demo, no time elapses in between ticks
static int I_GetFracTime_FastDemo(void)
{
return 0;
}
int (*I_GetFracTime)(void) = I_GetFracTime_Scaled;
// killough 4/13/98: Make clock rate adjustable by scale factor
int realtic_clock_rate = 100;
void I_InitTimer(void)
{
int p;
p = M_CheckParmWithArgs("-speed", 1);
if (p)
{
time_scale = BETWEEN(10, 1000, atoi(myargv[p+1]));
}
else
{
time_scale = realtic_clock_rate;
}
if (fastdemo)
{
I_GetTime = I_GetTime_FastDemo;
I_GetFracTime = I_GetFracTime_FastDemo;
}
else
{
I_GetTime = I_GetTime_Scaled;
I_GetFracTime = I_GetFracTime_Scaled;
}
}
void I_SetTimeScale(int scale)
{
Uint32 time;
time = GetTimeMS_Scaled();
time_scale = scale;
basetime += (GetTimeMS_Scaled() - time);
}
void I_SetFastdemoTimer(void)
{
if (fastdemo)
{
fasttic = I_GetTime();
I_GetTime = I_GetTime_FastDemo;
I_GetFracTime = I_GetFracTime_FastDemo;
}
else
{
Uint32 time;
time = TicToMS(I_GetTime_FastDemo());
basetime += (GetTimeMS_Scaled() - time);
I_GetTime = I_GetTime_Scaled;
I_GetFracTime = I_GetFracTime_Scaled;
}
}
// [FG] toggle demo warp mode
void I_EnableWarp(boolean warp)
{
static int (*I_GetTime_old)() = I_GetTime_Scaled;
static boolean nodrawers_old;
static boolean nomusicparm_old, nosfxparm_old;
if (warp)
{
I_GetTime_old = I_GetTime;
nodrawers_old = nodrawers;
nomusicparm_old = nomusicparm;
nosfxparm_old = nosfxparm;
I_GetTime = I_GetTime_FastDemo;
nodrawers = true;
nomusicparm = true;
nosfxparm = true;
}
else
{
I_GetTime = I_GetTime_old;
D_StartGameLoop();
nodrawers = nodrawers_old;
nomusicparm = nomusicparm_old;
nosfxparm = nosfxparm_old;
}
}
// Sleep for a specified number of ms
void I_Sleep(int ms)
{
SDL_Delay(ms);
}
void I_WaitVBL(int count)
{
// haleyjd
I_Sleep((count * 500) / TICRATE);
}

51
Source/i_timer.h Normal file
View File

@ -0,0 +1,51 @@
//
// Copyright (C) 1999 by
// id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
// Copyright (C) 2022 Roman Fomin
//
// 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.
//
// DESCRIPTION:
// Timer functions.
//
#ifndef __I_TIMER__
#define __I_TIMER__
#include "doomtype.h"
// Called by D_DoomLoop,
// returns current time in tics.
extern int (*I_GetTime)(void);
int I_GetTime_RealTime(void); // killough
extern int (*I_GetFracTime)(void);
// [FG] Same as I_GetTime, but returns time in milliseconds
int I_GetTimeMS();
void I_SetTimeScale(int scale);
void I_SetFastdemoTimer(void);
// [FG] toggle demo warp mode
void I_EnableWarp(boolean warp);
// Pause for a specified number of ms
void I_Sleep(int ms);
// Initialize timer
void I_InitTimer(void);
// Wait for vertical retrace or pause a bit.
void I_WaitVBL(int count);
#endif

View File

@ -864,14 +864,6 @@ void I_StartTic (void)
I_UpdateJoystick();
}
//
// I_UpdateNoBlit
//
void I_UpdateNoBlit (void)
{
}
int use_vsync; // killough 2/8/98: controls whether vsync is called
int page_flip; // killough 8/15/98: enables page flipping
int hires;
@ -1028,7 +1020,7 @@ void I_BeginRead(unsigned int bytes)
static void I_DrawDiskIcon(void)
{
if (!disk_icon || !in_graphics_mode)
if (!disk_icon || !in_graphics_mode || demo_skipping)
return;
if (disk_to_draw >= DISK_ICON_THRESHOLD)
@ -1051,7 +1043,7 @@ void I_EndRead(void)
static void I_RestoreDiskBackground(void)
{
if (!disk_icon || !in_graphics_mode)
if (!disk_icon || !in_graphics_mode || demo_skipping)
return;
if (disk_to_restore)
@ -1339,8 +1331,6 @@ static void I_InitGraphicsMode(void)
{
firsttime = false;
I_InitKeyboard();
if (M_CheckParm("-hires"))
hires = true;
else if (M_CheckParm("-nohires"))

View File

@ -53,13 +53,8 @@ void I_ShutdownGraphics(void);
// Takes full 8 bit values.
void I_SetPalette (byte* palette);
void I_UpdateNoBlit (void);
void I_FinishUpdate (void);
// Wait for vertical retrace or pause a bit.
void I_WaitVBL(int count);
void I_Sleep(int ms); // [FG] let the CPU sleep
void I_ReadScreen (byte* scr);
int I_DoomCode2ScanCode(int); // killough

View File

@ -89,6 +89,10 @@ enum
input_pause,
input_spy,
input_demo_quit,
input_demo_fforward,
input_speed_up,
input_speed_down,
input_speed_default,
input_map,
input_map_up,

View File

@ -2782,11 +2782,15 @@ setup_menu_t keys_settings2[] = // Key Binding screen strings
{"BFG", S_INPUT ,m_scrn,KB_X,M_Y+7*M_SPC,{0},input_weapon7},
{"CHAINSAW",S_INPUT ,m_scrn,KB_X,M_Y+8*M_SPC,{0},input_weapon8},
{"SSG" ,S_INPUT ,m_scrn,KB_X,M_Y+9*M_SPC,{0},input_weapon9},
{"BEST" ,S_INPUT ,m_scrn,KB_X,M_Y+10*M_SPC,{0},input_weapontoggle},
// [FG] prev/next weapon keys and buttons
{"PREV" ,S_INPUT ,m_scrn,KB_X,M_Y+11*M_SPC,{0},input_prevweapon},
{"NEXT" ,S_INPUT ,m_scrn,KB_X,M_Y+12*M_SPC,{0},input_nextweapon},
{"BEST" ,S_INPUT ,m_scrn,KB_X,M_Y+13*M_SPC,{0},input_weapontoggle},
{"GAME SPEED",S_SKIP|S_TITLE,m_null,KB_X,M_Y+14*M_SPC},
{"INCREASE" ,S_INPUT,m_scrn,KB_X,M_Y+15*M_SPC,{0},input_speed_up},
{"DECREASE" ,S_INPUT,m_scrn,KB_X,M_Y+16*M_SPC,{0},input_speed_down},
{"DEFAULT" ,S_INPUT,m_scrn,KB_X,M_Y+17*M_SPC,{0},input_speed_default},
{"<- PREV",S_SKIP|S_PREV,m_null,M_X_PREV,M_Y_PREVNEXT, {keys_settings1}},
{"NEXT ->",S_SKIP|S_NEXT,m_null,M_X_NEXT,M_Y_PREVNEXT, {keys_settings3}},
@ -2821,7 +2825,8 @@ setup_menu_t keys_settings3[] =
{"MISCELLANEOUS",S_SKIP|S_TITLE,m_null,KB_X,M_Y+11*M_SPC},
{"RELOAD LEVEL",S_INPUT,m_scrn,KB_X,M_Y+12*M_SPC,{0},input_menu_reloadlevel},
{"NEXT LEVEL" ,S_INPUT,m_scrn,KB_X,M_Y+13*M_SPC,{0},input_menu_nextlevel},
{"FINISH DEMO" ,S_INPUT,m_scrn,KB_X,M_Y+14*M_SPC,{0},input_demo_quit},
{"FAST-FORWARD DEMO",S_INPUT,m_scrn,KB_X,M_Y+14*M_SPC,{0},input_demo_fforward},
{"FINISH DEMO" ,S_INPUT,m_scrn,KB_X,M_Y+15*M_SPC,{0},input_demo_quit},
{"<- PREV", S_SKIP|S_PREV,m_null,M_X_PREV,M_Y_PREVNEXT, {keys_settings2}},
{"NEXT ->", S_SKIP|S_NEXT,m_null,M_X_NEXT,M_Y_PREVNEXT, {keys_settings4}},
@ -3712,6 +3717,7 @@ enum {
general_skill,
general_comp,
general_endoom,
general_demobar,
general_end5,
};
@ -3768,6 +3774,9 @@ setup_menu_t gen_settings2[] = { // General Settings screen2
{"Show ENDOOM screen", S_CHOICE, m_null, M_X,
G_Y4 + general_endoom*M_SPC, {"show_endoom"}, 0, NULL, default_endoom_strings},
{"Show demo progress bar", S_YESNO, m_null, M_X,
G_Y4 + general_demobar*M_SPC, {"demobar"}},
{"<- PREV",S_SKIP|S_PREV, m_null, M_X_PREV, M_Y_PREVNEXT, {gen_settings1}},
// Final entry
@ -5076,15 +5085,48 @@ boolean M_Responder (event_t* ev)
// [FG] reload current level / go to next level
if (M_InputActivated(input_menu_nextlevel))
{
if (demoplayback && singledemo && !demoskip)
if (demoplayback && singledemo && !demo_skipping)
{
demoskip = true;
demonext = true;
I_EnableWarp(true);
return true;
}
else if (G_GotoNextLevel(NULL, NULL))
return true;
}
if (M_InputActivated(input_demo_fforward))
{
if (demoplayback && singledemo && !demo_skipping)
{
fastdemo = !fastdemo;
I_SetFastdemoTimer();
return true;
}
}
if (M_InputActivated(input_speed_up) && (!netgame || demoplayback))
{
realtic_clock_rate += 10;
realtic_clock_rate = BETWEEN(10, 1000, realtic_clock_rate);
dprintf("Game Speed: %d", realtic_clock_rate);
I_SetTimeScale(realtic_clock_rate);
}
if (M_InputActivated(input_speed_down) && (!netgame || demoplayback))
{
realtic_clock_rate -= 10;
realtic_clock_rate = BETWEEN(10, 1000, realtic_clock_rate);
dprintf("Game Speed: %d", realtic_clock_rate);
I_SetTimeScale(realtic_clock_rate);
}
if (M_InputActivated(input_speed_default) && (!netgame || demoplayback))
{
realtic_clock_rate = 100;
dprintf("Game Speed: %d", realtic_clock_rate);
I_SetTimeScale(realtic_clock_rate);
}
}
// Pop-up Main menu?

View File

@ -95,6 +95,7 @@ extern char *soundfont_path;
extern boolean mus_chorus;
extern boolean mus_reverb;
#endif
extern boolean demobar;
extern char *chat_macros[], *wad_files[], *deh_files[]; // killough 10/98
@ -188,6 +189,13 @@ default_t defaults[] = {
"1 for linear horizontal sky scrolling "
},
{
"demobar",
(config_t *) &demobar, NULL,
{0}, {0,1}, number, ss_gen, wad_no,
"1 to enable demo progress bar"
},
{ // killough 2/21/98
"pitched_sounds",
(config_t *) &pitched_sounds, NULL,
@ -399,13 +407,6 @@ default_t defaults[] = {
"1 to use Doom's main menu ordering"
},
{ // killough 3/6/98
"leds_always_off",
(config_t *) &leds_always_off, NULL,
{0}, {0,1}, number, ss_gen, wad_no,
"1 to keep keyboard LEDs turned off"
},
{ //jff 4/3/98 allow unlimited sensitivity
"mouse_sensitivity_horiz",
(config_t *) &mouseSensitivity_horiz, NULL,
@ -859,6 +860,38 @@ default_t defaults[] = {
input_demo_quit, { {0, 0} }
},
{
"input_demo_fforward",
NULL, NULL,
{0}, {UL,UL}, input, ss_keys, wad_no,
"key for fast-forward demo",
input_demo_fforward, { {0, 0} }
},
{
"input_speed_up",
NULL, NULL,
{0}, {UL,UL}, input, ss_keys, wad_no,
"key to increase game speed",
input_speed_up, { {0, 0} }
},
{
"input_speed_down",
NULL, NULL,
{0}, {UL,UL}, input, ss_keys, wad_no,
"key to decrease game speed",
input_speed_down, { {0, 0} }
},
{
"input_speed_default",
NULL, NULL,
{0}, {UL,UL}, input, ss_keys, wad_no,
"key to reset game speed",
input_speed_default, { {0, 0} }
},
{
"input_strafeleft",
NULL, NULL,

View File

@ -1419,7 +1419,7 @@ static boolean P_LoadReject(int lumpnum, int totallines)
// killough 5/3/98: reformatted, cleaned up
// fast-forward demo to the next map
boolean demoskip = false;
boolean demonext = false;
void P_SetupLevel(int episode, int map, int playermask, skill_t skill)
{
@ -1440,11 +1440,13 @@ void P_SetupLevel(int episode, int map, int playermask, skill_t skill)
players[consoleplayer].viewz = 1;
// [FG] fast-forward demo to the desired map
if (demowarp == map || demoskip)
if (demowarp == map || demonext)
{
I_EnableWarp(false);
if (demoskip_tics == -1)
I_EnableWarp(false);
demowarp = -1;
demoskip = false;
demonext = false;
}
// Make sure all sounds are stopped before Z_FreeTags.

View File

@ -54,8 +54,6 @@
#define S_ATTENUATOR ((S_CLIPPING_DIST-S_CLOSE_DIST)>>FRACBITS)
//jff 1/22/98 make sound enabling variables readable here
extern boolean nosfxparm, nomusicparm;
//jff end sound enabling variables readable here
typedef struct channel_s
@ -563,20 +561,24 @@ void S_SetSfxVolume(int volume)
snd_SfxVolume = volume;
}
static int current_musicnum = -1;
void S_ChangeMusic(int musicnum, int looping)
{
musicinfo_t *music;
musinfo.current_item = -1;
S_music[mus_musinfo].lumpnum = -1;
if(musicnum <= mus_None || musicnum >= NUMMUSIC)
I_Error("Bad music number %d", musicnum);
current_musicnum = musicnum;
//jff 1/22/98 return if music is not enabled
if(nomusicparm)
return;
if(musicnum <= mus_None || musicnum >= NUMMUSIC)
I_Error("Bad music number %d", musicnum);
music = &S_music[musicnum];
if(mus_playing == music)
@ -668,6 +670,18 @@ void S_ChangeMusInfoMusic (int lumpnum, int looping)
musinfo.current_item = lumpnum;
}
void S_RestartMusic(void)
{
if (musinfo.current_item != -1)
{
S_ChangeMusInfoMusic(musinfo.current_item, true);
}
else if (current_musicnum != -1)
{
S_ChangeMusic(current_musicnum, true);
}
}
//
// Starts some music with the music id found in sounds.h.
//
@ -726,10 +740,6 @@ void S_Start(void)
}
}
//jff 1/22/98 return if music is not enabled
if (nomusicparm)
return;
// start new music for the level
mus_paused = 0;

View File

@ -73,6 +73,8 @@ void S_StopMusic(void);
void S_PauseSound(void);
void S_ResumeSound(void);
void S_RestartMusic(void);
//
// Updates music & sounds
//

View File

@ -867,6 +867,27 @@ void V_PutBlock(int x, int y, int scrn, int width, int height, byte *src)
}
}
void V_DrawHorizLine(int x, int y, int scrn, int width, byte color)
{
byte *dest;
int height = 1;
// [crispy] prevent framebuffer overflows
if (x + width > (unsigned)SCREENWIDTH)
width = SCREENWIDTH - x;
if (hires)
y<<=2, x<<=1, width<<=1, height<<=1;
dest = screens[scrn] + y * SCREENWIDTH + x;
while (height--)
{
memset(dest, color, width);
dest += SCREENWIDTH << hires;
}
}
//
// V_Init
//

View File

@ -133,6 +133,8 @@ void V_GetBlock(int x, int y, int scrn, int width, int height, byte *dest);
void V_PutBlock(int x, int y, int scrn, int width, int height, byte *src);
void V_DrawHorizLine(int x, int y, int scrn, int width, byte color);
#define V_MarkRect(x,y,width,height) /* killough 11/98: unused */
// [FG] colored blood and gibs