Subversion Repositories Games.Carmageddon

Rev

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

  1. #include "utility.h"
  2. #include <stdlib.h>
  3.  
  4. #include "brender.h"
  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) {
  210. #if 1
  211.     int num;
  212.     //char s[32]; // Pierre-Marie Baty -- unused variable
  213.  
  214.     num = rand();
  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)
  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
  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
  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>)
  517. br_uintptr_t DRActorEnumRecurse(br_actor* pActor, br_actor_enum_cbfn* callback, void* arg) {
  518.     br_uintptr_t result;
  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)
  534. br_uintptr_t CompareActorID(br_actor* pActor, void* pArg) {
  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, ...) {
  1156.     char* sub_str;
  1157.     char temp_str[256];
  1158.     char* sub_pt;
  1159.     va_list ap;
  1160.     LOG_TRACE("(\"%s\")", pStr);
  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.     }
  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. }
  1591.