1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus - util.c *
3 * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
4 * Copyright (C) 2012 CasualJames *
5 * Copyright (C) 2002 Hacktarux *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
21 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24 * Provides common utilities to the rest of the code:
39 #include "osal/files.h"
40 #include "osal/preproc.h"
42 /**********************
44 **********************/
46 file_status_t read_from_file(const char *filename, void *data, size_t size)
48 FILE *f = fopen(filename, "rb");
51 return file_open_error;
54 if (fread(data, 1, size, f) != size)
57 return file_read_error;
64 file_status_t write_to_file(const char *filename, const void *data, size_t size)
66 FILE *f = fopen(filename, "wb");
69 return file_open_error;
72 if (fwrite(data, 1, size, f) != size)
75 return file_read_error;
82 /**********************
84 **********************/
85 void swap_buffer(void *buffer, size_t length, size_t count)
90 unsigned short *pun = (unsigned short *)buffer;
91 for (i = 0; i < count; i++)
92 pun[i] = m64p_swap16(pun[i]);
96 unsigned int *pun = (unsigned int *)buffer;
97 for (i = 0; i < count; i++)
98 pun[i] = m64p_swap32(pun[i]);
100 else if (length == 8)
102 unsigned long long *pun = (unsigned long long *)buffer;
103 for (i = 0; i < count; i++)
104 pun[i] = m64p_swap64(pun[i]);
108 void to_little_endian_buffer(void *buffer, size_t length, size_t count)
110 #ifdef M64P_BIG_ENDIAN
111 swap_buffer(buffer, length, count);
115 void to_big_endian_buffer(void *buffer, size_t length, size_t count)
117 #ifndef M64P_BIG_ENDIAN
118 swap_buffer(buffer, length, count);
122 /**********************
124 **********************/
125 void countrycodestring(unsigned short countrycode, char *string)
130 strcpy(string, "Demo");
134 strcpy(string, "Beta");
137 case 0x41: /* Japan / USA */
138 strcpy(string, "USA/Japan");
141 case 0x44: /* Germany */
142 strcpy(string, "Germany");
146 strcpy(string, "USA");
149 case 0x46: /* France */
150 strcpy(string, "France");
153 case 'I': /* Italy */
154 strcpy(string, "Italy");
157 case 0x4A: /* Japan */
158 strcpy(string, "Japan");
161 case 'S': /* Spain */
162 strcpy(string, "Spain");
165 case 0x55: case 0x59: /* Australia */
166 sprintf(string, "Australia (0x%02X)", countrycode);
169 case 0x50: case 0x58: case 0x20:
170 case 0x21: case 0x38: case 0x70:
171 sprintf(string, "Europe (0x%02X)", countrycode);
175 sprintf(string, "Unknown (0x%02X)", countrycode);
180 void imagestring(unsigned char imagetype, char *string)
185 strcpy(string, ".z64 (native)");
188 strcpy(string, ".v64 (byteswapped)");
191 strcpy(string, ".n64 (wordswapped)");
198 /**********************
200 **********************/
202 /* Looks for an instance of ANY of the characters in 'needles' in 'haystack',
203 * starting from the end of 'haystack'. Returns a pointer to the last position
204 * of some character on 'needles' on 'haystack'. If not found, returns NULL.
206 static const char* strpbrk_reverse(const char* needles, const char* haystack)
208 size_t stringlength = strlen(haystack), counter;
210 for (counter = stringlength; counter > 0; --counter)
212 if (strchr(needles, haystack[counter-1]))
219 return haystack + counter - 1;
222 const char* namefrompath(const char* path)
224 const char* last_separator_ptr = strpbrk_reverse(OSAL_DIR_SEPARATORS, path);
226 if (last_separator_ptr != NULL)
227 return last_separator_ptr + 1;
232 static int is_path_separator(char c)
234 return strchr(OSAL_DIR_SEPARATORS, c) != NULL;
237 char* combinepath(const char* first, const char *second)
239 size_t len_first = strlen(first), off_second = 0;
241 if (first == NULL || second == NULL)
244 while (is_path_separator(first[len_first-1]))
247 while (is_path_separator(second[off_second]))
250 return formatstr("%.*s%c%s", (int) len_first, first, OSAL_DIR_SEPARATORS[0], second + off_second);
253 /**********************
255 **********************/
256 char *trim(char *str)
258 char *start = str, *end = str + strlen(str);
260 while (start < end && isspace(*start))
263 while (end > start && isspace(*(end-1)))
266 memmove(str, start, end - start);
267 str[end - start] = '\0';
272 int string_to_int(const char *str, int *result)
276 if (*str == '\0' || isspace(*str))
279 n = strtol(str, &endptr, 10);
280 if (*endptr != '\0' || errno != 0 || n < INT_MIN || n > INT_MAX)
286 static unsigned char char2hex(char c)
289 if(c >= '0' && c <= '9')
291 else if(c >= 'a' && c <= 'f')
297 int parse_hex(const char *str, unsigned char *output, size_t output_size)
300 for (i = 0; i < output_size; i++)
303 for (j = 0; j < 2; j++)
305 unsigned char h = char2hex(*str++);
309 output[i] = (output[i] << 4) | h;
319 char *formatstr(const char *fmt, ...)
322 char *str = (char *)malloc(size), *newstr;
325 /* There are two implementations of vsnprintf we have to deal with:
326 * C99 version: Returns the number of characters which would have been written
327 * if the buffer had been large enough, and -1 on failure.
328 * Windows version: Returns the number of characters actually written,
329 * and -1 on failure or truncation.
330 * NOTE: An implementation equivalent to the Windows one appears in glibc <2.1.
335 ret = vsnprintf(str, size, fmt, args);
338 // Successful result?
339 if (ret >= 0 && ret < size)
342 // Increment the capacity of the buffer
344 size = ret + 1; // C99 version: We got the needed buffer size
346 size *= 2; // Windows version: Keep guessing
348 newstr = (char *)realloc(str, size);
357 ini_line ini_parse_line(char **lineptr)
359 char *line = *lineptr, *endline = strchr(*lineptr, '\n'), *equal;
362 // Null terminate the current line and point to the next line
365 *lineptr = line + strlen(line) + 1;
367 // Parse the line contents
370 if (line[0] == '#' || line[0] == ';')
374 l.type = INI_COMMENT;
376 l.value = trim(line);
378 else if (line[0] == '[' && line[strlen(line)-1] == ']')
380 line[strlen(line)-1] = '\0';
383 l.type = INI_SECTION;
387 else if ((equal = strchr(line, '=')) != NULL)
389 char *name = line, *value = equal + 1;
392 l.type = INI_PROPERTY;
394 l.value = trim(value);
398 l.type = (*line == '\0') ? INI_BLANK : INI_TRASH;