mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-27 04:00:42 +00:00
0157446ad1
This was one huge mess where nothing fit together. Also added an enhancement that the CD Audio boss theme tracks are also played when CD music is generally off, because these have no equivalent in MIDI. This needs to be checked if it's stylistically ok, though.
624 lines
14 KiB
C++
624 lines
14 KiB
C++
//-------------------------------------------------------------------------
|
|
/*
|
|
Copyright (C) 1997, 2005 - 3D Realms Entertainment
|
|
|
|
This file is part of Shadow Warrior version 1.2
|
|
|
|
Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
Original Source: 1997 - Frank Maddin and Jim Norwood
|
|
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
|
|
*/
|
|
//-------------------------------------------------------------------------
|
|
|
|
#include "ns.h"
|
|
//#define MAIN
|
|
//#define QUIET
|
|
#include "build.h"
|
|
#include "cache1d.h"
|
|
|
|
#include "keys.h"
|
|
#include "names2.h"
|
|
#include "panel.h"
|
|
#include "game.h"
|
|
#include "network.h"
|
|
|
|
#include "mytypes.h"
|
|
#include "control.h"
|
|
#include "gamecontrol.h"
|
|
#include "demo.h"
|
|
|
|
#include "player.h"
|
|
#include "menus.h"
|
|
|
|
BEGIN_SW_NS
|
|
|
|
DFILE DemoFileIn;
|
|
FILE *DemoFileOut;
|
|
SWBOOL DemoPlaying = FALSE;
|
|
SWBOOL DemoRecording = FALSE;
|
|
SWBOOL DemoEdit = FALSE;
|
|
SWBOOL DemoMode = FALSE;
|
|
SWBOOL DemoModeMenuState = FALSE;
|
|
SWBOOL DemoOverride = FALSE;
|
|
char DemoFileName[16] = "demo.dmo";
|
|
char DemoLevelName[16] = "";
|
|
extern SWBOOL NewGame;
|
|
|
|
// Demo sync stuff
|
|
FILE *DemoSyncFile;
|
|
SWBOOL DemoSyncTest = FALSE, DemoSyncRecord = FALSE;
|
|
char DemoTmpName[16] = "";
|
|
|
|
SW_PACKET DemoBuffer[DEMO_BUFFER_MAX];
|
|
int DemoRecCnt = 0; // Can only record 1-player game
|
|
|
|
SWBOOL DemoDone;
|
|
|
|
void DemoWriteHeader(void);
|
|
void DemoReadHeader(void);
|
|
void DemoReadBuffer(void);
|
|
|
|
|
|
//
|
|
// DemoDebug Vars
|
|
//
|
|
|
|
// DemoDebugMode will close the file after every write
|
|
SWBOOL DemoDebugMode = FALSE;
|
|
//SWBOOL DemoDebugMode = TRUE;
|
|
SWBOOL DemoInitOnce = FALSE;
|
|
short DemoDebugBufferMax = 1;
|
|
|
|
extern char LevelName[];
|
|
extern uint8_t FakeMultiNumPlayers;
|
|
extern SWBOOL QuitFlag;
|
|
|
|
///////////////////////////////////////////
|
|
//
|
|
// Demo File Manipulation
|
|
//
|
|
///////////////////////////////////////////
|
|
|
|
char *DemoSyncFileName(void)
|
|
{
|
|
static char file_name[32];
|
|
char *ptr;
|
|
|
|
strcpy(file_name, DemoFileName);
|
|
|
|
if ((ptr = strchr(file_name, '.')) == 0)
|
|
strcat(file_name, ".dms");
|
|
else
|
|
{
|
|
*ptr = '\0';
|
|
strcat(file_name, ".dms");
|
|
}
|
|
|
|
return file_name;
|
|
}
|
|
|
|
void
|
|
DemoSetup(void)
|
|
{
|
|
if (DemoRecording)
|
|
{
|
|
if (DemoSyncRecord)
|
|
DemoSyncFile = fopen(DemoSyncFileName(),"wb");
|
|
|
|
DemoWriteHeader();
|
|
memset(&DemoBuffer, -1, sizeof(DemoBuffer));
|
|
}
|
|
|
|
if (DemoPlaying)
|
|
{
|
|
if (DemoSyncRecord)
|
|
DemoSyncFile = fopen(DemoSyncFileName(),"wb");
|
|
if (DemoSyncTest)
|
|
DemoSyncFile = fopen(DemoSyncFileName(),"rb");
|
|
|
|
DemoReadHeader();
|
|
memset(&DemoBuffer, -1, sizeof(DemoBuffer));
|
|
DemoReadBuffer();
|
|
}
|
|
}
|
|
|
|
void
|
|
DemoRecordSetup(void)
|
|
{
|
|
if (DemoRecording)
|
|
{
|
|
if (DemoSyncRecord)
|
|
DemoSyncFile = fopen(DemoSyncFileName(),"wb");
|
|
|
|
DemoWriteHeader();
|
|
memset(&DemoBuffer, -1, sizeof(DemoBuffer));
|
|
}
|
|
}
|
|
|
|
void
|
|
DemoPlaySetup(void)
|
|
{
|
|
if (DemoPlaying)
|
|
{
|
|
if (DemoSyncRecord)
|
|
DemoSyncFile = fopen(DemoSyncFileName(),"wb");
|
|
if (DemoSyncTest)
|
|
DemoSyncFile = fopen(DemoSyncFileName(),"rb");
|
|
|
|
DemoReadHeader();
|
|
memset(&DemoBuffer, -1, sizeof(DemoBuffer));
|
|
DemoReadBuffer();
|
|
}
|
|
}
|
|
|
|
void
|
|
DemoWriteHeader(void)
|
|
{
|
|
DEMO_HEADER dh;
|
|
DEMO_START_POS dsp;
|
|
PLAYERp pp;
|
|
|
|
DemoFileOut = fopen(DemoFileName, "wb");
|
|
|
|
if (!DemoFileOut)
|
|
return;
|
|
|
|
strcpy(dh.map_name, LevelName);
|
|
strcpy(dh.LevelSong, "");
|
|
dh.Level = Level;
|
|
|
|
if (FakeMultiNumPlayers)
|
|
dh.numplayers = FakeMultiNumPlayers;
|
|
else
|
|
dh.numplayers = numplayers;
|
|
|
|
fwrite(&dh, sizeof(dh), 1, DemoFileOut);
|
|
|
|
for (pp = Player; pp < Player + dh.numplayers; pp++)
|
|
{
|
|
dsp.x = pp->posx;
|
|
dsp.y = pp->posy;
|
|
dsp.z = pp->posz;
|
|
fwrite(&dsp, sizeof(dsp), 1, DemoFileOut);
|
|
fwrite(&pp->Flags, sizeof(pp->Flags), 1, DemoFileOut);
|
|
fwrite(&pp->pang, sizeof(pp->pang), 1, DemoFileOut);
|
|
}
|
|
|
|
fwrite(&Skill, sizeof(Skill), 1, DemoFileOut);
|
|
fwrite(&gNet, sizeof(gNet), 1, DemoFileOut);
|
|
|
|
if (DemoDebugMode)
|
|
{
|
|
DemoDebugBufferMax = numplayers;
|
|
fclose(DemoFileOut);
|
|
}
|
|
}
|
|
|
|
void
|
|
DemoReadHeader(void)
|
|
{
|
|
DEMO_HEADER dh;
|
|
DEMO_START_POS dsp;
|
|
PLAYERp pp;
|
|
|
|
#if DEMO_FILE_TYPE != DEMO_FILE_GROUP
|
|
if (DemoEdit)
|
|
{
|
|
DemoFileIn = fopen(DemoFileName, "rb+");
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
//DemoFileIn = fopen(DemoFileName, "rb");
|
|
DemoFileIn = DOPEN_READ(DemoFileName);
|
|
}
|
|
|
|
if (DF_ERR(DemoFileIn))
|
|
{
|
|
TerminateGame();
|
|
printf("File %s is not a valid demo file.",DemoFileName);
|
|
exit(0);
|
|
}
|
|
|
|
DREAD(&dh, sizeof(dh), 1, DemoFileIn);
|
|
|
|
strcpy(DemoLevelName, dh.map_name);
|
|
Level = dh.Level;
|
|
if (dh.numplayers > 1)
|
|
{
|
|
FakeMultiNumPlayers = dh.numplayers;
|
|
}
|
|
else
|
|
numplayers = dh.numplayers;
|
|
|
|
for (pp = Player; pp < Player + dh.numplayers; pp++)
|
|
{
|
|
DREAD(&dsp, sizeof(dsp), 1, DemoFileIn);
|
|
pp->posx = dsp.x;
|
|
pp->posy = dsp.y;
|
|
pp->posz = dsp.z;
|
|
COVERupdatesector(pp->posx, pp->posy, &pp->cursectnum);
|
|
//pp->cursectnum = 0;
|
|
//updatesectorz(pp->posx, pp->posy, pp->posz, &pp->cursectnum);
|
|
DREAD(&pp->Flags, sizeof(pp->Flags), 1, DemoFileIn);
|
|
DREAD(&pp->pang, sizeof(pp->pang), 1, DemoFileIn);
|
|
}
|
|
|
|
DREAD(&Skill, sizeof(Skill), 1, DemoFileIn);
|
|
DREAD(&gNet, sizeof(gNet), 1, DemoFileIn);
|
|
}
|
|
|
|
void
|
|
DemoDebugWrite(void)
|
|
{
|
|
int size;
|
|
|
|
DemoFileOut = fopen(DemoFileName, "ab");
|
|
|
|
ASSERT(DemoFileOut);
|
|
|
|
size = sizeof(SW_PACKET) * DemoDebugBufferMax;
|
|
fwrite(&DemoBuffer, size, 1, DemoFileOut);
|
|
memset(&DemoBuffer, -1, size);
|
|
|
|
fclose(DemoFileOut);
|
|
}
|
|
|
|
void
|
|
DemoWriteBuffer(void)
|
|
{
|
|
fwrite(&DemoBuffer, sizeof(DemoBuffer), 1, DemoFileOut);
|
|
memset(&DemoBuffer, -1, sizeof(DemoBuffer));
|
|
}
|
|
|
|
void
|
|
DemoReadBuffer(void)
|
|
{
|
|
memset(&DemoBuffer, -1, sizeof(DemoBuffer));
|
|
DREAD(&DemoBuffer, sizeof(DemoBuffer), 1, DemoFileIn);
|
|
}
|
|
|
|
void
|
|
DemoBackupBuffer(void)
|
|
{
|
|
#if DEMO_FILE_TYPE != DEMO_FILE_GROUP
|
|
FILE *NewDemoFile;
|
|
FILE *OldDemoFile = DemoFileIn;
|
|
int pos,i;
|
|
char copy_buffer;
|
|
char NewDemoFileName[16] = "!";
|
|
|
|
// seek backwards to beginning of last buffer
|
|
fseek(OldDemoFile, -sizeof(DemoBuffer), SEEK_CUR);
|
|
pos = ftell(OldDemoFile);
|
|
|
|
// open a new edit file
|
|
strcat(NewDemoFileName, DemoFileName);
|
|
NewDemoFile = fopen(NewDemoFileName, "wb");
|
|
|
|
rewind(OldDemoFile);
|
|
|
|
// copy old demo to new demo
|
|
for (i = 0; i < pos; i++)
|
|
{
|
|
fread(©_buffer, sizeof(copy_buffer), 1, OldDemoFile);
|
|
fwrite(©_buffer,sizeof(copy_buffer), 1, NewDemoFile);
|
|
}
|
|
|
|
DemoFileOut = NewDemoFile;
|
|
fclose(OldDemoFile);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
DemoTerm(void)
|
|
{
|
|
if (DemoRecording)
|
|
{
|
|
// if already closed
|
|
if (DemoFileOut == NULL)
|
|
return;
|
|
|
|
if (DemoDebugMode)
|
|
{
|
|
DemoFileOut = fopen(DemoFileName, "ab");
|
|
ASSERT(DemoFileOut);
|
|
}
|
|
else
|
|
{
|
|
// paste on a -1 record to the current buffer
|
|
if (DemoRecCnt < DEMO_BUFFER_MAX)
|
|
memset(&DemoBuffer[DemoRecCnt], -1, sizeof(DemoBuffer[DemoRecCnt]));
|
|
|
|
DemoWriteBuffer();
|
|
}
|
|
|
|
// write at least 1 record at the end filled with -1
|
|
// just for good measure
|
|
memset(&DemoBuffer[0], -1, sizeof(DemoBuffer[0]));
|
|
fwrite(&DemoBuffer[0], sizeof(DemoBuffer[0]), 1, DemoFileOut);
|
|
|
|
fclose(DemoFileOut);
|
|
DemoFileOut = NULL;
|
|
}
|
|
|
|
if (DemoPlaying)
|
|
{
|
|
if (DF_ERR(DemoFileIn))
|
|
return;
|
|
|
|
DCLOSE(DemoFileIn);
|
|
}
|
|
|
|
if (DemoSyncTest||DemoSyncRecord)
|
|
{
|
|
fclose(DemoSyncFile);
|
|
DemoSyncFile = NULL;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////
|
|
//
|
|
// Demo Play Back
|
|
//
|
|
///////////////////////////////////////////
|
|
|
|
|
|
void
|
|
DemoPlayBack(void)
|
|
{
|
|
int pnum, cnt;
|
|
static int buf_ndx;
|
|
PLAYERp pp;
|
|
ControlInfo info;
|
|
int Xdim, Ydim, ScreenSize;
|
|
|
|
// Initialize Game part of network code (When ready2send != 0)
|
|
InitNetVars();
|
|
|
|
// IMPORTANT - MUST be right before game loop
|
|
InitTimingVars();
|
|
|
|
// THIS STUFF DEPENDS ON MYCONNECTINDEX BEING SET RIGHT
|
|
pp = Player + myconnectindex;
|
|
SetRedrawScreen(pp);
|
|
|
|
if (!DemoInitOnce)
|
|
buf_ndx = 0;
|
|
|
|
// everything has been inited at least once for PLAYBACK
|
|
DemoInitOnce = TRUE;
|
|
|
|
cnt = 0;
|
|
ready2send = 0;
|
|
DemoDone = FALSE;
|
|
|
|
while (TRUE)
|
|
{
|
|
// makes code run at the same rate
|
|
while (totalclock > totalsynctics)
|
|
{
|
|
handleevents();
|
|
|
|
TRAVERSE_CONNECT(pnum)
|
|
{
|
|
pp = Player + pnum;
|
|
pp->inputfifo[pp->movefifoend & (MOVEFIFOSIZ-1)] = DemoBuffer[buf_ndx];
|
|
pp->movefifoend++;
|
|
buf_ndx++;
|
|
|
|
if (pp->inputfifo[(pp->movefifoend - 1) & (MOVEFIFOSIZ-1)].bits == -1)
|
|
{
|
|
DemoDone = TRUE;
|
|
break;
|
|
}
|
|
|
|
if (buf_ndx > DEMO_BUFFER_MAX - 1)
|
|
{
|
|
DemoReadBuffer();
|
|
buf_ndx = 0;
|
|
}
|
|
}
|
|
|
|
if (DemoDone)
|
|
break;
|
|
|
|
cnt++;
|
|
|
|
CONTROL_GetInput(&info);
|
|
|
|
domovethings();
|
|
|
|
// fast forward and slow mo
|
|
if (DemoEdit)
|
|
{
|
|
if (inputState.GetKeyStatus(KEYSC_F))
|
|
{
|
|
if (inputState.GetKeyStatus(KEYSC_LSHIFT) || inputState.GetKeyStatus(KEYSC_RSHIFT))
|
|
totalclock += synctics;
|
|
else
|
|
totalclock += synctics-1;
|
|
}
|
|
|
|
if (inputState.GetKeyStatus(KEYSC_S))
|
|
totalclock += 1-synctics;
|
|
}
|
|
else
|
|
{
|
|
|
|
if (buttonMap.ButtonDown(gamefunc_See_Coop_View))
|
|
{
|
|
buttonMap.ClearButton(gamefunc_See_Coop_View);
|
|
|
|
screenpeek = connectpoint2[screenpeek];
|
|
|
|
if (screenpeek < 0)
|
|
screenpeek = connecthead;
|
|
}
|
|
}
|
|
|
|
|
|
if (DemoSyncRecord)
|
|
demosync_record();
|
|
if (DemoSyncTest)
|
|
demosync_test(cnt);
|
|
}
|
|
|
|
// Put this back in later when keyboard stuff is stable
|
|
if (DemoEdit)
|
|
{
|
|
//CONTROL_GetButtonInput();
|
|
CONTROL_GetInput(&info);
|
|
|
|
// if a key is pressed, start recording from the point the key
|
|
// was pressed
|
|
if (buttonMap.ButtonDown(gamefunc_Move_Forward) ||
|
|
buttonMap.ButtonDown(gamefunc_Move_Backward) ||
|
|
buttonMap.ButtonDown(gamefunc_Turn_Left) ||
|
|
buttonMap.ButtonDown(gamefunc_Turn_Right) ||
|
|
buttonMap.ButtonDown(gamefunc_Fire) ||
|
|
buttonMap.ButtonDown(gamefunc_Open) ||
|
|
buttonMap.ButtonDown(gamefunc_Jump) ||
|
|
buttonMap.ButtonDown(gamefunc_Crouch) ||
|
|
buttonMap.ButtonDown(gamefunc_Look_Up) ||
|
|
buttonMap.ButtonDown(gamefunc_Look_Down))
|
|
{
|
|
DemoBackupBuffer();
|
|
|
|
DemoRecCnt = buf_ndx;
|
|
DemoPlaying = FALSE;
|
|
DemoRecording = TRUE;
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (buttonMap.ButtonDown(gamefunc_See_Co_Op_View))
|
|
{
|
|
screenpeek += 1;
|
|
if (screenpeek > numplayers-1)
|
|
screenpeek = 0;
|
|
}
|
|
|
|
// demo is over
|
|
if (DemoDone)
|
|
break;
|
|
|
|
if (QuitFlag)
|
|
{
|
|
DemoMode = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (ExitLevel)
|
|
{
|
|
// Quiting Demo
|
|
ExitLevel = FALSE;
|
|
if (DemoMode)
|
|
{
|
|
DemoPlaying = FALSE;
|
|
DemoMode = FALSE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
drawscreen(Player + screenpeek);
|
|
}
|
|
|
|
// only exit if conditions are write
|
|
if (DemoDone && !DemoMode && !NewGame)
|
|
{
|
|
TerminateLevel();
|
|
TerminateGame();
|
|
exit(0);
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Still using old method of playback - this was for opening demo
|
|
//
|
|
|
|
void
|
|
ScenePlayBack(void)
|
|
{
|
|
int buf_ndx, pnum, cnt;
|
|
PLAYERp pp;
|
|
|
|
if (SW_SHAREWARE)
|
|
{
|
|
// code here needs to be similar to RunLevel startup code
|
|
PlaySong(nullptr, "yokoha03.mid", -1);
|
|
}
|
|
|
|
// IMPORTANT - MUST be right before game loop
|
|
InitTimingVars();
|
|
|
|
buf_ndx = 0;
|
|
cnt = 0;
|
|
ready2send = 0;
|
|
DemoDone = FALSE;
|
|
|
|
ResetKeys();
|
|
|
|
while (TRUE)
|
|
{
|
|
// makes code run at the same rate
|
|
while ((totalclock > totalsynctics))
|
|
{
|
|
TRAVERSE_CONNECT(pnum)
|
|
{
|
|
pp = Player + pnum;
|
|
pp->inputfifo[pp->movefifoend & (MOVEFIFOSIZ - 1)] = DemoBuffer[buf_ndx];
|
|
pp->movefifoend++;
|
|
buf_ndx++;
|
|
|
|
if (pp->inputfifo[(pp->movefifoend - 1) & (MOVEFIFOSIZ - 1)].bits == -1)
|
|
{
|
|
DemoDone = TRUE;
|
|
break;
|
|
}
|
|
|
|
if (buf_ndx > DEMO_BUFFER_MAX - 1)
|
|
{
|
|
DemoReadBuffer();
|
|
buf_ndx = 0;
|
|
}
|
|
}
|
|
|
|
if (KeyPressed())
|
|
DemoDone = TRUE;
|
|
|
|
if (DemoDone)
|
|
break;
|
|
|
|
cnt++;
|
|
|
|
//movethings();
|
|
domovethings();
|
|
}
|
|
|
|
// demo is over
|
|
if (DemoDone)
|
|
break;
|
|
|
|
drawscreen(Player + screenpeek);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
END_SW_NS
|