Subversion Repositories Games.Carmageddon

Rev

Rev 11 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
#include "utility.h"
2
#include <stdlib.h>
3
 
18 pmbaty 4
#include "brender.h"
1 pmbaty 5
#include "constants.h"
6
#include "errors.h"
7
#include "globvars.h"
8
#include "globvrpb.h"
9
#include "graphics.h"
10
#include "harness/config.h"
11
#include "harness/trace.h"
12
#include "input.h"
13
#include "loading.h"
14
#include "loadsave.h"
15
#include "mainmenu.h"
16
#include "network.h"
17
#include "pd/sys.h"
18
#include "sound.h"
19
#include "world.h"
20
 
21
#include <ctype.h>
22
#include <stdio.h>
23
#include <string.h>
24
 
25
// Added >>
26
#define MIN_SERVICE_INTERVAL 200
27
// <<
28
 
29
int gIn_check_quit = 0;
30
tU32 gLost_time = 0;
31
//#if BR_ENDIAN_BIG
32
//tU32 gLong_key[4] = { 0x6c1b995f, 0xb9cd5f13, 0xcb04200e, 0x5e1ca10e };
33
char gLong_key[16]       = { 0x6c, 0x1b, 0x99, 0x5f, 0xb9, 0xcd, 0x5f, 0x13, 0xcb, 0x04, 0x20, 0x0e, 0x5e, 0x1c, 0xa1, 0x0e }; // Pierre-Marie Baty -- have an endianness-independent pattern
34
//tU32 gOther_long_key[4] = { 0x67a8d626, 0xb6dd451b, 0x327e2213, 0x15c29437 };
35
char gOther_long_key[16] = { 0x67, 0xa8, 0xd6, 0x26, 0xb6, 0xdd, 0x45, 0x1b, 0x32, 0x7e, 0x22, 0x13, 0x15, 0xc2, 0x94, 0x37 }; // Pierre-Marie Baty -- have an endianness-independent pattern
36
//#else
37
//tU32 gLong_key[4] = { 0x5f991b6c, 0x135fcdb9, 0x0e2004cb, 0x0ea11c5e };
38
//tU32 gOther_long_key[4] = { 0x26d6a867, 0x1b45ddb6, 0x13227e32, 0x3794c215 };
39
//#endif
40
int gEncryption_method = 0;
41
char* gMisc_strings[250];
42
br_pixelmap* g16bit_palette;
43
br_pixelmap* gSource_for_16bit_palette;
44
 
45
// IDA: int __cdecl CheckQuit()
46
int CheckQuit(void) {
47
    LOG_TRACE8("()");
48
 
49
    if (!gIn_check_quit && KeyIsDown(KEYMAP_CTRL_QUIT) && KeyIsDown(KEYMAP_CONTROL_ANY)) {
50
        gIn_check_quit = 1;
51
        while (AnyKeyDown()) {
52
            ;
53
        }
54
 
55
        if (DoVerifyQuit(1)) {
56
            DoSaveGame(1);
57
        }
58
        gIn_check_quit = 0;
59
    }
60
    return 0;
61
}
62
 
63
// IDA: double __cdecl sqr(double pN)
64
double sqr(double pN) {
65
 
66
    return pN * pN;
67
}
68
 
69
// Added to handle demo-specific text file decryption behavior
70
void EncodeLine_DEMO(char* pS) {
71
    int len;
72
    int seed;
73
    int i;
74
    char* key;
75
    unsigned char c;
76
    //FILE* test; // Pierre-Marie Baty -- unused variable
77
    //tPath_name the_path; // Pierre-Marie Baty -- unused variable
78
//#if BR_ENDIAN_BIG
79
//    const tU32 gLong_key_DEMO[] = { 0x58503A76, 0xCBB68565, 0x15CD5B07, 0xB168DE3A };
80
    const char gLong_key_DEMO[16] = { 0x58, 0x50, 0x3A, 0x76, 0xCB, 0xB6, 0x85, 0x65, 0x15, 0xCD, 0x5B, 0x07, 0xB1, 0x68, 0xDE, 0x3A }; // Pierre-Marie Baty -- have an endianness-independent pattern
81
//#else
82
//    const tU32 gLong_key_DEMO[] = { 0x763A5058, 0x6585B6CB, 0x75BCD15, 0x3ADE68B1 };
83
//#endif
84
 
85
    len = strlen(pS);
86
    key = (char*)gLong_key_DEMO;
87
 
88
    while (len > 0 && (pS[len - 1] == '\r' || pS[len - 1] == '\n')) {
89
        len--;
90
        pS[len] = 0;
91
    }
92
    seed = len % 16;
93
    for (i = 0; i < len; i++) {
94
        c = pS[i];
95
        if (c == '\t') {
96
            c = 0x9F;
97
        }
98
        c = ((key[seed] ^ (c - 32)) & 0x7F) + 32;
99
        seed = (seed + 7) % 16;
100
        if (c == 0x9F) {
101
            c = '\t';
102
        }
103
        pS[i] = c;
104
    }
105
}
106
 
107
// IDA: void __usercall EncodeLine(char *pS@<EAX>)
108
void EncodeLine(char* pS) {
109
    int len;
110
    int seed;
111
    int i;
112
    char* key;
113
    unsigned char c;
114
    //FILE* test; // Pierre-Marie Baty -- unused variable
115
    //tPath_name the_path; // Pierre-Marie Baty -- unused variable
116
    //char s[256]; // Pierre-Marie Baty -- unused variable
117
 
118
    // Demo has its own decryption key + behavior
119
    if (harness_game_info.mode == eGame_carmageddon_demo) {
120
        EncodeLine_DEMO(pS);
121
        return;
122
    }
123
 
124
    len = strlen(pS);
125
    key = (char*)gLong_key;
126
#if 0 // Pierre-Marie Baty -- consider the line individually
127
    if (gEncryption_method == 0) {
128
        PathCat(the_path, gApplication_path, "GENERAL.TXT");
129
 
130
        test = fopen(the_path, "rt");
131
        if (test != NULL) {
132
            fgets(s, 256, test);
133
            if (s[0] != '@') {
134
                gEncryption_method = 2;
135
            } else {
136
                gEncryption_method = 1;
137
                EncodeLine(&s[1]);
138
                s[7] = '\0';
139
                if (strcmp(&s[1], "0.01\t\t") != 0) {
140
                    gEncryption_method = 2;
141
                }
142
            }
143
            fclose(test);
144
        } else {
145
            gEncryption_method = 2;
146
        }
147
    }
148
#endif // 0
149
    while (len > 0 && (pS[len - 1] == '\r' || pS[len - 1] == '\n')) {
150
        len--;
151
        pS[len] = '\0';
152
    }
153
 
154
    seed = len % 16;
155
 
156
    for (i = 0; i < len; i++) {
157
        c = pS[i];
158
#if defined(DETHRACE_FIX_BUGS)
159
        // When loading game data, Carmageddon does not switch the XOR cypher when the comments start.
160
        if (i >= 2) {
161
            if (pS[i - 1] == '/' && pS[i - 2] == '/') {
162
                key = (char*)gOther_long_key;
163
            }
164
        }
165
#endif
166
#if 0 // Pierre-Marie Baty -- decode systematically
167
        if (gEncryption_method == 1) {
168
            if (c == '\t') {
169
                c = 0x9f;
170
            }
171
 
172
            c -= 0x20;
173
            c ^= key[seed];
174
            c &= 0x7f;
175
            c += 0x20;
176
 
177
            seed += 7;
178
            seed %= 16;
179
 
180
            if (c == 0x9f) {
181
                c = '\t';
182
            }
183
        } else {
184
#endif // 0
185
            if (c == '\t') {
186
                c = 0x80;
187
            }
188
 
189
            c -= 0x20;
190
            if ((c & 0x80) == 0) {
191
                c ^= key[seed] & 0x7f;
192
            }
193
            c += 0x20;
194
 
195
            seed += 7;
196
            seed %= 16;
197
 
198
            if (c == 0x80) {
199
                c = '\t';
200
            }
201
#if 0 // Pierre-Marie Baty -- decode systematically
202
        }
203
#endif // 0
204
        pS[i] = c;
205
    }
206
}
207
 
208
// IDA: int __usercall IRandomBetween@<EAX>(int pA@<EAX>, int pB@<EDX>)
209
int IRandomBetween(int pA, int pB) {
11 pmbaty 210
#if 1
1 pmbaty 211
    int num;
212
    //char s[32]; // Pierre-Marie Baty -- unused variable
213
 
214
    num = rand();
8 pmbaty 215
#if (INT_MAX > 0x7fffffff) && (RAND_MAX == 0x7fff) // Pierre-Marie Baty -- this hack just doesn't work when sizeof(int) == 32 (e.g. on Windows)
1 pmbaty 216
    //  If RAND_MAX == 0x7fff, then `num` can be seen as a fixed point number with 15 fractional and 17 integral bits
217
    return pA + ((num * (pB + 1 - pA)) >> 15);
218
#else
219
    //  If RAND_MAX != 0x7fff, then use floating numbers (alternative is using modulo)
220
    return pA + (int)((pB + 1 - pA) * (num / ((float)RAND_MAX + 1)));
221
#endif
11 pmbaty 222
#else // Pierre-Marie Baty -- madebr's code -- TODO: test
223
    long long int a = rand () * (pB + 1 - pA);
224
    a &= 0x7fffffffffffffff;
225
    return pA + (a >> 15);
226
#endif
1 pmbaty 227
}
228
 
229
// IDA: int __usercall PercentageChance@<EAX>(int pC@<EAX>)
230
int PercentageChance(int pC) {
231
    LOG_TRACE("(%d)", pC);
232
 
233
    return IRandomBetween(0, 99) < pC;
234
}
235
 
