Merge pull request #438 from s4Ys369/revert-434-patch-1
[sm64pc.git] / tools / utils.c
blob3ba6e3e6f74125170b0fd4ecb253873d3a3f8f55
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
16 #include "utils.h"
18 // global verbosity setting
19 int g_verbosity = 0;
21 int read_s16_be(unsigned char *buf)
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;
30 return ret;
33 float read_f32_be(unsigned char *buf)
35 union {uint32_t i; float f;} ret;
36 ret.i = read_u32_be(buf);
37 return ret.f;
40 int is_power2(unsigned int val)
42 while (((val & 1) == 0) && (val > 1)) {
43 val >>= 1;
45 return (val == 1);
48 void fprint_hex(FILE *fp, const unsigned char *buf, int length)
50 int i;
51 for (i = 0; i < length; i++) {
52 fprint_byte(fp, buf[i]);
53 fputc(' ', fp);
57 void fprint_hex_source(FILE *fp, const unsigned char *buf, int length)
59 int i;
60 for (i = 0; i < length; i++) {
61 if (i > 0) fputs(", ", fp);
62 fputs("0x", fp);
63 fprint_byte(fp, buf[i]);
67 void print_hex(const unsigned char *buf, int length)
69 fprint_hex(stdout, buf, length);
72 void swap_bytes(unsigned char *data, long length)
74 long i;
75 unsigned char tmp;
76 for (i = 0; i < length; i += 2) {
77 tmp = data[i];
78 data[i] = data[i+1];
79 data[i+1] = tmp;
83 void reverse_endian(unsigned char *data, long length)
85 long i;
86 unsigned char tmp;
87 for (i = 0; i < length; i += 4) {
88 tmp = data[i];
89 data[i] = data[i+3];
90 data[i+3] = tmp;
91 tmp = data[i+1];
92 data[i+1] = data[i+2];
93 data[i+2] = tmp;
97 long filesize(const char *filename)
99 struct stat st;
101 if (stat(filename, &st) == 0) {
102 return st.st_size;
105 return -1;
108 void touch_file(const char *filename)
110 int fd;
111 //fd = open(filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666);
112 fd = open(filename, O_WRONLY|O_CREAT, 0666);
113 if (fd >= 0) {
114 utime(filename, NULL);
115 close(fd);
119 long read_file(const char *file_name, unsigned char **data)
121 FILE *in;
122 unsigned char *in_buf = NULL;
123 long file_size;
124 long bytes_read;
125 in = fopen(file_name, "rb");
126 if (in == NULL) {
127 return -1;
130 // allocate buffer to read from offset to end of file
131 fseek(in, 0, SEEK_END);
132 file_size = ftell(in);
134 // sanity check
135 if (file_size > 256*MB) {
136 return -2;
139 in_buf = malloc(file_size);
140 fseek(in, 0, SEEK_SET);
142 // read bytes
143 bytes_read = fread(in_buf, 1, file_size, in);
144 if (bytes_read != file_size) {
145 return -3;
148 fclose(in);
149 *data = in_buf;
150 return bytes_read;
153 long write_file(const char *file_name, unsigned char *data, long length)
155 FILE *out;
156 long bytes_written;
157 // open output file
158 out = fopen(file_name, "wb");
159 if (out == NULL) {
160 perror(file_name);
161 return -1;
163 bytes_written = fwrite(data, 1, length, out);
164 fclose(out);
165 return bytes_written;
168 void generate_filename(const char *in_name, char *out_name, char *extension)
170 char tmp_name[FILENAME_MAX];
171 int len;
172 int i;
173 strcpy(tmp_name, in_name);
174 len = strlen(tmp_name);
175 for (i = len - 1; i > 0; i--) {
176 if (tmp_name[i] == '.') {
177 break;
180 if (i <= 0) {
181 i = len;
183 tmp_name[i] = '\0';
184 sprintf(out_name, "%s.%s", tmp_name, extension);
187 char *basename(const char *name)
189 const char *base = name;
190 while (*name) {
191 if (*name++ == '/') {
192 base = name;
195 return (char *)base;
198 void make_dir(const char *dir_name)
200 struct stat st = {0};
201 if (stat(dir_name, &st) == -1) {
202 mkdir(dir_name, 0755);
206 long copy_file(const char *src_name, const char *dst_name)
208 unsigned char *buf;
209 long bytes_written;
210 long bytes_read;
212 bytes_read = read_file(src_name, &buf);
214 if (bytes_read > 0) {
215 bytes_written = write_file(dst_name, buf, bytes_read);
216 if (bytes_written != bytes_read) {
217 bytes_read = -1;
219 free(buf);
222 return bytes_read;
225 void dir_list_ext(const char *dir, const char *extension, dir_list *list)
227 char *pool;
228 char *pool_ptr;
229 struct dirent *entry;
230 DIR *dfd;
231 int idx;
233 dfd = opendir(dir);
234 if (dfd == NULL) {
235 ERROR("Can't open '%s'\n", dir);
236 exit(1);
239 pool = malloc(FILENAME_MAX * MAX_DIR_FILES);
240 pool_ptr = pool;
242 idx = 0;
243 while ((entry = readdir(dfd)) != NULL && idx < MAX_DIR_FILES) {
244 if (!extension || str_ends_with(entry->d_name, extension)) {
245 sprintf(pool_ptr, "%s/%s", dir, entry->d_name);
246 list->files[idx] = pool_ptr;
247 pool_ptr += strlen(pool_ptr) + 1;
248 idx++;
251 list->count = idx;
253 closedir(dfd);
256 void dir_list_free(dir_list *list)
258 // assume first entry in array is allocated
259 if (list->files[0]) {
260 free(list->files[0]);
261 list->files[0] = NULL;
265 int str_ends_with(const char *str, const char *suffix)
267 if (!str || !suffix) {
268 return 0;
270 size_t len_str = strlen(str);
271 size_t len_suffix = strlen(suffix);
272 if (len_suffix > len_str) {
273 return 0;
275 return (0 == strncmp(str + len_str - len_suffix, suffix, len_suffix));