diff --git a/README.md b/README.md index fcd8097..819d815 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,7 @@ Only OS X and Linux are tested. You'll need a modern compiler that supports C11 `brew install sdl2`; using apt, you can `apt-get install libsdl2-dev`. Run `make` to create `./crater`. To build the development version with debug -symbols and extra diagnostic info (they can exist simultaneously), run -`make DEBUG=1`, which creates `./crater-dev`. +symbols and no optimizations, run `make DEBUG=1`, which creates `./crater-dev`. crater has a number of test cases. Run the entire suite with `make test`; individual components can be tested by doing `make test-{component}`, where @@ -51,9 +50,8 @@ Add or symlink ROMs to `roms/` at your leisure. Note that they must end in Add `--fullscreen` (`-f`) to enable fullscreen mode, or `--scale ` (`-s `) to scale the game screen by an integer factor. -Add `--debug` (`-g`) to display detailed information about emulation state -while running, including register values and memory contents. You can also -pause emulation to set breakpoints and change state. +Add `--debug` (`-g`) to show logging information while running. Pass it twice +(`-g -g`) to show more detailed logs, including an emulator trace. `./crater -h` gives (fairly basic) command-line usage, and `./crater -v` gives the current version. diff --git a/crater.c b/crater.c index f9335c6..9b9527e 100644 --- a/crater.c +++ b/crater.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 Ben Kurtovic +/* Copyright (C) 2014-2016 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ #include @@ -24,15 +24,15 @@ int main(int argc, char *argv[]) if (retval != CONFIG_OK) return retval == CONFIG_EXIT_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE; -#ifdef DEBUG_MODE - config_dump_args(config); -#endif + SET_LOG_LEVEL(config->debug) + if (DEBUG_LEVEL) + config_dump_args(config); - if (config->assemble || config->disassemble) { - if (config->assemble) - retval = assemble_file(config->src_path, config->dst_path); - else - retval = disassemble_file(config->src_path, config->dst_path); + if (config->assemble) { + retval = assemble_file(config->src_path, config->dst_path); + retval = retval ? EXIT_SUCCESS : EXIT_FAILURE; + } else if (config->disassemble) { + retval = disassemble_file(config->src_path, config->dst_path); retval = retval ? EXIT_SUCCESS : EXIT_FAILURE; } else { ROM *rom; diff --git a/makefile b/makefile index 6793148..0f96b9c 100644 --- a/makefile +++ b/makefile @@ -8,17 +8,16 @@ DEVEXT = -dev TESTS = cpu vdp psg asm dis integrate CC = clang -FLAGS = -O2 -Wall -Wextra -pedantic -std=c11 +FLAGS = -Wall -Wextra -pedantic -std=c11 CFLAGS = $(shell sdl2-config --cflags) LIBS = $(shell sdl2-config --libs) -DFLAGS = -g -DDEBUG_MODE +DFLAGS = -g +RFLAGS = -O2 + MKDIR = mkdir -p RM = rm -rf ASM_UP = scripts/update_asm_instructions.py -MODE = release -BNRY = $(PROGRAM) -FLGS = $(FLAGS) SDRS = $(shell find $(SOURCES) -type d | xargs echo) SRCS = $(filter-out %.inc.c,$(foreach d,. $(SDRS),$(wildcard $(addprefix $(d)/*,.c)))) OBJS = $(patsubst %.c,%.o,$(addprefix $(BUILD)/$(MODE)/,$(SRCS))) @@ -27,9 +26,13 @@ DIRS = $(sort $(dir $(OBJS))) TCPS = $(addprefix test-,$(TESTS)) ifdef DEBUG - BNRY := $(BNRY)$(DEVEXT) - FLGS += $(DFLAGS) + BNRY := $(PROGRAM)$(DEVEXT) + FLGS += $(DFLAGS) $(FLAGS) MODE = debug +else + BNRY := $(PROGRAM) + FLGS += $(RFLAGS) $(FLAGS) + MODE = release endif export CC diff --git a/src/assembler.c b/src/assembler.c index 67750a1..06d9f5c 100644 --- a/src/assembler.c +++ b/src/assembler.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 Ben Kurtovic +/* Copyright (C) 2014-2016 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ #include @@ -38,6 +38,7 @@ static size_t bounding_rom_size(size_t size) */ static ErrorInfo* resolve_defaults(AssemblerState *state) { + DEBUG("Resolving defaults") if (!state->rom_size) { state->rom_size = ROM_SIZE_MIN; @@ -82,6 +83,7 @@ static ErrorInfo* resolve_symbols(AssemblerState *state) ASMInstruction *inst = state->instructions; const ASMSymbol *symbol; + DEBUG("Resolving symbols") while (inst) { if (inst->symbol) { symbol = asm_symtable_find(state->symtable, inst->symbol); @@ -145,6 +147,7 @@ static void write_header(const ASMHeaderInfo *info, uint8_t *binary) */ static void serialize_binary(const AssemblerState *state, uint8_t *binary) { + DEBUG("Serializing binary data") memset(binary, 0xFF, state->rom_size); const ASMInstruction *inst = state->instructions; @@ -188,16 +191,13 @@ size_t assemble(const LineBuffer *source, uint8_t **binary_ptr, ErrorInfo **ei_p asm_symtable_init(&state.symtable); -#ifdef DEBUG_MODE - asm_lines_print(state.lines); -#endif + if (TRACE_LEVEL) + asm_lines_print(state.lines); if ((error_info = tokenize(&state))) goto error; - if ((error_info = resolve_defaults(&state))) goto error; - if ((error_info = resolve_symbols(&state))) goto error; @@ -240,6 +240,7 @@ bool assemble_file(const char *src_path, const char *dst_path) return false; } + DEBUG("Writing output file") bool success = write_binary_file(dst_path, binary, size); free(binary); return success; diff --git a/src/assembler/preprocessor.c b/src/assembler/preprocessor.c index 884f017..3c0c2cd 100644 --- a/src/assembler/preprocessor.c +++ b/src/assembler/preprocessor.c @@ -373,7 +373,7 @@ static inline bool is_header_offset_valid(uint16_t offset) ErrorInfo* preprocess(AssemblerState *state, const LineBuffer *source) { ErrorInfo* ei = NULL; - DEBUG("Running preprocessor:") + DEBUG("Running preprocessor") if ((ei = build_asm_lines(source, &state->lines, NULL, &state->includes, 0))) return ei; diff --git a/src/assembler/state.c b/src/assembler/state.c index 5852b90..e545e6a 100644 --- a/src/assembler/state.c +++ b/src/assembler/state.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 Ben Kurtovic +/* Copyright (C) 2014-2016 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ #include @@ -196,17 +196,16 @@ bool asm_deftable_remove( return hash_table_remove(tab, key, size); } -#ifdef DEBUG_MODE /* - DEBUG FUNCTION: Print out an ASMLine list to stdout. + @TRACE_LEVEL + Print out an ASMLine list to stdout. */ void asm_lines_print(const ASMLine *line) { - DEBUG("Dumping ASMLines:") + TRACE("Dumping ASMLines:") while (line) { - DEBUG("- %-40.*s [%s:%02zu]", (int) line->length, line->data, + TRACE("- %-40.*s [%s:%02zu]", (int) line->length, line->data, line->filename, line->original->lineno) line = line->next; } } -#endif diff --git a/src/assembler/state.h b/src/assembler/state.h index 2fa41c3..1ec9fd4 100644 --- a/src/assembler/state.h +++ b/src/assembler/state.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 Ben Kurtovic +/* Copyright (C) 2014-2016 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ #pragma once @@ -112,6 +112,4 @@ const ASMDefine* asm_deftable_find(const ASMDefineTable*, const char*, size_t); void asm_deftable_insert(ASMDefineTable*, ASMDefine*); bool asm_deftable_remove(ASMDefineTable*, const char*, size_t); -#ifdef DEBUG_MODE void asm_lines_print(const ASMLine*); -#endif diff --git a/src/assembler/tokenizer.c b/src/assembler/tokenizer.c index 2028a45..cb58a18 100644 --- a/src/assembler/tokenizer.c +++ b/src/assembler/tokenizer.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 Ben Kurtovic +/* Copyright (C) 2014-2016 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ #include @@ -468,6 +468,7 @@ ErrorInfo* tokenize(AssemblerState *state) const ASMLine *line = state->lines; size_t offset = 0; + DEBUG("Running tokenizer") init_layout_info(&li, state); memset(si.slots, -1, MMU_NUM_ROM_BANKS); diff --git a/src/config.c b/src/config.c index d13fb14..4021c0f 100644 --- a/src/config.c +++ b/src/config.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 Ben Kurtovic +/* Copyright (C) 2014-2016 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ #include @@ -24,15 +24,14 @@ static void print_help(const char *arg1) " -h, --help show this help message and exit\n" " -v, --version show crater's version number and exit\n" " -f, --fullscreen enable fullscreen mode\n" -" -s, --scale scale the game screen by an integer factor\n" -" (applies to windowed mode only)\n" " path to the rom file to execute; if not given, will look\n" " in the roms/ directory and prompt the user\n" "\n" "advanced options:\n" -" -g, --debug display information about emulation state while running,\n" -" including register and memory values; can also pause\n" -" emulation, set breakpoints, and change state\n" +" -g, --debug show logging information while running; add twice (-g -g)\n" +" to show more detailed logs, including an emulator trace\n" +" -s, --scale scale the game screen by an integer factor\n" +" (applies to windowed mode only)\n" " -a, --assemble [] convert z80 assembly source code into a\n" " binary file that can be run by crater\n" " -d, --disassemble [] convert a binary file into z80 assembly\n" @@ -202,7 +201,7 @@ static int parse_args(Config *config, int argc, char *argv[]) } config->scale = scale; } else if (!strcmp(arg, "g") || !strcmp(arg, "debug")) { - config->debug = true; + config->debug++; } else if (!strcmp(arg, "a") || !strcmp(arg, "assemble")) { if (paths_read >= 1) { config->src_path = config->rom_path; @@ -277,7 +276,7 @@ static bool sanity_check(Config* config) } else if (config->assemble && config->disassemble) { ERROR("cannot assemble and disassemble at the same time") return false; - } else if (assembler && (config->debug || config->fullscreen || config->scale > 1)) { + } else if (assembler && (config->fullscreen || config->scale > 1)) { ERROR("cannot specify emulator options in assembler mode") return false; } else if (assembler && !config->src_path) { @@ -309,7 +308,7 @@ int config_create(Config** config_ptr, int argc, char* argv[]) Config *config = cr_malloc(sizeof(Config)); int retval; - config->debug = false; + config->debug = 0; config->assemble = false; config->disassemble = false; config->fullscreen = false; @@ -342,21 +341,20 @@ void config_destroy(Config *config) free(config); } -#ifdef DEBUG_MODE /* - DEBUG FUNCTION: Print out all config arguments to stdout. + @DEBUG_LEVEL + Print out all config arguments to stdout. */ void config_dump_args(const Config* config) { DEBUG("Dumping arguments:") - DEBUG("- fullscreen: %s", config->fullscreen ? "true" : "false") - DEBUG("- scale: %d", config->scale) - DEBUG("- debug: %s", config->debug ? "true" : "false") + DEBUG("- debug: %d", config->debug) DEBUG("- assemble: %s", config->assemble ? "true" : "false") DEBUG("- disassemble: %s", config->disassemble ? "true" : "false") + DEBUG("- fullscreen: %s", config->fullscreen ? "true" : "false") + DEBUG("- scale: %d", config->scale) DEBUG("- rom_path: %s", config->rom_path ? config->rom_path : "(null)") DEBUG("- src_path: %s", config->src_path ? config->src_path : "(null)") DEBUG("- dst_path: %s", config->dst_path ? config->dst_path : "(null)") DEBUG("- overwrite: %s", config->overwrite ? "true" : "false") } -#endif diff --git a/src/config.h b/src/config.h index 2803b6c..f7514ff 100644 --- a/src/config.h +++ b/src/config.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 Ben Kurtovic +/* Copyright (C) 2014-2016 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ #pragma once @@ -21,7 +21,7 @@ /* Structs */ typedef struct { - bool debug; + int debug; bool assemble; bool disassemble; bool fullscreen; @@ -36,7 +36,4 @@ typedef struct { int config_create(Config**, int, char*[]); void config_destroy(Config*); - -#ifdef DEBUG_MODE void config_dump_args(const Config*); -#endif diff --git a/src/iomanager.c b/src/iomanager.c index 806b950..43d9eab 100644 --- a/src/iomanager.c +++ b/src/iomanager.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 Ben Kurtovic +/* Copyright (C) 2014-2016 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ #include @@ -36,9 +36,8 @@ void iomanager_emulate(GameGear *gg) while (!caught_signal) { if (gamegear_simulate(gg)) { ERROR("caught exception: %s", gamegear_get_exception(gg)) -#ifdef DEBUG_MODE - z80_dump_registers(&gg->cpu); -#endif + if (DEBUG_LEVEL) + z80_dump_registers(&gg->cpu); break; } usleep(1000 * 1000 / 60); @@ -46,9 +45,8 @@ void iomanager_emulate(GameGear *gg) if (caught_signal) { WARN("caught signal, stopping...") -#ifdef DEBUG_MODE - z80_dump_registers(&gg->cpu); -#endif + if (DEBUG_LEVEL) + z80_dump_registers(&gg->cpu); } DEBUG("IOManager unpowering GameGear") diff --git a/src/logging.h b/src/logging.h index 16e2a90..d77c63f 100644 --- a/src/logging.h +++ b/src/logging.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 Ben Kurtovic +/* Copyright (C) 2014-2016 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ #pragma once @@ -10,30 +10,38 @@ /* Internal usage only */ -#define LOG_MSG_(dest, level, extra, after, ...) \ - do { \ - fprintf(dest, level ": " __VA_ARGS__); \ - extra; \ - fprintf(dest, "\n"); \ - after; \ +#define LOG_MSG_(dest, level, type, extra, after, ...) \ + do { \ + if (logging_level_ >= level) { \ + fprintf(dest, type " " __VA_ARGS__); \ + extra; \ + fprintf(dest, "\n"); \ + after; \ + } \ } while (0); #define LOG_ERR_(...) LOG_MSG_(stderr, __VA_ARGS__) #define LOG_OUT_(...) LOG_MSG_(stdout, __VA_ARGS__) -#define PRINT_ERRNO_() fprintf(stderr, ": %s", strerror(errno)) +#define PRINT_ERR_ fprintf(stderr, ": %s", strerror(errno)) +#define EXIT_FAIL_ exit(EXIT_FAILURE) + +#define DEBUG_TEXT_ "\x1b[0m\x1b[37m[DEBUG]\x1b[0m" +#define TRACE_TEXT_ "\x1b[1m\x1b[33m[TRACE]\x1b[0m" + +unsigned logging_level_; /* Public logging macros */ -#define FATAL(...) LOG_ERR_("fatal", {}, exit(EXIT_FAILURE), __VA_ARGS__) -#define FATAL_ERRNO(...) LOG_ERR_("fatal", PRINT_ERRNO_(), exit(EXIT_FAILURE), __VA_ARGS__) -#define ERROR(...) LOG_ERR_("error", {}, {}, __VA_ARGS__) -#define ERROR_ERRNO(...) LOG_ERR_("error", PRINT_ERRNO_(), {}, __VA_ARGS__) -#define WARN(...) LOG_ERR_("warning", {}, {}, __VA_ARGS__) -#define WARN_ERRNO(...) LOG_ERR_("warning", PRINT_ERRNO_(), {}, __VA_ARGS__) - -#ifdef DEBUG_MODE -#define DEBUG(...) LOG_OUT_("[DEBUG]", {}, {}, __VA_ARGS__) -#else -#define DEBUG(...) {} -#endif +#define FATAL(...) LOG_ERR_(0, "fatal:", {}, EXIT_FAIL_, __VA_ARGS__) +#define FATAL_ERRNO(...) LOG_ERR_(0, "fatal:", PRINT_ERR_, EXIT_FAIL_, __VA_ARGS__) +#define ERROR(...) LOG_ERR_(0, "error:", {}, {}, __VA_ARGS__) +#define ERROR_ERRNO(...) LOG_ERR_(0, "error:", PRINT_ERR_, {}, __VA_ARGS__) +#define WARN(...) LOG_ERR_(0, "warning:", {}, {}, __VA_ARGS__) +#define WARN_ERRNO(...) LOG_ERR_(0, "warning:", PRINT_ERR_, {}, __VA_ARGS__) +#define DEBUG(...) LOG_OUT_(1, DEBUG_TEXT_, {}, {}, __VA_ARGS__) +#define TRACE(...) LOG_OUT_(2, TRACE_TEXT_, {}, {}, __VA_ARGS__) + +#define SET_LOG_LEVEL(level) logging_level_ = (level); +#define DEBUG_LEVEL (logging_level_ >= 1) +#define TRACE_LEVEL (logging_level_ >= 2) diff --git a/src/mmu.c b/src/mmu.c index f6b2879..bb9e2a5 100644 --- a/src/mmu.c +++ b/src/mmu.c @@ -1,9 +1,10 @@ -/* Copyright (C) 2014-2015 Ben Kurtovic +/* Copyright (C) 2014-2016 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ #include #include +#include "mmu.h" #include "logging.h" #include "util.h" #include "z80.h" @@ -31,6 +32,27 @@ void mmu_free(MMU *mmu) } /* + @DEBUG_LEVEL + Print out the bank mapping. +*/ +static void dump_bank_table(const MMU *mmu, const uint8_t *data) +{ + char buffer[49]; + size_t group, elem, bank; + + DEBUG("Dumping MMU bank table:") + for (group = 0; group < MMU_NUM_ROM_BANKS / 8; group++) { + for (elem = 0; elem < 8; elem++) { + bank = 8 * group + elem; + snprintf(buffer + 6 * elem, 7, "%02zX=%02zX ", bank, + (mmu->rom_banks[bank] - data) >> 14); + } + buffer[47] = '\0'; + DEBUG("- %s", buffer) + } +} + +/* Load a block of ROM into the MMU. size must be a multiple of MMU_ROM_BANK_SIZE (16 KB), the load will fail @@ -55,19 +77,8 @@ void mmu_load_rom(MMU *mmu, const uint8_t *data, size_t size) mmu->rom_banks[mirror] = data + (bank * MMU_ROM_BANK_SIZE); } -#ifdef DEBUG_MODE - char temp_str[64]; - DEBUG("Dumping MMU bank table:") - for (size_t group = 0; group < MMU_NUM_ROM_BANKS / 8; group++) { - for (size_t elem = 0; elem < 8; elem++) { - bank = 8 * group + elem; - snprintf(temp_str + 6 * elem, 7, "%02zX=%02zX ", bank, - (mmu->rom_banks[bank] - data) >> 14); - } - temp_str[47] = '\0'; - DEBUG("- %s", temp_str) - } -#endif + if (DEBUG_LEVEL) + dump_bank_table(mmu, data); } /* diff --git a/src/rom.c b/src/rom.c index 1185f7b..a8ed91d 100644 --- a/src/rom.c +++ b/src/rom.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 Ben Kurtovic +/* Copyright (C) 2014-2016 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ #include @@ -18,11 +18,29 @@ static size_t header_locations[NUM_LOCATIONS] = {0x7FF0, 0x3FF0, 0x1FF0}; -#ifdef DEBUG_MODE /* - DEBUG FUNCTION: Print out the header to stdout. + @DEBUG_LEVEL + Given a ROM size, return a pretty string. */ -static void print_header(const uint8_t *header) +static const char* size_to_string(size_t size) +{ + static char buffer[SIZE_CODE_BUF]; + + if (!size) + strncpy(buffer, "unknown", SIZE_CODE_BUF); + else if (size >= (1 << 20)) + snprintf(buffer, SIZE_CODE_BUF, "%zu MB", size >> 20); + else + snprintf(buffer, SIZE_CODE_BUF, "%zu KB", size >> 10); + + return buffer; +} + +/* + @DEBUG_LEVEL + Print out the raw header to stdout. +*/ +static void print_header_dump(const uint8_t *header) { char header_hex[3 * HEADER_SIZE], header_chr[3 * HEADER_SIZE]; @@ -40,26 +58,27 @@ static void print_header(const uint8_t *header) DEBUG("- header dump (hex): %s", header_hex) DEBUG("- header dump (chr): %s", header_chr) } -#endif -#ifdef DEBUG_MODE /* - DEBUG FUNCTION: Given a ROM size, return a pretty string. + @DEBUG_LEVEL + Print out the analyzed header to stdout. */ -static const char* size_to_string(size_t size) +static void print_header_contents(const ROM *rom, const uint8_t *header) { - static char buffer[SIZE_CODE_BUF]; - - if (!size) - strncpy(buffer, "unknown", SIZE_CODE_BUF); - else if (size >= (1 << 20)) - snprintf(buffer, SIZE_CODE_BUF, "%zu MB", size >> 20); + DEBUG("- header info:") + if (rom->reported_checksum == rom->expected_checksum) + DEBUG(" - checksum: 0x%04X (valid)", rom->reported_checksum) else - snprintf(buffer, SIZE_CODE_BUF, "%zu KB", size >> 10); - - return buffer; + DEBUG(" - checksum: 0x%04X (invalid, expected 0x%04X)", + rom->reported_checksum, rom->expected_checksum) + DEBUG(" - product code: %u (%s)", rom->product_code, + rom_product(rom) ? rom_product(rom) : "unknown") + DEBUG(" - version: %u", rom->version) + DEBUG(" - region code: %u (%s)", rom->region_code, + rom_region(rom) ? rom_region(rom) : "unknown") + DEBUG(" - reported size: %s", + size_to_string(size_code_to_bytes(header[0xF] & 0xF))) } -#endif /* Parse a ROM image's header, and return whether or not it is valid. @@ -88,9 +107,8 @@ static const char* size_to_string(size_t size) */ static bool parse_header(ROM *rom, const uint8_t *header) { -#ifdef DEBUG_MODE - print_header(header); -#endif + if (DEBUG_LEVEL) + print_header_dump(header); rom->reported_checksum = header[0xA] + (header[0xB] << 8); rom->expected_checksum = compute_checksum(rom->data, rom->size, header[0xF]); @@ -99,19 +117,8 @@ static bool parse_header(ROM *rom, const uint8_t *header) rom->version = header[0xE] & 0x0F; rom->region_code = header[0xF] >> 4; - DEBUG("- header info:") - if (rom->reported_checksum == rom->expected_checksum) - DEBUG(" - checksum: 0x%04X (valid)", rom->reported_checksum) - else - DEBUG(" - checksum: 0x%04X (invalid, expected 0x%04X)", - rom->reported_checksum, rom->expected_checksum) - DEBUG(" - product code: %u (%s)", rom->product_code, - rom_product(rom) ? rom_product(rom) : "unknown") - DEBUG(" - version: %u", rom->version) - DEBUG(" - region code: %u (%s)", rom->region_code, - rom_region(rom) ? rom_region(rom) : "unknown") - DEBUG(" - reported size: %s", - size_to_string(size_code_to_bytes(header[0xF] & 0xF))) + if (DEBUG_LEVEL) + print_header_contents(rom, header); return true; } diff --git a/src/z80.c b/src/z80.c index 593d2fd..b3a45bd 100644 --- a/src/z80.c +++ b/src/z80.c @@ -1,8 +1,9 @@ -/* Copyright (C) 2014-2015 Ben Kurtovic +/* Copyright (C) 2014-2016 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ -#include "logging.h" #include "z80.h" +#include "disassembler.h" +#include "logging.h" #define REG_AF 0 #define REG_BC 1 @@ -19,7 +20,6 @@ #define FLAG_ZERO 6 #define FLAG_SIGN 7 -#ifdef DEBUG_MODE #define BINARY_FMT "0b%u%u%u%u%u%u%u%u" // Used by z80_dump_registers() #define BINARY_VAL(data) \ (data & (1 << 7) ? 1 : 0), \ @@ -30,7 +30,6 @@ (data & (1 << 2) ? 1 : 0), \ (data & (1 << 1) ? 1 : 0), \ (data & (1 << 0) ? 1 : 0) -#endif /* Initialize a Z80 object. @@ -92,6 +91,7 @@ static inline uint16_t get_pair(Z80 *z80, uint8_t pair) case REG_HL: return (z80->regfile.h << 8) + z80->regfile.l; default: FATAL("invalid call: get_pair(z80, %u)", pair) } + return 0; } /* @@ -164,6 +164,16 @@ static inline void increment_refresh_counter(Z80 *z80) #include "z80_ops.inc.c" /* + @TRACE_LEVEL + Trace the instruction about to be executed by the CPU. +*/ +static inline void trace_instruction(const Z80 *z80) +{ + TRACE("PC @ 0x%04X", z80->regfile.pc) + // TODO +} + +/* Emulate the given number of cycles of the Z80, or until an exception. The return value indicates whether the exception flag is set. If it is, @@ -175,6 +185,8 @@ bool z80_do_cycles(Z80 *z80, double cycles) cycles -= z80->pending_cycles; while (cycles > 0 && !z80->except) { uint8_t opcode = mmu_read_byte(z80->mmu, z80->regfile.pc); + if (TRACE_LEVEL) + trace_instruction(z80); increment_refresh_counter(z80); cycles -= (*instruction_lookup_table[opcode])(z80, opcode); } @@ -183,9 +195,9 @@ bool z80_do_cycles(Z80 *z80, double cycles) return z80->except; } -#ifdef DEBUG_MODE /* - DEBUG FUNCTION: Print out all register values to stdout. + @DEBUG_LEVEL + Print out all register values to stdout. */ void z80_dump_registers(const Z80 *z80) { @@ -233,4 +245,3 @@ void z80_dump_registers(const Z80 *z80) DEBUG("- IFF1: %u", rf->iff1) DEBUG("- IFF2: %u", rf->iff2) } -#endif diff --git a/src/z80.h b/src/z80.h index 6da08ea..9ccbe8b 100644 --- a/src/z80.h +++ b/src/z80.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 Ben Kurtovic +/* Copyright (C) 2014-2016 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ #pragma once @@ -35,7 +35,4 @@ typedef struct { void z80_init(Z80*, MMU*); void z80_power(Z80*); bool z80_do_cycles(Z80*, double); - -#ifdef DEBUG_MODE void z80_dump_registers(const Z80*); -#endif