Subversion Repositories Games.Carmageddon

Rev

Rev 18 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
#include "newgame.h"
2
#include "cutscene.h"
3
#include "displays.h"
4
#include "drmem.h"
5
#include "errors.h"
6
#include "flicplay.h"
7
#include "globvars.h"
8
#include "globvrpb.h"
9
#include "grafdata.h"
10
#include "graphics.h"
11
#include "harness/config.h"
12
#include "harness/hooks.h"
13
#include "harness/trace.h"
14
#include "init.h"
15
#include "input.h"
16
#include "intrface.h"
17
#include "loading.h"
18
#include "network.h"
19
#include "pd/sys.h"
20
#include "racestrt.h"
21
#include "sound.h"
22
#include "structur.h"
23
#include "utility.h"
24
#include "world.h"
25
#include <stdlib.h>
26
#include <string.h>
27
 
28
tU8* gFrank_flic_data;
29
tU8* gAnne_flic_data;
30
int gNet_storage_allocated;
31
// clang-format off
32
tRadio_bastards gRadio_bastards__newgame[11] = { // suffix added to avoid duplicate symbol
33
    { 1,  32, 0, { 245,   0,   0,   0,   0, }, },
34
    { 1,  43, 0, { 245,   0,   0,   0,   0, }, },
35
    { 1,  54, 0, { 245,   0,   0,   0,   0, }, },
36
    { 1,  65, 0, { 245,   0,   0,   0,   0, }, },
37
    { 1,  76, 0, { 245,   0,   0,   0,   0, }, },
38
    { 2,  86, 0, {  81, 150,   0,   0,   0, }, },
39
    { 2,  97, 0, {  81, 150,   0,   0,   0, }, },
40
    { 2, 108, 0, {  81, 150,   0,   0,   0, }, },
41
    { 2, 119, 0, { 150, 201,   0,   0,   0, }, },
42
    { 4, 130, 0, { 115, 150, 183, 215,   0, }, },
43
    { 5, 141, 0, { 142, 160, 182, 204, 230, }, },
44
};
45
// clang-format on
46
char _name1[] = "xxxxxxxx.TXT"; // keep compiler happy
47
char _name2[] = "yyyyyyyy.TXT"; // keep compiler happy
48
char* gBasic_car_names[2] = { _name1, _name2 };
49
tNet_game_options gNet_settings[8];
50
tJoinable_game gGames_to_join[6];
51
tNet_game_options* gOptions;
52
int gNet_target[7];
53
int gLast_graph_sel__newgame;                   // suffix added to avoid duplicate symbol
54
tInterface_spec* gThe_interface_spec__newgame;  // suffix added to avoid duplicate symbol
55
tNet_sequence_type gNet_race_sequence__newgame; // suffix added to avoid duplicate symbol
56
tNet_game_type gLast_game_type;
57
int gCurrent_net_game_count;
58
tU32 gAnne_flic_data_length;
59
int gShifted_default_yet;
60
char* gNet_name;
61
tU32 gFrank_flic_data_length;
62
int gLast_net_choose_box;
63
int gCurrent_game_selection;
64
int gRace_index;
65
int gRadio_selected;
66
 
67
// IDA: void __cdecl StartRollingPlayerNamesIn()
68
void StartRollingPlayerNamesIn(void) {
69
    int i;
70
    LOG_TRACE("()");
71
 
72
    for (i = 0; i < COUNT_OF(gCurrent_graf_data->player_name_x); i++) {
73
        SetSlotXY(i, gCurrent_graf_data->player_name_x[i], gCurrent_graf_data->player_name_y);
74
        AddRollingString(gProgram_state.player_name[i], gCurrent_graf_data->player_name_x[i], gCurrent_graf_data->player_name_y, eRT_alpha);
75
    }
76
}
77
 
78
// IDA: void __cdecl FrankAnneStart1()
79
void FrankAnneStart1(void) {
80
    LOG_TRACE("()");
81
 
82
    StartRollingPlayerNamesIn();
83
    if (gFrank_flic_data == NULL) {
84
        if (!LoadFlicData("FRANK.FLI", &gFrank_flic_data, &gFrank_flic_data_length)) {
85
            FatalError(kFatalError_LoadOpponentMugShotFile);
86
        }
87
    } else {
88
        MAMSLock((void**)&gFrank_flic_data);
89
    }
90
    if (!gAnne_flic_data) {
91
        if (!LoadFlicData("ANNIE.FLI", &gAnne_flic_data, &gAnne_flic_data_length)) {
92
            FatalError(kFatalError_LoadOpponentMugShotFile);
93
        }
94
    } else {
95
        MAMSLock((void**)&gAnne_flic_data);
96
    }
97
    InitialiseFlicPanel(0,
98
        gCurrent_graf_data->frank_panel_left,
99
        gCurrent_graf_data->frank_panel_top,
100
        gCurrent_graf_data->frank_panel_right - gCurrent_graf_data->frank_panel_left,
101
        gCurrent_graf_data->frank_panel_bottom - gCurrent_graf_data->frank_panel_top);
102
    InitialiseFlicPanel(1,
103
        gCurrent_graf_data->anne_panel_left,
104
        gCurrent_graf_data->anne_panel_top,
105
        gCurrent_graf_data->anne_panel_right - gCurrent_graf_data->anne_panel_left,
106
        gCurrent_graf_data->anne_panel_bottom - gCurrent_graf_data->anne_panel_top);
107
}
108
 
109
// IDA: void __cdecl FrankAnneStart2()
110
void FrankAnneStart2(void) {
111
    LOG_TRACE("()");
112
 
113
    ChangePanelFlic(0, gFrank_flic_data, gFrank_flic_data_length);
114
    ChangePanelFlic(1, gAnne_flic_data, gAnne_flic_data_length);
115
    TellyInImage(GetPanelPixelmap(0), gCurrent_graf_data->frank_panel_left, gCurrent_graf_data->frank_panel_top);
116
    TellyInImage(GetPanelPixelmap(1), gCurrent_graf_data->anne_panel_left, gCurrent_graf_data->anne_panel_top);
117
}
118
 
119
// IDA: void __usercall GetPlayerName(int pStarting_to_type@<EAX>, int pCurrent_choice@<EDX>, char *pString@<EBX>, int *pMax_length@<ECX>)
120
void GetPlayerName(int pStarting_to_type, int pCurrent_choice, char* pString, int* pMax_length) {
121
    LOG_TRACE("(%d, %d, \"%s\", %p)", pStarting_to_type, pCurrent_choice, pString, pMax_length);
122
 
123
    strcpy(pString, gProgram_state.player_name[pCurrent_choice]);
124
    *pMax_length = PLAYER_NAME_MAX_LENGTH;
125
}
126
 
127
// IDA: int __usercall FrankAnneDone@<EAX>(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>, int pGo_ahead@<EBX>, int pEscaped@<ECX>, int pTimed_out)
128
int FrankAnneDone(int pCurrent_choice, int pCurrent_mode, int pGo_ahead, int pEscaped, int pTimed_out) {
129
    LOG_TRACE("(%d, %d, %d, %d, %d)", pCurrent_choice, pCurrent_mode, pGo_ahead, pEscaped, pTimed_out);
130
 
131
    RemoveTransientBitmaps(1);
132
    TellyOutImage(GetPanelPixelmap(1), gCurrent_graf_data->anne_panel_left, gCurrent_graf_data->anne_panel_top);
133
    TellyOutImage(GetPanelPixelmap(0), gCurrent_graf_data->frank_panel_left, gCurrent_graf_data->frank_panel_top);
134
    if (gFrank_flic_data) {
135
        MAMSUnlock((void**)&gFrank_flic_data);
136
    }
137
    if (gAnne_flic_data) {
138
        MAMSUnlock((void**)&gAnne_flic_data);
139
    }
140
    gProgram_state.frank_or_anniness = pCurrent_choice;
141
    GetTypedName(gProgram_state.player_name[pCurrent_choice], PLAYER_NAME_MAX_LENGTH);
142
    return pCurrent_choice;
143
}
144
 
145
// IDA: void __usercall FrankAnneDraw(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>)
146
void FrankAnneDraw(int pCurrent_choice, int pCurrent_mode) {
147
    LOG_TRACE9("(%d, %d)", pCurrent_choice, pCurrent_mode);
148
 
149
    if (gTyping) {
150
        if (GetTotalTime() & 0x100) {
151
            if (pCurrent_choice < 2) {
152
                TransDRPixelmapText(
153
                    gBack_screen,
154
                    gCurrent_graf_data->enter_name_x[pCurrent_choice],
155
                    gCurrent_graf_data->enter_name_y,
156
                    &gFonts[FONT_GRNLIT],
157
                    GetMiscString(kMiscString_ENTER_NAME),
158
                    gBack_screen->width);
159
            }
160
        }
161
    }
162
}
163
 
164
// IDA: int __cdecl FrankieOrAnnie()
165
int FrankieOrAnnie(void) {
166
    static tFlicette flicker_on[3] = {
167
        { 83, { 61, 122 }, { 52, 125 } },
168
        { 83, { 184, 398 }, { 52, 125 } },
169
        { 43, { 215, 430 }, { 158, 379 } }
170
    };
171
    static tFlicette flicker_off[3] = {
172
        { 82, { 61, 122 }, { 52, 125 } },
173
        { 82, { 184, 398 }, { 52, 125 } },
174
        { 42, { 215, 430 }, { 158, 379 } }
175
    };
176
    static tFlicette push[3] = {
177
        { 83, { 61, 122 }, { 52, 125 } },
178
        { 83, { 184, 398 }, { 52, 125 } },
179
        { 45, { 215, 430 }, { 158, 379 } }
180
    };
181
    static tMouse_area mouse_areas[3] = {
182
        { { 55, 110 }, { 52, 125 }, { 161, 322 }, { 154, 370 }, 0, 0, 0, NULL },
183
        { { 178, 356 }, { 52, 125 }, { 295, 596 }, { 154, 370 }, 1, 0, 0, NULL },
184
        { { 215, 430 }, { 158, 379 }, { 278, 556 }, { 179, 430 }, 2, 1, 1, NULL }
185
    };
186
    static tRectile recopy_areas[2] = {
187
        { { 55, 110 }, { 132, 317 }, { 161, 322 }, { 154, 370 } },
188
        { { 178, 356 }, { 132, 317 }, { 295, 590 }, { 154, 370 } }
189
    };
190
    static tInterface_spec interface_spec = {
191
        0,               // initial_imode
192
        80,              // first_opening_flic
193
        0,               // second_opening_flic
194
        81,              // end_flic_go_ahead
195
        81,              // end_flic_escaped
196
        81,              // end_flic_otherwise
197
        0,               // flic_bunch_to_load
198
        { -1, -1 },      // move_left_new_mode
199
        { -1, 0 },       // move_left_delta
200
        { 0, 2 },        // move_left_min
201
        { 1, 2 },        // move_left_max
202
        { NULL, NULL },  // move_left_proc
203
        { -1, -1 },      // move_right_new_mode
204
        { 1, 0 },        // move_right_delta
205
        { 0, 2 },        // move_right_min
206
        { 1, 2 },        // move_right_max
207
        { NULL, NULL },  // move_right_proc
208
        { 1, 0 },        // move_up_new_mode
209
        { -2, -1 },      // move_up_delta
210
        { 2, 1 },        // move_up_min
211
        { 2, 1 },        // move_up_max
212
        { NULL, NULL },  // move_up_proc
213
        { 1, 0 },        // move_down_new_mode
214
        { 2, -1 },       // move_down_delta
215
        { 2, 1 },        // move_down_min
216
        { 2, 1 },        // move_down_max
217
        { NULL, NULL },  // move_down_proc
218
        { 1, 1 },        // go_ahead_allowed
219
        { NULL, NULL },  // go_ahead_proc
220
        { 1, 1 },        // escape_allowed
221
        { NULL, NULL },  // escape_proc
222
        NULL,            // exit_proc
223
        FrankAnneDraw,   // draw_proc
224
        0,               // time_out
225
        FrankAnneStart1, // start_proc1
226
        FrankAnneStart2, // start_proc2
227
        FrankAnneDone,   // done_proc
228
        1,               // font_needed
229
        { 1, 0 },        // typeable
230
        GetPlayerName,   // get_original_string
231
        2,               // escape_code
232
        1,               // dont_save_or_load
233
        3,               // number_of_button_flics
234
        flicker_on,      // flicker_on_flics
235
        flicker_off,     // flicker_off_flics
236
        push,            // pushed_flics
237
        3,               // number_of_mouse_areas
238
        mouse_areas,     // mouse_areas
239
        2,               // number_of_recopy_areas
240
        recopy_areas     // recopy_areas
241
    };
242
 
243
    int result;
244
    LOG_TRACE("()");
245
 
246
    LoadFont(FONT_GRNLIT);
247
    result = DoInterfaceScreen(&interface_spec, 0, gProgram_state.frank_or_anniness);
248
    DisposeFlicPanel(1);
249
    DisposeFlicPanel(0);
250
    DisposeFont(FONT_GRNLIT);
251
    return result < 2;
252
}
253
 