236
// IDA: int __usercall IRandomPosNeg@<EAX>(int pN@<EAX>)
237
int IRandomPosNeg(int pN) {
238
    LOG_TRACE("(%d)", pN);
239
 
240
    return IRandomBetween(-pN, pN);
241
}
242
 
243
// IDA: float __cdecl FRandomBetween(float pA, float pB)
244
float FRandomBetween(float pA, float pB) {
245
    LOG_TRACE8("(%f, %f)", pA, pB);
246
    return (double)rand() * (pB - pA) / (double)RAND_MAX + pA;
247
}
248
 
249
// IDA: float __cdecl FRandomPosNeg(float pN)
250
float FRandomPosNeg(float pN) {
251
    LOG_TRACE("(%f)", pN);
252
 
253
    return FRandomBetween(-pN, pN);
254
}
255
 
256
// IDA: br_scalar __cdecl SRandomBetween(br_scalar pA, br_scalar pB)
257
br_scalar SRandomBetween(br_scalar pA, br_scalar pB) {
258
    LOG_TRACE8("(%f, %f)", pA, pB);
259
 
260
    return FRandomBetween(pA, pB);
261
}
262
 
263
// IDA: br_scalar __cdecl SRandomPosNeg(br_scalar pN)
264
br_scalar SRandomPosNeg(br_scalar pN) {
265
    LOG_TRACE("(%f)", pN);
266
 
267
    return SRandomBetween(-pN, pN);
268
}
269
 
270
// IDA: char* __usercall GetALineWithNoPossibleService@<EAX>(FILE *pF@<EAX>, unsigned char *pS@<EDX>)
271
char* GetALineWithNoPossibleService(FILE* pF, unsigned char* pS) {
272
    // Jeff removed "signed' to avoid compiler warnings..
273
    /*signed*/ char* result;
274
    /*signed*/ char s[256];
275
    int ch;
276
    int len;
277
    int i;
278
 
279
    do {
280
        result = fgets(s, 256, pF);
281
        if (result == NULL) {
282
            s[0] = '\0';
283
            break;
284
        }
285
        if (s[0] == '@') {
286
            EncodeLine(&s[1]);
287
            len = strlen(s);
288
            memmove(s, &s[1], len);
289
        } else {
290
            while (s[0] == ' ' || s[0] == '\t') {
291
                len = strlen(s);
292
                memmove(s, &s[1], len);
293
            }
294
        }
295
 
296
        while (1) {
297
            ch = fgetc(pF);
298
            if (ch != '\r' && ch != '\n') {
299
                break;
300
            }
301
        }
302
        if (ch != -1) {
303
            ungetc(ch, pF);
304
        }
305
    } while (!isalnum(s[0])
306
        && s[0] != '-'
307
        && s[0] != '.'
308
        && s[0] != '!'
309
        && s[0] != '&'
310
        && s[0] != '('
311
        && s[0] != '\''
312
        && s[0] != '\"'
313
        && s[0] >= 0);
314
 
315
    if (result) {
316
        len = strlen(result);
317
        if (len != 0 && (result[len - 1] == '\r' || result[len - 1] == '\n')) {
318
            result[len - 1] = 0;
319
        }
320
        if (len != 1 && (result[len - 2] == '\r' || result[len - 2] == '\n')) {
321
            result[len - 2] = 0;
322
        }
323
    }
324
    strcpy((char*)pS, s);
325
    len = strlen(s);
326
    for (i = 0; i < len; i++) {
327
        if (pS[i] >= 0xe0) {
328
            pS[i] -= 32;
329
        }
330
    }
331
    // LOG_DEBUG("%s", result);
332
    return result;
333
}
334
 
335
// IDA: char* __usercall GetALineAndDontArgue@<EAX>(FILE *pF@<EAX>, char *pS@<EDX>)
336
char* GetALineAndDontArgue(FILE* pF, char* pS) {
337
    // LOG_TRACE10("(%p, \"%s\")", pF, pS);
338
 
339
    PossibleService();
340
    return GetALineWithNoPossibleService(pF, (unsigned char*)pS);
341
}
342
 
343
// IDA: void __usercall PathCat(char *pDestn_str@<EAX>, char *pStr_1@<EDX>, char *pStr_2@<EBX>)
344
void PathCat(char* pDestn_str, char* pStr_1, char* pStr_2) {
345
 
346
    if (pDestn_str != pStr_1) { // Added to avoid strcpy overlap checks
347
        strcpy(pDestn_str, pStr_1);
348
    }
349
    if (strlen(pStr_2) != 0) {
350
        strcat(pDestn_str, gDir_separator);
351
        strcat(pDestn_str, pStr_2);
352
    }
353
}
354
 
355
// IDA: int __cdecl Chance(float pChance_per_second, int pPeriod)
356
int Chance(float pChance_per_second, int pPeriod) {
357
    LOG_TRACE("(%f, %d)", pChance_per_second, pPeriod);
358
 
359
    return FRandomBetween(0.f, 1.f) < (pPeriod * pChance_per_second / 1000.f);
360
}
361
 
362
// IDA: float __cdecl tandeg(float pAngle)
363
float tandeg(float pAngle) {
364
    LOG_TRACE("(%f)", pAngle);
365
 
366
    pAngle = DEG_TO_RAD(pAngle);
367
    return sinf(pAngle) / cosf(pAngle);
368
}
369
 
370
// IDA: tU32 __usercall GetFileLength@<EAX>(FILE *pF@<EAX>)
371
tU32 GetFileLength(FILE* pF) {
372
    tU32 the_size;
373
 
374
    fseek(pF, 0, SEEK_END);
375
    the_size = ftell(pF);
376
    rewind(pF);
377
    return the_size;
378
}
379
 
380
// IDA: int __usercall BooleanTo1Or0@<EAX>(int pB@<EAX>)
381
int BooleanTo1Or0(int pB) {
382
    LOG_TRACE("(%d)", pB);
383
 
384
    return pB != 0;
385
}
386
 
387
// IDA: br_pixelmap* __usercall DRPixelmapAllocate@<EAX>(br_uint_8 pType@<EAX>, br_uint_16 pW@<EDX>, br_uint_16 pH@<EBX>, void *pPixels@<ECX>, int pFlags)
388
br_pixelmap* DRPixelmapAllocate(br_uint_8 pType, br_uint_16 pW, br_uint_16 pH, void* pPixels, int pFlags) {
389
    br_pixelmap* the_map;
390
 
391
    the_map = BrPixelmapAllocate(pType, pW, pH, pPixels, pFlags);
392
    if (the_map != NULL) {
393
        the_map->origin_y = 0;
394
        the_map->origin_x = 0;
395
    }
396
    return the_map;
397
}
398
 
399
// IDA: br_pixelmap* __usercall DRPixelmapAllocateSub@<EAX>(br_pixelmap *pPm@<EAX>, br_uint_16 pX@<EDX>, br_uint_16 pY@<EBX>, br_uint_16 pW@<ECX>, br_uint_16 pH)
400
br_pixelmap* DRPixelmapAllocateSub(br_pixelmap* pPm, br_uint_16 pX, br_uint_16 pY, br_uint_16 pW, br_uint_16 pH) {
401
    br_pixelmap* the_map;
402
    LOG_TRACE("(%p, %d, %d, %d, %d)", pPm, pX, pY, pW, pH);
403
 
404
    the_map = BrPixelmapAllocateSub(pPm, pX, pY, pW, pH);
405
    if (the_map != NULL) {
406
        the_map->origin_y = 0;
407
        the_map->origin_x = 0;
408
    }
409
    return the_map;
410
}
411
 
412
// IDA: br_pixelmap* __usercall DRPixelmapMatchSized@<EAX>(br_pixelmap *pSrc@<EAX>, tU8 pMatch_type@<EDX>, tS32 pWidth@<EBX>, tS32 pHeight@<ECX>)
413
br_pixelmap* DRPixelmapMatchSized(br_pixelmap* pSrc, tU8 pMatch_type, tS32 pWidth, tS32 pHeight) {
414
    //br_pixelmap* result; // Pierre-Marie Baty -- unused variable
415
    LOG_TRACE("(%p, %d, %d, %d)", pSrc, pMatch_type, pWidth, pHeight);
416
    NOT_IMPLEMENTED();
417
}
418
 
419
// IDA: void __usercall CopyDoubled8BitTo16BitRectangle(br_pixelmap *pDst@<EAX>, br_pixelmap *pSrc@<EDX>, int pSrc_width@<EBX>, int pSrc_height@<ECX>, int pDst_x, int pDst_y, br_pixelmap *pPalette)
420
void CopyDoubled8BitTo16BitRectangle(br_pixelmap* pDst, br_pixelmap* pSrc, int pSrc_width, int pSrc_height, int pDst_x, int pDst_y, br_pixelmap* pPalette) {
421
    //int x; // Pierre-Marie Baty -- unused variable
422
    //int y; // Pierre-Marie Baty -- unused variable
423
    //tU8* src_start; // Pierre-Marie Baty -- unused variable
424
    //tU16* dst_start0; // Pierre-Marie Baty -- unused variable
425
    //tU16* dst_start1; // Pierre-Marie Baty -- unused variable
426
    //tU16* palette_entry; // Pierre-Marie Baty -- unused variable
427
    LOG_TRACE("(%p, %p, %d, %d, %d, %d, %p)", pDst, pSrc, pSrc_width, pSrc_height, pDst_x, pDst_y, pPalette);
428
    NOT_IMPLEMENTED();
429
}
430
 
