An emulator, assembler, and disassembler for the Sega Game Gear
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 

174 рядки
4.7 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 the region code 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_region_string(uint8_t *result, const ASMLine *line)
  117. {
  118. char buffer[MAX_REGION_SIZE];
  119. size_t offset = DIRECTIVE_OFFSET(line, DIR_ROM_REGION) + 1;
  120. const char *arg = line->data + offset;
  121. ssize_t len = line->length - offset;
  122. if (len <= 2 || len >= MAX_REGION_SIZE + 2) // Account for double quotes
  123. return false;
  124. if (arg[0] != '"' || arg[len - 1] != '"')
  125. return false;
  126. strncpy(buffer, arg + 1, len - 2);
  127. buffer[len - 2] = '\0';
  128. uint8_t code = region_string_to_code(buffer);
  129. if (code)
  130. return (*result = code), true;
  131. return false;
  132. }
  133. /*
  134. Parse the size code in an ASMLine and store it in *result.
  135. Return true on success and false on failure; in the latter case, *result is
  136. not modified.
  137. */
  138. bool parse_size_code(uint8_t *result, const ASMLine *line)
  139. {
  140. uint32_t bytes;
  141. if (!parse_uint32_t(&bytes, line, DIR_ROM_DECLSIZE))
  142. return false;
  143. uint8_t code = size_bytes_to_code(bytes);
  144. if (code)
  145. return (*result = code), true;
  146. return false;
  147. }