An emulator, assembler, and disassembler for the Sega Game Gear
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 

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