254
// IDA: int __cdecl SelectSkillLevel()
255
int SelectSkillLevel(void) {
256
    static tFlicette flicker_on[4] = {
257
        { 116, { 38, 76 }, { 55, 132 } },
258
        { 119, { 36, 72 }, { 83, 199 } },
259
        { 121, { 38, 76 }, { 111, 266 } },
260
        { 43, { 227, 454 }, { 158, 379 } }
261
    };
262
 
263
    static tFlicette flicker_off[4] = {
264
        { 115, { 38, 76 }, { 55, 132 } },
265
        { 118, { 36, 72 }, { 83, 199 } },
266
        { 120, { 38, 76 }, { 111, 266 } },
267
        { 42, { 227, 454 }, { 158, 379 } }
268
    };
269
 
270
    static tFlicette push[4] = {
271
        { 117, { 38, 76 }, { 55, 132 } },
272
        { 117, { 36, 72 }, { 83, 199 } },
273
        { 117, { 38, 76 }, { 111, 266 } },
274
        { 45, { 227, 454 }, { 158, 379 } }
275
    };
276
    static tMouse_area mouse_areas[4] = {
277
        { { 38, 76 }, { 55, 132 }, { 205, 410 }, { 69, 166 }, 0, 0, 0, NULL },
278
        { { 36, 72 }, { 83, 199 }, { 205, 410 }, { 98, 235 }, 1, 0, 0, NULL },
279
        { { 38, 76 }, { 111, 266 }, { 205, 410 }, { 125, 300 }, 2, 0, 0, NULL },
280
        { { 227, 454 }, { 158, 379 }, { 290, 580 }, { 178, 427 }, 3, 0, 0, NULL }
281
    };
282
 
283
    static tInterface_spec interface_spec = {
284
        0,              // initial_imode
285
        110,            // first_opening_flic
286
        0,              // second_opening_flic
287
        -1,             // end_flic_go_ahead
288
        111,            // end_flic_escaped
289
        -1,             // end_flic_otherwise
290
        0,              // flic_bunch_to_load
291
        { -1, 0 },      // move_left_new_mode
292
        { 0, 0 },       // move_left_delta
293
        { 0, 0 },       // move_left_min
294
        { 0, 0 },       // move_left_max
295
        { NULL, NULL }, // move_left_proc
296
        { -1, 0 },      // move_right_new_mode
297
        { 0, 0 },       // move_right_delta
298
        { 0, 0 },       // move_right_min
299
        { 0, 0 },       // move_right_max
300
        { NULL, NULL }, // move_right_proc
301
        { -1, 0 },      // move_up_new_mode
302
        { -1, 0 },      // move_up_delta
303
        { 0, 0 },       // move_up_min
304
        { 3, 0 },       // move_up_max
305
        { NULL, NULL }, // move_up_proc
306
        { -1, 0 },      // move_down_new_mode
307
        { 1, 0 },       // move_down_delta
308
        { 0, 0 },       // move_down_min
309
        { 3, 0 },       // move_down_max
310
        { NULL, NULL }, // move_down_proc
311
        { 1, 1 },       // go_ahead_allowed
312
        { NULL, NULL }, // go_ahead_proc
313
        { 1, 1 },       // escape_allowed
314
        { NULL, NULL }, // escape_proc
315
        NULL,           // exit_proc
316
        NULL,           // draw_proc
317
        0u,             // time_out
318
        NULL,           // start_proc1
319
        NULL,           // start_proc2
320
        NULL,           // done_proc
321
        0,              // font_needed
322
        { 0, 0 },       // typeable
323
        NULL,           // get_original_string
324
        3,              // escape_code
325
        1,              // dont_save_or_load
326
        4,              // number_of_button_flics
327
        flicker_on,     // flicker_on_flics
328
        flicker_off,    // flicker_off_flics
329
        push,           // pushed_flics
330
        4,              // number_of_mouse_areas
331
        mouse_areas,    // mouse_areas
332
        0,              // number_of_recopy_areas
333
        NULL            // recopy_areas
334
    };
335
 
336
    int result;
337
    LOG_TRACE("()");
338
 
339
    result = DoInterfaceScreen(&interface_spec, 0, gProgram_state.skill_level);
340
    if (result > 2) {
341
        return 0;
342
    }
343
    gProgram_state.skill_level = result;
344
    return 1;
345
}
346
 
347
// IDA: int __cdecl DoOnePlayerStart()
348
int DoOnePlayerStart(void) {
349
    int merrily_looping;
350
    tProgram_state saved_state;
351
    LOG_TRACE("()");
352
 
353
    if (OriginalCarmaCDinDrive()) {
354
        memcpy(&saved_state, &gProgram_state, sizeof(tProgram_state));
355
        do {
356
            merrily_looping = FrankieOrAnnie();
357
            if (!merrily_looping) {
358
                memcpy(&gProgram_state, &saved_state, sizeof(tProgram_state));
359
                return 0;
360
            }
361
            if ((harness_game_info.mode == eGame_carmageddon_demo || harness_game_info.mode == eGame_splatpack_demo || harness_game_info.mode == eGame_splatpack_xmas_demo) && gProgram_state.frank_or_anniness != eFrankie) {
362
                DoFeatureUnavailableInDemo();
363
                memset(&gProgram_state, 0, sizeof(gProgram_state));
364
                return 0;
365
            }
366
 
367
            if (SelectSkillLevel()) {
368
                DoGoToRaceAnimation();
369
                StartLoadingScreen();
370
                AboutToLoadFirstCar();
371
                PrintMemoryDump(0, "JUST BEFORE LOADING YOUR CAR");
372
                SwitchToRealResolution();
373
                LoadCar(
374
                    gBasic_car_names[gProgram_state.frank_or_anniness],
375
                    eDriver_local_human,
376
                    &gProgram_state.current_car,
377
                    gProgram_state.frank_or_anniness,
378
                    gProgram_state.player_name[gProgram_state.frank_or_anniness],
379
                    &gOur_car_storage_space);
380
                SwitchToLoresMode();
381
                SetCarStorageTexturingLevel(&gOur_car_storage_space, GetCarTexturingLevel(), eCTL_full);
382
                PrintMemoryDump(0, "IMMEDIATELY AFTER LOADING YOUR CAR");
383
                gNet_mode = eNet_mode_none;
384
                InitGame(0);
385
                merrily_looping = 0;
386
            }
387
        } while (merrily_looping);
388
        UnlockBunchOfFlics(4);
389
        return 1;
390
    } else {
391
        DoErrorInterface(kMiscString_PLEASE_INSERT_THE_CARMAGEDDON_CD);
392
        return 0;
393
    }
394
}
395
 
396
// IDA: int __usercall NewNetGameUp@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
397
int NewNetGameUp(int* pCurrent_choice, int* pCurrent_mode) {
398
    int new_sel;
399
    int i;
400
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
401
 
402
    DRS3StartSound(gEffects_outlet, 3000);
403
    if (*pCurrent_mode == 0) {
404
        gLast_graph_sel__newgame = COUNT_OF(gGames_to_join);
405
    }
406
    new_sel = -1;
407
    for (i = gLast_graph_sel__newgame - 1; i >= 0; i--) {
408
        gLast_graph_sel__newgame = i;
409
        if (gGames_to_join[i].game == NULL) {
410
            continue;
411
        }
412
        if (!gGames_to_join[i].game->options.open_game && !gGames_to_join[i].game->no_races_yet) {
413
            continue;
414
        }
415
        if (gGames_to_join[i].game->num_players > 5) {
416
            continue;
417
        }
418
        new_sel = i;
419
        break;
420
    }
421
    if (new_sel < 0) {
422
        gLast_graph_sel__newgame = -1;
423
        *pCurrent_choice = 0;
424
        *pCurrent_mode = 0;
425
    } else {
426
        gLast_graph_sel__newgame = new_sel;
427
        *pCurrent_choice = 2;
428
        *pCurrent_mode = 1;
429
    }
430
    return 1;
431
}
432
 
433
// IDA: int __usercall NewNetGameDown@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
434
int NewNetGameDown(int* pCurrent_choice, int* pCurrent_mode) {
435
    int new_sel;
436
    int i;
437
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
438
 
439
    DRS3StartSound(gEffects_outlet, 3000);
440
    if (*pCurrent_mode == 0) {
441
        gLast_graph_sel__newgame = -1;
442
    }
443
 
444
    new_sel = -1;
445
    for (i = gLast_graph_sel__newgame - 1; i < COUNT_OF(gGames_to_join); i++) {
446
        gLast_graph_sel__newgame = i;
447
        if (gGames_to_join[i].game == NULL) {
448
            continue;
449
        }
450
        if (!gGames_to_join[i].game->options.open_game && !gGames_to_join[i].game->no_races_yet) {
451
            continue;
452
        }
453
        if (gGames_to_join[i].game->num_players > 5) {
454
            continue;
455
        }
456
        new_sel = i;
457
        break;
458
    }
459
    if (new_sel < 0) {
460
        gLast_graph_sel__newgame = -1;
461
        *pCurrent_choice = 0;
462
        *pCurrent_mode = 0;
463
    } else {
464
        gLast_graph_sel__newgame = new_sel;
465
        *pCurrent_choice = 2;
466
        *pCurrent_mode = 1;
467
    }
468
    return 1;
469
}
470
 
471
// IDA: void __usercall DisposeJoinableGame(int pIndex@<EAX>)
472
void DisposeJoinableGame(int pIndex) {
473
    LOG_TRACE("(%d)", pIndex);
474
 
475
    NetDisposeGameDetails(gGames_to_join[pIndex].game);
476
    gGames_to_join[pIndex].game = NULL;
477
}
478
 
479
// IDA: void __usercall DrawAnItem(int pX@<EAX>, int pY_index@<EDX>, int pFont_index@<EBX>, char *pText@<ECX>)
480
void DrawAnItem__newgame(int pX, int pY_index, int pFont_index, char* pText) {
481
    LOG_TRACE("(%d, %d, %d, \"%s\")", pX, pY_index, pFont_index, pText);
482
 
483
    TransDRPixelmapText(gBack_screen,
484
        pX,
485
        gCurrent_graf_data->joinable_games_y + gCurrent_graf_data->joinable_games_y_pitch * pY_index,
486
        &gFonts[pFont_index],
487
        pText,
488
        pX + DRTextWidth(&gFonts[pFont_index], pText));
489
}
490
 
