Advertisement
Guest User

Cod4 Shader Compiler

a guest
Nov 2nd, 2018
790
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 18.66 KB | None | 0 0
  1. /*
  2. Copyright (c) 2015 Otso O.
  3.  
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7.  
  8. Permission is granted to anyone to use this software for any purpose,
  9. including commercial applications, and to alter it and redistribute it
  10. freely, subject to the following restrictions:
  11.  
  12. 1. The origin of this software must not be misrepresented; you must not
  13.    claim that you wrote the original software. If you use this software
  14.    in a product, an acknowledgement in the product documentation would be
  15.    appreciated but is not required.
  16. 2. Altered source versions must be plainly marked as such, and must not be
  17.    misrepresented as being the original software.
  18. 3. This notice may not be removed or altered from any source distribution.
  19. */
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <stdint.h>
  25. #include <time.h>
  26.  
  27. #ifdef _DEBUG
  28. #   define _CRTDBG_MAP_ALLOC
  29. #   include <stdlib.h>
  30. #   include <crtdbg.h>
  31. #endif // _DEBUG
  32.  
  33. int isDefined(void const *ptr)
  34. {
  35.     return (*(uint32_t*)ptr != 0);
  36. }
  37.  
  38. #include <windows.h>
  39. int colorPrint(uint8_t color, char const *fmt, ...)
  40. {
  41.     int result;
  42.     va_list arg;
  43.  
  44.     HANDLE handle = 0;
  45.     handle = GetStdHandle(STD_OUTPUT_HANDLE);
  46.  
  47.     va_start(arg, fmt);
  48.     if(isDefined(&handle))
  49.     {
  50.         SetConsoleTextAttribute(handle, color);
  51.         result = vprintf(fmt, arg);
  52.         SetConsoleTextAttribute(handle, 0x07);
  53.     } else
  54.         result = vprintf(fmt, arg);
  55.  
  56.     va_end(arg);
  57.     return result;
  58. }
  59.  
  60. uint32_t swapByteOrder32(uint32_t uint)
  61. {
  62.     return ((uint & 0x000000ff) << 24) |
  63.            ((uint & 0x0000ff00) << 8)  |
  64.            ((uint & 0x00ff0000) >> 8)  |
  65.            ((uint & 0xff000000) >> 24);
  66. }
  67.  
  68. uint32_t generateHashValue(char const *str)
  69. {
  70.     uint32_t esi, eax, ebx, ecx;
  71.     ebx = ebx ^ ebx;
  72.     for(esi = 0; esi < strlen(str); ++esi)
  73.     {
  74.         ecx = str[esi];
  75.         eax = ebx;
  76.         eax = eax << 5;
  77.         ebx = ebx + eax;
  78.         ebx = ebx ^ ecx;
  79.     }
  80.     return ebx;
  81. }
  82.  
  83. enum COLORS {BLACK, DARK_BLUE, DARK_GREEN, DARK_CYAN, DARK_RED, DARK_MAGENTA, DARK_YELLOW,
  84.              GRAY, DARK_GRAY, BLUE, GREEN, CYAN, RED, MAGENTA, YELLOW, WHITE};
  85.  
  86. enum SHADER_TYPES {VERTEX_SHADER = 0x01, PIXEL_SHADER = 0x02};
  87.  
  88. typedef struct Shader
  89. {
  90.     uint8_t  type;
  91.     uint32_t hlsl_file;
  92.     uint32_t bin_file;
  93. } Shader;
  94.  
  95. int updateShaders(Shader **shaders, uint32_t num_new);
  96. int getNumShaders(FILE *file, uint32_t *num_vs, uint32_t *num_ps);
  97. int backupShaders(Shader const *shaders, uint32_t ofs, uint32_t num_vs, uint32_t num_ps);
  98. int getUniqueShaders(Shader **shaders, uint32_t num_new, uint32_t num_vs, uint32_t num_ps);
  99. int updateNumShaders(Shader const *shaders, uint32_t num_new, uint32_t *num_vs, uint32_t *num_ps);
  100. int sortShaders(void const *pa, void const *pb);
  101. int compileShaders(int argc, char const **argv);
  102. int updateShaderSize(char const *filename);
  103.  
  104. int main(int argc, char **argv)
  105. {
  106.     int i;
  107.  
  108.     Shader *shaders = 0;
  109.  
  110.     if(argc < 2)
  111.     {
  112.         printf("USAGE: shader_tool.exe <shader_name> <shader_name2> <shader_name3> ...\n");
  113.         colorPrint(YELLOW, "WARNING: The use of special characters in shader names will result in undefined behavior!\n");
  114.         return 0;
  115.     }
  116.  
  117.     shaders = malloc((argc - 1) * sizeof(Shader));
  118.     if(!isDefined(&shaders))
  119.     {
  120.         colorPrint(RED, "ERROR: Failed to allocate %u bytes of memory!\n", ((argc - 1) * sizeof(Shader)));
  121.         return 1;
  122.     }
  123.  
  124.     printf("#----------------------------------------------------------------------------#\n");
  125.     printf("|                  -- Call of Duty 4 - Shader Tool v0.1 --                   |\n");
  126.     printf("|                         Copyright (c) 2015 Otso O.                         |\n");
  127.     printf("#----------#----------------------------#------------------------------------#\n");
  128.     printf("| Hash     | Shader name for techniques | File name in raw\\shader_bin        |\n");
  129.     printf("#----------#----------------------------#------------------------------------#\n");
  130.     for(i = 0; i < (argc - 1); ++i)
  131.     {
  132.         int x;
  133.  
  134.         char const *arg = argv[i + 1];
  135.  
  136.         for(x = 1; x < argc; ++x)
  137.         {
  138.             if(strcmp(argv[x], arg) == 0 && x != (i + 1))
  139.             {
  140.                 free(shaders);
  141.                 printf("#----------#----------------------------#------------------------------------#\n");
  142.                 colorPrint(RED, "ERROR: Encountered a duplicate shader name '%s'!\n", arg);
  143.                 colorPrint(RED, "Remove the duplicate shader name from command line arguments and try again.\n");
  144.                 return 1;
  145.             }
  146.         }
  147.  
  148.         shaders[i].type      = 0;
  149.         shaders[i].hlsl_file = generateHashValue(arg);
  150.         shaders[i].bin_file  = 0xFFFFFFFF - swapByteOrder32(shaders[i].hlsl_file);
  151.         printf("| %.8X | %-24.24s%s | vs_3_0_%.8x or ps_3_0_%.8x |\n",
  152.                    swapByteOrder32(shaders[i].hlsl_file), arg, strlen(arg) > 24 ? ".." : "  ",
  153.                    shaders[i].bin_file, shaders[i].bin_file);
  154.     }
  155.     printf("#----------#----------------------------#------------------------------------#\n");
  156.  
  157.     qsort(shaders, (argc - 1), sizeof(Shader), sortShaders);
  158.     updateShaders(&shaders, (argc - 1));
  159.     free(shaders);
  160.  
  161.     compileShaders(argc, argv);
  162.  
  163. #ifdef _DEBUG
  164.     system("pause");
  165.     _CrtDumpMemoryLeaks();
  166. #endif // _DEBUG
  167.  
  168.     return 0;
  169. }
  170.  
  171. int updateShaders(Shader **shaders, uint32_t num_new)
  172. {
  173.     int i, j;
  174.  
  175.     FILE *file      = 0;
  176.     Shader *temp    = 0;
  177.     void *ptr       = 0;
  178.     uint32_t ofs    = num_new;
  179.     uint32_t num_vs = 0;
  180.     uint32_t num_ps = 0;
  181.     uint32_t total  = 0;
  182.     int count       = 0;
  183.  
  184.     printf("\nUpdating 'shader_names' file ...\n");
  185.     file = fopen("shader_names", "rb");
  186.     if(!isDefined(&file))
  187.     {
  188.         colorPrint(RED, "ERROR: Failed to open file 'shader_names' for reading!\n");
  189.         colorPrint(RED, "Make sure you are running shader_tool.exe in the raw\\shader_bin\\ directory.\n");
  190.         return 0;
  191.     }
  192.     if(!getNumShaders(file, &num_vs, &num_ps))
  193.     {
  194.         fclose(file);
  195.         return 0;
  196.     }
  197.  
  198.     total = (num_vs + num_ps + num_new);
  199.     temp = realloc(*shaders, total * sizeof(Shader));
  200.     if(!isDefined(&temp))
  201.     {
  202.         fclose(file);
  203.         colorPrint(RED, "ERROR: Failed to allocate %u bytes of memory!\n", total * sizeof(Shader));
  204.         return 0;
  205.     }
  206.    
  207.     *shaders = temp;
  208.     ptr = ((uint32_t)*shaders + (ofs * sizeof(Shader)));
  209.     memset(ptr, 0, ((num_vs + num_ps) * sizeof(Shader)));
  210.  
  211.     fseek(file, sizeof(uint32_t), SEEK_SET);
  212.     for(i = 0; i < (num_vs + num_ps); ++i)
  213.     {
  214.         if(i == num_vs)
  215.             fseek(file, sizeof(uint32_t), SEEK_CUR);
  216.        
  217.         if(i < num_vs)
  218.             (*shaders)[i + ofs].type = VERTEX_SHADER;
  219.         else
  220.             (*shaders)[i + ofs].type = PIXEL_SHADER;
  221.  
  222.         if(!fread(&(*shaders)[i + ofs].hlsl_file, 1, sizeof(uint32_t), file) || !fread(&(*shaders)[i + ofs].bin_file, 1, sizeof(uint32_t), file))
  223.         {
  224.             fclose(file);
  225.             colorPrint(RED, "ERROR: Failed to read shader #%d!\n", i);
  226.             return 0;
  227.         }
  228.     }
  229.  
  230.     fclose(file);
  231.     if(!backupShaders(*shaders, ofs, num_vs, num_ps))
  232.     {
  233.         colorPrint(RED, "ERROR: Failed to backup the current 'shader_names' file!\n");
  234.         return 0;
  235.     }
  236.  
  237.     file = fopen("shader_names", "wb");
  238.     if(!isDefined(&file))
  239.     {
  240.         colorPrint(RED, "ERROR: Failed to open file 'shader_names' for writing!\n");
  241.         colorPrint(RED, "Make sure you are running shader_tool.exe as administrator!\n");
  242.         return 0;
  243.     }
  244.  
  245.     count = getUniqueShaders(shaders, num_new, num_vs, num_ps);
  246.     printf("%d new shaders\n", count);
  247.     updateNumShaders(*shaders, num_new, &num_vs, &num_ps);
  248.  
  249.     fwrite(&num_vs, sizeof(uint32_t), 1, file);
  250.     for(i = 0; i < total; ++i)
  251.     {
  252.         if((*shaders)[i].type == VERTEX_SHADER)
  253.         {
  254.             for(j = 0; j < num_new; ++j)
  255.             {
  256.                 if((*shaders)[i].hlsl_file > (*shaders)[j].hlsl_file && (*shaders)[j].type == 0x00)
  257.                 {
  258.                     (*shaders)[j].type = 0xAA;
  259.                     fwrite(&(*shaders)[j].hlsl_file, sizeof(uint32_t), 1, file);
  260.                     fwrite(&(*shaders)[j].bin_file, sizeof(uint32_t), 1, file);
  261.                 }
  262.             }
  263.             fwrite(&(*shaders)[i].hlsl_file, sizeof(uint32_t), 1, file);
  264.             fwrite(&(*shaders)[i].bin_file, sizeof(uint32_t), 1, file);
  265.         } else
  266.         if((*shaders)[i].type == 0x00 && (*shaders)[i].hlsl_file < (*shaders)[num_new].hlsl_file)
  267.         {
  268.             (*shaders)[i].type = 0xAA;
  269.             fwrite(&(*shaders)[i].hlsl_file, sizeof(uint32_t), 1, file);
  270.             fwrite(&(*shaders)[i].bin_file, sizeof(uint32_t), 1, file);
  271.         }
  272.     }
  273.  
  274.     fwrite(&num_ps, sizeof(uint32_t), 1, file);
  275.     for(i = 0; i < total; ++i)
  276.     {
  277.         if((*shaders)[i].type == PIXEL_SHADER)
  278.         {
  279.             for(j = 0; j < num_new; ++j)
  280.             {
  281.                 if((*shaders)[i].hlsl_file > (*shaders)[j].hlsl_file && (*shaders)[j].type == 0xAA)
  282.                 {
  283.                     (*shaders)[j].type = 0xBB;
  284.                     fwrite(&(*shaders)[j].hlsl_file, sizeof(uint32_t), 1, file);
  285.                     fwrite(&(*shaders)[j].bin_file, sizeof(uint32_t), 1, file);
  286.                 }
  287.             }
  288.             fwrite(&(*shaders)[i].hlsl_file, sizeof(uint32_t), 1, file);
  289.             fwrite(&(*shaders)[i].bin_file, sizeof(uint32_t), 1, file);
  290.         } else
  291.         if((*shaders)[i].type == 0xAA && (*shaders)[i].hlsl_file < (*shaders)[num_vs].hlsl_file)
  292.         {
  293.             (*shaders)[i].type = 0xBB;
  294.             fwrite(&(*shaders)[i].hlsl_file, sizeof(uint32_t), 1, file);
  295.             fwrite(&(*shaders)[i].bin_file, sizeof(uint32_t), 1, file);
  296.         }
  297.     }
  298.  
  299.     fclose(file);
  300.     return count;
  301. }
  302.  
  303. int getNumShaders(FILE *file, uint32_t *num_vs, uint32_t *num_ps)
  304. {
  305.     uint32_t fsize = 0;
  306.  
  307.     fseek(file, 0, SEEK_END);
  308.     fsize = ftell(file);
  309.     fseek(file, 0, SEEK_SET);
  310.  
  311.     if(fsize == 0)
  312.     {
  313.         colorPrint(RED, "ERROR: File 'shader_names' is empty!\n");
  314.         colorPrint(RED, "Please restore the original 'shader_names' file and try again.\n");
  315.         return 0;
  316.     }
  317.     if(fread(num_vs, sizeof(uint32_t), 1, file))
  318.     {
  319.         if(fseek(file, 8 * (*num_vs) + sizeof(uint32_t), SEEK_SET) == 0 && fread(num_ps, sizeof(uint32_t), 1, file))
  320.         {
  321.             if(fsize == ((2 * sizeof(uint32_t)) + (((*num_vs) + (*num_ps)) * 8)))
  322.             {
  323.                 printf("%u vertex shaders\n%u pixel shaders\n", (*num_vs), (*num_ps));
  324.                 return 1;
  325.             }
  326.  
  327.             colorPrint(RED, "ERROR: File 'shader_names' is corrupt! Expected size of %u bytes, got %u bytes instead.\n",
  328.                       ((2 * sizeof(uint32_t)) + (((*num_vs) + (*num_ps)) * 8)), fsize);
  329.         } else
  330.             colorPrint(RED, "ERROR: Could not read the number of pixel shaders!\n");
  331.     } else
  332.         colorPrint(RED, "ERROR: Could not read the number of vertex shaders!\n");
  333.  
  334.     colorPrint(RED, "Please restore the original 'shader_names' file and try again.\n");
  335.     return 0;
  336. }
  337.  
  338. int backupShaders(Shader const *shaders, uint32_t ofs, uint32_t num_vs, uint32_t num_ps)
  339. {
  340.     int i;
  341.     time_t now;
  342.     struct tm *t;
  343.     char filename[64];
  344.  
  345.     FILE *file = 0;
  346.  
  347.     now = time(0);
  348.     t = localtime(&now);
  349.     strftime(filename, sizeof(filename), "backups\\shader_names_%d%m%y%H%M%S.bak", t);
  350.  
  351.     file = fopen(filename, "wb");
  352.     if(!isDefined(&file))
  353.     {
  354.         colorPrint(RED, "ERROR: Failed to create file '%s'!\n", filename);
  355.         colorPrint(RED, "Make sure you are running shader_tool.exe as administrator!\n");
  356.         return 0;
  357.     }
  358.  
  359.     fwrite(&num_vs, sizeof(uint32_t), 1, file);
  360.     for(i = 0; i < (num_vs + num_ps); ++i)
  361.     {
  362.         if(i == num_vs)
  363.             fwrite(&num_ps, sizeof(uint32_t), 1, file);
  364.  
  365.         if(!fwrite(&shaders[i + ofs].hlsl_file, sizeof(uint32_t), 1, file) || !fwrite(&shaders[i + ofs].bin_file, sizeof(uint32_t), 1, file))
  366.         {
  367.             colorPrint(RED, "ERROR: Failed to write shader #%d!\n", i);
  368.             fclose(file);
  369.             return 0;
  370.         }
  371.     }
  372.     fclose(file);
  373.     return 1;
  374. }
  375.  
  376. int getUniqueShaders(Shader **shaders, uint32_t num_new, uint32_t num_vs, uint32_t num_ps)
  377. {
  378.     int i, j;
  379.  
  380.     int uniques    = 0;
  381.     int duplicates = 0;
  382.  
  383.     for(i = 0; i < num_new; ++i)
  384.     {
  385.         for(j = 0; j < (num_vs + num_ps); ++j)
  386.         {
  387.             if((*shaders)[i].hlsl_file == (*shaders)[j + num_new].hlsl_file || (*shaders)[i].bin_file == (*shaders)[j + num_new].bin_file)
  388.             {
  389.                 (*shaders)[i].type = 0xFF;
  390.                 (*shaders)[i].hlsl_file = 0xDEADBEEF;
  391.                 (*shaders)[i].bin_file = 0xDEADBEEF;
  392.                 ++duplicates;
  393.             }
  394.         }
  395.     }
  396.     if(duplicates > 0)
  397.         colorPrint(YELLOW, "WARNING: %d of the new shaders already exist in 'shader_names' file!\n", duplicates);
  398.  
  399.     uniques = num_new - duplicates;
  400.     return uniques;
  401. }
  402.  
  403. int updateNumShaders(Shader const *shaders, uint32_t num_new, uint32_t *num_vs, uint32_t *num_ps)
  404. {
  405.     int i;
  406.  
  407.     for(i = 0; i < num_new; ++i)
  408.     {
  409.         if(shaders[i].type != 0xFF)
  410.         {
  411.             ++(*num_vs);
  412.             ++(*num_ps);
  413.         }
  414.     }
  415.     return 1;
  416. }
  417.  
  418. int sortShaders(void const *pa, void const *pb)
  419. {
  420.     Shader *a = (Shader*)pa;
  421.     Shader *b = (Shader*)pb;
  422.     return a->hlsl_file >= b->hlsl_file ? 1 : 0;
  423. }
  424.  
  425. int compileShaders(int argc, char const **argv)
  426. {
  427.     int i;
  428.  
  429.     printf("\nCompiling shaders with fxc.exe ...\n");
  430.     for(i = 0; i < (argc - 1); ++i)
  431.     {
  432.         char shader[32];
  433.         char cmd[256];
  434.  
  435.         char const *arg = argv[i + 1];
  436.         uint32_t bin_file = 0xFFFFFFFF - swapByteOrder32(generateHashValue(arg));
  437.  
  438.         sprintf(shader, "vs_3_0_%.8x", bin_file);
  439.         sprintf(cmd, "shader_src\\fxc.exe shader_src\\vs_3_0_%s.hlsl /T vs_3_0 /E vs_main /Fo vs_3_0_%.8x > nul", arg, bin_file);
  440.         system(cmd);
  441.         updateShaderSize(shader);
  442.  
  443.         sprintf(shader, "ps_3_0_%.8x", bin_file);
  444.         sprintf(cmd, "shader_src\\fxc.exe shader_src\\ps_3_0_%s.hlsl /T ps_3_0 /E ps_main /Fo ps_3_0_%.8x > nul", arg, bin_file);
  445.         system(cmd);
  446.         updateShaderSize(shader);
  447.     }
  448.  
  449.     return 1;
  450. }
  451.  
  452. int updateShaderSize(char const *filename)
  453. {
  454.     FILE *file = 0;
  455.  
  456.     file = fopen(filename, "rb");
  457.     if(isDefined(&file))
  458.     {
  459.         uint8_t *buffer;
  460.  
  461.         uint32_t fsize = 0;
  462.  
  463.         fseek(file, 0, SEEK_END);
  464.         fsize = ftell(file);
  465.         fseek(file, 0, SEEK_SET);
  466.  
  467.         buffer = malloc(fsize * sizeof(uint8_t));
  468.         if(isDefined(&buffer))
  469.         {
  470.             fread(buffer, sizeof(uint8_t), fsize, file);
  471.             fclose(file);
  472.  
  473.             fopen(filename, "wb");
  474.             if(isDefined(&file))
  475.             {
  476.                 fwrite(&fsize, sizeof(uint32_t), 1, file);
  477.                 fwrite(buffer, sizeof(uint8_t), fsize, file);
  478.                 printf("%s, %u bytes\n", filename, fsize);
  479.                 fclose(file);
  480.             } else {
  481.                 colorPrint(RED, "ERROR: Failed to open file '%s' for writing!\n", filename);
  482.                 colorPrint(RED, "Make sure you are running shader_tool.exe as administrator!\n");
  483.             }
  484.             free(buffer);
  485.         } else {
  486.             fclose(file);
  487.             colorPrint(RED, "ERROR: Failed to allocate %u bytes of memory!\n", fsize);
  488.         }
  489.     }
  490.     return 1;
  491. }
  492.  
  493. /*
  494. 00464EC0  /$ 55             PUSH EBP
  495. 00464EC1  |. 8BEC           MOV EBP,ESP
  496. 00464EC3  |. 53             PUSH EBX
  497. 00464EC4  |. 56             PUSH ESI
  498. 00464EC5  |. 57             PUSH EDI
  499. 00464EC6  |. 8B7D 08        MOV EDI,DWORD PTR SS:[EBP+8]
  500. 00464EC9  |. 33DB           XOR EBX,EBX
  501. 00464ECB  |. 381F           CMP BYTE PTR DS:[EDI],BL
  502. 00464ECD  |. 8BF7           MOV ESI,EDI
  503. 00464ECF  |. 74 5B          JE SHORT linker_p.00464F2C
  504. 00464ED1  |> 8A06           /MOV AL,BYTE PTR DS:[ESI]
  505. 00464ED3  |. 3C 41          |CMP AL,41
  506. 00464ED5  |. 7C 20          |JL SHORT linker_p.00464EF7
  507. 00464ED7  |. 3C 5A          |CMP AL,5A
  508. 00464ED9  |. 7F 1C          |JG SHORT linker_p.00464EF7
  509. 00464EDB  |. 57             |PUSH EDI                                ; /Arg6
  510. 00464EDC  |. 68 9C044F00    |PUSH linker_p.004F049C                  ; |Arg5 = 004F049C ASCII "(*pos < 'A' || *pos > 'Z')"
  511. 00464EE1  |. 68 EC554D00    |PUSH linker_p.004D55EC                  ; |Arg4 = 004D55EC ASCII "%s
  512.         (name) = %s"
  513. 00464EE6  |. 6A 00          |PUSH 0                                  ; |Arg3 = 00000000
  514. 00464EE8  |. 6A 2A          |PUSH 2A                                 ; |Arg2 = 0000002A
  515. 00464EEA  |. 68 5C044F00    |PUSH linker_p.004F045C                  ; |Arg1 = 004F045C ASCII "C:\trees\cod3-pc\cod3-modtools\cod3src\src\gfx_d3d\r_utils.cpp"
  516. 00464EEF  |. E8 AC970200    |CALL linker_p.0048E6A0                  ; \linker_p.0048E6A0
  517. 00464EF4  |. 83C4 18        |ADD ESP,18
  518. 00464EF7  |> 803E 5C        |CMP BYTE PTR DS:[ESI],5C
  519. 00464EFA  |. 75 1C          |JNZ SHORT linker_p.00464F18
  520. 00464EFC  |. 57             |PUSH EDI                                ; /Arg6
  521. 00464EFD  |. 68 3C044F00    |PUSH linker_p.004F043C                  ; |Arg5 = 004F043C ASCII "(*pos != '\\' || *pos == '/')"
  522. 00464F02  |. 68 EC554D00    |PUSH linker_p.004D55EC                  ; |Arg4 = 004D55EC ASCII "%s
  523.         (name) = %s"
  524. 00464F07  |. 6A 00          |PUSH 0                                  ; |Arg3 = 00000000
  525. 00464F09  |. 6A 2B          |PUSH 2B                                 ; |Arg2 = 0000002B
  526. 00464F0B  |. 68 5C044F00    |PUSH linker_p.004F045C                  ; |Arg1 = 004F045C ASCII "C:\trees\cod3-pc\cod3-modtools\cod3src\src\gfx_d3d\r_utils.cpp"
  527. 00464F10  |. E8 8B970200    |CALL linker_p.0048E6A0                  ; \linker_p.0048E6A0
  528. 00464F15  |. 83C4 18        |ADD ESP,18
  529. 00464F18  |> 0FBE0E         |MOVSX ECX,BYTE PTR DS:[ESI]
  530. 00464F1B  |. 8BC3           |MOV EAX,EBX
  531. 00464F1D  |. C1E0 05        |SHL EAX,5
  532. 00464F20  |. 03D8           |ADD EBX,EAX
  533. 00464F22  |. 83C6 01        |ADD ESI,1
  534. 00464F25  |. 33D9           |XOR EBX,ECX
  535. 00464F27  |. 803E 00        |CMP BYTE PTR DS:[ESI],0
  536. 00464F2A  |.^75 A5          \JNZ SHORT linker_p.00464ED1
  537. 00464F2C  |> 5F             POP EDI
  538. 00464F2D  |. 5E             POP ESI
  539. 00464F2E  |. 8BC3           MOV EAX,EBX
  540. 00464F30  |. 5B             POP EBX
  541. 00464F31  |. 5D             POP EBP
  542. 00464F32  \. C3             RETN
  543. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement