Subversion Repositories Games.Carmageddon

Rev

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