491
// IDA: void __usercall DrawColumnHeading(int pStr_index@<EAX>, int pX@<EDX>)
492
void DrawColumnHeading__newgame(int pStr_index, int pX) {
493
    LOG_TRACE("(%d, %d)", pStr_index, pX);
494
 
495
    TransDRPixelmapText(gBack_screen,
496
        pX,
497
        gCurrent_graf_data->joinable_games_y - gCurrent_graf_data->joinable_games_y_pitch,
11 pmbaty 498
        &gFonts[kFont_GRYLIT],
1 pmbaty 499
        GetMiscString(pStr_index),
11 pmbaty 500
        pX + DRTextWidth(&gFonts[kFont_GRYLIT], GetMiscString(pStr_index)));
1 pmbaty 501
}
502
 
503
// IDA: void __usercall DrawGames(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>)
504
void DrawGames(int pCurrent_choice, int pCurrent_mode) {
505
    int i;
506
    int font_index;
507
    int current_index;
508
    int x_coord;
509
    int y_coord;
510
    char s[256];
511
    //char* s2; // Pierre-Marie Baty -- unused variable
512
    //char* s3; // Pierre-Marie Baty -- unused variable
513
    LOG_TRACE("(%d, %d)", pCurrent_choice, pCurrent_mode);
514
 
515
    current_index = 0;
516
    BrPixelmapRectangleFill(gBack_screen,
517
        gCurrent_graf_data->joinable_games_sel_left,
518
        gCurrent_graf_data->joinable_games_sel_top_marg + gCurrent_graf_data->joinable_games_y,
519
        gCurrent_graf_data->joinable_games_sel_right - gCurrent_graf_data->joinable_games_sel_left,
520
        (COUNT_OF(gGames_to_join) + 1) * gCurrent_graf_data->joinable_games_y_pitch + gCurrent_graf_data->joinable_games_sel_bot_marg,
521
        0);
522
    if (gMouse_in_use && pCurrent_mode) {
523
        GetMousePosition(&x_coord, &y_coord);
524
        gLast_graph_sel__newgame = -1;
525
    }
526
    DrawColumnHeading__newgame(kMiscString_NetworkGamesTableHeading_HOST, gCurrent_graf_data->joinable_games_x_1);
527
    DrawColumnHeading__newgame(kMiscString_NetworkGamesTableHeading_GAME_TYPE, gCurrent_graf_data->joinable_games_x_2);
528
    DrawColumnHeading__newgame(kMiscString_NetworkGamesTableHeading_PLAYERS, gCurrent_graf_data->joinable_games_x_3);
529
    DrawColumnHeading__newgame(kMiscString_NetworkGamesTableHeading_STATUS, gCurrent_graf_data->joinable_games_x_4);
530
    BrPixelmapLine(gBack_screen,
531
        gCurrent_graf_data->joinable_games_sel_left,
11 pmbaty 532
        gCurrent_graf_data->joinable_games_y + gFonts[kFont_GRYLIT].height + 1 - (TranslationMode() ? 2 : 0) - gCurrent_graf_data->joinable_games_y_pitch,
1 pmbaty 533
        gCurrent_graf_data->joinable_games_sel_right - 1,
11 pmbaty 534
        gCurrent_graf_data->joinable_games_y + gFonts[kFont_GRYLIT].height + 1 - (TranslationMode() ? 2 : 0) - gCurrent_graf_data->joinable_games_y_pitch,
1 pmbaty 535
        6);
536
    for (i = 0; i < COUNT_OF(gGames_to_join); i++) {
537
        if (gGames_to_join[i].game == NULL) {
538
            continue;
539
        }
540
        if (gGames_to_join[i].game->type < 0 || gGames_to_join[i].game->type >= eNet_game_type_count) {
541
            continue;
542
        }
543
        if ((PDGetTotalTime() - gGames_to_join[i].time) >= 15000) {
544
            DisposeJoinableGame(i);
545
            continue;
546
        }
547
        if (gMouse_in_use
548
            && pCurrent_mode != 0
549
            && gGames_to_join[i].game != NULL
550
            && (gGames_to_join[i].game->options.open_game || gGames_to_join[i].game->no_races_yet)
551
            && gGames_to_join[i].game->num_players <= 5
552
            && x_coord >= gCurrent_graf_data->joinable_games_sel_left
553
            && x_coord <= gCurrent_graf_data->joinable_games_sel_right
554
            && y_coord >= (gCurrent_graf_data->joinable_games_y + gCurrent_graf_data->joinable_games_sel_top_marg + current_index * gCurrent_graf_data->joinable_games_y_pitch)
555
            && y_coord <= (gCurrent_graf_data->joinable_games_y + gCurrent_graf_data->joinable_games_sel_bot_marg + current_index * gCurrent_graf_data->joinable_games_y_pitch - 1)) {
556
            gLast_graph_sel__newgame = i;
557
        }
558
        if (i == gLast_graph_sel__newgame) {
559
            font_index = 10;
560
        } else {
561
            font_index = 9;
562
        }
563
        sprintf(s, "%s", gGames_to_join[i].game->host_name);
564
        DrawAnItem__newgame(gCurrent_graf_data->joinable_games_x_1, current_index, font_index, s);
565
        sprintf(s, "%s", GetMiscString(kMiscString_NetworkGameTypeNames_START + gGames_to_join[i].game->type));
566
        DrawAnItem__newgame(gCurrent_graf_data->joinable_games_x_2, current_index, font_index, s);
567
        sprintf(s, "%d", gGames_to_join[i].game->num_players);
568
        DrawAnItem__newgame(gCurrent_graf_data->joinable_games_x_3, current_index, font_index, s);
569
        sprintf(s, "%s, %s",
570
            GetMiscString(kMiscString_NetworkGameStage_START + gGames_to_join[i].game->status.stage),
571
            GetMiscString(kMiscString_NetworkGameOpenGame_START + gGames_to_join[i].game->options.open_game));
572
        DrawAnItem__newgame(gCurrent_graf_data->joinable_games_x_4, current_index, font_index, s);
573
        if (i == gLast_graph_sel__newgame) {
574
            DrawRectangle(gBack_screen,
575
                gCurrent_graf_data->joinable_games_sel_left,
576
                gCurrent_graf_data->joinable_games_y + gCurrent_graf_data->joinable_games_sel_top_marg + gCurrent_graf_data->joinable_games_y_pitch * current_index,
577
                gCurrent_graf_data->joinable_games_sel_right - 1,
578
                gCurrent_graf_data->joinable_games_y + gCurrent_graf_data->joinable_games_sel_bot_marg + gCurrent_graf_data->joinable_games_y_pitch * current_index - 1,
579
                45);
580
        }
581
        current_index++;
582
    }
583
 
584
    if (current_index != 0 && (gCurrent_game_selection == 0 || (gLast_graph_sel__newgame >= 0 && (gGames_to_join[gLast_graph_sel__newgame].game == NULL || (!gGames_to_join[gLast_graph_sel__newgame].game->options.open_game && !gGames_to_join[gLast_graph_sel__newgame].game->no_races_yet) || gGames_to_join[gLast_graph_sel__newgame].game->num_players > 5)))) {
585
        gCurrent_game_selection = 1;
586
        for (i = 0; i < COUNT_OF(gGames_to_join); i++) {
587
            if (gGames_to_join[i].game != NULL && (gGames_to_join[i].game->options.open_game || gGames_to_join[i].game->no_races_yet) && gGames_to_join[i].game->num_players <= 5) {
588
                gLast_graph_sel__newgame = i;
589
                ChangeSelectionTo(2, 1);
590
                return;
591
            }
592
        }
593
    }
594
    if (pCurrent_mode != 0 &&
595
#if defined(DETHRACE_FIX_BUGS)
596
        (gLast_graph_sel__newgame >= 0) &&
597
#endif
598
        (current_index == 0
599
            || gGames_to_join[gLast_graph_sel__newgame].game == NULL
600
            || (!gGames_to_join[gLast_graph_sel__newgame].game->options.open_game && !gGames_to_join[gLast_graph_sel__newgame].game->no_races_yet)
601
            || gGames_to_join[gLast_graph_sel__newgame].game->num_players > 5)) {
602
        gLast_graph_sel__newgame = -1;
603
        ChangeSelectionTo(0, 0);
604
    }
605
}
606
 
607
// IDA: void __cdecl InitGamesToJoin()
608
void InitGamesToJoin(void) {
609
    int i;
610
    LOG_TRACE("()");
611
 
612
    for (i = 0; i < COUNT_OF(gGames_to_join); i++) {
613
        gGames_to_join[i].game = NULL;
614
    }
615
    gLast_graph_sel__newgame = -1;
616
}
617
 
618
// IDA: void __usercall DisposeJoinList(int pExemption@<EAX>)
619
void DisposeJoinList(int pExemption) {
620
    int i;
621
    LOG_TRACE("(%d)", pExemption);
622
 
623
    for (i = 0; i < COUNT_OF(gGames_to_join); i++) {
624
        if (i == pExemption) {
625
            continue;
626
        }
627
        if (gGames_to_join[i].game != NULL) {
628
            DisposeJoinableGame(i);
629
        }
630
    }
631
}
632
 
633
// IDA: void __usercall AddToJoinList(tNet_game_details *pGame@<EAX>)
634
void AddToJoinList(tNet_game_details* pGame) {
635
    int i;
636
    int slot_to_use;
637
    tU32 this_game_ID;
638
    LOG_TRACE("(%p)", pGame);
639
 
640
    slot_to_use = -1;
641
    this_game_ID = NetExtractGameID(pGame);
642
    for (i = 0; i < COUNT_OF(gGames_to_join); i++) {
643
        if (gGames_to_join[i].game != NULL) {
644
            if (NetExtractGameID(gGames_to_join[i].game) == this_game_ID) {
645
                DisposeJoinableGame(i);
646
                slot_to_use = i;
647
                break;
648
            }
649
        }
650
    }
651
    if (slot_to_use < 0) {
652
        for (i = 0; i < COUNT_OF(gGames_to_join); i++) {
653
            if (gGames_to_join[i].game == NULL) {
654
                slot_to_use = i;
655
                break;
656
            }
657
        }
658
    }
659
    if (slot_to_use >= 0) {
660
        gGames_to_join[slot_to_use].game = pGame;
661
        gGames_to_join[slot_to_use].time = PDGetTotalTime();
662
    }
663
}
664
 
665
// IDA: void __cdecl NewNetStart1()
666
void NewNetStart1(void) {
667
    LOG_TRACE("()");
668
 
669
    gTyping = 1;
670
    SetSlotXY(0, gCurrent_graf_data->net_player_name_x, gCurrent_graf_data->net_player_name_y);
671
    AddRollingString(gNet_player_name,
672
        gCurrent_graf_data->net_player_name_x, gCurrent_graf_data->net_player_name_y, eRT_alpha);
673
}
674
 
675
// IDA: void __cdecl NewNetStart2()
676
void NewNetStart2(void) {
677
    LOG_TRACE("()");
678
 
679
    gTyping_slot = 0;
680
    StartTyping(0, gNet_player_name, 11);
681
}
682
 
683
// IDA: void __usercall NewNetGetName(int pStarting_to_type@<EAX>, int pCurrent_choice@<EDX>, char *pString@<EBX>, int *pMax_length@<ECX>)
684
void NewNetGetName(int pStarting_to_type, int pCurrent_choice, char* pString, int* pMax_length) {
685
    LOG_TRACE("(%d, %d, \"%s\", %p)", pStarting_to_type, pCurrent_choice, pString, pMax_length);
686
 
687
    strcpy(pString, gNet_player_name);
688
    *pMax_length = 10;
689
}
690
 
691
// IDA: int __usercall NewNetDone@<EAX>(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>, int pGo_ahead@<EBX>, int pEscaped@<ECX>, int pTimed_out)
692
int NewNetDone(int pCurrent_choice, int pCurrent_mode, int pGo_ahead, int pEscaped, int pTimed_out) {
693
    LOG_TRACE("(%d, %d, %d, %d, %d)", pCurrent_choice, pCurrent_mode, pGo_ahead, pEscaped, pTimed_out);
694
 
695
    if (pCurrent_choice != 1) {
696
        GetTypedName(gNet_player_name, 10);
697
    }
698
    return pCurrent_choice;
699
}
700
 
