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 "options.h"
2
#include "brucetrk.h"
3
#include "controls.h"
4
#include "depth.h"
5
#include "displays.h"
6
#include "dr_types.h"
7
#include "drmem.h"
8
#include "errors.h"
9
#include "flicplay.h"
10
#include "globvars.h"
11
#include "grafdata.h"
12
#include "graphics.h"
11 pmbaty 13
#include "harness/config.h"
1 pmbaty 14
#include "harness/trace.h"
15
#include "input.h"
16
#include "intrface.h"
17
#include "loading.h"
18
#include "network.h"
19
#include "pd/sys.h"
20
#include "sound.h"
21
#include "spark.h"
22
#include "utility.h"
23
#include "world.h"
20 pmbaty 24
#include <brender/brender.h>
1 pmbaty 25
#include <stdlib.h>
26
#include <string.h>
27
 
28
int gKey_defns[18] = { 48, 49, 46, 47, 53, 44, 59, 57, 55, 45, 50, 51, 52, 56, 62, 63, 64, 66 };
29
tRadio_bastards gRadio_bastards__options[13] = {
30
    // suffix added to avoid duplicate symbol
31
    { 4, 36, 0, { 132, 175, 221, 253, 0 } },
32
    { 3, 45, 0, { 132, 157, 217, 0, 0 } },
33
    { 3, 54, 0, { 132, 183, 236, 0, 0 } },
34
    { 3, 67, 0, { 132, 194, 234, 0, 0 } },
35
    { 3, 76, 0, { 132, 194, 234, 0, 0 } },
36
    { 4, 89, 0, { 132, 176, 204, 246, 0 } },
37
    { 4, 98, 0, { 132, 176, 204, 246, 0 } },
38
    { 2, 111, 0, { 132, 158, 0, 0, 0 } },
39
    { 2, 120, 0, { 132, 158, 0, 0, 0 } },
40
    { 2, 129, 0, { 132, 158, 0, 0, 0 } },
41
    { 2, 138, 0, { 132, 158, 0, 0, 0 } },
42
    { 3, 150, 0, { 132, 164, 207, 0, 0 } },
43
    { 4, 153, 0, { 177, 199, 220, 242, 0 } },
44
};
45
int gKey_count;
46
int gLast_graph_sel__options; // suffix added to avoid duplicate symbol
47
char* gKey_names[125];
48
int gPending_entry;
49
tInterface_spec* gThe_interface_spec__options; // suffix added to avoid duplicate symbol
50
int gOrig_key_mapping[67];
51
br_pixelmap* gDials_pix;
52
int gCurrent_key;
53
 
54
// IDA: void __usercall DrawDial(int pWhich_one@<EAX>, int pWhich_stage@<EDX>)
55
void DrawDial(int pWhich_one, int pWhich_stage) {
56
    LOG_TRACE("(%d, %d)", pWhich_one, pWhich_stage);
11 pmbaty 57
 
58
    RemoveTransientBitmaps(1);
59
    DRPixelmapRectangleMaskedCopy(gBack_screen,
60
        gCurrent_graf_data->dial__x[pWhich_one],
61
        gCurrent_graf_data->dial__y[pWhich_one],
62
        gDials_pix,
63
        0,
64
        pWhich_stage * 64,
65
        gDials_pix->width,
66
        64);
67
    ProcessFlicQueue(gFrame_period);
68
    DoMouseCursor();
69
    PDScreenBufferSwap(0);
1 pmbaty 70
}
71
 
72
// IDA: void __usercall MoveDialFromTo(int pWhich_one@<EAX>, int pOld_stage@<EDX>, int pNew_stage@<EBX>)
73
void MoveDialFromTo(int pWhich_one, int pOld_stage, int pNew_stage) {
11 pmbaty 74
    tS32 time_diff;
75
    tU32 start_time;
1 pmbaty 76
    LOG_TRACE("(%d, %d, %d)", pWhich_one, pOld_stage, pNew_stage);
11 pmbaty 77
 
78
    DrawDial(pWhich_one, pOld_stage);
79
    start_time = PDGetTotalTime();
80
    while ((time_diff = PDGetTotalTime() - start_time) < 100) {
20 pmbaty 81
         DrawDial(pWhich_one, pOld_stage + (pNew_stage - pOld_stage) * time_diff / 100);
11 pmbaty 82
    }
83
    DrawDial(pWhich_one, pNew_stage);
84
 
85
    start_time = PDGetTotalTime();
86
    DrawDial(pWhich_one, pNew_stage < 24 ? pNew_stage + 1 : 22);
87
    while ((time_diff = PDGetTotalTime() - start_time) < 20) {
88
    }
89
 
90
    start_time = PDGetTotalTime();
91
    DrawDial(pWhich_one, pNew_stage == 0 ? 2 : pNew_stage - 1);
92
    while ((time_diff = PDGetTotalTime() - start_time) < 20) {
93
    }
94
 
95
    start_time = PDGetTotalTime();
96
    DrawDial(pWhich_one, pNew_stage < 24 ? pNew_stage + 1 : 22);
97
    while ((time_diff = PDGetTotalTime() - start_time) < 20) {
98
    }
99
 
100
    start_time = PDGetTotalTime();
101
    DrawDial(pWhich_one, pNew_stage);
102
    while ((time_diff = PDGetTotalTime() - start_time) < 20) {
103
    }
104
 
105
    start_time = PDGetTotalTime();
106
    DrawDial(pWhich_one, pNew_stage == 0 ? 2 : pNew_stage - 1);
107
    while ((time_diff = PDGetTotalTime() - start_time) < 20) {
108
    }
109
    DrawDial(pWhich_one, pNew_stage);
1 pmbaty 110
}
111
 
112
// IDA: void __cdecl SoundOptionsStart()
113
void SoundOptionsStart(void) {
114
    LOG_TRACE("()");
11 pmbaty 115
 
116
    DrawDial(0, 0);
117
    DrawDial(1, 0);
118
    MoveDialFromTo(0, 0, 4 * gProgram_state.music_volume);
119
    MoveDialFromTo(1, 0, 4 * gProgram_state.music_volume);
1 pmbaty 120
}
121
 
122
// IDA: int __usercall SoundOptionsDone@<EAX>(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>, int pGo_ahead@<EBX>, int pEscaped@<ECX>, int pTimed_out)
123
int SoundOptionsDone(int pCurrent_choice, int pCurrent_mode, int pGo_ahead, int pEscaped, int pTimed_out) {
124
    LOG_TRACE("(%d, %d, %d, %d, %d)", pCurrent_choice, pCurrent_mode, pGo_ahead, pEscaped, pTimed_out);
11 pmbaty 125
 
126
    MoveDialFromTo(0, 4 * gProgram_state.music_volume, 0);
127
    MoveDialFromTo(0, 4 * gProgram_state.effects_volume, 0);
128
    return pCurrent_choice;
1 pmbaty 129
}
130
 
131
// IDA: int __usercall SoundOptionsLeft@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
132
int SoundOptionsLeft(int* pCurrent_choice, int* pCurrent_mode) {
11 pmbaty 133
    int old_value;
134
    int* the_value;
1 pmbaty 135
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
11 pmbaty 136
 
137
    if (*pCurrent_choice == 2) {
138
        return 0;
139
    }
140
    the_value = (*pCurrent_choice == 0) ? &gProgram_state.music_volume : &gProgram_state.effects_volume;
141
    old_value = *the_value;
142
    *the_value -= 1;
143
    if (*the_value < 0) {
144
        *the_value = 0;
145
    }
146
    SetSoundVolumes();
147
    DRS3StartSound(gEffects_outlet, 3000);
148
    MoveDialFromTo(*pCurrent_choice, 4 * old_value, 4 * *the_value);
149
    return 0;
1 pmbaty 150
}
151
 
152
// IDA: int __usercall SoundOptionsRight@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
153
int SoundOptionsRight(int* pCurrent_choice, int* pCurrent_mode) {
11 pmbaty 154
    int old_value; // Pierre-Marie Baty -- unused variable
155
    int* the_value; // Pierre-Marie Baty -- unused variable
1 pmbaty 156
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
11 pmbaty 157
 
158
    if (*pCurrent_choice == 2) {
159
        return 0;
160
    }
161
    the_value = (*pCurrent_choice == 0) ? &gProgram_state.music_volume : &gProgram_state.effects_volume;
162
    old_value = *the_value;
163
    *the_value += 1;
164
    if (*the_value >= 6) {
165
        *the_value = 6;
166
    }
167
    SetSoundVolumes();
168
    DRS3StartSound(gEffects_outlet, 3000);
169
    MoveDialFromTo(*pCurrent_choice, 4 * old_value, 4 * *the_value);
170
    return 0;
1 pmbaty 171
}
172
 
