An emulator, assembler, and disassembler for the Sega Game Gear
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

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