#include #include #include #include #include "lib/op.h" #define OP_ADDR_MODE (OP_ADDR_IMPL | OP_ADDR_REL | OP_ADDR_IND \ | OP_ADDR_IMM | OP_ADDR_ABS) char *prg_name; FILE *input; FILE *output; uint8_t readu8(void) { uint8_t val; if (fread(&val, 1, 1, input) != 1) { return (-1); /* XXX: TODO */ } return (val); } uint16_t readu16(void) { uint16_t val; if (fread(&val, 1, 2, input) != 2) { return (-1); /* XXX: TODO */ } return (val); } uint32_t readu32(void) { uint32_t val; if (fread(&val, 1, 4, input) != 4) { return (-1); /* XXX: TODO */ } return (val); } int16_t read16(void) { int16_t val; if (fread(&val, 1, 2, input) != 2) { return (-1); /* XXX: TODO */ } return (val); } int32_t read32(void) { int32_t val; if (fread(&val, 1, 4, input) != 4) { return (-1); /* XXX: TODO */ } return (val); } void fatal(const char *str, ...) { va_list ap; fprintf(stderr, "%s: ", prg_name); va_start(ap, str); vfprintf(stderr, str, ap); va_end(ap); fprintf(stderr, "\n"); exit(EXIT_FAILURE); } void decode_target_suffix(uint8_t attr) { fprintf(output, "."); if (IS_TARGET_ZEXT(attr)) { fprintf(output, "U"); } switch (GET_TARGET_SIZE(attr)) { case SIZE_BYTE: fprintf(output, "B"); break; case SIZE_WORD: fprintf(output, "W"); break; case SIZE_LONG: fprintf(output, "L"); break; } } void decode_address(uint8_t attr) { switch (GET_ADDRESS_SIZE(attr)) { case SIZE_BYTE: fprintf(output, " %%%X", readu8()); break; case SIZE_WORD: fprintf(output, " %%%hX", readu16()); break; case SIZE_LONG: fprintf(output, " %%%X", readu32()); break; default: break; } } void decode_imm(uint8_t opcode) { uint8_t attr; attr = readu8(); fprintf(output, "%s", opcode_str[opcode]); decode_target_suffix(attr); switch (GET_TARGET_SIZE(attr)) { case SIZE_BYTE: fprintf(output, " #$%X\n", readu8()); break; case SIZE_WORD: fprintf(output, " #$%hX\n", readu16()); break; case SIZE_LONG: fprintf(output, " #$%X\n", readu32()); break; default: break; } } void decode_ind(uint8_t opcode) { uint8_t attr; fprintf(output, "%s", opcode_str[opcode]); attr = readu8(); if (opcode != OP_JMP_ind) { decode_target_suffix(attr); } if (opcode_addr[opcode] & (OP_ADDR_X | OP_ADDR_Y)) { fprintf(output, " ("); } else { fprintf(output, " "); } decode_address(attr); if (opcode_addr[opcode] & OP_ADDR_X) { fprintf(output, ", X)"); } else if (opcode_addr[opcode] & OP_ADDR_Y) { fprintf(output, "), Y"); } fprintf(output, "\n"); } void decode_abs(uint8_t opcode) { uint8_t attr; fprintf(output, "%s", opcode_str[opcode]); attr = readu8(); if (opcode != OP_JSR_abs || opcode != OP_JMP_abs) { decode_target_suffix(attr); } decode_address(attr); if (opcode_addr[opcode] & OP_ADDR_X) { fprintf(output, ", X"); } else if (opcode_addr[opcode] & OP_ADDR_Y) { fprintf(output, ", Y"); } fprintf(output, "\n"); } void decode(void) { uint8_t opcode; int16_t relative; do { opcode = readu8(); if (feof(input)) return; switch (opcode_addr[opcode] & OP_ADDR_MODE) { case OP_ADDR_IMPL: fprintf(output, "%s\n", opcode_str[opcode]); break; case OP_ADDR_REL: relative = read16(); fprintf(output, "%s $%hX\n", opcode_str[opcode], relative); break; case OP_ADDR_IMM: decode_imm(opcode); break; case OP_ADDR_IND: decode_ind(opcode); break; case OP_ADDR_ABS: decode_abs(opcode); break; default: fprintf(output, "???\n", opcode); break; } } while (!feof(input)); } int main(int argc, char **argv) { prg_name = argv[0]; input = stdin; output = stdout; if (argc > 2) { output = fopen(argv[2], "w"); if (output == NULL) fatal("can't open %s.", argv[2]); } if (argc > 1) { input = fopen(argv[1], "rb"); if (input == NULL) fatal("can't open %s.", argv[1]); } decode(); return (EXIT_SUCCESS); }