173
// IDA: int __usercall SoundClick@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>, int pX_offset@<EBX>, int pY_offset@<ECX>)
174
int SoundClick(int* pCurrent_choice, int* pCurrent_mode, int pX_offset, int pY_offset) {
11 pmbaty 175
    float x_delta; // Pierre-Marie Baty -- unused variable
176
    float y_delta; // Pierre-Marie Baty -- unused variable
177
    float angle; // Pierre-Marie Baty -- unused variable
178
    int old_value; // Pierre-Marie Baty -- unused variable
179
    int* the_value; // Pierre-Marie Baty -- unused variable
1 pmbaty 180
    LOG_TRACE("(%p, %p, %d, %d)", pCurrent_choice, pCurrent_mode, pX_offset, pY_offset);
11 pmbaty 181
 
182
#define ANGLE_RANGE_START (20 * PI / 360)
183
#define ANGLE_RANGE_END (340 * PI / 360)
184
 
185
    x_delta = pX_offset - gCurrent_graf_data->dial__x_centre;
186
    y_delta = gCurrent_graf_data->dial__y_centre - pY_offset;
187
    if (y_delta <= 0.f) {
188
        return 0;
189
    }
190
    angle = x_delta == 0.f ? PI / 2 : atanf(y_delta / x_delta);
191
    if (angle < 0.f) {
192
        angle += PI;
193
    }
194
    if (angle > ANGLE_RANGE_START && angle < ANGLE_RANGE_END) {
195
        the_value = (*pCurrent_choice == 0) ? &gProgram_state.music_volume : &gProgram_state.effects_volume;
196
        old_value = *the_value;
197
        *the_value = (ANGLE_RANGE_END - angle + 0.233001455141243) / 0.4660029102824859;
198
        if (*the_value > 6) {
199
            *the_value = 6;
200
        } else if (*the_value < 0) {
201
            *the_value = 0;
202
        }
203
        if (*the_value != old_value) {
204
            SetSoundVolumes();
205
            if (old_value < *the_value) {
206
                DRS3StartSound(gEffects_outlet, 3000);
207
            } else {
208
                DRS3StartSound(gEffects_outlet, 3000);
209
            }
210
            MoveDialFromTo(*pCurrent_choice, 4 * old_value, 4 * *the_value);
211
        }
212
    }
213
    return 0;
1 pmbaty 214
}
215
 
216
// IDA: void __cdecl DoSoundOptions()
217
void DoSoundOptions(void) {
11 pmbaty 218
    static tFlicette flicker_on[3] = {
20 pmbaty 219
        { 156, {  26,  52 }, {  21,  50 } },
220
        { 156, { 155, 310 }, {  88, 211 } },
221
        {  43, {  38,  76 }, { 153, 367 } },
11 pmbaty 222
    };
223
    static tFlicette flicker_off[3] = {
20 pmbaty 224
        { 155, {  26,  52 }, {  21,  50 } },
225
        { 155, { 155, 310 }, {  88, 211 } },
226
        {  42, {  38,  76 }, { 153, 367 } },
11 pmbaty 227
    };
228
    static tFlicette push[3] = {
20 pmbaty 229
        { 156, {  26,  52 }, {  21,  50 } },
230
        { 156, { 155, 310 }, {  88, 211 } },
231
        {  43, {  38,  76 }, { 153, 367 } },
11 pmbaty 232
    };
233
    static tMouse_area mouse_areas[3] = {
20 pmbaty 234
        { {  26,  52 }, {  21,  50 }, { 144, 288 }, {  97, 233 },   0,   0,   0, SoundClick },
235
        { { 155, 310 }, {  88, 211 }, { 273, 546 }, { 164, 394 },   1,   0,   0, SoundClick },
236
        { {  38,  76 }, { 153, 367 }, { 101, 202 }, { 173, 415 },   2,   0,   0, NULL },
11 pmbaty 237
    };
238
    static tInterface_spec interface_spec = {
239
        0,
240
        150,
241
        0,
242
        0,
243
        0,
244
        0,
245
        1,
246
        { -1, 0 },
247
        { 0, 0 },
248
        { 0, 0 },
249
        { 0, 0 },
250
        { SoundOptionsLeft, NULL },
251
        { -1, 0 },
252
        { 0, 0 },
253
        { 0, 0 },
254
        { 0, 0 },
255
        { SoundOptionsRight, NULL },
256
        { -1, 0 },
257
        { -1, 0 },
258
        { 0, 0 },
259
        { 2, 0 },
260
        { NULL, NULL },
261
        { -1, 0 },
262
        { 1, 0 },
263
        { 0, 0 },
264
        { 2, 0 },
265
        { NULL, NULL },
266
        { 1, 1 },
267
        { NULL, NULL },
268
        { 1, 1 },
269
        { NULL, NULL },
270
        NULL,
271
        NULL,
272
        0,
273
        NULL,
274
        SoundOptionsStart,
275
        SoundOptionsDone,
276
        0,
277
        { 0, 0 },
278
        NULL,
279
        2,
280
        1,
281
        COUNT_OF(flicker_on),
282
        flicker_on,
283
        flicker_off,
284
        push,
285
        COUNT_OF(mouse_areas),
286
        mouse_areas,
287
        0,
288
        NULL,
289
    };
290
    int result; // Pierre-Marie Baty -- unused variable
1 pmbaty 291
    LOG_TRACE("()");
11 pmbaty 292
 
293
    DoInterfaceScreen(&interface_spec, 0, 0);
294
    if (!gProgram_state.racing) {
295
        RunFlic(151);
296
    } else {
297
        FadePaletteDown();
298
    }
1 pmbaty 299
}
300
 
301
// IDA: void __cdecl GetGraphicsOptions()
302
void GetGraphicsOptions(void) {
303
    int value;
304
    br_scalar br_value;
305
    LOG_TRACE("()");
306
 
307
    value = GetCarSimplificationLevel();
308
    if (value > 1) {
309
        value--;
310
    }
311
    gRadio_bastards__options[0].current_value = value;
312
 
313
    switch (GetCarTexturingLevel()) {
314
    case eCTL_none:
315
        value = 2;
316
        break;
317
    case eCTL_transparent:
318
        value = 1;
319
        break;
320
    case eCTL_full:
321
        value = 0;
322
        break;
323
    case eCTL_count:
324
        TELL_ME_IF_WE_PASS_THIS_WAY();
325
        break;
326
    }
327
    gRadio_bastards__options[1].current_value = value;
328
 
329
    switch (GetShadowLevel()) {
330
    case eShadow_none:
331
        value = 2;
332
        break;
333
    case eShadow_us_only:
334
        value = 1;
335
        break;
336
    default:
337
        value = 0;
338
        break;
339
    }
340
    gRadio_bastards__options[2].current_value = value;
341
 
342
    switch (GetWallTexturingLevel()) {
343
    case eWTL_none:
344
        value = 2;
345
        break;
346
    case eWTL_linear:
347
        value = 1;
348
        break;
349
    case eWTL_full:
350
        value = 0;
351
        break;
352
    case eWTL_count:
353
        TELL_ME_IF_WE_PASS_THIS_WAY();
354
        break;
355
    }
356
    gRadio_bastards__options[3].current_value = value;
357
 
358
    switch (GetRoadTexturingLevel()) {
359
    case eRTL_none:
360
        value = 2;
361
        break;
362
    case eRTL_full:
363
        value = 0;
364
        break;
365
    case eRTL_count:
366
        TELL_ME_IF_WE_PASS_THIS_WAY();
367
        break;
368
    }
369
    gRadio_bastards__options[4].current_value = value;
370
 
371
    value = (int)((35.f - GetYon()) / 5.f);
372
    gRadio_bastards__options[5].current_value = value;
373
 
374
    br_value = GetYonFactor();
375
    if (br_value < .5f) {
376
        if (br_value < .25f) {
377
            value = 3;
378
        } else {
379
            value = 2;
380
        }
381
    } else {
382
        if (br_value < 1.f) {
383
            value = 1;
384
        } else {
385
            value = 0;
386
        }
387
    }
388
    gRadio_bastards__options[6].current_value = value;
389
 
390
    value = !GetSkyTextureOn();
391
    gRadio_bastards__options[7].current_value = value;
392
 
393
    value = !GetDepthCueingOn();
394
    gRadio_bastards__options[8].current_value = value;
395
 
396
    value = !GetAccessoryRendering();
397
    gRadio_bastards__options[9].current_value = value;
398
 
399
    value = !GetSmokeOn();
400
    gRadio_bastards__options[10].current_value = value;
401
 
402
    value = 2 - GetSoundDetailLevel();
403
    gRadio_bastards__options[11].current_value = value;
404
}
405
 