701
// IDA: int __usercall NewNetGoAhead@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
702
int NewNetGoAhead(int* pCurrent_choice, int* pCurrent_mode) {
703
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
704
 
705
    return gLast_graph_sel__newgame >= 0;
706
}
707
 
708
// IDA: tJoin_or_host_result __usercall JoinOrHostGame@<EAX>(tNet_game_details **pGame_to_join@<EAX>)
709
tJoin_or_host_result JoinOrHostGame(tNet_game_details** pGame_to_join) {
710
    static tFlicette flicker_on[2] = {
711
        { 43, { 41, 122 }, { 164, 370 } },
712
        { 43, { 230, 440 }, { 164, 370 } },
713
    };
714
    static tFlicette flicker_off[2] = {
715
        { 42, { 41, 122 }, { 164, 370 } },
716
        { 42, { 230, 440 }, { 164, 370 } },
717
    };
718
    static tFlicette push[2] = {
719
        { 90, { 41, 122 }, { 164, 370 } },
720
        { 45, { 230, 440 }, { 164, 370 } },
721
    };
722
    static tMouse_area mouse_areas[3] = {
723
        { { 41, 122 }, { 164, 370 }, { 104, 326 }, { 184, 422 }, 0, 0, 1, NULL },
724
        { { 230, 440 }, { 164, 370 }, { 293, 568 }, { 184, 422 }, 1, 0, 1, NULL },
725
        { { 42, 94 }, { 57, 137 }, { 290, 556 }, { 150, 341 }, 2, 1, 1, NULL },
726
    };
727
    static tRectile recopy_areas[1] = {
728
        {
729
            { 124, 110 },
730
            { 163, 317 },
731
            { 212, 322 },
732
            { 180, 370 },
733
        },
734
    };
735
    static tInterface_spec interface_spec = {
736
        0,
737
        100,
738
        0,
739
        101,
740
        101,
741
        101,
742
        -1,
743
        { 0, -1 },
744
        { -1, -1 },
745
        { 0, 2 },
746
        { 1, 2 },
747
        { NULL, NULL },
748
        { 0, -1 },
749
        { 1, -1 },
750
        { 0, 2 },
751
        { 1, 2 },
752
        { NULL, NULL },
753
        { 1, -1 },
754
        { 0, 0 },
755
        { 2, 0 },
756
        { 2, 0 },
757
        { NewNetGameUp, NewNetGameUp },
758
        { 1, -1 },
759
        { 0, 0 },
760
        { 2, 0 },
761
        { 2, 0 },
762
        { NewNetGameDown, NewNetGameDown },
763
        { 1, 1 },
764
        { NULL, NewNetGoAhead },
765
        { 1, 1 },
766
        { NULL, NULL },
767
        NULL,
768
        DrawGames,
769
        0,
770
        NewNetStart1,
771
        NewNetStart2,
772
        NewNetDone,
773
        1,
774
        { 1, 1 },
775
        NewNetGetName,
776
        1,
777
        1,
778
        COUNT_OF(flicker_on),
779
        flicker_on,
780
        flicker_off,
781
        push,
782
        COUNT_OF(mouse_areas),
783
        mouse_areas,
784
        COUNT_OF(recopy_areas),
785
        recopy_areas,
786
    };
787
    int result;
788
    LOG_TRACE("(%p)", pGame_to_join);
789
 
790
    gCurrent_game_selection = 0;
11 pmbaty 791
    LoadFont(kFont_GRNDK);
792
    LoadFont(kFont_GRNLIT);
793
    LoadFont(kFont_GREENHED);
794
    LoadFont(kFont_GRYLIT);
1 pmbaty 795
    SetAlwaysTyping();
796
    InitGamesToJoin();
797
    NetStartProducingJoinList(AddToJoinList);
798
    result = DoInterfaceScreen(&interface_spec, 0, 0);
799
    ClearAlwaysTyping();
800
    NetEndJoinList();
801
    DisposeJoinList(gLast_graph_sel__newgame);
11 pmbaty 802
    DisposeFont(kFont_GRNDK); // Pierre-Marie Baty -- replaced font number with symbol
803
    DisposeFont(kFont_GRNLIT); // Pierre-Marie Baty -- replaced font number with symbol
804
    DisposeFont(kFont_GREENHED); // Pierre-Marie Baty -- replaced font number with symbol
805
    DisposeFont(kFont_GRYLIT); // Pierre-Marie Baty -- replaced font number with symbol
1 pmbaty 806
    strcpy(gProgram_state.player_name[0], gNet_player_name);
807
    SaveOptions();
808
    switch (result) {
809
    case 0:
810
        return eJoin_or_host_host;
811
    case 1:
812
        return eJoin_or_host_cancel;
813
    case 2:
814
        *pGame_to_join = gGames_to_join[gLast_graph_sel__newgame].game;
815
        return eJoin_or_host_join;
816
    default:
817
        return eJoin_or_host_cancel;
818
    }
819
}
820
 
821
// IDA: void __usercall GetNetOptions(tNet_game_options *pGame_options@<EAX>)
822
void GetNetOptions(tNet_game_options* pGame_options) {
823
    LOG_TRACE("(%p)", pGame_options);
824
 
825
    pGame_options->enable_text_messages = gRadio_bastards__newgame[0].current_value;
826
    pGame_options->show_players_on_map = gRadio_bastards__newgame[1].current_value;
827
    pGame_options->show_peds_on_map = gRadio_bastards__newgame[2].current_value;
828
    pGame_options->show_powerups_on_map = gRadio_bastards__newgame[3].current_value;
829
    pGame_options->powerup_respawn = gRadio_bastards__newgame[4].current_value;
830
    pGame_options->open_game = !gRadio_bastards__newgame[5].current_value;
831
    pGame_options->grid_start = !gRadio_bastards__newgame[6].current_value;
832
    pGame_options->race_sequence_type = gRadio_bastards__newgame[7].current_value ? eNet_sequence_sequential : eNet_sequence_random;
833
    pGame_options->random_car_choice = gRadio_bastards__newgame[8].current_value;
834
    pGame_options->car_choice = gRadio_bastards__newgame[9].current_value;
835
    pGame_options->starting_money_index = gRadio_bastards__newgame[10].current_value;
836
}
837
 
838
// IDA: void __usercall SetNetOptions(tNet_game_options *pGame_options@<EAX>)
839
void SetNetOptions(tNet_game_options* pGame_options) {
840
    LOG_TRACE("(%p)", pGame_options);
841
 
842
    gRadio_bastards__newgame[0].current_value = pGame_options->enable_text_messages;
843
    gRadio_bastards__newgame[1].current_value = pGame_options->show_players_on_map;
844
    gRadio_bastards__newgame[2].current_value = pGame_options->show_peds_on_map;
845
    gRadio_bastards__newgame[3].current_value = pGame_options->show_powerups_on_map;
846
    gRadio_bastards__newgame[4].current_value = pGame_options->powerup_respawn;
847
    gRadio_bastards__newgame[5].current_value = !pGame_options->open_game;
848
    gRadio_bastards__newgame[6].current_value = !pGame_options->grid_start;
849
    gRadio_bastards__newgame[7].current_value = pGame_options->race_sequence_type == eNet_sequence_sequential;
850
    gRadio_bastards__newgame[8].current_value = pGame_options->random_car_choice;
851
    gRadio_bastards__newgame[9].current_value = pGame_options->car_choice;
852
    gRadio_bastards__newgame[10].current_value = pGame_options->starting_money_index;
853
}
854
 
855
// IDA: void __usercall NetPlayCheckboxOn2(int pIndex@<EAX>)
856
void NetPlayCheckboxOn2(int pIndex) {
857
    LOG_TRACE("(%d)", pIndex);
858
 
859
    RunFlicAt(95,
860
        gRadio_bastards__newgame[pIndex].left[0],
861
        gRadio_bastards__newgame[pIndex].top + 1);
862
}
863
 
864
// IDA: void __usercall NetPlayCheckboxOff2(int pIndex@<EAX>)
865
void NetPlayCheckboxOff2(int pIndex) {
866
    LOG_TRACE("(%d)", pIndex);
867
 
868
    RunFlicAt(96,
869
        gRadio_bastards__newgame[pIndex].left[0],
870
        gRadio_bastards__newgame[pIndex].top + 1);
871
}
872
 
873
// IDA: void __usercall NetPlayCheckboxOn(int pIndex@<EAX>)
874
void NetPlayCheckboxOn(int pIndex) {
875
    LOG_TRACE("(%d)", pIndex);
876
 
877
    RemoveTransientBitmaps(1);
878
    DontLetFlicFuckWithPalettes();
879
    TurnFlicTransparencyOn();
880
    NetPlayCheckboxOn2(pIndex);
881
    TurnFlicTransparencyOff();
882
    LetFlicFuckWithPalettes();
883
}
884
 
885
// IDA: void __usercall NetPlayCheckboxOff(int pIndex@<EAX>)
886
void NetPlayCheckboxOff(int pIndex) {
887
    LOG_TRACE("(%d)", pIndex);
888
 
889
    RemoveTransientBitmaps(1);
890
    DontLetFlicFuckWithPalettes();
891
    TurnFlicTransparencyOn();
892
    NetPlayCheckboxOff2(pIndex);
893
    TurnFlicTransparencyOff();
894
    LetFlicFuckWithPalettes();
895
}
896
 
897
// IDA: void __usercall NetPlayRadioOn2(int pIndex@<EAX>, int pValue@<EDX>)
898
void NetPlayRadioOn2(int pIndex, int pValue) {
899
    LOG_TRACE("(%d, %d)", pIndex, pValue);
900
 
901
    RunFlicAt(288,
902
        gRadio_bastards__newgame[pIndex].left[pValue],
903
        gRadio_bastards__newgame[pIndex].top + 1);
904
}
905
 
906
// IDA: void __usercall NetPlayRadioOff2(int pIndex@<EAX>, int pValue@<EDX>)
907
void NetPlayRadioOff2(int pIndex, int pValue) {
908
    LOG_TRACE("(%d, %d)", pIndex, pValue);
909
 
910
    RunFlicAt(287,
911
        gRadio_bastards__newgame[pIndex].left[pValue],
912
        gRadio_bastards__newgame[pIndex].top + 1);
913
}
914
 
915
// IDA: void __usercall NetPlayRadioOn(int pIndex@<EAX>, int pValue@<EDX>)
916
void NetPlayRadioOn(int pIndex, int pValue) {
917
    LOG_TRACE("(%d, %d)", pIndex, pValue);
918
 
919
    RemoveTransientBitmaps(1);
920
    DontLetFlicFuckWithPalettes();
921
    TurnFlicTransparencyOn();
922
    NetPlayRadioOn2(pIndex, pValue);
923
    TurnFlicTransparencyOff();
924
    LetFlicFuckWithPalettes();
925
}
926
 
927
// IDA: void __usercall NetPlayRadioOff(int pIndex@<EAX>, int pValue@<EDX>)
928
void NetPlayRadioOff(int pIndex, int pValue) {
929
    LOG_TRACE("(%d, %d)", pIndex, pValue);
930
 
931
    RemoveTransientBitmaps(1);
932
    DontLetFlicFuckWithPalettes();
933
    TurnFlicTransparencyOn();
934
    NetPlayRadioOff2(pIndex, pValue);
935
    TurnFlicTransparencyOff();
936
    LetFlicFuckWithPalettes();
937
}
938
 
