REDRIVER2/src_rebuild/GAME/C/CUTSCENE.C
Ilya Shurumov 51a7512123 - Cutscene recorder command-line feature
- implement LoadCutsceneAsReplay
- implement cutscene recorder under CUTSCENE_RECORDER define
2020-05-21 03:37:33 +06:00

1553 lines
31 KiB
C

#include "THISDUST.H"
#include "CUTSCENE.H"
#include "MISSION.H"
#include "CARS.H"
#include "PLAYERS.H"
#include "REPLAYS.H"
#include "GAMESND.H"
#include "GLAUNCH.H"
#include "CIV_AI.H"
#include "PEDEST.H"
#include "PRES.H"
#include "SYSTEM.H"
#include "CAMERA.H"
#include "MAIN.H"
#include "MC_SND.H"
#include "HANDLING.H"
#include "EVENT.H"
#include "DENTING.H"
#include "PAUSE.H"
#include "OVERMAP.H"
#include "DIRECTOR.H"
#include "LIBETC.H"
#include "STRINGS.H"
int gInGameCutsceneActive = 0;
int gInGameCutsceneDelay = 0;
int gInGameChaseActive = 0;
int gInGameCutsceneID = -1;
int gCutsceneAtEnd = 0;
int gThePlayerCar = -1;
static int CutsceneStreamIndex = 0;
int CutsceneFrameCnt = 0;
static int NumCutsceneStreams = 0;
static int gHaveInGameCutscene = 0;
static int gCSDestroyPlayer = 0;
static int PreLoadedCutscene = -1;
static char *CutsceneReplayStart = NULL;
static int CutsceneInReplayBuffer = 0;
static int CutsceneLength = 0;
static int BlackBorderHeight = 0;
int JustReturnedFromCutscene = 0;
int CutsceneEventTrigger = 0;
CUTSCENE_BUFFER CutsceneBuffer = { 0 };
static PLAYBACKCAMERA *CutLastChange;
static PLAYBACKCAMERA *CutNextChange;
PLAYBACKCAMERA *CutsceneCamera = NULL;
static int CutsceneCameraOffset = 0;
// decompiled code
// original method signature:
// void /*$ra*/ InitInGameCutsceneVariables()
// line 566, offset 0x000325c0
/* begin block 1 */
// Start line: 2383
/* end block 1 */
// End Line: 2384
/* begin block 2 */
// Start line: 1132
/* end block 2 */
// End Line: 1133
/* begin block 3 */
// Start line: 2384
/* end block 3 */
// End Line: 2385
/* WARNING: Unknown calling convention yet parameter storage is locked */
// [D]
void InitInGameCutsceneVariables(void)
{
CutsceneStreamIndex = 0;
CutsceneFrameCnt = 0;
NumCutsceneStreams = 0;
gHaveInGameCutscene = 0;
gInGameChaseActive = 0;
gInGameCutsceneActive = 0;
gCSDestroyPlayer = 0;
PreLoadedCutscene = -1;
CutsceneReplayStart = (char *)0x0;
CutsceneCamera = (PLAYBACKCAMERA *)0x0;
CutsceneInReplayBuffer = 0;
CutsceneEventTrigger = 0;
CutsceneLength = 0;
BlackBorderHeight = 0;
gInGameCutsceneDelay = 0;
gInGameCutsceneID = -1;
gCutsceneAtEnd = 0;
JustReturnedFromCutscene = 0;
FreeCutsceneBuffer();
}
// decompiled code
// original method signature:
// void /*$ra*/ HandleInGameCutscene()
// line 594, offset 0x0003262c
/* begin block 1 */
// Start line: 596
// Start offset: 0x0003262C
/* begin block 1.1 */
// Start line: 631
// Start offset: 0x0003270C
/* end block 1.1 */
// End offset: 0x00032730
// End Line: 642
/* end block 1 */
// End offset: 0x00032740
// End Line: 644
/* begin block 2 */
// Start line: 2446
/* end block 2 */
// End Line: 2447
/* begin block 3 */
// Start line: 2447
/* end block 3 */
// End Line: 2448
/* begin block 4 */
// Start line: 2452
/* end block 4 */
// End Line: 2453
/* WARNING: Unknown calling convention yet parameter storage is locked */
// [D]
void HandleInGameCutscene(void)
{
int iVar1;
if (gInGameCutsceneDelay != 0)
{
BlackBorderHeight = gInGameCutsceneDelay;
gInGameCutsceneDelay++;
if (27 < gInGameCutsceneDelay)
{
TriggerInGameCutscene(gInGameCutsceneID);
gInGameCutsceneDelay = 0;
BlackBorderHeight = 0x1c;
}
}
if (gHaveInGameCutscene == 0)
return;
if (pauseflag != 0)
return;
if (CameraCnt < 2)
BlackBorderHeight = 28;
if (CutsceneLength-28 < CutsceneFrameCnt)
{
iVar1 = BlackBorderHeight - 1;
if (BlackBorderHeight < 1)
goto LAB_000326f4;
}
else
{
iVar1 = BlackBorderHeight + 1;
if (27 < BlackBorderHeight)
goto LAB_000326f4;
}
BlackBorderHeight = iVar1;
LAB_000326f4:
CutsceneFrameCnt++;
if (CutsceneFrameCnt == CutsceneLength)
{
gHaveInGameCutscene = 0;
if (gInGameCutsceneActive != 0)
JustReturnedFromCutscene = 1;
ReleaseInGameCutscene();
InitOverheadMap();
}
}
// decompiled code
// original method signature:
// void /*$ra*/ DrawInGameCutscene()
// line 646, offset 0x00031398
/* begin block 1 */
// Start line: 648
// Start offset: 0x00031398
// Variables:
// struct TILE *tile; // $s0
/* end block 1 */
// End offset: 0x000314E8
// End Line: 676
/* begin block 2 */
// Start line: 1292
/* end block 2 */
// End Line: 1293
/* begin block 3 */
// Start line: 1293
/* end block 3 */
// End Line: 1294
/* begin block 4 */
// Start line: 1300
/* end block 4 */
// End Line: 1301
/* WARNING: Unknown calling convention yet parameter storage is locked */
void DrawInGameCutscene(void)
{
UNIMPLEMENTED();
/*
short sVar1;
DB *pDVar2;
ulong *puVar3;
uint *puVar4;
uint *puVar5;
if ((gInGameCutsceneActive != 0) || (gInGameCutsceneDelay != 0)) {
puVar4 = (uint *)current->primptr;
SetTile(puVar4);
*(char *)(puVar4 + 1) = '\0';
*(char *)((int)puVar4 + 5) = '\0';
*(char *)((int)puVar4 + 6) = '\0';
pDVar2 = current;
sVar1 = (short)BlackBorderHeight;
*(undefined2 *)(puVar4 + 2) = 0;
*(undefined2 *)((int)puVar4 + 10) = 0;
*(undefined2 *)(puVar4 + 3) = 0x140;
*(short *)((int)puVar4 + 0xe) = sVar1;
*puVar4 = *puVar4 & 0xff000000 | *pDVar2->ot & 0xffffff;
puVar3 = pDVar2->ot;
puVar5 = puVar4 + 4;
*puVar3 = *puVar3 & 0xff000000 | (uint)puVar4 & 0xffffff;
SetTile(puVar5);
*(char *)(puVar4 + 5) = '\0';
*(char *)((int)puVar4 + 0x15) = '\0';
*(char *)((int)puVar4 + 0x16) = '\0';
pDVar2 = current;
sVar1 = (short)BlackBorderHeight;
*(undefined2 *)(puVar4 + 6) = 0;
*(undefined2 *)(puVar4 + 7) = 0x140;
*(short *)((int)puVar4 + 0x1a) = 0x100 - sVar1;
*(short *)((int)puVar4 + 0x1e) = sVar1;
*puVar5 = *puVar5 & 0xff000000 | *pDVar2->ot & 0xffffff;
*pDVar2->ot = *pDVar2->ot & 0xff000000 | (uint)puVar5 & 0xffffff;
pDVar2->primptr = pDVar2->primptr + 0x20;
}
return;
*/
}
// decompiled code
// original method signature:
// void /*$ra*/ TriggerChase(int *car /*$s2*/, int cutscene /*$a1*/)
// line 683, offset 0x000314e8
/* begin block 1 */
// Start line: 684
// Start offset: 0x000314E8
// Variables:
// void *inform; // $s3
// int i; // $a0
// int length; // $s1
/* begin block 1.1 */
// Start line: 695
// Start offset: 0x00031558
/* end block 1.1 */
// End offset: 0x000316A4
// End Line: 721
/* end block 1 */
// End offset: 0x000316EC
// End Line: 725
/* begin block 2 */
// Start line: 1380
/* end block 2 */
// End Line: 1381
/* begin block 3 */
// Start line: 1388
/* end block 3 */
// End Line: 1389
// [D]
void TriggerChase(int *car, int cutscene)
{
int *inform;
int i;
int length;
inform = car_data[*car].inform;
car_data[*car].inform = NULL;
gInGameChaseActive = TriggerInGameCutsceneSystem(gRandomChase);
if (gInGameChaseActive)
{
length = 0;
// find maximum length of cutscene
for (i = CutsceneStreamIndex; i < NumReplayStreams; i++)
{
if (ReplayStreams[i].length > length)
length = ReplayStreams[i].length;
}
switch (gCurrentMissionNumber)
{
case 2:
case 4:
case 6:
case 10:
case 18:
Mission.timer[0].count = (15000 + (length / 30) * 3000);
break;
default:
Mission.timer[0].count = (length / 30) * 3000 - 15000;
}
Mission.timer[0].flags = 1;
*car = CutsceneStreamIndex;
player[0].targetCarId = CutsceneStreamIndex;
InitLeadHorn();
}
car_data[*car].inform = inform;
}
// decompiled code
// original method signature:
// void /*$ra*/ TriggerInGameCutscene(int cutscene /*$s0*/)
// line 732, offset 0x00032740
/* begin block 1 */
// Start line: 733
// Start offset: 0x00032740
/* begin block 1.1 */
// Start line: 762
// Start offset: 0x000327F0
/* end block 1.1 */
// End offset: 0x0003282C
// End Line: 769
/* end block 1 */
// End offset: 0x0003282C
// End Line: 770
/* begin block 2 */
// Start line: 2637
/* end block 2 */
// End Line: 2638
/* begin block 3 */
// Start line: 2726
/* end block 3 */
// End Line: 2727
static int SavedCameraView = 0;
static int SavedWorldCentreCarId = 0;
static VECTOR *SavedSpoolXZ = NULL;
static int SavedCameraCarId = 0;
static int SavedCameraAngle = 0;
// [D]
void TriggerInGameCutscene(int cutscene)
{
if (IsCutsceneResident(cutscene) == 0)
return;
gInGameCutsceneID = cutscene;
if (CameraCnt < 3 || 27 < gInGameCutsceneDelay)
{
SavedCameraCarId = player[0].cameraCarId;
SavedCameraView = cameraview;
SavedWorldCentreCarId = player[0].worldCentreCarId;
SavedCameraAngle = gCameraAngle;
SavedSpoolXZ = player[0].spoolXZ;
gInGameCutsceneActive = TriggerInGameCutsceneSystem(cutscene);
if (gInGameCutsceneActive != 0)
{
TerminateSkidding(0);
TerminateSkidding(1);
gStopPadReads = 1;
scr_z = 0x100;
if (gCSDestroyPlayer)
{
DestroyPlayer(0, 1);
}
}
}
else
{
gCutsceneAtEnd = 1;
gInGameCutsceneDelay = gInGameCutsceneDelay + 1;
}
}
// decompiled code
// original method signature:
// int /*$ra*/ CalcInGameCutsceneSize()
// line 778, offset 0x0003283c
/* begin block 1 */
// Start line: 817
// Start offset: 0x0003283C
// Variables:
// struct CUTSCENE_HEADER header; // stack offset -136
// char filename[64]; // stack offset -72
/* end block 1 */
// End offset: 0x000328C8
// End Line: 830
/* begin block 2 */
// Start line: 2827
/* end block 2 */
// End Line: 2828
/* begin block 3 */
// Start line: 2865
/* end block 3 */
// End Line: 2866
/* begin block 4 */
// Start line: 2868
/* end block 4 */
// End Line: 2869
/* WARNING: Unknown calling convention yet parameter storage is locked */
// [D]
int CalcInGameCutsceneSize(void)
{
CUTSCENE_HEADER header;
char filename[64];
if (gCurrentMissionNumber < 21)
sprintf(filename, "REPLAYS\\CUT%d.R", gCurrentMissionNumber);
else
sprintf(filename, "REPLAYS\\A\\CUT%d.R", gCurrentMissionNumber);
if (FileExists(filename) == 0)
return 0;
LoadfileSeg(filename, (char *)&header, 0, sizeof(CUTSCENE_HEADER));
return header.maxsize;
}
// decompiled code
// original method signature:
// void /*$ra*/ ReleaseInGameCutscene()
// line 838, offset 0x000316ec
/* begin block 1 */
// Start line: 840
// Start offset: 0x000316EC
/* begin block 1.1 */
// Start line: 845
// Start offset: 0x00031748
// Variables:
// struct STREAM_SOURCE *pinfo; // $a0
// int i; // $s0
/* end block 1.1 */
// End offset: 0x00031978
// End Line: 917
/* end block 1 */
// End offset: 0x00031A20
// End Line: 943
/* begin block 2 */
// Start line: 1601
/* end block 2 */
// End Line: 1602
/* begin block 3 */
// Start line: 1715
/* end block 3 */
// End Line: 1716
/* begin block 4 */
// Start line: 1716
/* end block 4 */
// End Line: 1717
/* WARNING: Unknown calling convention yet parameter storage is locked */
// [D] [A] might be incorrect
void ReleaseInGameCutscene(void)
{
int plr;
if (gInGameChaseActive != 0 && Mission.ChaseTarget != NULL)
{
player[1].padid = -128;
}
if (gInGameCutsceneActive != 0)
{
PingOutAllCivCarsAndCopCars();
InitCivCars();
if (CutsceneStreamIndex < NumReplayStreams)
{
plr = CutsceneStreamIndex;
do {
if ((PlayerStartInfo[plr]->flags & 4) == 0)
{
DestroyPlayer(plr, 1);
}
else
{
memcpy(&player[0], &player[plr], sizeof(_PLAYER));
if (player[0].playerType == 2)
{
player[0].pPed->padId = 0;
SavedWorldCentreCarId = -1;
SavedSpoolXZ = (VECTOR *)&player[0].pPed->position;
}
else
{
Swap2Cars(player[0].playerCarId, 0);
SavedWorldCentreCarId = player[0].playerCarId;
SavedSpoolXZ = (VECTOR *)car_data[SavedWorldCentreCarId].hd.where.t;
car_data[SavedWorldCentreCarId].ai.padid = &player[0].padid;
}
SavedCameraCarId = SavedWorldCentreCarId;
DestroyPlayer(plr, 0);
}
plr++;
} while (plr < NumReplayStreams);
}
gThePlayerCar = -1;
player[0].targetCarId = -1;
DestroyCivPedestrians();
AdjustPlayerCarVolume();
plr = player[0].playerCarId;
player[0].padid = 0;
player[0].worldCentreCarId = SavedWorldCentreCarId;
player[0].spoolXZ = SavedSpoolXZ;
player[0].cameraCarId = SavedCameraCarId;
if (plr != -1)
{
car_data[plr].ai.padid = &player[0].padid;
car_data[plr].controlType = 1;
}
cameraview = SavedCameraView;
gCameraAngle = SavedCameraAngle;
InitCamera(&player[0]);
player[0].cameraAngle = 0;
player[0].cameraDist = 1000;
CutsceneEventTrigger = 0;
}
if (CutsceneReplayStart != NULL)
replayptr = CutsceneReplayStart;
NumReplayStreams -= NumCutsceneStreams;
CutsceneReplayStart = NULL;
CutsceneStreamIndex = 0;
NumCutsceneStreams = 0;
PreLoadedCutscene = -1;
gHaveInGameCutscene = 0;
gCSDestroyPlayer = 0;
CutsceneLength = 0;
BlackBorderHeight = 0;
CutsceneCamera = NULL;
gInGameChaseActive = 0;
gInGameCutsceneActive = 0;
CutsceneFrameCnt = 0;
gInGameCutsceneDelay = 0;
gStopPadReads = 0;
xa_timeout = 70;
}
// decompiled code
// original method signature:
// int /*$ra*/ PreLoadInGameCutscene(int chase /*$a0*/)
// line 951, offset 0x000328c8
/* begin block 1 */
// Start line: 3054
/* end block 1 */
// End Line: 3055
/* begin block 2 */
// Start line: 3176
/* end block 2 */
// End Line: 3177
/* begin block 3 */
// Start line: 3177
/* end block 3 */
// End Line: 3178
// [D]
int PreLoadInGameCutscene(int chase)
{
return LoadInGameCutscene(chase) != 0;
}
// decompiled code
// original method signature:
// int /*$ra*/ CutsceneCameraChange(int cameracnt /*$s0*/)
// line 965, offset 0x000328e8
/* begin block 1 */
// Start line: 3204
/* end block 1 */
// End Line: 3205
/* begin block 2 */
// Start line: 3212
/* end block 2 */
// End Line: 3213
// [D]
int CutsceneCameraChange(int cameracnt)
{
cameracnt -= CutsceneCameraOffset;
if (CutNextChange->FrameCnt != cameracnt)
{
if (cameracnt < CutNextChange->FrameCnt)
{
IsMovingCamera(CutLastChange, CutNextChange, cameracnt);
return 0;
}
if (CutNextChange->next == -2)
return 0;
}
if (CutLastChange != CutNextChange && -1 < CutNextChange->angle.pad)
CutNextChange->angle.pad += CutsceneStreamIndex;
SetPlaybackCamera(CutNextChange);
if (-1 < cameracnt)
{
InvalidCamera(player[0].cameraCarId);
CutLastChange = CutNextChange;
FindNextCutChange(cameracnt + 1);
}
return 1;
}
// decompiled code
// original method signature:
// int /*$ra*/ LoadInGameCutscene(int subindex /*$s1*/)
// line 1010, offset 0x000329b4
/* begin block 1 */
// Start line: 1011
// Start offset: 0x000329B4
// Variables:
// int ret; // $s0
/* end block 1 */
// End offset: 0x00032A34
// End Line: 1033
/* begin block 2 */
// Start line: 3298
/* end block 2 */
// End Line: 3299
/* begin block 3 */
// Start line: 3301
/* end block 3 */
// End Line: 3302
// [D]
int LoadInGameCutscene(int subindex)
{
if (CutsceneInReplayBuffer)
return LoadCutsceneToBuffer(subindex);
if (LoadCutsceneToBuffer(subindex) != 0)
{
if (LoadCutsceneToReplayBuffer(0) != 0)
{
CutsceneInReplayBuffer = 1;
PreLoadedCutscene = subindex;
}
FreeCutsceneBuffer();
}
}
// decompiled code
// original method signature:
// int /*$ra*/ TriggerInGameCutsceneSystem(int cutscene /*$a0*/)
// line 1040, offset 0x00031a20
/* begin block 1 */
// Start line: 1041
// Start offset: 0x00031A20
// Variables:
// static char padid[8]; // offset 0x0
// int bDamageOverride; // stack offset -64
// int i; // $s2
// int id; // $v1
/* begin block 1.1 */
// Start line: 1058
// Start offset: 0x00031A64
/* begin block 1.1.1 */
// Start line: 1094
// Start offset: 0x00031BC4
// Variables:
// int car; // $v1
// int model; // $v1
// int palette; // $a1
/* end block 1.1.1 */
// End offset: 0x00031C1C
// End Line: 1105
/* begin block 1.1.2 */
// Start line: 1125
// Start offset: 0x00031CAC
/* begin block 1.1.2.1 */
// Start line: 1130
// Start offset: 0x00031D0C
// Variables:
// int car; // $v1
/* end block 1.1.2.1 */
// End offset: 0x00031D90
// End Line: 1144
/* end block 1.1.2 */
// End offset: 0x00031D90
// End Line: 1152
/* end block 1.1 */
// End offset: 0x00031EA0
// End Line: 1186
/* end block 1 */
// End offset: 0x00031EDC
// End Line: 1191
/* begin block 2 */
// Start line: 2105
/* end block 2 */
// End Line: 2106
/* begin block 3 */
// Start line: 2203
/* end block 3 */
// End Line: 2204
/* begin block 4 */
// Start line: 2209
/* end block 4 */
// End Line: 2210
// [D] [A] might be bugged
int TriggerInGameCutsceneSystem(int cutscene)
{
static char padid[8];
int iVar4;
_CAR_DATA *cp;
REPLAY_STREAM *stream;
int player_id;
int bDamageOverride;
bDamageOverride = 0;
if (cutscene > -1 && (gHaveInGameCutscene = LoadCutsceneInformation(cutscene), gHaveInGameCutscene != 0))
{
PingOutAllCivCarsAndCopCars();
InitCivCars();
DestroyCivPedestrians();
if (CutsceneStreamIndex <= player[0].playerCarId)
{
Swap2Cars(player[0].playerCarId, 0);
SavedCameraCarId = player[0].cameraCarId;
SavedWorldCentreCarId = player[0].playerCarId;
SavedSpoolXZ = player[0].spoolXZ;
}
if (CutsceneEventTrigger != 0)
{
TriggerEvent(CutsceneEventTrigger);
}
gThePlayerCar = -1;
if (CutsceneStreamIndex < NumReplayStreams)
{
stream = ReplayStreams + CutsceneStreamIndex;
player_id = CutsceneStreamIndex;
do {
PlayerStartInfo[player_id] = &stream->SourceType;
if ((stream->SourceType.flags & 4) != 0)
{
gCSDestroyPlayer = 1;
if (stream->SourceType.type == 1)
{
gThePlayerCar = player_id;
if (gCutsceneAtEnd != 0 && player[0].playerType == 1)
{
stream->SourceType.palette = car_data[player[0].playerCarId].ap.palette;
stream->SourceType.model = MissionHeader->residentModels[car_data[player[0].playerCarId].ap.model];
bDamageOverride = 1;
gCutsceneAtEnd = 0;
}
}
}
padid[player_id] = -player_id;
gStartOnFoot = stream->SourceType.type == 2;
if (gStartOnFoot || (stream->SourceType.flags & 1) == 0)
{
TerminateSkidding(player_id);
cp = &car_data[player_id];
InitPlayer(&player[player_id], cp,
stream->SourceType.controlType,
stream->SourceType.rotation,
(long(*)[4])&stream->SourceType.position,
stream->SourceType.model,
stream->SourceType.palette,
&padid[player_id]);
if (bDamageOverride != 0)
{
iVar4 = player[0].playerCarId;
cp->ap.needsDenting = 1;
cp->ap.damage[0] = car_data[iVar4].ap.damage[0];
cp->ap.damage[1] = car_data[iVar4].ap.damage[1];
cp->ap.damage[2] = car_data[iVar4].ap.damage[2];
cp->ap.damage[3] = car_data[iVar4].ap.damage[3];
cp->ap.damage[4] = car_data[iVar4].ap.damage[4];
cp->ap.damage[5] = car_data[iVar4].ap.damage[5];
bDamageOverride = 0;
cp->totalDamage = car_data[iVar4].totalDamage;
DentCar(cp);
}
}
else
{
iVar4 = CreateStationaryCivCar(stream->SourceType.rotation, 0, 1024,
(long(*)[4])&stream->SourceType.position,
stream->SourceType.model,
stream->SourceType.palette, 0);
if (iVar4 != -1)
{
player[player_id].playerCarId = iVar4;
SetNullPlayer(player_id);
}
}
if (player_id == CutsceneStreamIndex)
{
if (gStartOnFoot == 0)
{
player[0].spoolXZ = (VECTOR *)car_data[player_id].hd.where.t;
player[0].worldCentreCarId = CutsceneStreamIndex;
}
else
{
player[0].worldCentreCarId = -1;
player[0].spoolXZ = (VECTOR *)&player[player_id].pPed->position;
}
}
if (CutsceneLength < stream->length)
CutsceneLength = stream->length;
stream++;
player_id++;
} while (player_id < NumReplayStreams);
}
CutsceneCameraOffset = CameraCnt + 1;
CutNextChange = CutsceneCamera;
CutLastChange = NULL;
return 1;
}
ShowCutsceneError();
return 0;
}
// decompiled code
// original method signature:
// void /*$ra*/ SetNullPlayer(int plr /*$a0*/)
// line 1199, offset 0x00031edc
/* begin block 1 */
// Start line: 1200
// Start offset: 0x00031EDC
/* end block 1 */
// End offset: 0x00031F60
// End Line: 1213
/* begin block 2 */
// Start line: 2628
/* end block 2 */
// End Line: 2629
/* begin block 3 */
// Start line: 2637
/* end block 3 */
// End Line: 2638
/* begin block 4 */
// Start line: 2640
/* end block 4 */
// End Line: 2641
// [D]
void SetNullPlayer(int plr)
{
int carId = player[plr].playerCarId;
if (carId != -1)
{
car_data[carId].controlType = 2;
car_data[carId].ai.c.thrustState = 3;
car_data[carId].ai.c.ctrlState = 7;
car_data[carId].ai.c.ctrlNode = NULL;
player[plr].playerCarId = -1;
}
player[plr].playerType = 3;
}
// decompiled code
// original method signature:
// void /*$ra*/ SetNullPlayerDontKill(int plr /*$a0*/)
// line 1221, offset 0x00031f60
/* begin block 1 */
// Start line: 1222
// Start offset: 0x00031F60
/* end block 1 */
// End offset: 0x00031FE0
// End Line: 1235
/* begin block 2 */
// Start line: 2675
/* end block 2 */
// End Line: 2676
/* begin block 3 */
// Start line: 2684
/* end block 3 */
// End Line: 2685
/* begin block 4 */
// Start line: 2687
/* end block 4 */
// End Line: 2688
// [D]
void SetNullPlayerDontKill(int plr)
{
int carId = player[plr].playerCarId;
if (carId != -1)
{
car_data[carId].controlType = 7;
car_data[carId].ai.c.thrustState = 3;
car_data[carId].ai.c.ctrlState = 7;
car_data[carId].ai.c.ctrlNode = NULL;
player[plr].playerCarId = -1;
}
player[plr].playerType = 3;
}
// decompiled code
// original method signature:
// void /*$ra*/ DestroyPlayer(int plr /*$s0*/, int fully /*$a1*/)
// line 1244, offset 0x00031fe0
/* begin block 1 */
// Start line: 2723
/* end block 1 */
// End Line: 2724
/* begin block 2 */
// Start line: 2733
/* end block 2 */
// End Line: 2734
void DestroyPlayer(int plr, int fully)
{
if (PlayerStartInfo[plr]->flags & 2)
{
SetNullPlayerDontKill(plr);
return;
}
if (fully)
{
if (player[plr].playerType == 1 && player[plr].playerCarId != gThePlayerCar)
PingOutCar(&car_data[player[plr].playerCarId]);
if (player[plr].pPed != NULL)
DestroyPedestrian(player[plr].pPed);
}
player[plr].playerType = 3;
player[plr].playerCarId = -1;
player[plr].pPed = NULL;
}
// decompiled code
// original method signature:
// void /*$ra*/ FindNextCutChange(int cameracnt /*$a0*/)
// line 1274, offset 0x00032a34
/* begin block 1 */
// Start line: 1275
// Start offset: 0x00032A34
// Variables:
// int found; // $t0
// int count; // $a3
// int nextframe; // $a2
/* end block 1 */
// End offset: 0x00032A98
// End Line: 1291
/* begin block 2 */
// Start line: 3587
/* end block 2 */
// End Line: 3588
/* begin block 3 */
// Start line: 3829
/* end block 3 */
// End Line: 3830
/* begin block 4 */
// Start line: 3830
/* end block 4 */
// End Line: 3831
// [D]
void FindNextCutChange(int cameracnt)
{
bool found;
int iVar2;
PLAYBACKCAMERA *pPVar3;
int nextframe;
int iVar5;
found = false;
nextframe = 100001;
iVar5 = 59;
pPVar3 = CutsceneCamera;
do {
iVar2 = pPVar3->FrameCnt;
if (cameracnt <= iVar2 && iVar2 < nextframe)
{
found = true;
nextframe = iVar2;
CutNextChange = pPVar3;
}
iVar5--;
pPVar3++;
} while (-1 < iVar5);
if (!found)
CutNextChange->next = -2;
}
// decompiled code
// original method signature:
// int /*$ra*/ LoadCutsceneToReplayBuffer(int residentCutscene /*$a0*/)
// line 1299, offset 0x00032118
/* begin block 1 */
// Start line: 1301
// Start offset: 0x00032118
// Variables:
// struct REPLAY_SAVE_HEADER *rheader; // $a1
// struct REPLAY_STREAM_HEADER *sheader; // $t1
// char filename[64]; // stack offset -88
// char *pt; // $s1
// int i; // $a0
// int size; // $s0
/* end block 1 */
// End offset: 0x0003243C
// End Line: 1355
/* begin block 2 */
// Start line: 2846
/* end block 2 */
// End Line: 2847
/* begin block 3 */
// Start line: 2847
/* end block 3 */
// End Line: 2848
/* begin block 4 */
// Start line: 2852
/* end block 4 */
// End Line: 2853
// [D]
int LoadCutsceneToReplayBuffer(int residentCutscene)
{
REPLAY_SAVE_HEADER *rheader;
REPLAY_STREAM_HEADER *sheader;
char *pt;
rheader = (REPLAY_SAVE_HEADER *)CutsceneBuffer.residentPointers[residentCutscene];
if (rheader == NULL || rheader && (rheader->magic != 0x14793209 || rheader->NumReplayStreams == 0) )
{
ShowCutsceneError();
return 0;
}
CutsceneStreamIndex = NumReplayStreams;
NumCutsceneStreams = rheader->NumReplayStreams;
CutsceneReplayStart = replayptr;
CutsceneEventTrigger = rheader->CutsceneEvent;
pt = (char *)(rheader + 1);
// add to existing replay streams
for (int i = NumReplayStreams; i < (NumReplayStreams + rheader->NumReplayStreams); i++)
{
sheader = (REPLAY_STREAM_HEADER *)pt;
pt += sizeof(REPLAY_STREAM_HEADER);
REPLAY_STREAM* destStream = &ReplayStreams[i];
// copy source type
memcpy(&destStream->SourceType, &sheader->SourceType, sizeof(STREAM_SOURCE));
// init buffers
destStream->InitialPadRecordBuffer = (PADRECORD*)replayptr;
destStream->PadRecordBuffer = (PADRECORD*)replayptr;
destStream->PadRecordBufferEnd = (PADRECORD *)(replayptr + sheader->Size);
destStream->length = sheader->Length;
int size = (sheader->Size + sizeof(PADRECORD)) & -4;
// copy pad data and advance buffer
memcpy(replayptr, pt, size);
replayptr += size;
pt += size;
}
NumReplayStreams += rheader->NumReplayStreams;
// copy cutscene cameras and pings
CutsceneCamera = (PLAYBACKCAMERA *)replayptr;
memcpy(CutsceneCamera, pt, sizeof(PLAYBACKCAMERA) * 60); // MAX_CUTSCENE_CAMERAS
replayptr += sizeof(PLAYBACKCAMERA) * 60;
pt += sizeof(PLAYBACKCAMERA) * 60;
memcpy(PingBuffer, pt, sizeof(_PING_PACKET) * 400); // MAX_REPLAY_PINGS
PingBufferPos = 0;
return 1;
}
// decompiled code
// original method signature:
// int /*$ra*/ LoadCutsceneToBuffer(int subindex /*$s3*/)
// line 1362, offset 0x0003243c
/* begin block 1 */
// Start line: 1363
// Start offset: 0x0003243C
// Variables:
// struct CUTSCENE_HEADER header; // stack offset -440
// struct REPLAY_SAVE_HEADER rheader; // stack offset -376
// char filename[64]; // stack offset -88
// int offset; // $a2
// int size; // $s0
/* end block 1 */
// End offset: 0x000325C0
// End Line: 1440
/* begin block 2 */
// Start line: 3041
/* end block 2 */
// End Line: 3042
/* begin block 3 */
// Start line: 3049
/* end block 3 */
// End Line: 3050
/* begin block 4 */
// Start line: 3090
/* end block 4 */
// End Line: 3091
// [D]
int LoadCutsceneToBuffer(int subindex)
{
int offset;
int size;
CUTSCENE_HEADER header;
char filename[64];
if (gCurrentMissionNumber < 21)
sprintf(filename, "REPLAYS\\CUT%d.R", gCurrentMissionNumber);
else
sprintf(filename, "REPLAYS\\A\\CUT%d.R", gCurrentMissionNumber);
printInfo("Loading cutscene '%s' (%d)\n", filename, subindex);
if (FileExists(filename))
{
LoadfileSeg(filename, (char *)&header, 0, sizeof(CUTSCENE_HEADER));
if (header.data[subindex].offset != 0xffff)
{
offset = header.data[subindex].offset * 4;
size = header.data[subindex].size;
if (CutsceneBuffer.bytesFree < size)
{
// load into lead/path AI buffer
leadAILoaded = 0;
pathAILoaded = 0;
CutsceneBuffer.currentPointer = _other_buffer2;
CutsceneBuffer.bytesFree = 0xc000;
LoadfileSeg(filename, _other_buffer2, offset, size);
}
else
{
LoadfileSeg(filename, CutsceneBuffer.currentPointer, offset, size);
}
CutsceneBuffer.residentCutscenes[CutsceneBuffer.numResident] = subindex;
CutsceneBuffer.residentPointers[CutsceneBuffer.numResident] = CutsceneBuffer.currentPointer;
CutsceneBuffer.numResident++;
CutsceneBuffer.currentPointer += size;
CutsceneBuffer.bytesFree -= size;
return 1;
}
}
ShowCutsceneError();
return 0;
}
// decompiled code
// original method signature:
// void /*$ra*/ ShowCutsceneError()
// line 1442, offset 0x00032c08
/* begin block 1 */
// Start line: 4288
/* end block 1 */
// End Line: 4289
/* begin block 2 */
// Start line: 2884
/* end block 2 */
// End Line: 2885
/* begin block 3 */
// Start line: 4309
/* end block 3 */
// End Line: 4310
/* WARNING: Unknown calling convention yet parameter storage is locked */
// [A] From Code Review
void ShowCutsceneError(void)
{
RECT16 rect;
printf("Cutscene initialisation error!\n");
SetDispMask(0);
DrawSync(0);
rect.x = 0;
rect.y = 0;
rect.w = 320;
rect.h = 256;
ClearImage2(&rect, 0,0,0);
DrawSync(0);
SetTextColour(128, 0, 0);
PrintStringCentred("CUTSCENE ERROR!", 0x78);
DrawSync(0);
SetDispMask(1);
VSync(20);
}
// decompiled code
// original method signature:
// int /*$ra*/ LoadCutsceneInformation(int cutscene /*$s2*/)
// line 1471, offset 0x00032a98
/* begin block 1 */
// Start line: 1472
// Start offset: 0x00032A98
// Variables:
// int i; // $s1
/* end block 1 */
// End offset: 0x00032B54
// End Line: 1498
/* begin block 2 */
// Start line: 4048
/* end block 2 */
// End Line: 4049
/* begin block 3 */
// Start line: 4229
/* end block 3 */
// End Line: 4230
/* begin block 4 */
// Start line: 4232
/* end block 4 */
// End Line: 4233
// [D]
int LoadCutsceneInformation(int cutscene)
{
int i;
if (cutscene == PreLoadedCutscene)
{
PreLoadedCutscene = -1;
return 1;
}
ReleaseInGameCutscene();
for(i = 0; i < 4; i++)
{
if (cutscene == CutsceneBuffer.residentCutscenes[i])
{
if (LoadCutsceneToReplayBuffer(i))
{
CutsceneBuffer.residentCutscenes[i] = 0xFF;
CutsceneBuffer.residentPointers[i] = NULL;
return 1;
}
}
};
return 0;
}
// decompiled code
// original method signature:
// void /*$ra*/ FreeCutsceneBuffer()
// line 1505, offset 0x00032b54
/* begin block 1 */
// Start line: 1507
// Start offset: 0x00032B54
// Variables:
// int i; // $v1
/* end block 1 */
// End offset: 0x00032BC0
// End Line: 1518
/* begin block 2 */
// Start line: 4307
/* end block 2 */
// End Line: 4308
/* begin block 3 */
// Start line: 4315
/* end block 3 */
// End Line: 4316
/* begin block 4 */
// Start line: 4316
/* end block 4 */
// End Line: 4317
/* begin block 5 */
// Start line: 4318
/* end block 5 */
// End Line: 4319
/* WARNING: Unknown calling convention yet parameter storage is locked */
// [D]
void FreeCutsceneBuffer(void)
{
int i;
for (i = 0; i < 4; i++)
{
CutsceneBuffer.residentCutscenes[i] = -1;
CutsceneBuffer.residentPointers[i] = NULL;
}
CutsceneBuffer.numResident = 0;
CutsceneBuffer.currentPointer = CutsceneBuffer.buffer;
CutsceneBuffer.bytesFree = sizeof(CutsceneBuffer.buffer);
ClearMem(CutsceneBuffer.buffer, sizeof(CutsceneBuffer.buffer));
}
// decompiled code
// original method signature:
// int /*$ra*/ IsCutsceneResident(int cutscene /*$a0*/)
// line 1520, offset 0x00032bc0
/* begin block 1 */
// Start line: 1521
// Start offset: 0x00032BC0
// Variables:
// int i; // $a1
/* end block 1 */
// End offset: 0x00032C08
// End Line: 1533
/* begin block 2 */
// Start line: 4349
/* end block 2 */
// End Line: 4350
/* begin block 3 */
// Start line: 4352
/* end block 3 */
// End Line: 4353
/* begin block 4 */
// Start line: 4355
/* end block 4 */
// End Line: 4356
// [D]
int IsCutsceneResident(int cutscene)
{
int i;
if (cutscene == PreLoadedCutscene)
return 1;
for (i = 0; i < 4; i++)
{
if (CutsceneBuffer.residentCutscenes[i] == cutscene)
return 1;
}
return 0;
}