406
// IDA: void __cdecl SetGraphicsOptions()
407
void SetGraphicsOptions(void) {
408
    LOG_TRACE("()");
409
 
410
    if (gRadio_bastards__options[0].current_value < 2) {
411
        SetCarSimplificationLevel(gRadio_bastards__options[0].current_value);
412
    } else {
413
        SetCarSimplificationLevel(gRadio_bastards__options[0].current_value + 1);
414
    }
415
 
416
    switch (gRadio_bastards__options[1].current_value) {
417
    case 0:
418
        SetCarTexturingLevel(eCTL_full);
419
        break;
420
    case 1:
421
        SetCarTexturingLevel(eCTL_transparent);
422
        break;
423
    case 2:
424
        SetCarTexturingLevel(eCTL_none);
425
        break;
426
    }
427
 
428
    switch (gRadio_bastards__options[2].current_value) {
429
    case 0:
430
        SetShadowLevel(eShadow_everyone);
431
        break;
432
    case 1:
433
        SetShadowLevel(eShadow_us_only);
434
        break;
435
    case 2:
436
        SetShadowLevel(eShadow_none);
437
        break;
438
    }
439
 
440
    switch (gRadio_bastards__options[3].current_value) {
441
    case 0:
442
        SetWallTexturingLevel(eWTL_full);
443
        break;
444
    case 1:
445
        SetWallTexturingLevel(eWTL_linear);
446
        break;
447
    case 2:
448
        SetWallTexturingLevel(eWTL_none);
449
        break;
450
    }
451
 
452
    switch (gRadio_bastards__options[4].current_value) {
453
    case 0:
454
        SetRoadTexturingLevel(eRTL_full);
455
        break;
456
    case 2:
457
        SetRoadTexturingLevel(eRTL_none);
458
        break;
459
    }
460
 
461
    SetYon(35.f - gRadio_bastards__options[5].current_value * 5.f);
462
 
463
    switch (gRadio_bastards__options[6].current_value) {
464
    case 0:
465
        SetYonFactor(1.f);
466
        break;
467
    case 1:
468
        SetYonFactor(.5f);
469
        break;
470
    case 2:
471
        SetYonFactor(.25f);
472
        break;
473
    case 3:
474
        SetYonFactor(.125f);
475
        break;
476
    }
477
 
478
    SetSkyTextureOn(1 - gRadio_bastards__options[7].current_value);
479
    SetDepthCueingOn(1 - gRadio_bastards__options[8].current_value);
480
    SetAccessoryRendering(1 - gRadio_bastards__options[9].current_value);
481
    SetSmokeOn(1 - gRadio_bastards__options[10].current_value);
482
    SetSoundDetailLevel(2 - gRadio_bastards__options[11].current_value);
483
    SaveOptions();
484
}
485
 
486
// IDA: void __usercall PlayRadioOn2(int pIndex@<EAX>, int pValue@<EDX>)
487
void PlayRadioOn2(int pIndex, int pValue) {
488
    LOG_TRACE("(%d, %d)", pIndex, pValue);
489
 
490
    RunFlicAt(288,
491
        gRadio_bastards__options[pIndex].left[pValue],
492
        gRadio_bastards__options[pIndex].top);
493
}
494
 
495
// IDA: void __usercall PlayRadioOff2(int pIndex@<EAX>, int pValue@<EDX>)
496
void PlayRadioOff2(int pIndex, int pValue) {
497
    LOG_TRACE("(%d, %d)", pIndex, pValue);
498
 
499
    RunFlicAt(287,
500
        gRadio_bastards__options[pIndex].left[pValue],
501
        gRadio_bastards__options[pIndex].top);
502
}
503
 
504
// IDA: void __usercall PlayRadioOn(int pIndex@<EAX>, int pValue@<EDX>)
505
void PlayRadioOn__options(int pIndex, int pValue) {
506
    LOG_TRACE("(%d, %d)", pIndex, pValue);
507
 
508
    RemoveTransientBitmaps(1);
509
    DontLetFlicFuckWithPalettes();
510
    TurnFlicTransparencyOn();
511
    PlayRadioOn2(pIndex, pValue);
512
    TurnFlicTransparencyOff();
513
    LetFlicFuckWithPalettes();
514
}
515
 
516
// IDA: void __usercall PlayRadioOff(int pIndex@<EAX>, int pValue@<EDX>)
517
void PlayRadioOff__options(int pIndex, int pValue) {
518
    LOG_TRACE("(%d, %d)", pIndex, pValue);
519
 
520
    RemoveTransientBitmaps(1);
521
    DontLetFlicFuckWithPalettes();
522
    TurnFlicTransparencyOn();
523
    PlayRadioOff2(pIndex, pValue);
524
    TurnFlicTransparencyOff();
525
    LetFlicFuckWithPalettes();
526
}
527
 
528
// IDA: void __cdecl DrawInitialRadios()
529
void DrawInitialRadios(void) {
530
    int i;
531
    LOG_TRACE("()");
532
 
533
    RemoveTransientBitmaps(1);
534
    DontLetFlicFuckWithPalettes();
535
    TurnFlicTransparencyOn();
536
    // FIXME: count of radio buttons does not agree with windows version
537
    for (i = 0; i < COUNT_OF(gRadio_bastards__options) - 1; i++) {
538
        PlayRadioOn2(i, gRadio_bastards__options[i].current_value);
539
    }
540
    TurnFlicTransparencyOff();
541
    LetFlicFuckWithPalettes();
542
}
543
 
544
// IDA: void __usercall RadioChanged(int pIndex@<EAX>, int pNew_value@<EDX>)
545
void RadioChanged(int pIndex, int pNew_value) {
546
    LOG_TRACE("(%d, %d)", pIndex, pNew_value);
547
 
548
    PlayRadioOff__options(pIndex, gRadio_bastards__options[pIndex].current_value);
549
    PlayRadioOn__options(pIndex, pNew_value);
550
    gRadio_bastards__options[pIndex].current_value = pNew_value;
551
}
552
 
553
// IDA: int __usercall GraphOptLeft@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
554
int GraphOptLeft(int* pCurrent_choice, int* pCurrent_mode) {
555
    int new_value;
556
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
557
 
558
    DRS3StartSound(gEffects_outlet, 3000);
559
    new_value = gRadio_bastards__options[*pCurrent_choice - 2].current_value - 1;
560
    if (new_value < 0) {
561
        new_value = gRadio_bastards__options[*pCurrent_choice - 2].count - 1;
562
    }
563
    RadioChanged(*pCurrent_choice - 2, new_value);
564
    return 1;
565
}
566
 
567
// IDA: int __usercall GraphOptRight@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
568
int GraphOptRight(int* pCurrent_choice, int* pCurrent_mode) {
569
    int new_value;
570
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
571
 
572
    DRS3StartSound(gEffects_outlet, 3000);
573
    new_value = gRadio_bastards__options[*pCurrent_choice + -2].current_value + 1;
574
    if (new_value == gRadio_bastards__options[*pCurrent_choice - 2].count) {
575
        new_value = 0;
576
    }
577
    RadioChanged(*pCurrent_choice - 2, new_value);
578
    return 1;
579
}
580
 
581
// IDA: int __usercall GraphOptUp@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
582
int GraphOptUp(int* pCurrent_choice, int* pCurrent_mode) {
583
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
584
 
585
    if (*pCurrent_mode == 0) {
586
        *pCurrent_mode = 1;
587
        *pCurrent_choice = 13;
588
        DRS3StartSound(gEffects_outlet, 3000);
589
        return 1;
590
    } else if (*pCurrent_choice == 1) {
591
        *pCurrent_mode = 0;
592
        *pCurrent_choice = 0;
593
        DRS3StartSound(gEffects_outlet, 3000);
594
        return 1;
595
    } else {
596
        return 0;
597
    }
598
}
599
 
600
// IDA: int __usercall GraphOptDown@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
601
int GraphOptDown(int* pCurrent_choice, int* pCurrent_mode) {
602
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
603
 
604
    if (*pCurrent_mode == 0) {
605
        *pCurrent_mode = 1;
606
        *pCurrent_choice = 2;
607
        DRS3StartSound(gEffects_outlet, 3000);
608
        return 1;
609
    } else if (*pCurrent_choice == 14) {
610
        *pCurrent_mode = 0;
611
        *pCurrent_choice = 0;
612
        DRS3StartSound(gEffects_outlet, 3000);
613
        return 1;
614
    } else {
615
        return 0;
616
    }
617
}
618
 
619
// IDA: int __usercall RadioClick@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>, int pX_offset@<EBX>, int pY_offset@<ECX>)
620
int RadioClick(int* pCurrent_choice, int* pCurrent_mode, int pX_offset, int pY_offset) {
621
    int i;
622
    LOG_TRACE("(%p, %p, %d, %d)", pCurrent_choice, pCurrent_mode, pX_offset, pY_offset);
623
 
624
    for (i = gRadio_bastards__options[*pCurrent_choice - 2].count - 1; i >= 0; i--) {
625
        if (gThe_interface_spec__options->mouse_areas[2].left[gGraf_data_index] + pX_offset + 3 >= gRadio_bastards__options[*pCurrent_choice - 2].left[i]) {
626
            DRS3StartSound(gEffects_outlet, 3000);
627
            RadioChanged(*pCurrent_choice - 2, i);
628
            return 0;
629
        }
630
    }
631
    return 0;
632
}
633
 
634
// IDA: int __usercall GraphOptGoAhead@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
635
int GraphOptGoAhead(int* pCurrent_choice, int* pCurrent_mode) {
636
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
637
 
638
    GraphOptRight(pCurrent_choice, pCurrent_mode);
639
    return 0;
640
}
641
 