939
// IDA: void __cdecl DrawNOptInitialRadios()
940
void DrawNOptInitialRadios(void) {
941
    int i;
942
    int j;
943
    LOG_TRACE("()");
944
 
945
    RemoveTransientBitmaps(1);
946
    DontLetFlicFuckWithPalettes();
947
    TurnFlicTransparencyOn();
948
    for (i = 0; i < COUNT_OF(gRadio_bastards__newgame); i++) {
949
        if (gRadio_bastards__newgame[i].count < 2) {
950
            if (gRadio_bastards__newgame[i].current_value) {
951
                NetPlayCheckboxOn2(i);
952
            } else {
953
                NetPlayCheckboxOff2(i);
954
            }
955
        } else {
956
            NetPlayRadioOn2(i, gRadio_bastards__newgame[i].current_value);
957
            for (j = 0; j < gRadio_bastards__newgame[i].count; j++) {
958
                if (j != gRadio_bastards__newgame[i].current_value) {
959
                    NetPlayRadioOff2(i, j);
960
                }
961
            }
962
        }
963
    }
964
    TurnFlicTransparencyOff();
965
    LetFlicFuckWithPalettes();
966
}
967
 
968
// IDA: void __usercall NetRadioChanged(int pIndex@<EAX>, int pNew_value@<EDX>)
969
void NetRadioChanged(int pIndex, int pNew_value) {
970
    LOG_TRACE("(%d, %d)", pIndex, pNew_value);
971
 
972
    NetPlayRadioOff(pIndex, gRadio_bastards__newgame[pIndex].current_value);
973
    NetPlayRadioOn(pIndex, pNew_value);
974
    gRadio_bastards__newgame[pIndex].current_value = pNew_value;
975
}
976
 
977
// IDA: void __usercall NetCheckboxChanged(int pIndex@<EAX>)
978
void NetCheckboxChanged(int pIndex) {
979
    LOG_TRACE("(%d)", pIndex);
980
 
981
    if (gRadio_bastards__newgame[pIndex].current_value) {
982
        NetPlayCheckboxOff(pIndex);
983
    } else {
984
        NetPlayCheckboxOn(pIndex);
985
    }
986
    gRadio_bastards__newgame[pIndex].current_value = !gRadio_bastards__newgame[pIndex].current_value;
987
}
988
 
989
// IDA: int __usercall NetOptLeft@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
990
int NetOptLeft(int* pCurrent_choice, int* pCurrent_mode) {
991
    int new_value;
992
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
993
 
994
    DRS3StartSound(gEffects_outlet, 3000);
995
    if (gRadio_bastards__newgame[*pCurrent_choice - 3].count < 2) {
996
        NetCheckboxChanged(*pCurrent_choice - 3);
997
    } else {
998
        new_value = gRadio_bastards__newgame[*pCurrent_choice - 3].current_value - 1;
999
        if (new_value < 0) {
1000
            new_value = gRadio_bastards__newgame[*pCurrent_choice - 3].count - 1;
1001
        }
1002
        NetRadioChanged(*pCurrent_choice - 3, new_value);
1003
    }
1004
    return 1;
1005
}
1006
 
1007
// IDA: int __usercall NetOptRight@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
1008
int NetOptRight(int* pCurrent_choice, int* pCurrent_mode) {
1009
    int new_value;
1010
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
1011
 
1012
    DRS3StartSound(gEffects_outlet, 3000);
1013
    if (gRadio_bastards__newgame[*pCurrent_choice - 3].count < 2) {
1014
        NetCheckboxChanged(*pCurrent_choice - 3);
1015
    } else {
1016
        new_value = gRadio_bastards__newgame[*pCurrent_choice - 3].current_value + 1;
1017
        if (new_value == gRadio_bastards__newgame[*pCurrent_choice - 3].count) {
1018
            new_value = 0;
1019
        }
1020
        NetRadioChanged(*pCurrent_choice - 3, new_value);
1021
    }
1022
    return 1;
1023
}
1024
 
1025
// IDA: int __usercall NetOptUp@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
1026
int NetOptUp(int* pCurrent_choice, int* pCurrent_mode) {
1027
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
1028
 
1029
    if (*pCurrent_mode == 0) {
1030
        *pCurrent_mode = 1;
1031
        *pCurrent_choice = 13;
1032
        DRS3StartSound(gEffects_outlet, 3000);
1033
        return 1;
1034
    } else if (*pCurrent_choice == 2) {
1035
        *pCurrent_mode = 0;
1036
        *pCurrent_choice = 0;
1037
        DRS3StartSound(gEffects_outlet, 3000);
1038
        return 1;
1039
    } else {
1040
        return 0;
1041
    }
1042
}
1043
 
1044
// IDA: int __usercall NetOptDown@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
1045
int NetOptDown(int* pCurrent_choice, int* pCurrent_mode) {
1046
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
1047
 
1048
    if (*pCurrent_mode == 0) {
1049
        *pCurrent_mode = 1;
1050
        *pCurrent_choice = 3;
1051
        DRS3StartSound(gEffects_outlet, 3000);
1052
        return 1;
1053
    } else if (*pCurrent_choice == 14) {
1054
        *pCurrent_mode = 0;
1055
        *pCurrent_choice = 0;
1056
        DRS3StartSound(gEffects_outlet, 3000);
1057
        return 1;
1058
    } else {
1059
        return 0;
1060
    }
1061
}
1062
 
1063
// IDA: int __usercall NetRadioClick@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>, int pX_offset@<EBX>, int pY_offset@<ECX>)
1064
int NetRadioClick(int* pCurrent_choice, int* pCurrent_mode, int pX_offset, int pY_offset) {
1065
    int i;
1066
    LOG_TRACE("(%p, %p, %d, %d)", pCurrent_choice, pCurrent_mode, pX_offset, pY_offset);
1067
 
1068
    if (gRadio_bastards__newgame[*pCurrent_choice - 3].count < 2) {
1069
        NetCheckboxChanged(*pCurrent_choice - 3);
1070
    } else {
1071
        for (i = gRadio_bastards__newgame[*pCurrent_choice - 3].count - 1; i >= 0; i--) {
1072
            if (gThe_interface_spec__newgame->mouse_areas[3].left[gGraf_data_index] + pX_offset + 3 >= gRadio_bastards__newgame[*pCurrent_choice - 3].left[i]) {
1073
                DRS3StartSound(gEffects_outlet, 3000);
1074
                NetRadioChanged(*pCurrent_choice - 3, i);
1075
                break;
1076
            }
1077
        }
1078
    }
1079
    return 0;
1080
}
1081
 
1082
// IDA: void __cdecl RevertToDefaults()
1083
void RevertToDefaults(void) {
1084
    tPath_name the_path;
1085
    FILE* f;
1086
    tNet_game_options net_options;
1087
    int i;
1088
    LOG_TRACE("()");
1089
 
1090
    PathCat(the_path, gApplication_path, "NETDEFLT.TXT");
1091
    f = DRfopen(the_path, "rt");
1092
    if (f == NULL) {
1093
        return;
1094
    }
1095
    for (i = 0; i < gLast_game_type + 1; i++) {
1096
        ReadNetworkSettings(f, &net_options);
1097
    }
1098
    SetNetOptions(&net_options);
1099
    DrawNOptInitialRadios();
1100
    fclose(f);
1101
}
1102
 
1103
// IDA: void __cdecl DefaultNetSettings()
1104
void DefaultNetSettings(void) {
1105
    FILE* f;
1106
    int i;
1107
    tPath_name the_path; // added
1108
 
1109
    PathCat(the_path, gApplication_path, "NETDEFLT.TXT");
1110
    f = DRfopen(the_path, "rt");
1111
    if (f == NULL) {
1112
        return;
1113
    }
1114
    ReadNetworkSettings(f, gNet_settings);
1115
    rewind(f);
1116
    for (i = 0; i < COUNT_OF(gNet_settings) - 1; i++) {
1117
        ReadNetworkSettings(f, &gNet_settings[i + 1]);
1118
    }
1119
    fclose(f);
1120
}
1121
 
1122
// IDA: int __usercall NetOptGoAhead@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
1123
int NetOptGoAhead(int* pCurrent_choice, int* pCurrent_mode) {
1124
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
1125
 
1126
    if (*pCurrent_mode == 0) {
1127
        if (*pCurrent_choice == 2) {
1128
            RevertToDefaults();
1129
            return 0;
1130
        } else {
1131
            return 1;
1132
        }
1133
    } else {
1134
        NetOptRight(pCurrent_choice, pCurrent_mode);
1135
        return 0;
1136
    }
1137
}
1138
 
1139
// IDA: void __usercall NetPlotAGraphBox(int pIndex@<EAX>, int pColour_value@<EDX>)
1140
void NetPlotAGraphBox(int pIndex, int pColour_value) {
1141
    LOG_TRACE("(%d, %d)", pIndex, pColour_value);
1142
 
1143
    if (pIndex >= 0) {
1144
        DrawRRectangle(gBack_screen,
1145
            gThe_interface_spec__newgame->mouse_areas[pIndex + 3].left[gGraf_data_index],
1146
            gThe_interface_spec__newgame->mouse_areas[pIndex + 3].top[gGraf_data_index],
1147
            gThe_interface_spec__newgame->mouse_areas[pIndex + 3].right[gGraf_data_index],
1148
            gThe_interface_spec__newgame->mouse_areas[pIndex + 3].bottom[gGraf_data_index],
1149
            pColour_value);
1150
    }
1151
}
1152
 
1153
// IDA: void __usercall NetDrawAGraphBox(int pIndex@<EAX>)
1154
void NetDrawAGraphBox(int pIndex) {
1155
    LOG_TRACE("(%d)", pIndex);
1156
 
1157
    NetPlotAGraphBox(pIndex, 45);
1158
}
1159
 
1160
// IDA: void __usercall NetEraseAGraphBox(int pIndex@<EAX>)
1161
void NetEraseAGraphBox(int pIndex) {
1162
    LOG_TRACE("(%d)", pIndex);
1163
 
1164
    NetPlotAGraphBox(pIndex, 0);
1165
}
1166
 
1167
// IDA: void __usercall DrawNetOptBox(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>)
1168
void DrawNetOptBox(int pCurrent_choice, int pCurrent_mode) {
1169
    LOG_TRACE("(%d, %d)", pCurrent_choice, pCurrent_mode);
1170
 
1171
    if (gRadio_selected != pCurrent_choice) {
1172
        NetEraseAGraphBox(gRadio_selected - 3);
1173
        NetDrawAGraphBox(pCurrent_choice - 3);
1174
        gRadio_selected = pCurrent_choice;
1175
    }
1176
}
1177
 
