From 9ec9fb008f7108a275f3d97e1d57535990cb504e Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Fri, 16 Sep 2022 05:10:52 +0200 Subject: [PATCH] Implement DoEndSummary2 (aka Damage Gallery) (#152) * Implement DoEndSummary2 (aka Damage Gallery) * Fix warnings emitted by -Wabsolute-value and -Wsometimes-uninitialized --- src/BRSRC13/include/brender/brender.h | 3 + src/DETHRACE/common/racesumm.c | 574 ++++++++++++++++++++++++-- src/DETHRACE/common/raycast.c | 14 +- 3 files changed, 565 insertions(+), 26 deletions(-) diff --git a/src/BRSRC13/include/brender/brender.h b/src/BRSRC13/include/brender/brender.h index fb829827..f9ba88cc 100644 --- a/src/BRSRC13/include/brender/brender.h +++ b/src/BRSRC13/include/brender/brender.h @@ -85,12 +85,15 @@ void BrMatrix34LPNormalise(br_matrix34* A, br_matrix34* B); void BrMatrix34PreRotate(br_matrix34* mat, br_angle r, br_vector3* axis); void BrMatrix34Rotate(br_matrix34* mat, br_angle r, br_vector3* a); void BrMatrix34PreTranslate(br_matrix34* mat, br_scalar x, br_scalar y, br_scalar z); +void BrMatrix34Post(br_matrix34* mat, br_matrix34* A); void BrMatrix34PostShearX(br_matrix34* mat, br_scalar sy, br_scalar sz); void BrMatrix34PostShearY(br_matrix34* mat, br_scalar sx, br_scalar sz); void BrMatrix34PostShearZ(br_matrix34* mat, br_scalar sx, br_scalar sy); +void BrMatrix34PreScale(br_matrix34* mat, br_scalar sx, br_scalar sy, br_scalar sz); void BrMatrix34PreShearX(br_matrix34* mat, br_scalar sy, br_scalar sz); void BrMatrix34PreRotateY(br_matrix34* mat, br_angle ry); void BrMatrix34PreRotateZ(br_matrix34* mat, br_angle rz); +void BrMatrix34RollingBall(br_matrix34* mat, int dx, int dy, int radius); // BrMatrix4 void BrMatrix4Copy(br_matrix4* A, br_matrix4* B); diff --git a/src/DETHRACE/common/racesumm.c b/src/DETHRACE/common/racesumm.c index 9a257bcb..7d518a62 100644 --- a/src/DETHRACE/common/racesumm.c +++ b/src/DETHRACE/common/racesumm.c @@ -2,17 +2,23 @@ #include "brender/brender.h" #include "crush.h" #include "cutscene.h" +#include "displays.h" #include "flicplay.h" #include "globvars.h" +#include "globvrkm.h" #include "globvrpb.h" #include "grafdata.h" #include "graphics.h" #include "harness/config.h" #include "harness/trace.h" +#include "input.h" #include "intrface.h" #include "loading.h" +#include "main.h" #include "network.h" +#include "opponent.h" #include "pd/sys.h" +#include "raycast.h" #include "s3/s3.h" #include "sound.h" #include "utility.h" @@ -473,7 +479,17 @@ void PrepareBoundingRadius__racesumm(br_model* model) { int v; br_vertex* vp; LOG_TRACE("(%p)", model); - NOT_IMPLEMENTED(); + + max = 0.f; + for (v = 0; v < model->nvertices; v++) { + vp = &model->vertices[v]; + d = BrVector3LengthSquared(&vp->p); + if (d > max) { + max = d; + } + } + d = sqrtf(max); + model->radius = d; } // IDA: void __cdecl BuildWrecks() @@ -485,7 +501,63 @@ void BuildWrecks() { br_actor* this_car; tCar_spec* the_car; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + gWreck_count = 0; + position = 0; + gWreck_root = BrActorAllocate(BR_ACTOR_NONE, NULL); + gWreck_camera = BrActorAllocate(BR_ACTOR_CAMERA, NULL); + BrActorAdd(gUniverse_actor, gWreck_root); + BrActorAdd(gWreck_root, gWreck_camera); + memcpy(gWreck_camera->type_data, gCamera_list[1]->type_data, sizeof(br_camera)); + ((br_camera*)gWreck_camera->type_data)->aspect = 2.f; + ((br_camera*)gWreck_camera->type_data)->field_of_view = BR_ANGLE_DEG(55); + BrMatrix34Identity(&gWreck_camera->t.t.mat); + BrVector3SetFloat(&gWreck_camera->t.t.translate.t, 0.f, 0.f, 2.2f); + for (cat = eVehicle_self; cat < eVehicle_rozzer; cat++) { + if (cat == eVehicle_self) { + car_count = 1; + } else { + car_count = GetCarCount(cat); + } + for (i = 0; i < car_count; i++) { + if (cat == eVehicle_self) { + the_car = &gProgram_state.current_car; + } else { + the_car = GetCarSpec(cat, i); + } + this_car = the_car->car_model_actors[the_car->principal_car_actor].actor; + memcpy(&gWreck_array[gWreck_count].original_matrix, &this_car->t.t.mat, sizeof(br_matrix34)); + BrActorRelink(gWreck_root, this_car); + this_car->render_style = BR_RSTYLE_FACES; + gWreck_array[gWreck_count].customised = 0; + gWreck_array[gWreck_count].actor = this_car; + PrepareBoundingRadius__racesumm(this_car->model); + gWreck_array[gWreck_count].scaling_factor = .47f / this_car->model->radius; + gWreck_array[gWreck_count].pos_x = (position % 3) - 1.0f; + gWreck_array[gWreck_count].pos_y = (position / 3) - 0.5f; + this_car->t.t.translate.t.v[0] = 1.5f * gWreck_array[gWreck_count].pos_x; + this_car->t.t.translate.t.v[1] = -1.2f * gWreck_array[gWreck_count].pos_y; + this_car->t.t.translate.t.v[2] = 0.f; + gWreck_array[gWreck_count].car_type = cat; + gWreck_array[gWreck_count].car_index = i; + gWreck_count += 1; + position += 1; + } + } + gWreck_render_area = BrPixelmapAllocateSub( + gBack_screen, + gCurrent_graf_data->wreck_render_x, + gCurrent_graf_data->wreck_render_y, + gCurrent_graf_data->wreck_render_w, + gCurrent_graf_data->wreck_render_h); + gWreck_render_area->origin_x = gWreck_render_area->width / 2; + gWreck_render_area->origin_y = gWreck_render_area->height / 2; + gWreck_z_buffer = BrPixelmapAllocateSub( + gDepth_buffer, + gCurrent_graf_data->wreck_render_x, + gCurrent_graf_data->wreck_render_y, + gCurrent_graf_data->wreck_render_w, + gCurrent_graf_data->wreck_render_h); } // IDA: void __cdecl DisposeWrecks() @@ -497,13 +569,47 @@ void DisposeWrecks() { br_actor* this_car; tCar_spec* the_car; LOG_TRACE("()"); - NOT_IMPLEMENTED(); + + for (cat = eVehicle_self; cat < eVehicle_rozzer; cat++) { + if (cat == eVehicle_self) { + car_count = 1; + } + else { + car_count = GetCarCount(cat); + } + for (i = 0; i < car_count; i++) { + if (cat == eVehicle_self) { + the_car = &gProgram_state.current_car; + } + else { + the_car = GetCarSpec(cat, i); + } + this_car = the_car->car_model_actors[the_car->principal_car_actor].actor; + BrActorRelink(the_car->car_master_actor, this_car); + this_car->render_style = BR_RSTYLE_NONE; + } + } + for (i = 0; i < gWreck_count; i++) { + memcpy(&gWreck_array[i].actor->t.t.mat, &gWreck_array[i].original_matrix, sizeof(br_matrix34)); + } + BrActorRemove(gWreck_root); + BrActorRemove(gWreck_camera); + BrActorFree(gWreck_root); + BrActorFree(gWreck_camera); + gWreck_render_area->pixels = NULL; + gWreck_z_buffer->pixels = NULL; + BrPixelmapFree(gWreck_render_area); + BrPixelmapFree(gWreck_z_buffer); } // IDA: int __usercall MatrixIsIdentity@(br_matrix34 *pMat@) int MatrixIsIdentity(br_matrix34* pMat) { LOG_TRACE("(%p)", pMat); - NOT_IMPLEMENTED(); + + return (pMat->m[0][0] == 1.f && pMat->m[1][1] == 1.f && pMat->m[2][2] == 1.f && + pMat->m[0][1] == 0.f && pMat->m[0][2] == 0.f && + pMat->m[1][0] == 0.f && pMat->m[1][2] == 0.f && + pMat->m[2][0] == 0.f && pMat->m[2][1] == 0.f); } // IDA: void __usercall SpinWrecks(tU32 pFrame_period@) @@ -512,26 +618,74 @@ void SpinWrecks(tU32 pFrame_period) { br_vector3 translation; br_matrix34 old_mat; LOG_TRACE("(%d)", pFrame_period); - NOT_IMPLEMENTED(); + + for (i = 0; i < gWreck_count; i++) { + if (gWreck_array[i].customised == 0) { + BrMatrix34RotateY(&gWreck_array[i].rotation, BR_ANGLE_DEG(.05f * pFrame_period)); + } + BrVector3Copy(&translation, &gWreck_array[i].actor->t.t.translate.t); + BrVector3Set(&gWreck_array[i].actor->t.t.translate.t, 0.f, 0.f, 0.f); + BrMatrix34Post(&gWreck_array[i].actor->t.t.mat, &gWreck_array[i].rotation); + if (!MatrixIsIdentity(&gWreck_array[i].actor->t.t.mat)) { + memcpy(&old_mat, &gWreck_array[i].actor->t.t.mat, sizeof(br_matrix34)); + BrMatrix34LPNormalise(&gWreck_array[i].actor->t.t.mat, &old_mat); + BrMatrix34PostScale(&gWreck_array[i].actor->t.t.mat, + gWreck_array[i].scaling_factor, gWreck_array[i].scaling_factor, gWreck_array[i].scaling_factor); + } + BrVector3Copy(&gWreck_array[i].actor->t.t.translate.t, &translation); + } } // IDA: void __usercall ZoomInTo(int pIndex@, int *pCurrent_choice@, int *pCurrent_mode@) void ZoomInTo(int pIndex, int* pCurrent_choice, int* pCurrent_mode) { LOG_TRACE("(%d, %p, %p)", pIndex, pCurrent_choice, pCurrent_mode); - NOT_IMPLEMENTED(); + + gWreck_zoom_in = pIndex; + gWreck_zoom_out = -1; + gWreck_start_zoom = PDGetTotalTime(); + if (gWreck_selected == 0 && !gUser_interacted) { + *pCurrent_choice = 2; + *pCurrent_mode = 1; + } else { + *pCurrent_choice = 0; + *pCurrent_mode = 0; + } + RemoveTransientBitmaps(1); + TurnFlicTransparencyOn(); + RunFlicAt(325, 9, 174); + TurnFlicTransparencyOff(); + gBack_button_ptr->new_choice = -1; + gBack_button_ptr->new_mode = -1; } // IDA: void __usercall ZoomOutTo(int pIndex@, int *pCurrent_choice@, int *pCurrent_mode@) void ZoomOutTo(int pIndex, int* pCurrent_choice, int* pCurrent_mode) { LOG_TRACE("(%d, %p, %p)", pIndex, pCurrent_choice, pCurrent_mode); - NOT_IMPLEMENTED(); + + gWreck_zoom_out = pIndex; + gWreck_zoom_in = -1; + gWreck_start_zoom = PDGetTotalTime(); + RemoveTransientBitmaps(1); + TurnFlicTransparencyOn(); + RunFlicAt(326, 9, 174); + TurnFlicTransparencyOff(); + memcpy(gBack_button_ptr, &gOld_back_button, sizeof(tMouse_area)); + *pCurrent_choice = 1; + *pCurrent_mode = 1; } // IDA: int __cdecl WreckPick(br_actor *pActor, br_model *pModel, br_material *pMaterial, br_vector3 *pRay_pos, br_vector3 *pRay_dir, br_scalar pNear, br_scalar pFar, void *pArg) int WreckPick(br_actor* pActor, br_model* pModel, br_material* pMaterial, br_vector3* pRay_pos, br_vector3* pRay_dir, br_scalar pNear, br_scalar pFar, void* pArg) { int i; LOG_TRACE("(%p, %p, %p, %p, %p, %f, %f, %p)", pActor, pModel, pMaterial, pRay_pos, pRay_dir, pNear, pFar, pArg); - NOT_IMPLEMENTED(); + + for (i = 0; i < gWreck_count; i++) { + if (gWreck_array[i].actor == pActor) { + gWreck_selected = i; + return 1; + } + } + return 0; } // IDA: int __usercall CastSelectionRay@(int *pCurrent_choice@, int *pCurrent_mode@) @@ -542,13 +696,67 @@ int CastSelectionRay(int* pCurrent_choice, int* pCurrent_mode) { int result; br_scalar inv_wreck_pick_scale_factor; LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode); - NOT_IMPLEMENTED(); + + if (!gMouse_in_use) { + return 0; + } + if (*pCurrent_choice != 0) { + return 0; + } + if (*pCurrent_mode != 0) { + return 0; + } + if (gWreck_zoomed_in >= 0) { + return 0; + } + if (gWreck_zoom_out >= 0) { + return 0; + } + if (gWreck_zoom_in >= 0) { + return 0; + } + + inv_wreck_pick_scale_factor = 0.5f; + GetMousePosition(&mouse_x, &mouse_y); + if (gReal_graf_data_index != 0) { + mouse_x = 2 * mouse_x; + mouse_y = 2 * mouse_y + 40; + } + for (i = 0; i < gWreck_count; i++) { + BrMatrix34PreScale(&gWreck_array[i].actor->t.t.mat, 2.f, 2.f, 2.f); + } + result = DRScenePick2DXY(gWreck_root, gWreck_camera, gRender_screen, + mouse_x - gBack_screen->width / 2, + mouse_y - gBack_screen->height / 2, + WreckPick, + NULL); + for (i = 0; i < gWreck_count; i++) { + BrMatrix34PreScale(&gWreck_array[i].actor->t.t.mat, + inv_wreck_pick_scale_factor, inv_wreck_pick_scale_factor, inv_wreck_pick_scale_factor); + } + return result; } // IDA: int __usercall DamageScrnExit@(int *pCurrent_choice@, int *pCurrent_mode@) int DamageScrnExit(int* pCurrent_choice, int* pCurrent_mode) { LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode); - NOT_IMPLEMENTED(); + + if (gProgram_state.prog_status == eProg_idling) { + return 1; + } + else { + if (gWreck_gallery_start == 0) { + gWreck_gallery_start = PDGetTotalTime(); + } + else if (!gDone_initial && gWreck_selected == 0) { + if (PDGetTotalTime() - gWreck_gallery_start > 1500) { + ZoomOutTo(gWreck_selected, pCurrent_choice, pCurrent_mode); + gDone_initial = 1; + } + } + CastSelectionRay(pCurrent_choice, pCurrent_mode); + return 0; + } } // IDA: void __usercall DamageScrnDraw(int pCurrent_choice@, int pCurrent_mode@) @@ -564,21 +772,153 @@ void DamageScrnDraw(int pCurrent_choice, int pCurrent_mode) { br_actor* sel_actor; char* name; LOG_TRACE("(%d, %d)", pCurrent_choice, pCurrent_mode); - NOT_IMPLEMENTED(); + + if (((pCurrent_choice == 0 && pCurrent_mode == 0) || !gDone_initial) && (gWreck_zoomed_in < 0 && gWreck_selected >= 0)) { + sel_actor = BrActorAllocate(BR_ACTOR_MODEL, NULL); + sel_actor->render_style = BR_RSTYLE_BOUNDING_EDGES; + sel_actor->render_style = BR_RSTYLE_NONE; // FIXME: remove this line once BR_RSTYLE_BOUNDING_EDGES rener style has been implemente + sel_actor->model = gWreck_array[gWreck_selected].actor->model; + BrActorAdd(gWreck_array[gWreck_selected].actor, sel_actor); + } else { + sel_actor = NULL; + } + the_time = PDGetTotalTime(); + SpinWrecks(the_time - gLast_wreck_draw); + gLast_wreck_draw = the_time; + if (gWreck_zoom_out >= 0 || gWreck_zoom_in >= 0) { + if (gWreck_start_zoom == 0) { + gWreck_start_zoom = the_time; + } + finished = the_time - gWreck_start_zoom > 1000; + if (finished) { + the_time = gWreck_start_zoom + 1000; + } + if (gWreck_zoom_out < 0) { + camera_movement.v[0] = (1.f - (the_time - gWreck_start_zoom) / 1000.f) * gWreck_array[gWreck_zoom_in].actor->t.t.translate.t.v[0]; + camera_movement.v[1] = (1.f - (the_time - gWreck_start_zoom) / 1000.f) * gWreck_array[gWreck_zoom_in].actor->t.t.translate.t.v[1]; + camera_movement.v[2] = (1.f - (the_time - gWreck_start_zoom) / 1000.f) * -1.45f; + if (finished) { + gWreck_zoom_in = -1; + gWreck_zoomed_in = -1; + } + } else { + camera_movement.v[0] = (the_time - gWreck_start_zoom) / 1000.f * gWreck_array[gWreck_zoom_out].actor->t.t.translate.t.v[0]; + camera_movement.v[1] = (the_time - gWreck_start_zoom) / 1000.f * gWreck_array[gWreck_zoom_out].actor->t.t.translate.t.v[1]; + camera_movement.v[2] = (the_time - gWreck_start_zoom) / 1000.f * -1.45f; + if (finished) { + gWreck_zoomed_in = gWreck_zoom_out; + gWreck_zoom_out = -1; + } + } + gWreck_camera->t.t.translate.t.v[0] = camera_movement.v[0]; + gWreck_camera->t.t.translate.t.v[1] = camera_movement.v[1]; + gWreck_camera->t.t.translate.t.v[2] = camera_movement.v[2] + 2.2f; + } + EnsureRenderPalette(); + EnsurePaletteUp(); + BrPixelmapFill(gWreck_z_buffer, 0xffffffff); + BrPixelmapFill(gWreck_render_area, BR_COLOUR_RGBA(0xb0, 0xb0, 0xb0, 0xb0)); + + rows = gWreck_render_area->height / 15.f; + columns = gWreck_render_area->width / 15.f; + for (v = 0; v <= rows; v++) { + BrPixelmapLine(gWreck_render_area, + -gWreck_render_area->origin_x, + gWreck_render_area->height / 2.f - 15.f * (rows / 2.f - v) - gWreck_render_area->origin_y, + gWreck_render_area->width - gWreck_render_area->origin_x, + gWreck_render_area->height / 2.f - 15.f * (rows / 2.f - v) - gWreck_render_area->origin_y, + 8); + } + for (h = 0; h <= columns; h++) { + BrPixelmapLine(gWreck_render_area, + gWreck_render_area->width / 2.f - 15.f * (columns / 2.f - h) - gWreck_render_area->origin_x, + -gWreck_render_area->origin_y, + gWreck_render_area->width / 2.f - 15.f * (columns / 2.f - h) - gWreck_render_area->origin_x, + gWreck_render_area->height - gWreck_render_area->origin_y, + 8); + } + BrZbSceneRenderBegin(gUniverse_actor, gWreck_camera, gWreck_render_area, gWreck_z_buffer); + BrZbSceneRenderAdd(gWreck_root); + BrZbSceneRenderEnd(); + if (sel_actor != NULL) { + BrActorRemove(sel_actor); + sel_actor->model = NULL; + BrActorFree(sel_actor); + } + BrPixelmapRectangleFill(gBack_screen, + gCurrent_graf_data->wreck_name_left, + gCurrent_graf_data->wreck_name_top, + gCurrent_graf_data->wreck_name_right - gCurrent_graf_data->wreck_name_left, + gCurrent_graf_data->wreck_name_bottom - gCurrent_graf_data->wreck_name_top, + 0); + if (gWreck_selected >= 0 && (gWreck_zoomed_in >= 0 || pCurrent_mode == 0)) { + name = GetDriverName(gWreck_array[gWreck_selected].car_type, + gWreck_array[gWreck_selected].car_index); + TransBrPixelmapText(gBack_screen, + (gCurrent_graf_data->wreck_name_left + gCurrent_graf_data->wreck_name_right - BrPixelmapTextWidth(gBack_screen, gFont_7, name)) / 2, + gCurrent_graf_data->wreck_name_base_line, + 84, + gFont_7, + (signed char*)name); // FIXME: remove (signed char*) cast + } } // IDA: int __usercall DamageScrnLeft@(int *pCurrent_choice@, int *pCurrent_mode@) int DamageScrnLeft(int* pCurrent_choice, int* pCurrent_mode) { int i; LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode); - NOT_IMPLEMENTED(); + + gDone_initial = 1; + DRS3StartSound(gEffects_outlet, 3000); + if (*pCurrent_mode == 0 && gWreck_zoomed_in < 0) { + if (gWreck_selected < 0) { + gWreck_selected = gWreck_count - 1; + } else if (gWreck_selected != 0 && gWreck_array[gWreck_selected - 1].pos_y == gWreck_array[gWreck_selected]. pos_y) { + gWreck_selected--; + } else { + for (i = gWreck_count - 1; i >= 0; i--) { + if (gWreck_array[i].pos_y == gWreck_array[gWreck_selected].pos_y) { + gWreck_selected = i; + break; + } + } + } + } else if (gWreck_zoomed_in >= 0) { + *pCurrent_choice = *pCurrent_choice + 1; + if (*pCurrent_choice == 3) { + *pCurrent_choice = 1; + } + } + return 1; } // IDA: int __usercall DamageScrnRight@(int *pCurrent_choice@, int *pCurrent_mode@) int DamageScrnRight(int* pCurrent_choice, int* pCurrent_mode) { int i; LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode); - NOT_IMPLEMENTED(); + + gDone_initial = 1; + DRS3StartSound(gEffects_outlet, 3000); + if (*pCurrent_mode == 0 && gWreck_zoomed_in < 0) { + if (gWreck_selected < 0) { + gWreck_selected = 0; + } else if (gWreck_selected - 1 != gWreck_count && gWreck_array[gWreck_selected + 1].pos_y == gWreck_array[gWreck_selected]. pos_y) { + gWreck_selected++; + } else { + for (i = 0; i < gWreck_count; i++) { + if (gWreck_array[i].pos_y == gWreck_array[gWreck_selected].pos_y) { + gWreck_selected = i; + break; + } + } + } + } else if (gWreck_zoomed_in >= 0) { + *pCurrent_choice = *pCurrent_choice + 1; + if (*pCurrent_choice == 3) { + *pCurrent_choice = 1; + } + } + return 1; } // IDA: int __usercall DamageScrnUp@(int *pCurrent_choice@, int *pCurrent_mode@) @@ -588,7 +928,46 @@ int DamageScrnUp(int* pCurrent_choice, int* pCurrent_mode) { int new_difference; int new_selection; LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode); - NOT_IMPLEMENTED(); + + gDone_initial = 1; + DRS3StartSound(gEffects_outlet, 3000); + if (*pCurrent_mode != 0) { + *pCurrent_mode = 0; + *pCurrent_choice = 0; + if (gWreck_zoomed_in < 0) { + gWreck_selected = gWreck_count + -1; + } + } else { + if (gWreck_selected < 0) { + if (gWreck_zoomed_in < 0) { + gWreck_selected = gWreck_count - 1; + } + } else if (gWreck_zoomed_in >= 0) { + *pCurrent_mode = 1; + *pCurrent_choice = 1; + } else if (gWreck_array[gWreck_selected].pos_y == gWreck_array[0].pos_y) { + *pCurrent_mode = 1; + *pCurrent_choice = 2; + } else { + new_difference = 1000; + new_selection = gWreck_selected; + for (i = 0; i < gWreck_count; i++) { + if (gWreck_array[gWreck_selected].pos_y - 1.f == gWreck_array[i].pos_y) { + if (gWreck_array[i].pos_x == gWreck_array[gWreck_selected].pos_x) { + new_selection = i; + break; + } + difference = abs(gWreck_array[i].pos_x - gWreck_array[gWreck_selected].pos_x); + if (difference < new_difference) { + new_selection = i; + new_difference = difference; + } + } + } + gWreck_selected = new_selection; + } + } + return 1; } // IDA: int __usercall DamageScrnDown@(int *pCurrent_choice@, int *pCurrent_mode@) @@ -598,13 +977,68 @@ int DamageScrnDown(int* pCurrent_choice, int* pCurrent_mode) { int new_difference; int new_selection; LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode); - NOT_IMPLEMENTED(); + + gDone_initial = 1; + DRS3StartSound(gEffects_outlet, 3000); + if (*pCurrent_mode != 0) { + *pCurrent_mode = 0; + *pCurrent_choice = 0; + if (gWreck_zoomed_in < 0) { + for (i = gWreck_count - 1; i >= 0; i--) { + if (gWreck_array[i].pos_y == gWreck_array[0].pos_y) { + gWreck_selected = i; + break; + } + } + } + } else { + if (gWreck_selected < 0) { + gWreck_selected = 0; + } else if (gWreck_zoomed_in >= 0) { + *pCurrent_mode = 1; + *pCurrent_choice = 1; + } else if (gWreck_array[gWreck_selected].pos_y == gWreck_array[gWreck_count - 1].pos_y) { + *pCurrent_mode = 1; + *pCurrent_choice = 2; + } else { + new_difference = 1000; + new_selection = gWreck_selected; + for (i = 0; i < gWreck_count; i++) { + if (gWreck_array[gWreck_selected].pos_y + 1.f == gWreck_array[i].pos_y) { + if (gWreck_array[i].pos_x == gWreck_array[gWreck_selected].pos_x) { + new_selection = i; + break; + } + difference = abs((int)(gWreck_array[i].pos_x - gWreck_array[gWreck_selected].pos_x)); + if (difference < new_difference) { + new_selection = i; + new_difference = difference; + } + } + } + gWreck_selected = new_selection; + } + } + return 1; } // IDA: int __usercall DamageScrnGoHead@(int *pCurrent_choice@, int *pCurrent_mode@) int DamageScrnGoHead(int* pCurrent_choice, int* pCurrent_mode) { LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode); - NOT_IMPLEMENTED(); + + gDone_initial = 1; + if (*pCurrent_choice == 2) { + return 1; + } else if (gWreck_zoomed_in < 0) { + if (*pCurrent_choice == 0 && gWreck_selected >= 0) { + ZoomOutTo(gWreck_selected, pCurrent_choice, pCurrent_mode); + gUser_interacted = 1; + } + } else if (*pCurrent_choice == 1) { + ZoomInTo(gWreck_selected, pCurrent_choice, pCurrent_mode); + } + gDone_initial = 1; + return 0; } // IDA: int __usercall ClickDamage@(int *pCurrent_choice@, int *pCurrent_mode@, int pX_offset@, int pY_offset@) @@ -614,26 +1048,116 @@ int ClickDamage(int* pCurrent_choice, int* pCurrent_mode, int pX_offset, int pY_ int old_mouse_x; int old_mouse_y; LOG_TRACE("(%p, %p, %d, %d)", pCurrent_choice, pCurrent_mode, pX_offset, pY_offset); - NOT_IMPLEMENTED(); + +#if defined(DETHRACE_FIX_BUGS) + old_mouse_x = 0; // Fixes warning caused by -Wsometimes-uninitialized + old_mouse_y = 0; // Fixes warning caused by -Wsometimes-uninitialized +#endif + GetMousePosition(&old_mouse_y, &old_mouse_y); + if (gWreck_zoomed_in < 0) { + if (CastSelectionRay(pCurrent_choice, pCurrent_mode)) { + gUser_interacted = 1; + return 1; + } else { + return 0; + } + } else { + while (1) { + GetMousePosition(&mouse_x, &mouse_y); + BrMatrix34RollingBall(&gWreck_array[gWreck_zoomed_in].rotation, mouse_x - old_mouse_x, old_mouse_y - mouse_y, 50); + old_mouse_x = mouse_x; + old_mouse_y = mouse_y; + gWreck_array[gWreck_zoomed_in].customised = 1; + RemoveTransientBitmaps(1); + DamageScrnDraw(0, 0); + ProcessFlicQueue(gFrame_period); + DoMouseCursor(); + PDScreenBufferSwap(0); + ServiceGame(); + if (!EitherMouseButtonDown()) { + break; + } + } + return 0; + } } // IDA: int __usercall DamageScrnDone@(int pCurrent_choice@, int pCurrent_mode@, int pGo_ahead@, int pEscaped@, int pTimed_out) int DamageScrnDone(int pCurrent_choice, int pCurrent_mode, int pGo_ahead, int pEscaped, int pTimed_out) { LOG_TRACE("(%d, %d, %d, %d, %d)", pCurrent_choice, pCurrent_mode, pGo_ahead, pEscaped, pTimed_out); - NOT_IMPLEMENTED(); + + if (pTimed_out) { + pCurrent_choice = 2; + } + return pCurrent_choice; } // IDA: tSO_result __cdecl DoEndRaceSummary2() tSO_result DoEndRaceSummary2() { - static tFlicette flicker_on[3]; - static tFlicette flicker_off[3]; - static tFlicette push[3]; - static tMouse_area mouse_areas[3]; - static tInterface_spec interface_spec; + static tFlicette flicker_on[3] = { + { -1, { 0, 0 }, { 0, 0 } }, + { 321, { 9, 18 }, { 174, 418 } }, + { 321, { 247, 494 }, { 174, 418 } }, + }; + static tFlicette flicker_off[3] = { + { -1, { 0, 0 }, { 0, 0 } }, + { 322, { 9, 18 }, { 174, 418 } }, + { 322, { 247, 494 }, { 174, 418 } }, + }; + static tFlicette push[3] = { + { -1, { 0, 0 }, { 0, 0 } }, + { 324, { 9, 18 }, { 174, 418 } }, + { 323, { 247, 494 }, { 174, 418 } }, + }; + static tMouse_area mouse_areas[3] = { + { { 11, 22 }, { 20, 48 }, { 309, 618 }, { 169, 406 }, 0, 0, 0, ClickDamage }, + { { 9, 18 }, { 174, 418 }, { 72, 144 }, { 194, 466 }, 1, 1, 0, NULL }, + { { 247, 494 }, { 174, 418 }, { 310, 620 }, { 194, 466 }, 2, 1, 0, NULL }, + }; + static tInterface_spec interface_spec = { + 1, 320, 0, -1, -1, -1, -1, + {-1, -1}, {0, 0}, {0, 0}, {0, 2}, {DamageScrnLeft,DamageScrnLeft}, + {-1, -1}, {0, 0}, {0, 0}, {0, 2}, {DamageScrnRight, DamageScrnRight}, + {1, 0}, {0, 0}, {1, 0}, {2, 0}, {DamageScrnUp, DamageScrnUp}, + {1,0}, {0, 0}, {1, 0}, {2, 0}, {DamageScrnDown, DamageScrnDown}, + {1, 1}, {DamageScrnGoHead, DamageScrnGoHead}, + {1, 1}, {NULL, NULL}, + DamageScrnExit, DamageScrnDraw, + 20000, NULL, NULL, DamageScrnDone, 0, + {0, 0}, NULL, 2, 1, + COUNT_OF(flicker_on), flicker_on, flicker_off, push, + COUNT_OF(mouse_areas), mouse_areas, + 0, NULL + }; int result; LOG_TRACE("()"); - STUB(); + if (gAusterity_mode) { + return eSO_continue; + } + NetPlayerStatusChanged(ePlayer_status_wrecks_gallery); + gBack_button_ptr = &mouse_areas[1]; + memcpy(&gOld_back_button, &mouse_areas[1], sizeof(tMouse_area)); + gOld_back_button.new_choice = 1; + gOld_back_button.new_mode = 1; + memcpy(gBack_button_ptr, &gOld_back_button, sizeof(tMouse_area)); + BuildWrecks(); + gWreck_zoom_out = -1; + gWreck_zoom_in = -1; + gWreck_start_zoom = 0; + gWreck_zoomed_in = -1; + gWreck_selected = 0; + gUser_interacted = 0; + gDone_initial = 0; + TurnOnPaletteConversion(); + gWreck_gallery_start = 0; + result = DoInterfaceScreen(&interface_spec, 0, 2); + NetPlayerStatusChanged(ePlayer_status_loading); + TurnOffPaletteConversion(); + DisposeWrecks(); + if (result < 0) { + return eSO_main_menu_invoked; + } return eSO_continue; } @@ -690,7 +1214,7 @@ tSO_result DoEndRaceSummary(int* pFirst_summary_done, tRace_result pRace_result) tSO_result result; LOG_TRACE("(%p, %d)", pFirst_summary_done, pRace_result); - if (harness_game_info.mode == eGame_carmageddon_demo || harness_game_info.mode == eGame_carmageddon_demo) { + if (harness_game_info.mode == eGame_carmageddon_demo || harness_game_info.mode == eGame_splatpack_demo) { gRank_etc_munged = 1; DoEndRaceSummary2(); return eSO_continue; diff --git a/src/DETHRACE/common/raycast.c b/src/DETHRACE/common/raycast.c index bacc2113..57115c4f 100644 --- a/src/DETHRACE/common/raycast.c +++ b/src/DETHRACE/common/raycast.c @@ -227,7 +227,19 @@ int DRScenePick2DXY(br_actor* world, br_actor* camera, br_pixelmap* viewport, in br_camera* camera_data; br_angle view_over_2; LOG_TRACE("(%p, %p, %p, %d, %d, %p, %p)", world, camera, viewport, pick_x, pick_y, callback, arg); - NOT_IMPLEMENTED(); + + camera_data = camera->type_data; + DRActorToRoot(camera, world, &camera_tfm); + BrMatrix34Inverse(&gPick_model_to_view__raycast, &camera_tfm); + view_over_2 = camera_data->field_of_view / 2; + cos_angle = BR_COS(view_over_2); + sin_angle = BR_SIN(view_over_2); + scale = cos_angle / sin_angle; + BrMatrix34PostScale(&gPick_model_to_view__raycast, scale / camera_data->aspect, scale, 1.f); + BrMatrix34PostShearZ(&gPick_model_to_view__raycast, + 2 * pick_x / (float)viewport->width, + -2 * pick_y / (float)viewport->height); + return ActorPick2D(world, model_unk1, material_unk1, callback, arg); } // IDA: int __usercall DRScenePick2D@(br_actor *world@, br_actor *camera@, dr_pick2d_cbfn *callback@, void *arg@)