642
// IDA: void __usercall PlotAGraphBox(int pIndex@<EAX>, int pColour_value@<EDX>)
643
//  Suffix added to avoid duplicate symbol
644
void PlotAGraphBox__options(int pIndex, int pColour_value) {
645
    LOG_TRACE("(%d, %d)", pIndex, pColour_value);
646
 
647
    if (pIndex < 0) {
648
        return;
649
    }
650
    DrawRRectangle(gBack_screen,
651
        gThe_interface_spec__options->mouse_areas[2].left[gGraf_data_index] - 6,
652
        gRadio_bastards__options[pIndex].top - 3,
653
        gThe_interface_spec__options->mouse_areas[2].right[gGraf_data_index] + 3,
15 pmbaty 654
        gRadio_bastards__options[pIndex].top + gFonts[kFont_GRYLIT].height + 2 - (TranslationMode() ? 2 : 0), pColour_value);
1 pmbaty 655
}
656
 
657
// IDA: void __usercall DrawAGraphBox(int pIndex@<EAX>)
658
//  Suffix added to avoid duplicate symbol
659
void DrawAGraphBox__options(int pIndex) {
660
    LOG_TRACE("(%d)", pIndex);
661
 
662
    PlotAGraphBox__options(pIndex, 45);
663
}
664
 
665
// IDA: void __usercall EraseAGraphBox(int pIndex@<EAX>)
666
//  Suffix added to avoid duplicate symbol
667
void EraseAGraphBox__options(int pIndex) {
668
    LOG_TRACE("(%d)", pIndex);
669
 
670
    PlotAGraphBox__options(pIndex, 0);
671
}
672
 
673
// IDA: void __usercall DrawGraphBox(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>)
674
void DrawGraphBox(int pCurrent_choice, int pCurrent_mode) {
675
    LOG_TRACE("(%d, %d)", pCurrent_choice, pCurrent_mode);
676
 
677
    if (pCurrent_choice != gCurrent_key) {
678
        EraseAGraphBox__options(gCurrent_key - 2);
679
        DrawAGraphBox__options(pCurrent_choice - 2);
680
        gCurrent_key = pCurrent_choice;
681
    }
682
}
683
 
684
// IDA: void __cdecl DoGraphicsOptions()
685
void DoGraphicsOptions(void) {
686
    static tFlicette flicker_on[14] = {
687
        { 43, { 45, 90 }, { 166, 398 } },
688
        { 43, { 220, 440 }, { 166, 398 } },
689
        { 238, { 49, 98 }, { 36, 86 } },
690
        { 239, { 49, 98 }, { 45, 108 } },
691
        { 240, { 49, 98 }, { 54, 130 } },
692
        { 241, { 49, 98 }, { 67, 161 } },
693
        { 242, { 49, 98 }, { 76, 182 } },
694
        { 243, { 49, 98 }, { 89, 214 } },
695
        { 244, { 49, 98 }, { 98, 235 } },
696
        { 245, { 49, 98 }, { 111, 266 } },
697
        { 246, { 49, 98 }, { 120, 288 } },
698
        { 247, { 49, 98 }, { 129, 310 } },
699
        { 248, { 49, 98 }, { 138, 331 } },
700
        { 249, { 49, 98 }, { 150, 360 } },
701
    };
702
    static tFlicette flicker_off[14] = {
703
        { 42, { 45, 90 }, { 166, 398 } },
704
        { 42, { 220, 440 }, { 166, 398 } },
705
        { 265, { 49, 98 }, { 36, 86 } },
706
        { 266, { 49, 98 }, { 45, 108 } },
707
        { 267, { 49, 98 }, { 54, 130 } },
708
        { 268, { 49, 98 }, { 67, 161 } },
709
        { 269, { 49, 98 }, { 76, 182 } },
710
        { 270, { 49, 98 }, { 89, 214 } },
711
        { 271, { 49, 98 }, { 98, 235 } },
712
        { 272, { 49, 98 }, { 111, 266 } },
713
        { 273, { 49, 98 }, { 120, 288 } },
714
        { 274, { 49, 98 }, { 129, 310 } },
715
        { 275, { 49, 98 }, { 138, 331 } },
716
        { 276, { 49, 98 }, { 150, 360 } },
717
    };
718
    static tFlicette push[14] = {
719
        { 154, { 45, 90 }, { 166, 398 } },
720
        { 45, { 220, 440 }, { 166, 398 } },
721
        { 45, { 210, 440 }, { 170, 408 } },
722
        { 45, { 210, 440 }, { 170, 408 } },
723
        { 45, { 210, 440 }, { 170, 408 } },
724
        { 45, { 210, 440 }, { 170, 408 } },
725
        { 45, { 210, 440 }, { 170, 408 } },
726
        { 45, { 210, 440 }, { 170, 408 } },
727
        { 45, { 210, 440 }, { 170, 408 } },
728
        { 45, { 210, 440 }, { 170, 408 } },
729
        { 45, { 210, 440 }, { 170, 408 } },
730
        { 45, { 210, 440 }, { 170, 408 } },
731
        { 45, { 210, 440 }, { 170, 408 } },
732
        { 45, { 210, 440 }, { 170, 408 } },
733
    };
734
    static tMouse_area mouse_areas[14] = {
735
        { { 45, 90 }, { 165, 396 }, { 104, 214 }, { 185, 444 }, 0, 0, 0, NULL },
736
        { { 220, 440 }, { 165, 396 }, { 276, 552 }, { 185, 444 }, 1, 0, 0, NULL },
737
        { { 49, 98 }, { 35, 84 }, { 284, 568 }, { 43, 103 }, 2, 1, 0, RadioClick },
738
        { { 49, 98 }, { 44, 106 }, { 284, 568 }, { 52, 125 }, 3, 1, 0, RadioClick },
739
        { { 49, 98 }, { 53, 127 }, { 284, 568 }, { 61, 146 }, 4, 1, 0, RadioClick },
740
        { { 49, 98 }, { 66, 158 }, { 284, 568 }, { 74, 178 }, 5, 1, 0, RadioClick },
741
        { { 49, 98 }, { 75, 180 }, { 284, 568 }, { 83, 199 }, 6, 1, 0, RadioClick },
742
        { { 49, 98 }, { 88, 192 }, { 284, 568 }, { 96, 230 }, 7, 1, 0, RadioClick },
743
        { { 49, 98 }, { 97, 233 }, { 284, 568 }, { 105, 252 }, 8, 1, 0, RadioClick },
744
        { { 49, 98 }, { 110, 264 }, { 284, 568 }, { 118, 283 }, 9, 1, 0, RadioClick },
745
        { { 49, 98 }, { 119, 286 }, { 284, 568 }, { 127, 305 }, 10, 1, 0, RadioClick },
746
        { { 49, 98 }, { 128, 307 }, { 284, 322 }, { 136, 326 }, 11, 1, 0, RadioClick },
747
        { { 49, 98 }, { 137, 329 }, { 284, 322 }, { 145, 348 }, 12, 1, 0, RadioClick },
748
        { { 49, 98 }, { 149, 358 }, { 284, 322 }, { 157, 377 }, 13, 1, 0, RadioClick },
749
    };
750
    static tInterface_spec interface_spec = {
751
        0,
752
        160,
753
        0,
754
        0,
755
        0,
756
        0,
757
        1,
758
        { -1, 0 },
759
        { -1, 0 },
760
        { 0, 2 },
761
        { 1, 2 },
762
        { NULL, GraphOptLeft },
763
        { -1, 0 },
764
        { 1, 0 },
765
        { 0, 2 },
766
        { 1, 13 },
767
        { NULL, GraphOptRight },
768
        { -1, -1 },
769
        { 0, -1 },
770
        { 0, 1 },
771
        { 0, 13 },
772
        { GraphOptUp, GraphOptUp },
773
        { -1, -1 },
774
        { 1, 1 },
775
        { 0, 2 },
776
        { 0, 14 },
777
        { GraphOptDown, GraphOptDown },
778
        { 1, 1 },
779
        { NULL, GraphOptGoAhead },
780
        { 1, 1 },
781
        { NULL, NULL },
782
        NULL,
783
        DrawGraphBox,
784
        0,
785
        NULL,
786
        DrawInitialRadios,
787
        NULL,
788
        0,
789
        { 0, 0 },
790
        NULL,
791
        1,
792
        1,
793
        COUNT_OF(flicker_on),
794
        flicker_on,
795
        flicker_off,
796
        push,
797
        COUNT_OF(mouse_areas),
798
        mouse_areas,
799
        0,
800
        NULL,
801
    };
802
    LOG_TRACE("()");
803
 
804
    gThe_interface_spec__options = &interface_spec;
805
    gCurrent_key = -1;
11 pmbaty 806
    LoadFont(kFont_GRYLIT);
1 pmbaty 807
    GetGraphicsOptions();
808
    if (DoInterfaceScreen(&interface_spec, 0, 0) == 0) {
809
        SetGraphicsOptions();
810
    }
811
    if (gProgram_state.racing) {
812
        FadePaletteDown();
813
    } else {
814
        RunFlic(161);
815
    }
11 pmbaty 816
    DisposeFont(kFont_GRYLIT); // Pierre-Marie Baty -- replaced font number with symbol
1 pmbaty 817
}
818
 