1178
// IDA: void __usercall DoNetOptions(tNet_game_options *pGame_options@<EAX>)
1179
void DoNetOptions(tNet_game_options* pGame_options) {
1180
    static tFlicette flicker_on[14] = {
1181
        { 43, { 169, 90 }, { 156, 398 } },
1182
        { 43, { 236, 440 }, { 156, 398 } },
1183
        { 43, { 37, 440 }, { 156, 398 } },
1184
        { 68, { 81, 98 }, { 32, 86 } },
1185
        { 75, { 81, 98 }, { 43, 108 } },
1186
        { 77, { 81, 98 }, { 54, 130 } },
1187
        { 79, { 81, 98 }, { 65, 161 } },
1188
        { 112, { 81, 98 }, { 76, 182 } },
1189
        { 127, { 81, 98 }, { 86, 214 } },
1190
        { 129, { 81, 98 }, { 97, 235 } },
1191
        { 134, { 81, 98 }, { 108, 266 } },
1192
        { 137, { 81, 98 }, { 119, 288 } },
1193
        { 139, { 81, 98 }, { 130, 310 } },
1194
        { 143, { 81, 98 }, { 141, 331 } },
1195
    };
1196
    static tFlicette flicker_off[14] = {
1197
        { 42, { 169, 90 }, { 156, 398 } },
1198
        { 42, { 236, 440 }, { 156, 398 } },
1199
        { 42, { 37, 440 }, { 156, 398 } },
1200
        { 69, { 81, 98 }, { 32, 86 } },
1201
        { 76, { 81, 98 }, { 43, 108 } },
1202
        { 78, { 81, 98 }, { 54, 130 } },
1203
        { 109, { 81, 98 }, { 65, 161 } },
1204
        { 113, { 81, 98 }, { 76, 182 } },
1205
        { 128, { 81, 98 }, { 86, 214 } },
1206
        { 133, { 81, 98 }, { 97, 235 } },
1207
        { 136, { 81, 98 }, { 108, 266 } },
1208
        { 138, { 81, 98 }, { 119, 288 } },
1209
        { 142, { 81, 98 }, { 130, 310 } },
1210
        { 148, { 81, 98 }, { 141, 331 } },
1211
    };
1212
    static tFlicette push[14] = {
1213
        { 154, { 169, 90 }, { 156, 398 } },
1214
        { 45, { 236, 440 }, { 156, 398 } },
1215
        { 67, { 37, 440 }, { 156, 398 } },
1216
        { 68, { 81, 98 }, { 32, 86 } },
1217
        { 75, { 81, 98 }, { 43, 108 } },
1218
        { 77, { 81, 98 }, { 54, 130 } },
1219
        { 79, { 81, 98 }, { 65, 161 } },
1220
        { 112, { 81, 98 }, { 76, 182 } },
1221
        { 127, { 81, 98 }, { 86, 214 } },
1222
        { 129, { 81, 98 }, { 97, 235 } },
1223
        { 134, { 81, 98 }, { 108, 266 } },
1224
        { 137, { 81, 98 }, { 119, 288 } },
1225
        { 139, { 81, 98 }, { 130, 310 } },
1226
        { 143, { 81, 98 }, { 141, 331 } },
1227
    };
1228
    static tMouse_area mouse_areas[14] = {
1229
        { { 169, 90 }, { 156, 396 }, { 232, 214 }, { 176, 444 }, 0, 0, 0, NULL },
1230
        { { 236, 440 }, { 156, 396 }, { 299, 552 }, { 176, 444 }, 1, 0, 0, NULL },
1231
        { { 37, 98 }, { 156, 84 }, { 100, 568 }, { 176, 103 }, 2, 0, 0, NULL },
1232
        { { 61, 98 }, { 30, 106 }, { 270, 568 }, { 40, 125 }, 3, 1, 0, NetRadioClick },
1233
        { { 61, 98 }, { 41, 127 }, { 270, 568 }, { 51, 146 }, 4, 1, 0, NetRadioClick },
1234
        { { 61, 98 }, { 52, 158 }, { 270, 568 }, { 62, 178 }, 5, 1, 0, NetRadioClick },
1235
        { { 61, 98 }, { 63, 180 }, { 270, 568 }, { 73, 199 }, 6, 1, 0, NetRadioClick },
1236
        { { 61, 98 }, { 74, 192 }, { 270, 568 }, { 84, 230 }, 7, 1, 0, NetRadioClick },
1237
        { { 61, 98 }, { 84, 233 }, { 270, 568 }, { 94, 252 }, 8, 1, 0, NetRadioClick },
1238
        { { 61, 98 }, { 95, 264 }, { 270, 568 }, { 105, 283 }, 9, 1, 0, NetRadioClick },
1239
        { { 61, 98 }, { 106, 286 }, { 270, 568 }, { 116, 305 }, 10, 1, 0, NetRadioClick },
1240
        { { 61, 98 }, { 117, 307 }, { 270, 322 }, { 127, 326 }, 11, 1, 0, NetRadioClick },
1241
        { { 61, 98 }, { 128, 329 }, { 270, 322 }, { 138, 348 }, 12, 1, 0, NetRadioClick },
1242
        { { 61, 98 }, { 139, 358 }, { 270, 322 }, { 149, 377 }, 13, 1, 0, NetRadioClick },
1243
    };
1244
    static tInterface_spec interface_spec = {
1245
        0, 65, 0, 66, 66, 66, -1,
1246
        { -1, 0 }, { -1, 0 }, { 0, 3 }, { 2, 13 }, { NULL, NetOptLeft },
1247
        { -1, 0 }, { 1, 0 }, { 0, 3 }, { 2, 13 }, { NULL, NetOptRight },
1248
        { -1, -1 }, { 0, -1 }, { 0, 2 }, { 0, 13 }, { NetOptUp, NetOptUp },
1249
        { -1, -1 }, { 1, 1 }, { 0, 3 }, { 0, 14 }, { NetOptDown, NetOptDown },
1250
        { 1, 1 }, { NetOptGoAhead, NetOptGoAhead }, { 1, 1 }, { NULL, NULL },
1251
        NULL, DrawNetOptBox, 0,
1252
        NULL, DrawNOptInitialRadios, NULL, 0, { 0, 0 }, NULL, 1, 1,
1253
        COUNT_OF(flicker_on), flicker_on, flicker_off, push,
1254
        COUNT_OF(mouse_areas), mouse_areas,
1255
        0, NULL
1256
    };
1257
    LOG_TRACE("(%p)", pGame_options);
1258
 
1259
    gThe_interface_spec__newgame = &interface_spec;
1260
    gRadio_selected = -1;
11 pmbaty 1261
    LoadFont(kFont_GRYLIT);
1 pmbaty 1262
    SetNetOptions(pGame_options);
1263
    if (DoInterfaceScreen(&interface_spec, 0, 0) == 0) {
1264
        GetNetOptions(pGame_options);
1265
    }
11 pmbaty 1266
    DisposeFont(kFont_GRYLIT); // Pierre-Marie Baty -- replaced font number with symbol
1 pmbaty 1267
}
1268
 
1269
// IDA: void __usercall PlayRadioOn(int pIndex@<EAX>)
1270
//  Suffix added to avoid duplicate symbol
1271
void PlayRadioOn__newgame(int pIndex) {
1272
    LOG_TRACE("(%d)", pIndex);
1273
 
1274
    RunFlicAt(288,
1275
        gThe_interface_spec__newgame->pushed_flics[pIndex + 4].x[gGraf_data_index],
1276
        gThe_interface_spec__newgame->pushed_flics[pIndex + 4].y[gGraf_data_index]);
1277
}
1278
 
1279
// IDA: void __usercall PlayRadioOff(int pIndex@<EAX>)
1280
//  Suffix added to avoid duplicate symbol
1281
void PlayRadioOff__newgame(int pIndex) {
1282
    LOG_TRACE("(%d)", pIndex);
1283
 
1284
    RunFlicAt(287,
1285
        gThe_interface_spec__newgame->pushed_flics[pIndex + 4].x[gGraf_data_index],
1286
        gThe_interface_spec__newgame->pushed_flics[pIndex + 4].y[gGraf_data_index]);
1287
}
1288
 
1289
// IDA: void __usercall SetOptions(tNet_game_type pGame_type@<EAX>, tNet_game_options *pGame_options@<EDX>)
1290
void SetOptions(tNet_game_type pGame_type, tNet_game_options* pGame_options) {
1291
    LOG_TRACE("(%d, %p)", pGame_type, pGame_options);
1292
 
1293
    pGame_options->show_players_on_map = gNet_settings[0].show_players_on_map;
1294
    pGame_options->show_peds_on_map = gNet_settings[pGame_type + 1].show_peds_on_map;
1295
    pGame_options->enable_text_messages = gNet_settings[0].enable_text_messages;
1296
    pGame_options->powerup_respawn = gNet_settings[0].powerup_respawn;
1297
    pGame_options->show_powerups_on_map = gNet_settings[0].show_powerups_on_map;
1298
    pGame_options->open_game = gNet_settings[pGame_type + 1].open_game;
1299
    pGame_options->grid_start = gNet_settings[pGame_type + 1].grid_start;
1300
    pGame_options->random_car_choice = gNet_settings[0].random_car_choice;
1301
    pGame_options->car_choice = gNet_settings[0].car_choice;
1302
    pGame_options->starting_money_index = gNet_settings[0].starting_money_index;
1303
    pGame_options->race_sequence_type = gNet_settings[0].race_sequence_type;
1304
}
1305
 
1306
// IDA: void __cdecl DrawNetChooseInitial()
1307
void DrawNetChooseInitial(void) {
1308
    LOG_TRACE("()");
1309
 
1310
    PlayRadioOn__newgame(gLast_game_type);
1311
}
1312
 
1313
// IDA: int __usercall NetChooseGoAhead@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
1314
int NetChooseGoAhead(int* pCurrent_choice, int* pCurrent_mode) {
1315
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
1316
 
1317
    if (*pCurrent_mode == 0) {
1318
        return 1;
1319
    } else {
1320
        if (*pCurrent_choice - 4 != gLast_game_type) {
1321
            RemoveTransientBitmaps(1);
1322
            DontLetFlicFuckWithPalettes();
1323
            TurnFlicTransparencyOn();
1324
            PlayRadioOff__newgame(gLast_game_type);
1325
            gLast_game_type = *pCurrent_choice - 4;
1326
            PlayRadioOn__newgame(gLast_game_type);
1327
            LoadRaces(gRace_list, &gNumber_of_races, gLast_game_type);
1328
            SetOptions(gLast_game_type, gOptions);
1329
            TurnFlicTransparencyOff();
1330
            LetFlicFuckWithPalettes();
1331
            if (gRace_index >= gNumber_of_races) {
1332
                gRace_index = PickNetRace(-1, gNet_race_sequence__newgame);
1333
            }
1334
            if (!gMouse_in_use) {
1335
                *pCurrent_mode = 0;
1336
                *pCurrent_choice = 0;
1337
            }
1338
        }
1339
        return 0;
1340
    }
1341
}
1342
 
1343
// IDA: void __usercall PlotAGraphBox(int pIndex@<EAX>, int pColour_value@<EDX>)
1344
// Suffix added to avoid duplicate symbol
1345
void PlotAGraphBox__newgame(int pIndex, int pColour_value) {
1346
    LOG_TRACE("(%d, %d)", pIndex, pColour_value);
1347
 
1348
    if (pIndex >= 0) {
1349
        DrawRRectangle(gBack_screen,
1350
            gThe_interface_spec__newgame->mouse_areas[pIndex].left[gGraf_data_index],
1351
            gThe_interface_spec__newgame->mouse_areas[pIndex].top[gGraf_data_index],
1352
            gThe_interface_spec__newgame->mouse_areas[pIndex].right[gGraf_data_index],
1353
            gThe_interface_spec__newgame->mouse_areas[pIndex].bottom[gGraf_data_index],
1354
            pColour_value);
1355
    }
1356
}
1357
 
1358
// IDA: void __usercall DrawAGraphBox(int pIndex@<EAX>)
1359
// Suffix added to avoid duplicate symbol
1360
void DrawAGraphBox__newgame(int pIndex) {
1361
    LOG_TRACE("(%d)", pIndex);
1362
 
1363
    PlotAGraphBox__newgame(pIndex, 45);
1364
}
1365
 
1366
// IDA: void __usercall EraseAGraphBox(int pIndex@<EAX>)
1367
// Suffix added to avoid duplicate symbol
1368
void EraseAGraphBox__newgame(int pIndex) {
1369
    LOG_TRACE("(%d)", pIndex);
1370
 
1371
    PlotAGraphBox__newgame(pIndex, 0);
1372
}
1373
 
