An emulator, assembler, and disassembler for the Sega Game Gear
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 

191 lignes
5.1 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 <string.h>
  5. #include "parse_util.h"
  6. #include "directives.h"
  7. #include "../util.h"
  8. #define MAX_REGION_SIZE 32
  9. /*
  10. Read in a boolean argument from the given line and store it in *result.
  11. Return true on success and false on failure; in the latter case, *result is
  12. not modified.
  13. */
  14. bool parse_bool(bool *result, const ASMLine *line, const char *directive)
  15. {
  16. size_t offset = DIRECTIVE_OFFSET(line, directive) + 1;
  17. const char *arg = line->data + offset;
  18. ssize_t len = line->length - offset;
  19. if (len <= 0 || len > 5)
  20. return false;
  21. switch (len) {
  22. case 1: // 0, 1
  23. if (*arg == '0' || *arg == '1')
  24. return (*result = *arg - '0'), true;
  25. return false;
  26. case 2: // on
  27. if (!strncmp(arg, "on", 2))
  28. return (*result = true), true;
  29. return false;
  30. case 3: // off
  31. if (!strncmp(arg, "off", 3))
  32. return (*result = false), true;
  33. return false;
  34. case 4: // true
  35. if (!strncmp(arg, "true", 4))
  36. return (*result = true), true;
  37. return false;
  38. case 5: // false
  39. if (!strncmp(arg, "false", 5))
  40. return (*result = false), true;
  41. return false;
  42. }
  43. return false;
  44. }
  45. /*
  46. Read in a 32-bit int argument from the given line and store it in *result.
  47. Return true on success and false on failure; in the latter case, *result is
  48. not modified.
  49. */
  50. bool parse_uint32_t(uint32_t *result, const ASMLine *line, const char *directive)
  51. {
  52. size_t offset = DIRECTIVE_OFFSET(line, directive) + 1;
  53. const char *str = line->data + offset;
  54. const char *end = str + line->length - offset;
  55. if (end - str <= 0)
  56. return false;
  57. uint64_t value = 0;
  58. if (*str == '$') {
  59. str++;
  60. if (str == end)
  61. return false;
  62. while (str < end) {
  63. if (*str >= '0' && *str <= '9')
  64. value = value * 16 + (*str - '0');
  65. else if (*str >= 'a' && *str <= 'f')
  66. value = (value * 0x10) + 0xA + (*str - 'a');
  67. else
  68. return false;
  69. if (value > UINT32_MAX)
  70. return false;
  71. str++;
  72. }
  73. }
  74. else {
  75. while (str < end) {
  76. if (*str < '0' || *str > '9')
  77. return false;
  78. value = (value * 10) + (*str - '0');
  79. if (value > UINT32_MAX)
  80. return false;
  81. str++;
  82. }
  83. }
  84. *result = value;
  85. return true;
  86. }
  87. /*
  88. Read in a 16-bit int argument from the given line and store it in *result.
  89. Return true on success and false on failure; in the latter case, *result is
  90. not modified.
  91. */
  92. bool parse_uint16_t(uint16_t *result, const ASMLine *line, const char *directive)
  93. {
  94. uint32_t value;
  95. if (parse_uint32_t(&value, line, directive) && value <= UINT16_MAX)
  96. return (*result = value), true;
  97. return false;
  98. }
  99. /*
  100. Read in an 8-bit int argument from the given line and store it in *result.
  101. Return true on success and false on failure; in the latter case, *result is
  102. not modified.
  103. */
  104. bool parse_uint8_t(uint8_t *result, const ASMLine *line, const char *directive)
  105. {
  106. uint32_t value;
  107. if (parse_uint32_t(&value, line, directive) && value <= UINT8_MAX)
  108. return (*result = value), true;
  109. return false;
  110. }
  111. /*
  112. Parse a ROM size string in an ASMLine and store it in *result.
  113. Return true on success and false on failure; in the latter case, *result is
  114. not modified.
  115. */
  116. bool parse_rom_size(uint32_t *result, const ASMLine *line)
  117. {
  118. uint32_t bytes;
  119. if (!parse_uint32_t(&bytes, line, DIR_ROM_SIZE))
  120. return false;
  121. if (size_bytes_to_code(bytes))
  122. return (*result = bytes), true;
  123. return false;
  124. }
  125. /*
  126. Parse a region code string in an ASMLine and store it in *result.
  127. Return true on success and false on failure; in the latter case, *result is
  128. not modified.
  129. */
  130. bool parse_region_string(uint8_t *result, const ASMLine *line)
  131. {
  132. char buffer[MAX_REGION_SIZE];
  133. size_t offset = DIRECTIVE_OFFSET(line, DIR_ROM_REGION) + 1;
  134. const char *arg = line->data + offset;
  135. ssize_t len = line->length - offset;
  136. if (len <= 2 || len >= MAX_REGION_SIZE + 2) // Account for double quotes
  137. return false;
  138. if (arg[0] != '"' || arg[len - 1] != '"')
  139. return false;
  140. strncpy(buffer, arg + 1, len - 2);
  141. buffer[len - 2] = '\0';
  142. uint8_t code = region_string_to_code(buffer);
  143. if (code)
  144. return (*result = code), true;
  145. return false;
  146. }
  147. /*
  148. Parse a size code in an ASMLine and store it in *result.
  149. Return true on success and false on failure; in the latter case, *result is
  150. not modified.
  151. */
  152. bool parse_size_code(uint8_t *result, const ASMLine *line)
  153. {
  154. uint32_t bytes;
  155. if (!parse_uint32_t(&bytes, line, DIR_ROM_DECLSIZE))
  156. return false;
  157. uint8_t code = size_bytes_to_code(bytes);
  158. if (code)
  159. return (*result = code), true;
  160. return false;
  161. }