431
// IDA: br_pixelmap* __usercall Scale8BitPixelmap@<EAX>(br_pixelmap *pSrc@<EAX>, int pWidth@<EDX>, int pHeight@<EBX>)
432
br_pixelmap* Scale8BitPixelmap(br_pixelmap* pSrc, int pWidth, int pHeight) {
433
    //br_pixelmap* result; // Pierre-Marie Baty -- unused variable
434
    //int x; // Pierre-Marie Baty -- unused variable
435
    //int y; // Pierre-Marie Baty -- unused variable
436
    //tU8* src_pixels; // Pierre-Marie Baty -- unused variable
437
    //tU8* dst_pixels; // Pierre-Marie Baty -- unused variable
438
    LOG_TRACE("(%p, %d, %d)", pSrc, pWidth, pHeight);
439
    NOT_IMPLEMENTED();
440
}
441
 
442
// IDA: br_pixelmap* __usercall Tile8BitPixelmap@<EAX>(br_pixelmap *pSrc@<EAX>, int pN@<EDX>)
443
br_pixelmap* Tile8BitPixelmap(br_pixelmap* pSrc, int pN) {
444
    //br_pixelmap* result; // Pierre-Marie Baty -- unused variable
445
    //int new_width; // Pierre-Marie Baty -- unused variable
446
    //int new_height; // Pierre-Marie Baty -- unused variable
447
    //int x; // Pierre-Marie Baty -- unused variable
448
    //int y2; // Pierre-Marie Baty -- unused variable
449
    //int y; // Pierre-Marie Baty -- unused variable
450
    //tU8* src_pixels; // Pierre-Marie Baty -- unused variable
451
    //tU8* dst_pixels; // Pierre-Marie Baty -- unused variable
452
    LOG_TRACE("(%p, %d)", pSrc, pN);
453
    NOT_IMPLEMENTED();
454
}
455
 
456
// IDA: tException_list __usercall FindExceptionInList@<EAX>(char *pName@<EAX>, tException_list pList@<EDX>)
457
tException_list FindExceptionInList(char* pName, tException_list pList) {
458
    LOG_TRACE("(\"%s\", %d)", pName, pList);
459
    NOT_IMPLEMENTED();
460
}
461
 
462
// IDA: br_pixelmap* __usercall PurifiedPixelmap@<EAX>(br_pixelmap *pSrc@<EAX>)
463
br_pixelmap* PurifiedPixelmap(br_pixelmap* pSrc) {
464
    //br_pixelmap* intermediate; // Pierre-Marie Baty -- unused variable
465
    //br_pixelmap* result; // Pierre-Marie Baty -- unused variable
466
    //int new_width; // Pierre-Marie Baty -- unused variable
467
    //int new_height; // Pierre-Marie Baty -- unused variable
468
    //tException_list e; // Pierre-Marie Baty -- unused variable
469
    LOG_TRACE("(%p)", pSrc);
470
    NOT_IMPLEMENTED();
471
}
472
 
473
// IDA: br_pixelmap* __usercall DRPixelmapLoad@<EAX>(char *pFile_name@<EAX>)
474
br_pixelmap* DRPixelmapLoad(char* pFile_name) {
475
    br_pixelmap* the_map;
476
    //br_int_8 lobyte; // Pierre-Marie Baty -- unused variable
477
    LOG_TRACE("(\"%s\")", pFile_name);
478
 
479
    the_map = BrPixelmapLoad(pFile_name);
480
    if (the_map != NULL) {
481
        the_map->origin_x = 0;
482
        the_map->origin_y = 0;
483
        the_map->row_bytes = (the_map->row_bytes + sizeof(int32_t) - 1) & ~(sizeof(int32_t) - 1);
484
    }
485
    return the_map;
486
}
487
 
488
// IDA: br_uint_32 __usercall DRPixelmapLoadMany@<EAX>(char *pFile_name@<EAX>, br_pixelmap **pPixelmaps@<EDX>, br_uint_16 pNum@<EBX>)
489
br_uint_32 DRPixelmapLoadMany(char* pFile_name, br_pixelmap** pPixelmaps, br_uint_16 pNum) {
490
    br_pixelmap* the_map;
491
    int number_loaded;
492
    int i;
493
    //br_uint_8 lobyte; // Pierre-Marie Baty -- unused variable
494
    LOG_TRACE("(\"%s\", %p, %d)", pFile_name, pPixelmaps, pNum);
495
    number_loaded = BrPixelmapLoadMany(pFile_name, pPixelmaps, pNum);
496
    for (i = 0; i < number_loaded; i++) {
497
        the_map = pPixelmaps[i];
498
        the_map->row_bytes = (the_map->row_bytes + sizeof(int32_t) - 1) & ~(sizeof(int32_t) - 1);
499
        the_map->base_x = 0;
500
        the_map->base_y = 0;
501
    }
502
    return number_loaded;
503
}
504
 
505
// IDA: void __usercall WaitFor(tU32 pDelay@<EAX>)
506
void WaitFor(tU32 pDelay) {
507
    tU32 start_time;
508
    LOG_TRACE("(%d)", pDelay);
509
 
510
    start_time = PDGetTotalTime();
511
    while (start_time + pDelay < (tU32) PDGetTotalTime()) { // Pierre-Marie Baty -- added type cast
512
        SoundService();
513
    }
514
}
515
 
516
// IDA: br_uint_32 __usercall DRActorEnumRecurse@<EAX>(br_actor *pActor@<EAX>, br_actor_enum_cbfn *callback@<EDX>, void *arg@<EBX>)
18 pmbaty 517
br_uintptr_t DRActorEnumRecurse(br_actor* pActor, br_actor_enum_cbfn* callback, void* arg) {
518
    br_uintptr_t result;
1 pmbaty 519
 
520
    result = callback(pActor, arg);
521
    if (result != 0) {
522
        return result;
523
    }
524
    for (pActor = pActor->children; pActor != NULL; pActor = pActor->next) {
525
        result = DRActorEnumRecurse(pActor, callback, arg);
526
        if (result != 0) {
527
            return result;
528
        }
529
    }
530
    return 0;
531
}
532
 
533
// IDA: br_uint_32 __cdecl CompareActorID(br_actor *pActor, void *pArg)
18 pmbaty 534
br_uintptr_t CompareActorID(br_actor* pActor, void* pArg) {
1 pmbaty 535
    LOG_TRACE("(%p, %p)", pActor, pArg);
536
 
537
    if (pActor->identifier && !strcmp(pActor->identifier, (const char*)pArg)) {
538
        return (intptr_t)pActor;
539
    } else {
540
        return 0;
541
    }
542
}
543
 
544
// IDA: br_actor* __usercall DRActorFindRecurse@<EAX>(br_actor *pSearch_root@<EAX>, char *pName@<EDX>)
545
br_actor* DRActorFindRecurse(br_actor* pSearch_root, char* pName) {
546
    LOG_TRACE("(%p, \"%s\")", pSearch_root, pName);
547
 
548
    return (br_actor*)DRActorEnumRecurse(pSearch_root, CompareActorID, pName);
549
}
550
 
551
// IDA: br_uint_32 __usercall DRActorEnumRecurseWithMat@<EAX>(br_actor *pActor@<EAX>, br_material *pMat@<EDX>, br_uint_32 (*pCall_back)(br_actor*, br_material*, void*)@<EBX>, void *pArg@<ECX>)
552
br_uint_32 DRActorEnumRecurseWithMat(br_actor* pActor, br_material* pMat, recurse_with_mat_cbfn* pCall_back, void* pArg) {
553
    br_uint_32 result;
554
    LOG_TRACE("(%p, %p, %p, %p)", pActor, pMat, pCall_back, pArg);
555
 
556
    if (pActor->material != NULL) {
557
        pMat = pActor->material;
558
    }
559
    result = pCall_back(pActor, pMat, pArg);
560
    if (result != 0) {
561
        return result;
562
    }
563
    for (pActor = pActor->children; pActor != NULL; pActor = pActor->next) {
564
        result = DRActorEnumRecurseWithMat(pActor, pMat, pCall_back, pArg);
565
        if (result != 0) {
566
            return result;
567
        }
568
    }
569
    return 0;
570
}
571
 
572
// IDA: br_uint_32 __usercall DRActorEnumRecurseWithTrans@<EAX>(br_actor *pActor@<EAX>, br_matrix34 *pMatrix@<EDX>, br_uint_32 (*pCall_back)(br_actor*, br_matrix34*, void*)@<EBX>, void *pArg@<ECX>)
573
br_uint_32 DRActorEnumRecurseWithTrans(br_actor* pActor, br_matrix34* pMatrix, br_uint_32 (*pCall_back)(br_actor*, br_matrix34*, void*), void* pArg) {
574
    br_uint_32 result;
575
    br_matrix34 combined_transform;
576
    LOG_TRACE("(%p, %p, %p, %p)", pActor, pMatrix, pCall_back, pArg);
577
 
578
    if (pMatrix == NULL) {
579
        BrMatrix34Copy(&combined_transform, &pActor->t.t.mat);
580
    } else {
581
        BrMatrix34Mul(&combined_transform, pMatrix, &pActor->t.t.mat);
582
    }
583
    result = pCall_back(pActor, &combined_transform, pArg);
584
    if (result != 0) {
585
        return result;
586
    }
587
    for (pActor = pActor->children; pActor != NULL; pActor = pActor->next) {
588
        result = DRActorEnumRecurseWithTrans(pActor, &combined_transform, pCall_back, pArg);
589
        if (result != 0) {
590
            return result;
591
        }
592
    }
593
    return 0;
594
}
595
 
596
// IDA: int __usercall sign@<EAX>(int pNumber@<EAX>)
597
int sign(int pNumber) {
598
    LOG_TRACE("(%d)", pNumber);
599
 
600
    if (pNumber > 0) {
601
        return 1;
602
    } else if (pNumber < 0) {
603
        return -1;
604
    } else {
605
        return 0;
606
    }
607
}
608
 
609
// IDA: float __cdecl fsign(float pNumber)
610
float fsign(float pNumber) {
611
    LOG_TRACE("(%f)", pNumber);
612
    if (pNumber > 0.f) {
613
        return 1;
614
    } else if (pNumber < 0.f) {
615
        return -1.f;
616
    } else {
617
        return 0.f;
618
    }
619
}
620
 