819
// IDA: void __cdecl CalibrateJoysticks()
820
void CalibrateJoysticks(void) {
821
    //tJoy_calib_stage stage; // Pierre-Marie Baty -- unused variable
822
    //int escaped; // Pierre-Marie Baty -- unused variable
823
    //int joy_value_x; // Pierre-Marie Baty -- unused variable
824
    //int joy_value_y; // Pierre-Marie Baty -- unused variable
825
    //int key; // Pierre-Marie Baty -- unused variable
826
    //int top_left[2]; // Pierre-Marie Baty -- unused variable
827
    //int bot_right[2]; // Pierre-Marie Baty -- unused variable
828
    //int centre[2]; // Pierre-Marie Baty -- unused variable
829
    //int range[2]; // Pierre-Marie Baty -- unused variable
830
    //int min[2]; // Pierre-Marie Baty -- unused variable
831
    //int i; // Pierre-Marie Baty -- unused variable
832
    //int saved_1x; // Pierre-Marie Baty -- unused variable
833
    //int saved_1y; // Pierre-Marie Baty -- unused variable
834
    //int saved_2x; // Pierre-Marie Baty -- unused variable
835
    //int saved_2y; // Pierre-Marie Baty -- unused variable
836
    //int max; // Pierre-Marie Baty -- unused variable
837
    //char s[256]; // Pierre-Marie Baty -- unused variable
838
    LOG_TRACE("()");
839
 
840
#ifdef __DOS__
841
    NOT_IMPLEMENTED();
842
#else
20 pmbaty 843
    NetFullScreenMessage(229, 0);
1 pmbaty 844
#endif
845
}
846
 
847
// IDA: void __usercall StripControls(unsigned char *pStr@<EAX>)
848
void StripControls(unsigned char* pStr) {
849
    int i;
850
    int len;
851
    LOG_TRACE("(%p)", pStr);
852
 
853
    len = strlen((char*)pStr);
854
    for (i = 0; i < len; i++) {
855
        if (pStr[i] < ' ') {
856
            memmove(&pStr[i], &pStr[i + 1], (len - i) * sizeof(char));
857
            len--;
11 pmbaty 858
#ifdef DETHRACE_FIX_BUGS
859
            // correctly handle stripping multiple control characters
860
            i--;
861
#endif
1 pmbaty 862
        }
863
    }
864
}
865
 
866
// IDA: void __cdecl LoadKeyNames()
867
void LoadKeyNames(void) {
868
    int i;
869
    FILE* f;
870
    tPath_name the_path;
871
    unsigned char s[256];
872
    LOG_TRACE("()");
873
 
874
    PathCat(the_path, gApplication_path, "KEYNAMES.TXT");
875
    f = DRfopen(the_path, "rt");
876
    if (f == NULL) {
877
        FatalError(kFatalError_OpenKeyNamesFile);
878
    }
879
    for (i = 0; i < COUNT_OF(gKey_names); i++) {
880
        fgets((char*)s, sizeof(s), f);
881
        StripControls(s);
882
        gKey_names[i] = BrMemAllocate(strlen((char*)s) + 1, kMem_key_names);
883
        strcpy(gKey_names[i], (char*)s);
884
    }
885
    fclose(f);
886
}
887
 
888
// IDA: void __cdecl DisposeKeyNames()
889
void DisposeKeyNames(void) {
890
    int i;
891
    LOG_TRACE("()");
892
 
893
    for (i = 0; i < COUNT_OF(gKey_names); i++) {
894
        BrMemFree(gKey_names[i]);
895
    }
896
}
897
 
898
// IDA: void __cdecl SaveOrigKeyMapping()
899
void SaveOrigKeyMapping(void) {
900
    LOG_TRACE("()");
901
 
902
    memcpy(gOrig_key_mapping, gKey_mapping, sizeof(gKey_mapping));
903
}
904
 
905
// IDA: void __usercall GetKeyCoords(int pIndex@<EAX>, int *pY@<EDX>, int *pName_x@<EBX>, int *pKey_x@<ECX>, int *pEnd_box)
906
void GetKeyCoords(int pIndex, int* pY, int* pName_x, int* pKey_x, int* pEnd_box) {
907
    int col;
908
    LOG_TRACE("(%d, %p, %p, %p, %p)", pIndex, pY, pName_x, pKey_x, pEnd_box);
909
 
910
    if (pIndex >= 0) {
911
        col = gKey_count + 1;
912
        *pY = (pIndex % ((gKey_count + 1) / 2)) * gCurrent_graf_data->key_assign_y_pitch + gCurrent_graf_data->key_assign_y;
913
        if (pIndex < col / 2) {
914
            *pName_x = gCurrent_graf_data->key_assign_col_1;
915
            *pKey_x = gCurrent_graf_data->key_assign_col_1_a;
916
            *pEnd_box = gCurrent_graf_data->key_assign_col_2 - 7;
917
        } else {
918
            *pName_x = gCurrent_graf_data->key_assign_col_2;
919
            *pKey_x = gCurrent_graf_data->key_assign_col_2_a;
920
            *pEnd_box = gCurrent_graf_data->key_assign_col_2 + gCurrent_graf_data->key_assign_col_2 - gCurrent_graf_data->key_assign_col_1 - 7;
921
        }
922
    } else {
923
        *pName_x = gCurrent_graf_data->key_assign_col_1;
924
        *pKey_x = 0;
925
        *pEnd_box = gCurrent_graf_data->key_assign_col_2 + gCurrent_graf_data->key_assign_col_2 - gCurrent_graf_data->key_assign_col_1 - 7;
926
        *pY = gCurrent_graf_data->key_assign_key_map_y;
927
    }
928
}
929
 
930
// IDA: void __cdecl SetKeysToDefault()
931
void SetKeysToDefault(void) {
932
    FILE* f;
933
    tPath_name the_path;
934
    int i;
935
    LOG_TRACE("()");
936
 
937
    PathCat(the_path, gApplication_path, "DKEYMAPX.TXT");
938
    the_path[strlen(the_path) - 5] = '0' + gKey_map_index;
939
    f = DRfopen(the_path, "rt");
940
    if (f == NULL) {
941
        FatalError(kFatalError_OpenKeyMapFile);
942
    }
943
    for (i = 0; i < COUNT_OF(gKey_mapping); i++) {
944
        fscanf(f, "%d", &gKey_mapping[i]);
945
    }
946
    fclose(f);
947
}
948
 
949
// IDA: void __cdecl SaveKeyMapping()
950
void SaveKeyMapping(void) {
951
    FILE* f;
952
    tPath_name the_path;
953
    int i;
954
    LOG_TRACE("()");
955
 
956
    PathCat(the_path, gApplication_path, "KEYMAP_X.TXT");
957
    the_path[strlen(the_path) - 5] = '0' + gKey_map_index;
958
    PDFileUnlock(the_path);
959
    f = DRfopen(the_path, "wb");
960
    if (f == NULL) {
961
        FatalError(kFatalError_OpenKeyMapFile);
962
    }
963
    for (i = 0; i < COUNT_OF(gKey_mapping); i++) {
964
        fprintf(f, "%d", gKey_mapping[i]);
965
        fputc('\r', f);
966
        fputc('\n', f);
967
    }
968
    fclose(f);
969
}
970
 
971
// IDA: void __usercall ChangeKeyMapIndex(int pNew_one@<EAX>)
972
void ChangeKeyMapIndex(int pNew_one) {
973
    LOG_TRACE("(%d)", pNew_one);
974
 
975
    SaveKeyMapping();
976
    gKey_map_index = pNew_one;
977
    LoadKeyMapping();
978
    SaveOrigKeyMapping();
979
}
980
 
