sm64

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

utils.c (6111B)


      1 #include <dirent.h>
      2 #include <fcntl.h>
      3 #include <stdint.h>
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <string.h>
      7 #include <sys/stat.h>
      8 #if defined(_MSC_VER) || defined(__MINGW32__)
      9   #include <io.h>
     10   #include <sys/utime.h>
     11 #else
     12   #include <unistd.h>
     13   #include <utime.h>
     14 #endif
     15 
     16 #include "utils.h"
     17 
     18 // global verbosity setting
     19 int g_verbosity = 0;
     20 
     21 int read_s16_be(unsigned char *buf)
     22 {
     23    unsigned tmp = read_u16_be(buf);
     24    int ret;
     25    if (tmp > 0x7FFF) {
     26       ret = -((int)0x10000 - (int)tmp);
     27    } else {
     28       ret = (int)tmp;
     29    }
     30    return ret;
     31 }
     32 
     33 float read_f32_be(unsigned char *buf)
     34 {
     35    union {uint32_t i; float f;} ret;
     36    ret.i = read_u32_be(buf);
     37    return ret.f;
     38 }
     39 
     40 int is_power2(unsigned int val)
     41 {
     42    while (((val & 1) == 0) && (val > 1)) {
     43       val >>= 1;
     44    }
     45    return (val == 1);
     46 }
     47 
     48 int fprint_write_output(FILE *fp, write_encoding encoding, const uint8_t *raw, int length)
     49 {
     50    typedef struct {
     51       int bytes_per_val;
     52       const char *suffix;
     53    } encoding_format;
     54    const encoding_format enc_fmt[] = {
     55       [ENCODING_RAW] = {0,                ""},
     56       [ENCODING_U8]  = {sizeof(uint8_t),  ""},
     57       [ENCODING_U16] = {sizeof(uint16_t), ""},
     58       [ENCODING_U32] = {sizeof(uint32_t), ""},
     59       [ENCODING_U64] = {sizeof(uint64_t), "ULL"},
     60    };
     61    int flength = 0;
     62    const encoding_format *fmt = &enc_fmt[encoding];
     63    switch (encoding) {
     64       case ENCODING_RAW:
     65          flength = fwrite(raw, 1, length, fp);
     66          break;
     67       case ENCODING_U8:
     68       case ENCODING_U16:
     69       case ENCODING_U32:
     70       case ENCODING_U64:
     71          for (int w = 0; w < length; w += fmt->bytes_per_val) {
     72             flength += fprintf(fp, "0x");
     73             for (int b = 0; b < fmt->bytes_per_val; b++) {
     74                int off = w + b;
     75                flength += fprintf(fp, "%02x", off < length ? raw[off] : 0x00);
     76             }
     77             flength += fprintf(fp, "%s%c", fmt->suffix, (w < length - fmt->bytes_per_val) ? ',' : '\n');
     78          }
     79          break;
     80    }
     81    return flength;
     82 }
     83 
     84 void swap_bytes(unsigned char *data, long length)
     85 {
     86    long i;
     87    unsigned char tmp;
     88    for (i = 0; i < length; i += 2) {
     89       tmp = data[i];
     90       data[i] = data[i+1];
     91       data[i+1] = tmp;
     92    }
     93 }
     94 
     95 void reverse_endian(unsigned char *data, long length)
     96 {
     97    long i;
     98    unsigned char tmp;
     99    for (i = 0; i < length; i += 4) {
    100       tmp = data[i];
    101       data[i] = data[i+3];
    102       data[i+3] = tmp;
    103       tmp = data[i+1];
    104       data[i+1] = data[i+2];
    105       data[i+2] = tmp;
    106    }
    107 }
    108 
    109 long filesize(const char *filename)
    110 {
    111    struct stat st;
    112 
    113    if (stat(filename, &st) == 0) {
    114       return st.st_size;
    115    }
    116 
    117    return -1;
    118 }
    119 
    120 void touch_file(const char *filename)
    121 {
    122    int fd;
    123    //fd = open(filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666);
    124    fd = open(filename, O_WRONLY|O_CREAT, 0666);
    125    if (fd >= 0) {
    126       utime(filename, NULL);
    127       close(fd);
    128    }
    129 }
    130 
    131 long read_file(const char *file_name, unsigned char **data)
    132 {
    133    FILE *in;
    134    unsigned char *in_buf = NULL;
    135    long file_size;
    136    long bytes_read;
    137    in = fopen(file_name, "rb");
    138    if (in == NULL) {
    139       return -1;
    140    }
    141 
    142    // allocate buffer to read from offset to end of file
    143    fseek(in, 0, SEEK_END);
    144    file_size = ftell(in);
    145 
    146    // sanity check
    147    if (file_size > 256*MB) {
    148       return -2;
    149    }
    150 
    151    in_buf = malloc(file_size);
    152    fseek(in, 0, SEEK_SET);
    153 
    154    // read bytes
    155    bytes_read = fread(in_buf, 1, file_size, in);
    156    if (bytes_read != file_size) {
    157       return -3;
    158    }
    159 
    160    fclose(in);
    161    *data = in_buf;
    162    return bytes_read;
    163 }
    164 
    165 long write_file(const char *file_name, unsigned char *data, long length)
    166 {
    167    FILE *out;
    168    long bytes_written;
    169    // open output file
    170    out = fopen(file_name, "wb");
    171    if (out == NULL) {
    172       perror(file_name);
    173       return -1;
    174    }
    175    bytes_written = fwrite(data, 1, length, out);
    176    fclose(out);
    177    return bytes_written;
    178 }
    179 
    180 void generate_filename(const char *in_name, char *out_name, char *extension)
    181 {
    182    char tmp_name[FILENAME_MAX];
    183    int len;
    184    int i;
    185    strcpy(tmp_name, in_name);
    186    len = strlen(tmp_name);
    187    for (i = len - 1; i > 0; i--) {
    188       if (tmp_name[i] == '.') {
    189          break;
    190       }
    191    }
    192    if (i <= 0) {
    193       i = len;
    194    }
    195    tmp_name[i] = '\0';
    196    sprintf(out_name, "%s.%s", tmp_name, extension);
    197 }
    198 
    199 char *basename(const char *name)
    200 {
    201    const char *base = name;
    202    while (*name) {
    203       if (*name++ == '/') {
    204          base = name;
    205       }
    206    }
    207    return (char *)base;
    208 }
    209 
    210 void make_dir(const char *dir_name)
    211 {
    212    struct stat st = {0};
    213    if (stat(dir_name, &st) == -1) {
    214       mkdir(dir_name, 0755);
    215    }
    216 }
    217 
    218 long copy_file(const char *src_name, const char *dst_name)
    219 {
    220    unsigned char *buf;
    221    long bytes_written;
    222    long bytes_read;
    223 
    224    bytes_read = read_file(src_name, &buf);
    225 
    226    if (bytes_read > 0) {
    227       bytes_written = write_file(dst_name, buf, bytes_read);
    228       if (bytes_written != bytes_read) {
    229          bytes_read = -1;
    230       }
    231       free(buf);
    232    }
    233 
    234    return bytes_read;
    235 }
    236 
    237 void dir_list_ext(const char *dir, const char *extension, dir_list *list)
    238 {
    239    char *pool;
    240    char *pool_ptr;
    241    struct dirent *entry;
    242    DIR *dfd;
    243    int idx;
    244 
    245    dfd = opendir(dir);
    246    if (dfd == NULL) {
    247       ERROR("Can't open '%s'\n", dir);
    248       exit(1);
    249    }
    250 
    251    pool = malloc(FILENAME_MAX * MAX_DIR_FILES);
    252    pool_ptr = pool;
    253 
    254    idx = 0;
    255    while ((entry = readdir(dfd)) != NULL && idx < MAX_DIR_FILES) {
    256       if (!extension || str_ends_with(entry->d_name, extension)) {
    257          sprintf(pool_ptr, "%s/%s", dir, entry->d_name);
    258          list->files[idx] = pool_ptr;
    259          pool_ptr += strlen(pool_ptr) + 1;
    260          idx++;
    261       }
    262    }
    263    list->count = idx;
    264 
    265    closedir(dfd);
    266 }
    267 
    268 void dir_list_free(dir_list *list)
    269 {
    270    // assume first entry in array is allocated
    271    if (list->files[0]) {
    272       free(list->files[0]);
    273       list->files[0] = NULL;
    274    }
    275 }
    276 
    277 int str_ends_with(const char *str, const char *suffix)
    278 {
    279    if (!str || !suffix) {
    280       return 0;
    281    }
    282    size_t len_str = strlen(str);
    283    size_t len_suffix = strlen(suffix);
    284    if (len_suffix > len_str) {
    285       return 0;
    286    }
    287    return (0 == strncmp(str + len_str - len_suffix, suffix, len_suffix));
    288 }