Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MorsGames
GitHub Repository: MorsGames/sm64plus
Path: blob/master/tools/utils.c
7854 views
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
}
289
290