981
// IDA: void __usercall DrawKeyAssignments(int pCurrent_choice@<EAX>, int pCurrent_mode@<EDX>)
982
void DrawKeyAssignments(int pCurrent_choice, int pCurrent_mode) {
983
    int i;
984
    int y;
985
    int x_coord;
986
    int y_coord;
987
    int name_x;
988
    int key_x;
989
    int new_key;
990
    int end_box;
991
    tDR_font* font_n;
992
    tDR_font* font_k;
993
    static int on_radios_last_time;
994
    LOG_TRACE("(%d, %d)", pCurrent_choice, pCurrent_mode);
995
 
996
#if defined(DETHRACE_FIX_BUGS)
11 pmbaty 997
    font_k = &gFonts[kFont_GRYDK];
1 pmbaty 998
#endif
999
    if (gMouse_in_use && pCurrent_choice == 4) {
1000
        GetMousePosition(&x_coord, &y_coord);
1001
        if (y_coord >= gCurrent_graf_data->key_assign_key_map_y
11 pmbaty 1002
            && y_coord <= gCurrent_graf_data->key_assign_key_map_y + gFonts[kFont_GRYLIT].height + 5
1 pmbaty 1003
            && x_coord > gCurrent_graf_data->key_assign_col_1
1004
            && x_coord < gCurrent_graf_data->key_assign_col_2 + gCurrent_graf_data->key_assign_col_2 - gCurrent_graf_data->key_assign_col_1 - 7) {
1005
            gCurrent_key = -1;
1006
        } else {
1007
            if (x_coord > gCurrent_graf_data->key_assign_col_2) {
1008
                new_key = (gKey_count + 1) / 2;
1009
            } else {
1010
                new_key = 0;
1011
            }
1012
            if (y_coord >= gCurrent_graf_data->key_assign_y - 2
1013
                && y_coord < gCurrent_graf_data->key_assign_y + gCurrent_graf_data->key_assign_y_pitch * (gKey_count + 1) / 2) {
1014
                new_key += (y_coord - gCurrent_graf_data->key_assign_y - 2) / gCurrent_graf_data->key_assign_y_pitch;
1015
                if (new_key >= 0 && new_key < gKey_count) {
1016
                    gCurrent_key = new_key;
1017
                }
1018
            }
1019
        }
1020
    }
1021
    BrPixelmapRectangleFill(gBack_screen,
1022
        gCurrent_graf_data->key_assign_col_1 - 3,
1023
        gCurrent_graf_data->key_assign_y - 3,
1024
        2 * (gCurrent_graf_data->key_assign_col_2 - gCurrent_graf_data->key_assign_col_1) - 3,
1025
        gCurrent_graf_data->key_assign_y_pitch * gKey_count / 2 + 4,
1026
        0);
1027
    GetKeyCoords(-1, &y, &name_x, &key_x, &end_box);
11 pmbaty 1028
    DrawRRectangle(gBack_screen, name_x - 3, y - 3, end_box, gFonts[kFont_GRYLIT].height + y + 2 - (TranslationMode() ? 2 : 0), 0);
1 pmbaty 1029
    for (i = 0; i < gKey_count; i++) {
1030
        GetKeyCoords(i, &y, &name_x, &key_x, &end_box);
1031
        if (i == gCurrent_key && pCurrent_mode != 0) {
11 pmbaty 1032
            font_n = &gFonts[kFont_GRNLIT];
1033
            font_k = &gFonts[kFont_GRYLIT];
1 pmbaty 1034
        } else {
11 pmbaty 1035
            font_n = &gFonts[kFont_GRNDK];
1036
            font_k = &gFonts[kFont_GRYDK];
1 pmbaty 1037
        }
1038
        TransDRPixelmapText(gBack_screen, name_x, y, font_n, GetMiscString(kMiscString_InputOptions_START + i), 640);
1039
        TransDRPixelmapText(gBack_screen, key_x, y, font_k, gKey_names[gKey_mapping[gKey_defns[i]] + 2], 640);
1040
        if (i == gCurrent_key && pCurrent_mode != 0) {
1041
            DrawRRectangle(gBack_screen, name_x - 3, y - 3, end_box, font_k->height + y + 2 - (TranslationMode() ? 2 : 0), 45);
1042
        }
1043
    }
1044
    if (gCurrent_key < 0 && pCurrent_mode != 0) {
1045
        GetKeyCoords(-1, &y, &name_x, &key_x, &end_box);
1046
        DrawRRectangle(gBack_screen, name_x - 3, y - 3, end_box, font_k->height + y + 2 - (TranslationMode() ? 2 : 0), 45);
1047
    }
1048
    if (on_radios_last_time && (pCurrent_mode == 0 || gCurrent_key >= 0)) {
1049
        DontLetFlicFuckWithPalettes();
1050
        TurnFlicTransparencyOn();
1051
        RunFlicAt(193, gCurrent_graf_data->key_assign_flic_x, gCurrent_graf_data->key_assign_flic_y);
1052
        TurnFlicTransparencyOff();
1053
        DontLetFlicFuckWithPalettes();
1054
    } else if (!on_radios_last_time && pCurrent_mode != 0 && gCurrent_key < 0) {
1055
        DontLetFlicFuckWithPalettes();
1056
        TurnFlicTransparencyOn();
1057
        RunFlicAt(194, gCurrent_graf_data->key_assign_flic_x, gCurrent_graf_data->key_assign_flic_y);
1058
        TurnFlicTransparencyOff();
1059
        DontLetFlicFuckWithPalettes();
1060
    }
1061
    on_radios_last_time = pCurrent_mode != 0 && gCurrent_key < 0;
1062
}
1063
 
1064
// IDA: int __usercall KeyAssignLeft@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
1065
int KeyAssignLeft(int* pCurrent_choice, int* pCurrent_mode) {
1066
    int new_index;
1067
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
1068
 
1069
    if (gCurrent_key < 0) {
1070
        if (gKey_map_index == 0) {
1071
            new_index = 3;
1072
        } else {
1073
            new_index = gKey_map_index - 1;
1074
        }
1075
        ChangeKeyMapIndex(new_index);
1076
        RadioChanged(12, new_index);
1077
        DRS3StartSound(gEffects_outlet, 3000);
1078
    } else {
1079
        if (gCurrent_key >= (gKey_count + 1) / 2) {
1080
            gCurrent_key -= (gKey_count + 1) / 2;
1081
        } else {
1082
            gCurrent_key += (gKey_count + 1) / 2;
1083
            if (gCurrent_key >= gKey_count) {
1084
                gCurrent_key -= (gKey_count + 1) / 2;
1085
            }
1086
        }
1087
        DRS3StartSound(gEffects_outlet, 3000);
1088
    }
1089
    return 1;
1090
}
1091
 
1092
// IDA: int __usercall KeyAssignRight@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
1093
int KeyAssignRight(int* pCurrent_choice, int* pCurrent_mode) {
1094
    int new_index;
1095
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
1096
 
1097
    if (gCurrent_key < 0) {
1098
        if (gKey_map_index < 3) {
1099
            new_index = gKey_map_index + 1;
1100
        } else {
1101
            new_index = 0;
1102
        }
1103
        ChangeKeyMapIndex(new_index);
1104
        RadioChanged(12, new_index);
1105
        DRS3StartSound(gEffects_outlet, 3000);
1106
    } else {
1107
        if (gCurrent_key >= (gKey_count + 1) / 2) {
1108
            gCurrent_key -= (gKey_count + 1) / 2;
1109
        } else {
1110
            gCurrent_key += (gKey_count + 1) / 2;
1111
            if (gCurrent_key >= gKey_count) {
1112
                gCurrent_key -= (gKey_count + 1) / 2;
1113
            }
1114
        }
1115
        DRS3StartSound(gEffects_outlet, 3000);
1116
    }
1117
    return 1;
1118
}
1119
 
1120
// IDA: int __usercall KeyAssignUp@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
1121
int KeyAssignUp(int* pCurrent_choice, int* pCurrent_mode) {
1122
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
1123
 
1124
    if (*pCurrent_mode == 0) {
1125
        gCurrent_key = -1;
1126
        *pCurrent_choice = 4;
1127
        *pCurrent_mode = 1;
1128
        DRS3StartSound(gEffects_outlet, 3000);
1129
    } else if (gCurrent_key < 0) {
1130
        gCurrent_key = (gKey_count + 1) / 2 - 1;
1131
        *pCurrent_choice = 4;
1132
        *pCurrent_mode = 1;
1133
        DRS3StartSound(gEffects_outlet, 3000);
1134
    } else if (gCurrent_key > (gKey_count + 1) / 2) {
1135
        gCurrent_key -= 1;
1136
    } else if (gCurrent_key == (gKey_count + 1) / 2) {
1137
        *pCurrent_choice = 0;
1138
        *pCurrent_mode = 0;
1139
    } else if (gCurrent_key == 0) {
1140
        *pCurrent_choice = 0;
1141
        *pCurrent_mode = 0;
1142
    } else {
1143
        gCurrent_key -= 1;
1144
    }
1145
    DRS3StartSound(gEffects_outlet, 3000);
1146
    return 1;
1147
}
1148
 
1149
// IDA: int __usercall KeyAssignDown@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
1150
int KeyAssignDown(int* pCurrent_choice, int* pCurrent_mode) {
1151
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
1152
 
1153
    if (*pCurrent_mode == 0) {
1154
        if (*pCurrent_choice >= 2) {
1155
            gCurrent_key = (gKey_count + 1) / 2;
1156
        } else {
1157
            gCurrent_key = 0;
1158
        }
1159
        *pCurrent_choice = 4;
1160
        *pCurrent_mode = 1;
1161
    } else if (gCurrent_key < 0) {
1162
        *pCurrent_choice = 0;
1163
        *pCurrent_mode = 0;
1164
    } else if (gCurrent_key < (gKey_count + 1) / 2) {
1165
        if (gCurrent_key < ((gKey_count + 1) / 2 - 1)) {
1166
            gCurrent_key += 1;
1167
        } else {
1168
            gCurrent_key = -1;
1169
        }
1170
    } else if (gCurrent_key < gKey_count - 1) {
1171
        gCurrent_key += 1;
1172
    } else {
1173
        gCurrent_key = -1;
1174
    }
1175
    DRS3StartSound(gEffects_outlet, 3000);
1176
    return 1;
1177
}
1178
 
