Advertisement
Guest User

readVCC.C

a guest
Jul 21st, 2014
1,083
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 2.97 KB | None | 0 0
  1. /*
  2.   Filename: readVCC.c
  3.     Author: Jeremy L. Crabtree <JeremyLC@GMail.com>
  4.       Date: 20 July, 2014
  5.  
  6.    Purpose: This will read and extract the VOC/ACMP files embedded in
  7.             the VCC container files used in Interplay's
  8.             "Star Trek: Judgement Rites".  Decompressing the ACMP audio
  9.             is a job for someone less lazy than me.
  10.  
  11.      Notes: Output files are dumped in pwd because I'm lazy. Run this from
  12.             where you want the output.
  13.  
  14.    License: If you re-use this code (pity you!) give me credit, thanks! :)
  15. */
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <errno.h>
  21.  
  22. /* The master record is in the same format as the individual file records */
  23. typedef struct vccRecord
  24. {
  25.   unsigned char header[9];
  26.   unsigned int offset, size;
  27. } vccRecord;
  28.  
  29. int read4byteint(FILE * inFile)
  30. {
  31.   /* Read a 4 byte int that is stored LSB..MSB */
  32.   unsigned char value[4];
  33.   fread(value, 1, 4, inFile);
  34.   return value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] << 24);
  35. }
  36.  
  37. void readRecord(FILE * inFile, vccRecord *rec)
  38. {
  39.   /*
  40.     Read a 16 byte record.
  41.     The first 8 bytes are text.
  42.     The next 8 bytes are two 4-byte little-endian ints
  43.   */
  44.   rec->header[8] = '\x0'; //8 byte headers aren't null-terminated.
  45.   fread(rec->header, 1, 8, inFile);
  46.   rec->offset = read4byteint(inFile);
  47.   rec->size = read4byteint(inFile);
  48. }
  49.  
  50. void extractFile(vccRecord newFile, FILE *inFile)
  51. {
  52.   /* Extract a VOC/ACMP from the main VCC file */
  53.   unsigned int savedPos;
  54.   unsigned char *fBuf;
  55.   FILE *outFile;
  56.  
  57.   if(outFile = fopen(newFile.header, "wb"))
  58.     {
  59.       savedPos = ftell(inFile);
  60.       fseek(inFile, newFile.offset, SEEK_SET);
  61.       fBuf = malloc(newFile.size);
  62.       fread(fBuf, 1, newFile.size, inFile);
  63.       fwrite(fBuf, 1, newFile.size, outFile);
  64.       free(fBuf);
  65.       fclose(outFile);
  66.       fseek(inFile, savedPos, SEEK_SET);
  67.     }
  68.   else
  69.     {
  70.       printf("Error %d opening %s for output\n", errno, newFile.header);
  71.       exit(errno);
  72.     }
  73. }
  74.  
  75. int main(argc, argv)
  76.      int argc;
  77.      char **argv;
  78. {
  79.   /* The rest of this should be self explanatory */
  80.   unsigned int fileNum;
  81.   vccRecord vccHead , fileRec;
  82.   FILE *vccFile;
  83.  
  84.   if (2 == argc)
  85.     if (vccFile = fopen(argv[1], "rb"))
  86.         {
  87.           readRecord(vccFile, &vccHead);
  88.           if (strcmp(vccHead.header, "VOCFILES"))
  89.             {
  90.               fclose(vccFile);
  91.               printf("Error %s is not a VCC file.\n", argv[1]);
  92.               exit(1);
  93.             }
  94.  
  95.           fseek(vccFile, vccHead.offset, SEEK_SET);
  96.           for (fileNum = 0; fileNum < vccHead.size; fileNum++)
  97.             {
  98.               readRecord(vccFile, &fileRec);
  99.               extractFile(fileRec, vccFile);
  100.             }
  101.           fclose(vccFile);
  102.         }
  103.     else
  104.       {
  105.         printf("Error %d opening %s\n", errno, argv[1]);
  106.         exit(errno);
  107.       }
  108.   else
  109.     printf("Usage %s <filename.vcc>\n", argv[0]);
  110.  
  111.   return 0;
  112. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement