Add action replay (#230)

* Add replay

* Hide action replay behind --enable-replay

* Update src/DETHRACE/dr_types.h

* Compy OS_ALlocateACtionReplayBuffer from linux to macos

* Add missing macro

* Fix LengthOfSession for smudges

* Implement PipeInstantUnSmudge
This commit is contained in:
Anonymous Maarten 2022-11-21 22:44:37 +01:00 committed by GitHub
parent e1cbc20465
commit 5eebedfdc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 2438 additions and 228 deletions

View File

@ -22,6 +22,9 @@ br_uint_32 BrActorEnum(br_actor* parent, br_actor_enum_cbfn* callback, void* arg
br_bounds* BrActorToBounds(br_bounds* b, br_actor* ap);
br_uint_16 BrActorToActorMatrix34(br_matrix34* m, br_actor* a, br_actor* b);
void BrLightEnable(br_actor* l);
void BrLightDisable(br_actor* l);
// BrAllocator
br_allocator* BrAllocatorSet(br_allocator* newal);

View File

@ -1,6 +1,8 @@
# Create object files so we can link them into the main binary and into tests without building twice.
add_library(dethrace_obj OBJECT)
option(DETHRACE_REPLAY_DEBUG "Debug replay" OFF)
target_include_directories(dethrace_obj
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
@ -43,6 +45,10 @@ else()
target_compile_definitions(dethrace_obj PRIVATE BR_ENDIAN_LITTLE=1)
endif()
if(DETHRACE_REPLAY_DEBUG)
target_compile_definitions(dethrace_obj PRIVATE DETHRACE_REPLAY_DEBUG)
endif()
target_sources(dethrace_obj PRIVATE
common/brucetrk.c
common/brucetrk.h

View File

@ -21,6 +21,7 @@
#include "oil.h"
#include "opponent.h"
#include "pd/sys.h"
#include "pedestrn.h"
#include "piping.h"
#include "pratcam.h"
#include "raycast.h"
@ -34,8 +35,8 @@
#include <math.h>
#include <stdlib.h>
int gDoing_physics;
br_scalar gDt;
int gDoing_physics = 0;
br_scalar gDt = 0.f;
// suffix added to avoid duplicate symbol
int gCollision_detection_on__car = 1;
// suffix added to avoid duplicate symbol
@ -51,9 +52,9 @@ void (*ControlCar[6])(tCar_spec*, br_scalar) = {
};
int gControl__car = 3; // suffix added to avoid duplicate symbol
int gFace_num__car = 1; // suffix added to avoid duplicate symbol
br_angle gOld_yaw__car; // suffix added to avoid duplicate symbol
br_angle gOld_zoom;
br_vector3 gCamera_pos_before_collide;
br_angle gOld_yaw__car = 0; // suffix added to avoid duplicate symbol
br_angle gOld_zoom = 0;
br_vector3 gCamera_pos_before_collide = { { 0 } };
int gMetal_crunch_sound_id__car[5] = {
// suffix added to avoid duplicate symbol
5000,
@ -69,24 +70,24 @@ int gMetal_scrape_sound_id__car[3] = {
5012,
};
int gCar_car_collisions = 1;
int gFreeze_mechanics;
tU32 gLast_cunning_stunt;
tU32 gWild_start;
tU32 gQuite_wild_start;
tU32 gQuite_wild_end;
tU32 gOn_me_wheels_start;
int gWoz_upside_down_at_all;
tS3_sound_tag gSkid_tag[2];
tCar_spec* gLast_car_to_skid[2];
int gEliminate_faces;
br_vector3 gZero_v__car; // suffix added to avoid duplicate symbol
tU32 gSwitch_time;
int gFreeze_mechanics = 0;
tU32 gLast_cunning_stunt = 0;
tU32 gWild_start = 0;
tU32 gQuite_wild_start = 0;
tU32 gQuite_wild_end = 0;
tU32 gOn_me_wheels_start = 0;
int gWoz_upside_down_at_all = 0;
tS3_sound_tag gSkid_tag[2] = { 0, 0 };
tCar_spec* gLast_car_to_skid[2] = { NULL, NULL};
int gEliminate_faces = 0;
br_vector3 gZero_v__car = { { 0 } }; // suffix added to avoid duplicate symbol
tU32 gSwitch_time = 0;
tSave_camera gSave_camera[2];
tU32 gLast_mechanics_time;
int gOpponent_viewing_mode;
int gNet_player_to_view_index;
int gDouble_pling_water;
int gStop_opponents_moving;
int gNet_player_to_view_index = -1;
int gDouble_pling_water = 0;
int gStop_opponents_moving = 0;
float gDefensive_powerup_factor[6] = { 1.0f, 0.825f, 0.65f, 0.475f, 0.3f, 0.01f };
float gOffensive_powerup_factor[6] = { 1.0f, 1.5f, 2.0f, 3.0f, 5.0f, 10.0f };
float gEngine_powerup_factor[6] = { 1.3f, 1.9f, 2.5f, 3.2f, 4.0f, 10.0f };
@ -4505,8 +4506,14 @@ void PutOpponentsInNeutral() {
// IDA: void __cdecl SetPanningFieldOfView()
void SetPanningFieldOfView() {
br_camera* camera_ptr;
static br_angle panning_angle = 0; // Added by DethRace
LOG_TRACE("()");
NOT_IMPLEMENTED();
camera_ptr = gCamera->type_data;
if (panning_angle == 0) {
panning_angle = BrDegreeToAngle(gCamera_angle) * 0.7f;
}
camera_ptr->field_of_view = panning_angle;
}
// IDA: void __usercall CheckDisablePlingMaterials(tCar_spec *pCar@<EAX>)
@ -4515,7 +4522,23 @@ void CheckDisablePlingMaterials(tCar_spec* pCar) {
br_scalar height;
int i;
LOG_TRACE("(%p)", pCar);
STUB_ONCE();
height = 0.f;
if (pCar->water_d == 10000.f) {
DisablePlingMaterials();
} else {
mat = &pCar->car_master_actor->t.t.mat;
for (i = 0; i < 3; i++) {
if (mat->m[i][1] > 0.f) {
height += pCar->bounds[0].max.v[i] * mat->m[i][1];
} else {
height += pCar->bounds[0].min.v[i] * mat->m[i][1];
}
}
if (mat->m[3][1] / WORLD_SCALE + height < pCar->water_d) {
DisablePlingMaterials();
}
}
}
// IDA: void __usercall PositionExternalCamera(tCar_spec *c@<EAX>, tU32 pTime@<EDX>)
@ -4537,23 +4560,25 @@ void PositionExternalCamera(tCar_spec* c, tU32 pTime) {
} else {
c = gCar_to_view;
}
if (c->car_master_actor->t.t.mat.m[3][0] <= 500.0) {
if (c->car_master_actor->t.t.translate.t.v[0] <= 500.0) {
if (gAction_replay_mode && gAction_replay_camera_mode) {
LOG_PANIC("%d, %d", gAction_replay_mode, gAction_replay_camera_mode);
if (gAction_replay_camera_mode == eAction_replay_action && (CheckDisablePlingMaterials(c), IncidentCam(c, pTime))) {
SetPanningFieldOfView();
EnablePlingMaterials();
old_camera_mode = gAction_replay_camera_mode;
} else {
if (gAction_replay_camera_mode == eAction_replay_action) {
CheckDisablePlingMaterials(c);
SetPanningFieldOfView();
if (gAction_replay_camera_mode != old_camera_mode) {
SetUpPanningCamera(c);
if (IncidentCam(c, pTime)) {
SetPanningFieldOfView();
EnablePlingMaterials();
old_camera_mode = gAction_replay_camera_mode;
return;
}
PanningExternalCamera(c, pTime);
EnablePlingMaterials();
}
CheckDisablePlingMaterials(c);
SetPanningFieldOfView();
if (gAction_replay_camera_mode != old_camera_mode) {
SetUpPanningCamera(c);
old_camera_mode = gAction_replay_camera_mode;
}
PanningExternalCamera(c, pTime);
EnablePlingMaterials();
} else {
NormalPositionExternalCamera(c, pTime);
}
@ -4567,16 +4592,25 @@ void CameraBugFix(tCar_spec* c, tU32 pTime) {
br_matrix34* m2;
br_vector3 tv;
LOG_TRACE("(%p, %d)", c, pTime);
STUB_ONCE();
}
if (gAction_replay_mode && gAction_replay_camera_mode != eAction_replay_standard && gPed_actor != NULL && !gProgram_state.cockpit_on) {
IncidentCam(c, pTime);
}
}
// IDA: int __usercall PossibleRemoveNonCarFromWorld@<EAX>(br_actor *pActor@<EAX>)
int PossibleRemoveNonCarFromWorld(br_actor* pActor) {
tU8 cx;
tU8 cz;
tTrack_spec* track_spec;
LOG_TRACE("(%p)", pActor);
NOT_IMPLEMENTED();
track_spec = &gProgram_state.track_spec;
XZToColumnXZ(&cx, &cz, pActor->t.t.translate.t.v[0], pActor->t.t.translate.t.v[2], track_spec);
if (track_spec->columns[cz][cx] == pActor->parent) {
BrActorRemove(pActor);
return 1;
}
return 0;
}
// IDA: void __usercall PutNonCarBackInWorld(br_actor *pActor@<EAX>)
@ -4585,7 +4619,10 @@ void PutNonCarBackInWorld(br_actor* pActor) {
tU8 cz;
tTrack_spec* track_spec;
LOG_TRACE("(%p)", pActor);
NOT_IMPLEMENTED();
track_spec = &gProgram_state.track_spec;
XZToColumnXZ(&cx, &cz, pActor->t.t.translate.t.v[0], pActor->t.t.translate.t.v[2], track_spec);
BrActorAdd(track_spec->columns[cz][cx], pActor);
}
// IDA: int __usercall IncidentCam@<EAX>(tCar_spec *c@<EAX>, tU32 pTime@<EDX>)
@ -4599,17 +4636,125 @@ int IncidentCam(tCar_spec* c, tU32 pTime) {
br_vector3 murderer_pos;
br_scalar ts;
tCar_spec* car2;
static tU32 next_incident_time;
static tU32 next_incident_time = 0;
static tIncident_type type = eNo_incident;
static float severity;
static tIncident_info info;
static int random;
static int count;
static int random = 1;
static int count = 0;
br_scalar temp;
br_vector3 old_cam_pos;
int removed;
LOG_TRACE("(%p, %d)", c, pTime);
NOT_IMPLEMENTED();
gPed_actor = NULL;
m2 = &gCamera->t.t.mat;
if (type == eNo_incident) {
MoveCamToIncident(c, &type, &severity, &info, &next_incident_time);
}
if (type == eNo_incident) {
return 0;
}
if (type == eIncident_ped) {
BrVector3Copy(&old_cam_pos, &gCamera->t.t.translate.t);
gPed_actor = info.ped_info.ped_actor;
removed = PossibleRemoveNonCarFromWorld(info.ped_info.murderer_actor);
BrMatrix34Mul(&mat, &gPed_actor->t.t.mat, &gPed_actor->parent->t.t.mat);
info.ped_info.murderer_actor = c->car_master_actor;
if (info.ped_info.murderer_actor != NULL) {
BrVector3Copy(&murderer_pos, &c->pos);
} else if (info.ped_info.murderer_actor->model != NULL) {
BrVector3Add(&murderer_pos, &info.ped_info.murderer_actor->model->bounds.max, &info.ped_info.murderer_actor->model->bounds.min);
BrVector3Scale(&murderer_pos, &murderer_pos, 0.5f);
BrMatrix34ApplyP(&murderer_pos, &murderer_pos, &info.ped_info.murderer_actor->t.t.mat);
} else {
BrVector3Copy(&murderer_pos, &info.ped_info.murderer_actor->t.t.translate.t);
}
BrVector3Normalise(&vertical, (br_vector3*)mat.m[1]);
BrVector3Scale(&vertical, &vertical, PedHeightFromActor(info.ped_info.ped_actor) / 2.f);
BrVector3Accumulate((br_vector3*)mat.m[3], &vertical);
if (next_incident_time > GetTotalTime() || !PipeSearchForwards()) {
BrVector3Sub(&tv, (br_vector3*)mat.m[3], &murderer_pos);
tv.v[1] = 0.f;
BrVector3Normalise(&tv, &tv);
BrVector3Set(&vertical, .0f, .4f, .0f);
BrVector3Cross(&perp, &tv, &vertical);
if (random) {
BrVector3Negate(&perp, &perp);
}
if (PipeSearchForwards()) {
BrVector3Accumulate(&perp, &tv);
}
BrVector3Add(&gCamera->t.t.translate.t, (br_vector3*)mat.m[3], &perp);
CollideCamera2(&murderer_pos, &gCamera->t.t.translate.t, NULL, 1);
}
PointCamera((br_vector3*)mat.m[3], m2);
BrVector3Sub(&tv, &gCamera->t.t.translate.t, &info.ped_info.murderer_actor->t.t.translate.t);
ts = BrVector3LengthSquared(&tv);
if (abs(GetTotalTime() - next_incident_time) > 2500) {
type = eNo_incident;
}
if ((PipeSearchForwards() ? (next_incident_time < GetTotalTime()) : (next_incident_time > GetTotalTime()))
&& (ts > 25.f || CheckForWall(&info.ped_info.murderer_actor->t.t.translate.t, &gCamera->t.t.translate.t))) {
type = eNo_incident;
}
if (removed) {
PutNonCarBackInWorld(info.ped_info.murderer_actor);
}
if (Vector3DistanceSquared((br_vector3*)mat.m[3], &gCamera->t.t.translate.t) < .15f * .15f) {
BrVector3Copy(&gCamera->t.t.translate.t, &old_cam_pos);
gPed_actor = NULL;
return 0;
}
} else if (type == eIncident_car) {
BrVector3Sub(&tv, &info.car_info.car->pos, &c->pos);
tv.v[1] = 0.f;
BrVector3Normalise(&tv, &tv);
BrVector3Scale(&tv, &tv, 2.f);
BrVector3Add(&gCamera->t.t.translate.t, &info.car_info.car->pos, &tv);
gCamera->t.t.translate.t.v[1] += 1.f;
CollideCamera2(&info.car_info.car->pos, &gCamera->t.t.translate.t, NULL, 1);
PointCamera(&info.car_info.car->pos, m2);
BrVector3Sub(&tv, &gCamera->t.t.translate.t, &c->pos);
ts = BrVector3LengthSquared(&tv);
if (abs(GetTotalTime() - next_incident_time) > 2500) {
type = eNo_incident;
}
if ((PipeSearchForwards() ? (next_incident_time < GetTotalTime()) : (next_incident_time > GetTotalTime()))
&& (ts > 25.f || CheckForWall(&c->pos, &gCamera->t.t.translate.t))) {
type = eNo_incident;
}
} else if (type == eIncident_wall) {
PointCamera(&c->pos, m2);
BrVector3Sub(&tv, &gCamera->t.t.translate.t, &c->pos);
ts = BrVector3LengthSquared(&tv);
if (abs(GetTotalTime() - next_incident_time) > 2500) {
type = eNo_incident;
}
if ((PipeSearchForwards() ? (next_incident_time < GetTotalTime()) : (next_incident_time > GetTotalTime()))
&& (ts > 25.f || CheckForWall(&c->pos, &gCamera->t.t.translate.t))) {
type = eNo_incident;
}
} else {
type = eNo_incident;
}
if (type == eNo_incident) {
if (count > 1) {
SetUpPanningCamera(c);
return 0;
} else {
count++;
if (IncidentCam(c, pTime)) {
count--;
return 1;
} else {
count--;
return 0;
}
}
} else {
return 1;
}
}
// IDA: int __usercall MoveCamToIncident@<EAX>(tCar_spec *c@<EAX>, tIncident_type *type@<EDX>, float *severity@<EBX>, tIncident_info *info@<ECX>, tU32 *next_incident_time)
@ -4628,7 +4773,67 @@ int MoveCamToIncident(tCar_spec* c, tIncident_type* type, float* severity, tInci
br_vector3 perp;
int test;
LOG_TRACE("(%p, %p, %p, %p, %p)", c, type, severity, info, next_incident_time);
NOT_IMPLEMENTED();
test = 0;
if (!GetNextIncident(-1, type, severity, info, next_incident_time)) {
*type = eNo_incident;
} else {
if (abs(*next_incident_time) > 2500) {
*type = eNo_incident;
} else {
t = *next_incident_time;
for (test = 0; GetNextIncident(abs(t), &type2, &severity2, &info2, &next_incident_time2) && test <= 10 && abs(next_incident_time2) <= 3500; test++) {
if ((*type != type2 && type2 < *type) || (*type == type2 && *severity <= severity2)) {
*info = info2;
*severity = severity2;
*type = type2;
*next_incident_time = next_incident_time2;
}
t = next_incident_time2;
}
if (abs(*next_incident_time) > 2500) {
*type = eNo_incident;
} else {
if (*type == eIncident_wall) {
if (*severity < 0.1f) {
*type = eNo_incident;
return 0;
}
ScanCarsPositions(c, &c->pos, 100000.f, -1, abs(*next_incident_time), &pos, &t);
if (t == 0) {
*type = eNo_incident;
} else {
BrVector3Sub(&tv, &pos, &c->pos);
if (BrVector3LengthSquared(&tv) > 102.91955471539592f) {
*type = eNo_incident;
} else {
BrVector3Sub(&tv, &pos, &info->wall_info.pos);
BrVector3Normalise(&tv, &tv);
BrVector3Scale(&tv, &tv, 2.f);
BrVector3Set(&vertical, 0.f, 1.f, 0.f);
BrVector3Cross(&perp, &vertical, &tv);
BrVector3Add(&left, &pos, &tv);
BrVector3Add(&left, &left, &perp);
left.v[1] += 2.f;
BrVector3Add(&right, &pos, &tv);
BrVector3Sub(&right, &right, &perp);
right.v[1] += 2.f;
CollideCamera2(&pos, &left, NULL, 1);
CollideCamera2(&pos, &right, NULL, 1);
if (Vector3DistanceSquared(&left, &pos) <= Vector3DistanceSquared(&right, &pos)) {
BrVector3Copy(&tv, &right);
} else {
BrVector3Copy(&tv, &left);
}
BrVector3Copy(&gCamera->t.t.translate.t, &tv);
}
}
}
*next_incident_time += GetTotalTime();
}
}
}
return 0;
}
// IDA: void __usercall PanningExternalCamera(tCar_spec *c@<EAX>, tU32 pTime@<EDX>)
@ -4637,9 +4842,22 @@ void PanningExternalCamera(tCar_spec* c, tU32 pTime) {
br_matrix34* m1;
br_vector3 tv;
br_scalar ts;
static int inside_camera_zone;
static int inside_camera_zone = 1;
LOG_TRACE("(%p, %d)", c, pTime);
NOT_IMPLEMENTED();
BrVector3Sub(&tv, &gCamera->t.t.translate.t, &c->pos);
ts = BrVector3LengthSquared(&tv);
if (ts > 102.91955471539592f || (gSwitch_time != 0 && (PipeSearchForwards() ? (gSwitch_time <= GetTotalTime()) : (gSwitch_time >= GetTotalTime())))) {
if ((inside_camera_zone || ts > 205.83910943079184f) && (ts > 25.f || CheckForWall(&c->pos, &gCamera->t.t.translate.t))) {
SetUpPanningCamera(c);
inside_camera_zone = 0;
}
} else {
inside_camera_zone = 1;
}
m1 = &c->car_master_actor->t.t.mat;
m2 = &gCamera->t.t.mat;
PointCameraAtCar(c, m1, m2);
}
// IDA: int __usercall CheckForWall@<EAX>(br_vector3 *start@<EAX>, br_vector3 *end@<EDX>)
@ -4649,7 +4867,10 @@ int CheckForWall(br_vector3* start, br_vector3* end) {
br_vector3 normal;
br_scalar d;
LOG_TRACE("(%p, %p)", start, end);
NOT_IMPLEMENTED();
BrVector3Sub(&dir, end, start);
FindFace(start, &dir, &normal, &d, &material);
return d <= 1.f;
}
// IDA: void __usercall SetUpPanningCamera(tCar_spec *c@<EAX>)
@ -4672,7 +4893,64 @@ void SetUpPanningCamera(tCar_spec* c) {
int left_score;
int right_score;
LOG_TRACE("(%p)", c);
NOT_IMPLEMENTED();
ScanCarsPositions(c, &c->pos, 411.6782f, -1, 5000, &car_centre, &t);
BrVector3Sub(&dir, &car_centre, &c->pos);
time_step = ((t > GetTotalTime()) ? t - GetTotalTime() : GetTotalTime() - t) * SRandomBetween(0.8f, 1.5f);
if (BrVector3LengthSquared(&dir) >= .01f && t != 0) {
ScanCarsPositions(c, &c->pos, 102.9196f, -1, time_step / 2, &pos, &t2);
if (t2 == 0) {
BrVector3Copy(&pos, &c->pos);
}
} else {
BrVector3Negate(&dir, (br_vector3*)&c->car_master_actor->t.t.mat.m[2]);
BrVector3Copy(&pos, &c->pos);
time_step = 0;
}
BrVector3SetFloat(&tv, 0.f, 1.f, 0.f);
BrVector3Cross(&perp, &tv, &dir);
ts = BrVector3Length(&perp);
if (ts >= .1f) {
BrVector3Scale(&perp, &perp, 2.f / ts * SRandomBetween(0.3333333f, 1.f));
BrVector3Set(&tv2, 0.f, 2 * SRandomBetween(0.3333333f, 1.f), 0.f);
BrVector3Add(&tv, &pos, &tv2);
BrVector3Add(&left, &tv, &perp);
BrVector3Sub(&right, &tv, &perp);
CollideCamera2(&pos, &left, NULL, 1);
CollideCamera2(&pos, &right, NULL, 1);
BrVector3Sub(&tv, &left, &pos);
BrVector3Sub(&tv2, &right, &pos);
if (BrVector3LengthSquared(&tv) + SRandomPosNeg(.01f) <= BrVector3LengthSquared(&tv2)) {
BrVector3Copy(&gCamera->t.t.translate.t, &right);
} else {
BrVector3Copy(&gCamera->t.t.translate.t, &left);
}
if (t != 0 && CheckForWall(&c->pos, &gCamera->t.t.translate.t)) {
ScanCarsPositions(c, &c->pos, 10000.f, -1, 1000, &tv, &time);
CollideCamera2(&tv, &gCamera->t.t.translate.t, NULL, 1);
}
if (t != 0 && CheckForWall(&car_centre, &gCamera->t.t.translate.t)) {
time_step = time_step / 16;
BrVector3Copy(&tv, &pos);
while (1) {
ScanCarsPositions(c, &tv, 10000.f, abs(t2 - GetTotalTime()), time_step, &tv2, &time);
t2 += (GetReplayDirection() ? 1 : -1) * time_step;
BrVector3Copy(&tv, &tv2);
if (CheckForWall(&tv, &gCamera->t.t.translate.t)) {
break;
}
if (t2 >= GetTotalTime() + 5000) {
break;
}
}
gSwitch_time = t2;
} else {
if (t == 0) {
t = 5000;
}
gSwitch_time = t;
}
}
}
// IDA: void __usercall SaveCameraPosition(int i@<EAX>)
@ -4729,7 +5007,7 @@ void NormalPositionExternalCamera(tCar_spec* c, tU32 pTime) {
swoop = gCountdown && c->pos.v[1] + 0.001f < gCamera_height;
manual_swing = gOld_yaw__car != gCamera_yaw || swoop;
manual_zoom = (double)gOld_zoom != gCamera_zoom;
old_camera_pos = *(br_vector3*)&m1->m[3][0];
BrVector3Copy(&old_camera_pos, &gCamera->t.t.translate.t);
if (!gProgram_state.cockpit_on) {
if (swoop) {
gCamera_yaw = 0;
@ -4737,10 +5015,7 @@ void NormalPositionExternalCamera(tCar_spec* c, tU32 pTime) {
}
if (fabs(c->speedo_speed) > 0.0006f && gCamera_mode > 0) {
gCamera_mode = -1;
gCamera_sign = m2->m[2][1] * c->direction.v[1]
+ m2->m[2][2] * c->direction.v[2]
+ m2->m[2][0] * c->direction.v[0]
> 0.0;
gCamera_sign = BrVector3Dot((br_vector3*)m2->m[2], &c->direction) > 0.0f;
}
if (c->frame_collision_flag && gCamera_mode != -2) {
gCamera_mode = 1;
@ -4748,34 +5023,32 @@ void NormalPositionExternalCamera(tCar_spec* c, tU32 pTime) {
if (gCar_flying || gCamera_reset || gCamera_mode == -2) {
gCamera_mode = 0;
}
d = sqrtf((float)gCamera_zoom) + 0.57971013f;
d = sqrtf(gCamera_zoom) + 0.57971013f;
if (!gCamera_mode || gCamera_mode == -1) {
vn = c->direction;
BrVector3Copy(&vn, &c->direction);
MoveWithWheels(c, &vn, manual_swing);
vn.v[1] = 0.0;
vn.v[1] = 0.0f;
BrVector3Normalise(&vn, &vn);
if (gCar_flying) {
gCamera_sign = 0;
}
SwingCamera(c, m2, m1, &vn, pTime);
BrVector3Scale(&a, &vn, d);
m1->m[3][0] = c->pos.v[0] - a.v[0];
m1->m[3][1] = c->pos.v[1] - a.v[1];
m1->m[3][2] = c->pos.v[2] - a.v[2];
gView_direction = vn;
BrVector3Sub(&gCamera->t.t.translate.t, &c->pos, &a);
BrVector3Copy(&gView_direction, &vn);
}
if (gCamera_mode == 1) {
if (manual_swing || manual_zoom) {
old_camera_pos = gCamera_pos_before_collide;
BrVector3Copy(&old_camera_pos, &gCamera_pos_before_collide);
}
BrVector3Sub(&a, &c->pos, &old_camera_pos);
a.v[1] = 0.0;
a.v[1] = 0.0f;
if (manual_swing) {
DrVector3RotateY(&a, (gCamera_sign == 0 ? 1 : -1) * (gCamera_yaw - gOld_yaw__car));
gCamera_yaw = gOld_yaw__car;
}
BrVector3Normalise(&vn, &a);
gView_direction = vn;
BrVector3Copy(&gView_direction, &vn);
BrVector3Scale(&vn, &vn, -d);
BrVector3Accumulate(&a, &vn);
dist = BrVector3Length(&a);
@ -4784,28 +5057,24 @@ void NormalPositionExternalCamera(tCar_spec* c, tU32 pTime) {
BrVector3Scale(&a, &a, (l - 1.f));
BrVector3Accumulate(&vn, &a);
}
m1->m[3][0] = c->pos.v[0] + vn.v[0];
m1->m[3][1] = c->pos.v[1] + vn.v[1];
m1->m[3][2] = c->pos.v[2] + vn.v[2];
BrVector3Add(&gCamera->t.t.translate.t, &c->pos, &vn);
}
height_inc = gCamera_zoom * gCamera_zoom + 0.3f;
time = pTime * 0.001f;
if (!gCamera_frozen || gAction_replay_mode) {
if (pTime < 5000) {
if (swoop) {
if (time > 0.2) {
time = 0.2;
}
gCamera_height -= time * 5.0;
if (gCamera_height < c->pos.v[1]) {
gCamera_height = c->pos.v[1];
}
} else {
gCamera_height = time * 5.0 * c->pos.v[1] + gCamera_height;
gCamera_height = gCamera_height / (time * 5.0 + 1.0);
if (pTime >= 5000) {
gCamera_height = c->pos.v[1];
} else if (swoop) {
if (time > 0.2f) {
time = 0.2f;
}
gCamera_height -= time * 5.0f;
if (gCamera_height < c->pos.v[1]) {
gCamera_height = c->pos.v[1];
}
} else {
gCamera_height = c->pos.v[1];
gCamera_height = time * 5.0f * c->pos.v[1] + gCamera_height;
gCamera_height = gCamera_height / (time * 5.0f + 1.0f);
}
}
l = c->direction.v[1] * d;
@ -4815,14 +5084,10 @@ void NormalPositionExternalCamera(tCar_spec* c, tU32 pTime) {
}
}
m1->m[3][1] = height_inc + gCamera_height;
gCamera_pos_before_collide = *(br_vector3*)&m1->m[3][0];
CollideCameraWithOtherCars(&c->pos, (br_vector3*)m1->m[3]);
if (manual_swing || manual_zoom) {
CollideCamera2(&c->pos, (br_vector3*)m1->m[3], &old_camera_pos, 1);
} else {
CollideCamera2(&c->pos, (br_vector3*)m1->m[3], &old_camera_pos, 0);
}
gCamera->t.t.translate.t.v[1] = height_inc + gCamera_height;
BrVector3Copy(&gCamera_pos_before_collide, &gCamera->t.t.translate.t);
CollideCameraWithOtherCars(&c->pos, &gCamera->t.t.translate.t);
CollideCamera2(&c->pos, &gCamera->t.t.translate.t, &old_camera_pos, manual_swing || manual_zoom);
if (gCamera_has_collided && swoop) {
gCamera_height = c->pos.v[1];
}
@ -5045,7 +5310,23 @@ void PointCamera(br_vector3* pos, br_matrix34* m2) {
br_angle theta;
br_camera* camera_ptr;
LOG_TRACE("(%p, %p)", pos, m2);
NOT_IMPLEMENTED();
camera_ptr = gCamera->type_data;
BrVector3Sub(&vn, pos, (br_vector3*)m2->m[3]);
vn.v[1] = 0.f;
BrVector3Normalise(&vn, &vn);
m2->m[0][0] = -vn.v[2];
m2->m[0][1] = 0.f;
m2->m[0][2] = vn.v[0];
m2->m[1][0] = 0.f;
m2->m[1][1] = 1.f;
m2->m[1][2] = 0.f;
m2->m[2][0] = -vn.v[0];
m2->m[2][1] = 0.f;
m2->m[2][2] = -vn.v[2];
dist = BrVector3LengthSquared(&vn);
theta = BR_ATAN2(m2->m[3][1] - pos->v[1], dist);
BrMatrix34PreRotateX(m2, camera_ptr->field_of_view / 5 - theta);
}
// IDA: int __usercall CollideCamera2@<EAX>(br_vector3 *car_pos@<EAX>, br_vector3 *cam_pos@<EDX>, br_vector3 *old_camera_pos@<EBX>, int manual_move@<ECX>)
@ -6963,14 +7244,31 @@ void AdjustNonCar(br_actor* pActor, br_matrix34* pMat) {
tU8 cz;
tTrack_spec* track_spec;
LOG_TRACE("(%p, %p)", pActor, pMat);
NOT_IMPLEMENTED();
track_spec = &gProgram_state.track_spec;
BrMatrix34Copy(&pActor->t.t.mat, pMat);
if (pActor->parent != gNon_track_actor) {
XZToColumnXZ(&cx, &cz, pActor->t.t.translate.t.v[0], pActor->t.t.translate.t.v[2], track_spec);
if (track_spec->columns[cz][cx] != pActor->parent && track_spec->columns[cz][cx] != NULL) {
BrActorRemove(pActor);
BrActorAdd(track_spec->columns[cz][cx], pActor);
}
}
}
// IDA: void __usercall PipeSingleNonCar(tCollision_info *c@<EAX>)
void PipeSingleNonCar(tCollision_info* c) {
LOG_TRACE("(%p)", c);
STUB_ONCE();
StartPipingSession(ePipe_chunk_non_car);
if (gDoing_physics) {
BrVector3InvScale(&c->car_master_actor->t.t.translate.t, &c->car_master_actor->t.t.translate.t, WORLD_SCALE);
}
AddNonCarToPipingSession(c->car_ID, c->car_master_actor);
if (gDoing_physics) {
BrVector3Scale(&c->car_master_actor->t.t.translate.t, &c->car_master_actor->t.t.translate.t, WORLD_SCALE);
}
EndPipingSession();
}
// IDA: int __usercall GetPrecalculatedFacesUnderCar@<EAX>(tCar_spec *pCar@<EAX>, tFace_ref **pFace_refs@<EDX>)

View File

@ -770,13 +770,16 @@ void NewScreenWobble(double pAmplitude_x, double pAmplitude_y, double pPeriod) {
// IDA: void __usercall SetScreenWobble(int pWobble_x@<EAX>, int pWobble_y@<EDX>)
void SetScreenWobble(int pWobble_x, int pWobble_y) {
LOG_TRACE("(%d, %d)", pWobble_x, pWobble_y);
NOT_IMPLEMENTED();
gScreen_wobble_y = pWobble_y;
gScreen_wobble_x = pWobble_x;
}
// IDA: void __cdecl ResetScreenWobble()
void ResetScreenWobble() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
SetScreenWobble(0, 0);
}
// IDA: void __usercall CalculateWobblitude(tU32 pThe_time@<EAX>)
@ -1784,7 +1787,7 @@ void RenderAFrame(int pDepth_mask_on) {
PipeFrameFinish();
}
gRender_screen->pixels = old_pixels;
if (!gPalette_fade_time || GetRaceTime() > (gPalette_fade_time + 500)) {
if (!gPalette_fade_time || GetRaceTime() > gPalette_fade_time + 500) {
PDScreenBufferSwap(0);
}
if (gAction_replay_mode) {
@ -2092,7 +2095,15 @@ void DRPixelmapRectangleMaskedCopy(br_pixelmap* pDest, br_int_16 pDest_x, br_int
// IDA: void __usercall DRMaskedStamp(br_int_16 pDest_x@<EAX>, br_int_16 pDest_y@<EDX>, br_pixelmap *pSource@<EBX>)
void DRMaskedStamp(br_int_16 pDest_x, br_int_16 pDest_y, br_pixelmap* pSource) {
LOG_TRACE("(%d, %d, %p)", pDest_x, pDest_y, pSource);
NOT_IMPLEMENTED();
DRPixelmapRectangleMaskedCopy(gBack_screen,
pDest_x,
pDest_y,
pSource,
0,
0,
pSource->width,
pSource->height);
}
// IDA: void __usercall DRPixelmapRectangleOnscreenCopy(br_pixelmap *pDest@<EAX>, br_int_16 pDest_x@<EDX>, br_int_16 pDest_y@<EBX>, br_pixelmap *pSource@<ECX>, br_int_16 pSource_x, br_int_16 pSource_y, br_int_16 pWidth, br_int_16 pHeight)

View File

@ -2295,7 +2295,7 @@ void RevivePedestrian(tPedestrian_data* pPedestrian, int pAnimate) {
pPedestrian->fate = NULL;
gInitial_instruction = NULL;
PedestrianNextInstruction(pPedestrian, 0.f, 1, 0);
pPedestrian->from_pos = pPedestrian->actor->t.t.translate.t;
BrVector3Copy(&pPedestrian->from_pos, &pPedestrian->actor->t.t.translate.t);
MungePedModel(pPedestrian);
pPedestrian->pos.v[V_Y] += pPedestrian->sequences[pPedestrian->current_sequence].frames[0].offset.v[V_Y];
}

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,30 @@
#include "replay.h"
#include "harness/trace.h"
#include <stdlib.h>
#include <brender/brender.h>
#include "car.h"
#include "controls.h"
#include "displays.h"
#include "globvars.h"
#include "globvrpb.h"
#include "grafdata.h"
#include "graphics.h"
#include "input.h"
#include "loading.h"
#include "main.h"
#include "netgame.h"
#include "oil.h"
#include "opponent.h"
#include "piping.h"
#include "s3/s3.h"
#include "sys.h"
#include "utility.h"
#include "world.h"
#include "harness/config.h"
#include "harness/os.h"
#include "harness/trace.h"
#include <stdio.h>
#include <stdlib.h>
char* gReplay_pixie_names[10] = {
"REPLAY.PIX",
@ -15,14 +36,14 @@ char* gReplay_pixie_names[10] = {
"PLAY.PIX",
"FFWD.PIX",
"FWDEND.PIX",
"CAMERA.PIX"
"CAMERA.PIX",
};
int gSingle_frame_mode;
tU32 gCam_change_time;
int gSave_file;
int gProgress_line_left[2];
int gProgress_line_right[2];
int gProgress_line_top[2];
int gSingle_frame_mode = 0;
tU32 gCam_change_time = 0;
int gSave_file = 0;
int gProgress_line_left[2] = { 70, 141 };
int gProgress_line_right[2] = { 279, 558 };
int gProgress_line_top[2] = { 178, 429 };
br_pixelmap* gReplay_pixies[10];
int gKey_down;
int gNo_cursor;
@ -43,7 +64,7 @@ tAction_replay_camera_type gAction_replay_camera_mode;
int ReplayIsPaused() {
LOG_TRACE8("()");
return gReplay_rate == 0.0;
return gReplay_rate == 0.f;
}
// IDA: float __cdecl GetReplayRate()
@ -56,13 +77,16 @@ float GetReplayRate() {
// IDA: int __cdecl GetReplayDirection()
int GetReplayDirection() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
return gPlay_direction;
}
// IDA: void __cdecl StopSaving()
void StopSaving() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
gSave_file = 0;
gPaused = 1;
}
// IDA: void __usercall ActualActionReplayHeadups(int pSpecial_zappy_bastard@<EAX>)
@ -74,7 +98,104 @@ void ActualActionReplayHeadups(int pSpecial_zappy_bastard) {
tU16 to_play_col1;
tU16 to_play_col2;
LOG_TRACE("(%d)", pSpecial_zappy_bastard);
NOT_IMPLEMENTED();
the_time = PDGetTotalTime();
if (gSave_file || PDKeyDown(KEY_SHIFT_ANY)) {
return;
}
if ((the_time / 400) % 2) {
DRMaskedStamp(gCurrent_graf_data->action_replay_R_x,
gCurrent_graf_data->action_replay_R_y,
gReplay_pixies[0]);
}
DRMaskedStamp(gCurrent_graf_data->action_replay_controls_x,
gCurrent_graf_data->action_replay_controls_y,
gReplay_pixies[1]);
if (pSpecial_zappy_bastard < 0) {
DRMaskedStamp(gCurrent_graf_data->action_replay_rew_start_x,
gCurrent_graf_data->action_replay_hilite_y,
gReplay_pixies[2]);
} else if (pSpecial_zappy_bastard == 0) {
if (gReplay_rate < -1.f) {
DRMaskedStamp(gCurrent_graf_data->action_replay_rew_x,
gCurrent_graf_data->action_replay_hilite_y,
gReplay_pixies[3]);
} else if (gReplay_rate > 1.f) {
DRMaskedStamp(gCurrent_graf_data->action_replay_ffwd_x,
gCurrent_graf_data->action_replay_hilite_y,
gReplay_pixies[7]);
} else if (gReplay_rate == 1.f) {
DRMaskedStamp(gCurrent_graf_data->action_replay_play_x,
gCurrent_graf_data->action_replay_hilite_y,
gReplay_pixies[6]);
} else if (gReplay_rate == -1.f) {
DRMaskedStamp(gCurrent_graf_data->action_replay_rev_play_x,
gCurrent_graf_data->action_replay_hilite_y,
gReplay_pixies[4]);
} else {
DRMaskedStamp(gCurrent_graf_data->action_replay_pause_x,
gCurrent_graf_data->action_replay_hilite_y,
gReplay_pixies[5]);
}
} else {
DRMaskedStamp(gCurrent_graf_data->action_replay_fwd_end_x,
gCurrent_graf_data->action_replay_hilite_y,
gReplay_pixies[8]);
}
x = gProgress_line_left[gGraf_data_index] + (float)(gProgress_line_right[gGraf_data_index] - gProgress_line_left[gGraf_data_index]) * (gLast_replay_frame_time - gAction_replay_start_time) / (gAction_replay_end_time - gAction_replay_start_time);
if (x > gProgress_line_left[gGraf_data_index]) {
BrPixelmapLine(gBack_screen,
gProgress_line_left[gGraf_data_index], gProgress_line_top[gGraf_data_index],
x - 1, gProgress_line_top[gGraf_data_index],
2);
BrPixelmapLine(gBack_screen,
gProgress_line_left[gGraf_data_index], gProgress_line_top[gGraf_data_index] + 1,
x - 1, gProgress_line_top[gGraf_data_index] + 1,
4);
BrPixelmapLine(gBack_screen,
gProgress_line_left[gGraf_data_index], gProgress_line_top[gGraf_data_index] + 2,
x - 1, gProgress_line_top[gGraf_data_index] + 2,
2);
}
if (x < gProgress_line_right[gGraf_data_index]) {
BrPixelmapLine(gBack_screen,
x, gProgress_line_top[gGraf_data_index],
gProgress_line_right[gGraf_data_index] - 1, gProgress_line_top[gGraf_data_index],
81);
BrPixelmapLine(gBack_screen,
x, gProgress_line_top[gGraf_data_index] + 1,
gProgress_line_right[gGraf_data_index] - 1, gProgress_line_top[gGraf_data_index] + 1,
82);
BrPixelmapLine(gBack_screen,
x, gProgress_line_top[gGraf_data_index] + 2,
gProgress_line_right[gGraf_data_index] - 1, gProgress_line_top[gGraf_data_index] + 2,
81);
}
BrPixelmapLine(gBack_screen,
gProgress_line_left[gGraf_data_index] - 1, gProgress_line_top[gGraf_data_index],
gProgress_line_left[gGraf_data_index] - 1, gProgress_line_top[gGraf_data_index] + 2,
2);
BrPixelmapLine(gBack_screen,
gProgress_line_right[gGraf_data_index], gProgress_line_top[gGraf_data_index],
gProgress_line_right[gGraf_data_index], gProgress_line_top[gGraf_data_index] + 2,
81);
if (gCam_change_button_down) {
DRMaskedStamp(gCurrent_graf_data->action_replay_camera_x,
gCurrent_graf_data->action_replay_hilite_y,
gReplay_pixies[9]);
}
if (the_time - gCam_change_time < 2000) {
TransDRPixelmapText(gBack_screen,
gCurrent_graf_data->action_replay_cam_text_x - DRTextWidth(&gFonts[1], GetMiscString(gAction_replay_camera_mode ? 39 : 38)),
gCurrent_graf_data->action_replay_cam_text_y,
&gFonts[1],
GetMiscString(gAction_replay_camera_mode ? 39 : 38),
2 * gCurrent_graf_data->action_replay_cam_text_x);
}
TurnOnPaletteConversion();
DoMouseCursor();
TurnOffPaletteConversion();
}
// IDA: void __cdecl DoActionReplayPostSwap()
@ -88,13 +209,22 @@ void DoActionReplayPostSwap() {
void DoZappyActionReplayHeadups(int pSpecial_zappy_bastard) {
tU32 the_time;
LOG_TRACE("(%d)", pSpecial_zappy_bastard);
NOT_IMPLEMENTED();
the_time = PDGetTotalTime();
// Draw screen every 50ms (when we are going fast)
if (abs(pSpecial_zappy_bastard) > 10000 && the_time - gLast_replay_zappy_screen > 50) {
ActualActionReplayHeadups(pSpecial_zappy_bastard);
gLast_replay_zappy_screen = the_time;
PDScreenBufferSwap(0);
RemoveTransientBitmaps(1);
}
}
// IDA: void __cdecl DoActionReplayHeadups()
void DoActionReplayHeadups() {
LOG_TRACE("()");
STUB_ONCE();
ActualActionReplayHeadups(0);
}
// IDA: void __usercall MoveReplayBuffer(tS32 pMove_amount@<EAX>)
@ -106,27 +236,123 @@ void MoveReplayBuffer(tS32 pMove_amount) {
int a;
tU32 old_time;
LOG_TRACE("(%d)", pMove_amount);
NOT_IMPLEMENTED();
old_play_ptr = NULL;
gLast_replay_zappy_screen = 0;
old_play_ptr2 = GetPipePlayPtr();
play_ptr = old_play_ptr2;
old_time = GetTotalTime();
for (i = 0; i < abs(pMove_amount) && play_ptr != old_play_ptr; i++) {
if (KeyIsDown(KEYMAP_ESCAPE)) {
break;
}
if (SomeReplayLeft()) {
PipingFrameReset();
}
old_play_ptr = play_ptr;
if (pMove_amount >= 1) {
while (!ApplyPipedSession(&play_ptr)) {
DoZappyActionReplayHeadups(pMove_amount);
}
SetPipePlayPtr(play_ptr);
} else if (pMove_amount <= -1) {
while (!UndoPipedSession(&play_ptr)) {
DoZappyActionReplayHeadups(pMove_amount);
}
SetPipePlayPtr(play_ptr);
}
ProcessOilSpills(gFrame_period);
}
if (gReplay_rate < 0.f) {
CheckSound((tPipe_chunk*)old_play_ptr2, old_time, GetTotalTime());
}
if (old_play_ptr == play_ptr) {
gReplay_rate = 0.f;
gPaused = 1;
StopSaving();
}
if (KeyIsDown(KEYMAP_ESCAPE)) {
WaitForNoKeys();
}
}
// IDA: void __cdecl MoveToEndOfReplay()
void MoveToEndOfReplay() {
float old_replay_rate;
LOG_TRACE("()");
NOT_IMPLEMENTED();
DisablePipedSounds();
old_replay_rate = gReplay_rate;
gReplay_rate = 100.f;
MoveReplayBuffer(INT32_MAX);
gReplay_rate = old_replay_rate;
EnablePipedSounds();
}
// IDA: void __cdecl MoveToStartOfReplay()
void MoveToStartOfReplay() {
float old_replay_rate;
LOG_TRACE("()");
NOT_IMPLEMENTED();
DisablePipedSounds();
old_replay_rate = gReplay_rate;
gReplay_rate = -100.f;
MoveReplayBuffer(-INT32_MAX);
gReplay_rate = old_replay_rate;
EnablePipedSounds();
}
// IDA: void __cdecl ToggleReplay()
void ToggleReplay() {
LOG_TRACE("()");
STUB_ONCE();
if (!harness_game_config.enable_replay) {
NewTextHeadupSlot(4, 0, 1000, -4, "Action replay disabled (start dethrace with --enable-replay)");
return;
}
if (!IsActionReplayAvailable()) {
NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(37));
return;
}
if (!gAction_replay_mode) {
if (gMap_mode) {
ToggleMap();
}
if (gNet_mode == eNet_mode_host) {
SendGameplayToAllPlayers(eNet_gameplay_host_paused, 0, 0, 0, 0);
}
gReplay_rate = 1.f;
gPaused = 1;
gStopped_time = PDGetTotalTime();
gPlay_direction = 1;
gAction_replay_end_time = GetTotalTime();
gLast_replay_frame_time = gAction_replay_end_time;
gAction_replay_start_time = GetARStartTime();
ResetPipePlayToEnd();
LoadInterfaceStuff(1);
StartMouseCursor();
gKey_down = KEY_KP_ENTER;
gPending_replay_rate = 0;
gCam_change_time = PDGetTotalTime();
if (!gRace_finished) {
SaveCameraPosition(0);
}
} else {
MoveToEndOfReplay();
EndMouseCursor();
S3SetEffects(NULL, NULL);
UnlockInterfaceStuff();
AddLostTime(PDGetTotalTime() - gStopped_time);
if (!gRace_finished) {
RestoreCameraPosition(0);
}
if (gNet_mode == eNet_mode_host) {
SendGameplayToAllPlayers(eNet_gameplay_host_unpaused, 0, 0, 0, 0);
}
}
gAction_replay_mode = !gAction_replay_mode;
ForceRebuildActiveCarList();
}
// IDA: void __usercall ReverseSound(tS3_effect_tag pEffect_index@<EAX>, tS3_sound_tag pSound_tag@<EDX>)
@ -141,7 +367,19 @@ int FindUniqueFile() {
FILE* f;
tPath_name the_path;
LOG_TRACE("()");
NOT_IMPLEMENTED();
for (index = 0; index < 1000; index++) {
PathCat(the_path, gApplication_path, "BMPFILES");
PathCat(the_path, the_path, "");
sprintf(&the_path[strlen(the_path)], "%03d", index);
strcat(the_path, "_0000.BMP");
f = DRfopen(the_path, "rt");
if (f == NULL) {
return index;
}
fclose(f);
}
return 0;
}
// IDA: void __usercall PollActionReplayControls(tU32 pFrame_period@<EAX>)
@ -152,17 +390,193 @@ void PollActionReplayControls(tU32 pFrame_period) {
int y_coord;
int i;
tU32 real_time;
static tU32 last_real_time;
static int psuedo_mouse_keys[8];
static tRectangle mouse_areas[2][8];
static tU32 last_real_time = 0;
static int psuedo_mouse_keys[8] = {
KEY_KP_7,
KEY_KP_4,
KEY_COMMA,
KEY_SPACE,
KEY_PERIOD,
KEY_KP_6,
KEY_KP_9,
KEY_KP_MULTIPLY,
};
static tRectangle mouse_areas[2][8] = {
{
{ 63, 182, 92, 198, },
{ 93, 182, 118, 198, },
{ 119, 182, 144, 198, },
{ 145, 182, 166, 198, },
{ 167, 182, 192, 198, },
{ 193, 182, 218, 198, },
{ 219, 182, 244, 198, },
{ 245, 182, 272, 198, },
},
{
{ 126, 436, 184, 475, },
{ 186, 436, 236, 475, },
{ 238, 436, 288, 475, },
{ 290, 436, 332, 475, },
{ 334, 436, 384, 475, },
{ 386, 436, 436, 475, },
{ 438, 436, 488, 475, },
{ 490, 436, 544, 475, },
},
};
LOG_TRACE("(%d)", pFrame_period);
STUB_ONCE();
real_time = PDGetTotalTime();
old_replay_rate = gReplay_rate;
old_key_down = gKey_down == KEY_CAPSLOCK ? -1 : gKey_down;
gKey_down = PDAnyKeyDown();
if (KeyIsDown(KEYMAP_REPLAYMODE) && old_key_down == -1) {
ToggleReplay();
return;
}
if (gKey_down == -1) {
if ((old_key_down == -1 || old_key_down == KEY_KP_4 || old_key_down == KEY_KP_6 || old_key_down == KEY_KP_MULTIPLY) && EitherMouseButtonDown()) {
GetMousePosition(&x_coord, &y_coord);
for (i = 0; i < COUNT_OF(mouse_areas[0]); i++) {
if (mouse_areas[gGraf_data_index][i].left <= x_coord && mouse_areas[gGraf_data_index][i].top <= y_coord &&
mouse_areas[gGraf_data_index][i].right >= x_coord && mouse_areas[gGraf_data_index][i].bottom >= y_coord) {
gKey_down = psuedo_mouse_keys[i];
break;
}
}
}
} else {
gMouse_in_use = 0;
}
if (gKey_down == KEY_KP_DIVIDE && old_key_down != KEY_KP_DIVIDE) {
if (gSave_file) {
StopSaving();
} else {
gSave_bunch_ID = FindUniqueFile();
gSave_frame_number = 0;
gSave_file = 1;
gPlay_direction = 1;
gPaused = 0;
}
}
if (gKey_down == KEY_KP_MULTIPLY) {
gCam_change_button_down = 1;
if (old_key_down != KEY_KP_MULTIPLY) {
gCam_change_time = PDGetTotalTime();
if (gAction_replay_camera_mode == eAction_replay_action) {
gAction_replay_camera_mode = eAction_replay_standard;
} else {
gAction_replay_camera_mode++;
}
}
} else {
gCam_change_button_down = 0;
}
if ((gKey_down == KEY_KP_5 || gKey_down == KEY_SPACE) && old_key_down == -1) {
gPaused = !gPaused;
} else if ((gKey_down == KEY_KP_0 || gKey_down == KEY_BACKSPACE) && old_key_down == -1) {
gPlay_direction = -gPlay_direction;
if (gPaused) {
gPaused = 0;
}
}
if (gKey_down == KEY_KP_1 && old_key_down == -1) {
gReplay_rate = -1.f;
gPlay_direction = -1;
gSingle_frame_mode = 1;
} else if (gKey_down == KEY_KP_3 && old_key_down == -1) {
gReplay_rate = 1.f;
gPlay_direction = 1;
gSingle_frame_mode = 1;
} else if (gKey_down == KEY_KP_4 || gKey_down == KEY_PAGEUP) {
if (gReplay_rate > -1.2f) {
gReplay_rate = -1.2f;
}
if (last_real_time != 0) {
gReplay_rate -= 0.002f * (real_time - last_real_time);
}
if (gReplay_rate < -8.f) {
gReplay_rate = -8.f;
}
} else if (gKey_down == KEY_KP_6 || gKey_down == KEY_PAGEDOWN) {
if (gReplay_rate < 1.2f) {
gReplay_rate = 1.2f;
}
if (last_real_time != 0) {
gReplay_rate += 0.002f * (real_time - last_real_time);
}
if (gReplay_rate > 8.f) {
gReplay_rate = 8.f;
}
} else if (gKey_down == KEY_COMMA) {
gReplay_rate = -1.f;
gPlay_direction = -1;
gPaused = 0;
} else if (gKey_down == KEY_PERIOD) {
gReplay_rate = 1.f;
gPlay_direction = 1;
gPaused = 0;
} else if (gPaused) {
gReplay_rate = 0.f;
} else {
gReplay_rate = (float)gPlay_direction;
}
if ((gKey_down == KEY_KP_7 || gKey_down == KEY_HOME) && old_key_down == -1) {
MoveToStartOfReplay();
gReplay_rate = 1.f;
MungeCarGraphics(gFrame_period);
GrooveThoseDelics();
gReplay_rate = 0.f;
gPlay_direction = 1;
gPaused = 1;
} else if ((gKey_down == KEY_KP_9 || gKey_down == KEY_END) && old_key_down == -1) {
MoveToEndOfReplay();
gReplay_rate = -1.f;
MungeCarGraphics(gFrame_period);
GrooveThoseDelics();
gReplay_rate = 0.f;
gPlay_direction = -1;
gPaused = 1;
}
if (gPending_replay_rate != 0.f) {
gReplay_rate = gPending_replay_rate;
}
if (old_replay_rate * gReplay_rate >= 0.f) {
gPending_replay_rate = 0.f;
} else {
gPending_replay_rate = gReplay_rate;
gReplay_rate = 0.f;
}
if (old_replay_rate != 0.f) {
gFrame_period = gFrame_period * gReplay_rate / old_replay_rate;
}
last_real_time = fabsf(gReplay_rate) >= 1.2f ? real_time : 0;
if (old_replay_rate <= 0.f && gReplay_rate > 0.f) {
S3SetEffects(NULL, NULL);
} else if (old_replay_rate >= 0.f && gReplay_rate < 0.f) {
S3SetEffects(ReverseSound, ReverseSound);
}
}
// IDA: void __cdecl CheckReplayTurnOn()
void CheckReplayTurnOn() {
LOG_TRACE("()");
STUB_ONCE();
if (!gAction_replay_mode) {
if (!KeyIsDown(KEYMAP_REPLAYMODE) || gEntering_message) {
gKey_down = -1;
} else if (gKey_down == -1) {
ToggleReplay();
}
}
}
// IDA: void __cdecl InitializeActionReplay()
@ -170,7 +584,7 @@ void InitializeActionReplay() {
int i;
LOG_TRACE("()");
for (int i = 0; i < 10; i++) {
for (i = 0; i < COUNT_OF(gReplay_pixie_names); i++) {
gReplay_pixies[i] = LoadPixelmap(gReplay_pixie_names[i]);
}
gAction_replay_camera_mode = eAction_replay_action;
@ -179,7 +593,10 @@ void InitializeActionReplay() {
// IDA: void __usercall DoActionReplay(tU32 pFrame_period@<EAX>)
void DoActionReplay(tU32 pFrame_period) {
LOG_TRACE("(%d)", pFrame_period);
NOT_IMPLEMENTED();
if (gReplay_rate != 0.f) {
MoveReplayBuffer((tS32)gReplay_rate);
}
}
// IDA: void __cdecl SynchronizeActionReplay()
@ -188,5 +605,28 @@ void SynchronizeActionReplay() {
tPath_name the_path;
static tU32 gLast_synch_time;
LOG_TRACE("()");
NOT_IMPLEMENTED();
while (gReplay_rate != 0.f) {
if (PDGetTotalTime() - gLast_synch_time >= gFrame_period / fabsf(gReplay_rate)) {
break;
}
ServiceGameInRace();
}
gLast_synch_time = PDGetTotalTime();
if (gSingle_frame_mode) {
gReplay_rate = 0.f;
gSingle_frame_mode = 0;
}
if (gSave_file) {
PathCat(the_path, gApplication_path, "BMPFILES");
strcat(the_path, gDir_separator);
sprintf(&the_path[strlen(the_path)], "%03d_%04d.BMP", gSave_bunch_ID, gSave_frame_number);
f = DRfopen(the_path, "wb");
if (f != NULL) {
PrintScreenFile(f);
fclose(f);
}
gSave_frame_number++;
}
}

View File

@ -637,7 +637,8 @@ void SetSoundVolumes() {
// IDA: tS3_outlet_ptr __usercall GetOutletFromIndex@<EAX>(int pIndex@<EAX>)
tS3_outlet_ptr GetOutletFromIndex(int pIndex) {
LOG_TRACE("(%d)", pIndex);
NOT_IMPLEMENTED();
return gIndexed_outlets[pIndex];
}
// IDA: int __usercall GetIndexFromOutlet@<EAX>(tS3_outlet_ptr pOutlet@<EAX>)

View File

@ -312,7 +312,28 @@ void ReplaySparks(br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_ac
br_vector3 tv;
br_vector3 new_pos;
LOG_TRACE("(%p, %p, %p, %d)", pRender_screen, pDepth_buffer, pCamera, pTime);
NOT_IMPLEMENTED();
for (i = 0; i < COUNT_OF(gSparks); i++) {
if (gSpark_flags & (1 << i)) {
if (gSparks[i].car == NULL) {
BrVector3Copy(&pos, &gSparks[i].pos);
} else {
BrMatrix34ApplyP(&tv, &o, &gSparks[i].car->car_master_actor->t.t.mat);
BrVector3Copy(&o, &tv);
BrMatrix34ApplyP(&pos, &gSparks[i].pos, &gSparks[i].car->car_master_actor->t.t.mat);
}
BrVector3Add(&o, &pos, &gSparks[i].length);
BrVector3Sub(&tv, &pos, (br_vector3*)gCamera_to_world.m[3]);
BrMatrix34TApplyV(&new_pos, &tv, &gCamera_to_world);
BrVector3Sub(&tv, &o, (br_vector3*)gCamera_to_world.m[3]);
BrMatrix34TApplyV(&p, &tv, &gCamera_to_world);
if (gSparks[i].colour) {
DrawLine3D(&p, &new_pos, pRender_screen, pDepth_buffer, gFog_shade_table);
} else {
DrawLine3D(&p, &new_pos, pRender_screen, pDepth_buffer, gAcid_shade_table);
}
}
}
}
// IDA: void __usercall RenderSparks(br_pixelmap *pRender_screen@<EAX>, br_pixelmap *pDepth_buffer@<EDX>, br_actor *pCamera@<EBX>, br_matrix34 *pCamera_to_world@<ECX>, tU32 pTime)
@ -737,7 +758,15 @@ void ReplayShrapnel(tU32 pTime) {
int i;
br_matrix34* mat;
LOG_TRACE("(%d)", pTime);
NOT_IMPLEMENTED();
for (i = 0; i < COUNT_OF(gShrapnel); i++) {
mat = &gShrapnel[i].actor->t.t.mat;
if (gShrapnel_flags & (1 << i)) {
gShrapnel[i].age += GetReplayRate() * pTime;
DrMatrix34Rotate(mat, gShrapnel[i].age * BrDegreeToAngle(1), &gShrapnel[i].axis);
BrMatrix34PreShearX(mat, gShrapnel[i].shear1, gShrapnel[i].shear2);
}
}
}
// IDA: void __usercall MungeShrapnel(tU32 pTime@<EAX>)
@ -1090,7 +1119,19 @@ void ReplaySmoke(br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_act
br_scalar aspect;
int i;
LOG_TRACE("(%p, %p, %p)", pRender_screen, pDepth_buffer, pCamera);
NOT_IMPLEMENTED();
for (i = 0; i < COUNT_OF(gSmoke_column); i++) {
if (gSmoke_flags & (1 << i)) {
aspect = 1.f + (gSmoke[i].radius - .05f) / .25f * .5f;
if (gSmoke[i].type & 0x10) {
SmokeCircle3D(&gSmoke[i].pos, gSmoke[i].radius / aspect, gSmoke[i].strength, 1.f,
pRender_screen, pDepth_buffer, gShade_list[gSmoke[i].type & 0xf], pCamera);
} else {
SmokeCircle3D(&gSmoke[i].pos, gSmoke[i].radius, gSmoke[i].strength, aspect,
pRender_screen, pDepth_buffer, gShade_list[gSmoke[i].type & 0xf], pCamera);
}
}
}
}
// IDA: void __usercall GenerateContinuousSmoke(tCar_spec *pCar@<EAX>, int wheel@<EDX>, tU32 pTime@<EBX>)
@ -1301,19 +1342,25 @@ void CreatePuffOfSmoke(br_vector3* pos, br_vector3* v, br_scalar strength, br_sc
// IDA: void __cdecl ResetSmoke()
void ResetSmoke() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
gSmoke_flags = 0;;
}
// IDA: void __usercall AdjustSmoke(int pIndex@<EAX>, tU8 pType@<EDX>, br_vector3 *pPos@<EBX>, br_scalar pRadius, br_scalar pStrength)
void AdjustSmoke(int pIndex, tU8 pType, br_vector3* pPos, br_scalar pRadius, br_scalar pStrength) {
LOG_TRACE("(%d, %d, %p, %f, %f)", pIndex, pType, pPos, pRadius, pStrength);
NOT_IMPLEMENTED();
gSmoke[pIndex].type = pType;
gSmoke[pIndex].radius = pRadius;
gSmoke[pIndex].strength = pStrength;
BrVector3Copy(&gSmoke[pIndex].pos, pPos);
gSmoke_flags |= 1 << pIndex;
}
// IDA: void __cdecl ActorError()
void ActorError() {
LOG_TRACE("()");
NOT_IMPLEMENTED();
}
// IDA: void __usercall AdjustSmokeColumn(int pIndex@<EAX>, tCar_spec *pCar@<EDX>, int pVertex@<EBX>, int pColour@<ECX>)
@ -1321,7 +1368,27 @@ void AdjustSmokeColumn(int pIndex, tCar_spec* pCar, int pVertex, int pColour) {
int i;
br_actor* actor;
LOG_TRACE("(%d, %p, %d, %d)", pIndex, pCar, pVertex, pColour);
NOT_IMPLEMENTED();
gColumn_flags ^= 1 << pIndex;
gSmoke_column[pIndex].car = pCar;
gSmoke_column[pIndex].vertex_index = pVertex;
gSmoke_column[pIndex].colour = pColour;
for (i = 0; i < COUNT_OF(gSmoke_column->frame_count); i++) {
gSmoke_column[pIndex].frame_count[i] = 100;
}
if (pColour == 0) {
if ((gColumn_flags & (1 << pIndex)) != 0) {
if (gSmoke_column[pIndex].flame_actor->depth != 0) {
ActorError();
}
BrActorAdd(gNon_track_actor, gSmoke_column[pIndex].flame_actor);
} else {
if (gSmoke_column[pIndex].flame_actor->depth == 0) {
ActorError();
}
BrActorRemove(gSmoke_column[pIndex].flame_actor);
}
}
}
// IDA: void __usercall CreateSmokeColumn(tCar_spec *pCar@<EAX>, int pColour@<EDX>, int pVertex_index@<EBX>, tU32 pLifetime@<ECX>)
@ -1431,14 +1498,38 @@ void AdjustFlame(int pIndex, int pFrame_count, br_scalar pScale_x, br_scalar pSc
tSmoke_column* col;
br_actor* actor;
LOG_TRACE("(%d, %d, %f, %f, %f, %f)", pIndex, pFrame_count, pScale_x, pScale_y, pOffset_x, pOffset_z);
NOT_IMPLEMENTED();
i = pIndex >> 4;
j = pIndex & 0xf;
col = &gSmoke_column[i];
col->frame_count[j] = pFrame_count;
col->scale_x[j] = pScale_x;
col->scale_y[j] = pScale_y;
col->offset_x[j] = pOffset_x;
col->offset_z[j] = pOffset_z;
}
// IDA: void __usercall ReplayFlame(tSmoke_column *col@<EAX>, br_actor *actor@<EDX>)
void ReplayFlame(tSmoke_column* col, br_actor* actor) {
int i;
LOG_TRACE("(%p, %p)", col, actor);
NOT_IMPLEMENTED();
for (i = 0; i < COUNT_OF(col->frame_count); i++, actor = actor->next) {
col->frame_count[i] += GetReplayRate();
if (col->frame_count[i] < 0 || col->frame_count[i] >= COUNT_OF(gFlame_map)) {
actor->type = BR_ACTOR_NONE;
} else {
actor->type = BR_ACTOR_MODEL;
actor->material->colour_map = gFlame_map[col->frame_count[i]];
BrMaterialUpdate(actor->material, BR_MATU_ALL);
BrMatrix34Scale(&actor->t.t.mat,
col->scale_x[i] * gFlame_map[col->frame_count[i]]->width,
col->scale_y[i] * gFlame_map[col->frame_count[i]]->height,
1.f);
actor->t.t.translate.t.v[0] = col->offset_x[i];
actor->t.t.translate.t.v[2] = col->offset_z[i];
}
}
}
// IDA: void __usercall FlameAnimate(int c@<EAX>, br_vector3 *pPos@<EDX>, tU32 pTime@<EBX>)
@ -1540,7 +1631,15 @@ void ReplaySmokeColumn(tU32 pTime) {
int i;
br_vector3 dummy;
LOG_TRACE("(%d)", pTime);
NOT_IMPLEMENTED();
for (i = 0; i < MAX_SMOKE_COLUMNS; i++) {
if ((gColumn_flags & (1 << i)) != 0) {
DoSmokeColumn(i, pTime, &dummy);
if (gSmoke_column[i].colour == 0) {
FlameAnimate(i, &gSmoke_column[i].pos, pTime);
}
}
}
}
// IDA: void __usercall MungeSmokeColumn(tU32 pTime@<EAX>)
@ -1866,7 +1965,66 @@ void PipeInstantUnSmudge(tCar_spec* pCar) {
int group;
tSmudged_vertex data[1000];
LOG_TRACE("(%p)", pCar);
NOT_IMPLEMENTED();
if (!gAction_replay_mode) {
return;
}
actor = pCar->car_model_actors[pCar->principal_car_actor].actor;
model = actor->model;
bonny = pCar->car_model_actors[pCar->car_actor_count - 1].actor;
n = 0;
if ((model->flags & BR_MODF_KEEP_ORIGINAL) != 0 || (model->flags & BR_MODF_UPDATEABLE) != 0) {
StartPipingSession(ePipe_chunk_smudge);
j = 0;
for (group = 0; group < V11MODEL(model)->ngroups; group++) {
for (v = 0; v < V11MODEL(model)->groups[group].nvertices; v++) {
if ((V11MODEL(model)->groups[group].vertex_colours[v] >> 24) != 0) {
data[n].vertex_index = j;
data[n].light_index = -(V11MODEL(model)->groups[group].vertex_colours[v] >> 24);
n += 1;
V11MODEL(model)->groups[group].vertex_colours[v] = 0;
if ((model->flags & 0x80) != 0) {
model->vertices[V11MODEL(model)->groups[group].vertex_user[v]].index = 0;
}
if (n >= COUNT_OF(data)) {
group = V11MODEL(model)->ngroups;
break;
}
}
j += 1;
}
}
if (n != 0) {
AddSmudgeToPipingSession(pCar->car_ID, pCar->principal_car_actor, n, data);
}
if (bonny != actor) {
b_model = bonny->model;
n = 0;
j = 0;
for (group = 0; group < V11MODEL(model)->ngroups; group++) {
for (v = 0; v < V11MODEL(model)->groups[group].nvertices; v++) {
if ((V11MODEL(model)->groups[group].vertex_colours[v] >> 24) != 0) {
data[n].vertex_index = j;
data[n].light_index = -V11MODEL(model)->groups[group].nvertices;
n += 1;
V11MODEL(model)->groups[group].vertex_colours[v] = 0;
if ((b_model->flags & BR_MODF_UPDATEABLE) != 0) {
b_model->vertices[V11MODEL(model)->groups[group].vertex_user[v]].index = 0;
}
if (n >= COUNT_OF(data)) {
group = V11MODEL(model)->groups[group].nvertices;
break;
}
}
j += 1;
}
}
if (n != 0) {
AddSmudgeToPipingSession(pCar->car_ID, pCar->car_actor_count - 1, n, data);
}
}
EndPipingSession();
}
}
// IDA: void __usercall SmudgeCar(tCar_spec *pCar@<EAX>, int fire_point@<EDX>)

View File

@ -305,6 +305,7 @@ typedef enum keymapcodes {
KEYMAP_SEND_MESSAGE = 66, // default `
KEYMAP_ARROW = 25, // default R
KEYMAP_INFO = 26, // default I
KEYMAP_REPLAYMODE = 57, // default KP_ENTER
} keymapcodes;
enum {

View File

@ -74,7 +74,7 @@ typedef struct tCar_spec_struct2 tCar_spec2;
typedef struct tPath_node_struct tPath_node;
typedef struct tPath_section_struct tPath_section;
typedef tU32 tPlayer_ID;
typedef void* tPipe_reset_proc(void);
typedef void tPipe_reset_proc(void);
typedef struct tPowerup tPowerup;
#ifdef DETHRACE_FIX_BUGS
typedef int tGot_proc(tPowerup*, tCar_spec*);
@ -2700,6 +2700,9 @@ typedef struct tPipe_chunk { // size: 0x58
typedef struct tPipe_session {
tPipe_chunk_type chunk_type;
tU8 number_of_chunks;
#if defined(DETHRACE_REPLAY_DEBUG)
int magic1;
#endif
tPipe_chunk chunks;
} tPipe_session;

View File

@ -39,7 +39,8 @@
#define Vector3EqualElements(V, A, B, C) \
((V)->v[0] == (A) && (V)->v[1] == (B) && (V)->v[2] == (C))
#define Vector3IsZero(V) Vector3EqualElements((V), 0.f, 0.f, 0.f)
#define Vector3AddFloats(V1, V2, X, Y, Z) \
do { (V1)->v[0] = (V2)->v[0] + (X); (V1)->v[1] = (V2)->v[1] + (Y); (V1)->v[2] = (V2)->v[2] + (Z); } while (0)
#define SwapValuesUsingTemporary(V1, V2, T) \
do { \
(T) = (V1); \
@ -47,4 +48,4 @@
(V2) = (T); \
} while (0)
#endif
#endif

View File

@ -264,7 +264,7 @@ void PDFatalError(char* pThe_str) {
// wait for keypress
exit(1);
abort();
}
// IDA: void __usercall PDNonFatalError(char *pThe_str@<EAX>)
@ -595,13 +595,13 @@ void PDAllocateActionReplayBuffer(char** pBuffer, tU32* pBuffer_size) {
tU32 lba;
tU32 required;
LOG_TRACE("(%p, %p)", pBuffer, pBuffer_size);
NOT_IMPLEMENTED();
OS_AllocateActionReplayBuffer(pBuffer, pBuffer_size);
}
// IDA: void __usercall PDDisposeActionReplayBuffer(char *pBuffer@<EAX>)
void PDDisposeActionReplayBuffer(char* pBuffer) {
LOG_TRACE("(\"%s\")", pBuffer);
NOT_IMPLEMENTED();
}
// IDA: void __usercall Usage(char *pProgpath@<EAX>)

View File

@ -60,4 +60,6 @@ void S3BindListenerLeftBRender(br_vector3* left);
int S3IsCDAPlaying2();
int S3SetEffects(tS3_sample_filter* filter1, tS3_sample_filter* filter2);
#endif

View File

@ -3,6 +3,7 @@
#include "harness/config.h"
#include "miniaudio/miniaudio.h"
#include "resource.h"
#include "harness/trace.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -356,4 +357,8 @@ int S3SyncSampleRate(tS3_channel* chan) {
}
}
return 1;
}
}
void S3SetEffects(tS3_sample_filter* filter1, tS3_sample_filter* filter2) {
STUB_ONCE();
}

View File

@ -195,6 +195,8 @@ void Harness_Init(int* argc, char* argv[]) {
harness_game_config.volume_multiplier = 1.0f;
// start window in windowed mode
harness_game_config.start_full_screen = 0;
// disable replay by default
harness_game_config.enable_replay = 0;
// install signal handler by default
harness_game_config.install_signalhandler = 1;
@ -284,6 +286,9 @@ int Harness_ProcessCommandLine(int* argc, char* argv[]) {
} else if (strcasecmp(argv[i], "--full-screen") == 0) {
harness_game_config.start_full_screen = 1;
handled = 1;
} else if (strcasecmp(argv[i], "--enable-replay") == 0) {
harness_game_config.enable_replay = 1;
handled = 1;
}
if (handled) {

View File

@ -39,6 +39,7 @@ typedef struct tHarness_game_config {
int enable_diagnostics;
float volume_multiplier;
int start_full_screen;
int enable_replay;
int install_signalhandler;
} tHarness_game_config;

View File

@ -46,4 +46,7 @@ void OS_InstallSignalHandler(char* program_name);
FILE* OS_fopen(const char* pathname, const char* mode);
// Required: return a buffer for action replay. Preferably 20MB. If that is not available, then allocate a buffer of 12MB, 6MB, 4MB, 500kB or 64kiB
void OS_AllocateActionReplayBuffer(char** pBuffer, unsigned* pBuffer_size);
#endif

View File

@ -23,6 +23,8 @@
#include <time.h>
#include <unistd.h>
#define ARRAY_SIZE(A) (sizeof(A) / sizeof(A[0]))
static int stack_nbr = 0;
static char _program_name[1024];
#define MAX_STACK_FRAMES 64
@ -335,3 +337,31 @@ FILE* OS_fopen(const char* pathname, const char* mode) {
}
return NULL;
}
void OS_AllocateActionReplayBuffer(char** pBuffer, unsigned* pBuffer_size) {
static int allocated = 0;
static char* buffer = NULL;
static unsigned buffer_size = 0;
unsigned i;
const int wanted_sizes[] = {
20000000,
16000000,
6000000,
4000000,
500000,
};
if (!allocated) {
allocated = 1;
buffer_size = 0;
for (i = 0; i < ARRAY_SIZE(wanted_sizes); i++) {
buffer = malloc(wanted_sizes[i]);
if (buffer != NULL) {
buffer_size = wanted_sizes[i];
break;
}
}
}
*pBuffer = buffer;
*pBuffer_size = buffer_size;
}

View File

@ -19,6 +19,8 @@
#include <time.h>
#include <unistd.h>
#define ARRAY_SIZE(A) (sizeof(A) / sizeof(A[0]))
static int stack_nbr = 0;
static char _program_name[1024];
#define MAX_STACK_FRAMES 64
@ -294,3 +296,31 @@ void OS_InstallSignalHandler(char* program_name) {
FILE* OS_fopen(const char* pathname, const char* mode) {
return fopen(pathname, mode);
}
void OS_AllocateActionReplayBuffer(char** pBuffer, unsigned* pBuffer_size) {
static int allocated = 0;
static char* buffer = NULL;
static unsigned buffer_size = 0;
unsigned i;
const int wanted_sizes[] = {
20000000,
16000000,
6000000,
4000000,
500000,
};
if (!allocated) {
allocated = 1;
buffer_size = 0;
for (i = 0; i < ARRAY_SIZE(wanted_sizes); i++) {
buffer = malloc(wanted_sizes[i]);
if (buffer != NULL) {
buffer_size = wanted_sizes[i];
break;
}
}
}
*pBuffer = buffer;
*pBuffer_size = buffer_size;
}

View File

@ -6,6 +6,7 @@
#include <imagehlp.h>
#include "harness/os.h"
#include <assert.h>
#include <direct.h>
#include <errno.h>
@ -23,6 +24,8 @@
#define Ebp Rbp
#endif
void dr_dprintf(char* fmt_string, ...);
static int stack_nbr = 0;
static char _program_name[1024];
LARGE_INTEGER qpc_start_time, EndingTime, ElapsedMicroseconds;
@ -216,3 +219,92 @@ FILE* OS_fopen(const char* pathname, const char* mode) {
return f;
}
void OS_AllocateActionReplayBuffer(char** pBuffer, unsigned* pBuffer_size) {
static int allocated = 0;
static char* buffer = NULL;
static unsigned buffer_size = 0;
MEMORYSTATUS memory_status;
unsigned wanted;
if (allocated) {
*pBuffer = buffer;
*pBuffer_size = buffer_size;
return;
}
allocated = 1;
buffer = NULL;
memory_status.dwLength = sizeof(memory_status);
GlobalMemoryStatus(&memory_status);
dr_dprintf(
"Win32AllocateActionReplayBuffer(): Memory Status BEFORE Action Replay Allocation:\n"
" dwLength %u\n"
" dwMemoryLoad %u\n"
" dwTotalPhys %u\n"
" dwAvailPhys %u\n"
" dwTotalPageFile %u\n"
" dwAvailPageFile %u\n"
" dwTotalVirtual %u\n"
" dwAvailVirtual %u",
memory_status.dwLength,
memory_status.dwMemoryLoad,
memory_status.dwTotalPhys,
memory_status.dwAvailPhys,
memory_status.dwTotalPageFile,
memory_status.dwAvailPageFile,
memory_status.dwTotalVirtual,
memory_status.dwAvailVirtual);
wanted = 20000000;
if (memory_status.dwTotalPhys < 16000000) {
wanted = 500000;
} else if (memory_status.dwTotalPhys < 24000000) {
wanted = 4000000;
} else if (memory_status.dwTotalPhys < 32000000) {
wanted = 6000000;
} else if (memory_status.dwTotalPhys < 48000000) {
wanted = 12000000;
}
dr_dprintf("Win32AllocateActionReplayBuffer(): We want %d bytes...", wanted);
if (memory_status.dwAvailPageFile + memory_status.dwAvailPhys < wanted) {
wanted = (memory_status.dwAvailPageFile + memory_status.dwAvailPhys) - 0x100000;
dr_dprintf("Win32AllocateActionReplayBuffer(): ...but there's only %d bytes available...", wanted);
}
if (wanted < 0x10000) {
wanted = 0x10000;
dr_dprintf("Win32AllocateActionReplayBuffer(): ...but we have to have a minimum size of %d bytes...", wanted);
}
while (wanted >= 0x10000) {
buffer = malloc(wanted);
if (buffer != NULL) {
break;
}
}
if (buffer == NULL) {
buffer_size = 0;
} else {
buffer_size = wanted;
// Sleep(1000); // Commented out 1s sleep
}
dr_dprintf("Win32AllocateActionReplayBuffer(): Actually allocated %d bytes.", wanted);
GlobalMemoryStatus(&memory_status);
dr_dprintf(
"Win32AllocateActionReplayBuffer(): Memory Status AFTER Action Replay Allocation:\n"
" dwLength %u\n"
" dwMemoryLoad %u\n"
" dwTotalPhys %u\n"
" dwAvailPhys %u\n"
" dwTotalPageFile %u\n"
" dwAvailPageFile %u\n"
" dwTotalVirtual %u\n"
" dwAvailVirtual %u",
memory_status.dwLength,
memory_status.dwMemoryLoad,
memory_status.dwTotalPhys,
memory_status.dwAvailPhys,
memory_status.dwTotalPageFile,
memory_status.dwAvailPageFile,
memory_status.dwTotalVirtual,
memory_status.dwAvailVirtual);
*pBuffer = buffer;
*pBuffer_size = buffer_size;
}