1179
// IDA: int __usercall KeyAssignGoAhead@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>)
1180
int KeyAssignGoAhead(int* pCurrent_choice, int* pCurrent_mode) {
1181
    int key;
1182
    int i;
1183
    int j;
1184
    int y;
1185
    int new_index;
1186
    int disallowed;
1187
    int name_x;
1188
    int key_x;
1189
    int end_box;
1190
    tDR_font* font;
1191
    LOG_TRACE("(%p, %p)", pCurrent_choice, pCurrent_mode);
1192
 
1193
    RemoveTransientBitmaps(1);
1194
    if (*pCurrent_mode == 0) {
1195
        key = -1;
1196
        if (*pCurrent_choice == 0) {
1197
            for (i = 0; i < COUNT_OF(gKey_defns); i++) {
1198
                if (gKey_mapping[gKey_defns[i]] == -2) {
1199
                    key = i;
1200
                    break;
1201
                }
1202
            }
1203
        }
1204
        if (key < 0) {
1205
            DontLetFlicFuckWithPalettes();
1206
            TurnFlicTransparencyOn();
1207
            RunFlicAt(
1208
                gThe_interface_spec__options->pushed_flics[*pCurrent_choice].flic_index,
1209
                gThe_interface_spec__options->pushed_flics[*pCurrent_choice].x[gGraf_data_index],
1210
                gThe_interface_spec__options->pushed_flics[*pCurrent_choice].y[gGraf_data_index]);
1211
            TurnFlicTransparencyOff();
1212
            LetFlicFuckWithPalettes();
1213
        }
1214
        switch (*pCurrent_choice) {
1215
        case 0:
1216
            if (key < 0) {
1217
                disallowed = 1;
1218
            } else {
1219
                *pCurrent_choice = key + 4;
1220
                *pCurrent_mode = 1;
1221
                gCurrent_key = key;
1222
                gMouse_in_use = 0;
1223
                DRS3StartSound(gEffects_outlet, 3100);
1224
                disallowed = 0;
1225
            }
1226
            break;
1227
        case 1:
1228
            *pCurrent_choice = -1;
1229
            disallowed = 1;
1230
            break;
1231
        case 2:
1232
            SetKeysToDefault();
1233
            disallowed = 0;
1234
            break;
1235
        case 3:
1236
            disallowed = 1;
1237
            break;
1238
        default:
1239
            disallowed = 0;
1240
            break;
1241
        }
1242
        return disallowed;
1243
    } else {
1244
        if (gCurrent_key < 0) {
1245
            if (gKey_map_index < 3) {
1246
                new_index = gKey_map_index + 1;
1247
            } else {
1248
                new_index = 0;
1249
            }
1250
            ChangeKeyMapIndex(new_index);
1251
            RadioChanged(12, new_index);
1252
        } else {
1253
            PDScreenBufferSwap(0);
1254
            CyclePollKeys();
1255
            PollKeys();
1256
            WaitForNoKeys();
1257
            GetKeyCoords(gCurrent_key, &y, &name_x, &key_x, &end_box);
11 pmbaty 1258
            font = &gFonts[kFont_GRYLIT];
1 pmbaty 1259
            gPending_entry = -1;
1260
            while (1) {
1261
                key = PDAnyKeyDown();
1262
                if (key != -1 && key != 63) {
1263
                    for (i = 27; i < 65; i++) {
1264
                        if (gKey_mapping[i] == key && gKey_defns[gCurrent_key] != i) {
1265
                            for (j = 0; j < COUNT_OF(gKey_defns); j++) {
1266
                                if (gKey_defns[j] == i) {
1267
                                    gKey_mapping[i] = -2;
1268
                                    gPending_entry = j;
1269
                                    break;
1270
                                }
1271
                            }
1272
                            if (gPending_entry < 0) {
1273
                                DRS3StartSound(gEffects_outlet, 3100);
1274
                                key = -1;
1275
                                break;
1276
                            }
1277
                        }
1278
                    }
1279
                }
1280
                CyclePollKeys();
1281
                PollKeys();
1282
                if ((PDGetTotalTime() / 100) & 1) {
1283
                    TransDRPixelmapText(gBack_screen, key_x, y, font, gKey_names[gKey_mapping[gKey_defns[gCurrent_key]] + 2], 640);
1284
                } else {
1285
                    BrPixelmapRectangleFill(gBack_screen, key_x, y, end_box - key_x, font->height, 0);
1286
                }
1287
                PDScreenBufferSwap(0);
1288
                if (key != -1 || EitherMouseButtonDown()) {
1289
                    break;
1290
                }
1291
            }
1292
            DRS3StartSound(gEffects_outlet, 3004);
1293
            WaitForNoKeys();
1294
            if (key != 63 && key != -1) {
1295
                gKey_mapping[gKey_defns[gCurrent_key]] = key;
1296
            }
1297
            if (gPending_entry >= 0) {
1298
                *pCurrent_choice = gPending_entry + 4;
1299
                gCurrent_key = gPending_entry;
1300
            }
1301
        }
1302
        return 0;
1303
    }
1304
}
1305
 
1306
// IDA: int __usercall MouseyClickBastard@<EAX>(int *pCurrent_choice@<EAX>, int *pCurrent_mode@<EDX>, int pX_offset@<EBX>, int pY_offset@<ECX>)
1307
int MouseyClickBastard(int* pCurrent_choice, int* pCurrent_mode, int pX_offset, int pY_offset) {
1308
    int i;
1309
    int x_coord;
1310
    int y_coord;
1311
    LOG_TRACE("(%p, %p, %d, %d)", pCurrent_choice, pCurrent_mode, pX_offset, pY_offset);
1312
 
1313
    if (gCurrent_key < 0) {
1314
        GetMousePosition(&x_coord, &y_coord);
1315
        for (i = gRadio_bastards__options[12].count - 1; i >= 0; i--) {
1316
            if (x_coord + 3 >= gRadio_bastards__options[12].left[i]) {
1317
                DRS3StartSound(gEffects_outlet, 3000);
1318
                ChangeKeyMapIndex(i);
1319
                RadioChanged(12, i);
1320
                break;
1321
            }
1322
        }
1323
        return 0;
1324
    } else {
1325
        KeyAssignGoAhead(pCurrent_choice, pCurrent_mode);
1326
    }
1327
    return 0;
1328
}
1329
 
1330
// IDA: void __cdecl DrawInitialKMRadios()
1331
void DrawInitialKMRadios(void) {
1332
    //int i; // Pierre-Marie Baty -- unused variable
1333
    LOG_TRACE("()");
1334
 
1335
    RemoveTransientBitmaps(1);
1336
    DontLetFlicFuckWithPalettes();
1337
    TurnFlicTransparencyOn();
1338
    PlayRadioOn2(12, gKey_map_index);
1339
    gRadio_bastards__options[12].current_value = gKey_map_index;
1340
    TurnFlicTransparencyOff();
1341
    DontLetFlicFuckWithPalettes();
1342
}
1343
 