621
// IDA: FILE* __usercall OpenUniqueFileB@<EAX>(char *pPrefix@<EAX>, char *pExtension@<EDX>)
622
FILE* OpenUniqueFileB(char* pPrefix, char* pExtension) {
623
    int index;
624
    FILE* f;
625
    tPath_name the_path;
626
    LOG_TRACE("(\"%s\", \"%s\")", pPrefix, pExtension);
627
 
628
    for (index = 0; index < 10000; index++) {
629
        PathCat(the_path, gApplication_path, pPrefix);
630
        sprintf(the_path + strlen(the_path), "%04d.%s", index, pExtension);
631
        f = DRfopen(the_path, "rt");
632
        if (f == NULL) {
633
            return DRfopen(the_path, "wb");
634
        }
635
        fclose(f);
636
    }
637
    return NULL;
638
}
639
 
640
// IDA: void __usercall PrintScreenFile(FILE *pF@<EAX>)
641
void PrintScreenFile(FILE* pF) {
642
    int i;
643
    int j;
644
    int bit_map_size;
645
    int offset;
646
    //tU8* pixel_ptr; // Pierre-Marie Baty -- unused variable
647
    LOG_TRACE("(%p)", pF);
648
 
649
    bit_map_size = gBack_screen->height * gBack_screen->row_bytes;
650
 
651
    // 1. BMP Header
652
    //    1. 'BM' Signature
653
    WriteU8L(pF, 'B');
654
    WriteU8L(pF, 'M');
655
    //    2. File size in bytes (header = 0xe bytes; infoHeader = 0x28 bytes; colorTable = 0x400 bytes; pixelData = xxx)
656
    WriteU32L(pF, bit_map_size + 0x436);
657
    //    3. unused
658
    WriteU16L(pF, 0);
659
    //    4. unused
660
    WriteU16L(pF, 0);
661
    //    5. pixelData offset (from beginning of file)
662
    WriteU32L(pF, 0x436);
663
 
664
    // 2. Info Header
665
    //    1. InfoHeader Size
666
    WriteU32L(pF, 0x28);
667
    //    2. Width of bitmap in pixels
668
    WriteU32L(pF, gBack_screen->row_bytes);
669
    //    3. Height of bitmap in pixels
670
    WriteU32L(pF, gBack_screen->height);
671
    //    4. Number of planes
672
    WriteU16L(pF, 1);
673
    //    5. Bits per pixels / palletization (8 -> 8bit palletized ==> #colors = 256)
674
    WriteU16L(pF, 8);
675
    //    6. Compression (0 = BI_RGB -> no compression)
676
    WriteU32L(pF, 0);
677
    //    7. Image Size (0 --> no compression)
678
    WriteU32L(pF, 0);
679
    //    8. Horizontal Pixels Per Meter
680
    WriteU32L(pF, 0);
681
    //    9. Vertical Pixels Per Meter
682
    WriteU32L(pF, 0);
683
    //    10. # Actually used colors
684
    WriteU32L(pF, 0);
685
    //    11. Number of important colors
686
    WriteU32L(pF, 256);
687
 
688
    // 3. Color table (=palette)
689
    for (i = 0; i < 256; i++) {
690
        // red, green, blue, unused
691
        WriteU8L(pF, ((tU8*)gCurrent_palette->pixels)[4 * i]);
692
        WriteU8L(pF, ((tU8*)gCurrent_palette->pixels)[4 * i + 1]);
693
        WriteU8L(pF, ((tU8*)gCurrent_palette->pixels)[4 * i + 2]);
694
        WriteU8L(pF, 0);
695
    }
696
 
697
    // 4. Pixel Data (=LUT)
698
    offset = bit_map_size - gBack_screen->row_bytes;
699
    for (i = 0; i < gBack_screen->height; i++) {
700
        for (j = 0; j < gBack_screen->row_bytes; j++) {
701
            WriteU8L(pF, ((tU8*)gBack_screen->pixels)[offset]);
702
            offset++;
703
        }
704
        offset -= 2 * gBack_screen->row_bytes;
705
    }
706
    WriteU16L(pF, 0);
707
}
708
 
709
// IDA: void __usercall PrintScreenFile16(FILE *pF@<EAX>)
710
void PrintScreenFile16(FILE* pF) {
711
    //int i; // Pierre-Marie Baty -- unused variable
712
    //int j; // Pierre-Marie Baty -- unused variable
713
    //int bit_map_size; // Pierre-Marie Baty -- unused variable
714
    //int offset; // Pierre-Marie Baty -- unused variable
715
    //tU8* pixel_ptr; // Pierre-Marie Baty -- unused variable
716
    //tU16 pixel; // Pierre-Marie Baty -- unused variable
717
    LOG_TRACE("(%p)", pF);
718
    NOT_IMPLEMENTED();
719
}
720
 
721
// IDA: void __cdecl PrintScreen()
722
void PrintScreen(void) {
723
    FILE* f;
724
    LOG_TRACE("()");
725
 
726
    f = OpenUniqueFileB("DUMP", "BMP");
727
    if (f != NULL) {
728
        PrintScreenFile(f);
729
        fclose(f);
730
    }
731
}
732
 
733
// IDA: tU32 __cdecl GetTotalTime()
734
tU32 GetTotalTime(void) {
735
    LOG_TRACE9("()");
736
 
737
    if (gAction_replay_mode) {
738
        return gLast_replay_frame_time;
739
    }
740
    if (gNet_mode != eNet_mode_none) {
741
        return PDGetTotalTime();
742
    }
743
    return PDGetTotalTime() - gLost_time;
744
}
745
 
746
// IDA: tU32 __cdecl GetRaceTime()
747
tU32 GetRaceTime(void) {
748
    LOG_TRACE("()");
749
 
750
    return GetTotalTime() - gRace_start;
751
}
752
 
753
// IDA: void __usercall AddLostTime(tU32 pLost_time@<EAX>)
754
void AddLostTime(tU32 pLost_time) {
755
 
756
    gLost_time += pLost_time;
757
}
758
 
759
// IDA: void __usercall TimerString(tU32 pTime@<EAX>, char *pStr@<EDX>, int pFudge_colon@<EBX>, int pForce_colon@<ECX>)
760
void TimerString(tU32 pTime, char* pStr, int pFudge_colon, int pForce_colon) {
761
    int seconds;
762
    LOG_TRACE("(%d, \"%s\", %d, %d)", pTime, pStr, pFudge_colon, pForce_colon);
763
 
764
    seconds = (pTime + 500) / 1000;
765
    if (pForce_colon || seconds > 59) {
766
        if (pFudge_colon) {
767
            sprintf(pStr, "%d/%02d", seconds / 60, seconds % 60);
768
        } else {
769
            sprintf(pStr, "%d:%02d", seconds / 60, seconds % 60);
770
        }
771
    } else {
772
        sprintf(pStr, "%d", seconds);
773
    }
774
}
775
 
776
// IDA: char* __usercall GetMiscString@<EAX>(int pIndex@<EAX>)
777
char* GetMiscString(int pIndex) {
778
 
779
    return gMisc_strings[pIndex];
780
}
781
 
782
// IDA: void __usercall GetCopyOfMiscString(int pIndex@<EAX>, char *pStr@<EDX>)
783
void GetCopyOfMiscString(int pIndex, char* pStr) {
784
    LOG_TRACE("(%d, \"%s\")", pIndex, pStr);
785
 
786
    strcpy(pStr, GetMiscString(pIndex));
787
}
788
 
789
// IDA: int __usercall Flash@<EAX>(tU32 pPeriod@<EAX>, tU32 *pLast_change@<EDX>, int *pCurrent_state@<EBX>)
790
int Flash(tU32 pPeriod, tU32* pLast_change, int* pCurrent_state) {
791
    tU32 the_time;
792
    LOG_TRACE("(%d, %p, %p)", pPeriod, pLast_change, pCurrent_state);
793
 
794
    the_time = PDGetTotalTime();
795
    if (the_time - *pLast_change > pPeriod) {
796
        *pCurrent_state = !*pCurrent_state;
797
        *pLast_change = the_time;
798
    }
799
    return *pCurrent_state;
800
}
801
 
802
// IDA: void __usercall MaterialCopy(br_material *pDst@<EAX>, br_material *pSrc@<EDX>)
803
void MaterialCopy(br_material* pDst, br_material* pSrc) {
804
    LOG_TRACE("(%p, %p)", pDst, pSrc);
805
 
806
    pDst->flags = pSrc->flags;
807
    pDst->ka = pSrc->ka;
808
    pDst->kd = pSrc->kd;
809
    pDst->ks = pSrc->ks;
810
    pDst->power = pSrc->power;
811
    pDst->colour = pSrc->colour;
812
    pDst->index_base = pSrc->index_base;
813
    pDst->index_range = pSrc->index_range;
814
    pDst->index_shade = pSrc->index_shade;
815
    pDst->colour_map = pSrc->colour_map;
816
    pDst->map_transform = pSrc->map_transform;
817
    pDst->identifier = pSrc->identifier;
818
}
819
 
820
// IDA: double __usercall RGBDifferenceSqr@<ST0>(tRGB_colour *pColour_1@<EAX>, tRGB_colour *pColour_2@<EDX>)
821
double RGBDifferenceSqr(tRGB_colour* pColour_1, tRGB_colour* pColour_2) {
822
    LOG_TRACE("(%p, %p)", pColour_1, pColour_2);
823
 
824
    return ((pColour_1->red - pColour_2->red) * (pColour_1->red - pColour_2->red))
825
        + ((pColour_1->green - pColour_2->green) * (pColour_1->green - pColour_2->green))
826
        + ((pColour_1->blue - pColour_2->blue) * (pColour_1->blue - pColour_2->blue));
827
}
828
 
