sm64

A Super Mario 64 decompilation
Log | Files | Refs | README | LICENSE

aiff_extract_codebook.c (5011B)


      1 /**
      2  * Create an ADPCM codebook either by extracting it from an AIFF section, or
      3  * by executing tabledesign.
      4  */
      5 #include <unistd.h>
      6 #include <math.h>
      7 #include <string.h>
      8 #include <stdio.h>
      9 #include <stdlib.h>
     10 #include <stdarg.h>
     11 
     12 typedef short s16;
     13 typedef int s32;
     14 typedef unsigned char u8;
     15 typedef unsigned int u32;
     16 
     17 #define BSWAP16(x) x = __builtin_bswap16(x)
     18 #define BSWAP32(x) x = __builtin_bswap32(x)
     19 
     20 #define NORETURN __attribute__((noreturn))
     21 #define UNUSED __attribute__((unused))
     22 
     23 typedef struct
     24 {
     25     u32 start;
     26     u32 end;
     27     u32 count;
     28     s16 state[16];
     29 } ALADPCMloop;
     30 
     31 static const char usage[] = "input.aiff";
     32 static const char *progname, *infilename;
     33 
     34 #define checked_fread(a, b, c, d) if (fread(a, b, c, d) != c) fail_parse("error parsing file")
     35 
     36 NORETURN
     37 void fail_parse(const char *fmt, ...)
     38 {
     39     char *formatted = NULL;
     40     va_list ap;
     41     va_start(ap, fmt);
     42     int size = vsnprintf(NULL, 0, fmt, ap);
     43     va_end(ap);
     44     if (size >= 0) {
     45         size++;
     46         formatted = malloc(size);
     47         if (formatted != NULL) {
     48             va_start(ap, fmt);
     49             size = vsnprintf(formatted, size, fmt, ap);
     50             va_end(ap);
     51             if (size < 0) {
     52                 free(formatted);
     53                 formatted = NULL;
     54             }
     55         }
     56     }
     57 
     58     if (formatted != NULL) {
     59         fprintf(stderr, "%s: %s [%s]\n", progname, formatted, infilename);
     60         free(formatted);
     61     }
     62     exit(1);
     63 }
     64 
     65 s32 readaifccodebook(FILE *fhandle, s32 ****table, s16 *order, s16 *npredictors)
     66 {
     67     checked_fread(order, sizeof(s16), 1, fhandle);
     68     BSWAP16(*order);
     69     checked_fread(npredictors, sizeof(s16), 1, fhandle);
     70     BSWAP16(*npredictors);
     71     *table = malloc(*npredictors * sizeof(s32 **));
     72     for (s32 i = 0; i < *npredictors; i++) {
     73         (*table)[i] = malloc(8 * sizeof(s32 *));
     74         for (s32 j = 0; j < 8; j++) {
     75             (*table)[i][j] = malloc((*order + 8) * sizeof(s32));
     76         }
     77     }
     78 
     79     for (s32 i = 0; i < *npredictors; i++) {
     80         s32 **table_entry = (*table)[i];
     81         for (s32 j = 0; j < *order; j++) {
     82             for (s32 k = 0; k < 8; k++) {
     83                 s16 ts;
     84                 checked_fread(&ts, sizeof(s16), 1, fhandle);
     85                 BSWAP16(ts);
     86                 table_entry[k][j] = ts;
     87             }
     88         }
     89 
     90         for (s32 k = 1; k < 8; k++) {
     91             table_entry[k][*order] = table_entry[k - 1][*order - 1];
     92         }
     93 
     94         table_entry[0][*order] = 1 << 11;
     95 
     96         for (s32 k = 1; k < 8; k++) {
     97             s32 j = 0;
     98             for (; j < k; j++) {
     99                 table_entry[j][k + *order] = 0;
    100             }
    101 
    102             for (; j < 8; j++) {
    103                 table_entry[j][k + *order] = table_entry[j - k][*order];
    104             }
    105         }
    106     }
    107     return 0;
    108 }
    109 
    110 int main(int argc, char **argv)
    111 {
    112     s16 order = -1;
    113     s16 npredictors = -1;
    114     s32 ***coefTable = NULL;
    115     FILE *ifile;
    116     progname = argv[0];
    117 
    118     if (argc < 2) {
    119         fprintf(stderr, "%s %s\n", progname, usage);
    120         exit(1);
    121     }
    122 
    123     infilename = argv[1];
    124 
    125     if ((ifile = fopen(infilename, "rb")) == NULL) {
    126         fail_parse("AIFF file could not be opened");
    127         exit(1);
    128     }
    129 
    130     char buf[5] = {0};
    131     checked_fread(buf, 4, 1, ifile);
    132     if (strcmp(buf, "FORM") != 0) fail_parse("not an AIFF file");
    133     checked_fread(buf, 4, 1, ifile);
    134     checked_fread(buf, 4, 1, ifile);
    135     if (strcmp(buf, "AIFF") != 0 && strcmp(buf, "AIFC") != 0) {
    136         fail_parse("not an AIFF file");
    137     }
    138 
    139     for (;;) {
    140         s32 size;
    141         if (!fread(buf, 4, 1, ifile) || !fread(&size, 4, 1, ifile)) break;
    142         BSWAP32(size);
    143         s32 nextOffset = ftell(ifile) + ((size + 1) & ~1);
    144 
    145         if (strcmp(buf, "APPL") == 0) {
    146             checked_fread(buf, 4, 1, ifile);
    147             if (strcmp(buf, "stoc") == 0) {
    148                 u8 len;
    149                 checked_fread(&len, 1, 1, ifile);
    150                 if (len == 11) {
    151                     char chunkName[12];
    152                     s16 version;
    153                     checked_fread(chunkName, 11, 1, ifile);
    154                     chunkName[11] = '\0';
    155                     if (strcmp(chunkName, "VADPCMCODES") == 0) {
    156                         checked_fread(&version, sizeof(s16), 1, ifile);
    157                         BSWAP16(version);
    158                         if (version == 1) {
    159                             readaifccodebook(ifile, &coefTable, &order, &npredictors);
    160                         }
    161                     }
    162                 }
    163             }
    164         }
    165 
    166         fseek(ifile, nextOffset, SEEK_SET);
    167     }
    168     fclose(ifile);
    169 
    170     if (coefTable == NULL) {
    171         execl("./tools/tabledesign", "tabledesign", "-s", "1", infilename, NULL);
    172     } else {
    173         printf("%d\n%d\n", order, npredictors);
    174         for (s32 i = 0; i < npredictors; i++) {
    175             for (s32 j = 0; j < order; j++) {
    176                 for (s32 k = 0; k < 8; k++) {
    177                     printf("% 5d ", coefTable[i][k][j]);
    178                 }
    179                 puts("");
    180             }
    181         }
    182     }
    183     return 0;
    184 }