1344
// IDA: void __cdecl DoControlOptions()
1345
void DoControlOptions(void) {
1346
    static tFlicette flicker_on[4] = {
1347
        { 177, { 51, 102 }, { 166, 398 } },
1348
        { 177, { 112, 224 }, { 166, 398 } },
1349
        { 177, { 173, 346 }, { 166, 398 } },
1350
        { 177, { 234, 468 }, { 166, 398 } },
1351
    };
1352
    static tFlicette flicker_off[4] = {
1353
        { 176, { 51, 102 }, { 166, 398 } },
1354
        { 176, { 112, 224 }, { 166, 398 } },
1355
        { 176, { 173, 346 }, { 166, 398 } },
1356
        { 176, { 234, 468 }, { 166, 398 } },
1357
    };
1358
    static tFlicette push[4] = {
1359
        { 172, { 51, 102 }, { 166, 398 } },
1360
        { 175, { 112, 224 }, { 166, 398 } },
1361
        { 174, { 173, 346 }, { 166, 398 } },
1362
        { 173, { 234, 468 }, { 166, 398 } },
1363
    };
1364
    static tMouse_area mouse_areas[5] = {
1365
        { { 51, 102 }, { 166, 398 }, { 102, 204 }, { 187, 449 }, 0, 0, 0, NULL },
1366
        { { 112, 224 }, { 166, 398 }, { 164, 328 }, { 187, 449 }, 1, 0, 0, NULL },
1367
        { { 173, 346 }, { 166, 398 }, { 225, 450 }, { 187, 449 }, 2, 0, 0, NULL },
1368
        { { 234, 468 }, { 166, 398 }, { 286, 572 }, { 187, 449 }, 3, 0, 0, NULL },
1369
        { { 45, 90 }, { 33, 79 }, { 285, 570 }, { 159, 382 }, 4, 1, 0, MouseyClickBastard },
1370
    };
1371
    static tInterface_spec interface_spec = {
1372
        0, 170, 179, 0, 0, 0, 1,
1373
        { -1, -1 }, { -1, 0 }, { 0, 4 }, { 3, 4 }, { NULL, KeyAssignLeft },
1374
        { -1, -1 }, { 1, 0 }, { 0, 4 }, { 3, 4 }, { NULL, KeyAssignRight },
1375
        { -1, -1 }, { 0, 0 }, { 0, 4 }, { 3, 4 }, { KeyAssignUp, KeyAssignUp },
1376
        { -1, -1 }, { 0, 0 }, { 0, 4 }, { 3, 4 }, { KeyAssignDown, KeyAssignDown },
1377
        { 1, 1 }, { KeyAssignGoAhead, KeyAssignGoAhead }, { 1, 1 },
1378
        { 0, 0 }, NULL, DrawKeyAssignments, 0, NULL, DrawInitialKMRadios, NULL, 0,
1379
        { 0, 0 }, NULL, 3, 1,
1380
        COUNT_OF(flicker_on), flicker_on, flicker_off, push,
1381
        COUNT_OF(mouse_areas), mouse_areas,
1382
        0, NULL
1383
    };
1384
    int result;
1385
    //int swap_font_1; // Pierre-Marie Baty -- unused variable
1386
    //int swap_font_2; // Pierre-Marie Baty -- unused variable
1387
    //int swap_font_3; // Pierre-Marie Baty -- unused variable
1388
    int second_time_around;
1389
    int orig_key_map_index;
1390
    LOG_TRACE("()");
1391
 
1392
    orig_key_map_index = gKey_map_index;
1393
    second_time_around = 0;
1394
    gThe_interface_spec__options = &interface_spec;
1395
    SaveOrigKeyMapping();
1396
    LoadKeyNames();
11 pmbaty 1397
    LoadFont(kFont_GRNDK);
1398
    LoadFont(kFont_GRYDK);
1399
    LoadFont(kFont_GRNLIT);
1400
    LoadFont(kFont_GRYLIT);
1 pmbaty 1401
    gPending_entry = -1;
1402
    gKey_count = 18;
1403
    gCurrent_key = 8;
1404
    while ((result = DoInterfaceScreen(&interface_spec, second_time_around, 0)) < 0) {
1405
        FadePaletteDown();
1406
        CalibrateJoysticks();
1407
        FadePaletteDown();
1408
        second_time_around = 1;
1409
    }
1410
    if (result == 0) {
1411
        SaveKeyMapping();
1412
    } else {
1413
        gKey_map_index = orig_key_map_index;
1414
        memcpy(gKey_mapping, gOrig_key_mapping, sizeof(gKey_mapping));
1415
    }
11 pmbaty 1416
    DisposeFont(kFont_GRNDK); // Pierre-Marie Baty -- replaced font number with symbol
1417
    DisposeFont(kFont_GRYDK); // Pierre-Marie Baty -- replaced font number with symbol
1418
    DisposeFont(kFont_GRNLIT); // Pierre-Marie Baty -- replaced font number with symbol
1419
    DisposeFont(kFont_GRYLIT); // Pierre-Marie Baty -- replaced font number with symbol
1 pmbaty 1420
    DisposeKeyNames();
1421
    if (gProgram_state.racing) {
1422
        FadePaletteDown();
1423
    } else {
1424
        RunFlic(171);
1425
    }
1426
}
1427
 
1428
// IDA: void __cdecl LoadSoundOptionsData()
1429
void LoadSoundOptionsData(void) {
1430
    LOG_TRACE("()");
1431
 
1432
    gDials_pix = LoadPixelmap("DIALSTCK.PIX");
1433
    if (gDials_pix == NULL) {
1434
        FatalError(kFatalError_LoadDialsPix);
1435
    }
1436
}
1437
 
1438
// IDA: void __cdecl FreeSoundOptionsData()
1439
void FreeSoundOptionsData(void) {
1440
    LOG_TRACE("()");
1441
 
1442
    BrPixelmapFree(gDials_pix);
1443
}
1444
 
1445
// IDA: void __cdecl DrawDisabledOptions()
1446
void DrawDisabledOptions(void) {
1447
    br_pixelmap* image;
1448
    LOG_TRACE("()");
1449
 
1450
    PrintMemoryDump(0, "INSIDE OPTIONS");
1451
 
11 pmbaty 1452
    if (!harness_game_config.sound_options) {
1453
        // Disable sound options menu
1454
        image = LoadPixelmap("NOSNDOPT.PIX");
1455
        DisableChoice(0);
1456
        if (image != NULL) {
1457
            DRPixelmapRectangleMaskedCopy(gBack_screen, gCurrent_graf_data->sound_opt_disable_x,
1458
                gCurrent_graf_data->sound_opt_disable_y, image, 0, 0, image->width, image->height);
1459
            BrPixelmapFree(image);
1460
        }
1 pmbaty 1461
    }
1462
 
1463
    // Disable graphics options menu when in-game
1464
    if (gProgram_state.track_spec.the_actor != NULL) {
1465
        image = LoadPixelmap("NODETOPT.PIX");
1466
        DisableChoice(1);
1467
        if (image != NULL) {
1468
            DRPixelmapRectangleMaskedCopy(gBack_screen, gCurrent_graf_data->graph_opt_disable_x,
1469
                gCurrent_graf_data->graph_opt_disable_y, image, 0, 0, image->width, image->height);
1470
            BrPixelmapFree(image);
1471
        }
1472
    }
1473
}
1474
 
1475
// IDA: void __cdecl DoOptions()
1476
void DoOptions(void) {
1477
    static tFlicette flicker_on[4] = {
1478
        { 43, { 57, 114 }, { 41, 98 } },
1479
        { 43, { 57, 114 }, { 78, 187 } },
1480
        { 43, { 57, 114 }, { 114, 274 } },
1481
        { 43, { 57, 114 }, { 154, 370 } }
1482
    };
1483
    static tFlicette flicker_off[4] = {
1484
        { 42, { 57, 114 }, { 41, 98 } },
1485
        { 42, { 57, 114 }, { 78, 187 } },
1486
        { 42, { 57, 114 }, { 114, 274 } },
1487
        { 42, { 57, 114 }, { 154, 370 } },
1488
    };
1489
    static tFlicette push[4] = {
1490
        { 144, { 57, 114 }, { 41, 98 } },
1491
        { 146, { 57, 114 }, { 78, 187 } },
1492
        { 145, { 57, 114 }, { 114, 274 } },
1493
        { 45, { 57, 114 }, { 154, 370 } },
1494
    };
1495
    static tMouse_area mouse_areas[4] = {
1496
        { { 57, 114 }, { 41, 98 }, { 123, 246 }, { 62, 149 }, 0, 0, 0, NULL },
1497
        { { 57, 114 }, { 78, 187 }, { 123, 246 }, { 99, 238 }, 1, 0, 0, NULL },
1498
        { { 57, 114 }, { 114, 274 }, { 123, 246 }, { 135, 324 }, 2, 0, 0, NULL },
1499
        { { 57, 114 }, { 154, 370 }, { 123, 246 }, { 175, 420 }, 3, 0, 0, NULL },
1500
    };
1501
    static tInterface_spec interface_spec = {
1502
        0,
1503
        140,
1504
        0,
1505
        141,
1506
        141,
1507
        141,
1508
        1,
1509
        { -1, 0 },
1510
        { 0, 0 },
1511
        { 0, 0 },
1512
        { 0, 0 },
1513
        { NULL, NULL },
1514
        { -1, 0 },
1515
        { 0, 0 },
1516
        { 0, 0 },
1517
        { 0, 0 },
1518
        { NULL, NULL },
1519
        { -1, 0 },
1520
        { -1, 0 },
1521
        { 0, 0 },
1522
        { 3, 0 },
1523
        { NULL, NULL },
1524
        { -1, 0 },
1525
        { 1, 0 },
1526
        { 0, 0 },
1527
        { 3, 0 },
1528
        { NULL, NULL },
1529
        { 1, 1 },
1530
        { NULL, NULL },
1531
        { 1, 1 },
1532
        { NULL, NULL },
1533
        NULL,
1534
        NULL,
1535
        0,
1536
        NULL,
1537
        DrawDisabledOptions,
1538
        NULL,
1539
        0,
1540
        { 0, 0 },
1541
        NULL,
1542
        3,
1543
        1,
1544
        COUNT_OF(flicker_on),
1545
        flicker_on,
1546
        flicker_off,
1547
        push,
1548
        COUNT_OF(mouse_areas),
1549
        mouse_areas,
1550
        0,
1551
        NULL,
1552
    };
1553
    int result;
1554
    LOG_TRACE("()");
1555
 
1556
    PrintMemoryDump(0, "BEFORE ENTERING OPTIONS");
1557
    PreloadBunchOfFlics(1);
1558
    result = DoInterfaceScreen(&interface_spec, 0, gProgram_state.track_spec.the_actor ? 2 : 1);
1559
    switch (result) {
1560
    case 0:
1561
        DoSoundOptions();
1562
        break;
1563
    case 1:
1564
        DoGraphicsOptions();
1565
        break;
1566
    case 2:
1567
        DoControlOptions();
1568
        break;
1569
    }
1570
    UnlockBunchOfFlics(1);
1571
    PrintMemoryDump(0, "AFTER ENTERING OPTIONS");
1572
}