829
// IDA: int __usercall FindBestMatch@<EAX>(tRGB_colour *pRGB_colour@<EAX>, br_pixelmap *pPalette@<EDX>)
830
int FindBestMatch(tRGB_colour* pRGB_colour, br_pixelmap* pPalette) {
831
    int n;
832
    int near_c;
833
    double min_d;
834
    double d;
835
    tRGB_colour trial_RGB;
836
    br_colour* dp;
837
    LOG_TRACE("(%p, %p)", pRGB_colour, pPalette);
838
 
839
    near_c = 127;
840
    min_d = 1.79769e+308; // max double
841
    dp = pPalette->pixels;
842
    for (n = 0; n < 256; n++) {
843
        trial_RGB.red = (dp[n] >> 16) & 0xff;
844
        trial_RGB.green = (dp[n] >> 8) & 0xff;
845
        trial_RGB.blue = (dp[n] >> 0) & 0xff;
846
        d = RGBDifferenceSqr(pRGB_colour, &trial_RGB);
847
        if (d < min_d) {
848
            min_d = d;
849
            near_c = n;
850
        }
851
    }
852
    return near_c;
853
}
854
 
855
// IDA: void __usercall BuildShadeTablePath(char *pThe_path@<EAX>, int pR@<EDX>, int pG@<EBX>, int pB@<ECX>)
856
void BuildShadeTablePath(char* pThe_path, int pR, int pG, int pB) {
857
    char s[32];
858
    LOG_TRACE("(\"%s\", %d, %d, %d)", pThe_path, pR, pG, pB);
859
 
860
    s[0] = 's';
861
    s[1] = 't';
862
    s[2] = 'A' + ((pR & 0xf0) >> 4);
863
    s[3] = 'A' + ((pR & 0x0f) >> 0);
864
    s[4] = 'A' + ((pG & 0xf0) >> 4);
865
    s[5] = 'A' + ((pG & 0x0f) >> 0);
866
    s[6] = 'A' + ((pB & 0xf0) >> 4);
867
    s[7] = 'A' + ((pB & 0x0f) >> 0);
868
    s[8] = '\0';
869
    strcat(s, ".TAB");
870
    PathCat(pThe_path, gApplication_path, "SHADETAB");
871
    PathCat(pThe_path, pThe_path, s);
872
}
873
 
874
// IDA: br_pixelmap* __usercall LoadGeneratedShadeTable@<EAX>(int pR@<EAX>, int pG@<EDX>, int pB@<EBX>)
875
br_pixelmap* LoadGeneratedShadeTable(int pR, int pG, int pB) {
876
    char the_path[256];
877
    LOG_TRACE("(%d, %d, %d)", pR, pG, pB);
878
 
879
    BuildShadeTablePath(the_path, pR, pG, pB);
880
    return BrPixelmapLoad(the_path);
881
}
882
 
883
// IDA: void __usercall SaveGeneratedShadeTable(br_pixelmap *pThe_table@<EAX>, int pR@<EDX>, int pG@<EBX>, int pB@<ECX>)
884
void SaveGeneratedShadeTable(br_pixelmap* pThe_table, int pR, int pG, int pB) {
885
    char the_path[256];
886
    LOG_TRACE("(%p, %d, %d, %d)", pThe_table, pR, pG, pB);
887
 
888
    BuildShadeTablePath(the_path, pR, pG, pB);
889
    BrPixelmapSave(the_path, pThe_table);
890
}
891
 
892
// IDA: br_pixelmap* __usercall GenerateShadeTable@<EAX>(int pHeight@<EAX>, br_pixelmap *pPalette@<EDX>, int pRed_mix@<EBX>, int pGreen_mix@<ECX>, int pBlue_mix, float pQuarter, float pHalf, float pThree_quarter)
893
br_pixelmap* GenerateShadeTable(int pHeight, br_pixelmap* pPalette, int pRed_mix, int pGreen_mix, int pBlue_mix, float pQuarter, float pHalf, float pThree_quarter) {
894
    LOG_TRACE("(%d, %p, %d, %d, %d, %f, %f, %f)", pHeight, pPalette, pRed_mix, pGreen_mix, pBlue_mix, pQuarter, pHalf, pThree_quarter);
895
 
896
    PossibleService();
897
    return GenerateDarkenedShadeTable(
898
        pHeight,
899
        pPalette,
900
        pRed_mix,
901
        pGreen_mix,
902
        pBlue_mix,
903
        pQuarter,
904
        pHalf,
905
        pThree_quarter,
906
        1.0);
907
}
908
 
909
// IDA: br_pixelmap* __usercall GenerateDarkenedShadeTable@<EAX>(int pHeight@<EAX>, br_pixelmap *pPalette@<EDX>, int pRed_mix@<EBX>, int pGreen_mix@<ECX>, int pBlue_mix, float pQuarter, float pHalf, float pThree_quarter, br_scalar pDarken)
910
br_pixelmap* GenerateDarkenedShadeTable(int pHeight, br_pixelmap* pPalette, int pRed_mix, int pGreen_mix, int pBlue_mix, float pQuarter, float pHalf, float pThree_quarter, br_scalar pDarken) {
911
    br_pixelmap* the_table;
912
    tRGB_colour the_RGB;
913
    tRGB_colour new_RGB;
914
    tRGB_colour ref_col;
915
    br_colour* cp;
916
    char* tab_ptr;
917
    char* shade_ptr;
918
    double f_i;
919
    double f_total_minus_1;
920
    double ratio1;
921
    double ratio2;
922
    int i;
923
    int c;
924
    LOG_TRACE("(%d, %p, %d, %d, %d, %f, %f, %f, %f)", pHeight, pPalette, pRed_mix, pGreen_mix, pBlue_mix, pQuarter, pHalf, pThree_quarter, pDarken);
925
 
926
    the_table = LoadGeneratedShadeTable(pRed_mix, pGreen_mix, pBlue_mix);
927
    if (the_table == NULL) {
928
        the_table = BrPixelmapAllocate(BR_PMT_INDEX_8, 256, pHeight, NULL, 0);
929
        if (the_table == NULL) {
930
            FatalError(kFatalError_LoadGeneratedShadeTable);
931
        }
932
        cp = pPalette->pixels;
933
 
934
        ref_col.red = pRed_mix;
935
        ref_col.green = pGreen_mix;
936
        ref_col.blue = pBlue_mix;
937
 
938
        for (c = 0, tab_ptr = the_table->pixels; c < 256; c++, tab_ptr++) {
939
            the_RGB.red = ((cp[c] >> 16) & 0xff) * pDarken;
940
            the_RGB.green = ((cp[c] >> 8) & 0xff) * pDarken;
941
            the_RGB.blue = ((cp[c] >> 0) & 0xff) * pDarken;
942
 
943
            if (pHeight == 1) {
944
                f_total_minus_1 = 1.;
945
            } else {
946
                f_total_minus_1 = pHeight - 1;
947
            }
948
            shade_ptr = tab_ptr;
949
            for (i = 0, shade_ptr = tab_ptr; i < pHeight; i++, shade_ptr += 0x100) {
950
                f_i = i;
951
                ratio1 = f_i / f_total_minus_1;
952
                if (ratio1 < .5) {
953
                    if (ratio1 < .25) {
954
                        ratio2 = pQuarter * ratio1 * 4.;
955
                    } else {
956
                        ratio2 = (ratio1 - .25) * (pHalf - pQuarter) * 4. + pQuarter;
957
                    }
958
                } else {
959
                    if (ratio1 < 0.75) {
960
                        ratio2 = (ratio1 - .5) * (pThree_quarter - pHalf) * 4. + pHalf;
961
                    } else {
962
                        ratio2 = 1. - (1. - pThree_quarter) * (1. - ratio1) * 4.;
963
                    }
964
                }
965
                new_RGB.red = ref_col.red * ratio2 + the_RGB.red * (1. - ratio2);
966
                new_RGB.green = ref_col.green * ratio2 + the_RGB.green * (1. - ratio2);
967
                new_RGB.blue = ref_col.blue * ratio2 + the_RGB.blue * (1. - ratio2);
968
                *shade_ptr = FindBestMatch(&new_RGB, pPalette);
969
            }
970
        }
971
        SaveGeneratedShadeTable(the_table, pRed_mix, pGreen_mix, pBlue_mix);
972
    }
973
    BrTableAdd(the_table);
974
    return the_table;
975
}
976
 
977
// IDA: void __cdecl PossibleService()
978
void PossibleService(void) {
979
    tU32 time;
980
    static tU32 last_service = 0;
981
 
982
    time = PDGetTotalTime();
983
    if (time - last_service > MIN_SERVICE_INTERVAL && !gProgram_state.racing) {
984
        SoundService();
985
        NetService(gProgram_state.racing);
986
        last_service = time;
987
    }
988
}
989
 
990
// IDA: void __usercall DRMatrix34TApplyP(br_vector3 *pA@<EAX>, br_vector3 *pB@<EDX>, br_matrix34 *pC@<EBX>)
991
void DRMatrix34TApplyP(br_vector3* pA, br_vector3* pB, br_matrix34* pC) {
992
    br_scalar t1;
993
    br_scalar t2;
994
    br_scalar t3;
995
    LOG_TRACE("(%p, %p, %p)", pA, pB, pC);
996
 
997
    t1 = pB->v[0] - pC->m[3][0];
998
    t2 = pB->v[1] - pC->m[3][1];
999
    t3 = pB->v[2] - pC->m[3][2];
1000
    pA->v[0] = pC->m[0][0] * t1 + pC->m[0][1] * t2 + pC->m[0][2] * t3;
1001
    pA->v[1] = pC->m[1][0] * t1 + pC->m[1][1] * t2 + pC->m[1][2] * t3;
1002
    pA->v[2] = pC->m[2][0] * t1 + pC->m[2][1] * t2 + pC->m[2][2] * t3;
1003
}
1004
 
1005
// IDA: tU16 __usercall PaletteEntry16Bit@<AX>(br_pixelmap *pPal@<EAX>, int pEntry@<EDX>)
1006
tU16 PaletteEntry16Bit(br_pixelmap* pPal, int pEntry) {
1007
    //tU32* src_entry; // Pierre-Marie Baty -- unused variable
1008
    //int red; // Pierre-Marie Baty -- unused variable
1009
    //int green; // Pierre-Marie Baty -- unused variable
1010
    //int blue; // Pierre-Marie Baty -- unused variable
1011
    LOG_TRACE("(%p, %d)", pPal, pEntry);
1012
    NOT_IMPLEMENTED();
1013
}
1014
 
1015
// IDA: br_pixelmap* __usercall PaletteOf16Bits@<EAX>(br_pixelmap *pSrc@<EAX>)
1016
br_pixelmap* PaletteOf16Bits(br_pixelmap* pSrc) {
1017
    //tU16* dst_entry; // Pierre-Marie Baty -- unused variable
1018
    //int value; // Pierre-Marie Baty -- unused variable
1019
    LOG_TRACE("(%p)", pSrc);
1020
    NOT_IMPLEMENTED();
1021
}
1022
 
1023
// IDA: void __usercall Copy8BitTo16Bit(br_pixelmap *pDst@<EAX>, br_pixelmap *pSrc@<EDX>, br_pixelmap *pPalette@<EBX>)
1024
void Copy8BitTo16Bit(br_pixelmap* pDst, br_pixelmap* pSrc, br_pixelmap* pPalette) {
1025
    //int x; // Pierre-Marie Baty -- unused variable
1026
    //int y; // Pierre-Marie Baty -- unused variable
1027
    //tU8* src_start; // Pierre-Marie Baty -- unused variable
1028
    //tU16* dst_start; // Pierre-Marie Baty -- unused variable
1029
    //tU16* palette_entry; // Pierre-Marie Baty -- unused variable
1030
    LOG_TRACE("(%p, %p, %p)", pDst, pSrc, pPalette);
1031
    NOT_IMPLEMENTED();
1032
}
1033
 
1034
// IDA: void __usercall Copy8BitTo16BitRectangle(br_pixelmap *pDst@<EAX>, tS16 pDst_x@<EDX>, tS16 pDst_y@<EBX>, br_pixelmap *pSrc@<ECX>, tS16 pSrc_x, tS16 pSrc_y, tS16 pWidth, tS16 pHeight, br_pixelmap *pPalette)
1035
void Copy8BitTo16BitRectangle(br_pixelmap* pDst, tS16 pDst_x, tS16 pDst_y, br_pixelmap* pSrc, tS16 pSrc_x, tS16 pSrc_y, tS16 pWidth, tS16 pHeight, br_pixelmap* pPalette) {
1036
    //int x; // Pierre-Marie Baty -- unused variable
1037
    //int y; // Pierre-Marie Baty -- unused variable
1038
    //tU8* src_start; // Pierre-Marie Baty -- unused variable
1039
    //tU16* dst_start; // Pierre-Marie Baty -- unused variable
1040
    //tU16* palette_entry; // Pierre-Marie Baty -- unused variable
1041
    LOG_TRACE("(%p, %d, %d, %p, %d, %d, %d, %d, %p)", pDst, pDst_x, pDst_y, pSrc, pSrc_x, pSrc_y, pWidth, pHeight, pPalette);
1042
    NOT_IMPLEMENTED();
1043
}
1044
 
1045
// IDA: void __usercall Copy8BitTo16BitRectangleWithTransparency(br_pixelmap *pDst@<EAX>, tS16 pDst_x@<EDX>, tS16 pDst_y@<EBX>, br_pixelmap *pSrc@<ECX>, tS16 pSrc_x, tS16 pSrc_y, tS16 pWidth, tS16 pHeight, br_pixelmap *pPalette)
1046
void Copy8BitTo16BitRectangleWithTransparency(br_pixelmap* pDst, tS16 pDst_x, tS16 pDst_y, br_pixelmap* pSrc, tS16 pSrc_x, tS16 pSrc_y, tS16 pWidth, tS16 pHeight, br_pixelmap* pPalette) {
1047
    //int x; // Pierre-Marie Baty -- unused variable
1048
    //int y; // Pierre-Marie Baty -- unused variable
1049
    //tU8* src_start; // Pierre-Marie Baty -- unused variable
1050
    //tU16* dst_start; // Pierre-Marie Baty -- unused variable
1051
    //tU16* palette_entry; // Pierre-Marie Baty -- unused variable
1052
    LOG_TRACE("(%p, %d, %d, %p, %d, %d, %d, %d, %p)", pDst, pDst_x, pDst_y, pSrc, pSrc_x, pSrc_y, pWidth, pHeight, pPalette);
1053
    NOT_IMPLEMENTED();
1054
}
1055
 
1056
// IDA: void __usercall Copy8BitToOnscreen16BitRectangleWithTransparency(br_pixelmap *pDst@<EAX>, tS16 pDst_x@<EDX>, tS16 pDst_y@<EBX>, br_pixelmap *pSrc@<ECX>, tS16 pSrc_x, tS16 pSrc_y, tS16 pWidth, tS16 pHeight, br_pixelmap *pPalette)
1057
void Copy8BitToOnscreen16BitRectangleWithTransparency(br_pixelmap* pDst, tS16 pDst_x, tS16 pDst_y, br_pixelmap* pSrc, tS16 pSrc_x, tS16 pSrc_y, tS16 pWidth, tS16 pHeight, br_pixelmap* pPalette) {
1058
    //int x; // Pierre-Marie Baty -- unused variable
1059
    //int y; // Pierre-Marie Baty -- unused variable
1060
    //tU8* src_start; // Pierre-Marie Baty -- unused variable
1061
    //tU16* dst_start; // Pierre-Marie Baty -- unused variable
1062
    //tU16* palette_entry; // Pierre-Marie Baty -- unused variable
1063
    LOG_TRACE("(%p, %d, %d, %p, %d, %d, %d, %d, %p)", pDst, pDst_x, pDst_y, pSrc, pSrc_x, pSrc_y, pWidth, pHeight, pPalette);
1064
    NOT_IMPLEMENTED();
1065
}
1066
 
1067
// IDA: void __usercall Copy8BitRectangleTo16BitRhombusWithTransparency(br_pixelmap *pDst@<EAX>, tS16 pDst_x@<EDX>, tS16 pDst_y@<EBX>, br_pixelmap *pSrc@<ECX>, tS16 pSrc_x, tS16 pSrc_y, tS16 pWidth, tS16 pHeight, tX1616 pShear, br_pixelmap *pPalette)
1068
void Copy8BitRectangleTo16BitRhombusWithTransparency(br_pixelmap* pDst, tS16 pDst_x, tS16 pDst_y, br_pixelmap* pSrc, tS16 pSrc_x, tS16 pSrc_y, tS16 pWidth, tS16 pHeight, tX1616 pShear, br_pixelmap* pPalette) {
1069
    //int x; // Pierre-Marie Baty -- unused variable
1070
    //int y; // Pierre-Marie Baty -- unused variable
1071
    //tU8* src_start; // Pierre-Marie Baty -- unused variable
1072
    //tU16* dst_start; // Pierre-Marie Baty -- unused variable
1073
    //tU16* palette_entry; // Pierre-Marie Baty -- unused variable
1074
    //tX1616 total_shear; // Pierre-Marie Baty -- unused variable
1075
    //tS16 sheared_x; // Pierre-Marie Baty -- unused variable
1076
    //tS16 clipped_src_x; // Pierre-Marie Baty -- unused variable
1077
    //tS16 clipped_width; // Pierre-Marie Baty -- unused variable
1078
    LOG_TRACE("(%p, %d, %d, %p, %d, %d, %d, %d, %d, %p)", pDst, pDst_x, pDst_y, pSrc, pSrc_x, pSrc_y, pWidth, pHeight, pShear, pPalette);
1079
    NOT_IMPLEMENTED();
1080
}
1081
 
1082
// IDA: void __usercall DRPixelmapRectangleCopy(br_pixelmap *dst@<EAX>, br_int_16 dx@<EDX>, br_int_16 dy@<EBX>, br_pixelmap *src@<ECX>, br_int_16 sx, br_int_16 sy, br_uint_16 w, br_uint_16 h)
1083
void DRPixelmapRectangleCopy(br_pixelmap* dst, br_int_16 dx, br_int_16 dy, br_pixelmap* src, br_int_16 sx, br_int_16 sy, br_uint_16 w, br_uint_16 h) {
1084
    LOG_TRACE("(%p, %d, %d, %p, %d, %d, %d, %d)", dst, dx, dy, src, sx, sy, w, h);
1085
 
1086
    BrPixelmapRectangleCopy(dst, dx, dy, src, sx, sy, w, h);
1087
}
1088
 
1089
// IDA: void __usercall DRPixelmapCopy(br_pixelmap *dst@<EAX>, br_pixelmap *src@<EDX>)
1090
void DRPixelmapCopy(br_pixelmap* dst, br_pixelmap* src) {
1091
    LOG_TRACE("(%p, %p)", dst, src);
1092
 
1093
    BrPixelmapCopy(dst, src);
1094
}
1095
 
1096
// IDA: void __usercall DRPixelmapRectangleFill(br_pixelmap *dst@<EAX>, br_int_16 x@<EDX>, br_int_16 y@<EBX>, br_uint_16 w@<ECX>, br_uint_16 h, br_uint_32 colour)
1097
void DRPixelmapRectangleFill(br_pixelmap* dst, br_int_16 x, br_int_16 y, br_uint_16 w, br_uint_16 h, br_uint_32 colour) {
1098
    LOG_TRACE("(%p, %d, %d, %d, %d, %d)", dst, x, y, w, h, colour);
1099
 
1100
    BrPixelmapRectangleFill(dst, x, y, w, h, colour);
1101
}
1102
 
