An emulator, assembler, and disassembler for the Sega Game Gear
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 
 

355 satır
9.6 KiB

  1. /* Copyright (C) 2014-2015 Ben Kurtovic <ben.kurtovic@gmail.com>
  2. Released under the terms of the MIT License. See LICENSE for details. */
  3. #include <limits.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "parse_util.h"
  7. #include "directives.h"
  8. #include "../logging.h"
  9. #include "../util.h"
  10. #define MAX_REGION_SIZE 32
  11. #define DIRECTIVE_PARSE_FUNC(name, type) \
  12. bool dparse_##name(type *result, const ASMLine *line, const char *directive)
  13. /*
  14. All public functions in this file follow the same return conventions:
  15. - Return true on success and false on failure.
  16. - *result is only modified on success.
  17. */
  18. /*
  19. Read in a boolean value and store it in *result.
  20. */
  21. bool parse_bool(bool *result, const char *arg, ssize_t size)
  22. {
  23. switch (size) {
  24. case 1: // 0, 1
  25. if (*arg == '0' || *arg == '1')
  26. return (*result = *arg - '0'), true;
  27. return false;
  28. case 2: // on
  29. if (!strncmp(arg, "on", 2))
  30. return (*result = true), true;
  31. return false;
  32. case 3: // off
  33. if (!strncmp(arg, "off", 3))
  34. return (*result = false), true;
  35. return false;
  36. case 4: // true
  37. if (!strncmp(arg, "true", 4))
  38. return (*result = true), true;
  39. return false;
  40. case 5: // false
  41. if (!strncmp(arg, "false", 5))
  42. return (*result = false), true;
  43. return false;
  44. }
  45. return false;
  46. }
  47. /*
  48. Read in a 32-bit integer and store it in *result.
  49. */
  50. bool parse_uint32_t(uint32_t *result, const char *arg, ssize_t size)
  51. {
  52. if (size <= 0)
  53. return false;
  54. const char *end = arg + size;
  55. uint64_t value = 0;
  56. if (*arg == '$') {
  57. arg++;
  58. if (arg == end)
  59. return false;
  60. while (arg < end) {
  61. if (*arg >= '0' && *arg <= '9')
  62. value = (value * 0x10) + (*arg - '0');
  63. else if (*arg >= 'a' && *arg <= 'f')
  64. value = (value * 0x10) + 0xA + (*arg - 'a');
  65. else
  66. return false;
  67. if (value > UINT32_MAX)
  68. return false;
  69. arg++;
  70. }
  71. }
  72. else {
  73. while (arg < end) {
  74. if (*arg < '0' || *arg > '9')
  75. return false;
  76. value = (value * 10) + (*arg - '0');
  77. if (value > UINT32_MAX)
  78. return false;
  79. arg++;
  80. }
  81. }
  82. *result = value;
  83. return true;
  84. }
  85. /*
  86. Read in a string, possibly with escape sequences, and store it in *result.
  87. *length is also updated to the size of the string, which is *not*
  88. null-terminated. *result must be free()'d when finished.
  89. */
  90. bool parse_string(char **result, size_t *length, const char *arg, ssize_t size)
  91. {
  92. if (size < 2 || arg[0] != '"' || arg[size - 1] != '"')
  93. return false;
  94. ssize_t i, slashes = 0;
  95. for (i = 1; i < size; i++) {
  96. if (arg[i] == '"' && (slashes % 2) == 0)
  97. break;
  98. // TODO: parse escape codes here
  99. if (arg[i] == '\\')
  100. slashes++;
  101. else
  102. slashes = 0;
  103. }
  104. if (i != size - 1) // Junk present after closing quote
  105. return false;
  106. *length = size - 2;
  107. *result = malloc(sizeof(char) * (*length));
  108. if (!*result)
  109. OUT_OF_MEMORY()
  110. memcpy(*result, arg + 1, *length);
  111. return true;
  112. }
  113. /*
  114. Read in a space-separated sequence of bytes and store it in *result.
  115. *length is also updated to the number of bytes in the array. *result must
  116. be free()'d when finished.
  117. */
  118. bool parse_bytes(uint8_t **result, size_t *length, const char *arg, ssize_t size)
  119. {
  120. if (size <= 0)
  121. return false;
  122. const char *end = arg + size;
  123. uint8_t *bytes = NULL;
  124. size_t nbytes = 0;
  125. while (arg < end) {
  126. const char *start = arg;
  127. while (arg != end && *arg != ' ' && *arg != ',')
  128. arg++;
  129. uint32_t temp;
  130. if (!parse_uint32_t(&temp, start, arg - start) || temp > UINT8_MAX) {
  131. free(bytes);
  132. return false;
  133. }
  134. nbytes++;
  135. bytes = realloc(bytes, sizeof(uint8_t) * nbytes);
  136. if (!bytes)
  137. OUT_OF_MEMORY()
  138. bytes[nbytes - 1] = temp;
  139. if (arg < end - 1 && *arg == ',' && *(arg + 1) == ' ')
  140. arg += 2;
  141. else if (arg++ >= end)
  142. break;
  143. }
  144. *result = bytes;
  145. *length = nbytes;
  146. return true;
  147. }
  148. /*
  149. Read in a register argument and store it in *result.
  150. */
  151. bool parse_register(ASMArgRegister *result, const char *arg, ssize_t size)
  152. {
  153. if (size < 1 || size > 3)
  154. return false;
  155. #define LCASE(c) ((c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c)
  156. char buf[3] = {'\0'};
  157. switch (size) {
  158. case 3: buf[2] = LCASE(arg[2]);
  159. case 2: buf[1] = LCASE(arg[1]);
  160. case 1: buf[0] = LCASE(arg[0]);
  161. }
  162. #undef LCASE
  163. switch (size) {
  164. case 1:
  165. switch (buf[0]) {
  166. case 'a': return (*result = REG_A), true;
  167. case 'f': return (*result = REG_F), true;
  168. case 'b': return (*result = REG_B), true;
  169. case 'c': return (*result = REG_C), true;
  170. case 'd': return (*result = REG_D), true;
  171. case 'e': return (*result = REG_E), true;
  172. case 'h': return (*result = REG_H), true;
  173. case 'l': return (*result = REG_L), true;
  174. case 'i': return (*result = REG_I), true;
  175. case 'r': return (*result = REG_R), true;
  176. }
  177. return false;
  178. case 2:
  179. switch ((buf[0] << 8) + buf[1]) {
  180. case 0x6166: return (*result = REG_AF), true;
  181. case 0x6263: return (*result = REG_BC), true;
  182. case 0x6465: return (*result = REG_DE), true;
  183. case 0x686c: return (*result = REG_HL), true;
  184. case 0x6978: return (*result = REG_IX), true;
  185. case 0x6979: return (*result = REG_IY), true;
  186. case 0x7063: return (*result = REG_PC), true;
  187. case 0x7370: return (*result = REG_SP), true;
  188. }
  189. return false;
  190. case 3:
  191. switch ((buf[0] << 16) + (buf[1] << 8) + buf[2]) {
  192. case 0x616627: return (*result = REG_AF_), true;
  193. case 0x697868: return (*result = REG_IXH), true;
  194. case 0x69786c: return (*result = REG_IXL), true;
  195. case 0x697968: return (*result = REG_IYH), true;
  196. case 0x69796c: return (*result = REG_IYL), true;
  197. }
  198. return false;
  199. }
  200. return false;
  201. }
  202. /*
  203. Read in a boolean argument from the given line and store it in *result.
  204. */
  205. DIRECTIVE_PARSE_FUNC(bool, bool)
  206. {
  207. size_t offset = DIRECTIVE_OFFSET(line, directive) + 1;
  208. return parse_bool(result, line->data + offset, line->length - offset);
  209. }
  210. /*
  211. Read in a 32-bit int argument from the given line and store it in *result.
  212. */
  213. DIRECTIVE_PARSE_FUNC(uint32_t, uint32_t)
  214. {
  215. size_t offset = DIRECTIVE_OFFSET(line, directive) + 1;
  216. return parse_uint32_t(result, line->data + offset, line->length - offset);
  217. }
  218. /*
  219. Read in a 16-bit int argument from the given line and store it in *result.
  220. */
  221. DIRECTIVE_PARSE_FUNC(uint16_t, uint16_t)
  222. {
  223. uint32_t value;
  224. if (dparse_uint32_t(&value, line, directive) && value <= UINT16_MAX)
  225. return (*result = value), true;
  226. return false;
  227. }
  228. /*
  229. Read in an 8-bit int argument from the given line and store it in *result.
  230. */
  231. DIRECTIVE_PARSE_FUNC(uint8_t, uint8_t)
  232. {
  233. uint32_t value;
  234. if (dparse_uint32_t(&value, line, directive) && value <= UINT8_MAX)
  235. return (*result = value), true;
  236. return false;
  237. }
  238. /*
  239. Parse a ROM size string in an ASMLine and store it in *result.
  240. */
  241. DIRECTIVE_PARSE_FUNC(rom_size, uint32_t)
  242. {
  243. const char *arg = line->data + DIRECTIVE_OFFSET(line, directive) + 1;
  244. const char *end = line->data + line->length - 1;
  245. if (end - arg < 5)
  246. return false;
  247. if (*(arg++) != '"' || *(end--) != '"')
  248. return false;
  249. if (*end != 'B' && *end != 'b')
  250. return false;
  251. end--;
  252. uint32_t factor;
  253. if (*end == 'K' || *end == 'k')
  254. factor = 1 << 10;
  255. else if (*end == 'M' || *end == 'm')
  256. factor = 1 << 20;
  257. else
  258. return false;
  259. end--;
  260. if (*end != ' ')
  261. return false;
  262. uint32_t value = 0;
  263. while (arg < end) {
  264. if (*arg < '0' || *arg > '9')
  265. return false;
  266. value = (value * 10) + (*arg - '0');
  267. if (value > UINT16_MAX)
  268. return false;
  269. arg++;
  270. }
  271. *result = value * factor;
  272. return true;
  273. }
  274. /*
  275. Parse a region code string in an ASMLine and store it in *result.
  276. */
  277. DIRECTIVE_PARSE_FUNC(region_string, uint8_t)
  278. {
  279. char buffer[MAX_REGION_SIZE];
  280. size_t offset = DIRECTIVE_OFFSET(line, directive) + 1;
  281. const char *arg = line->data + offset;
  282. ssize_t len = line->length - offset;
  283. if (len <= 2 || len >= MAX_REGION_SIZE + 2) // Account for double quotes
  284. return false;
  285. if (arg[0] != '"' || arg[len - 1] != '"')
  286. return false;
  287. strncpy(buffer, arg + 1, len - 2);
  288. buffer[len - 2] = '\0';
  289. uint8_t code = region_string_to_code(buffer);
  290. if (code)
  291. return (*result = code), true;
  292. return false;
  293. }
  294. /*
  295. Parse a size code in an ASMLine and store it in *result.
  296. */
  297. DIRECTIVE_PARSE_FUNC(size_code, uint8_t)
  298. {
  299. uint32_t bytes;
  300. if (!dparse_uint32_t(&bytes, line, directive)) {
  301. if (!dparse_rom_size(&bytes, line, directive))
  302. return false;
  303. }
  304. uint8_t code = size_bytes_to_code(bytes);
  305. if (code != INVALID_SIZE_CODE)
  306. return (*result = code), true;
  307. return false;
  308. }