1374
// IDA: void __usercall DrawNetChoose(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>)
1375
void DrawNetChoose(int pCurrent_choice, int pCurrent_mode) {
1376
    char s[256];
1377
    tU32* k;
1378
    int i;
1379
    LOG_TRACE("(%d, %d)", pCurrent_choice, pCurrent_mode);
1380
 
1381
    if (gLast_net_choose_box >= 0) {
1382
        EraseAGraphBox__newgame(gLast_net_choose_box);
1383
    }
1384
    if (pCurrent_mode != 0) {
1385
        gLast_net_choose_box = pCurrent_choice;
1386
        DrawAGraphBox__newgame(pCurrent_choice);
1387
    } else {
1388
        gLast_net_choose_box = -1;
1389
    }
1390
    BrPixelmapRectangleFill(gBack_screen,
1391
        gCurrent_graf_data->net_descr_race_l,
1392
        gCurrent_graf_data->net_choose_race_y,
1393
        gCurrent_graf_data->net_descr_race_r - gCurrent_graf_data->net_descr_race_l,
11 pmbaty 1394
        gFonts[kFont_GRNLIT].height + 1 - (TranslationMode() ? 2 : 0), 0);
1 pmbaty 1395
    sprintf(s, "%s %s", GetMiscString(kMiscString_FIRST_RACE), gRace_list[gRace_index].name);
1396
    DRPixelmapCentredText(gBack_screen,
1397
        gCurrent_graf_data->net_choose_race_x,
1398
        gCurrent_graf_data->net_choose_race_y,
11 pmbaty 1399
        &gFonts[kFont_GRNLIT], s);
1 pmbaty 1400
    BrPixelmapRectangleFill(gBack_screen,
1401
        gCurrent_graf_data->net_descr_race_l,
1402
        gCurrent_graf_data->net_descr_race_top - (TranslationMode() ? 2 : 0),
1403
        gCurrent_graf_data->net_descr_race_r - gCurrent_graf_data->net_descr_race_l,
1404
        gCurrent_graf_data->net_descr_race_bot - gCurrent_graf_data->net_descr_race_top,
1405
        0);
1406
    OoerrIveGotTextInMeBoxMissus(9,
1407
        GetMiscString(kMiscString_NetworkGameTypeDescriptions_START + (pCurrent_mode ? pCurrent_choice - 4 : gLast_game_type)),
1408
        gBack_screen,
1409
        gCurrent_graf_data->net_descr_race_l,
1410
        gCurrent_graf_data->net_descr_race_top,
1411
        gCurrent_graf_data->net_descr_race_r,
1412
        gCurrent_graf_data->net_descr_race_bot,
1413
        1);
1414
    k = KevKeyService();
1415
    if (k[0] == 0x2212d981 && k[1] == 0x90e8cf51) {
1416
        DRS3StartSound(gEffects_outlet, 3202);
1417
        DRS3StartSound(gEffects_outlet, 3202);
1418
        for (i = 0; i < gNumber_of_racers; i++) {
1419
            if (gOpponents[i].network_availability == eNet_avail_never) {
1420
                gOpponents[i].network_availability = eNet_avail_all;
1421
            }
1422
        }
1423
    }
1424
}
1425
 
1426
// IDA: int __usercall NetChooseLR@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
1427
int NetChooseLR(int* pCurrent_choice, int* pCurrent_mode) {
1428
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
1429
 
1430
    *pCurrent_choice = gLast_game_type + 4;
1431
    return 0;
1432
}
1433
 
1434
// IDA: void __usercall SetGameTarget(tNet_game_type *pGame_type@<EAX>, tNet_game_options *pGame_options@<EDX>)
1435
void SetGameTarget(tNet_game_type* pGame_type, tNet_game_options* pGame_options) {
1436
    LOG_TRACE("(%p, %p)", pGame_type, pGame_options);
1437
 
1438
    pGame_options->race_end_target = gNet_target[*pGame_type];
1439
    switch (*pGame_type) {
1440
    case eNet_game_type_car_crusher:
1441
        pGame_options->race_end_target = gNet_target[*pGame_type];
1442
        break;
1443
    case eNet_game_type_tag:
1444
        pGame_options->race_end_target = 1000 * gNet_target[*pGame_type];
1445
        break;
1446
    case eNet_game_type_foxy:
1447
        pGame_options->race_end_target = 1000 * gNet_target[*pGame_type];
1448
        break;
1449
    default:
1450
        pGame_options->race_end_target = gNet_target[*pGame_type];
1451
        break;
1452
    }
1453
}
1454
 
1455
// IDA: int __usercall NetGameChoices@<EAX>(tNet_game_type *pGame_type@<EAX>, tNet_game_options *pGame_options@<EDX>, int *pRace_index@<EBX>)
1456
int NetGameChoices(tNet_game_type* pGame_type, tNet_game_options* pGame_options, int* pRace_index) {
1457
    static tFlicette flicker_on[11] = {
1458
        { 43, { 226, 90 }, { 117, 398 } },
1459
        { 43, { 226, 440 }, { 148, 398 } },
1460
        { 43, { 226, 98 }, { 42, 86 } },
1461
        { 43, { 226, 98 }, { 74, 108 } },
1462
        { 162, { 74, 98 }, { 73, 130 } },
1463
        { 163, { 74, 98 }, { 83, 161 } },
1464
        { 164, { 74, 98 }, { 93, 182 } },
1465
        { 165, { 74, 98 }, { 103, 214 } },
1466
        { 166, { 74, 98 }, { 113, 235 } },
1467
        { 167, { 74, 98 }, { 123, 266 } },
1468
        { 168, { 74, 98 }, { 133, 288 } },
1469
    };
1470
    static tFlicette flicker_off[11] = {
1471
        { 42, { 226, 90 }, { 117, 398 } },
1472
        { 42, { 226, 440 }, { 148, 398 } },
1473
        { 42, { 226, 98 }, { 42, 86 } },
1474
        { 42, { 226, 98 }, { 74, 108 } },
1475
        { 182, { 74, 98 }, { 73, 130 } },
1476
        { 183, { 74, 98 }, { 83, 161 } },
1477
        { 184, { 74, 98 }, { 93, 182 } },
1478
        { 185, { 74, 98 }, { 103, 214 } },
1479
        { 186, { 74, 98 }, { 113, 235 } },
1480
        { 187, { 74, 98 }, { 123, 266 } },
1481
        { 188, { 74, 98 }, { 133, 288 } },
1482
    };
1483
    static tFlicette push[11] = {
1484
        { 88, { 227, 90 }, { 117, 398 } },
1485
        { 45, { 226, 440 }, { 148, 398 } },
1486
        { 195, { 227, 98 }, { 42, 86 } },
1487
        { 124, { 226, 98 }, { 74, 108 } },
1488
        { 162, { 74, 98 }, { 73, 130 } },
1489
        { 163, { 74, 98 }, { 83, 161 } },
1490
        { 164, { 74, 98 }, { 93, 182 } },
1491
        { 165, { 74, 98 }, { 103, 214 } },
1492
        { 166, { 74, 98 }, { 113, 235 } },
1493
        { 167, { 74, 98 }, { 123, 266 } },
1494
        { 168, { 74, 98 }, { 133, 288 } },
1495
    };
1496
    static tMouse_area mouse_areas[11] = {
1497
        { { 226, 90 }, { 117, 396 }, { 290, 214 }, { 137, 444 }, 0, 0, 0, NULL },
1498
        { { 226, 440 }, { 148, 396 }, { 290, 552 }, { 168, 444 }, 1, 0, 0, NULL },
1499
        { { 226, 98 }, { 42, 84 }, { 290, 568 }, { 62, 103 }, 2, 0, 0, NULL },
1500
        { { 226, 98 }, { 74, 106 }, { 290, 568 }, { 94, 125 }, 3, 0, 0, NULL },
1501
        { { 53, 98 }, { 71, 127 }, { 211, 568 }, { 79, 146 }, 4, 1, 0, NULL },
1502
        { { 53, 98 }, { 81, 158 }, { 211, 568 }, { 89, 178 }, 5, 1, 0, NULL },
1503
        { { 53, 98 }, { 91, 180 }, { 211, 568 }, { 99, 199 }, 6, 1, 0, NULL },
1504
        { { 53, 98 }, { 101, 192 }, { 211, 568 }, { 109, 230 }, 7, 1, 0, NULL },
1505
        { { 53, 98 }, { 111, 233 }, { 211, 568 }, { 119, 252 }, 8, 1, 0, NULL },
1506
        { { 53, 98 }, { 121, 264 }, { 211, 568 }, { 129, 283 }, 9, 1, 0, NULL },
1507
        { { 53, 98 }, { 131, 264 }, { 211, 568 }, { 139, 283 }, 10, 1, 0, NULL },
1508
    };
1509
    static tInterface_spec interface_spec = {
1510
        0, 122, 0, 0, 0, 0, -1,
1511
        { 1, 0 }, { 4, -10 }, { 4, 0 }, { 4, 0 }, { NetChooseLR, NULL },
1512
        { 1, 0 }, { 3, -10 }, { 4, 0 }, { 4, 0 }, { NetChooseLR, NULL },
1513
        { -1, -1 }, { -1, -1 }, { 0, 4 }, { 3, 10 }, { NULL, NULL },
1514
        { -1, -1 }, { 1, 1 }, { 0, 4 }, { 3, 10 }, { NULL, NULL },
1515
        { 1, 1 }, { NetChooseGoAhead, NetChooseGoAhead }, { 1, 1 }, { NULL, NULL },
1516
        NULL, DrawNetChoose, 0, NULL, DrawNetChooseInitial, NULL, 0, { 0, 0 }, NULL,
1517
        1, 1,
1518
        COUNT_OF(flicker_on), flicker_on, flicker_off, push,
1519
        COUNT_OF(mouse_areas), mouse_areas,
1520
        0, NULL
1521
 
1522
    };
1523
    int result;
1524
    LOG_TRACE("(%p, %p, %p)", pGame_type, pGame_options, pRace_index);
1525
 
1526
    gRace_index = *pRace_index;
1527
    gLast_game_type = *pGame_type;
1528
    do {
11 pmbaty 1529
        LoadFont(kFont_GRNLIT);
1530
        LoadFont(kFont_GRNDK);
1 pmbaty 1531
        gThe_interface_spec__newgame = &interface_spec;
1532
        gLast_net_choose_box = -1;
1533
        gOptions = pGame_options;
1534
        gNet_race_sequence__newgame = pGame_options->race_sequence_type;
1535
        result = DoInterfaceScreen(&interface_spec, 0, 0);
1536
        if (result || !pGame_options->random_car_choice) {
1537
            RunFlic(123);
1538
        } else {
1539
            FadePaletteDown();
1540
        }
11 pmbaty 1541
        DisposeFont(kFont_GRNDK); // Pierre-Marie Baty -- replaced font number with symbol
1542
        DisposeFont(kFont_GRNLIT); // Pierre-Marie Baty -- replaced font number with symbol
1 pmbaty 1543
        switch (result) {
1544
        case 0:
1545
            *pGame_type = gLast_game_type;
1546
            *pRace_index = gRace_index;
1547
            break;
1548
        case 2:
1549
            ChangeRace(&gRace_index, 1, pGame_options->race_sequence_type);
1550
            break;
1551
        case 3:
1552
            DoNetOptions(pGame_options);
1553
            break;
1554
        }
1555
    } while (result > 1);
1556
    gLast_game_type = *pGame_type;
1557
    gNet_settings[0] = *pGame_options;
1558
    gNet_settings[gLast_game_type + 1] = *pGame_options;
1559
    SaveOptions();
1560
    SetGameTarget(pGame_type, pGame_options);
1561
    return result == 0;
1562
}
1563
 
1564
// IDA: void __usercall ReadNetGameChoices(tNet_game_type *pGame_type@<EAX>, tNet_game_options *pGame_options@<EDX>, int *pRace_index@<EBX>)
1565
void ReadNetGameChoices(tNet_game_type* pGame_type, tNet_game_options* pGame_options, int* pRace_index) {
1566
    LOG_TRACE("(%p, %p, %p)", pGame_type, pGame_options, pRace_index);
1567
 
1568
    *pGame_type = gLast_game_type;
1569
    SetOptions(*pGame_type, pGame_options);
1570
    SetGameTarget(pGame_type, pGame_options);
1571
    *pRace_index = PickNetRace(-1, pGame_options->race_sequence_type);
1572
}
1573
 
1574
// IDA: int __usercall ChooseStartRace@<EAX>(int *pRank@<EAX>)
1575
int ChooseStartRace(int* pRank) {
1576
    LOG_TRACE("(%p)", pRank);
20 pmbaty 1577
    NOT_IMPLEMENTED();
1 pmbaty 1578
}
1579
 