1103
// IDA: int __usercall NormalSideOfPlane@<EAX>(br_vector3 *pPoint@<EAX>, br_vector3 *pNormal@<EDX>, br_scalar pD)
1104
int NormalSideOfPlane(br_vector3* pPoint, br_vector3* pNormal, br_scalar pD) {
1105
    //br_scalar numer; // Pierre-Marie Baty -- unused variable
1106
    //br_scalar denom; // Pierre-Marie Baty -- unused variable
1107
    LOG_TRACE("(%p, %p, %f)", pPoint, pNormal, pD);
1108
 
1109
    return (BrVector3Dot(pNormal, pPoint) - pD) >= 0.f;
1110
}
1111
 
1112
// IDA: br_material* __usercall DRMaterialClone@<EAX>(br_material *pMaterial@<EAX>)
1113
br_material* DRMaterialClone(br_material* pMaterial) {
1114
    br_material* the_material;
1115
    char s[256];
1116
    static int name_suffix = 0;
1117
    LOG_TRACE("(%p)", pMaterial);
1118
 
1119
    the_material = BrMaterialAllocate(NULL);
1120
    the_material->flags = pMaterial->flags;
1121
    the_material->ka = pMaterial->ka;
1122
    the_material->kd = pMaterial->kd;
1123
    the_material->ks = pMaterial->ks;
1124
    the_material->power = pMaterial->power;
1125
    the_material->colour = pMaterial->colour;
1126
    the_material->index_base = pMaterial->index_base;
1127
    the_material->index_range = pMaterial->index_range;
1128
    the_material->index_shade = pMaterial->index_shade;
1129
    the_material->index_blend = pMaterial->index_blend;
1130
    the_material->colour_map = pMaterial->colour_map;
1131
    memcpy(&the_material->map_transform, &pMaterial->map_transform, sizeof(the_material->map_transform));
1132
    sprintf(s, "%s(%d)", pMaterial->identifier, name_suffix);
1133
    name_suffix++;
1134
    the_material->identifier = BrResAllocate(the_material, strlen(s) + 1, BR_MEMORY_STRING);
1135
    strcpy(the_material->identifier, s);
1136
    BrMaterialAdd(the_material);
1137
    return the_material;
1138
}
1139
 
1140
// IDA: void __usercall StripCR(char *s@<EAX>)
1141
void StripCR(char* s) {
1142
    char* pos;
1143
 
1144
    pos = s;
1145
    while (*pos != '\0') {
1146
        if (*pos == '\r' || *pos == '\n') {
1147
            *pos = '\0';
1148
            break;
1149
        }
1150
        pos++;
1151
    }
1152
}
1153
 
1154
// IDA: void __cdecl SubsStringJob(char *pStr, ...)
1155
void SubsStringJob(char* pStr, ...) {
18 pmbaty 1156
    char* sub_str;
1157
    char temp_str[256];
1158
    char* sub_pt;
1159
    va_list ap;
1 pmbaty 1160
    LOG_TRACE("(\"%s\")", pStr);
18 pmbaty 1161
 
1162
    va_start(ap, pStr);
1163
    for (;;) {
1164
        sub_pt = strchr(pStr, '%');
1165
        if (sub_pt == NULL) {
1166
            va_end(ap);
1167
            return;
1168
        }
1169
        sub_str = va_arg(ap, char *);
1170
        StripCR(sub_str);
1171
        strcpy(temp_str, &sub_pt[1]);
1172
        strcpy(sub_pt, sub_str);
1173
        strcat(pStr, temp_str);
1174
    }
1 pmbaty 1175
}
1176
 
1177
// IDA: void __usercall DecodeLine2(char *pS@<EAX>)
1178
void DecodeLine2(char* pS) {
1179
    int len;
1180
    int seed;
1181
    int i;
1182
    unsigned char c;
1183
    char* key;
1184
 
1185
    len = strlen(pS);
1186
    key = (char*)gLong_key;
1187
    while (len > 0 && (pS[len - 1] == '\r' || pS[len - 1] == '\n')) {
1188
        len--;
1189
        pS[len] = '\0';
1190
    }
1191
    seed = len % 16;
1192
    for (i = 0; i < len; i++) {
1193
        c = pS[i];
1194
        if (i >= 2) {
1195
            if (pS[i - 1] == '/' && pS[i - 2] == '/') {
1196
                key = (char*)gOther_long_key;
1197
            }
1198
        }
1199
        if (gEncryption_method == 1) {
1200
            if (c == '\t') {
1201
                c = 0x9f;
1202
            }
1203
 
1204
            c -= 0x20;
1205
            c ^= key[seed];
1206
            c &= 0x7f;
1207
            c += 0x20;
1208
 
1209
            seed += 7;
1210
            seed %= 16;
1211
 
1212
            if (c == 0x9f) {
1213
                c = '\t';
1214
            }
1215
        } else {
1216
            if (c == '\t') {
1217
                c = 0x80;
1218
            }
1219
            c -= 0x20;
1220
            if ((c & 0x80) == 0) {
1221
                c ^= key[seed] & 0x7f;
1222
            }
1223
            c += 0x20;
1224
 
1225
            seed += 7;
1226
            seed %= 16;
1227
 
1228
            if (c == 0x80) {
1229
                c = '\t';
1230
            }
1231
        }
1232
        pS[i] = c;
1233
    }
1234
}
1235
 
1236
// IDA: void __usercall EncodeLine2(char *pS@<EAX>)
1237
void EncodeLine2(char* pS) {
1238
    int len;
1239
    int seed;
1240
    int i;
1241
    int count;
1242
    unsigned char c;
1243
    char* key;
1244
 
1245
    len = strlen(pS);
1246
    count = 0;
1247
    key = (char*)gLong_key;
1248
    while (len > 0 && (pS[len - 1] == '\r' || pS[len - 1] == '\n')) {
1249
        len--;
1250
        pS[len] = '\0';
1251
    }
1252
 
1253
    seed = len % 16;
1254
 
1255
    for (i = 0; i < len; i++) {
1256
        if (count == 2) {
1257
            key = (char*)gOther_long_key;
1258
        }
1259
        if (pS[i] == '/') {
1260
            count++;
1261
        } else {
1262
            count = 0;
1263
        }
1264
        if (pS[i] == '\t') {
1265
            pS[i] = 0x80;
1266
        }
1267
 
1268
        c = pS[i] - 0x20;
1269
        if ((c & 0x80) == 0) {
1270
            c ^= key[seed] & 0x7f;
1271
        }
1272
        c += 0x20;
1273
 
1274
        seed += 7;
1275
        seed %= 16;
1276
 
1277
        if (c == 0x80) {
1278
            c = '\t';
1279
        }
1280
        pS[i] = c;
1281
    }
1282
}
1283
 
1284
// IDA: void __usercall EncodeFile(char *pThe_path@<EAX>)
1285
void EncodeFile(char* pThe_path) {
1286
    FILE* f;
1287
    FILE* d;
1288
    char line[257];
1289
    char new_file[256];
1290
    char* s;
1291
    char* result;
1292
    int ch;
1293
    int decode;
1294
    int len;
1295
    int count;
1296
    LOG_TRACE("(\"%s\")", pThe_path);
1297
 
1298
    len = strlen(pThe_path);
1299
    strcpy(new_file, pThe_path);
1300
    strcpy(&new_file[len - 3], "ENC");
1301
 
1302
    f = fopen(pThe_path, "rt");
1303
    if (f == NULL) {
1304
        FatalError(kFatalError_Open_S, pThe_path);
1305
    }
1306
 
1307
    ch = fgetc(f);
1308
    ungetc(ch, f);
1309
 
1310
    if (gDecode_thing == '@' && gDecode_thing == (char)ch) {
1311
        fclose(f);
1312
        return;
1313
    }
1314
 
1315
    d = fopen(new_file, "wb");
1316
    if (d == NULL) {
1317
        FatalError(kFatalError_Open_S, new_file);
1318
    }
1319
 
1320
    result = &line[1];
1321
 
1322
    while (!feof(f)) {
1323
        s = fgets(result, 256, f);
1324
 
1325
        if (s == NULL) {
1326
            continue;
1327
        }
1328
 
1329
        if (result[0] == '@') {
1330
            decode = 1;
1331
        } else {
1332
            decode = 0;
1333
            // Strip leading whitespace
1334
            while (result[0] == ' ' || result[0] == '\t') {
1335
                memmove(result, &result[1], strlen(result));
1336
            }
1337
        }
1338
 
1339
        if (decode) {
1340
            DecodeLine2(&result[decode]);
1341
        } else {
1342
            EncodeLine2(&result[decode]);
1343
        }
1344
 
1345
        line[0] = '@';
1346
        fputs(&line[decode * 2], d);
1347
        count = -1;
1348
        while (1) {
1349
            count++;
1350
            ch = fgetc(f);
1351
            if (ch != '\r' && ch != '\n') {
1352
                break;
1353
            }
1354
        }
1355
        if (count > 2) {
1356
            fputc('\r', d);
1357
            fputc('\n', d);
1358
        }
1359
        fputc('\r', d);
1360
        fputc('\n', d);
1361
 
1362
        if (ch != -1) {
1363
            ungetc(ch, f);
1364
        }
1365
    }
1366
    fclose(f);
1367
    fclose(d);
1368
 
1369
    PDFileUnlock(pThe_path);
1370
    remove(pThe_path);
1371
    rename(new_file, pThe_path);
1372
}
1373
 
