From 078232d7ee4385eb4c37ad1606c002f65a702e87 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Tue, 23 Dec 2025 15:42:21 +0100 Subject: [PATCH] Fix pratcam null pointer dereference (#532) * Add enum for pratcam events * Force start of ambient pratcam when no current pratcam to avoid null dereference This fixes a null pointer dereference when showing the pratcam after finishing the race for the first time. Steps: 1. Start a race 2. Hide pratcam 3. Finish race 4. Start a new race 5. Finish race 6. Show pratcam.... CRASH --- src/DETHRACE/common/car.c | 30 ++++++++++----------- src/DETHRACE/common/controls.c | 12 ++++----- src/DETHRACE/common/crush.c | 10 +++---- src/DETHRACE/common/netgame.c | 2 +- src/DETHRACE/common/network.c | 2 +- src/DETHRACE/common/pedestrn.c | 10 +++---- src/DETHRACE/common/powerup.c | 2 +- src/DETHRACE/common/pratcam.c | 45 ++++++++++++++++++++++++------- src/DETHRACE/common/structur.c | 18 ++++++------- src/DETHRACE/constants.h | 48 ++++++++++++++++++++++++++++++++++ 10 files changed, 126 insertions(+), 53 deletions(-) diff --git a/src/DETHRACE/common/car.c b/src/DETHRACE/common/car.c index 0655b461..8fff2751 100644 --- a/src/DETHRACE/common/car.c +++ b/src/DETHRACE/common/car.c @@ -4387,35 +4387,35 @@ void SetAmbientPratCam(tCar_spec* pCar) { abs_omega_z = fabs(pCar->omega.v[2]); if (abs_omega_x > 4.5f || abs_omega_z > 4.5f) { - ChangeAmbientPratcam(9); + ChangeAmbientPratcam(kPratcam_rolling_violent); } else if (abs_omega_y > 4.5f) { - ChangeAmbientPratcam(12); + ChangeAmbientPratcam(kPratcam_spinning_violent); } else if (abs_omega_x > 3.f || abs_omega_z > 3.f) { - ChangeAmbientPratcam(8); + ChangeAmbientPratcam(kPratcam_rolling_medium); } else if (abs_omega_y > 3.f) { - ChangeAmbientPratcam(11); + ChangeAmbientPratcam(kPratcam_spinning_medium); } else if (pCar->car_master_actor->t.t.mat.m[1][1] < 0.1f) { - ChangeAmbientPratcam(44); + ChangeAmbientPratcam(kPratcam_upside_down); } else if (abs_vcs_y > abs_vcs_z && abs_vcs_y > abs_vcs_x && vcs_y < -.004f) { - ChangeAmbientPratcam(6); + ChangeAmbientPratcam(kPratcam_falling); } else if (the_time - last_time_on_ground > 500) { - ChangeAmbientPratcam(5); + ChangeAmbientPratcam(kPratcam_flying); } else if (abs_vcs_x > abs_vcs_z && vcs_x > .001f) { - ChangeAmbientPratcam(26); + ChangeAmbientPratcam(kPratcam_skidding_right); } else if (abs_vcs_x > abs_vcs_z && vcs_x < -.001f) { - ChangeAmbientPratcam(25); + ChangeAmbientPratcam(kPratcam_skidding_left); } else if (abs_omega_x > 1.5f || abs_omega_z > 1.5f) { - ChangeAmbientPratcam(7); + ChangeAmbientPratcam(kPratcam_rolling_gently); } else if (abs_omega_y > 1.5f) { - ChangeAmbientPratcam(10); + ChangeAmbientPratcam(kPratcam_spinning_gently); } else if (abs_vcs_z > .01f) { - ChangeAmbientPratcam(3); + ChangeAmbientPratcam(kPratcam_over_137mph); } else if (abs_vcs_z > .004f) { - ChangeAmbientPratcam(2); + ChangeAmbientPratcam(kPratcam_between_67_and_167mph); } else if (abs_vcs_z > .0015f) { - ChangeAmbientPratcam(1); + ChangeAmbientPratcam(kPratcam_between_25_and_67mph); } else { - ChangeAmbientPratcam(0); + ChangeAmbientPratcam(kPratcam_stationary_or_below_25mph); } } diff --git a/src/DETHRACE/common/controls.c b/src/DETHRACE/common/controls.c index e60fa926..a288d11a 100644 --- a/src/DETHRACE/common/controls.c +++ b/src/DETHRACE/common/controls.c @@ -801,7 +801,7 @@ void LookLeft(void) { if (gAusterity_mode) { NewTextHeadupSlot(eHeadupSlot_misc, 0, 1000, -4, GetMiscString(kMiscString_NOT_ENOUGH_MEMORY)); } else { - PratcamEvent(27); + PratcamEvent(kPratcam_cockpit_head_left); gProgram_state.old_view = gProgram_state.which_view; if (gProgram_state.which_view == eView_left) { LookForward(); @@ -822,9 +822,9 @@ void LookLeft(void) { void LookForward(void) { if (gProgram_state.which_view == eView_right) { - PratcamEvent(27); + PratcamEvent(kPratcam_cockpit_head_left); } else if (gProgram_state.which_view == eView_left) { - PratcamEvent(28); + PratcamEvent(kPratcam_cockpit_head_right); } if (gProgram_state.which_view != eView_forward) { gProgram_state.old_view = gProgram_state.which_view; @@ -842,7 +842,7 @@ void LookRight(void) { if (gAusterity_mode) { NewTextHeadupSlot(eHeadupSlot_misc, 0, 1000, -4, GetMiscString(kMiscString_NOT_ENOUGH_MEMORY)); } else { - PratcamEvent(28); + PratcamEvent(kPratcam_cockpit_head_right); gProgram_state.old_view = gProgram_state.which_view; if (gProgram_state.which_view == eView_right) { LookForward(); @@ -1132,7 +1132,7 @@ void ConcussMe(void) { SufferFromConcussion(1.f); NewScreenWobble(IRandomPosNeg(15), IRandomPosNeg(10), IRandomBetween(10, 60)); - PratcamEvent(3); + PratcamEvent(kPratcam_over_137mph); } // IDA: void __cdecl CheckHelp() @@ -1954,7 +1954,7 @@ void BrakeInstantly(void) { gProgram_state.current_car.revs = 0.f; if (gProgram_state.current_car.number_of_wheels_on_ground != 0 && BrVector3LengthSquared(&gProgram_state.current_car.v) > 0.0001f) { - PratcamEvent(41); + PratcamEvent(kPratcam_instant_handbrake); for (i = 0; i < 5; i++) { DRS3StartSound(gCar_outlet, 9000 + i); } diff --git a/src/DETHRACE/common/crush.c b/src/DETHRACE/common/crush.c index ec5a83f8..99bf037d 100644 --- a/src/DETHRACE/common/crush.c +++ b/src/DETHRACE/common/crush.c @@ -689,15 +689,15 @@ void DoPratcamHit(br_vector3* pHit_vector) { } if (fabs(pHit_vector->v[2]) >= fabs(pHit_vector->v[0])) { if (pHit_vector->v[2] >= 0.f) { - PratcamEvent(14 + strength_modifier); + PratcamEvent(kPratcam_small_hit_front + strength_modifier); } else { - PratcamEvent(13 + strength_modifier); + PratcamEvent(kPratcam_small_hit_behind + strength_modifier); } } else { if (pHit_vector->v[0] >= 0.f) { - PratcamEvent(15 + strength_modifier); + PratcamEvent(kPratcam_small_hit_left + strength_modifier); } else { - PratcamEvent(16 + strength_modifier); + PratcamEvent(kPratcam_small_hit_right + strength_modifier); } } } @@ -1187,7 +1187,7 @@ int DoCrashEarnings(tCar_spec* pCar1, tCar_spec* pCar2) { NetGuaranteedSendMessageToEverybody(gCurrent_net_game, message, NULL); NetEarnCredits(NetPlayerFromCar(culprit), credits); } else { - PratcamEvent(32); + PratcamEvent(kPratcam_opponent_wasted); DoFancyHeadup(kFancyHeadupYouWastedEm); credits_squared = sqr(0.7f / victim->car_model_actors[victim->principal_car_actor].crush_data.softness_factor) * gWasted_creds[gProgram_state.skill_level] + 50.0f; credits = 100 * (int)(credits_squared / 100.0); diff --git a/src/DETHRACE/common/netgame.c b/src/DETHRACE/common/netgame.c index 054dffe4..c0a22571 100644 --- a/src/DETHRACE/common/netgame.c +++ b/src/DETHRACE/common/netgame.c @@ -1586,7 +1586,7 @@ void ReceivedGameplay(tNet_contents* pContents, tNet_message* pMessage, tU32 pRe break; case eNet_gameplay_suddenly_death: DoFancyHeadup(kFancyHeadupNetworkRaceOverNetworkLoss); - ChangeAmbientPratcam(36); + ChangeAmbientPratcam(kPratcam_network_timeout); gRace_finished = 1; break; default: diff --git a/src/DETHRACE/common/network.c b/src/DETHRACE/common/network.c index e7994083..149b77c6 100644 --- a/src/DETHRACE/common/network.c +++ b/src/DETHRACE/common/network.c @@ -1724,7 +1724,7 @@ void ReceivedWasted(tNet_contents* pContents) { last_culprit = culprit; last_victim = victim; if (pContents->data.wasted.culprit == gLocal_net_ID) { - PratcamEvent(32); + PratcamEvent(kPratcam_opponent_wasted); last_wasted_em_time = PDGetTotalTime(); if (last_wasted_em_time - last_got_wasted_time > 1000) { DoFancyHeadup(kFancyHeadupYouWastedEm); diff --git a/src/DETHRACE/common/pedestrn.c b/src/DETHRACE/common/pedestrn.c index 8f4b6711..f38f167f 100644 --- a/src/DETHRACE/common/pedestrn.c +++ b/src/DETHRACE/common/pedestrn.c @@ -2042,7 +2042,7 @@ void CheckPedestrianDeathScenario(tPedestrian_data* pPedestrian) { BrVector3Set(&up, 0.f, 1.f, 0.f); if (billiards_shot) { credits_value *= 4; - PratcamEvent(30); + PratcamEvent(kPratcam_killed_lots_of_peds); DoFancyHeadup(kFancyHeadupNiceShotSir); } else if (fabs(the_car->omega.v[X]) <= 5.0f && fabs(the_car->omega.v[Z]) <= 5.0f @@ -2055,10 +2055,10 @@ void CheckPedestrianDeathScenario(tPedestrian_data* pPedestrian) { if (gCurrent_ped_multiplier >= 2) { DoFancyHeadup(gCurrent_ped_multiplier + kFancyHeadup2xComboBonus - 2); } else { - PratcamEvent(30); + PratcamEvent(kPratcam_killed_lots_of_peds); if (exploded) { DoFancyHeadup(kFancyHeadupSplatterBonus); - PratcamEvent(30); + PratcamEvent(kPratcam_killed_lots_of_peds); } } } else { @@ -2067,10 +2067,10 @@ void CheckPedestrianDeathScenario(tPedestrian_data* pPedestrian) { } } else { credits_value *= 4; - PratcamEvent(30); + PratcamEvent(kPratcam_killed_lots_of_peds); DoFancyHeadup(kFancyHeadupBonusForArtisticImpression); } - PratcamEvent(29); + PratcamEvent(kPratcam_killed_one_ped); EarnCredits(credits_value); } if (the_car->driver == eDriver_local_human && gProgram_state.cockpit_on) { diff --git a/src/DETHRACE/common/powerup.c b/src/DETHRACE/common/powerup.c index b32309de..4534e1b5 100644 --- a/src/DETHRACE/common/powerup.c +++ b/src/DETHRACE/common/powerup.c @@ -1123,7 +1123,7 @@ void ResetInstantHandbrake(tPowerup* pPowerup, tCar_spec* pCar) { void DoBouncey(tPowerup* pPowerup, tU32 pPeriod) { if (gProgram_state.current_car.bounce_rate <= GetTotalTime() - gProgram_state.current_car.last_bounce && gProgram_state.current_car.number_of_wheels_on_ground > 2) { - PratcamEvent(42); + PratcamEvent(kPratcam_bouncey_bouncey); gProgram_state.current_car.last_bounce = GetTotalTime(); gProgram_state.current_car.v.v[1] += gProgram_state.current_car.bounce_amount; DRS3StartSound(gCar_outlet, 9010); diff --git a/src/DETHRACE/common/pratcam.c b/src/DETHRACE/common/pratcam.c index 1216fc7e..99826eae 100644 --- a/src/DETHRACE/common/pratcam.c +++ b/src/DETHRACE/common/pratcam.c @@ -13,6 +13,7 @@ #include "loading.h" #include "pd/sys.h" #include "sound.h" +#include "structur.h" #include "utility.h" #include @@ -513,6 +514,30 @@ void DoPratcam(tU32 pThe_time) { DontLetFlicFuckWithPalettes(); DisableTranslationText(); for (i = 0; i < (old_last_time != 0 ? ((pThe_time - old_last_time) / gPrat_flic.frame_period) : 1); i++) { +#ifdef DETHRACE_FIX_BUGS + if (gPrat_flic.data == NULL) { + switch (gRace_over_reason) { + case eRace_over_laps: + case eRace_over_peds: + case eRace_over_opponents: + ChangeAmbientPratcamNow(kPratcam_race_complete, 0); + break; + case eRace_over_demo: + case eRace_over_out_of_time: + ChangeAmbientPratcamNow(kPratcam_out_of_time, 0); + break; + case eRace_over_abandoned: + case eRace_over_network_victory: + case eRace_over_network_loss: + ChangeAmbientPratcamNow(kPratcam_network_timeout, 0); + break; + default: + case eRace_not_over_yet: + ChangeAmbientPratcamNow(kPratcam_stationary_or_below_25mph, 0); + break; + } + } +#endif if (PlayNextFlicFrame(&gPrat_flic)) { NextPratcamChunk(); break; @@ -626,68 +651,68 @@ void TestPratCam(int pIndex) { // FUNCTION: CARM95 0x0044e6c0 void PratCam0(void) { - TestPratCam(0); + TestPratCam(kPratcam_stationary_or_below_25mph); } // IDA: void __cdecl PratCam1() // FUNCTION: CARM95 0x0044e72e void PratCam1(void) { - TestPratCam(1); + TestPratCam(kPratcam_between_25_and_67mph); } // IDA: void __cdecl PratCam2() // FUNCTION: CARM95 0x0044e743 void PratCam2(void) { - TestPratCam(2); + TestPratCam(kPratcam_between_67_and_167mph); } // IDA: void __cdecl PratCam3() // FUNCTION: CARM95 0x0044e758 void PratCam3(void) { - TestPratCam(3); + TestPratCam(kPratcam_over_137mph); } // IDA: void __cdecl PratCam4() // FUNCTION: CARM95 0x0044e76d void PratCam4(void) { - TestPratCam(4); + TestPratCam(kPratcam_accelerating_unused_4); } // IDA: void __cdecl PratCam5() // FUNCTION: CARM95 0x0044e782 void PratCam5(void) { - TestPratCam(5); + TestPratCam(kPratcam_flying); } // IDA: void __cdecl PratCam6() // FUNCTION: CARM95 0x0044e797 void PratCam6(void) { - TestPratCam(6); + TestPratCam(kPratcam_falling); } // IDA: void __cdecl PratCam7() // FUNCTION: CARM95 0x0044e7ac void PratCam7(void) { - TestPratCam(7); + TestPratCam(kPratcam_rolling_gently); } // IDA: void __cdecl PratCam8() // FUNCTION: CARM95 0x0044e7c1 void PratCam8(void) { - TestPratCam(8); + TestPratCam(kPratcam_rolling_medium); } // IDA: void __cdecl PratCam9() // FUNCTION: CARM95 0x0044e7d6 void PratCam9(void) { - TestPratCam(9); + TestPratCam(kPratcam_rolling_violent); } diff --git a/src/DETHRACE/common/structur.c b/src/DETHRACE/common/structur.c index 1d28fd63..12e27ada 100644 --- a/src/DETHRACE/common/structur.c +++ b/src/DETHRACE/common/structur.c @@ -90,9 +90,9 @@ void RaceCompleted(tRace_over_reason pReason) { NetFinishRace(gCurrent_net_game, pReason); } if (pReason == eRace_over_out_of_time || pReason == eRace_over_demo) { - ChangeAmbientPratcam(35); + ChangeAmbientPratcam(kPratcam_out_of_time); } else if (pReason < eRace_over_abandoned) { - ChangeAmbientPratcam(34); + ChangeAmbientPratcam(kPratcam_race_complete); } gRace_over_reason = pReason; if (gMap_mode) { @@ -100,30 +100,30 @@ void RaceCompleted(tRace_over_reason pReason) { } switch (gRace_over_reason) { case eRace_over_network_victory: - ChangeAmbientPratcam(34); + ChangeAmbientPratcam(kPratcam_race_complete); DoFancyHeadup(kFancyHeadupNetworkVictory); break; case eRace_over_network_loss: - ChangeAmbientPratcam(36); + ChangeAmbientPratcam(kPratcam_network_timeout); DoFancyHeadup(kFancyHeadupNetworkRaceOverNetworkLoss); break; case eRace_over_out_of_time: - ChangeAmbientPratcam(35); + ChangeAmbientPratcam(kPratcam_out_of_time); DoFancyHeadup(kFancyHeadupOutOfTime); DRS3StartSound(gPedestrians_outlet, 8010); break; case eRace_over_demo: - ChangeAmbientPratcam(35); + ChangeAmbientPratcam(kPratcam_out_of_time); DoFancyHeadup(kFancyHeadupDemoTimeout); break; case eRace_over_laps: case eRace_over_peds: case eRace_over_opponents: - ChangeAmbientPratcam(34); + ChangeAmbientPratcam(kPratcam_race_complete); DoFancyHeadup(kFancyHeadupRaceCompleted); DRS3StartSound(gPedestrians_outlet, 8011); break; @@ -150,7 +150,7 @@ void RaceCompleted(tRace_over_reason pReason) { // FUNCTION: CARM95 0x004141ca void Checkpoint(int pCheckpoint_index, int pDo_sound) { - PratcamEvent(33); + PratcamEvent(kPratcam_checkpoint); DoFancyHeadup(kFancyHeadupCheckpoint); if (pDo_sound) { DRS3StartSound(gPedestrians_outlet, 8012); @@ -174,7 +174,7 @@ void IncrementCheckpoint(void) { gCheckpoint = gCheckpoint_count; RaceCompleted(eRace_over_laps); } else if (gLap == gTotal_laps) { - PratcamEvent(33); + PratcamEvent(kPratcam_checkpoint); NewTextHeadupSlot(eHeadupSlot_misc, 0, 1000, -4, GetMiscString(kMiscString_FinalLap)); DRS3StartSound(gPedestrians_outlet, 8014); done_voice = 1; diff --git a/src/DETHRACE/constants.h b/src/DETHRACE/constants.h index 811d7823..ead70106 100644 --- a/src/DETHRACE/constants.h +++ b/src/DETHRACE/constants.h @@ -764,6 +764,54 @@ enum { kFont_DRKPLAQ1 = 20, }; +enum { + kPratcam_stationary_or_below_25mph = 0, + kPratcam_between_25_and_67mph = 1, + kPratcam_between_67_and_167mph = 2, + kPratcam_over_137mph = 3, + kPratcam_accelerating_unused_4 = 4, + kPratcam_flying = 5, + kPratcam_falling = 6, + kPratcam_rolling_gently = 7, + kPratcam_rolling_medium = 8, + kPratcam_rolling_violent = 9, + kPratcam_spinning_gently = 10, + kPratcam_spinning_medium = 11, + kPratcam_spinning_violent = 12, + kPratcam_small_hit_behind = 13, + kPratcam_small_hit_front = 14, + kPratcam_small_hit_left = 15, + kPratcam_small_hit_right = 16, + kPratcam_medium_hit_behind = 17, + kPratcam_medium_hit_front = 18, + kPratcam_medium_hit_left = 19, + kPratcam_medium_hit_right = 20, + kPratcam_big_hit_behind = 21, + kPratcam_big_hit_front = 22, + kPratcam_big_hit_left = 23, + kPratcam_big_hit_right = 24, + kPratcam_skidding_left = 25, + kPratcam_skidding_right = 26, + kPratcam_cockpit_head_left = 27, + kPratcam_cockpit_head_right = 28, + kPratcam_killed_one_ped = 29, + kPratcam_killed_lots_of_peds = 30, + kPratcam_apologise_for_ped_kill = 31, + kPratcam_opponent_wasted = 32, + kPratcam_checkpoint = 33, + kPratcam_race_complete = 34, + kPratcam_out_of_time = 35, + kPratcam_network_timeout = 36, + kPratcam_points_or_time = 37, + kPratcam_good_powerup = 38, + kPratcam_bad_powerup = 39, + kPratcam_weird_powerup = 40, + kPratcam_instant_handbrake = 41, + kPratcam_bouncey_bouncey = 42, + kPratcam_instant_bodywork_trash = 43, + kPratcam_upside_down = 44, +}; + enum { NETMSGID_SENDMEDETAILS = 0x00, NETMSGID_DETAILS = 0x01,