1580
// IDA: void __usercall SetUpOtherNetThings(tNet_game_details *pNet_game@<EAX>)
1581
void SetUpOtherNetThings(tNet_game_details* pNet_game) {
1582
    LOG_TRACE("(%p)", pNet_game);
1583
 
1584
    StartLoadingScreen();
1585
    gProgram_state.skill_level = 1;
1586
    InitGame(pNet_game->start_race);
1587
}
1588
 
1589
// IDA: void __usercall RequestCarDetails(tNet_game_details *pNet_game@<EAX>)
1590
void RequestCarDetails(tNet_game_details* pNet_game) {
1591
    tNet_message* message;
1592
    LOG_TRACE("(%p)", pNet_game);
1593
 
1594
    gReceived_car_details = 0;
1595
    if (gNet_mode == eNet_mode_none) {
1596
        gNet_mode = eNet_mode_thinking_about_it;
1597
    }
1598
    message = NetBuildMessage(NETMSGID_CARDETAILSREQ, 0);
1599
    NetGuaranteedSendMessageToAddress(pNet_game, message, &pNet_game->pd_net_info.addr_in, NULL);
1600
}
1601
 
1602
// IDA: int __cdecl PickARandomCar()
1603
int PickARandomCar(void) {
1604
    int i;
1605
    int cars[120];
1606
    int array_size;
1607
    LOG_TRACE("()");
1608
 
1609
    array_size = 0;
1610
    for (i = 0; i < gNumber_of_racers; i++) {
1611
        if (gCar_details[i].ownership == eCar_owner_none) {
1612
            cars[array_size] = i;
1613
            array_size++;
1614
            if (gOpponents[i].network_availability == eNet_avail_all) {
1615
                cars[array_size] = i;
1616
                array_size++;
1617
            }
1618
        }
1619
    }
1620
    return cars[IRandomBetween(0, array_size - 1)];
1621
}
1622
 
1623
// IDA: void __usercall PollCarDetails(tNet_game_details *pNet_game@<EAX>)
1624
void PollCarDetails(tNet_game_details* pNet_game) {
1625
    LOG_TRACE("(%p)", pNet_game);
1626
 
1627
    if (gReceived_car_details) {
1628
        RequestCarDetails(pNet_game);
1629
    }
1630
}
1631
 
1632
// IDA: void __usercall SetNetAvailability(tNet_game_options *pOptions@<EAX>)
1633
void SetNetAvailability(tNet_game_options* pOptions) {
1634
    int i;
1635
    LOG_TRACE("(%p)", pOptions);
1636
 
1637
    for (i = 0; i < gNumber_of_racers; i++) {
1638
        switch (gOpponents[i].network_availability) {
1639
        case eNet_avail_never:
1640
            gCar_details[i].ownership = eCar_owner_not_allowed;
1641
            break;
1642
        case eNet_avail_eagle:
1643
            if (pOptions->car_choice == eNet_car_annie) {
1644
                gCar_details[i].ownership = eCar_owner_not_allowed;
1645
            } else {
1646
                gCar_details[i].ownership = eCar_owner_none;
1647
            }
1648
            break;
1649
        case eNet_avail_hawk:
1650
            if (pOptions->car_choice == eNet_car_frankie) {
1651
                gCar_details[i].ownership = eCar_owner_not_allowed;
1652
            } else {
1653
                gCar_details[i].ownership = eCar_owner_none;
1654
            }
1655
            break;
1656
        case eNet_avail_all:
1657
            if (pOptions->car_choice == eNet_car_all) {
1658
                gCar_details[i].ownership = eCar_owner_none;
1659
            } else {
1660
                gCar_details[i].ownership = eCar_owner_not_allowed;
1661
            }
1662
        }
1663
    }
1664
}
1665
 
1666
// IDA: int __usercall ChooseNetCar@<EAX>(tNet_game_details *pNet_game@<EAX>, tNet_game_options *pOptions@<EDX>, int *pCar_index@<EBX>, int pIm_the_host_so_fuck_off@<ECX>)
1667
int ChooseNetCar(tNet_game_details* pNet_game, tNet_game_options* pOptions, int* pCar_index, int pIm_the_host_so_fuck_off) {
1668
    tS32 start_time;
1669
    int i;
1670
    int result;
1671
    int car_index;
1672
    //int the_car_index; // Pierre-Marie Baty -- unused variable
1673
    LOG_TRACE("(%p, %p, %p, %d)", pNet_game, pOptions, pCar_index, pIm_the_host_so_fuck_off);
1674
 
1675
    if (!pOptions->random_car_choice || pIm_the_host_so_fuck_off) {
1676
        gNet_options = pOptions;
1677
        if (pIm_the_host_so_fuck_off) {
1678
            SetNetAvailability(pOptions);
1679
        } else {
1680
            RequestCarDetails(pNet_game);
1681
            start_time = PDGetTotalTime();
1682
            while (!gReceived_car_details && PDGetTotalTime() - start_time < 10000) {
1683
                NetService(0);
1684
            }
1685
            gNet_mode = eNet_mode_none;
1686
            if (!gReceived_car_details) {
1687
                gNet_mode = eNet_mode_none;
1688
                return 0;
1689
            }
1690
        }
1691
        if (pOptions->random_car_choice) {
1692
            *pCar_index = PickARandomCar();
1693
            if (pIm_the_host_so_fuck_off && *pCar_index >= 0) {
1694
                gCar_details[*pCar_index].ownership = eCar_owner_someone;
1695
            }
1696
            result = 1;
1697
        } else {
1698
            if (*pCar_index < 0) {
1699
                *pCar_index = PickARandomCar();
1700
                car_index = 0;
1701
                for (i = 0; i < gNumber_of_racers; i++) {
20 pmbaty 1702
                    if (gCar_details[i].ownership != eCar_owner_not_allowed) {
1 pmbaty 1703
                        gProgram_state.cars_available[car_index] = i;
1704
                        car_index++;
1705
                    }
1706
                }
1707
                gProgram_state.number_of_cars = car_index;
1708
            }
1709
            result = ChangeCar(1, pCar_index, pNet_game);
1710
            gNet_mode = eNet_mode_none;
1711
            if (pIm_the_host_so_fuck_off) {
1712
                gCar_details[*pCar_index].ownership = eCar_owner_someone;
1713
            }
1714
        }
1715
    } else {
1716
        result = 1;
1717
    }
1718
    return result;
1719
}
1720
 
1721
// IDA: void __cdecl InitNetStorageSpace()
1722
void InitNetStorageSpace(void) {
1723
    int i;
1724
    LOG_TRACE("()");
1725
 
1726
    for (i = 0; i < COUNT_OF(gNet_players); i++) {
1727
        gCurrent_race.opponent_list[i].car_spec = NULL;
1728
    }
1729
    gNet_storage_allocated = 1;
1730
    InitialiseStorageSpace(&gNet_cars_storage_space, 500, 50, 500, 300);
1731
}
1732
 
1733
// IDA: void __cdecl DisposeNetStorageSpace()
1734
void DisposeNetStorageSpace(void) {
1735
    LOG_TRACE("()");
1736
 
1737
    if (gNet_storage_allocated) {
1738
        DisposeStorageSpace(&gNet_cars_storage_space);
1739
    }
1740
    gNet_storage_allocated = 0;
1741
}
1742
 
1743
// IDA: int __cdecl DoMultiPlayerStart()
1744
int DoMultiPlayerStart(void) {
1745
    tJoin_or_host_result result;
1746
    tNet_game_details* game_to_join;
1747
    char s[256];
1748
    //char* s2; // Pierre-Marie Baty -- unused variable
1749
    tNet_game_type new_game_type;
1750
    tNet_game_options new_game_options;
1751
    int start_rank;
1752
    int car_index;
1753
    //int race_index; // added by dethrace // Pierre-Marie Baty -- unused variable
1754
    LOG_TRACE("()");
1755
 
1756
    if (harness_game_info.mode == eGame_carmageddon_demo || harness_game_info.mode == eGame_splatpack_demo || harness_game_info.mode == eGame_splatpack_xmas_demo) {
1757
        SuspendPendingFlic();
1758
        DoFeatureUnavailableInDemo();
1759
        return 0;
1760
    }
1761
 
1762
    if (gAusterity_mode) {
20 pmbaty 1763
        NetFullScreenMessage(192, 0);
1 pmbaty 1764
        return 0;
1765
    }
1766
    if (NetInitialise()) {
1767
        SuspendPendingFlic();
1768
        DoErrorInterface(kMiscString_NetworkPlayIsNotAvailable);
1769
        return 0;
1770
    }
1771
    gSynch_race_start = 0;
1772
    gPending_race = -1;
1773
    gCurrent_race.number_of_racers = 0;
1774
    gAsk_time = 0;
1775
    AboutToLoadFirstCar();
1776
    result = JoinOrHostGame(&game_to_join);
1777
    switch (result) {
1778
    case eJoin_or_host_cancel:
1779
        return 0;
1780
    case eJoin_or_host_join:
1781
        gProgram_state.frank_or_anniness = eFrankie;
1782
        if (!CarmaCDinDriveOrFullGameInstalled()) {
1783
            DoErrorInterface(kMiscString_PLEASE_INSERT_THE_CARMAGEDDON_CD);
1784
            return 0;
1785
        }
1786
        car_index = -1;
1787
        // Abusing 'start_rank' here, it's probably better to introduce a new variable name (e.g. join_result)
1788
        start_rank = -4;
1789
        while (start_rank == -4) {
1790
            start_rank = 0;
1791
            if (!ChooseNetCar(game_to_join, &game_to_join->options, &car_index, 0)) {
1792
                continue;
1793
            }
1794
            StartLoadingScreen();
1795
            InitNetStorageSpace();
1796
            start_rank = NetJoinGame(game_to_join, gProgram_state.player_name[0], car_index);
1797
            if (start_rank == 0) {
1798
                LoadRaces(gRace_list, &gNumber_of_races, gCurrent_net_game->type);
1799
                SetUpOtherNetThings(game_to_join);
1800
                ReenableNetService();
1801
                strcpy(s, gProgram_state.player_name[0]);
1802
                strcat(s, " ");
1803
                strcat(s, GetMiscString(kMiscString_HasJoinedTheGame));
1804
                NetSendHeadupToAllPlayers(s);
1805
                start_rank = 1;
1806
            } else {
1807
                DisposeNetStorageSpace();
1808
            }
1809
        }
1810
        if (start_rank <= 0) {
1811
            NetDisposeGameDetails(game_to_join);
1812
            return 0;
1813
        } else {
1814
            return 1;
1815
        }
1816
    case eJoin_or_host_host:
1817
        gProgram_state.frank_or_anniness = eFrankie;
1818
        if (!OriginalCarmaCDinDrive()) {
1819
            DoErrorInterface(kMiscString_PLEASE_INSERT_THE_CARMAGEDDON_CD);
1820
            return 0;
1821
        }
1822
        car_index = -1;
1823
        ReadNetGameChoices(&new_game_type, &new_game_options, &start_rank);
1824
        LoadRaces(gRace_list, &gNumber_of_races, new_game_type);
1825
        start_rank = PickNetRace(-1, new_game_options.race_sequence_type);
1826
        if (NetGameChoices(&new_game_type, &new_game_options, &start_rank) != 0
1827
            && ChooseNetCar(gCurrent_net_game, &new_game_options, &car_index, 1) != 0) {
1828
            StartLoadingScreen();
1829
            InitNetStorageSpace();
1830
            if (NetHostGame(new_game_type, &new_game_options, start_rank, gProgram_state.player_name[0], car_index) != NULL) {
1831
                SetUpOtherNetThings(gCurrent_net_game);
1832
                ReenableNetService();
1833
                return 1;
1834
            } else {
1835
                DisposeNetStorageSpace();
1836
                ReenableNetService();
1837
                NetLeaveGame(gCurrent_net_game);
1838
                return 0;
1839
            }
1840
        }
1841
    default:
1842
        return 0;
1843
    }
1844
}