1374
// IDA: void __usercall EncodeFileWrapper(char *pThe_path@<EAX>)
1375
void EncodeFileWrapper(char* pThe_path) {
1376
    int len;
1377
    LOG_TRACE("(\"%s\")", pThe_path);
1378
 
1379
    len = strlen(pThe_path);
1380
 
1381
    // if file doesn't end in .txt, bail out
1382
    if (STR_ENDS_WITH(pThe_path, ".TXT") != 0) {
1383
        return;
1384
    }
1385
    if (STR_ENDS_WITH(pThe_path, "DKEYMAP0.TXT") == 0) {
1386
        return;
1387
    }
1388
    if (STR_ENDS_WITH(pThe_path, "DKEYMAP1.TXT") == 0) {
1389
        return;
1390
    }
1391
    if (STR_ENDS_WITH(pThe_path, "DKEYMAP2.TXT") == 0) {
1392
        return;
1393
    }
1394
    if (STR_ENDS_WITH(pThe_path, "DKEYMAP3.TXT") == 0) {
1395
        return;
1396
    }
1397
    if (STR_ENDS_WITH(pThe_path, "KEYMAP_0.TXT") == 0) {
1398
        return;
1399
    }
1400
    if (STR_ENDS_WITH(pThe_path, "KEYMAP_1.TXT") == 0) {
1401
        return;
1402
    }
1403
    if (STR_ENDS_WITH(pThe_path, "KEYMAP_2.TXT") == 0) {
1404
        return;
1405
    }
1406
    if (STR_ENDS_WITH(pThe_path, "KEYMAP_3.TXT") == 0) {
1407
        return;
1408
    }
1409
    if (STR_ENDS_WITH(pThe_path, "OPTIONS.TXT") == 0) {
1410
        return;
1411
    }
1412
    if (STR_ENDS_WITH(pThe_path, "KEYNAMES.TXT") == 0) {
1413
        return;
1414
    }
1415
    if (STR_ENDS_WITH(pThe_path, "KEYMAP.TXT") == 0) {
1416
        return;
1417
    }
1418
    if (STR_ENDS_WITH(pThe_path, "PATHS.TXT") == 0) {
1419
        return;
1420
    }
1421
 
1422
    EncodeFile(pThe_path);
1423
}
1424
 
1425
// IDA: void __usercall EncodeAllFilesInDirectory(char *pThe_path@<EAX>)
1426
void EncodeAllFilesInDirectory(char* pThe_path) {
1427
    char s[256];
1428
    LOG_TRACE("(\"%s\")", pThe_path);
1429
 
1430
    PathCat(s, gApplication_path, pThe_path);
1431
    PDForEveryFile(s, EncodeFileWrapper);
1432
}
1433
 
1434
// IDA: void __usercall SkipNLines(FILE *pF@<EAX>)
1435
void SkipNLines(FILE* pF) {
1436
    int i;
1437
    int count;
1438
    char s[256];
1439
    LOG_TRACE("(%p)", pF);
1440
 
1441
    count = GetAnInt(pF);
1442
    for (i = 0; i < count; i++) {
1443
        GetALineAndDontArgue(pF, s);
1444
    }
1445
}
1446
 
1447
// IDA: int __usercall DRStricmp@<EAX>(char *p1@<EAX>, char *p2@<EDX>)
1448
int DRStricmp(char* p1, char* p2) {
1449
    int val;
1450
    while (p1) {
1451
        val = tolower(*p1) - tolower(*p2);
1452
        if (val != 0) {
1453
            return val;
1454
        }
1455
        p1++;
1456
        p2++;
1457
    }
1458
    return 0;
1459
}
1460
 
1461
// IDA: void __usercall GlorifyMaterial(br_material **pArray@<EAX>, int pCount@<EDX>)
1462
void GlorifyMaterial(br_material** pArray, int pCount) {
1463
    //int i; // Pierre-Marie Baty -- unused variable
1464
    //int c; // Pierre-Marie Baty -- unused variable
1465
    //br_pixelmap* big_tile; // Pierre-Marie Baty -- unused variable
1466
    //tException_list e; // Pierre-Marie Baty -- unused variable
1467
    LOG_TRACE("(%p, %d)", pArray, pCount);
1468
    NOT_IMPLEMENTED();
1469
}
1470
 
1471
// IDA: void __usercall WhitenVertexRGB(br_model **pArray@<EAX>, int pN@<EDX>)
1472
void WhitenVertexRGB(br_model** pArray, int pN) {
1473
    //int m; // Pierre-Marie Baty -- unused variable
1474
    //int v; // Pierre-Marie Baty -- unused variable
1475
    //br_vertex* vertex; // Pierre-Marie Baty -- unused variable
1476
    LOG_TRACE("(%p, %d)", pArray, pN);
1477
    NOT_IMPLEMENTED();
1478
}
1479
 
1480
// IDA: void __usercall NobbleNonzeroBlacks(br_pixelmap *pPalette@<EAX>)
1481
void NobbleNonzeroBlacks(br_pixelmap* pPalette) {
1482
    //tU32 red; // Pierre-Marie Baty -- unused variable
1483
    //tU32 green; // Pierre-Marie Baty -- unused variable
1484
    //tU32 blue; // Pierre-Marie Baty -- unused variable
1485
    //tU32 value; // Pierre-Marie Baty -- unused variable
1486
    //tU32* palette_entry; // Pierre-Marie Baty -- unused variable
1487
    //tU32 frobbed; // Pierre-Marie Baty -- unused variable
1488
    LOG_TRACE("(%p)", pPalette);
1489
    NOT_IMPLEMENTED();
1490
}
1491
 
1492
// IDA: int __usercall PDCheckDriveExists@<EAX>(char *pThe_path@<EAX>)
1493
int PDCheckDriveExists(char* pThe_path) {
1494
    LOG_TRACE9("(\"%s\")", pThe_path);
1495
 
1496
    return PDCheckDriveExists2(pThe_path, NULL, 0);
1497
}
1498
 
1499
// IDA: int __usercall OpacityInPrims@<EAX>(br_token_value *pPrims@<EAX>)
1500
int OpacityInPrims(br_token_value* pPrims) {
1501
    LOG_TRACE("(%p)", pPrims);
1502
 
1503
    for (; pPrims->t != 0 && pPrims->t != BRT_OPACITY_X; pPrims++) {
1504
    }
1505
    return pPrims->t != 0;
1506
}
1507
 
1508
// IDA: int __usercall AlreadyBlended@<EAX>(br_material *pMaterial@<EAX>)
1509
int AlreadyBlended(br_material* pMaterial) {
1510
    LOG_TRACE("(%p)", pMaterial);
1511
 
1512
    if (pMaterial->index_blend != NULL) {
1513
        return 1;
1514
    }
1515
    if (pMaterial->extra_prim == NULL) {
1516
        return 0;
1517
    }
1518
    return OpacityInPrims(pMaterial->extra_prim);
1519
}
1520
 
1521
// IDA: void __usercall BlendifyMaterialTablishly(br_material *pMaterial@<EAX>, int pPercent@<EDX>)
1522
void BlendifyMaterialTablishly(br_material* pMaterial, int pPercent) {
1523
    char* s = NULL;
1524
    LOG_TRACE("(%p, %d)", pMaterial, pPercent);
1525
 
1526
    switch (pPercent) {
1527
    case 25:
1528
        s = "BLEND75.TAB";
1529
        break;
1530
    case 50:
1531
        s = "BLEND50.TAB";
1532
        break;
1533
    case 75:
1534
        s = "BLEND25.TAB";
1535
        break;
1536
    default:
1537
        PDFatalError("Invalid alpha");
1538
        break;
1539
    }
1540
    pMaterial->index_blend = BrTableFind(s);
1541
    if (pMaterial->index_blend == NULL) {
1542
        pMaterial->index_blend = LoadSingleShadeTable(&gTrack_storage_space, s);
1543
    }
1544
}
1545
 
1546
// IDA: void __usercall BlendifyMaterialPrimitively(br_material *pMaterial@<EAX>, int pPercent@<EDX>)
1547
void BlendifyMaterialPrimitively(br_material* pMaterial, int pPercent) {
1548
 
1549
    static br_token_value alpha25[3] = {
1550
        { BRT_BLEND_B, { .b = 1 } },
1551
        { BRT_OPACITY_X, { .x = 0x400000 } },
1552
        { 0 },
1553
    };
1554
    static br_token_value alpha50[3] = {
1555
        { BRT_BLEND_B, { .b = 1 } },
1556
        { BRT_OPACITY_X, { .x = 0x800000 } },
1557
        { 0 },
1558
    };
1559
    static br_token_value alpha75[3] = {
1560
        { BRT_BLEND_B, { .b = 1 } },
1561
        { BRT_OPACITY_X, { .x = 0xc00000 } },
1562
        { 0 },
1563
    };
1564
    LOG_TRACE("(%p, %d)", pMaterial, pPercent);
1565
 
1566
    switch (pPercent) {
1567
    case 25:
1568
        pMaterial->extra_prim = alpha25;
1569
        break;
1570
    case 50:
1571
        pMaterial->extra_prim = alpha50;
1572
        break;
1573
    case 75:
1574
        pMaterial->extra_prim = alpha75;
1575
        break;
1576
    default:
1577
        PDFatalError("Invalid alpha");
1578
    }
1579
}
1580
 
1581
// IDA: void __usercall BlendifyMaterial(br_material *pMaterial@<EAX>, int pPercent@<EDX>)
1582
void BlendifyMaterial(br_material* pMaterial, int pPercent) {
1583
    LOG_TRACE("(%p, %d)", pMaterial, pPercent);
1584
 
1585
    if (gScreen->type == BR_PMT_INDEX_8) {
1586
        BlendifyMaterialTablishly(pMaterial, pPercent);
1587
    } else {
1588
        BlendifyMaterialPrimitively(pMaterial, pPercent);
1589
    }
1590
}