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

181 строка
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 <stdlib.h>
  4. #include "assembler.h"
  5. #include "assembler/errors.h"
  6. #include "assembler/io.h"
  7. #include "assembler/preprocessor.h"
  8. #include "assembler/state.h"
  9. #include "logging.h"
  10. #include "rom.h"
  11. #include "util.h"
  12. /*
  13. Tokenize ASMLines into ASMInstructions.
  14. On success, state->instructions is modified and NULL is returned. On error,
  15. an ErrorInfo object is returned and state->instructions is not modified.
  16. state->symtable may or may not be modified regardless of success.
  17. */
  18. static ErrorInfo* tokenize(AssemblerState *state)
  19. {
  20. // TODO
  21. // verify no instructions clash with header offset
  22. // if rom size is set, verify nothing overflows
  23. // otherwise, check nothing overflows max rom size (1 MB)
  24. (void) state;
  25. #ifdef DEBUG_MODE
  26. DEBUG("Dumping ASMLines:")
  27. const ASMLine *temp = state->lines;
  28. while (temp) {
  29. DEBUG("- %-40.*s [%s:%02zu]", (int) temp->length, temp->data,
  30. temp->filename, temp->original->lineno)
  31. temp = temp->next;
  32. }
  33. #endif
  34. return NULL;
  35. }
  36. /*
  37. Resolve default placeholder values in assembler state, such as ROM size.
  38. On success, no new heap objects are allocated. On error, an ErrorInfo
  39. object is returned.
  40. */
  41. static ErrorInfo* resolve_defaults(AssemblerState *state)
  42. {
  43. if (!state->rom_size) {
  44. state->rom_size = 32 << 10;
  45. // TODO: use highest instruction too
  46. if (state->header.rom_size != INVALID_SIZE_CODE) {
  47. size_t decl_size = size_code_to_bytes(state->header.rom_size);
  48. if (decl_size > state->rom_size)
  49. state->rom_size = decl_size;
  50. }
  51. }
  52. if (state->header.rom_size == INVALID_SIZE_CODE)
  53. state->header.rom_size = size_bytes_to_code(state->rom_size);
  54. return NULL;
  55. }
  56. /*
  57. Resolve symbol placeholders in instructions such as jumps and branches.
  58. On success, no new heap objects are allocated. On error, an ErrorInfo
  59. object is returned.
  60. */
  61. static ErrorInfo* resolve_symbols(AssemblerState *state)
  62. {
  63. // TODO
  64. (void) state;
  65. return NULL;
  66. }
  67. /*
  68. Convert finalized ASMInstructions into a binary data block.
  69. This function should never fail.
  70. */
  71. static void serialize_binary(AssemblerState *state, uint8_t *binary)
  72. {
  73. // TODO
  74. for (size_t i = 0; i < state->rom_size; i++)
  75. binary[i] = 'X';
  76. }
  77. /*
  78. Assemble the z80 source code in the source code buffer into binary data.
  79. If successful, return the size of the assembled binary data and change
  80. *binary_ptr to point to the assembled ROM data buffer. *binary_ptr must be
  81. free()'d when finished.
  82. If an error occurred, return 0 and update *ei_ptr to point to an ErrorInfo
  83. object which can be shown to the user with error_info_print(). The
  84. ErrorInfo object must be destroyed with error_info_destroy() when finished.
  85. In either case, only one of *binary_ptr and *ei_ptr is modified.
  86. */
  87. size_t assemble(const LineBuffer *source, uint8_t **binary_ptr, ErrorInfo **ei_ptr)
  88. {
  89. AssemblerState state;
  90. ErrorInfo *error_info;
  91. size_t retval = 0;
  92. state_init(&state);
  93. if ((error_info = preprocess(&state, source)))
  94. goto error;
  95. asm_symtable_init(&state.symtable);
  96. if ((error_info = tokenize(&state)))
  97. goto error;
  98. if ((error_info = resolve_defaults(&state)))
  99. goto error;
  100. if ((error_info = resolve_symbols(&state)))
  101. goto error;
  102. uint8_t *binary = malloc(sizeof(uint8_t) * state.rom_size);
  103. if (!binary)
  104. OUT_OF_MEMORY()
  105. serialize_binary(&state, binary);
  106. *binary_ptr = binary;
  107. retval = state.rom_size;
  108. goto cleanup;
  109. error:
  110. *ei_ptr = error_info;
  111. cleanup:
  112. asm_lines_free(state.lines);
  113. asm_includes_free(state.includes);
  114. asm_instructions_free(state.instructions);
  115. asm_symtable_free(state.symtable);
  116. return retval;
  117. }
  118. /*
  119. Assemble the z80 source code at the input path into a binary file.
  120. Return true if the operation was a success and false if it was a failure.
  121. Errors are printed to STDOUT; if the operation was successful then nothing
  122. is printed.
  123. */
  124. bool assemble_file(const char *src_path, const char *dst_path)
  125. {
  126. LineBuffer *source = read_source_file(src_path, true);
  127. if (!source)
  128. return false;
  129. uint8_t *binary;
  130. ErrorInfo *error_info;
  131. size_t size = assemble(source, &binary, &error_info);
  132. line_buffer_free(source);
  133. if (!size) {
  134. error_info_print(error_info, stderr);
  135. error_info_destroy(error_info);
  136. return false;
  137. }
  138. bool success = write_binary_file(dst_path, binary, size);
  139. free(binary);
  140. return success;
  141. }