2828 lines
108 KiB
C
2828 lines
108 KiB
C
#include "racestrt.h"
|
|
#include "brender.h"
|
|
#include "cutscene.h"
|
|
#include "displays.h"
|
|
#include "drmem.h"
|
|
#include "errors.h"
|
|
#include "flicplay.h"
|
|
#include "globvars.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 "netgame.h"
|
|
#include "network.h"
|
|
#include "newgame.h"
|
|
#include "opponent.h"
|
|
#include "pd/sys.h"
|
|
#include "racestrt.h"
|
|
#include "sound.h"
|
|
#include "structur.h"
|
|
#include "utility.h"
|
|
#include "world.h"
|
|
#include <stdlib.h>
|
|
|
|
int gGrid_number_colour[4] = { 49u, 201u, 1u, 201u };
|
|
int gJust_bought_part;
|
|
tU32 gLast_host_query;
|
|
br_pixelmap* gDead_car;
|
|
int gFade_away_parts_shop;
|
|
tU32 gDare_start_time;
|
|
int gRefund_rate;
|
|
int gSwap_grid_2;
|
|
int gSwap_grid_1;
|
|
int gChange_race_net_mode;
|
|
tParts_category gPart_category;
|
|
tU32 gNet_synch_start;
|
|
tNet_game_details* gChoose_car_net_game;
|
|
int gPart_index;
|
|
int gChallenger_index__racestrt; // suffix added to avoid duplicate symbol
|
|
tGrid_draw gDraw_grid_status;
|
|
tNet_sequence_type gNet_race_sequence__racestrt; // suffix added to avoid duplicate symbol
|
|
br_pixelmap* gTaken_image;
|
|
int gGrid_number_x_coords[31];
|
|
int gGrid_transition_stage;
|
|
int gGrid_y_adjust;
|
|
br_pixelmap* gBullet_image;
|
|
br_pixelmap* gDeceased_image;
|
|
int gBest_pos_available;
|
|
int gChallenger_position;
|
|
int gOpponent_index;
|
|
int gChallenge_time;
|
|
int gOriginal_position;
|
|
int gCurrent_race_index;
|
|
tInterface_spec* gStart_interface_spec;
|
|
int gCurrent_car_index;
|
|
int gOur_starting_position;
|
|
|
|
// IDA: void __usercall DrawRaceList(int pOffset@<EAX>)
|
|
void DrawRaceList(int pOffset) {
|
|
int i;
|
|
int font_height;
|
|
int pitch;
|
|
int y;
|
|
int left_most;
|
|
int right_most;
|
|
int rank_colour;
|
|
int text_colour;
|
|
int box_bot;
|
|
int text_width;
|
|
int text_x;
|
|
char rank_str[256];
|
|
LOG_TRACE("(%d)", pOffset);
|
|
|
|
left_most = (gCurrent_graf_data->choose_race_rank_right - 2 * gBig_font->width[48] + gCurrent_graf_data->choose_race_left) / 2;
|
|
right_most = gCurrent_graf_data->choose_race_right - (left_most - gCurrent_graf_data->choose_race_left);
|
|
BrPixelmapRectangleFill(gBack_screen,
|
|
left_most,
|
|
gCurrent_graf_data->choose_race_y_top,
|
|
gCurrent_graf_data->choose_race_right - gCurrent_graf_data->choose_race_left - 2 * (left_most - gCurrent_graf_data->choose_race_left),
|
|
gCurrent_graf_data->choose_race_y_bottom - gCurrent_graf_data->choose_race_y_top,
|
|
0);
|
|
pitch = gCurrent_graf_data->choose_race_y_pitch;
|
|
for (i = 0; i < gNumber_of_races; i++) {
|
|
y = pitch * i + gCurrent_graf_data->choose_race_curr_y - pOffset;
|
|
if (gCurrent_graf_data->choose_race_y_top <= (y - (TranslationMode() ? 2 : 0)) && (y + gBig_font->glyph_y) < gCurrent_graf_data->choose_race_line_y) {
|
|
if ((gProgram_state.rank > gRace_list[i].rank_required || gProgram_state.rank < gRace_list[i].best_rank) && !gProgram_state.game_completed && !gChange_race_net_mode) {
|
|
rank_colour = 44;
|
|
text_colour = 49;
|
|
} else if (gCurrent_graf_data->choose_race_curr_y == y) {
|
|
rank_colour = 5;
|
|
text_colour = 1;
|
|
} else {
|
|
rank_colour = 198;
|
|
text_colour = 201;
|
|
}
|
|
if (!gChange_race_net_mode) {
|
|
sprintf(rank_str, "%2d", gRace_list[i].rank_required);
|
|
TransBrPixelmapText(gBack_screen,
|
|
gCurrent_graf_data->choose_race_rank_right - BrPixelmapTextWidth(gBack_screen, gBig_font, rank_str),
|
|
y,
|
|
rank_colour,
|
|
gBig_font,
|
|
rank_str);
|
|
}
|
|
TransBrPixelmapText(gBack_screen,
|
|
gCurrent_graf_data->choose_race_name_left,
|
|
y,
|
|
text_colour,
|
|
gBig_font,
|
|
gRace_list[i].name);
|
|
if (gRace_list[i].been_there_done_that && gBullet_image != NULL) {
|
|
#ifdef DETHRACE_3DFX_PATCH
|
|
DRPixelmapRectangleCopy(
|
|
#else
|
|
BrPixelmapRectangleCopy(
|
|
#endif
|
|
gBack_screen,
|
|
gCurrent_graf_data->choose_race_bullet_left,
|
|
y + (gBig_font->glyph_y - gBullet_image->height) / 2,
|
|
gBullet_image,
|
|
0,
|
|
0,
|
|
gBullet_image->width,
|
|
gBullet_image->height);
|
|
}
|
|
}
|
|
}
|
|
if (gChange_race_net_mode) {
|
|
strcpy(rank_str, GetMiscString(gNet_race_sequence__racestrt == 1 ? kMiscString_SUBSEQUENT_RACES_WILL_BE_RANDOM : kMiscString_RACES_WILL_CONTINUE_DOWN_THIS_LIST));
|
|
TransBrPixelmapText(gBack_screen,
|
|
(right_most + left_most - BrPixelmapTextWidth(gBack_screen, gBig_font, rank_str)) / 2,
|
|
gCurrent_graf_data->choose_race_current_text_y,
|
|
5,
|
|
gBig_font,
|
|
rank_str);
|
|
} else {
|
|
sprintf(rank_str, "%s%d", GetMiscString(kMiscString_YourCurrentRankIs), gProgram_state.rank);
|
|
text_x = (gCurrent_graf_data->choose_race_left + gCurrent_graf_data->choose_race_right) / 2 - BrPixelmapTextWidth(gBack_screen, gBig_font, rank_str) / 2;
|
|
TransBrPixelmapText(gBack_screen,
|
|
text_x,
|
|
gCurrent_graf_data->choose_race_current_text_y,
|
|
3,
|
|
gBig_font,
|
|
GetMiscString(kMiscString_YourCurrentRankIs));
|
|
sprintf(rank_str, "%d", gProgram_state.rank);
|
|
TransBrPixelmapText(gBack_screen,
|
|
text_x + BrPixelmapTextWidth(gBack_screen, gBig_font, GetMiscString(kMiscString_YourCurrentRankIs)),
|
|
gCurrent_graf_data->choose_race_current_text_y,
|
|
5,
|
|
gBig_font,
|
|
rank_str);
|
|
}
|
|
BrPixelmapLine(gBack_screen,
|
|
left_most,
|
|
gCurrent_graf_data->choose_race_line_y,
|
|
right_most,
|
|
gCurrent_graf_data->choose_race_line_y,
|
|
6);
|
|
DrawRectangle(gBack_screen,
|
|
left_most,
|
|
gCurrent_graf_data->choose_race_box_top - 1,
|
|
right_most,
|
|
2 * gCurrent_graf_data->choose_race_curr_y - gCurrent_graf_data->choose_race_box_top + gBig_font->glyph_y,
|
|
3);
|
|
PDScreenBufferSwap(0);
|
|
}
|
|
|
|
// IDA: void __usercall MoveRaceList(int pFrom@<EAX>, int pTo@<EDX>, tS32 pTime_to_move@<EBX>)
|
|
void MoveRaceList(int pFrom, int pTo, tS32 pTime_to_move) {
|
|
tS32 start_time;
|
|
tS32 the_time;
|
|
int move_distance;
|
|
int pitch;
|
|
LOG_TRACE("(%d, %d, %d)", pFrom, pTo, pTime_to_move);
|
|
|
|
pitch = gCurrent_graf_data->choose_race_y_pitch;
|
|
start_time = PDGetTotalTime();
|
|
while (1) {
|
|
the_time = PDGetTotalTime();
|
|
if (start_time + pTime_to_move <= the_time)
|
|
break;
|
|
DrawRaceList((the_time - start_time) * (pTo - pFrom) * pitch / pTime_to_move + pitch * pFrom);
|
|
}
|
|
DrawRaceList(pitch * pTo);
|
|
}
|
|
|
|
// IDA: int __usercall UpRace@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int UpRace(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
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(gEffects_outlet, 3000);
|
|
if (gCurrent_race_index != 0 && (gRace_list[gCurrent_race_index - 1].best_rank <= gProgram_state.rank || gProgram_state.game_completed || gChange_race_net_mode)) {
|
|
RemoveTransientBitmaps(1);
|
|
MoveRaceList(gCurrent_race_index, gCurrent_race_index - 1, 150);
|
|
gCurrent_race_index--;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall DownRace@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int DownRace(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
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(gEffects_outlet, 3000);
|
|
if (gCurrent_race_index < gNumber_of_races - 1 && (gProgram_state.rank <= gRace_list[gCurrent_race_index + 1].rank_required || gProgram_state.game_completed || gChange_race_net_mode)) {
|
|
RemoveTransientBitmaps(1);
|
|
MoveRaceList(gCurrent_race_index, gCurrent_race_index + 1, 150);
|
|
gCurrent_race_index++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall ClickOnRace@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>, int pX_offset@<EBX>, int pY_offset@<ECX>)
|
|
int ClickOnRace(int* pCurrent_choice, int* pCurrent_mode, int pX_offset, int pY_offset) {
|
|
int x_coord;
|
|
int y_coord;
|
|
int race_delta;
|
|
LOG_TRACE("(%p, %p, %d, %d)", pCurrent_choice, pCurrent_mode, pX_offset, pY_offset);
|
|
|
|
GetMousePosition(&x_coord, &y_coord);
|
|
race_delta = (y_coord - (gCurrent_graf_data->choose_race_curr_y - 5 * (gCurrent_graf_data->choose_race_y_pitch / 2) + gBig_font->glyph_y / 2)) / gCurrent_graf_data->choose_race_y_pitch - 2;
|
|
if (race_delta >= -2 && race_delta <= -1) {
|
|
do {
|
|
UpRace(pCurrent_choice, pCurrent_mode);
|
|
race_delta++;
|
|
} while (race_delta != 0);
|
|
} else if (race_delta > 0 && race_delta < 3) {
|
|
do {
|
|
DownRace(pCurrent_choice, pCurrent_mode);
|
|
race_delta--;
|
|
} while (race_delta != 0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall UpClickRace@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>, int pX_offset@<EBX>, int pY_offset@<ECX>)
|
|
int UpClickRace(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);
|
|
|
|
UpRace(pCurrent_choice, pCurrent_mode);
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall DownClickRace@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>, int pX_offset@<EBX>, int pY_offset@<ECX>)
|
|
int DownClickRace(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);
|
|
|
|
DownRace(pCurrent_choice, pCurrent_mode);
|
|
return 0;
|
|
}
|
|
|
|
// IDA: void __cdecl StartChangeRace()
|
|
void StartChangeRace(void) {
|
|
LOG_TRACE("()");
|
|
|
|
MoveRaceList(-3, gCurrent_race_index, 400);
|
|
}
|
|
|
|
// IDA: int __usercall ChangeRace@<EAX>(int *pRace_index@<EAX>, int pNet_mode@<EDX>, tNet_sequence_type pNet_race_sequence@<EBX>)
|
|
int ChangeRace(int* pRace_index, int pNet_mode, tNet_sequence_type pNet_race_sequence) {
|
|
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[5] = {
|
|
{ { 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, UpClickRace },
|
|
{ { 30, 60 }, { 118, 283 }, { 45, 90 }, { 145, 348 }, -1, 0, 0, DownClickRace },
|
|
{ { 66, 132 }, { 33, 79 }, { 278, 556 }, { 144, 346 }, -1, 0, 0, ClickOnRace },
|
|
};
|
|
static tInterface_spec interface_spec = {
|
|
0, 230, 60, 231, 231, 231, 6,
|
|
{ -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 }, { UpRace, NULL },
|
|
{ -1, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { DownRace, NULL },
|
|
{ 1, 1 }, { NULL, NULL }, { 1, 1 }, { NULL, NULL },
|
|
NULL, NULL, 0, NULL, StartChangeRace, 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 result;
|
|
LOG_TRACE("(%p, %d, %d)", pRace_index, pNet_mode, pNet_race_sequence);
|
|
|
|
gNet_race_sequence__racestrt = pNet_race_sequence;
|
|
gChange_race_net_mode = pNet_mode;
|
|
gStart_interface_spec = &interface_spec;
|
|
gCurrent_race_index = *pRace_index;
|
|
if (pNet_mode == 0) {
|
|
gBullet_image = LoadPixelmap("BULLET.PIX");
|
|
} else {
|
|
gBullet_image = NULL;
|
|
}
|
|
result = DoInterfaceScreen(&interface_spec, pNet_mode != 0, 0);
|
|
if (result == 0) {
|
|
*pRace_index = gCurrent_race_index;
|
|
}
|
|
if (gBullet_image != NULL) {
|
|
BrPixelmapFree(gBullet_image);
|
|
}
|
|
return result == 0;
|
|
}
|
|
|
|
// IDA: void __cdecl DoChangeRace()
|
|
void DoChangeRace(void) {
|
|
LOG_TRACE("()");
|
|
|
|
if (ChangeRace(&gProgram_state.current_race_index, 0, eNet_sequence_sequential) != 0) {
|
|
gProgram_state.current_race_index = gCurrent_race_index;
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall DrawCar(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>)
|
|
void DrawCar(int pCurrent_choice, int pCurrent_mode) {
|
|
char s[64];
|
|
int text_x;
|
|
int text_width;
|
|
LOG_TRACE("(%d, %d)", pCurrent_choice, pCurrent_mode);
|
|
|
|
// Added by dethrace to ignore warnings about using sprintf without a literal format string
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wformat-security"
|
|
|
|
PollCarDetails(gChoose_car_net_game);
|
|
if (gChange_race_net_mode == 0) {
|
|
if (gProgram_state.number_of_cars == 1) {
|
|
sprintf(s, GetMiscString(kMiscString_NoOtherCarsToChooseFromYet));
|
|
} else if (gProgram_state.cars_available[gCurrent_car_index] == gProgram_state.frank_or_anniness) {
|
|
sprintf(s, GetMiscString(kMiscString_YourOriginalCar));
|
|
} else {
|
|
sprintf(s, "%s %s", GetMiscString(kMiscString_OriginalDriverWas), 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(kMiscString_THIS_CAR_ALREADY_TAKEN_BY), gCar_details[gProgram_state.cars_available[gCurrent_car_index]].name);
|
|
} else {
|
|
sprintf(s, GetMiscString(kMiscString_AVAILABLE));
|
|
}
|
|
|
|
#pragma GCC diagnostic pop
|
|
|
|
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,
|
|
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(void) {
|
|
LOG_TRACE("()");
|
|
|
|
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@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int UpCar(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
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(gEffects_outlet, 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@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int DownCar(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
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(gEffects_outlet, 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@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>, int pX_offset@<EBX>, int pY_offset@<ECX>)
|
|
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);
|
|
|
|
UpCar(pCurrent_choice, pCurrent_mode);
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall DownClickCar@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>, int pX_offset@<EBX>, int pY_offset@<ECX>)
|
|
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);
|
|
|
|
DownCar(pCurrent_choice, pCurrent_mode);
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall ChangeCarGoAhead@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int ChangeCarGoAhead(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
if (gChange_race_net_mode == 0 || gCar_details[gProgram_state.cars_available[gCurrent_car_index]].ownership != eCar_owner_someone) {
|
|
return 1;
|
|
} else {
|
|
DRS3StartSound(gEffects_outlet, 3100);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// IDA: int __usercall ChangeCar@<EAX>(int pNet_mode@<EAX>, int *pCar_index@<EDX>, tNet_game_details *pNet_game@<EBX>)
|
|
int ChangeCar(int pNet_mode, int* pCar_index, tNet_game_details* pNet_game) {
|
|
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);
|
|
|
|
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 (pNet_mode) {
|
|
BrPixelmapFree(gTaken_image);
|
|
}
|
|
if (result == 0) {
|
|
if (pNet_mode) {
|
|
*pCar_index = gProgram_state.cars_available[gCurrent_car_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(void) {
|
|
LOG_TRACE("()");
|
|
|
|
ChangeCar(0, &gProgram_state.current_car.index, NULL);
|
|
}
|
|
|
|
// IDA: int __cdecl PartsShopRecommended()
|
|
int PartsShopRecommended(void) {
|
|
int running_cost;
|
|
int i;
|
|
int current_index;
|
|
int counter;
|
|
LOG_TRACE("()");
|
|
|
|
running_cost = 0;
|
|
counter = 0;
|
|
for (i = 0; i < eParts_count; i++) {
|
|
current_index = gProgram_state.current_car.power_up_levels[i];
|
|
if (current_index + 1 < gProgram_state.current_car.power_ups[i].number_of_parts && (gProgram_state.rank <= gProgram_state.current_car.power_ups[i].info[current_index + 1].rank_required || gProgram_state.game_completed)) {
|
|
running_cost += gProgram_state.current_car.power_ups[i].info[current_index + 1].prices[gProgram_state.skill_level];
|
|
counter++;
|
|
}
|
|
}
|
|
return running_cost != 0 && ((float)running_cost / counter * 1.5f <= gProgram_state.credits);
|
|
}
|
|
|
|
// IDA: void __usercall CalcPartPrice(int pCategory@<EAX>, int pIndex@<EDX>, int *pPrice@<EBX>, int *pCost@<ECX>)
|
|
void CalcPartPrice(int pCategory, int pIndex, int* pPrice, int* pCost) {
|
|
int current_value;
|
|
LOG_TRACE("(%d, %d, %p, %p)", pCategory, pIndex, pPrice, pCost);
|
|
|
|
*pPrice = gProgram_state.current_car.power_ups[pCategory].info[pIndex].prices[gProgram_state.skill_level];
|
|
if (gProgram_state.current_car.power_up_levels[pCategory] == pIndex) {
|
|
*pCost = 0;
|
|
} else {
|
|
*pCost = *pPrice - 10 * (gRefund_rate * gProgram_state.current_car.power_ups[pCategory].info[gProgram_state.current_car.power_up_levels[pCategory]].prices[gProgram_state.skill_level] / 1000);
|
|
}
|
|
}
|
|
|
|
// IDA: int __usercall BuyPart@<EAX>(int pCategory@<EAX>, int pIndex@<EDX>)
|
|
int BuyPart(int pCategory, int pIndex) {
|
|
int price;
|
|
int cost;
|
|
LOG_TRACE("(%d, %d)", pCategory, pIndex);
|
|
|
|
CalcPartPrice(pCategory, pIndex, &price, &cost);
|
|
if (cost == 0) {
|
|
return 1;
|
|
} else if (gProgram_state.credits < cost) {
|
|
return 0;
|
|
} else {
|
|
gProgram_state.credits -= cost;
|
|
if (gProgram_state.credits > 999999) {
|
|
gProgram_state.credits = 999999;
|
|
}
|
|
gProgram_state.current_car.power_up_levels[pCategory] = pIndex;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
// IDA: void __cdecl DoAutoParts()
|
|
void DoAutoParts(void) {
|
|
int i;
|
|
int lowest_yet;
|
|
int lowest_one;
|
|
int price;
|
|
int cost;
|
|
int current_level;
|
|
LOG_TRACE("()");
|
|
|
|
while (1) {
|
|
if (!PartsShopRecommended()) {
|
|
return;
|
|
}
|
|
lowest_yet = COUNT_OF(((tParts_spec*)NULL)->info);
|
|
for (i = 0; i < eParts_count; i++) {
|
|
current_level = gProgram_state.current_car.power_up_levels[i];
|
|
if (current_level + 1 < gProgram_state.current_car.power_ups[i].number_of_parts && (gProgram_state.rank <= gProgram_state.current_car.power_ups[i].info[current_level + 1].rank_required || gProgram_state.game_completed)) {
|
|
CalcPartPrice(i, current_level + 1, &price, &cost);
|
|
if (cost != 0 && cost <= gProgram_state.credits && current_level < lowest_yet) {
|
|
lowest_one = i;
|
|
lowest_yet = current_level + 1;
|
|
}
|
|
}
|
|
}
|
|
if (lowest_yet == COUNT_OF(((tParts_spec*)NULL)->info)) {
|
|
break;
|
|
}
|
|
if (!BuyPart(lowest_one, lowest_yet)) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// IDA: void __cdecl DrawPartsLabel()
|
|
void DrawPartsLabel(void) {
|
|
LOG_TRACE("()");
|
|
|
|
switch (gPart_category) {
|
|
case eParts_armour:
|
|
RunFlicAt(262, gCurrent_graf_data->parts_label_x, gCurrent_graf_data->parts_label_y);
|
|
break;
|
|
case eParts_power:
|
|
RunFlicAt(263, gCurrent_graf_data->parts_label_x, gCurrent_graf_data->parts_label_y);
|
|
break;
|
|
case eParts_offensive:
|
|
RunFlicAt(264, gCurrent_graf_data->parts_label_x, gCurrent_graf_data->parts_label_y);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall ErasePartsText(int pTotal_as_well@<EAX>)
|
|
void ErasePartsText(int pTotal_as_well) {
|
|
LOG_TRACE("(%d)", pTotal_as_well);
|
|
|
|
BrPixelmapRectangleFill(gBack_screen,
|
|
gCurrent_graf_data->parts_cost_x,
|
|
gCurrent_graf_data->parts_cost_y,
|
|
gCurrent_graf_data->parts_image_width - (gCurrent_graf_data->parts_cost_x - gCurrent_graf_data->parts_image_x),
|
|
gFont_7->glyph_y + gCurrent_graf_data->parts_net_y - gCurrent_graf_data->parts_cost_y,
|
|
0);
|
|
if (pTotal_as_well) {
|
|
BrPixelmapRectangleFill(gBack_screen,
|
|
gCurrent_graf_data->parts_total_x,
|
|
gCurrent_graf_data->parts_total_y,
|
|
gCurrent_graf_data->parts_image_width - (gCurrent_graf_data->parts_total_x - gCurrent_graf_data->parts_image_x),
|
|
gFont_7->glyph_y,
|
|
0);
|
|
}
|
|
}
|
|
|
|
// IDA: void __cdecl DrawPartsText()
|
|
void DrawPartsText(void) {
|
|
int price;
|
|
int cost;
|
|
LOG_TRACE("()");
|
|
|
|
CalcPartPrice(gPart_category, gPart_index, &price, &cost);
|
|
TransBrPixelmapText(gBack_screen, gCurrent_graf_data->parts_cost_x, gCurrent_graf_data->parts_cost_y, 5, gFont_7, GetMiscString(kMiscString_RetailColon));
|
|
BrPixelmapTextF(gBack_screen, gCurrent_graf_data->parts_numbers_x, gCurrent_graf_data->parts_cost_y - (TranslationMode() ? 2 : 0), 5, gFont_7, "%d", price);
|
|
if (cost > 0) {
|
|
TransBrPixelmapText(gBack_screen, gCurrent_graf_data->parts_net_x, gCurrent_graf_data->parts_net_y, 45, gFont_7, GetMiscString(kMiscString_YouPayColon));
|
|
BrPixelmapTextF(gBack_screen, gCurrent_graf_data->parts_numbers_x, gCurrent_graf_data->parts_net_y - (TranslationMode() ? 2 : 0), 45, gFont_7, "%d", cost);
|
|
} else if (cost < 0) {
|
|
TransBrPixelmapText(gBack_screen, gCurrent_graf_data->parts_net_x, gCurrent_graf_data->parts_net_y, 201, gFont_7, GetMiscString(kMiscString_RefundColon));
|
|
BrPixelmapTextF(gBack_screen, gCurrent_graf_data->parts_numbers_x, gCurrent_graf_data->parts_net_y - (TranslationMode() ? 2 : 0), 201, gFont_7, "%d", -cost);
|
|
} else if (gJust_bought_part) {
|
|
TransBrPixelmapText(gBack_screen, gCurrent_graf_data->parts_net_x, gCurrent_graf_data->parts_net_y, 134, gFont_7, GetMiscString(kMiscString_YouGotIt));
|
|
} else {
|
|
TransBrPixelmapText(gBack_screen, gCurrent_graf_data->parts_net_x, gCurrent_graf_data->parts_net_y, 134, gFont_7, GetMiscString(kMiscString_YoursAlready));
|
|
}
|
|
TransBrPixelmapText(gBack_screen, gCurrent_graf_data->parts_total_x, gCurrent_graf_data->parts_total_y, 2, gFont_7, GetMiscString(kMiscString_CreditsColon));
|
|
BrPixelmapTextF(gBack_screen, gCurrent_graf_data->parts_numbers_x, gCurrent_graf_data->parts_total_y - (TranslationMode() ? 2 : 0), 2, gFont_7, "%d", gProgram_state.credits);
|
|
}
|
|
|
|
// IDA: void __cdecl SetPartsImage()
|
|
void SetPartsImage(void) {
|
|
LOG_TRACE("()");
|
|
|
|
ChangePanelFlic(0,
|
|
gProgram_state.current_car.power_ups[gPart_category].info[gPart_index].data_ptr,
|
|
gProgram_state.current_car.power_ups[gPart_category].info[gPart_index].data_length);
|
|
TellyInImage(GetPanelPixelmap(0), gCurrent_graf_data->parts_image_x, gCurrent_graf_data->parts_image_y);
|
|
DrawPartsText();
|
|
}
|
|
|
|
// IDA: int __cdecl GetPartsMax()
|
|
int GetPartsMax(void) {
|
|
int i;
|
|
LOG_TRACE("()");
|
|
|
|
for (i = gProgram_state.current_car.power_ups[gPart_category].number_of_parts - 1; i >= 0; i--) {
|
|
if (gProgram_state.rank <= gProgram_state.current_car.power_ups[gPart_category].info[i].rank_required) {
|
|
return i;
|
|
}
|
|
if (gProgram_state.game_completed) {
|
|
return i;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// IDA: void __cdecl CalcPartsIndex()
|
|
void CalcPartsIndex(void) {
|
|
int current_index;
|
|
LOG_TRACE("()");
|
|
|
|
gPart_index = gProgram_state.current_car.power_up_levels[gPart_category];
|
|
if (gPart_index + 1 < gProgram_state.current_car.power_ups[gPart_category].number_of_parts && (gProgram_state.rank <= gProgram_state.current_car.power_ups[gPart_category].info[gPart_index + 1].rank_required || gProgram_state.game_completed)) {
|
|
gPart_index += 1;
|
|
}
|
|
}
|
|
|
|
// IDA: void __cdecl DoExchangePart()
|
|
void DoExchangePart(void) {
|
|
int price;
|
|
int cost;
|
|
LOG_TRACE("()");
|
|
|
|
CalcPartPrice(gPart_category, gPart_index, &price, &cost);
|
|
if (cost == 0 || gProgram_state.credits < cost) {
|
|
DRS3StartSound(gEffects_outlet, 3100);
|
|
} else {
|
|
gJust_bought_part = 1;
|
|
DRS3StartSound(gEffects_outlet, 3101);
|
|
BuyPart(gPart_category, gPart_index);
|
|
ErasePartsText(1);
|
|
DrawPartsText();
|
|
}
|
|
}
|
|
|
|
// IDA: int __usercall PartsShopGoAhead@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int PartsShopGoAhead(int* pCurrent_choice, int* pCurrent_mode) {
|
|
int flic_index;
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
if (*pCurrent_choice < 3 && *pCurrent_mode == 0) {
|
|
RemoveTransientBitmaps(1);
|
|
DontLetFlicFuckWithPalettes();
|
|
TurnFlicTransparencyOn();
|
|
RunFlicAt(
|
|
gStart_interface_spec->pushed_flics[*pCurrent_choice].flic_index,
|
|
gStart_interface_spec->pushed_flics[*pCurrent_choice].x[gGraf_data_index],
|
|
gStart_interface_spec->pushed_flics[*pCurrent_choice].y[gGraf_data_index]);
|
|
TurnFlicTransparencyOff();
|
|
LetFlicFuckWithPalettes();
|
|
gJust_bought_part = 0;
|
|
ErasePartsText(1);
|
|
TellyOutImage(GetPanelPixelmap(0), gCurrent_graf_data->parts_image_x, gCurrent_graf_data->parts_image_y);
|
|
gPart_category = *pCurrent_choice;
|
|
CalcPartsIndex();
|
|
RunFlic(261);
|
|
AddToFlicQueue(
|
|
gStart_interface_spec->flicker_on_flics[*pCurrent_choice].flic_index,
|
|
gStart_interface_spec->flicker_on_flics[*pCurrent_choice].x[gGraf_data_index],
|
|
gStart_interface_spec->flicker_on_flics[*pCurrent_choice].y[gGraf_data_index],
|
|
1);
|
|
DrawPartsLabel();
|
|
SetPartsImage();
|
|
ProcessFlicQueue(gFrame_period);
|
|
DoMouseCursor();
|
|
PDScreenBufferSwap(0);
|
|
return 0;
|
|
} else if (*pCurrent_mode == 1) {
|
|
AddToFlicQueue(
|
|
gStart_interface_spec->flicker_on_flics[4].flic_index,
|
|
gStart_interface_spec->flicker_on_flics[4].x[gGraf_data_index],
|
|
gStart_interface_spec->flicker_on_flics[4].y[gGraf_data_index],
|
|
1);
|
|
DoExchangePart();
|
|
return 0;
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
// IDA: int __usercall UpPart@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int UpPart(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
gJust_bought_part = 0;
|
|
AddToFlicQueue(
|
|
gStart_interface_spec->pushed_flics[5].flic_index,
|
|
gStart_interface_spec->pushed_flics[5].x[gGraf_data_index],
|
|
gStart_interface_spec->pushed_flics[5].y[gGraf_data_index],
|
|
1);
|
|
DRS3StartSound(gEffects_outlet, 3000);
|
|
RemoveTransientBitmaps(1);
|
|
ErasePartsText(0);
|
|
|
|
gPart_index = (gPart_index == 0) ? GetPartsMax() : (gPart_index - 1);
|
|
|
|
DropOutImageThruBottom(
|
|
GetPanelPixelmap(0),
|
|
gCurrent_graf_data->parts_image_x,
|
|
gCurrent_graf_data->parts_image_y,
|
|
gCurrent_graf_data->parts_top_clip,
|
|
gCurrent_graf_data->parts_bottom_clip);
|
|
ChangePanelFlic(0,
|
|
gProgram_state.current_car.power_ups[gPart_category].info[gPart_index].data_ptr,
|
|
gProgram_state.current_car.power_ups[gPart_category].info[gPart_index].data_length);
|
|
DropInImageFromTop(
|
|
GetPanelPixelmap(0),
|
|
gCurrent_graf_data->parts_image_x,
|
|
gCurrent_graf_data->parts_image_y,
|
|
gCurrent_graf_data->parts_top_clip,
|
|
gCurrent_graf_data->parts_bottom_clip);
|
|
DrawPartsText();
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall DownPart@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int DownPart(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
gJust_bought_part = 0;
|
|
AddToFlicQueue(
|
|
gStart_interface_spec->pushed_flics[6].flic_index,
|
|
gStart_interface_spec->pushed_flics[6].x[gGraf_data_index],
|
|
gStart_interface_spec->pushed_flics[6].y[gGraf_data_index],
|
|
1);
|
|
DRS3StartSound(gEffects_outlet, 3000);
|
|
RemoveTransientBitmaps(1);
|
|
ErasePartsText(0);
|
|
|
|
gPart_index = (gPart_index == GetPartsMax()) ? 0 : (gPart_index + 1);
|
|
|
|
DropOutImageThruTop(
|
|
GetPanelPixelmap(0),
|
|
gCurrent_graf_data->parts_image_x,
|
|
gCurrent_graf_data->parts_image_y,
|
|
gCurrent_graf_data->parts_top_clip,
|
|
gCurrent_graf_data->parts_bottom_clip);
|
|
ChangePanelFlic(0,
|
|
gProgram_state.current_car.power_ups[gPart_category].info[gPart_index].data_ptr,
|
|
gProgram_state.current_car.power_ups[gPart_category].info[gPart_index].data_length);
|
|
DropInImageFromBottom(
|
|
GetPanelPixelmap(0),
|
|
gCurrent_graf_data->parts_image_x,
|
|
gCurrent_graf_data->parts_image_y,
|
|
gCurrent_graf_data->parts_top_clip,
|
|
gCurrent_graf_data->parts_bottom_clip);
|
|
DrawPartsText();
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall UpClickPart@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>, int pX_offset@<EBX>, int pY_offset@<ECX>)
|
|
int UpClickPart(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);
|
|
|
|
UpPart(pCurrent_choice, pCurrent_mode);
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall DownClickPart@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>, int pX_offset@<EBX>, int pY_offset@<ECX>)
|
|
int DownClickPart(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);
|
|
|
|
DownPart(pCurrent_choice, pCurrent_mode);
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall PartsArrowsOn@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int PartsArrowsOn(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
AddToFlicQueue(
|
|
gStart_interface_spec->flicker_on_flics[5].flic_index,
|
|
gStart_interface_spec->flicker_on_flics[5].x[gGraf_data_index],
|
|
gStart_interface_spec->flicker_on_flics[5].y[gGraf_data_index],
|
|
1);
|
|
AddToFlicQueue(gStart_interface_spec->flicker_on_flics[6].flic_index,
|
|
gStart_interface_spec->flicker_on_flics[6].x[gGraf_data_index],
|
|
gStart_interface_spec->flicker_on_flics[6].y[gGraf_data_index],
|
|
1);
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall PartsArrowsOff@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int PartsArrowsOff(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
AddToFlicQueue(gStart_interface_spec->flicker_off_flics[5].flic_index,
|
|
gStart_interface_spec->flicker_off_flics[5].x[gGraf_data_index],
|
|
gStart_interface_spec->flicker_off_flics[5].y[gGraf_data_index],
|
|
1);
|
|
AddToFlicQueue(gStart_interface_spec->flicker_off_flics[6].flic_index,
|
|
gStart_interface_spec->flicker_off_flics[6].x[gGraf_data_index],
|
|
gStart_interface_spec->flicker_off_flics[6].y[gGraf_data_index],
|
|
1);
|
|
return 0;
|
|
}
|
|
|
|
// IDA: void __cdecl StartPartsShop()
|
|
void StartPartsShop(void) {
|
|
LOG_TRACE("()");
|
|
|
|
DrawPartsLabel();
|
|
SetPartsImage();
|
|
}
|
|
|
|
// IDA: int __usercall DonePartsShop@<EAX>(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>, int pGo_ahead@<EBX>, int pEscaped@<ECX>, int pTimed_out)
|
|
int DonePartsShop(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);
|
|
|
|
if (gFade_away_parts_shop) {
|
|
FadePaletteDown();
|
|
} else {
|
|
RunFlic(251);
|
|
}
|
|
return pGo_ahead;
|
|
}
|
|
|
|
// IDA: void __usercall DrawPartsShop(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>)
|
|
void DrawPartsShop(int pCurrent_choice, int pCurrent_mode) {
|
|
LOG_TRACE("(%d, %d)", pCurrent_choice, pCurrent_mode);
|
|
|
|
DrawPartsText();
|
|
}
|
|
|
|
// IDA: void __usercall DoPartsShop(int pFade_away@<EAX>)
|
|
void DoPartsShop(int pFade_away) {
|
|
static tFlicette flicker_on[7] = {
|
|
{ 43, { 225, 450 }, { 30, 72 } },
|
|
{ 43, { 225, 450 }, { 60, 144 } },
|
|
{ 43, { 225, 450 }, { 89, 214 } },
|
|
{ 43, { 225, 450 }, { 152, 365 } },
|
|
{ 43, { 85, 170 }, { 152, 365 } },
|
|
{ 221, { 30, 60 }, { 79, 190 } },
|
|
{ 221, { 30, 60 }, { 79, 190 } },
|
|
};
|
|
static tFlicette flicker_off[7] = {
|
|
{ 42, { 225, 450 }, { 30, 72 } },
|
|
{ 42, { 225, 450 }, { 60, 144 } },
|
|
{ 42, { 225, 450 }, { 89, 214 } },
|
|
{ 42, { 225, 450 }, { 152, 365 } },
|
|
{ 42, { 85, 170 }, { 152, 365 } },
|
|
{ 220, { 30, 60 }, { 79, 190 } },
|
|
{ 220, { 30, 60 }, { 79, 190 } },
|
|
};
|
|
static tFlicette push[7] = {
|
|
{ 254, { 225, 450 }, { 30, 72 } },
|
|
{ 255, { 225, 450 }, { 60, 144 } },
|
|
{ 256, { 225, 450 }, { 89, 214 } },
|
|
{ 154, { 225, 450 }, { 152, 365 } },
|
|
{ 260, { 85, 170 }, { 152, 365 } },
|
|
{ 222, { 30, 60 }, { 79, 190 } },
|
|
{ 225, { 30, 60 }, { 120, 288 } },
|
|
};
|
|
static tMouse_area mouse_areas[7] = {
|
|
{ { 225, 450 }, { 30, 72 }, { 288, 576 }, { 50, 120 }, 0, 0, 0, NULL },
|
|
{ { 225, 450 }, { 60, 144 }, { 288, 576 }, { 80, 192 }, 1, 0, 0, NULL },
|
|
{ { 225, 450 }, { 89, 214 }, { 288, 576 }, { 109, 262 }, 2, 0, 0, NULL },
|
|
{ { 225, 450 }, { 152, 365 }, { 288, 576 }, { 172, 413 }, 3, 0, 0, NULL },
|
|
{ { 85, 170 }, { 152, 365 }, { 148, 296 }, { 172, 413 }, 4, 1, 0, NULL },
|
|
{ { 30, 60 }, { 79, 190 }, { 45, 90 }, { 106, 254 }, -1, 1, 0, UpClickPart },
|
|
{ { 30, 60 }, { 120, 288 }, { 45, 90 }, { 147, 353 }, -1, 1, 0, DownClickPart },
|
|
};
|
|
static tInterface_spec interface_spec = {
|
|
0, 250, 190, 0, 0, 0, 6,
|
|
{ 1, 0 }, { 4, -1 }, { 4, 0 }, { 4, 3 }, { PartsArrowsOn, PartsArrowsOff },
|
|
{ 1, 0 }, { 4, -1 }, { 4, 0 }, { 4, 3 }, { PartsArrowsOn, PartsArrowsOff },
|
|
{ -1, -1 }, { -1, 0 }, { 0, 4 }, { 3, 4 }, { NULL, UpPart },
|
|
{ -1, -1 }, { 1, 0 }, { 0, 4 }, { 3, 4 }, { NULL, DownPart },
|
|
{ 1, 1 }, { PartsShopGoAhead, PartsShopGoAhead },
|
|
{ 1, 1 }, { NULL, NULL },
|
|
NULL, DrawPartsShop, 0, NULL, StartPartsShop, DonePartsShop,
|
|
0, { 0, 0 }, NULL, 3, 1,
|
|
COUNT_OF(flicker_on),
|
|
flicker_on,
|
|
flicker_off,
|
|
push,
|
|
COUNT_OF(mouse_areas),
|
|
mouse_areas,
|
|
0,
|
|
NULL
|
|
};
|
|
int result;
|
|
LOG_TRACE("(%d)", pFade_away);
|
|
|
|
LoadParts();
|
|
gFade_away_parts_shop = pFade_away;
|
|
InitialiseFlicPanel(0,
|
|
gCurrent_graf_data->parts_image_x,
|
|
gCurrent_graf_data->parts_image_y,
|
|
gCurrent_graf_data->parts_image_width,
|
|
gCurrent_graf_data->parts_image_height);
|
|
gStart_interface_spec = &interface_spec;
|
|
gPart_category = eParts_armour;
|
|
gJust_bought_part = 0;
|
|
gRefund_rate = 75;
|
|
CalcPartsIndex();
|
|
DoInterfaceScreen(&interface_spec, gFaded_palette, 3);
|
|
DisposeFlicPanel(0);
|
|
UnlockParts();
|
|
gProgram_state.parts_shop_visited = 1;
|
|
}
|
|
|
|
// IDA: int __usercall AutoPartsDone@<EAX>(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>, int pGo_ahead@<EBX>, int pEscaped@<ECX>, int pTimed_out)
|
|
int AutoPartsDone(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);
|
|
|
|
if (pEscaped) {
|
|
pCurrent_choice = -1;
|
|
}
|
|
return pCurrent_choice;
|
|
}
|
|
|
|
// IDA: tSO_result __cdecl DoAutoPartsShop()
|
|
tSO_result DoAutoPartsShop(void) {
|
|
static tFlicette flicker_on[3] = {
|
|
{ 43, { 84, 168 }, { 67, 161 } },
|
|
{ 43, { 84, 168 }, { 95, 228 } },
|
|
{ 43, { 84, 168 }, { 124, 298 } },
|
|
};
|
|
static tFlicette flicker_off[3] = {
|
|
{ 42, { 84, 168 }, { 67, 161 } },
|
|
{ 42, { 84, 168 }, { 95, 228 } },
|
|
{ 42, { 84, 168 }, { 124, 298 } },
|
|
};
|
|
static tFlicette push[3] = {
|
|
{ 284, { 84, 168 }, { 67, 161 } },
|
|
{ 284, { 84, 168 }, { 95, 228 } },
|
|
{ 284, { 84, 168 }, { 124, 298 } },
|
|
};
|
|
static tMouse_area mouse_areas[3] = {
|
|
{ { 84, 168 }, { 32, 77 }, { 147, 294 }, { 87, 209 }, 0, 0, 0, NULL },
|
|
{ { 84, 168 }, { 95, 228 }, { 147, 294 }, { 115, 276 }, 1, 0, 0, NULL },
|
|
{ { 84, 168 }, { 124, 298 }, { 147, 294 }, { 144, 346 }, 2, 0, 0, NULL },
|
|
};
|
|
static tInterface_spec interface_spec = {
|
|
0, 280, 0, 0, 0, 0, 6,
|
|
{ -1, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { NULL, NULL },
|
|
{ -1, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { NULL, NULL },
|
|
{ -1, -1 }, { -1, 0 }, { 0, 0 }, { 2, 0 }, { NULL, NULL },
|
|
{ -1, -1 }, { 1, 0 }, { 0, 0 }, { 2, 0 }, { NULL, NULL },
|
|
{ 1, 1 }, { NULL, NULL },
|
|
{ 1, 1 }, { NULL, NULL },
|
|
NULL, NULL, 0, NULL, NULL, AutoPartsDone, 0,
|
|
{ 0, 0 }, NULL, -1, 1,
|
|
COUNT_OF(flicker_on), flicker_on, flicker_off, push,
|
|
COUNT_OF(mouse_areas), mouse_areas,
|
|
0, NULL
|
|
};
|
|
int result;
|
|
LOG_TRACE("()");
|
|
|
|
gProgram_state.dont_load = 1;
|
|
result = DoInterfaceScreen(&interface_spec, 0, gProgram_state.auto_parts_reply);
|
|
gProgram_state.dont_load = 0;
|
|
if (result < 0) {
|
|
RunFlic(281);
|
|
return eSO_main_menu_invoked;
|
|
} else {
|
|
gProgram_state.auto_parts_reply = result;
|
|
switch (result) {
|
|
case eAP_auto:
|
|
DoAutoParts();
|
|
break;
|
|
case eAP_manual:
|
|
RunFlic(281);
|
|
DoPartsShop(1);
|
|
break;
|
|
}
|
|
FadePaletteDown();
|
|
return eSO_continue;
|
|
}
|
|
}
|
|
|
|
// IDA: void __cdecl SetOpponentFlic()
|
|
void SetOpponentFlic(void) {
|
|
LOG_TRACE("()");
|
|
ChangePanelFlic(0,
|
|
gOpponents[gCurrent_race.opponent_list[gOpponent_index].index].mug_shot_image_data,
|
|
gOpponents[gCurrent_race.opponent_list[gOpponent_index].index].mug_shot_image_data_length);
|
|
}
|
|
|
|
// IDA: void __cdecl DrawSceneyMappyInfoVieweyThing()
|
|
void DrawSceneyMappyInfoVieweyThing(void) {
|
|
LOG_TRACE("()");
|
|
|
|
RemoveTransientBitmaps(1);
|
|
if (gProgram_state.view_type) {
|
|
if (gProgram_state.view_type == eVT_Info) {
|
|
ChangePanelFlic(0, gCurrent_race.info_image_data, gCurrent_race.info_image_data_length);
|
|
} else if (gProgram_state.view_type == eVT_Opponents) {
|
|
SetOpponentFlic();
|
|
}
|
|
} else {
|
|
ChangePanelFlic(0, gCurrent_race.scene_image_data, gCurrent_race.scene_image_data_length);
|
|
}
|
|
TellyInImage(GetPanelPixelmap(0), gCurrent_graf_data->start_race_panel_left, gCurrent_graf_data->start_race_panel_top);
|
|
}
|
|
|
|
// IDA: void __cdecl DismissSceneyMappyInfoVieweyThing()
|
|
void DismissSceneyMappyInfoVieweyThing(void) {
|
|
LOG_TRACE("()");
|
|
|
|
RemoveTransientBitmaps(1);
|
|
TellyOutImage(GetPanelPixelmap(0), gCurrent_graf_data->start_race_panel_left, gCurrent_graf_data->start_race_panel_top);
|
|
}
|
|
|
|
// IDA: int __usercall SelectRaceDone@<EAX>(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>, int pGo_ahead@<EBX>, int pEscaped@<ECX>, int pTimed_out)
|
|
int SelectRaceDone(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);
|
|
|
|
DismissSceneyMappyInfoVieweyThing();
|
|
if (pEscaped) {
|
|
return -1;
|
|
}
|
|
return pCurrent_choice;
|
|
}
|
|
|
|
// IDA: int __usercall StartRaceGoAhead@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int StartRaceGoAhead(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
if (*pCurrent_choice != 1 || *pCurrent_mode) {
|
|
return 1;
|
|
}
|
|
RemoveTransientBitmaps(1);
|
|
DismissSceneyMappyInfoVieweyThing();
|
|
gProgram_state.view_type++;
|
|
if (gProgram_state.view_type > eVT_Opponents) {
|
|
gProgram_state.view_type = eVT_Scene;
|
|
}
|
|
if (gProgram_state.view_type) {
|
|
if (gProgram_state.view_type == eVT_Info) {
|
|
RunFlic(210);
|
|
} else if (gProgram_state.view_type == eVT_Opponents) {
|
|
RunFlic(212);
|
|
}
|
|
} else {
|
|
RunFlic(213);
|
|
}
|
|
DrawSceneyMappyInfoVieweyThing();
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall TryToMoveToArrows@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int TryToMoveToArrows(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
if (gProgram_state.view_type != eVT_Opponents) {
|
|
return 0;
|
|
}
|
|
*pCurrent_choice = 5;
|
|
*pCurrent_mode = 1;
|
|
DRS3StartSound(gEffects_outlet, 3000);
|
|
return 1;
|
|
}
|
|
|
|
// IDA: int __usercall UpOpponent@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int UpOpponent(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
#if defined(DETHRACE_FIX_BUGS)
|
|
// fixes bug where racers could be scrolled in other race menu modes
|
|
if (gProgram_state.view_type != eVT_Opponents) {
|
|
return 0;
|
|
}
|
|
#endif
|
|
AddToFlicQueue(gStart_interface_spec->pushed_flics[5].flic_index,
|
|
gStart_interface_spec->pushed_flics[5].x[gGraf_data_index],
|
|
gStart_interface_spec->pushed_flics[5].y[gGraf_data_index],
|
|
1);
|
|
DRS3StartSound(gEffects_outlet, 3000);
|
|
RemoveTransientBitmaps(1);
|
|
DropOutImageThruBottom(GetPanelPixelmap(0),
|
|
gCurrent_graf_data->start_race_panel_left,
|
|
gCurrent_graf_data->start_race_panel_top,
|
|
gCurrent_graf_data->start_race_panel_top_clip,
|
|
gCurrent_graf_data->start_race_panel_bottom_clip);
|
|
if (gOpponent_index == 0) {
|
|
gOpponent_index = gCurrent_race.number_of_racers;
|
|
}
|
|
gOpponent_index--;
|
|
SetOpponentFlic();
|
|
DropInImageFromTop(GetPanelPixelmap(0),
|
|
gCurrent_graf_data->start_race_panel_left,
|
|
gCurrent_graf_data->start_race_panel_top,
|
|
gCurrent_graf_data->start_race_panel_top_clip,
|
|
gCurrent_graf_data->start_race_panel_bottom_clip);
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall DownOpponent@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int DownOpponent(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
#if defined(DETHRACE_FIX_BUGS)
|
|
// fixes bug where racers could be scrolled in other race menu modes
|
|
if (gProgram_state.view_type != eVT_Opponents) {
|
|
return 0;
|
|
}
|
|
#endif
|
|
AddToFlicQueue(gStart_interface_spec->pushed_flics[6].flic_index,
|
|
gStart_interface_spec->pushed_flics[6].x[gGraf_data_index],
|
|
gStart_interface_spec->pushed_flics[6].y[gGraf_data_index],
|
|
1);
|
|
DRS3StartSound(gEffects_outlet, 3000);
|
|
RemoveTransientBitmaps(1);
|
|
DropOutImageThruTop(GetPanelPixelmap(0),
|
|
gCurrent_graf_data->start_race_panel_left,
|
|
gCurrent_graf_data->start_race_panel_top,
|
|
gCurrent_graf_data->start_race_panel_top_clip,
|
|
gCurrent_graf_data->start_race_panel_bottom_clip);
|
|
gOpponent_index++;
|
|
if (gOpponent_index == gCurrent_race.number_of_racers) {
|
|
gOpponent_index = 0;
|
|
}
|
|
SetOpponentFlic();
|
|
DropInImageFromBottom(GetPanelPixelmap(0),
|
|
gCurrent_graf_data->start_race_panel_left,
|
|
gCurrent_graf_data->start_race_panel_top,
|
|
gCurrent_graf_data->start_race_panel_top_clip,
|
|
gCurrent_graf_data->start_race_panel_bottom_clip);
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall UpClickOpp@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>, int pX_offset@<EBX>, int pY_offset@<ECX>)
|
|
int UpClickOpp(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);
|
|
|
|
UpOpponent(pCurrent_choice, pCurrent_mode);
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall DownClickOpp@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>, int pX_offset@<EBX>, int pY_offset@<ECX>)
|
|
int DownClickOpp(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);
|
|
|
|
DownOpponent(pCurrent_choice, pCurrent_mode);
|
|
return 0;
|
|
}
|
|
|
|
// IDA: void __cdecl SelectRaceStart()
|
|
void SelectRaceStart(void) {
|
|
LOG_TRACE("()");
|
|
|
|
DrawSceneyMappyInfoVieweyThing();
|
|
PrintMemoryDump(0, "INSIDE START RACE");
|
|
}
|
|
|
|
// IDA: int __cdecl SuggestRace()
|
|
int SuggestRace(void) {
|
|
int i;
|
|
int least_done;
|
|
int suggested_so_far;
|
|
int suggested_race;
|
|
int new_suggestion;
|
|
int number_of_visits;
|
|
LOG_TRACE("()");
|
|
|
|
suggested_so_far = 32767;
|
|
suggested_race = 0;
|
|
if (gProgram_state.game_completed) {
|
|
return IRandomBetween(0, gNumber_of_races - 1);
|
|
}
|
|
if (gProgram_state.redo_race_index >= 0) {
|
|
return gProgram_state.redo_race_index;
|
|
}
|
|
for (i = 0; i < gNumber_of_races; i++) {
|
|
if (gRace_list[i].suggested_rank <= suggested_so_far && gRace_list[i].suggested_rank >= gProgram_state.rank) {
|
|
suggested_so_far = gRace_list[i].suggested_rank;
|
|
suggested_race = i;
|
|
}
|
|
}
|
|
number_of_visits = gRace_list[suggested_race].been_there_done_that;
|
|
new_suggestion = suggested_race;
|
|
|
|
if (number_of_visits) {
|
|
// Jeff: if we have already completed the suggested race, look backwards for a race that we haven't completed as many times
|
|
for (i = suggested_race - 1; i >= 0 && i >= suggested_race - 5; i--) {
|
|
if (gRace_list[i].rank_required < gProgram_state.rank || gRace_list[i].best_rank > gProgram_state.rank) {
|
|
continue;
|
|
}
|
|
least_done = gRace_list[i].been_there_done_that < number_of_visits;
|
|
if (!gRace_list[i].been_there_done_that
|
|
|| (least_done && suggested_race - 3 <= i)) {
|
|
new_suggestion = i;
|
|
number_of_visits = gRace_list[i].been_there_done_that;
|
|
}
|
|
}
|
|
// Jeff: look forwards for a race that we haven't completed as many times as the previous suggestion
|
|
for (i = suggested_race + 1; i < gNumber_of_races; i++) {
|
|
least_done = gRace_list[i].been_there_done_that < number_of_visits;
|
|
if (!least_done) {
|
|
continue;
|
|
}
|
|
|
|
if ((gRace_list[i].rank_required >= gProgram_state.rank && gRace_list[i].best_rank <= gProgram_state.rank)
|
|
|| gProgram_state.game_completed) {
|
|
new_suggestion = i;
|
|
number_of_visits = gRace_list[i].been_there_done_that;
|
|
}
|
|
}
|
|
}
|
|
return new_suggestion;
|
|
}
|
|
|
|
// IDA: void __usercall SelectRaceDraw(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>)
|
|
void SelectRaceDraw(int pCurrent_choice, int pCurrent_mode) {
|
|
tOpponent* the_opponent;
|
|
tText_chunk* the_chunk;
|
|
int j;
|
|
int k;
|
|
int y_coord;
|
|
char s[256];
|
|
char temp_str[256];
|
|
char* sub_pt;
|
|
char sub_str[16];
|
|
tU32* test;
|
|
static tU32 test2;
|
|
LOG_TRACE8("(%d, %d)", pCurrent_choice, pCurrent_mode);
|
|
|
|
if (gProgram_state.view_type == eVT_Opponents) {
|
|
the_opponent = &gOpponents[gCurrent_race.opponent_list[gOpponent_index].index];
|
|
for (j = 0; j < the_opponent->text_chunk_count; j++) {
|
|
the_chunk = &the_opponent->text_chunks[j];
|
|
if (GetPanelFlicFrameIndex(0) >= the_chunk->frame_cue && GetPanelFlicFrameIndex(0) < the_chunk->frame_end) {
|
|
y_coord = the_chunk->y_coord * gGraf_specs[gGraf_spec_index].total_height / 200
|
|
+ gCurrent_graf_data->start_race_panel_top;
|
|
for (k = 0; k < the_chunk->line_count; k++) {
|
|
TransBrPixelmapText(
|
|
gBack_screen,
|
|
the_chunk->x_coord * gGraf_specs[gGraf_spec_index].total_width / 320
|
|
+ gCurrent_graf_data->start_race_panel_left,
|
|
y_coord,
|
|
201,
|
|
gFont_7,
|
|
the_chunk->text[k]);
|
|
y_coord += gFont_7->glyph_y + gFont_7->glyph_y / 2;
|
|
}
|
|
}
|
|
}
|
|
} else if (gProgram_state.view_type == eVT_Info) {
|
|
for (j = 0; j < gCurrent_race.text_chunk_count; j++) {
|
|
the_chunk = &gCurrent_race.text_chunks[j];
|
|
if (GetPanelFlicFrameIndex(0) >= the_chunk->frame_cue && GetPanelFlicFrameIndex(0) < the_chunk->frame_end) {
|
|
y_coord = the_chunk->y_coord * gGraf_specs[gGraf_spec_index].total_height / 200
|
|
+ gCurrent_graf_data->start_race_panel_top;
|
|
for (k = 0; k < the_chunk->line_count; k++) {
|
|
TransBrPixelmapText(
|
|
gBack_screen,
|
|
the_chunk->x_coord * gGraf_specs[gGraf_spec_index].total_width / 320
|
|
+ gCurrent_graf_data->start_race_panel_left,
|
|
y_coord,
|
|
201,
|
|
gFont_7,
|
|
the_chunk->text[k]);
|
|
y_coord += gFont_7->glyph_y + gFont_7->glyph_y / 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
test = KevKeyService();
|
|
if (*test) {
|
|
test2 = *test;
|
|
}
|
|
if (test[0] == 0x27645433 && test[1] == 0x758f0015) {
|
|
// cheat code: "KEVWOZEAR"
|
|
gProgram_state.game_completed = 1;
|
|
DRS3StartSound(gEffects_outlet, 3202);
|
|
DRS3StartSound(gEffects_outlet, 3202);
|
|
}
|
|
if (test[0] == 0x33f75455 && test[1] == 0xC10AAAF2) {
|
|
// cheat code: "IWANTTOFIDDLE"
|
|
|
|
char s[128];
|
|
FILE* f;
|
|
int i;
|
|
|
|
// Jeff
|
|
assert(strlen(gApplication_path) < 120);
|
|
|
|
PathCat(s, gApplication_path, "ACTORS");
|
|
PathCat(s, s, "PROG.ACT");
|
|
PDFileUnlock(s);
|
|
f = fopen(s, "wb");
|
|
if (f != NULL) {
|
|
DRS3StartSound(gEffects_outlet, 9000);
|
|
if (gDecode_thing) {
|
|
for (i = 0; i < strlen(gDecode_string); i++) {
|
|
gDecode_string[i] -= 50;
|
|
}
|
|
fputs(gDecode_string, f);
|
|
for (i = 0; i < strlen(gDecode_string); i++) {
|
|
gDecode_string[i] += 50;
|
|
}
|
|
} else {
|
|
for (i = 0; i < 20; i++) {
|
|
fputs("*************", f);
|
|
}
|
|
}
|
|
gDecode_thing ^= 0x40u;
|
|
fclose(f);
|
|
EncodeAllFilesInDirectory("");
|
|
EncodeAllFilesInDirectory("CARS");
|
|
EncodeAllFilesInDirectory("NONCARS");
|
|
EncodeAllFilesInDirectory("RACES");
|
|
EncodeAllFilesInDirectory("32X20X8");
|
|
EncodeAllFilesInDirectory("64X48X8");
|
|
PathCat(s, "32X20X8", "CARS");
|
|
EncodeAllFilesInDirectory(s);
|
|
PathCat(s, "64X48X8", "CARS");
|
|
EncodeAllFilesInDirectory(s);
|
|
PathCat(s, "32X20X8", "FONTS");
|
|
EncodeAllFilesInDirectory(s);
|
|
PathCat(s, "64X48X8", "FONTS");
|
|
EncodeAllFilesInDirectory(s);
|
|
}
|
|
DRS3StartSound(gEffects_outlet, 9000);
|
|
}
|
|
}
|
|
|
|
// IDA: tSO_result __usercall DoSelectRace@<EAX>(int *pSecond_time_around@<EAX>)
|
|
tSO_result DoSelectRace(int* pSecond_time_around) {
|
|
static tFlicette flicker_on[7] = {
|
|
{ 43, { 224, 448 }, { 28, 67 } },
|
|
{ 43, { 224, 448 }, { 56, 134 } },
|
|
{ 43, { 224, 448 }, { 85, 204 } },
|
|
{ 43, { 224, 448 }, { 113, 271 } },
|
|
{ 43, { 224, 448 }, { 147, 353 } },
|
|
{ 221, { 30, 60 }, { 79, 190 } },
|
|
{ 221, { 30, 60 }, { 79, 190 } }
|
|
};
|
|
|
|
static tFlicette flicker_off[7] = {
|
|
{ 42, { 224, 448 }, { 28, 67 } },
|
|
{ 42, { 224, 448 }, { 56, 134 } },
|
|
{ 42, { 224, 448 }, { 85, 204 } },
|
|
{ 42, { 224, 448 }, { 113, 271 } },
|
|
{ 42, { 224, 448 }, { 147, 353 } },
|
|
{ 220, { 30, 60 }, { 79, 190 } },
|
|
{ 220, { 30, 60 }, { 79, 190 } }
|
|
};
|
|
|
|
static tFlicette push[7] = {
|
|
{ 195, { 224, 448 }, { 28, 67 } },
|
|
{ -1, { 224, 448 }, { 56, 134 } },
|
|
{ 200, { 224, 448 }, { 85, 204 } },
|
|
{ 202, { 224, 448 }, { 113, 271 } },
|
|
{ 201, { 224, 448 }, { 147, 353 } },
|
|
{ 222, { 30, 60 }, { 79, 190 } },
|
|
{ 225, { 30, 60 }, { 119, 286 } }
|
|
};
|
|
|
|
static tMouse_area mouse_areas[7] = {
|
|
{ { 224, 448 }, { 28, 67 }, { 287, 574 }, { 48, 115 }, 0, 0, 0, NULL },
|
|
{ { 224, 448 }, { 56, 134 }, { 287, 574 }, { 76, 182 }, 1, 0, 0, NULL },
|
|
{ { 224, 448 }, { 85, 204 }, { 287, 574 }, { 105, 252 }, 2, 0, 0, NULL },
|
|
{ { 224, 448 }, { 113, 271 }, { 287, 574 }, { 133, 319 }, 3, 0, 0, NULL },
|
|
{ { 224, 448 }, { 147, 353 }, { 287, 574 }, { 167, 401 }, 4, 0, 0, NULL },
|
|
{ { 30, 60 },
|
|
{ 79, 190 },
|
|
{ 45, 90 },
|
|
{ 106, 254 },
|
|
-1,
|
|
0,
|
|
0,
|
|
&UpClickOpp },
|
|
{ { 30, 60 },
|
|
{ 119, 286 },
|
|
{ 45, 90 },
|
|
{ 146, 350 },
|
|
-1,
|
|
0,
|
|
0,
|
|
&DownClickOpp }
|
|
};
|
|
|
|
static tInterface_spec interface_spec = {
|
|
0, // initial_imode
|
|
191, // first_opening_flic
|
|
190, // second_opening_flic
|
|
0, // end_flic_go_ahead
|
|
0, // end_flic_escaped
|
|
0, // end_flic_otherwise
|
|
6, // flic_bunch_to_load
|
|
{ -1, 0 }, // move_left_new_mode
|
|
{ 0, -4 }, // move_left_delta
|
|
{ 0, 1 }, // move_left_min
|
|
{ 0, 1 }, // move_left_max
|
|
{ &TryToMoveToArrows, NULL }, // move_left_proc
|
|
{ -1, 0 }, // move_right_new_mode
|
|
{ 0, -4 }, // move_right_delta
|
|
{ 0, 1 }, // move_right_min
|
|
{ 0, 1 }, // move_right_max
|
|
{ &TryToMoveToArrows, NULL }, // move_right_proc
|
|
{ -1, -1 }, // move_up_new_mode
|
|
{ -1, 0 }, // move_up_delta
|
|
{ 0, 5 }, // move_up_min
|
|
{ 4, 5 }, // move_up_max
|
|
{ NULL, &UpOpponent }, // move_up_proc
|
|
{ -1, -1 }, // move_down_new_mode
|
|
{ 1, 0 }, // move_down_delta
|
|
{ 0, 5 }, // move_down_min
|
|
{ 4, 5 }, // move_down_max
|
|
{ NULL, &DownOpponent }, // move_down_proc
|
|
{ 1, 1 }, // go_ahead_allowed
|
|
{ &StartRaceGoAhead, NULL }, // go_ahead_proc
|
|
{ 1, 1 }, // escape_allowed
|
|
{ NULL, NULL }, // escape_proc
|
|
NULL, // exit_proc
|
|
&SelectRaceDraw, // draw_proc
|
|
0u, // time_out
|
|
NULL, // start_proc1
|
|
&SelectRaceStart, // start_proc2
|
|
&SelectRaceDone, // done_proc
|
|
0, // font_needed
|
|
{ 0, 0 }, // typeable
|
|
NULL, // get_original_string
|
|
-1, // escape_code
|
|
1, // dont_save_or_load
|
|
7, // number_of_button_flics
|
|
flicker_on, // flicker_on_flics
|
|
flicker_off, // flicker_off_flics
|
|
push, // pushed_flics
|
|
7, // number_of_mouse_areas
|
|
mouse_areas, // mouse_areas
|
|
0, // number_of_recopy_areas
|
|
NULL // recopy_areas
|
|
};
|
|
|
|
int result;
|
|
int default_choice;
|
|
int suggested;
|
|
int old_current_race;
|
|
LOG_TRACE("(%p)", pSecond_time_around);
|
|
|
|
suggested = SuggestRace();
|
|
if (!*pSecond_time_around) {
|
|
gProgram_state.current_race_index = suggested;
|
|
SelectOpponents(&gCurrent_race);
|
|
}
|
|
gProgram_state.parts_shop_visited = 0;
|
|
gProgram_state.dont_load = 1;
|
|
gDeceased_image = LoadPixelmap("DECEASED.PIX");
|
|
InitialiseFlicPanel(
|
|
0,
|
|
gCurrent_graf_data->start_race_panel_left,
|
|
gCurrent_graf_data->start_race_panel_top,
|
|
gCurrent_graf_data->start_race_panel_right - gCurrent_graf_data->start_race_panel_left,
|
|
gCurrent_graf_data->start_race_panel_bottom - gCurrent_graf_data->start_race_panel_top);
|
|
LoadRaceInfo(gProgram_state.current_race_index, &gCurrent_race);
|
|
do {
|
|
gProgram_state.view_type = 0;
|
|
gOpponent_index = 0;
|
|
gStart_interface_spec = &interface_spec;
|
|
if (gFaded_palette || gCurrent_splash) {
|
|
result = DoInterfaceScreen(&interface_spec, 1, 4);
|
|
} else {
|
|
result = DoInterfaceScreen(&interface_spec, 0, 4);
|
|
}
|
|
|
|
if (result == 0 || result == 2 || result == 3) {
|
|
DisposeFlicPanel(0);
|
|
|
|
if (result == 2) {
|
|
if (harness_game_info.mode == eGame_carmageddon_demo || harness_game_info.mode == eGame_splatpack_demo || harness_game_info.mode == eGame_splatpack_xmas_demo) {
|
|
DoFeatureUnavailableInDemo();
|
|
} else {
|
|
RunFlic(192);
|
|
DoPartsShop(0);
|
|
}
|
|
} else if (result == 3) {
|
|
RunFlic(192);
|
|
DoChangeCar();
|
|
} else if (result == 0) {
|
|
RunFlic(192);
|
|
old_current_race = gProgram_state.current_race_index;
|
|
DoChangeRace();
|
|
if (gProgram_state.current_race_index != old_current_race) {
|
|
DisposeRaceInfo(&gCurrent_race);
|
|
SelectOpponents(&gCurrent_race);
|
|
LoadRaceInfo(gProgram_state.current_race_index, &gCurrent_race);
|
|
}
|
|
}
|
|
InitialiseFlicPanel(
|
|
0,
|
|
gCurrent_graf_data->start_race_panel_left,
|
|
gCurrent_graf_data->start_race_panel_top,
|
|
gCurrent_graf_data->start_race_panel_right - gCurrent_graf_data->start_race_panel_left,
|
|
gCurrent_graf_data->start_race_panel_bottom - gCurrent_graf_data->start_race_panel_top);
|
|
}
|
|
} while (result >= 0 && result != 4);
|
|
BrPixelmapFree(gDeceased_image);
|
|
FillInRaceInfo(&gCurrent_race);
|
|
DisposeRaceInfo(&gCurrent_race);
|
|
DisposeFlicPanel(0);
|
|
*pSecond_time_around = 1;
|
|
gProgram_state.dont_load = 0;
|
|
if (result >= 0) {
|
|
*pSecond_time_around = 1;
|
|
if (gProgram_state.parts_shop_visited || !PartsShopRecommended()) {
|
|
FadePaletteDown();
|
|
return eSO_continue;
|
|
} else {
|
|
RunFlic(192);
|
|
return DoAutoPartsShop();
|
|
}
|
|
} else {
|
|
RunFlic(192);
|
|
gDisallow_abandon_race = 1;
|
|
return eSO_main_menu_invoked;
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall DrawGridCar(int pX@<EAX>, int pY@<EDX>, br_pixelmap *pImage@<EBX>)
|
|
void DrawGridCar(int pX, int pY, br_pixelmap* pImage) {
|
|
LOG_TRACE("(%d, %d, %p)", pX, pY, pImage);
|
|
|
|
if (gCurrent_graf_data->grid_left_clip <= pX && pX + pImage->width < gCurrent_graf_data->grid_right_clip) {
|
|
DRPixelmapRectangleMaskedCopy(gBack_screen, pX, pY, pImage, 0, 0, pImage->width, pImage->height);
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall DrawGrid(int pOffset@<EAX>, int pDraw_it@<EDX>)
|
|
void DrawGrid(int pOffset, int pDraw_it) {
|
|
int i;
|
|
int j;
|
|
int y;
|
|
int x;
|
|
int str_x;
|
|
int width_job;
|
|
int done_highest;
|
|
int str_index;
|
|
int swap_1_x = 0;
|
|
int swap_1_y = 0;
|
|
int swap_2_x = 0;
|
|
int swap_2_y = 0;
|
|
br_pixelmap* the_image = NULL;
|
|
br_pixelmap* swap_1_image = NULL;
|
|
br_pixelmap* swap_2_image = NULL;
|
|
char numbers_str[4][100];
|
|
char total_str[256];
|
|
tU32 the_time;
|
|
LOG_TRACE("(%d, %d)", pOffset, pDraw_it);
|
|
|
|
done_highest = 0;
|
|
str_index = 0;
|
|
|
|
memset(numbers_str, 0, sizeof(numbers_str));
|
|
memset(total_str, 0, sizeof(total_str));
|
|
|
|
the_time = PDGetTotalTime();
|
|
BrPixelmapRectangleFill(
|
|
gBack_screen,
|
|
gCurrent_graf_data->grid_left_clip,
|
|
gCurrent_graf_data->grid_top_clip,
|
|
gCurrent_graf_data->grid_right_clip - gCurrent_graf_data->grid_left_clip,
|
|
gCurrent_graf_data->grid_bottom_clip - gCurrent_graf_data->grid_top_clip,
|
|
0);
|
|
for (i = 0; i < gCurrent_race.number_of_racers; i++) {
|
|
if (gCurrent_race.opponent_list[i].index == -1) {
|
|
the_image = gProgram_state.current_car.grid_icon_image;
|
|
} else {
|
|
the_image = gCurrent_race.opponent_list[i].car_spec->grid_icon_image;
|
|
}
|
|
y = gCurrent_graf_data->grid_top_y
|
|
+ i % 2 * gCurrent_graf_data->grid_y_pitch
|
|
- the_image->height / 2
|
|
- gGrid_y_adjust;
|
|
x = gCurrent_graf_data->grid_left_x
|
|
+ i % 2 * gCurrent_graf_data->grid_x_stagger
|
|
+ i / 2 * gCurrent_graf_data->grid_x_pitch
|
|
- pOffset;
|
|
if (i == gSwap_grid_1) {
|
|
swap_1_x = x;
|
|
swap_1_y = y;
|
|
swap_1_image = the_image;
|
|
} else if (i == gSwap_grid_2) {
|
|
swap_2_x = x;
|
|
swap_2_y = y;
|
|
swap_2_image = the_image;
|
|
} else if (gCurrent_race.opponent_list[i].index != -1 || the_time % 900 / 300) {
|
|
DrawGridCar(x, y, the_image);
|
|
}
|
|
if (!done_highest && gCurrent_race.opponent_list[i].ranking >= gProgram_state.rank) {
|
|
done_highest = 1;
|
|
if (x - gCurrent_graf_data->grid_marker_margin >= gCurrent_graf_data->grid_left_clip
|
|
&& x + the_image->width < gCurrent_graf_data->grid_right_clip) {
|
|
BrPixelmapLine(
|
|
gBack_screen,
|
|
x - gCurrent_graf_data->grid_marker_margin,
|
|
y - gCurrent_graf_data->grid_marker_margin,
|
|
x - gCurrent_graf_data->grid_marker_margin,
|
|
y + gCurrent_graf_data->grid_marker_margin + the_image->height,
|
|
45);
|
|
BrPixelmapLine(
|
|
gBack_screen,
|
|
x - gCurrent_graf_data->grid_marker_margin,
|
|
y - gCurrent_graf_data->grid_marker_margin,
|
|
x + gCurrent_graf_data->grid_marker_x_len,
|
|
y - gCurrent_graf_data->grid_marker_margin,
|
|
45);
|
|
BrPixelmapLine(
|
|
gBack_screen,
|
|
x - gCurrent_graf_data->grid_marker_margin,
|
|
y + gCurrent_graf_data->grid_marker_margin + the_image->height,
|
|
x + gCurrent_graf_data->grid_marker_x_len,
|
|
y + gCurrent_graf_data->grid_marker_margin + the_image->height,
|
|
45);
|
|
}
|
|
}
|
|
if (gCurrent_race.opponent_list[i].index < 0) {
|
|
str_index = 2;
|
|
} else if (gProgram_state.rank <= gCurrent_race.opponent_list[i].ranking) {
|
|
if (str_index >= 2) {
|
|
str_index = 3;
|
|
} else {
|
|
str_index = 1;
|
|
}
|
|
}
|
|
if (gCurrent_race.opponent_list[i].index >= 0) {
|
|
if (gOpponents[gCurrent_race.opponent_list[i].index].car_number <= 0
|
|
|| gOpponents[gCurrent_race.opponent_list[i].index].car_number >= 100) {
|
|
if (gOpponents[gCurrent_race.opponent_list[i].index].car_number < 0) {
|
|
sprintf(&numbers_str[str_index][strlen(numbers_str[str_index])], "%c ", ':');
|
|
}
|
|
} else {
|
|
sprintf(
|
|
&numbers_str[str_index][strlen(numbers_str[str_index])],
|
|
"%d ",
|
|
gOpponents[gCurrent_race.opponent_list[i].index].car_number);
|
|
}
|
|
} else {
|
|
if (gProgram_state.frank_or_anniness == eAnnie) {
|
|
sprintf(&numbers_str[str_index][strlen(numbers_str[str_index])], "%c ", '<');
|
|
} else {
|
|
sprintf(&numbers_str[str_index][strlen(numbers_str[str_index])], "%c ", ';');
|
|
}
|
|
}
|
|
}
|
|
if (gSwap_grid_1 >= 0) {
|
|
DrawGridCar(
|
|
gGrid_transition_stage * (swap_2_x - swap_1_x) / 100 + swap_1_x,
|
|
gGrid_transition_stage * (swap_2_y - swap_1_y) / 100 + swap_1_y,
|
|
swap_1_image);
|
|
DrawGridCar(
|
|
gGrid_transition_stage * (swap_1_x - swap_2_x) / 100 + swap_2_x,
|
|
gGrid_transition_stage * (swap_1_y - swap_2_y) / 100 + swap_2_y,
|
|
swap_2_image);
|
|
}
|
|
if (gDraw_grid_status == eGrid_draw_all) {
|
|
if (strlen(numbers_str[3])) {
|
|
numbers_str[3][strlen(numbers_str[3]) - 1] = '\0';
|
|
} else {
|
|
numbers_str[2][strlen(numbers_str[2]) - 1] = '\0';
|
|
}
|
|
strcpy(total_str, numbers_str[0]);
|
|
for (i = 1; i < COUNT_OF(numbers_str); i++) {
|
|
strcat(total_str, numbers_str[i]);
|
|
}
|
|
str_x = (gCurrent_graf_data->grid_numbers_left + gCurrent_graf_data->grid_numbers_right) / 2
|
|
- (BrPixelmapTextWidth(gBack_screen, gBig_font, total_str) / 2);
|
|
BrPixelmapRectangleFill(
|
|
gBack_screen,
|
|
gCurrent_graf_data->grid_numbers_left,
|
|
gCurrent_graf_data->grid_numbers_top,
|
|
gCurrent_graf_data->grid_numbers_right - gCurrent_graf_data->grid_numbers_left,
|
|
gBig_font->glyph_y,
|
|
0);
|
|
gGrid_number_x_coords[0] = str_x - 3 - gCurrent_graf_data->grid_numbers_left;
|
|
for (i = 0; i < 4; ++i) {
|
|
if (i != 2 || the_time % 900 / 300) {
|
|
TransBrPixelmapText(
|
|
gBack_screen,
|
|
str_x,
|
|
gCurrent_graf_data->grid_numbers_top,
|
|
gGrid_number_colour[i],
|
|
gBig_font,
|
|
numbers_str[i]);
|
|
}
|
|
str_x += BrPixelmapTextWidth(gBack_screen, gBig_font, numbers_str[i]);
|
|
}
|
|
for (i = gCurrent_race.number_of_racers - 1; i > 0; i--) {
|
|
for (j = strlen(total_str) - 2; j >= 0; j--) {
|
|
if (total_str[j] == ' ') {
|
|
total_str[j + 1] = '\0';
|
|
break;
|
|
}
|
|
}
|
|
gGrid_number_x_coords[i] = gGrid_number_x_coords[0] + BrPixelmapTextWidth(gBack_screen, gBig_font, total_str);
|
|
}
|
|
}
|
|
if (pDraw_it) {
|
|
PDScreenBufferSwap(0);
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall MoveGrid(int pFrom@<EAX>, int pTo@<EDX>, tS32 pTime_to_move@<EBX>)
|
|
void MoveGrid(int pFrom, int pTo, tS32 pTime_to_move) {
|
|
tS32 start_time;
|
|
tS32 the_time;
|
|
int move_distance;
|
|
int pitch;
|
|
LOG_TRACE("(%d, %d, %d)", pFrom, pTo, pTime_to_move);
|
|
|
|
pitch = gCurrent_graf_data->grid_x_pitch;
|
|
start_time = PDGetTotalTime();
|
|
while (1) {
|
|
the_time = PDGetTotalTime();
|
|
if (start_time + pTime_to_move <= the_time) {
|
|
break;
|
|
}
|
|
DrawGrid(pitch * pFrom + pitch * (pTo - pFrom) * (the_time - start_time) / pTime_to_move, 1);
|
|
}
|
|
DrawGrid(pitch * pTo, 1);
|
|
}
|
|
|
|
// IDA: int __usercall CalcGridOffset@<EAX>(int pPosition@<EAX>)
|
|
int CalcGridOffset(int pPosition) {
|
|
LOG_TRACE("(%d)", pPosition);
|
|
|
|
return pPosition / 2 - 1;
|
|
}
|
|
|
|
// IDA: void __usercall GridDraw(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>)
|
|
void GridDraw(int pCurrent_choice, int pCurrent_mode) {
|
|
LOG_TRACE8("(%d, %d)", pCurrent_choice, pCurrent_mode);
|
|
|
|
if (gDraw_grid_status > eGrid_draw_none) {
|
|
DrawGrid(gCurrent_graf_data->grid_x_pitch * CalcGridOffset(gOur_starting_position), 0);
|
|
}
|
|
}
|
|
|
|
// IDA: void __usercall ActuallySwapOrder(int pFirst_index@<EAX>, int pSecond_index@<EDX>)
|
|
void ActuallySwapOrder(int pFirst_index, int pSecond_index) {
|
|
tOpp_spec temp_opp;
|
|
LOG_TRACE("(%d, %d)", pFirst_index, pSecond_index);
|
|
|
|
temp_opp = gCurrent_race.opponent_list[pFirst_index];
|
|
gCurrent_race.opponent_list[pFirst_index] = gCurrent_race.opponent_list[pSecond_index];
|
|
gCurrent_race.opponent_list[pSecond_index] = temp_opp;
|
|
gOur_starting_position = pSecond_index;
|
|
|
|
// LOG_DEBUG("first %d, second %d", gCurrent_race.opponent_list[pFirst_index].index, gCurrent_race.opponent_list[pSecond_index].index);
|
|
}
|
|
|
|
// IDA: void __usercall DoGridTransition(int pFirst_index@<EAX>, int pSecond_index@<EDX>)
|
|
void DoGridTransition(int pFirst_index, int pSecond_index) {
|
|
tU32 start_time;
|
|
tU32 the_time;
|
|
LOG_TRACE("(%d, %d)", pFirst_index, pSecond_index);
|
|
|
|
if (pFirst_index != pSecond_index) {
|
|
start_time = PDGetTotalTime();
|
|
gSwap_grid_1 = pFirst_index;
|
|
gSwap_grid_2 = pSecond_index;
|
|
while (1) {
|
|
the_time = PDGetTotalTime();
|
|
if (start_time + 150 <= the_time) {
|
|
break;
|
|
}
|
|
RemoveTransientBitmaps(1);
|
|
gGrid_transition_stage = 100 * (the_time - start_time) / 150;
|
|
DrawGrid(gCurrent_graf_data->grid_x_pitch * CalcGridOffset(gOur_starting_position), 0);
|
|
ProcessFlicQueue(gFrame_period);
|
|
DoMouseCursor();
|
|
PDScreenBufferSwap(0);
|
|
}
|
|
gSwap_grid_1 = -1;
|
|
gSwap_grid_2 = -1;
|
|
ActuallySwapOrder(pFirst_index, pSecond_index);
|
|
MoveGrid(CalcGridOffset(pFirst_index), CalcGridOffset(pSecond_index), 150);
|
|
}
|
|
}
|
|
|
|
// IDA: void __cdecl ChallengeStart()
|
|
void ChallengeStart(void) {
|
|
br_pixelmap* the_map;
|
|
int i;
|
|
int j;
|
|
int line_count;
|
|
int dare_index;
|
|
FILE* f;
|
|
tPath_name the_path;
|
|
char s[256];
|
|
LOG_TRACE("()");
|
|
|
|
InitialiseFlicPanel(
|
|
0,
|
|
gCurrent_graf_data->start_race_panel_left,
|
|
gCurrent_graf_data->start_race_panel_top,
|
|
gCurrent_graf_data->start_race_panel_right - gCurrent_graf_data->start_race_panel_left,
|
|
gCurrent_graf_data->start_race_panel_bottom - gCurrent_graf_data->start_race_panel_top);
|
|
ChangePanelFlic(
|
|
0,
|
|
gOpponents[gChallenger_index__racestrt].mug_shot_image_data,
|
|
gOpponents[gChallenger_index__racestrt].mug_shot_image_data_length);
|
|
if (gScreen->row_bytes < 0) {
|
|
BrFatal("C:\\Msdev\\Projects\\DethRace\\Racestrt.c", 2610, "Bruce bug at line %d, file C:\\Msdev\\Projects\\DethRace\\Racestrt.c", 50);
|
|
}
|
|
the_map = DRPixelmapAllocate(
|
|
#ifdef DETHRACE_3DFX_PATCH
|
|
BR_PMT_INDEX_8,
|
|
#else
|
|
gScreen->type,
|
|
#endif
|
|
gCurrent_graf_data->dare_mugshot_width,
|
|
gCurrent_graf_data->dare_mugshot_height,
|
|
0,
|
|
0);
|
|
|
|
BrPixelmapRectangleCopy(the_map, 0, 0, GetPanelPixelmap(0), gCurrent_graf_data->dare_mug_left_margin, gCurrent_graf_data->dare_mug_top_margin, gCurrent_graf_data->dare_mugshot_width, gCurrent_graf_data->dare_mugshot_height);
|
|
DisposeFlicPanel(0);
|
|
TellyInImage(the_map, gCurrent_graf_data->dare_mugshot_left, gCurrent_graf_data->dare_mugshot_top);
|
|
BrPixelmapFree(the_map);
|
|
the_map = DRPixelmapAllocate(
|
|
#ifdef DETHRACE_3DFX_PATCH
|
|
BR_PMT_INDEX_8,
|
|
#else
|
|
gScreen->type,
|
|
#endif
|
|
gCurrent_graf_data->dare_text_width,
|
|
gCurrent_graf_data->dare_mugshot_height,
|
|
0,
|
|
0);
|
|
BrPixelmapFill(the_map, 0);
|
|
TransBrPixelmapText(the_map, 0, 0, 1u, gBig_font, gOpponents[gChallenger_index__racestrt].abbrev_name);
|
|
PathCat(the_path, gApplication_path, "DARES.TXT");
|
|
f = DRfopen(the_path, "rt");
|
|
if (f == NULL) {
|
|
FatalError(kFatalError_OpenDareTxt);
|
|
}
|
|
|
|
dare_index = IRandomBetween(0, GetAnInt(f) - 1);
|
|
for (i = 0; i < dare_index; i++) {
|
|
line_count = GetAnInt(f);
|
|
for (j = 0; j < line_count; j++) {
|
|
GetALineAndDontArgue(f, s);
|
|
}
|
|
}
|
|
line_count = GetAnInt(f);
|
|
for (i = 0; i < line_count; i++) {
|
|
GetALineAndDontArgue(f, s);
|
|
TransBrPixelmapText(the_map, 0, 2 * (i + 1) * gBig_font->glyph_y, 0x86u, gBig_font, s);
|
|
}
|
|
fclose(f);
|
|
BrPixelmapLine(the_map, 0, gBig_font->glyph_y + 2, the_map->width, gBig_font->glyph_y + 2, 45);
|
|
TellyInImage(the_map, gCurrent_graf_data->dare_text_left, gCurrent_graf_data->dare_mugshot_top);
|
|
BrPixelmapFree(the_map);
|
|
UnlockOpponentMugshot(gChallenger_index__racestrt);
|
|
gDare_start_time = PDGetTotalTime();
|
|
}
|
|
|
|
// IDA: int __usercall CheckNextStage@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int CheckNextStage(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
if (gDare_start_time && (unsigned int)(PDGetTotalTime() - gDare_start_time) >= 7500) {
|
|
BrPixelmapRectangleFill(
|
|
gBack_screen,
|
|
gCurrent_graf_data->grid_left_clip,
|
|
gCurrent_graf_data->dare_mugshot_top,
|
|
gCurrent_graf_data->grid_right_clip - gCurrent_graf_data->grid_left_clip,
|
|
gCurrent_graf_data->dare_mugshot_height,
|
|
0);
|
|
DoGridTransition(gOur_starting_position, gChallenger_position);
|
|
gDraw_grid_status = eGrid_draw_icons_only;
|
|
gDare_start_time = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall ChallengeDone@<EAX>(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>, int pGo_ahead@<EBX>, int pEscaped@<ECX>, int pTimed_out)
|
|
int ChallengeDone(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);
|
|
|
|
if (!pEscaped || gDare_start_time) {
|
|
if (!pEscaped && gDare_start_time) {
|
|
ActuallySwapOrder(gOur_starting_position, gChallenger_position);
|
|
ChallengeOccurred(gChallenger_index__racestrt, 1);
|
|
}
|
|
} else {
|
|
DoGridTransition(gOur_starting_position, gOriginal_position);
|
|
ActuallySwapOrder(gOur_starting_position, gOriginal_position);
|
|
ChallengeOccurred(gChallenger_index__racestrt, 0);
|
|
}
|
|
ChallengeOccurred(gChallenger_index__racestrt, pEscaped == 0);
|
|
if (pTimed_out) {
|
|
return 0;
|
|
} else {
|
|
return pCurrent_choice;
|
|
}
|
|
}
|
|
|
|
// IDA: void __cdecl DoChallengeScreen()
|
|
void DoChallengeScreen(void) {
|
|
static tFlicette flicker_on[2] = { { 43, { 54, 108 }, { 157, 377 } }, { 43, { 218, 436 }, { 157, 377 } } };
|
|
static tFlicette flicker_off[2] = { { 42, { 54, 108 }, { 157, 377 } }, { 42, { 218, 436 }, { 157, 377 } } };
|
|
static tFlicette push[2] = { { 304, { 54, 108 }, { 157, 377 } }, { 305, { 218, 436 }, { 157, 377 } } };
|
|
static tMouse_area mouse_areas[2] = {
|
|
{ { 54, 108 }, { 157, 377 }, { 117, 234 }, { 178, 427 }, 0, 0, 0, NULL },
|
|
{ { 218, 436 }, { 157, 377 }, { 281, 562 }, { 178, 427 }, 1, 0, 0, NULL }
|
|
};
|
|
static tInterface_spec interface_spec = {
|
|
0, // initial_imode
|
|
301, // first_opening_flic
|
|
0, // second_opening_flic
|
|
-1, // end_flic_go_ahead
|
|
-1, // end_flic_escaped
|
|
-1, // end_flic_otherwise
|
|
0, // flic_bunch_to_load
|
|
{ -1, 0 }, // move_left_new_mode
|
|
{ -1, 0 }, // move_left_delta
|
|
{ 0, 0 }, // move_left_min
|
|
{ 1, 0 }, // move_left_max
|
|
{ NULL, NULL }, // move_left_proc
|
|
{ -1, 0 }, // move_right_new_mode
|
|
{ 1, 0 }, // move_right_delta
|
|
{ 0, 0 }, // move_right_min
|
|
{ 1, 0 }, // move_right_max
|
|
{ NULL, NULL }, // move_right_proc
|
|
{ -1, 0 }, // move_up_new_mode
|
|
{ 0, 0 }, // move_up_delta
|
|
{ 0, 0 }, // move_up_min
|
|
{ 0, 0 }, // move_up_max
|
|
{ NULL, NULL }, // move_up_proc
|
|
{ -1, 0 }, // move_down_new_mode
|
|
{ 0, 0 }, // move_down_delta
|
|
{ 0, 0 }, // move_down_min
|
|
{ 0, 0 }, // move_down_max
|
|
{ NULL, NULL }, // move_down_proc
|
|
{ 1, 1 }, // go_ahead_allowed
|
|
{ NULL, NULL }, // go_ahead_proc
|
|
{ 1, 1 }, // escape_allowed
|
|
{ NULL, NULL }, // escape_proc
|
|
&CheckNextStage, // exit_proc
|
|
&GridDraw, // draw_proc
|
|
0u, // time_out
|
|
NULL, // start_proc1
|
|
&ChallengeStart, // start_proc2
|
|
&ChallengeDone, // done_proc
|
|
0, // font_needed
|
|
{ 0, 0 }, // typeable
|
|
NULL, // get_original_string
|
|
1, // escape_code
|
|
1, // dont_save_or_load
|
|
2, // number_of_button_flics
|
|
flicker_on, // flicker_on_flics
|
|
flicker_off, // flicker_off_flics
|
|
push, // pushed_flics
|
|
2, // number_of_mouse_areas
|
|
mouse_areas, // mouse_areas
|
|
0, // number_of_recopy_areas
|
|
NULL // recopy_areas
|
|
};
|
|
|
|
int result;
|
|
LOG_TRACE("()");
|
|
|
|
gOriginal_position = gOur_starting_position;
|
|
gChallenger_position = IRandomBetween(0, 1);
|
|
if (gOpponents[gCurrent_race.opponent_list[gChallenger_position].index].car_number < 0) {
|
|
gChallenger_position ^= 1u;
|
|
}
|
|
gChallenger_index__racestrt = gCurrent_race.opponent_list[gChallenger_position].index;
|
|
LoadOpponentMugShot(gChallenger_index__racestrt);
|
|
gDraw_grid_status = eGrid_draw_none;
|
|
gGrid_y_adjust = gCurrent_graf_data->dare_y_adjust;
|
|
DoInterfaceScreen(&interface_spec, 0, 0);
|
|
}
|
|
|
|
// IDA: int __usercall GridDone@<EAX>(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>, int pGo_ahead@<EBX>, int pEscaped@<ECX>, int pTimed_out)
|
|
int GridDone(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);
|
|
|
|
if (pTimed_out) {
|
|
return 0;
|
|
}
|
|
if (pEscaped) {
|
|
return -1;
|
|
}
|
|
return pCurrent_choice;
|
|
}
|
|
|
|
// IDA: void __cdecl GridStart()
|
|
void GridStart(void) {
|
|
LOG_TRACE("()");
|
|
|
|
MoveGrid(-2, CalcGridOffset(gOur_starting_position), 400);
|
|
PrintMemoryDump(0, "IN GRID SCREEN");
|
|
}
|
|
|
|
// IDA: int __usercall GridMoveLeft@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int GridMoveLeft(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
if (gOur_starting_position
|
|
&& gCurrent_race.opponent_list[gOur_starting_position - 1].ranking >= gProgram_state.rank) {
|
|
AddToFlicQueue(
|
|
gStart_interface_spec->pushed_flics[1].flic_index,
|
|
gStart_interface_spec->pushed_flics[1].x[gGraf_data_index],
|
|
gStart_interface_spec->pushed_flics[1].y[gGraf_data_index],
|
|
1);
|
|
DRS3StartSound(gEffects_outlet, 3000);
|
|
DoGridTransition(gOur_starting_position, gOur_starting_position - 1);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall GridMoveRight@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int GridMoveRight(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
if (gOur_starting_position < gCurrent_race.number_of_racers - 1) {
|
|
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(gEffects_outlet, 3000);
|
|
DoGridTransition(gOur_starting_position, gOur_starting_position + 1);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall GridClickCar@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>, int pX_offset@<EBX>, int pY_offset@<ECX>)
|
|
int GridClickCar(int* pCurrent_choice, int* pCurrent_mode, int pX_offset, int pY_offset) {
|
|
int rel_pos;
|
|
int new_pos;
|
|
int base_pos;
|
|
int x_coord;
|
|
LOG_TRACE("(%p, %p, %d, %d)", pCurrent_choice, pCurrent_mode, pX_offset, pY_offset);
|
|
|
|
rel_pos = ((gCurrent_graf_data->grid_bottom_clip - gCurrent_graf_data->grid_top_clip) / 2) < pY_offset;
|
|
if (rel_pos) {
|
|
pX_offset -= gCurrent_graf_data->grid_x_stagger;
|
|
}
|
|
x_coord = pX_offset / gCurrent_graf_data->grid_x_pitch;
|
|
if (x_coord > 2) {
|
|
x_coord = 2;
|
|
}
|
|
new_pos = 2 * x_coord + rel_pos + (gOur_starting_position & ~1) - 2;
|
|
if (new_pos >= 0 && new_pos < gCurrent_race.number_of_racers && gProgram_state.rank < gCurrent_race.opponent_list[new_pos].ranking) {
|
|
DRS3StartSound(gEffects_outlet, 3000);
|
|
DoGridTransition(gOur_starting_position, new_pos);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall GridClickNumbers@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>, int pX_offset@<EBX>, int pY_offset@<ECX>)
|
|
int GridClickNumbers(int* pCurrent_choice, int* pCurrent_mode, int pX_offset, int pY_offset) {
|
|
int new_pos;
|
|
int i;
|
|
LOG_TRACE("(%p, %p, %d, %d)", pCurrent_choice, pCurrent_mode, pX_offset, pY_offset);
|
|
|
|
new_pos = -1;
|
|
for (i = 0; i < gCurrent_race.number_of_racers; i++) {
|
|
if (gGrid_number_x_coords[i] <= pX_offset && (gCurrent_race.number_of_racers - 1 == i || pX_offset < gGrid_number_x_coords[i + 1])) {
|
|
new_pos = i;
|
|
break;
|
|
}
|
|
}
|
|
if (new_pos >= 0 && new_pos < gCurrent_race.number_of_racers && gProgram_state.rank <= gCurrent_race.opponent_list[new_pos].ranking) {
|
|
DRS3StartSound(gEffects_outlet, 3000);
|
|
DoGridTransition(gOur_starting_position, new_pos);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall GridClickLeft@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>, int pX_offset@<EBX>, int pY_offset@<ECX>)
|
|
int GridClickLeft(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);
|
|
|
|
GridMoveLeft(pCurrent_choice, pCurrent_mode);
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall GridClickRight@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>, int pX_offset@<EBX>, int pY_offset@<ECX>)
|
|
int GridClickRight(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);
|
|
|
|
GridMoveRight(pCurrent_choice, pCurrent_mode);
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall CheckChallenge@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int CheckChallenge(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE8("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
if (!gChallenge_time || PDGetTotalTime() < gChallenge_time) {
|
|
return 0;
|
|
}
|
|
*pCurrent_choice = -2;
|
|
return 1;
|
|
}
|
|
|
|
// IDA: int __usercall FindBestPos@<EAX>(int pOur_rank@<EAX>)
|
|
int FindBestPos(int pOur_rank) {
|
|
int i;
|
|
LOG_TRACE("(%d)", pOur_rank);
|
|
|
|
for (i = gCurrent_race.number_of_racers - 1; i >= 0; i--) {
|
|
if (gCurrent_race.opponent_list[i].ranking < pOur_rank) {
|
|
return i + 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// IDA: int __usercall SortGridFunction@<EAX>(void *pFirst_one@<EAX>, void *pSecond_one@<EDX>)
|
|
int SortGridFunction(const void* pFirst_one, const void* pSecond_one) {
|
|
LOG_TRACE("(%p, %p)", pFirst_one, pSecond_one);
|
|
|
|
return ((tOpp_spec*)pFirst_one)->ranking - ((tOpp_spec*)pSecond_one)->ranking;
|
|
}
|
|
|
|
// IDA: void __cdecl SortOpponents()
|
|
void SortOpponents(void) {
|
|
int i;
|
|
LOG_TRACE("()");
|
|
|
|
for (i = 0; gCurrent_race.number_of_racers > i; ++i) {
|
|
if (gCurrent_race.opponent_list[i].index < 0) {
|
|
return;
|
|
}
|
|
}
|
|
qsort(gCurrent_race.opponent_list, gCurrent_race.number_of_racers, sizeof(tOpp_spec), SortGridFunction);
|
|
gBest_pos_available = FindBestPos(gProgram_state.rank);
|
|
gOur_starting_position = gCurrent_race.number_of_racers - 70 * (gCurrent_race.number_of_racers - gBest_pos_available) / 100;
|
|
for (i = gCurrent_race.number_of_racers; i > gOur_starting_position; i--) {
|
|
gCurrent_race.opponent_list[i] = gCurrent_race.opponent_list[i - 1];
|
|
}
|
|
gCurrent_race.opponent_list[gOur_starting_position].index = -1;
|
|
gCurrent_race.opponent_list[gOur_starting_position].ranking = gProgram_state.rank;
|
|
gCurrent_race.opponent_list[gOur_starting_position].car_spec = &gProgram_state.current_car;
|
|
gCurrent_race.number_of_racers++;
|
|
}
|
|
|
|
// IDA: tSO_result __cdecl DoGridPosition()
|
|
tSO_result DoGridPosition(void) {
|
|
static tFlicette flicker_on[3] = {
|
|
{ 43, { 240, 480 }, { 158, 379 } },
|
|
{ 293, { 56, 112 }, { 151, 362 } },
|
|
{ 296, { 136, 272 }, { 151, 362 } }
|
|
};
|
|
|
|
static tFlicette flicker_off[3] = {
|
|
{ 42, { 240, 480 }, { 158, 379 } },
|
|
{ 292, { 56, 112 }, { 151, 362 } },
|
|
{ 295, { 136, 272 }, { 151, 362 } }
|
|
};
|
|
|
|
static tFlicette push[3] = {
|
|
{ 154, { 240, 480 }, { 158, 379 } },
|
|
{ 294, { 56, 112 }, { 151, 362 } },
|
|
{ 297, { 136, 272 }, { 151, 362 } }
|
|
};
|
|
static tMouse_area mouse_areas[5] = {
|
|
{ { 240, 480 }, { 158, 379 }, { 305, 610 }, { 178, 427 }, 0, 0, 0, NULL },
|
|
{ { 56, 112 },
|
|
{ 151, 362 },
|
|
{ 91, 182 },
|
|
{ 158, 379 },
|
|
-1,
|
|
0,
|
|
0,
|
|
GridClickLeft },
|
|
{ { 136, 272 },
|
|
{ 151, 362 },
|
|
{ 171, 342 },
|
|
{ 158, 379 },
|
|
-1,
|
|
0,
|
|
0,
|
|
GridClickRight },
|
|
{ { 52, 104 },
|
|
{ 56, 134 },
|
|
{ 269, 538 },
|
|
{ 141, 338 },
|
|
-1,
|
|
0,
|
|
0,
|
|
GridClickCar },
|
|
{ { 60, 120 },
|
|
{ 163, 391 },
|
|
{ 235, 470 },
|
|
{ 176, 422 },
|
|
-1,
|
|
0,
|
|
0,
|
|
GridClickNumbers }
|
|
};
|
|
|
|
static tInterface_spec interface_spec = {
|
|
0, // initial_imode
|
|
290, // first_opening_flic
|
|
0, // second_opening_flic
|
|
0, // end_flic_go_ahead
|
|
0, // end_flic_escaped
|
|
0, // end_flic_otherwise
|
|
8, // flic_bunch_to_load
|
|
{ -1, 0 }, // move_left_new_mode
|
|
{ 0, 0 }, // move_left_delta
|
|
{ 0, 0 }, // move_left_min
|
|
{ 0, 0 }, // move_left_max
|
|
{ GridMoveLeft, NULL }, // move_left_proc
|
|
{ -1, 0 }, // move_right_new_mode
|
|
{ 0, 0 }, // move_right_delta
|
|
{ 0, 0 }, // move_right_min
|
|
{ 0, 0 }, // move_right_max
|
|
{ GridMoveRight, NULL }, // move_right_proc
|
|
{ -1, 0 }, // move_up_new_mode
|
|
{ 0, 0 }, // move_up_delta
|
|
{ 0, 0 }, // move_up_min
|
|
{ 0, 0 }, // move_up_max
|
|
{ GridMoveLeft, NULL }, // move_up_proc
|
|
{ -1, 0 }, // move_down_new_mode
|
|
{ 0, 0 }, // move_down_delta
|
|
{ 0, 0 }, // move_down_min
|
|
{ 0, 0 }, // move_down_max
|
|
{ GridMoveRight, NULL }, // move_down_proc
|
|
{ 1, 1 }, // go_ahead_allowed
|
|
{ NULL, NULL }, // go_ahead_proc
|
|
{ 1, 1 }, // escape_allowed
|
|
{ NULL, NULL }, // escape_proc
|
|
CheckChallenge, // exit_proc
|
|
GridDraw, // draw_proc
|
|
0u, // time_out
|
|
NULL, // start_proc1
|
|
GridStart, // start_proc2
|
|
GridDone, // done_proc
|
|
0, // font_needed
|
|
{ 0, 0 }, // typeable
|
|
NULL, // get_original_string
|
|
-1, // escape_code
|
|
1, // dont_save_or_load
|
|
3, // number_of_button_flics
|
|
flicker_on, // flicker_on_flics
|
|
flicker_off, // flicker_off_flics
|
|
push, // pushed_flics
|
|
5, // number_of_mouse_areas
|
|
mouse_areas, // mouse_areas
|
|
0, // number_of_recopy_areas
|
|
NULL // recopy_areas
|
|
};
|
|
|
|
int result;
|
|
LOG_TRACE("()");
|
|
|
|
gStart_interface_spec = &interface_spec;
|
|
if (!gAusterity_mode) {
|
|
LoadGridIcons(&gCurrent_race);
|
|
}
|
|
gSwap_grid_1 = -1;
|
|
gSwap_grid_2 = -1;
|
|
gDraw_grid_status = eGrid_draw_all;
|
|
gGrid_y_adjust = 0;
|
|
SortOpponents();
|
|
if (!gAusterity_mode) {
|
|
if (gBest_pos_available > 1
|
|
&& (gOpponents[gCurrent_race.opponent_list[0].index].car_number >= 0
|
|
|| gOpponents[gCurrent_race.opponent_list[1].index].car_number >= 0)
|
|
&& PercentageChance(10)) {
|
|
gChallenge_time = PDGetTotalTime() + IRandomBetween(1000, 10000);
|
|
} else {
|
|
gChallenge_time = 0;
|
|
}
|
|
result = DoInterfaceScreen(&interface_spec, 0, 0);
|
|
if (result >= 0) {
|
|
FadePaletteDown();
|
|
} else {
|
|
RunFlic(291);
|
|
}
|
|
if (result == -1) {
|
|
return eSO_main_menu_invoked;
|
|
}
|
|
if (result == -2) {
|
|
DoChallengeScreen();
|
|
}
|
|
DisposeGridIcons(&gCurrent_race);
|
|
}
|
|
return eSO_continue;
|
|
}
|
|
|
|
// IDA: void __cdecl CheckPlayersAreResponding()
|
|
void CheckPlayersAreResponding(void) {
|
|
int i;
|
|
tU32 time;
|
|
tNet_message* message;
|
|
LOG_TRACE("()");
|
|
|
|
time = PDGetTotalTime();
|
|
for (i = 0; i < gNumber_of_net_players; i++) {
|
|
if (i != gThis_net_player_index && time - gNet_players[i].last_heard_from_him > 20000) {
|
|
gNet_players[i].player_status = ePlayer_status_not_responding;
|
|
}
|
|
}
|
|
if (gNet_mode == eNet_mode_client && gLast_host_query == 0) {
|
|
message = NetBuildMessage(NETMSGID_HOSTQUERY, 0);
|
|
NetGuaranteedSendMessageToHost(gCurrent_net_game, message, NULL);
|
|
gLast_host_query = time;
|
|
}
|
|
}
|
|
|
|
// IDA: void __cdecl NetSynchStartStart()
|
|
void NetSynchStartStart(void) {
|
|
LOG_TRACE("()");
|
|
|
|
CheckPlayersAreResponding();
|
|
}
|
|
|
|
// IDA: void __usercall DrawAnItem(int pX@<EAX>, int pY_index@<EDX>, int pFont_index@<EBX>, char *pText@<ECX>)
|
|
// Suffix added to avoid duplicate symbol
|
|
void DrawAnItem__racestrt(int pX, int pY_index, int pFont_index, char* pText) {
|
|
LOG_TRACE("(%d, %d, %d, \"%s\")", pX, pY_index, pFont_index, pText);
|
|
|
|
TransBrPixelmapText(gBack_screen,
|
|
pX,
|
|
gCurrent_graf_data->start_synch_top + gCurrent_graf_data->start_synch_y_pitch * pY_index,
|
|
pFont_index,
|
|
gFont_7,
|
|
pText);
|
|
}
|
|
|
|
// IDA: void __usercall NetSynchStartDraw(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>)
|
|
void NetSynchStartDraw(int pCurrent_choice, int pCurrent_mode) {
|
|
int i;
|
|
int number_ready;
|
|
char s[256];
|
|
LOG_TRACE("(%d, %d)", pCurrent_choice, pCurrent_mode);
|
|
|
|
number_ready = 0;
|
|
CheckPlayersAreResponding();
|
|
NetPlayerStatusChanged(ePlayer_status_ready);
|
|
for (i = 0; i < COUNT_OF(gNet_players); i++) {
|
|
BrPixelmapRectangleFill(gBack_screen,
|
|
gCurrent_graf_data->start_synch_x_0,
|
|
gCurrent_graf_data->start_synch_y_pitch * i + gCurrent_graf_data->start_synch_top,
|
|
gCurrent_graf_data->start_synch_x_r - gCurrent_graf_data->start_synch_x_1,
|
|
gFont_7->glyph_y,
|
|
0);
|
|
}
|
|
for (i = 0; i < gNumber_of_net_players; i++) {
|
|
strcpy(s, gNet_players[i].player_name);
|
|
if (gNet_players[i].host) {
|
|
strcat(s, " -");
|
|
strcat(s, GetMiscString(kMiscString_HOST));
|
|
strcat(s, "-");
|
|
}
|
|
TurnOffPaletteConversion();
|
|
DRPixelmapRectangleMaskedCopy(gBack_screen,
|
|
gCurrent_graf_data->start_synch_x_0,
|
|
gCurrent_graf_data->start_synch_top + 1 + gCurrent_graf_data->start_synch_y_pitch * i,
|
|
gIcons_pix_low_res, /* DOS version uses low res, Windows version uses normal res */
|
|
0,
|
|
gNet_players[i].car_index * gCurrent_graf_data->net_head_icon_height,
|
|
gIcons_pix_low_res->width, /* DOS version uses low res, Windows version uses normal res */
|
|
gCurrent_graf_data->net_head_icon_height);
|
|
TurnOnPaletteConversion();
|
|
DrawAnItem__racestrt(
|
|
gCurrent_graf_data->start_synch_x_1,
|
|
i,
|
|
(gNet_players[i].player_status == ePlayer_status_ready) ? 66 : 4,
|
|
s);
|
|
DrawAnItem__racestrt(gCurrent_graf_data->start_synch_x_2,
|
|
i,
|
|
(gNet_players[i].player_status == ePlayer_status_ready) ? 83 : ((gNet_players[i].player_status == ePlayer_status_not_responding) ? 247 : 4),
|
|
GetMiscString(kMiscString_NetworkPlayerStatus_START + gNet_players[i].player_status));
|
|
if (gNet_players[i].player_status == ePlayer_status_ready) {
|
|
number_ready++;
|
|
}
|
|
}
|
|
if (gNet_mode == eNet_mode_host && gNumber_of_net_players == number_ready && gNumber_of_net_players > 1 && (!gNo_races_yet || gNumber_of_net_players == 6)) {
|
|
SignalToStartRace();
|
|
gSynch_race_start = 1;
|
|
}
|
|
}
|
|
|
|
// IDA: int __usercall NetSynchStartDone@<EAX>(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>, int pGo_ahead@<EBX>, int pEscaped@<ECX>, int pTimed_out)
|
|
int NetSynchStartDone(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);
|
|
|
|
if (pEscaped) {
|
|
pCurrent_choice = -1;
|
|
} else if (pCurrent_choice == 0) {
|
|
gProgram_state.prog_status = eProg_idling;
|
|
}
|
|
return pCurrent_choice;
|
|
}
|
|
|
|
// IDA: int __usercall NetSynchStartGoAhead@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int NetSynchStartGoAhead(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
if (*pCurrent_choice == 0 || (gNet_mode == eNet_mode_host && *pCurrent_choice >= 0)) {
|
|
if (*pCurrent_choice == 0) {
|
|
gProgram_state.prog_status = eProg_idling;
|
|
return 1;
|
|
} else if (gNet_mode == eNet_mode_host && *pCurrent_choice == 1) {
|
|
if (gNumber_of_net_players <= 1) {
|
|
DRS3StartSound(gEffects_outlet, 3100);
|
|
return 0;
|
|
} else {
|
|
SignalToStartRace();
|
|
gSynch_race_start = 1;
|
|
gNo_races_yet = 0;
|
|
return 1;
|
|
}
|
|
} else {
|
|
return 1;
|
|
}
|
|
} else {
|
|
DRS3StartSound(gEffects_outlet, 3100);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// IDA: int __usercall ExitWhenReady@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
|
|
int ExitWhenReady(int* pCurrent_choice, int* pCurrent_mode) {
|
|
LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
|
|
|
|
if (!gSynch_race_start && gProgram_state.prog_status != eProg_game_starting) {
|
|
if (gProgram_state.prog_status == eProg_idling) {
|
|
*pCurrent_choice = 0;
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
} else {
|
|
*pCurrent_choice = 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
// IDA: tSO_result __usercall NetSynchRaceStart2@<EAX>(tNet_synch_mode pMode@<EAX>)
|
|
tSO_result NetSynchRaceStart2(tNet_synch_mode pMode) {
|
|
static tFlicette flicker_on_hf[2] = {
|
|
{ 321, { 219, 112 }, { 172, 362 } },
|
|
{ 321, { 39, 480 }, { 172, 379 } },
|
|
};
|
|
static tFlicette flicker_off_hf[2] = {
|
|
{ 322, { 219, 112 }, { 172, 362 } },
|
|
{ 322, { 39, 480 }, { 172, 379 } },
|
|
};
|
|
static tFlicette push_hf[2] = {
|
|
{ 206, { 219, 112 }, { 172, 362 } },
|
|
{ 205, { 39, 480 }, { 172, 379 } },
|
|
};
|
|
static tMouse_area mouse_areas_hf[2] = {
|
|
{ { 219, 480 }, { 172, 379 }, { 282, 182 }, { 192, 427 }, 0, 0, 0, NULL },
|
|
{ { 39, 112 }, { 172, 362 }, { 102, 182 }, { 192, 379 }, 1, 0, 0, NULL },
|
|
};
|
|
static tInterface_spec interface_spec_hf = {
|
|
0,
|
|
203,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
8,
|
|
{ -1, 0 },
|
|
{ 1, 0 },
|
|
{ 0, 0 },
|
|
{ 1, 0 },
|
|
{ NULL, NULL },
|
|
{ -1, 0 },
|
|
{ 1, 0 },
|
|
{ 0, 0 },
|
|
{ 1, 0 },
|
|
{ NULL, NULL },
|
|
{ -1, 0 },
|
|
{ 1, 0 },
|
|
{ 0, 0 },
|
|
{ 1, 0 },
|
|
{ NULL, NULL },
|
|
{ -1, 0 },
|
|
{ 1, 0 },
|
|
{ 0, 0 },
|
|
{ 1, 0 },
|
|
{ NULL, NULL },
|
|
{ 1, 1 },
|
|
{ NetSynchStartGoAhead, NetSynchStartGoAhead },
|
|
{ 1, 1 },
|
|
{ NULL, NULL },
|
|
ExitWhenReady,
|
|
NetSynchStartDraw,
|
|
0,
|
|
NULL,
|
|
NetSynchStartStart,
|
|
NetSynchStartDone,
|
|
0,
|
|
{ 0, 0 },
|
|
NULL,
|
|
-1,
|
|
1,
|
|
COUNT_OF(flicker_on_hf),
|
|
flicker_on_hf,
|
|
flicker_off_hf,
|
|
push_hf,
|
|
COUNT_OF(mouse_areas_hf),
|
|
mouse_areas_hf,
|
|
0,
|
|
NULL,
|
|
};
|
|
static tFlicette flicker_on_hs[1] = {
|
|
{ 321, { 219, 112 }, { 172, 362 } },
|
|
};
|
|
static tFlicette flicker_off_hs[1] = {
|
|
{ 322, { 219, 112 }, { 172, 362 } },
|
|
};
|
|
static tFlicette push_hs[1] = {
|
|
{ 206, { 219, 112 }, { 172, 362 } },
|
|
};
|
|
static tMouse_area mouse_areas_hs[1] = {
|
|
{ { 219, 480 }, { 172, 379 }, { 282, 182 }, { 192, 427 }, 0, 0, 0, NULL },
|
|
};
|
|
static tInterface_spec interface_spec_hs = {
|
|
0, 209, 0, 0, 0, 0, 8,
|
|
{ -1, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { NULL, NULL },
|
|
{ -1, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { NULL, NULL },
|
|
{ -1, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { NULL, NULL },
|
|
{ -1, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { NULL, NULL },
|
|
{ 1, 1 }, { NetSynchStartGoAhead, NetSynchStartGoAhead }, { 1, 1 }, { NULL, NULL },
|
|
ExitWhenReady, NetSynchStartDraw, 0, NULL, NetSynchStartStart, NetSynchStartDone, 0, { 0, 0 },
|
|
NULL, -1, 1,
|
|
COUNT_OF(flicker_on_hs), flicker_on_hs, flicker_off_hs, push_hs,
|
|
COUNT_OF(mouse_areas_hs), mouse_areas_hs, 0, NULL
|
|
};
|
|
static tFlicette flicker_on_c[1] = {
|
|
{ 321, { 219, 112 }, { 172, 362 } },
|
|
};
|
|
static tFlicette flicker_off_c[1] = {
|
|
{ 322, { 219, 112 }, { 172, 362 } },
|
|
};
|
|
static tFlicette push_c[1] = {
|
|
{ 207, { 219, 112 }, { 172, 362 } },
|
|
};
|
|
static tMouse_area mouse_areas_c[1] = {
|
|
{ { 219, 112 }, { 172, 362 }, { 282, 182 }, { 192, 379 }, 0, 0, 0, NULL },
|
|
};
|
|
static tInterface_spec interface_spec_c = {
|
|
0, 204, 0, 0, 0, 0, 8,
|
|
{ -1, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { NULL, NULL },
|
|
{ -1, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { NULL, NULL },
|
|
{ -1, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { NULL, NULL },
|
|
{ -1, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { NULL, NULL },
|
|
{ 1, 1 }, { NetSynchStartGoAhead, NetSynchStartGoAhead }, { 1, 1 }, { NULL, NULL },
|
|
ExitWhenReady, NetSynchStartDraw, 0, NULL, NetSynchStartStart, NetSynchStartDone, 0, { 0, 0 },
|
|
NULL, -1, 1,
|
|
COUNT_OF(flicker_on_c), flicker_on_c, flicker_off_c, push_c,
|
|
COUNT_OF(mouse_areas_c), mouse_areas_c, 0, NULL
|
|
};
|
|
int result;
|
|
LOG_TRACE("(%d)", pMode);
|
|
|
|
if (pMode != eNet_synch_client) {
|
|
if (gCurrent_net_game->status.stage == eNet_game_starting) {
|
|
gCurrent_net_game->status.stage = eNet_game_ready;
|
|
}
|
|
SetUpNetCarPositions();
|
|
// gNet_synch_start = PDGetTotalTime();
|
|
}
|
|
TurnOnPaletteConversion();
|
|
switch (pMode) {
|
|
case eNet_synch_host_first:
|
|
result = DoInterfaceScreen(&interface_spec_hf, 0, 1);
|
|
break;
|
|
case eNet_synch_host_subsequent:
|
|
result = DoInterfaceScreen(&interface_spec_hs, 0, -1);
|
|
break;
|
|
case eNet_synch_client:
|
|
result = DoInterfaceScreen(&interface_spec_c, 0, -1);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
TurnOffPaletteConversion();
|
|
FadePaletteDown();
|
|
if (result > -2 && result < 1) {
|
|
NetLeaveGame(gCurrent_net_game);
|
|
}
|
|
return eSO_continue;
|
|
}
|
|
|
|
// IDA: tSO_result __cdecl NetSynchRaceStart()
|
|
tSO_result NetSynchRaceStart(void) {
|
|
LOG_TRACE("()");
|
|
|
|
SuspendPendingFlic();
|
|
if (gNet_mode == eNet_mode_host) {
|
|
if (gNo_races_yet) {
|
|
return NetSynchRaceStart2(eNet_synch_host_first);
|
|
} else {
|
|
return NetSynchRaceStart2(eNet_synch_host_subsequent);
|
|
}
|
|
} else {
|
|
return NetSynchRaceStart2(eNet_synch_client);
|
|
}
|
|
}
|