Subversion Repositories Games.Carmageddon

Rev

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

  1. #include "pratcam.h"
  2. #include "brender/brender.h"
  3. #include "displays.h"
  4. #include "errors.h"
  5. #include "flicplay.h"
  6. #include "globvars.h"
  7. #include "globvrpb.h"
  8. #include "grafdata.h"
  9. #include "graphics.h"
  10. #include "harness/trace.h"
  11. #include "input.h"
  12. #include "loading.h"
  13. #include "pd/sys.h"
  14. #include "sound.h"
  15. #include "utility.h"
  16. #include <stdlib.h>
  17.  
  18. tS3_sound_tag gWhirr_noise = 0;
  19. tFlic_descriptor gPrat_flic;
  20. tPrat_sequence* gPratcam_sequences;
  21. tPrat_flic_spec* gPratcam_flics;
  22. int gCurrent_pratcam_chunk;
  23. int gPending_ambient_prat;
  24. int gCurrent_pratcam_index;
  25. br_pixelmap* gPrat_buffer;
  26. int gNumber_of_prat_sequences;
  27. int gNumber_of_prat_flics;
  28. tU32 gLast_pratcam_frame_time;
  29. int gCurrent_pratcam_precedence;
  30. int gCurrent_ambient_prat_sequence;
  31. int gCurrent_pratcam_alternative;
  32.  
  33. // IDA: int __cdecl PratcamGetCurrent()
  34. int PratcamGetCurrent(void) {
  35.     LOG_TRACE("()");
  36.  
  37.     return gCurrent_pratcam_index;
  38. }
  39.  
  40. // IDA: int __cdecl PratcamGetAmbient()
  41. int PratcamGetAmbient(void) {
  42.     LOG_TRACE("()");
  43.  
  44.     return gCurrent_ambient_prat_sequence;
  45. }
  46.  
  47. // IDA: int __cdecl PratcamGetPending()
  48. int PratcamGetPending(void) {
  49.     LOG_TRACE("()");
  50.  
  51.     return gPending_ambient_prat;
  52. }
  53.  
  54. // IDA: void __cdecl TogglePratcam()
  55. void TogglePratcam(void) {
  56.     tU32 the_time;
  57.     tU32 time_diff;
  58.     LOG_TRACE("()");
  59.  
  60.     if (gAusterity_mode) {
  61.         NewTextHeadupSlot(4, 0, 1000, -4, GetMiscString(kMiscString_NOT_ENOUGH_MEMORY));
  62.     } else {
  63.         if (gWhirr_noise == 0 || !DRS3SoundStillPlaying(gWhirr_noise)) {
  64.             DRS3StopSound(gWhirr_noise);
  65.             gWhirr_noise = DRS3StartSoundNoPiping(gCar_outlet, 1000);
  66.             DRS3ChangePitchSpeed(gWhirr_noise, 19660);
  67.         }
  68.         the_time = GetTotalTime();
  69.         gProgram_state.prat_cam_on = !gProgram_state.prat_cam_on;
  70.         time_diff = the_time - gProgram_state.pratcam_move_start;
  71.         gProgram_state.pratcam_move_start = the_time;
  72.         if (time_diff <= 400) {
  73.             gProgram_state.pratcam_move_start = the_time - 400 + time_diff;
  74.         }
  75.     }
  76. }
  77.  
  78. // IDA: void __usercall LoadPratcam(char *pFolder_name@<EAX>)
  79. void LoadPratcam(char* pFolder_name) {
  80.     FILE* f;
  81.     FILE* g;
  82.     tPath_name the_path;
  83.     int i;
  84.     int j;
  85.     int k;
  86.     int l;
  87.     char s[256];
  88.     char folder_path[256];
  89.     char* str;
  90.     char num_str[256];
  91.     LOG_TRACE("(\"%s\")", pFolder_name);
  92.  
  93.     if (gAusterity_mode) {
  94.         return;
  95.     }
  96.     PathCat(folder_path, gApplication_path, gGraf_specs[gGraf_spec_index].data_dir_name);
  97.     PathCat(folder_path, folder_path, "PRATCAM");
  98.     PathCat(folder_path, folder_path, pFolder_name);
  99.     PathCat(the_path, folder_path, "PRATCAM.TXT");
  100.     f = DRfopen(the_path, "rt");
  101.     if (f == NULL) {
  102.         FatalError(kFatalError_OpenPratCamTextFile);
  103.     }
  104.     GetALineAndDontArgue(f, s);
  105.     str = strtok(s, "\t ,/");
  106.     sscanf(str, "%d", &gNumber_of_prat_flics);
  107.     gPratcam_flics = BrMemAllocate(gNumber_of_prat_flics * sizeof(tPrat_flic_spec), kMem_pratcam_flic_array);
  108.     for (i = 0; i < gNumber_of_prat_flics; i++) {
  109.         PossibleService();
  110.         GetALineAndDontArgue(f, s);
  111.         if (strcmp(s, "END") == 0) {
  112.             FatalError(kFatalError_TooFewFlicSpecsInPratCamFile);
  113.         }
  114.         str = strtok(s, "\t ,/");
  115.         PathCat(the_path, folder_path, str);
  116.         g = DRfopen(the_path, "rb");
  117.         if (g == NULL) {
  118.             FatalError(kFatalError_OpenPratCamFlicFile_S, str);
  119.         }
  120.         gPratcam_flics[i].data_length = GetFileLength(g);
  121.         gPratcam_flics[i].data = BrMemAllocate(gPratcam_flics[i].data_length, kMem_pratcam_flic_data);
  122.         if (gPratcam_flics[i].data == NULL) {
  123.             FatalError(kFatalError_AllocateMemoryPratCamFlicFile);
  124.         }
  125.         fread(gPratcam_flics[i].data, 1, gPratcam_flics[i].data_length, g);
  126.         fclose(g);
  127.     }
  128.     GetALineAndDontArgue(f, s);
  129.     if (strcmp(s, "END") != 0) {
  130.         FatalError(kFatalError_TooManyFlicSpecsInPratCamTextFIle);
  131.     }
  132.     GetALineAndDontArgue(f, s);
  133.     str = strtok(s, "\t ,/");
  134.     sscanf(str, "%d", &gNumber_of_prat_sequences);
  135.     gPratcam_sequences = BrMemAllocate(gNumber_of_prat_sequences * sizeof(tPrat_sequence), kMem_pratcam_sequence_array);
  136.     for (i = 0; i < gNumber_of_prat_sequences; i++) {
  137.         PossibleService();
  138.         sprintf(num_str, "%d", i);
  139.         GetALineAndDontArgue(f, s);
  140.         if (strcmp(s, "END") == 0) {
  141.             FatalError(kFatalError_TooFewSequencesInPratCamTextFile);
  142.         }
  143.         str = strtok(s, "\t ,/");
  144.         sscanf(str, "%d", &gPratcam_sequences[i].precedence);
  145.         gPratcam_sequences[i].repeat_chunk = GetAnInt(f);
  146.         gPratcam_sequences[i].number_of_chunks = GetAnInt(f);
  147.         if (gPratcam_sequences[i].number_of_chunks > COUNT_OF(gPratcam_sequences[i].chunks)) {
  148.             FatalError(kFatalError_PratCamSequenceTooManyChunks_S, num_str);
  149.         }
  150.         for (j = 0; j < gPratcam_sequences[i].number_of_chunks; j++) {
  151.             GetALineAndDontArgue(f, s);
  152.             str = strtok(s, "\t ,/");
  153.             sscanf(str, "%d", &gPratcam_sequences[i].chunks[j].number_of_alternatives);
  154.             if (gPratcam_sequences[i].chunks[j].number_of_alternatives > COUNT_OF(gPratcam_sequences[i].chunks[j].alternatives)) {
  155.                 FatalError(kFatalError_PratCamSequenceTooManyAlternatives_S, num_str);
  156.             }
  157.             for (k = 0; k < gPratcam_sequences[i].chunks[j].number_of_alternatives; k++) {
  158.                 GetALineAndDontArgue(f, s);
  159.                 str = strtok(s, "\t ,/");
  160.                 sscanf(str, "%d", &gPratcam_sequences[i].chunks[j].alternatives[k].ref);
  161.                 str = strtok(NULL, "\t ,/");
  162.                 sscanf(str, "%d", &gPratcam_sequences[i].chunks[j].alternatives[k].chance);
  163.                 str = strtok(NULL, "\t ,/");
  164.                 sscanf(str, "%d", &gPratcam_sequences[i].chunks[j].alternatives[k].sound_chance);
  165.                 if (gPratcam_sequences[i].chunks[j].alternatives[k].sound_chance > 0) {
  166.                     str = strtok(NULL, "\t ,/");
  167.                     sscanf(str, "%d", &gPratcam_sequences[i].chunks[j].alternatives[k].number_of_sounds);
  168.                     if (gPratcam_sequences[i].chunks[j].alternatives[k].number_of_sounds > COUNT_OF(gPratcam_sequences[i].chunks[j].alternatives[k].sound_ids)) {
  169.                         FatalError(kFatalError_PratCamSequenceTooManySounds_S, num_str);
  170.                     }
  171.                     for (l = 0; l < gPratcam_sequences[i].chunks[j].alternatives[k].number_of_sounds; l++) {
  172.                         str = strtok(NULL, "\t ,/");
  173.                         sscanf(str, "%d", &gPratcam_sequences[i].chunks[j].alternatives[k].sound_ids[l]);
  174.                         DRS3LoadSound(gPratcam_sequences[i].chunks[j].alternatives[k].sound_ids[l]);
  175.                     }
  176.                 }
  177.             }
  178.         }
  179.     }
  180.     GetALineAndDontArgue(f, s);
  181.     if (strcmp(s, "END") != 0) {
  182.         FatalError(kFatalError_TooManySequencesInPratCamTextFile);
  183.     }
  184.     fclose(f);
  185. }
  186.  
  187. // IDA: void __cdecl NextPratcamChunk()
  188. void NextPratcamChunk(void) {
  189.     int i;
  190.     int random_number;
  191.     int count;
  192.     tPrat_alternative* current_alternative;
  193.     LOG_TRACE("()");
  194.  
  195.     if (gCurrent_pratcam_index == -1) {
  196.         gCurrent_pratcam_index = gCurrent_ambient_prat_sequence;
  197.     } else {
  198.         EndFlic(&gPrat_flic);
  199.     }
  200.     count = gCurrent_pratcam_chunk;
  201.     gCurrent_pratcam_chunk++;
  202.     if (gPratcam_sequences[gCurrent_pratcam_index].number_of_chunks <= count) {
  203.         if (gPending_ambient_prat == -1) {
  204.             ChangeAmbientPratcamNow(gCurrent_ambient_prat_sequence, gPratcam_sequences[gCurrent_pratcam_index].repeat_chunk);
  205.         } else {
  206.             ChangeAmbientPratcamNow(gPending_ambient_prat, 0);
  207.         }
  208.     } else {
  209.         gLast_pratcam_frame_time = 0;
  210.         random_number = IRandomBetween(0, 99);
  211.         for (i = 0; i < gPratcam_sequences[gCurrent_pratcam_index].chunks[gCurrent_pratcam_chunk].number_of_alternatives; i++) {
  212.             current_alternative = &gPratcam_sequences[gCurrent_pratcam_index].chunks[gCurrent_pratcam_chunk].alternatives[i];
  213.             random_number -= current_alternative->chance;
  214.             if (random_number <= 0) {
  215.                 gCurrent_pratcam_alternative = i;
  216.                 gPrat_flic.data_start = NULL;
  217.                 StartFlic(NULL, -1, &gPrat_flic, gPratcam_flics[current_alternative->ref].data_length,
  218.                     (tS8*)gPratcam_flics[current_alternative->ref].data, gPrat_buffer, 0, 0, 0);
  219.                 if (current_alternative->sound_chance == 0) {
  220.                     return;
  221.                 }
  222.                 if (!PercentageChance(current_alternative->sound_chance)) {
  223.                     return;
  224.                 }
  225.                 if (gCurrent_pratcam_precedence == 0 && DRS3OutletSoundsPlaying(gDriver_outlet)) {
  226.                     return;
  227.                 }
  228.                 DRS3StartSound(gDriver_outlet, current_alternative->sound_ids[IRandomBetween(0, current_alternative->number_of_sounds - 1)]);
  229.                 return;
  230.             }
  231.         }
  232.         NextPratcamChunk();
  233.     }
  234. }
  235.  
  236. // IDA: void __usercall NewPratcamSequence(int pSequence_index@<EAX>, int pStart_chunk@<EDX>)
  237. void NewPratcamSequence(int pSequence_index, int pStart_chunk) {
  238.     LOG_TRACE("(%d, %d)", pSequence_index, pStart_chunk);
  239.  
  240.     gCurrent_pratcam_precedence = gPratcam_sequences[pSequence_index].precedence;
  241.     gCurrent_pratcam_index = pSequence_index;
  242.     gCurrent_pratcam_chunk = pStart_chunk - 1;
  243.     NextPratcamChunk();
  244. }
  245.  
  246. // IDA: void __usercall ChangeAmbientPratcamNow(int pIndex@<EAX>, int pStart_chunk@<EDX>)
  247. void ChangeAmbientPratcamNow(int pIndex, int pStart_chunk) {
  248.     LOG_TRACE("(%d, %d)", pIndex, pStart_chunk);
  249.  
  250.     gCurrent_ambient_prat_sequence = pIndex;
  251.     gPending_ambient_prat = -1;
  252.     NewPratcamSequence(pIndex, pStart_chunk);
  253. }
  254.  
  255. // IDA: void __usercall ChangeAmbientPratcam(int pIndex@<EAX>)
  256. void ChangeAmbientPratcam(int pIndex) {
  257.     LOG_TRACE("(%d)", pIndex);
  258.  
  259.     if (gRace_finished) {
  260.         return;
  261.     }
  262.     if (gInterface_within_race_mode) {
  263.         return;
  264.     }
  265.     if (pIndex == gCurrent_ambient_prat_sequence) {
  266.         return;
  267.     }
  268.     if (!gProgram_state.prat_cam_on) {
  269.         return;
  270.     }
  271.  
  272.     if (gCurrent_pratcam_index == -1) {
  273.         ChangeAmbientPratcamNow(pIndex, 0);
  274.     } else {
  275.         gPending_ambient_prat = pIndex;
  276.     }
  277. }
  278.  
  279. // IDA: void __usercall PratcamEventNow(int pIndex@<EAX>)
  280. void PratcamEventNow(int pIndex) {
  281.     LOG_TRACE("(%d)", pIndex);
  282.  
  283.     NewPratcamSequence(pIndex, 0);
  284.     gPending_ambient_prat = -1;
  285. }
  286.  
  287. // IDA: void __usercall PratcamEvent(int pIndex@<EAX>)
  288. void PratcamEvent(int pIndex) {
  289.     LOG_TRACE("(%d)", pIndex);
  290.  
  291.     if (gRace_finished) {
  292.         return;
  293.     }
  294.     if (gInterface_within_race_mode) {
  295.         return;
  296.     }
  297. #if defined(DETHRACE_FIX_BUGS)
  298.     // In low memory mode, `gPratcam_sequences`is not allocated and thus unsafe to access
  299.     if (gAusterity_mode) {
  300.         return;
  301.     }
  302. #endif
  303.     if (gPratcam_sequences[pIndex].precedence <= gCurrent_pratcam_precedence) {
  304.         return;
  305.     }
  306.     if (!gProgram_state.prat_cam_on) {
  307.         return;
  308.     }
  309.     PratcamEventNow(pIndex);
  310. }
  311.  
  312. // IDA: int __cdecl HighResPratBufferWidth()
  313. int HighResPratBufferWidth(void) {
  314.     //int prat_width; // Pierre-Marie Baty -- unused variable
  315.     LOG_TRACE("()");
  316.     NOT_IMPLEMENTED();
  317. }
  318.  
  319. // IDA: int __cdecl HighResPratBufferHeight()
  320. int HighResPratBufferHeight(void) {
  321.     //int prat_height; // Pierre-Marie Baty -- unused variable
  322.     LOG_TRACE("()");
  323.     NOT_IMPLEMENTED();
  324. }
  325.  
  326. // IDA: void __cdecl InitPratcam()
  327. void InitPratcam(void) {
  328.     void* the_pixels;
  329.     LOG_TRACE("()");
  330.  
  331.     if (gAusterity_mode) {
  332.         return;
  333.     }
  334.     gWhirr_noise = 0;
  335.     gPrat_flic.data = NULL;
  336.     gCurrent_ambient_prat_sequence = -1;
  337.     switch (gGraf_data_index) {
  338.     case 0:
  339.         the_pixels = BrMemAllocate(52 * 46, kMem_pratcam_pixelmap);
  340.         break;
  341.     case 1:
  342.         the_pixels = BrMemAllocate(104 * 110, kMem_pratcam_pixelmap);
  343.         break;
  344.     default:
  345.         TELL_ME_IF_WE_PASS_THIS_WAY();
  346.     }
  347.     if (gScreen->row_bytes < 0) {
  348.         BrFatal("C:\\Msdev\\Projects\\DethRace\\Pratcam.c", 409, "Bruce bug at line %d, file C:\\Msdev\\Projects\\DethRace\\Pratcam.c", 409);
  349.     }
  350.     switch (gGraf_data_index) {
  351.     case 0:
  352.         gPrat_buffer = DRPixelmapAllocate(gScreen->type, 52, 46, the_pixels, 0);
  353.         break;
  354.     case 1:
  355.         gPrat_buffer = DRPixelmapAllocate(gScreen->type, 104, 110, the_pixels, 0);
  356.         break;
  357.     default:
  358.         TELL_ME_IF_WE_PASS_THIS_WAY();
  359.     }
  360.     gCurrent_pratcam_index = -1;
  361.     gPending_ambient_prat = -1;
  362.     gCurrent_pratcam_precedence = 0;
  363.     if (gNet_mode == eNet_mode_none) {
  364.         if (gProgram_state.frank_or_anniness == eFrankie) {
  365.             LoadPratcam("FRANK");
  366.         } else {
  367.             LoadPratcam("ANNIE");
  368.         }
  369.     } else if (gNet_players[gThis_net_player_index].car_index == 1 || gNet_players[gThis_net_player_index].car_index > 34) {
  370.         LoadPratcam("ANNIE");
  371.     } else {
  372.         LoadPratcam("FRANK");
  373.     }
  374. }
  375.  
  376. // IDA: void __cdecl DisposePratcam()
  377. void DisposePratcam(void) {
  378.     int i;
  379.     int j;
  380.     int k;
  381.     int l;
  382.     LOG_TRACE("()");
  383.  
  384.     if (gAusterity_mode) {
  385.         return;
  386.     }
  387.     if (gWhirr_noise != 0) {
  388.         DRS3StopSound(gWhirr_noise);
  389.         gWhirr_noise = 0;
  390.     }
  391.     if (gCurrent_pratcam_index != -1) {
  392.         EndFlic(&gPrat_flic);
  393.     }
  394.     BrMemFree(gPrat_buffer->pixels);
  395.     BrPixelmapFree(gPrat_buffer);
  396.     for (i = 0; i < gNumber_of_prat_flics; i++) {
  397.         BrMemFree(gPratcam_flics[i].data);
  398.     }
  399.     for (i = 0; i < gNumber_of_prat_sequences; i++) {
  400.         for (j = 0; j < gPratcam_sequences[i].number_of_chunks; j++) {
  401.             for (k = 0; k < gPratcam_sequences[i].chunks[j].number_of_alternatives; k++) {
  402.                 for (l = 0; l < gPratcam_sequences[i].chunks[j].alternatives[k].number_of_sounds; l++) {
  403.                     DRS3ReleaseSound(gPratcam_sequences[i].chunks[j].alternatives[k].sound_ids[l]);
  404.                 }
  405.             }
  406.         }
  407.     }
  408.     BrMemFree(gPratcam_flics);
  409.     BrMemFree(gPratcam_sequences);
  410. }
  411.  
  412. // IDA: void __usercall DoPratcam(tU32 pThe_time@<EAX>)
  413. void DoPratcam(tU32 pThe_time) {
  414.     tU32 i; // Pierre-Marie Baty -- fixed type
  415.     int offset;
  416.     int y_offset;
  417.     int top_border_height;
  418.     int prat_cam_move_width;
  419.     int right_hand;
  420.     tU32 time_diff;
  421.     tU32 old_last_time;
  422.     //br_pixelmap* the_image; // Pierre-Marie Baty -- unused variable
  423.     br_pixelmap* left_image;
  424.     br_pixelmap* right_image;
  425.     LOG_TRACE("(%d)", pThe_time);
  426.  
  427.     if (gAusterity_mode) {
  428.         return;
  429.     }
  430.     left_image = gProgram_state.current_car.prat_cam_right;
  431.     right_image = gProgram_state.current_car.prat_cam_left;
  432.     y_offset = (gNet_mode == eNet_mode_none) ? 0 : gCurrent_graf_data->net_head_box_bot + 1;
  433.  
  434.     right_hand = gProgram_state.current_car.prat_left <= gBack_screen->width / 2;
  435.     if (right_hand) {
  436.         prat_cam_move_width = gProgram_state.current_car.prat_right + (right_image != NULL ? right_image->width : 0);
  437.     } else {
  438.         prat_cam_move_width = gBack_screen->width - gProgram_state.current_car.prat_left + (left_image != NULL ? left_image->width : 0);
  439.     }
  440.     time_diff = pThe_time - gProgram_state.pratcam_move_start;
  441.     if (time_diff <= 400) {
  442.         offset = prat_cam_move_width * time_diff / (float)400;
  443.     } else {
  444.         if (gWhirr_noise) {
  445.             DRS3StopSound(gWhirr_noise);
  446.             gWhirr_noise = 0;
  447.         }
  448.         if (!gProgram_state.prat_cam_on) {
  449.             gCurrent_pratcam_index = -1;
  450.             gCurrent_pratcam_precedence = 0;
  451.             gPending_ambient_prat = -1;
  452.             return;
  453.         }
  454.         offset = prat_cam_move_width;
  455.     }
  456.  
  457.     old_last_time = gLast_pratcam_frame_time;
  458.     if (gProgram_state.prat_cam_on) {
  459.         offset = prat_cam_move_width - offset;
  460.     }
  461.     if (right_hand) {
  462.         offset = -offset;
  463.     }
  464.     DontLetFlicFuckWithPalettes();
  465.     DisableTranslationText();
  466.     for (i = 0; i < (old_last_time != 0 ? ((pThe_time - old_last_time) / gPrat_flic.frame_period) : 1); i++) {
  467.         if (PlayNextFlicFrame(&gPrat_flic)) {
  468.             NextPratcamChunk();
  469.             break;
  470.         }
  471.         gLast_pratcam_frame_time = pThe_time;
  472.     }
  473.     EnableTranslationText();
  474.     LetFlicFuckWithPalettes();
  475.     BrPixelmapRectangleCopy(gBack_screen,
  476.         gProgram_state.current_car.prat_left + offset,
  477.         gProgram_state.current_car.prat_top + y_offset,
  478.         gPrat_buffer,
  479.         0, 0,
  480.         gPrat_buffer->width, gPrat_buffer->height);
  481.     if (gProgram_state.current_car.prat_cam_top != NULL) {
  482.         top_border_height = gProgram_state.current_car.prat_cam_top->height;
  483.         DRPixelmapRectangleMaskedCopy(
  484.             gBack_screen,
  485.             gProgram_state.current_car.prat_left + offset,
  486.             gProgram_state.current_car.prat_top - top_border_height + y_offset,
  487.             gProgram_state.current_car.prat_cam_top,
  488.             0, 0,
  489.             gProgram_state.current_car.prat_cam_top->width,
  490.             gProgram_state.current_car.prat_cam_top->height);
  491.     } else {
  492.         top_border_height = 0;
  493.     }
  494.     if (right_image != NULL) {
  495.         DRPixelmapRectangleMaskedCopy(gBack_screen,
  496.             gProgram_state.current_car.prat_left - right_image->width + offset,
  497.             gProgram_state.current_car.prat_top - top_border_height + y_offset,
  498.             right_image,
  499.             0, 0,
  500.             right_image->width, right_image->height);
  501.     }
  502.     if (left_image != NULL) {
  503.         DRPixelmapRectangleMaskedCopy(
  504.             gBack_screen,
  505.             gProgram_state.current_car.prat_right + offset - 1,
  506.             gProgram_state.current_car.prat_top - top_border_height - 1 + y_offset,
  507.             left_image,
  508.             0, 0,
  509.             left_image->width, left_image->height);
  510.     }
  511.     if (gProgram_state.current_car.prat_cam_bottom != NULL) {
  512.         DRPixelmapRectangleMaskedCopy(
  513.             gBack_screen,
  514.             gProgram_state.current_car.prat_left + offset,
  515.             gProgram_state.current_car.prat_bottom + y_offset,
  516.             gProgram_state.current_car.prat_cam_bottom,
  517.             0, 0,
  518.             gProgram_state.current_car.prat_cam_bottom->width,
  519.             gProgram_state.current_car.prat_cam_bottom->height);
  520.     }
  521. }
  522.  
  523. // IDA: void __usercall TestPratCam(int pIndex@<EAX>)
  524. void TestPratCam(int pIndex) {
  525.     LOG_TRACE("(%d)", pIndex);
  526.  
  527.     if (PDKeyDown(KEY_CTRL_ANY)) {
  528.         pIndex += 40;
  529.     }
  530.     if (PDKeyDown(KEY_ALT_ANY)) {
  531.         pIndex += 20;
  532.     }
  533.     if (PDKeyDown(KEY_SHIFT_ANY)) {
  534.         pIndex += 10;
  535.     }
  536.     PratcamEventNow(pIndex);
  537. }
  538.  
  539. // IDA: void __cdecl PratCam0()
  540. void PratCam0(void) {
  541.     LOG_TRACE("()");
  542.  
  543.     TestPratCam(0);
  544. }
  545.  
  546. // IDA: void __cdecl PratCam1()
  547. void PratCam1(void) {
  548.     LOG_TRACE("()");
  549.  
  550.     TestPratCam(1);
  551. }
  552.  
  553. // IDA: void __cdecl PratCam2()
  554. void PratCam2(void) {
  555.     LOG_TRACE("()");
  556.  
  557.     TestPratCam(2);
  558. }
  559.  
  560. // IDA: void __cdecl PratCam3()
  561. void PratCam3(void) {
  562.     LOG_TRACE("()");
  563.  
  564.     TestPratCam(3);
  565. }
  566.  
  567. // IDA: void __cdecl PratCam4()
  568. void PratCam4(void) {
  569.     LOG_TRACE("()");
  570.  
  571.     TestPratCam(4);
  572. }
  573.  
  574. // IDA: void __cdecl PratCam5()
  575. void PratCam5(void) {
  576.     LOG_TRACE("()");
  577.  
  578.     TestPratCam(5);
  579. }
  580.  
  581. // IDA: void __cdecl PratCam6()
  582. void PratCam6(void) {
  583.     LOG_TRACE("()");
  584.  
  585.     TestPratCam(6);
  586. }
  587.  
  588. // IDA: void __cdecl PratCam7()
  589. void PratCam7(void) {
  590.     LOG_TRACE("()");
  591.  
  592.     TestPratCam(7);
  593. }
  594.  
  595. // IDA: void __cdecl PratCam8()
  596. void PratCam8(void) {
  597.     LOG_TRACE("()");
  598.  
  599.     TestPratCam(8);
  600. }
  601.  
  602. // IDA: void __cdecl PratCam9()
  603. void PratCam9(void) {
  604.     LOG_TRACE("()");
  605.  
  606.     TestPratCam(9);
  607. }
  608.