| @@ -3,6 +3,7 @@ | |||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <string.h> | |||||
| #include <time.h> | #include <time.h> | ||||
| #include "disassembler.h" | #include "disassembler.h" | ||||
| @@ -19,6 +20,7 @@ | |||||
| #define NUM_BANKS(rom) \ | #define NUM_BANKS(rom) \ | ||||
| (((rom)->size + MMU_ROM_BANK_SIZE - 1) / MMU_ROM_BANK_SIZE) | (((rom)->size + MMU_ROM_BANK_SIZE - 1) / MMU_ROM_BANK_SIZE) | ||||
| #define MAX_BYTES_PER_LINE 16 | |||||
| /* Structs and things */ | /* Structs and things */ | ||||
| @@ -167,7 +169,7 @@ static void disassemble_header(Disassembly *dis, const ROM *rom) | |||||
| DEBUG("Disassembling header") | DEBUG("Disassembling header") | ||||
| WRITE_LINE(dis, ".rom_size\t\"%s\"\t\t; $%zX bytes in %zu banks", | WRITE_LINE(dis, ".rom_size\t\"%s\"\t\t; $%zX bytes in %zu banks", | ||||
| size_to_string(buf, rom->size), rom->size, NUM_BANKS(rom)) | |||||
| size_to_string(buf, rom->size), rom->size, NUM_BANKS(rom)) // TODO: fix alignment | |||||
| WRITE_LINE(dis, ".rom_header\t$%04X", | WRITE_LINE(dis, ".rom_header\t$%04X", | ||||
| rom->header_location) | rom->header_location) | ||||
| WRITE_LINE(dis, ".rom_checksum\t%s", | WRITE_LINE(dis, ".rom_checksum\t%s", | ||||
| @@ -225,21 +227,77 @@ static void mark_header(const ROM *rom, ROMBank *banks) | |||||
| } | } | ||||
| /* | /* | ||||
| Render a line of binary data within a block. | |||||
| */ | |||||
| static void render_binary(Disassembly *dis, size_t *idx, const ROMBank *bank) | |||||
| { | |||||
| size_t span = 1, i; | |||||
| while (span < MAX_BYTES_PER_LINE && bank->types[*idx + span] == DT_BINARY) | |||||
| span++; | |||||
| char buf[4 * MAX_BYTES_PER_LINE + 1]; | |||||
| for (i = 0; i < span; i++) | |||||
| sprintf(buf + 4 * i, "$%02X ", bank->data[*idx + i]); | |||||
| buf[4 * span - 1] = '\0'; | |||||
| WRITE_LINE(dis, ".byte %s", buf) | |||||
| (*idx) += span; | |||||
| } | |||||
| /* | |||||
| Render a single instruction within a block. | |||||
| */ | |||||
| static void render_code(Disassembly *dis, size_t *idx, const ROMBank *bank) | |||||
| { | |||||
| DisasInstr *instr = disassemble_instruction(bank->data + *idx); | |||||
| char padding[16], *split; | |||||
| if ((split = strchr(instr->line, '\t'))) { | |||||
| size_t tabs = (40 - (instr->line + strlen(instr->line) - split)) / 8; | |||||
| padding[tabs] = '\0'; | |||||
| while (tabs-- > 0) | |||||
| padding[tabs] = '\t'; | |||||
| } else { | |||||
| strcpy(padding, "\t\t\t\t\t"); | |||||
| } | |||||
| WRITE_LINE(dis, "\t%s%s\t; %s", instr->line, padding, instr->bytestr) | |||||
| (*idx) += instr->size; | |||||
| disas_instr_free(instr); | |||||
| } | |||||
| /* | |||||
| Render fully analyzed banks into lines of disassembly. | Render fully analyzed banks into lines of disassembly. | ||||
| */ | */ | ||||
| static void render_banks(Disassembly *dis, ROMBank *banks) | |||||
| static void render_banks(Disassembly *dis, const ROMBank *banks) | |||||
| { | { | ||||
| size_t bn = 0, i; | |||||
| size_t bn = 0, idx; | |||||
| DEBUG("Rendering lines") | |||||
| while (banks[bn].data) { | while (banks[bn].data) { | ||||
| TRACE("Rendering bank 0x%02zX (0x%06zX-0x%06zX)", bn, | |||||
| bn * MMU_ROM_BANK_SIZE, bn * MMU_ROM_BANK_SIZE + banks[bn].size) | |||||
| WRITE_LINE(dis, "") | WRITE_LINE(dis, "") | ||||
| WRITE_LINE(dis, ";; " HRULE) | WRITE_LINE(dis, ";; " HRULE) | ||||
| WRITE_LINE(dis, "") | WRITE_LINE(dis, "") | ||||
| WRITE_LINE(dis, ".block $%02zX", bn) | WRITE_LINE(dis, ".block $%02zX", bn) | ||||
| for (i = 0; i < banks[bn].size; i++) { | |||||
| if (banks[bn].types[i] == DT_BINARY) | |||||
| WRITE_LINE(dis, ".byte $%02X", banks[bn].data[i]) | |||||
| idx = 0; | |||||
| while (idx < banks[bn].size) { | |||||
| switch (banks[bn].types[idx]) { | |||||
| case DT_BINARY: | |||||
| render_binary(dis, &idx, &banks[bn]); | |||||
| break; | |||||
| case DT_CODE: | |||||
| render_code(dis, &idx, &banks[bn]); | |||||
| break; | |||||
| case DT_HEADER: | |||||
| idx += HEADER_SIZE; | |||||
| break; | |||||
| default: | |||||
| FATAL("invalid data type %d at addr 0x%06zX", | |||||
| banks[bn].types[idx], bn * MMU_ROM_BANK_SIZE + idx) | |||||
| } | |||||
| } | } | ||||
| bn++; | bn++; | ||||
| } | } | ||||
| @@ -261,7 +319,11 @@ char** disassemble(const ROM *rom) | |||||
| ROMBank *banks = init_banks(rom); | ROMBank *banks = init_banks(rom); | ||||
| mark_header(rom, banks); | mark_header(rom, banks); | ||||
| // TODO: analyze(): set DT_CODE (future: make labels, slots) where appropriate | // TODO: analyze(): set DT_CODE (future: make labels, slots) where appropriate | ||||
| for (size_t i = 0; i < 0x1000; i++) | |||||
| banks[0].types[i] = DT_CODE; | |||||
| render_banks(&dis, banks); | render_banks(&dis, banks); | ||||
| free_banks(banks); | free_banks(banks); | ||||