From 60102a37e4b70625584d66fb9f432e5ba244e052 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Thu, 10 Mar 2022 02:32:09 +0100 Subject: [PATCH] Add change car dialog (#102) * Add 'change car' dialog * Implement functions to support switching car * When opening a file in brender fails, try all uppercase file before failing * Some cars need GetFourScalars --- src/BRSRC13/CORE/FW/file.c | 25 ++++ src/BRSRC13/CORE/V1DB/actsupt.c | 12 +- src/DETHRACE/common/graphics.c | 100 +++++++++++++- src/DETHRACE/common/loading.c | 105 +++++++++++++- src/DETHRACE/common/newgame.c | 5 +- src/DETHRACE/common/pedestrn.c | 13 +- src/DETHRACE/common/racestrt.c | 235 ++++++++++++++++++++++++++++++-- src/DETHRACE/common/world.c | 35 ++++- 8 files changed, 499 insertions(+), 31 deletions(-) diff --git a/src/BRSRC13/CORE/FW/file.c b/src/BRSRC13/CORE/FW/file.c index 1a580604..e9820ad7 100644 --- a/src/BRSRC13/CORE/FW/file.c +++ b/src/BRSRC13/CORE/FW/file.c @@ -6,6 +6,10 @@ #include "harness/trace.h" #include #include +#ifdef BRENDER_FIX_BUGS +#include +#include +#endif // IDA: void __cdecl _BrFileFree(void *res, br_uint_8 res_class, br_size_t size) void _BrFileFree(void* res, br_uint_8 res_class, br_size_t size) { @@ -27,6 +31,9 @@ void* BrFileOpenRead(char* name, br_size_t n_magics, br_mode_test_cbfn* mode_tes void* raw_file; br_file* file; int bin_mode; +#ifdef BRENDER_FIX_BUGS + char *s; +#endif LOG_TRACE("(\"%s\", %d, %p, %p)", name, n_magics, mode_test, mode_result); bin_mode = 0; @@ -36,6 +43,24 @@ void* BrFileOpenRead(char* name, br_size_t n_magics, br_mode_test_cbfn* mode_tes raw_file = fw.fsys->open_read(name, n_magics, mode_test, &bin_mode); } +#ifdef BRENDER_FIX_BUGS + // Try all-uppercase filename for case sensitive file systems + if (raw_file == NULL) { + for (s = name + strlen(name); s != name;) { + s--; + if (*s == '\\' || *s == '/') { + break; + } + *s = toupper(*s); + } + if (mode_result != NULL) { + raw_file = fw.fsys->open_read(name, n_magics, mode_test, mode_result); + } else { + raw_file = fw.fsys->open_read(name, n_magics, mode_test, &bin_mode); + } + } +#endif + if (raw_file == NULL) { return NULL; } diff --git a/src/BRSRC13/CORE/V1DB/actsupt.c b/src/BRSRC13/CORE/V1DB/actsupt.c index 94b4cf27..9726f312 100644 --- a/src/BRSRC13/CORE/V1DB/actsupt.c +++ b/src/BRSRC13/CORE/V1DB/actsupt.c @@ -210,9 +210,9 @@ br_actor* BrActorAllocate(br_uint_8 type, void* type_data) { // IDA: void __usercall InternalActorFree(br_actor *a@) void InternalActorFree(br_actor* a) { - while (a->children) { - BrSimpleRemove((br_simple_node*)a->children); - InternalActorFree(a); + + while (a->children != NULL) { + InternalActorFree((br_actor*)BrSimpleRemove((br_simple_node*)a->children)); } BrActorEnableCheck(a); BrResFree(a); @@ -220,9 +220,9 @@ void InternalActorFree(br_actor* a) { // IDA: void __cdecl BrActorFree(br_actor *a) void BrActorFree(br_actor* a) { - while (a->children) { - BrSimpleRemove((br_simple_node*)a->children); - InternalActorFree(a); + + while (a->children != NULL) { + InternalActorFree((br_actor*)BrSimpleRemove((br_simple_node*)a->children)); } BrActorEnableCheck(a); BrResFree(a); diff --git a/src/DETHRACE/common/graphics.c b/src/DETHRACE/common/graphics.c index 0ebf4ba5..9a5ac752 100644 --- a/src/DETHRACE/common/graphics.c +++ b/src/DETHRACE/common/graphics.c @@ -2353,7 +2353,37 @@ void DrawDropImage(br_pixelmap* pImage, int pLeft, int pTop, int pTop_clip, int int src_height; int y_diff; LOG_TRACE("(%p, %d, %d, %d, %d, %d)", pImage, pLeft, pTop, pTop_clip, pBottom_clip, pOffset); - NOT_IMPLEMENTED(); + + BrPixelmapRectangleFill(gBack_screen, + pLeft, + pTop_clip, + pImage->width, + pBottom_clip - pTop_clip, + 0); + if (pOffset != 1000) { + src_y = 0; + src_height = pImage->height; + y = pOffset + pTop; + y_diff = pTop_clip - y; + if (y_diff > 0) { + src_height -= y_diff; + y += y_diff; + src_y = y_diff; + } + y_diff = pBottom_clip - y - pImage->height; + if (y_diff < 0) { + src_height += y_diff; + } + BrPixelmapRectangleCopy(gBack_screen, + pLeft, + y, + pImage, + 0, + src_y, + pImage->width, + src_height); + PDScreenBufferSwap(0); + } } // IDA: void __usercall DropInImageFromTop(br_pixelmap *pImage@, int pLeft@, int pTop@, int pTop_clip@, int pBottom_clip) @@ -2362,7 +2392,22 @@ void DropInImageFromTop(br_pixelmap* pImage, int pLeft, int pTop, int pTop_clip, tS32 the_time; int drop_distance; LOG_TRACE("(%p, %d, %d, %d, %d)", pImage, pLeft, pTop, pTop_clip, pBottom_clip); - NOT_IMPLEMENTED(); + + start_time = PDGetTotalTime(); + drop_distance = pImage->height - pTop_clip + pTop; + while (1) { + the_time = PDGetTotalTime(); + if (the_time >= start_time + 100) { + break; + } + DrawDropImage(pImage, + pLeft, + pTop, + pTop_clip, + pBottom_clip, + (the_time - start_time - 100) * drop_distance / 100); + } + DrawDropImage(pImage, pLeft, pTop, pTop_clip, pBottom_clip, 0); } // IDA: void __usercall DropOutImageThruBottom(br_pixelmap *pImage@, int pLeft@, int pTop@, int pTop_clip@, int pBottom_clip) @@ -2371,7 +2416,22 @@ void DropOutImageThruBottom(br_pixelmap* pImage, int pLeft, int pTop, int pTop_c tS32 the_time; int drop_distance; LOG_TRACE("(%p, %d, %d, %d, %d)", pImage, pLeft, pTop, pTop_clip, pBottom_clip); - NOT_IMPLEMENTED(); + + start_time = PDGetTotalTime(); + drop_distance = pBottom_clip - pTop; + while (1) { + the_time = PDGetTotalTime(); + if (the_time >= start_time + 100) { + break; + } + DrawDropImage(pImage, + pLeft, + pTop, + pTop_clip, + pBottom_clip, + (the_time - start_time) * drop_distance / 100); + } + DrawDropImage(pImage, pLeft, pTop, pTop_clip, pBottom_clip, 1000); } // IDA: void __usercall DropInImageFromBottom(br_pixelmap *pImage@, int pLeft@, int pTop@, int pTop_clip@, int pBottom_clip) @@ -2380,7 +2440,22 @@ void DropInImageFromBottom(br_pixelmap* pImage, int pLeft, int pTop, int pTop_cl tS32 the_time; int drop_distance; LOG_TRACE("(%p, %d, %d, %d, %d)", pImage, pLeft, pTop, pTop_clip, pBottom_clip); - NOT_IMPLEMENTED(); + + start_time = PDGetTotalTime(); + drop_distance = pBottom_clip - pTop; + while (1) { + the_time = PDGetTotalTime(); + if (the_time >= start_time + 100) { + break; + } + DrawDropImage(pImage, + pLeft, + pTop, + pTop_clip, + pBottom_clip, + (100 - the_time + start_time) * drop_distance / 100); + } + DrawDropImage(pImage, pLeft, pTop, pTop_clip, pBottom_clip, 0); } // IDA: void __usercall DropOutImageThruTop(br_pixelmap *pImage@, int pLeft@, int pTop@, int pTop_clip@, int pBottom_clip) @@ -2389,7 +2464,22 @@ void DropOutImageThruTop(br_pixelmap* pImage, int pLeft, int pTop, int pTop_clip tS32 the_time; int drop_distance; LOG_TRACE("(%p, %d, %d, %d, %d)", pImage, pLeft, pTop, pTop_clip, pBottom_clip); - NOT_IMPLEMENTED(); + + start_time = PDGetTotalTime(); + drop_distance = pImage->height - pTop_clip + pTop; + while (1) { + the_time = PDGetTotalTime(); + if (the_time >= start_time + 100) { + break; + } + DrawDropImage(pImage, + pLeft, + pTop, + pTop_clip, + pBottom_clip, + (start_time - the_time) * drop_distance / 100); + } + DrawDropImage(pImage, pLeft, pTop, pTop_clip, pBottom_clip, 1000); } // IDA: void __usercall DrawTellyLine(br_pixelmap *pImage@, int pLeft@, int pTop@, int pPercentage@) diff --git a/src/DETHRACE/common/loading.c b/src/DETHRACE/common/loading.c index 29a39085..f77c60ca 100644 --- a/src/DETHRACE/common/loading.c +++ b/src/DETHRACE/common/loading.c @@ -899,7 +899,95 @@ void DisposeCar(tCar_spec* pCar_spec, int pOwner) { int i; int j; LOG_TRACE("(%p, %d)", pCar_spec, pOwner); - NOT_IMPLEMENTED(); + + if (pCar_spec->driver_name[0] == '\0') { + return; + } + gFunk_groove_flags[pCar_spec->fg_index] = 0; + pCar_spec->driver_name[0] = '\0'; + if (pCar_spec->driver == eDriver_local_human) { + for (i = 0; i < COUNT_OF(pCar_spec->cockpit_images); i++) { + if (pCar_spec->cockpit_images[i] != NULL) { + BrMemFree(pCar_spec->cockpit_images[i]); + } + } + if (pCar_spec->speedo_image[0] != NULL) { + BrPixelmapFree(pCar_spec->speedo_image[0]); + } + if (pCar_spec->speedo_image[1] != NULL) { + BrPixelmapFree(pCar_spec->speedo_image[1]); + } + if (pCar_spec->tacho_image[0] != NULL) { + BrPixelmapFree(pCar_spec->tacho_image[0]); + } + if (pCar_spec->tacho_image[1] != NULL) { + BrPixelmapFree(pCar_spec->tacho_image[1]); + } + for (i = 0; i < pCar_spec->number_of_hands_images; i++) { + if (pCar_spec->lhands_images[i] != NULL) { + BrPixelmapFree(pCar_spec->lhands_images[i]); + } + if (pCar_spec->rhands_images[i] != NULL) { + BrPixelmapFree(pCar_spec->rhands_images[i]); + } + } + if (pCar_spec->prat_cam_left != NULL) { + BrPixelmapFree(pCar_spec->prat_cam_left); + } + if (pCar_spec->prat_cam_top != NULL) { + BrPixelmapFree(pCar_spec->prat_cam_top); + } + if (pCar_spec->prat_cam_right != NULL) { + BrPixelmapFree(pCar_spec->prat_cam_right); + } + if (pCar_spec->prat_cam_bottom != NULL) { + BrPixelmapFree(pCar_spec->prat_cam_bottom); + } + for (i = 0; i < COUNT_OF(pCar_spec->damage_units); i++) { + if (pCar_spec->damage_units[i].images != NULL) { + BrPixelmapFree(pCar_spec->damage_units[i].images); + } + } + if (pCar_spec->damage_background != NULL) { + BrPixelmapFree(pCar_spec->damage_background); + } + for (i = 0; i < COUNT_OF(pCar_spec->power_ups); i++) { + for (j = 0; j < pCar_spec->power_ups[i].number_of_parts; j++) { + if (pCar_spec->power_ups[i].info[j].data_ptr != NULL) { + BrMemFree(pCar_spec->power_ups[i].info[j].data_ptr); + } + } + } + gProgram_state.car_name[0] = '\0'; + } + if (pCar_spec->screen_material != NULL) { + KillWindscreen(pCar_spec->car_model_actors[pCar_spec->principal_car_actor].actor->model, + pCar_spec->screen_material); + BrMaterialRemove(pCar_spec->screen_material); + BrMaterialFree(pCar_spec->screen_material); + } + for (i = 0; i < COUNT_OF(pCar_spec->damage_programs); i++) { + BrMemFree(pCar_spec->damage_programs[i].clauses); + } + DropOffDyingPeds(pCar_spec); + for (i = 0; i < pCar_spec->car_actor_count; i++) { + BrActorRemove(pCar_spec->car_model_actors[i].actor); + BrActorFree(pCar_spec->car_model_actors[i].actor); + } + if (pCar_spec->driver != eDriver_local_human) { + BrActorRemove(pCar_spec->car_master_actor); + BrActorFree(pCar_spec->car_master_actor); + } + DisposeFunkotronics(pOwner); + DisposeGroovidelics(pOwner); + for (i = 0; i < pCar_spec->car_actor_count; i++) { + if (pCar_spec->car_model_actors[i].crush_data.crush_points != NULL) { + DisposeCrushData(&pCar_spec->car_model_actors[i].crush_data); + } + if (pCar_spec->car_model_actors[i].undamaged_vertices != NULL) { + BrMemFree(pCar_spec->car_model_actors[i].undamaged_vertices); + } + } } // IDA: void __usercall AdjustCarCoordinates(tCar_spec *pCar@) @@ -2799,7 +2887,20 @@ void GetFourScalars(FILE* pF, br_scalar* pF1, br_scalar* pF2, br_scalar* pF3, br float f3; float f4; LOG_TRACE("(%p, %p, %p, %p, %p)", pF, pF1, pF2, pF3, pF4); - NOT_IMPLEMENTED(); + + GetALineAndDontArgue(pF, s); + str = strtok(s, "\t ,/"); + sscanf(str, "%f", &f1); + str = strtok(NULL, "\t ,/"); + sscanf(str, "%f", &f2); + str = strtok(NULL, "\t ,/"); + sscanf(str, "%f", &f3); + str = strtok(NULL, "\t ,/"); + sscanf(str, "%f", &f4); + *pF1 = f1; + *pF2 = f2; + *pF3 = f3; + *pF4 = f4; } // IDA: void __usercall GetFiveScalars(FILE *pF@, br_scalar *pF1@, br_scalar *pF2@, br_scalar *pF3@, br_scalar *pF4, br_scalar *pF5) diff --git a/src/DETHRACE/common/newgame.c b/src/DETHRACE/common/newgame.c index 50dc74b8..509203cb 100644 --- a/src/DETHRACE/common/newgame.c +++ b/src/DETHRACE/common/newgame.c @@ -785,7 +785,10 @@ int PickARandomCar() { // IDA: void __usercall PollCarDetails(tNet_game_details *pNet_game@) void PollCarDetails(tNet_game_details* pNet_game) { LOG_TRACE("(%p)", pNet_game); - NOT_IMPLEMENTED(); + + if (gReceived_car_details != 0) { + RequestCarDetails(pNet_game); + } } // IDA: void __usercall SetNetAvailability(tNet_game_options *pOptions@) diff --git a/src/DETHRACE/common/pedestrn.c b/src/DETHRACE/common/pedestrn.c index 95fe74e4..24764ed7 100644 --- a/src/DETHRACE/common/pedestrn.c +++ b/src/DETHRACE/common/pedestrn.c @@ -18,6 +18,10 @@ #define FLAG_WAVING_BASTARD_REF 99 +#define FOURCC(A,B,C,D) (((A & 0xff) << 24) | ((B & 0xff) << 16)| ((C & 0xff) << 8)| ((D & 0xff) << 0)) +#define PEDESTRIAN_MAGIC FOURCC('P', 'e', 'd', '!') +#define ActorToPedestrianData(ACTOR) ((tPedestrian_data*)((ACTOR)->type_data)) + int gDetect_peds; int gReally_stupid_ped_bug_enable; int gPed_sound_disable; @@ -111,7 +115,14 @@ void PedModelUpdate(br_model* pModel, br_scalar x0, br_scalar y0, br_scalar x1, // IDA: int __usercall ActorIsPedestrian@(br_actor *pActor@) int ActorIsPedestrian(br_actor* pActor) { LOG_TRACE("(%p)", pActor); - NOT_IMPLEMENTED(); + + if (pActor->model == NULL) { + return 0; + } + if (pActor->type_data == NULL) { + return 0; + } + return ActorToPedestrianData(pActor)->magic_number == PEDESTRIAN_MAGIC; } // IDA: br_scalar __usercall PedHeightFromActor@(br_actor *pActor@) diff --git a/src/DETHRACE/common/racestrt.c b/src/DETHRACE/common/racestrt.c index 33ae535b..309cef1a 100644 --- a/src/DETHRACE/common/racestrt.c +++ b/src/DETHRACE/common/racestrt.c @@ -5,17 +5,20 @@ #include "errors.h" #include "flicplay.h" #include "globvars.h" +#include "globvrpb.h" #include "grafdata.h" #include "graphics.h" #include "harness/trace.h" #include "input.h" #include "intrface.h" #include "loading.h" +#include "newgame.h" #include "opponent.h" #include "pd/sys.h" #include "sound.h" #include "structur.h" #include "utility.h" +#include "world.h" #include int gGrid_number_colour[4] = { 49u, 201u, 1u, 201u }; @@ -327,63 +330,267 @@ void DrawCar(int pCurrent_choice, int pCurrent_mode) { int text_x; int text_width; LOG_TRACE("(%d, %d)", pCurrent_choice, pCurrent_mode); - NOT_IMPLEMENTED(); + + PollCarDetails(gChoose_car_net_game); + if (gChange_race_net_mode == 0) { + if (gProgram_state.number_of_cars == 1) { + sprintf(s, GetMiscString(34)); + } else if (gProgram_state.cars_available[gCurrent_car_index] == gProgram_state.frank_or_anniness) { + sprintf(s, GetMiscString(36)); + } else { + sprintf(s, "%s %s", GetMiscString(35), gOpponents[gProgram_state.cars_available[gCurrent_car_index]].name); + } + } else if (gCar_details[gProgram_state.cars_available[gCurrent_car_index]].ownership == eCar_owner_someone) { + sprintf(s, "%s %s", GetMiscString(204), gCar_details[gProgram_state.cars_available[gCurrent_car_index]].name); + } else { + sprintf(s, GetMiscString(205)); + } + text_width = BrPixelmapTextWidth(gBack_screen, gFont_7, s); + text_x = (gCurrent_graf_data->change_car_line_right + gCurrent_graf_data->change_car_line_left - text_width) / 2; + BrPixelmapRectangleFill(gBack_screen, + gCurrent_graf_data->change_car_line_left, + gCurrent_graf_data->change_car_text_y, + gCurrent_graf_data->change_car_line_right - gCurrent_graf_data->change_car_line_left, + gFont_7->glyph_y, + 0); + TransBrPixelmapText(gBack_screen, + text_x, + gCurrent_graf_data->change_car_text_y, + 3, + gFont_7, + (signed char*)s); + BrPixelmapLine(gBack_screen, + gCurrent_graf_data->change_car_line_left, + gCurrent_graf_data->change_car_line_y, + gCurrent_graf_data->change_car_line_right, + gCurrent_graf_data->change_car_line_y, + 6); + if (gChange_race_net_mode && gCar_details[gProgram_state.cars_available[gCurrent_car_index]].ownership == eCar_owner_someone) { + DRPixelmapRectangleMaskedCopy( + gBack_screen, + (gCurrent_graf_data->change_car_panel_left + gCurrent_graf_data->change_car_panel_right - gTaken_image->width) / 2, + (gCurrent_graf_data->change_car_panel_bottom + gCurrent_graf_data->change_car_panel_bottom - gTaken_image->height) / 2, + gTaken_image, + 0, + 0, + gTaken_image->width, + gTaken_image->height); + } } // IDA: void __cdecl SetCarFlic() void SetCarFlic() { LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + ChangePanelFlic(0, + gOpponents[gProgram_state.cars_available[gCurrent_car_index]].stolen_car_image_data, + gOpponents[gProgram_state.cars_available[gCurrent_car_index]].stolen_car_image_data_length); } // IDA: int __usercall UpCar@(int *pCurrent_choice@, int *pCurrent_mode@) int UpCar(int* pCurrent_choice, int* pCurrent_mode) { LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode); - NOT_IMPLEMENTED(); + + AddToFlicQueue(gStart_interface_spec->pushed_flics[2].flic_index, + gStart_interface_spec->pushed_flics[2].x[gGraf_data_index], + gStart_interface_spec->pushed_flics[2].y[gGraf_data_index], + 1); + DRS3StartSound(gIndexed_outlets[0], 3000); + if (gCurrent_car_index != 0) { + RemoveTransientBitmaps(1); + DropOutImageThruBottom(GetPanelPixelmap(0), + gCurrent_graf_data->change_car_panel_left, + gCurrent_graf_data->change_car_panel_top, + gCurrent_graf_data->change_car_panel_top_clip, + gCurrent_graf_data->change_car_panel_bottom_clip); + gCurrent_car_index--; + SetCarFlic(); + DropInImageFromTop(GetPanelPixelmap(0), + gCurrent_graf_data->change_car_panel_left, + gCurrent_graf_data->change_car_panel_top, + gCurrent_graf_data->change_car_panel_top_clip, + gCurrent_graf_data->change_car_panel_bottom_clip); + } + return 0; } // IDA: int __usercall DownCar@(int *pCurrent_choice@, int *pCurrent_mode@) int DownCar(int* pCurrent_choice, int* pCurrent_mode) { LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode); - NOT_IMPLEMENTED(); + + AddToFlicQueue(gStart_interface_spec->pushed_flics[3].flic_index, + gStart_interface_spec->pushed_flics[3].x[gGraf_data_index], + gStart_interface_spec->pushed_flics[3].y[gGraf_data_index], + 1); + DRS3StartSound(gIndexed_outlets[0], 3000); + if (gCurrent_car_index < gProgram_state.number_of_cars - 1) { + RemoveTransientBitmaps(1); + DropOutImageThruTop(GetPanelPixelmap(0), + gCurrent_graf_data->change_car_panel_left, + gCurrent_graf_data->change_car_panel_top, + gCurrent_graf_data->change_car_panel_top_clip, + gCurrent_graf_data->change_car_panel_bottom_clip); + gCurrent_car_index++; + SetCarFlic(); + DropInImageFromBottom(GetPanelPixelmap(0), + gCurrent_graf_data->change_car_panel_left, + gCurrent_graf_data->change_car_panel_top, + gCurrent_graf_data->change_car_panel_top_clip, + gCurrent_graf_data->change_car_panel_bottom_clip); + } + return 0; } // IDA: int __usercall UpClickCar@(int *pCurrent_choice@, int *pCurrent_mode@, int pX_offset@, int pY_offset@) int UpClickCar(int* pCurrent_choice, int* pCurrent_mode, int pX_offset, int pY_offset) { LOG_TRACE("(%p, %p, %d, %d)", pCurrent_choice, pCurrent_mode, pX_offset, pY_offset); - NOT_IMPLEMENTED(); + + UpCar(pCurrent_choice, pCurrent_mode); + return 0; } // IDA: int __usercall DownClickCar@(int *pCurrent_choice@, int *pCurrent_mode@, int pX_offset@, int pY_offset@) int DownClickCar(int* pCurrent_choice, int* pCurrent_mode, int pX_offset, int pY_offset) { LOG_TRACE("(%p, %p, %d, %d)", pCurrent_choice, pCurrent_mode, pX_offset, pY_offset); - NOT_IMPLEMENTED(); + + DownCar(pCurrent_choice, pCurrent_mode); + return 0; } // IDA: int __usercall ChangeCarGoAhead@(int *pCurrent_choice@, int *pCurrent_mode@) int ChangeCarGoAhead(int* pCurrent_choice, int* pCurrent_mode) { LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode); - NOT_IMPLEMENTED(); + + if (gChange_race_net_mode == 0 || gCar_details[gProgram_state.cars_available[gCurrent_car_index]].ownership != eCar_owner_someone) { + return 1; + } else { + DRS3StartSound(gIndexed_outlets[0], 3100); + return 0; + } } // IDA: int __usercall ChangeCar@(int pNet_mode@, int *pCar_index@, tNet_game_details *pNet_game@) int ChangeCar(int pNet_mode, int* pCar_index, tNet_game_details* pNet_game) { - static tFlicette flicker_on[4]; - static tFlicette flicker_off[4]; - static tFlicette push[4]; - static tMouse_area mouse_areas[4]; - static tInterface_spec interface_spec; + static tFlicette flicker_on[4] = { + { 43, { 60, 120 }, { 154, 370 } }, + { 43, { 221, 442 }, { 154, 370 } }, + { 221, { 30, 60 }, { 78, 187 } }, + { 221, { 30, 60 }, { 78, 187 } }, + }; + static tFlicette flicker_off[4] = { + { 42, { 60, 120 }, { 154, 370 } }, + { 42, { 221, 442 }, { 154, 370 } }, + { 220, { 30, 60 }, { 78, 187 } }, + { 220, { 30, 60 }, { 78, 187 } }, + }; + static tFlicette push[4] = { + { 154, { 60, 120 }, { 154, 370 } }, + { 45, { 221, 442 }, { 154, 370 } }, + { 222, { 30, 60 }, { 78, 187 } }, + { 225, { 30, 60 }, { 118, 283 } }, + }; + static tMouse_area mouse_areas[4] = { + { { 60, 120 }, { 154, 370 }, { 125, 250 }, { 174, 418 }, 0, 0, 0, NULL }, + { { 221, 442 }, { 154, 370 }, { 286, 572 }, { 174, 418 }, 1, 0, 0, NULL }, + { { 30, 60 }, { 78, 187 }, { 45, 90 }, { 104, 250 }, -1, 0, 0, UpClickCar }, + { { 30, 60 }, { 118, 283 }, { 45, 90 }, { 145, 348 }, -1, 0, 0, DownClickCar }, + }; + static tInterface_spec interface_spec = { + 0, 236, 62, 0, 0, 0, -1, + { -1, 0 }, { -1, 0 }, { 0, 0 }, { 1, 0 }, { NULL, NULL }, + { -1, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { NULL, NULL }, + { -1, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { UpCar, NULL }, + { -1, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { DownCar, NULL }, + { 1, 1 }, { ChangeCarGoAhead, NULL}, + { 1, 1 }, { NULL, NULL }, + NULL, DrawCar, 0, NULL, NULL, NULL, 0, { 0, 0 }, NULL, 1, 1, + COUNT_OF(flicker_on), flicker_on, flicker_off, push, + COUNT_OF(mouse_areas), mouse_areas, + 0, NULL, + }; int i; int result; int power_up_levels[3]; LOG_TRACE("(%d, %p, %p)", pNet_mode, pCar_index, pNet_game); - NOT_IMPLEMENTED(); + + gChoose_car_net_game = pNet_game; + gChange_race_net_mode = pNet_mode; + gStart_interface_spec = &interface_spec; + for (i = 0; i < gProgram_state.number_of_cars; i++) { + if (gProgram_state.cars_available[i] == *pCar_index) { + gCurrent_car_index = i; + break; + } + } + if (gProgram_state.game_completed) { + gProgram_state.number_of_cars = gNumber_of_racers; + for (i = 0; i < gProgram_state.number_of_cars; i++) { + gProgram_state.cars_available[i] = i; + } + } + for (i = 0; i < gProgram_state.number_of_cars; i++) { + if (gOpponents[gProgram_state.cars_available[i]].stolen_car_image_data == NULL) { + LoadFlicData(gOpponents[gProgram_state.cars_available[i]].stolen_car_flic_name, + &gOpponents[gProgram_state.cars_available[i]].stolen_car_image_data, + &gOpponents[gProgram_state.cars_available[i]].stolen_car_image_data_length); + } else { + MAMSLock((void**)&gOpponents[gProgram_state.cars_available[i]].stolen_car_image_data); + } + } + InitialiseFlicPanel(0, + gCurrent_graf_data->change_car_panel_left, + gCurrent_graf_data->change_car_panel_top, + gCurrent_graf_data->change_car_panel_right - gCurrent_graf_data->change_car_panel_left, + gCurrent_graf_data->change_car_panel_bottom - gCurrent_graf_data->change_car_panel_top); + SetCarFlic(); + if (pNet_mode) { + gTaken_image = LoadPixelmap("TAKEN.PIX"); + } + result = DoInterfaceScreen(&interface_spec, pNet_mode, 0); + if (pNet_mode) { + FadePaletteDown(); + } else { + RunFlic(237); + } + for (i = 0; i < gProgram_state.number_of_cars; i++) { + MAMSUnlock((void**)&gOpponents[gProgram_state.cars_available[i]].stolen_car_image_data); + } + DisposeFlicPanel(0); + if (result == 0) { + if (pNet_mode) { + *pCar_index = gProgram_state.cars_available[gCurrent_race_index]; + } else { + AboutToLoadFirstCar(); + SwitchToRealResolution(); + for (i = 0; i < COUNT_OF(power_up_levels); i++) { + power_up_levels[i] = gProgram_state.current_car.power_up_levels[i]; + } + LoadCar(gOpponents[gProgram_state.cars_available[gCurrent_car_index]].car_file_name, + eDriver_local_human, + &gProgram_state.current_car, + gProgram_state.cars_available[gCurrent_car_index], + gProgram_state.player_name[gProgram_state.frank_or_anniness], + &gOur_car_storage_space); + for (i = 0; i < COUNT_OF(power_up_levels); i++) { + gProgram_state.current_car.power_up_levels[i] = power_up_levels[i]; + } + SwitchToLoresMode(); + SetCarStorageTexturingLevel(&gOur_car_storage_space, GetCarTexturingLevel(), eCTL_full); + DisposeRaceInfo(&gCurrent_race); + SelectOpponents(&gCurrent_race); + LoadRaceInfo(gProgram_state.current_race_index, &gCurrent_race); + } + return 1; + } else { + return 0; + } } // IDA: void __cdecl DoChangeCar() void DoChangeCar() { LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + ChangeCar(0, &gProgram_state.current_car.index, NULL); } // IDA: int __cdecl PartsShopRecommended() diff --git a/src/DETHRACE/common/world.c b/src/DETHRACE/common/world.c index 46463bfb..c487a94d 100644 --- a/src/DETHRACE/common/world.c +++ b/src/DETHRACE/common/world.c @@ -867,7 +867,28 @@ void DisposeFunkotronics(int pOwner) { int i; tFunkotronic_spec* the_funk; LOG_TRACE("(%d)", pOwner); - NOT_IMPLEMENTED(); + + if (gFunkotronics_array == NULL) { + return; + } + for (i = 0; i < gFunkotronics_array_size; i++) { + the_funk = &gFunkotronics_array[i]; + PossibleService(); + if (the_funk->owner == pOwner) { + the_funk->owner = -999; + if (the_funk->proximity_array != NULL) { + BrMemFree(the_funk->proximity_array); + } + if (the_funk->texture_animation_type == eTexture_animation_flic) { + BrMemFree(the_funk->texture_animation_data.flic_info.flic_data); + EndFlic(&the_funk->texture_animation_data.flic_info.flic_descriptor); + BrMemFree(the_funk->material->colour_map->pixels); + the_funk->material->colour_map->pixels = NULL; + BrPixelmapFree(the_funk->material->colour_map); + the_funk->material->colour_map = NULL; + } + } + } } // IDA: void __usercall AddProximityVertex(br_vector3 *pV@, tFunkotronic_spec *pThe_funk@) @@ -1257,7 +1278,17 @@ void DisposeGroovidelics(int pOwner) { int i; tGroovidelic_spec* the_groove; LOG_TRACE("(%d)", pOwner); - NOT_IMPLEMENTED(); + + if (gGroovidelics_array == NULL) { + return; + } + for (i = 0; i < gGroovidelics_array_size; i++) { + the_groove = &gGroovidelics_array[i]; + PossibleService(); + if (the_groove->owner == pOwner) { + the_groove->owner = -999; + } + } } // IDA: tGroovidelic_spec* __cdecl AddNewGroovidelic()