# HG changeset patch # User Michael Pavone # Date 1437942331 25200 # Node ID 0b692b5d154b483bc1d2a78b640ead0f6ecfc25f # Parent 062a2199daf6cedd096a41e4387e84d496c01a3a# Parent 792be135d3af9ba6f091ae5c374a8811fcfe55b3 Merge diff -r 062a2199daf6 -r 0b692b5d154b Makefile --- a/Makefile Sun Jul 26 13:08:22 2015 -0700 +++ b/Makefile Sun Jul 26 13:25:31 2015 -0700 @@ -11,6 +11,7 @@ endif MEM:=mem_win.o +TERMINAL:=terminal_win.o BLASTEM:=blastem.exe CC:=wine gcc.exe CFLAGS:=-O2 -std=gnu99 -Wreturn-type -Werror=return-type -Werror=implicit-function-declaration -I"$(SDL2_PREFIX)/include/SDL2" -DGLEW_STATIC @@ -20,6 +21,7 @@ else MEM:=mem.o +TERMINAL:=terminal.o BLASTEM:=blastem ifeq ($(OS),Darwin) @@ -105,7 +107,7 @@ AUDIOOBJS=ym2612.o psg.o wave.o CONFIGOBJS=config.o tern.o util.o -MAINOBJS=blastem.o debug.o gdb_remote.o vdp.o render_sdl.o io.o romdb.o $(CONFIGOBJS) gst.o $(M68KOBJS) $(TRANSOBJS) $(AUDIOOBJS) +MAINOBJS=blastem.o debug.o gdb_remote.o vdp.o render_sdl.o io.o romdb.o $(TERMINAL) $(CONFIGOBJS) gst.o $(M68KOBJS) $(TRANSOBJS) $(AUDIOOBJS) ifeq ($(CPU),x86_64) CFLAGS+=-DX86_64 -m64 @@ -123,7 +125,13 @@ MAINOBJS+= $(Z80OBJS) endif -all : dis zdis stateview vgmplay $(BLASTEM) +ifeq ($(OS),Windows) +ALL=$(BLASTEM) +else +ALL= dis zdis stateview vgmplay blastem termhelper +endif + +all : $(ALL) $(BLASTEM) : $(MAINOBJS) $(CC) -o $(BLASTEM) $(MAINOBJS) $(LDFLAGS) @@ -190,4 +198,4 @@ vasmz80_mot -Fbin -spaces -o $@ $< clean : - rm -rf dis trans stateview test_x86 gen_fib *.o + rm -rf $(ALL) trans ztestrun ztestgen *.o diff -r 062a2199daf6 -r 0b692b5d154b blastem.c --- a/blastem.c Sun Jul 26 13:08:22 2015 -0700 +++ b/blastem.c Sun Jul 26 13:25:31 2015 -0700 @@ -91,8 +91,7 @@ return 0; } if (sizeof(header) != fread(header, 1, sizeof(header), f)) { - fprintf(stderr, "Error reading from %s\n", filename); - exit(1); + fatal_error("Error reading from %s\n", filename); } fseek(f, 0, SEEK_END); long filesize = ftell(f); @@ -106,16 +105,14 @@ } if (i == 8) { if (header[2]) { - fprintf(stderr, "%s is a split SMD ROM which is not currently supported", filename); - exit(1); + fatal_error("%s is a split SMD ROM which is not currently supported", filename); } return load_smd_rom(filesize, f); } } cart = malloc(nearest_pow2(filesize)); if (filesize != fread(cart, 1, filesize, f)) { - fprintf(stderr, "Error reading from %s\n", filename); - exit(1); + fatal_error("Error reading from %s\n", filename); } fclose(f); return filesize; @@ -289,8 +286,7 @@ m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_t value) { if (vdp_port & 0x2700E0) { - printf("machine freeze due to write to address %X\n", 0xC00000 | vdp_port); - exit(1); + fatal_error("machine freeze due to write to address %X\n", 0xC00000 | vdp_port); } vdp_port &= 0x1F; //printf("vdp_port write: %X, value: %X, cycle: %d\n", vdp_port, value, context->current_cycle); @@ -339,8 +335,7 @@ adjust_int_cycle(context, v_context); } } else { - printf("Illegal write to HV Counter port %X\n", vdp_port); - exit(1); + fatal_error("Illegal write to HV Counter port %X\n", vdp_port); } if (v_context->cycles != before_cycle) { //printf("68K paused for %d (%d) cycles at cycle %d (%d) for write\n", v_context->cycles - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle); @@ -369,8 +364,7 @@ genesis_context * gen = context->system; vdp_port &= 0xFF; if (vdp_port & 0xE0) { - printf("machine freeze due to write to Z80 address %X\n", 0x7F00 | vdp_port); - exit(1); + fatal_error("machine freeze due to write to Z80 address %X\n", 0x7F00 | vdp_port); } if (vdp_port < 0x10) { //These probably won't currently interact well with the 68K accessing the VDP @@ -380,8 +374,7 @@ } else if (vdp_port < 8) { vdp_control_port_write(gen->vdp, value << 8 | value); } else { - printf("Illegal write to HV Counter port %X\n", vdp_port); - exit(1); + fatal_error("Illegal write to HV Counter port %X\n", vdp_port); } } else if (vdp_port < 0x18) { sync_sound(gen, context->current_cycle); @@ -395,8 +388,7 @@ uint16_t vdp_port_read(uint32_t vdp_port, m68k_context * context) { if (vdp_port & 0x2700E0) { - printf("machine freeze due to read from address %X\n", 0xC00000 | vdp_port); - exit(1); + fatal_error("machine freeze due to read from address %X\n", 0xC00000 | vdp_port); } vdp_port &= 0x1F; uint16_t value; @@ -413,8 +405,7 @@ //printf("HV Counter: %X at cycle %d\n", value, v_context->cycles); } } else if (vdp_port < 0x18){ - printf("Illegal read from PSG port %X\n", vdp_port); - exit(1); + fatal_error("Illegal read from PSG port %X\n", vdp_port); } else { value = vdp_test_port_read(v_context); } @@ -444,8 +435,7 @@ { z80_context * context = vcontext; if (vdp_port & 0xE0) { - printf("machine freeze due to read from Z80 address %X\n", 0x7F00 | vdp_port); - exit(1); + fatal_error("machine freeze due to read from Z80 address %X\n", 0x7F00 | vdp_port); } genesis_context * gen = context->system; //VDP access goes over the 68K bus like a bank area access @@ -467,8 +457,7 @@ } else if (vdp_port < 8) { ret = vdp_control_port_read(gen->vdp); } else { - printf("Illegal write to HV Counter port %X\n", vdp_port); - exit(1); + fatal_error("Illegal write to HV Counter port %X\n", vdp_port); } } else { //TODO: Figure out the correct value today @@ -507,8 +496,7 @@ gen->z80->mem_pointers[1] = NULL; } } else { - printf("68K write to unhandled Z80 address %X\n", location); - exit(1); + fatal_error("68K write to unhandled Z80 address %X\n", location); } } } else { @@ -847,8 +835,7 @@ if (statefile) { uint32_t pc = load_gst(gen, statefile); if (!pc) { - fprintf(stderr, "Failed to load save state %s\n", statefile); - exit(1); + fatal_error("Failed to load save state %s\n", statefile); } printf("Loaded %s\n", statefile); if (debugger) { @@ -907,10 +894,6 @@ int main(int argc, char ** argv) { - if (argc < 2) { - fputs("Usage: blastem [OPTIONS] ROMFILE [WIDTH] [HEIGHT]\n", stderr); - return 1; - } set_exe_str(argv[0]); config = load_config(); int width = -1; @@ -931,8 +914,7 @@ case 'b': i++; if (i >= argc) { - fputs("-b must be followed by a frame count\n", stderr); - return 1; + fatal_error("-b must be followed by a frame count\n"); } headless = 1; exit_after = atoi(argv[i]); @@ -954,7 +936,7 @@ address_log = fopen("address.log", "w"); break; case 'v': - printf("blastem %s\n", BLASTEM_VERSION); + info_message("blastem %s\n", BLASTEM_VERSION); return 0; break; case 'n': @@ -963,20 +945,17 @@ case 'r': i++; if (i >= argc) { - fputs("-r must be followed by region (J, U or E)\n", stderr); - return 1; + fatal_error("-r must be followed by region (J, U or E)\n"); } force_version = translate_region_char(toupper(argv[i][0])); if (!force_version) { - fprintf(stderr, "'%c' is not a valid region character for the -r option\n", argv[i][0]); - return 1; + fatal_error("'%c' is not a valid region character for the -r option\n", argv[i][0]); } break; case 's': i++; if (i >= argc) { - fputs("-s must be followed by a savestate filename\n", stderr); - return 1; + fatal_error("-s must be followed by a savestate filename\n"); } statefile = argv[i]; break; @@ -984,7 +963,7 @@ ym_log = 1; break; case 'h': - puts( + info_message( "Usage: blastem [OPTIONS] ROMFILE [WIDTH] [HEIGHT]\n" "Options:\n" " -h Print this help text\n" @@ -1000,13 +979,11 @@ ); return 0; default: - fprintf(stderr, "Unrecognized switch %s\n", argv[i]); - return 1; + fatal_error("Unrecognized switch %s\n", argv[i]); } } else if (!loaded) { if (!(rom_size = load_rom(argv[i]))) { - fprintf(stderr, "Failed to open %s for reading\n", argv[i]); - return 1; + fatal_error("Failed to open %s for reading\n", argv[i]); } romfname = argv[i]; loaded = 1; @@ -1017,8 +994,7 @@ } } if (!loaded) { - fputs("You must specify a ROM filename!\n", stderr); - return 1; + fatal_error("Usage: blastem [OPTIONS] ROMFILE [WIDTH] [HEIGHT]\n"); } tern_node *rom_db = load_rom_db(); rom_info info = configure_rom(rom_db, cart, rom_size, base_map, sizeof(base_map)/sizeof(base_map[0])); diff -r 062a2199daf6 -r 0b692b5d154b config.c --- a/config.c Sun Jul 26 13:08:22 2015 -0700 +++ b/config.c Sun Jul 26 13:25:31 2015 -0700 @@ -59,8 +59,7 @@ if (started) { return head; } - fprintf(stderr, "unexpected } on line %d\n", *line); - exit(1); + fatal_error("unexpected } on line %d\n", *line); } char * end = curline + len - 1; @@ -141,7 +140,8 @@ return ret; } no_config: - fputs("Failed to find a config file in ~/.config/blastem/blastem.cfg or in the blastem executable directory\n", stderr); - exit(1); + fatal_error("Failed to find a config file in ~/.config/blastem/blastem.cfg or in the blastem executable directory\n"); + //this will never get reached, but the compiler doesn't know that. Let's make it happy + return NULL; } diff -r 062a2199daf6 -r 0b692b5d154b debug.c --- a/debug.c Sun Jul 26 13:08:22 2015 -0700 +++ b/debug.c Sun Jul 26 13:25:31 2015 -0700 @@ -7,6 +7,8 @@ #include #endif #include "render.h" +#include "util.h" +#include "terminal.h" static bp_def * breakpoints = NULL; static bp_def * zbreakpoints = NULL; @@ -286,6 +288,7 @@ static uint16_t branch_t; static uint16_t branch_f; z80inst inst; + init_terminal(); //Check if this is a user set breakpoint, or just a temporary one bp_def ** this_bp = find_breakpoint(&zbreakpoints, address); if (*this_bp) { @@ -298,15 +301,12 @@ pc = z80_ram + (address & 0x1FFF); } else if (address >= 0x8000) { if (context->bank_reg < (0x400000 >> 15)) { - fprintf(stderr, "Entered Z80 debugger in banked memory address %X, which is not yet supported\n", address); - exit(1); + fatal_error("Entered Z80 debugger in banked memory address %X, which is not yet supported\n", address); } else { - fprintf(stderr, "Entered Z80 debugger in banked memory address %X, but the bank is not pointed to a cartridge address\n", address); - exit(1); + fatal_error("Entered Z80 debugger in banked memory address %X, but the bank is not pointed to a cartridge address\n", address); } } else { - fprintf(stderr, "Entered Z80 debugger at address %X\n", address); - exit(1); + fatal_error("Entered Z80 debugger at address %X\n", address); } for (disp_def * cur = zdisplays; cur; cur = cur->next) { zdebugger_print(context, cur->format_char, cur->param); @@ -475,6 +475,9 @@ static uint32_t branch_t; static uint32_t branch_f; m68kinst inst; + + init_terminal(); + sync_components(context, 0); //probably not necessary, but let's play it safe address &= 0xFFFFFF; @@ -504,8 +507,7 @@ } else if(address > 0xE00000) { pc = ram + (address & 0xFFFF)/2; } else { - fprintf(stderr, "Entered 68K debugger at address %X\n", address); - exit(1); + fatal_error("Entered 68K debugger at address %X\n", address); } uint16_t * after_pc = m68k_decode(pc, &inst, address); m68k_disasm(&inst, input_buf); diff -r 062a2199daf6 -r 0b692b5d154b gdb_remote.c --- a/gdb_remote.c Sun Jul 26 13:08:22 2015 -0700 +++ b/gdb_remote.c Sun Jul 26 13:25:31 2015 -0700 @@ -6,6 +6,7 @@ #include "gdb_remote.h" #include "68kinst.h" #include "debug.h" +#include "util.h" #include #include #include @@ -76,8 +77,7 @@ void write_or_die(int fd, const void *buf, size_t count) { if (write(fd, buf, count) < count) { - fputs("Error writing to stdout\n", stderr); - exit(1); + fatal_error("Error writing to stdout\n"); } } @@ -186,8 +186,7 @@ } else if(pc > 0xE00000) { pc_ptr = ram + (pc & 0xFFFF)/2; } else { - fprintf(stderr, "Entered gdb remote debugger stub at address %X\n", pc); - exit(1); + fatal_error("Entered gdb remote debugger stub at address %X\n", pc); } uint16_t * after_pc = m68k_decode(pc_ptr, &inst, pc & 0xFFFFFF); uint32_t after = pc + (after_pc-pc_ptr)*2; @@ -407,8 +406,7 @@ } else if(pc > 0xE00000) { pc_ptr = ram + (pc & 0xFFFF)/2; } else { - fprintf(stderr, "Entered gdb remote debugger stub at address %X\n", pc); - exit(1); + fatal_error("Entered gdb remote debugger stub at address %X\n", pc); } uint16_t * after_pc = m68k_decode(pc_ptr, &inst, pc & 0xFFFFFF); uint32_t after = pc + (after_pc-pc_ptr)*2; @@ -452,8 +450,7 @@ } return; not_impl: - fprintf(stderr, "Command %s is not implemented, exiting...\n", command); - exit(1); + fatal_error("Command %s is not implemented, exiting...\n", command); } m68k_context * gdb_debug_enter(m68k_context * context, uint32_t pc) @@ -516,8 +513,7 @@ *curbuf = 0; //send acknowledgement if (write(STDOUT_FILENO, "+", 1) < 1) { - fputs("Error writing to stdout\n", stderr); - exit(1); + fatal_error("Error writing to stdout\n"); } gdb_run_command(context, pc, start); curbuf += 2; diff -r 062a2199daf6 -r 0b692b5d154b gen.c --- a/gen.c Sun Jul 26 13:08:22 2015 -0700 +++ b/gen.c Sun Jul 26 13:25:31 2015 -0700 @@ -2,14 +2,14 @@ #include #include "gen.h" #include "mem.h" +#include "util.h" void init_code_info(code_info *code) { size_t size = CODE_ALLOC_SIZE; code->cur = alloc_code(&size); if (!code->cur) { - fputs("Failed to allocate memory for generated code\n", stderr); - exit(1); + fatal_error("Failed to allocate memory for generated code\n"); } code->last = code->cur + size/sizeof(code_word) - RESERVE_WORDS; } diff -r 062a2199daf6 -r 0b692b5d154b gen_arm.c --- a/gen_arm.c Sun Jul 26 13:08:22 2015 -0700 +++ b/gen_arm.c Sun Jul 26 13:25:31 2015 -0700 @@ -76,8 +76,7 @@ size_t size = CODE_ALLOC_SIZE; uint32_t *next_code = alloc_code(&size); if (!next_code) { - fputs("Failed to allocate memory for generated code\n", stderr); - exit(1); + fatal_error("Failed to allocate memory for generated code\n"); } if (next_code = code->last + RESERVE_WORDS) { //new chunk is contiguous with the current one diff -r 062a2199daf6 -r 0b692b5d154b gen_x86.c --- a/gen_x86.c Sun Jul 26 13:08:22 2015 -0700 +++ b/gen_x86.c Sun Jul 26 13:25:31 2015 -0700 @@ -5,6 +5,7 @@ */ #include "gen_x86.h" #include "mem.h" +#include "util.h" #include #include #include @@ -187,8 +188,7 @@ disp >>= 8; *(out++) = disp; } else { - fprintf(stderr, "jmp: %p - %p = %lX\n", dest, out + 6, (long)disp); - exit(1); + fatal_error("jmp: %p - %p = %l which is out of range of a 32-bit displacementX\n", dest, out + 6, (long)disp); } } code->cur = out; @@ -200,8 +200,7 @@ size_t size = CODE_ALLOC_SIZE; code_ptr next_code = alloc_code(&size); if (!next_code) { - fputs("Failed to allocate memory for generated code\n", stderr); - exit(1); + fatal_error("Failed to allocate memory for generated code\n"); } if (next_code != code->last + RESERVE_WORDS) { //new chunk is not contiguous with the current one @@ -231,8 +230,7 @@ #ifdef X86_64 *out = PRE_REX; if (src >= AH && src <= BH || dst >= AH && dst <= BH) { - fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); - exit(1); + fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); } if (size == SZ_Q) { *out |= REX_QUAD; @@ -247,8 +245,7 @@ } out++; #else - fprintf(stderr, "Instruction requires REX prefix but this is a 32-bit build | opcode: %X, src: %s, dst: %s, size: %s\n", opcode, x86_reg_names[src], x86_reg_names[dst], x86_sizes[size]); - exit(1); + fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X, src: %s, dst: %s, size: %s\n", opcode, x86_reg_names[src], x86_reg_names[dst], x86_sizes[size]); #endif } if (size == SZ_B) { @@ -284,8 +281,7 @@ #ifdef X86_64 *out = PRE_REX; if (reg >= AH && reg <= BH) { - fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); - exit(1); + fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); } if (size == SZ_Q) { *out |= REX_QUAD; @@ -300,8 +296,7 @@ } out++; #else - fprintf(stderr, "Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, base: %s, size: %s\n", opcode, x86_reg_names[reg], x86_reg_names[base], x86_sizes[size]); - exit(1); + fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, base: %s, size: %s\n", opcode, x86_reg_names[reg], x86_reg_names[base], x86_sizes[size]); #endif } if (size == SZ_B) { @@ -349,8 +344,7 @@ #ifdef X86_64 *out = PRE_REX; if (reg >= AH && reg <= BH) { - fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); - exit(1); + fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); } if (size == SZ_Q) { *out |= REX_QUAD; @@ -365,8 +359,7 @@ } out++; #else - fprintf(stderr, "Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, base: %s, size: %s\n", opcode, x86_reg_names[reg], x86_reg_names[base], x86_sizes[size]); - exit(1); + fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, base: %s, size: %s\n", opcode, x86_reg_names[reg], x86_reg_names[base], x86_sizes[size]); #endif } if (size == SZ_B) { @@ -405,8 +398,7 @@ #ifdef X86_64 *out = PRE_REX; if (reg >= AH && reg <= BH) { - fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); - exit(1); + fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); } if (size == SZ_Q) { *out |= REX_QUAD; @@ -425,8 +417,7 @@ } out++; #else - fprintf(stderr, "Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, base: %s, size: %s\n", opcode, x86_reg_names[reg], x86_reg_names[base], x86_sizes[size]); - exit(1); + fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, base: %s, size: %s\n", opcode, x86_reg_names[reg], x86_reg_names[base], x86_sizes[size]); #endif } if (size == SZ_B) { @@ -461,8 +452,7 @@ #ifdef X86_64 *out = PRE_REX; if (dst >= AH && dst <= BH) { - fprintf(stderr, "attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); - exit(1); + fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode); } if (size == SZ_Q) { *out |= REX_QUAD; @@ -473,8 +463,7 @@ } out++; #else - fprintf(stderr, "Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, opex, x86_reg_names[dst], x86_sizes[size]); - exit(1); + fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, opex, x86_reg_names[dst], x86_sizes[size]); #endif } if (size == SZ_B) { @@ -509,8 +498,7 @@ } out++; #else - fprintf(stderr, "Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, opex, x86_reg_names[dst], x86_sizes[size]); - exit(1); + fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, opex, x86_reg_names[dst], x86_sizes[size]); #endif } if (size != SZ_B) { @@ -549,8 +537,7 @@ #ifdef X86_64 *out = PRE_REX | REX_QUAD; #else - fprintf(stderr, "Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, size: %s\n", al_opcode, x86_reg_names[dst], x86_sizes[size]); - exit(1); + fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, size: %s\n", al_opcode, x86_reg_names[dst], x86_sizes[size]); #endif } } @@ -568,8 +555,7 @@ } out++; #else - fprintf(stderr, "Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, op_ex, x86_reg_names[dst], x86_sizes[size]); - exit(1); + fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, op_ex, x86_reg_names[dst], x86_sizes[size]); #endif } if (dst >= AH && dst <= BH) { @@ -620,8 +606,7 @@ } out++; #else - fprintf(stderr, "Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, op_ex, x86_reg_names[dst], x86_sizes[size]); - exit(1); + fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, op_ex, x86_reg_names[dst], x86_sizes[size]); #endif } if (size != SZ_B) { @@ -1921,8 +1906,7 @@ disp >>= 8; *(out++) = disp; } else { - fprintf(stderr, "jcc: %p - %p = %lX\n", dest, out + 6, (long)disp); - exit(1); + fatal_error("jcc: %p - %p = %lX which is out of range for a 32-bit displacement\n", dest, out + 6, (long)disp); } } code->cur = out; @@ -1948,8 +1932,7 @@ disp >>= 8; *(out++) = disp; } else { - fprintf(stderr, "jmp: %p - %p = %lX\n", dest, out + 6, (long)disp); - exit(1); + fatal_error("jmp: %p - %p = %lX which is out of range for a 32-bit displacement\n", dest, out + 6, (long)disp); } } code->cur = out; @@ -1997,8 +1980,7 @@ *(out++) = disp; } else { //TODO: Implement far call??? - fprintf(stderr, "%p - %p = %lX\n", fun, out + 5, (long)disp); - exit(1); + fatal_error("call: %p - %p = %lX which is out of range for a 32-bit displacement\n", fun, out + 5, (long)disp); } code->cur = out; } diff -r 062a2199daf6 -r 0b692b5d154b m68k_core.c --- a/m68k_core.c Sun Jul 26 13:08:22 2015 -0700 +++ b/m68k_core.c Sun Jul 26 13:25:31 2015 -0700 @@ -8,6 +8,7 @@ #include "68kinst.h" #include "backend.h" #include "gen.h" +#include "util.h" #include #include #include @@ -174,8 +175,7 @@ break; default: m68k_disasm(inst, disasm_buf); - printf("%X: %s\naddress mode %d not implemented (lea src)\n", inst->address, disasm_buf, inst->src.addr_mode); - exit(1); + fatal_error("%X: %s\naddress mode %d not implemented (lea src)\n", inst->address, disasm_buf, inst->src.addr_mode); } if (inst->op == M68K_PEA) { subi_areg(opts, 4, 7); @@ -283,8 +283,7 @@ break; default: m68k_disasm(inst, disasm_buf); - printf("%s\naddress mode %d not yet supported (%s)\n", disasm_buf, inst->src.addr_mode, is_jsr ? "jsr" : "jmp"); - exit(1); + fatal_error("%s\naddress mode %d not yet supported (%s)\n", disasm_buf, inst->src.addr_mode, is_jsr ? "jsr" : "jmp"); } } @@ -410,8 +409,7 @@ break; default: m68k_disasm(inst, disasm_buf); - printf("%X: %s\naddress mode %d not implemented (movem dst)\n", inst->address, disasm_buf, inst->dst.addr_mode); - exit(1); + fatal_error("%X: %s\naddress mode %d not implemented (movem dst)\n", inst->address, disasm_buf, inst->dst.addr_mode); } if (inst->dst.addr_mode == MODE_AREG_PREDEC) { reg = 15; @@ -481,8 +479,7 @@ break; default: m68k_disasm(inst, disasm_buf); - printf("%X: %s\naddress mode %d not implemented (movem src)\n", inst->address, disasm_buf, inst->src.addr_mode); - exit(1); + fatal_error("%X: %s\naddress mode %d not implemented (movem src)\n", inst->address, disasm_buf, inst->src.addr_mode); } cycles(&opts->gen, early_cycles); for(reg = 0; reg < 16; reg ++) { @@ -830,8 +827,7 @@ translate_m68k_unary(opts, inst, info->impl.flag_mask, inst->dst.addr_mode != MODE_UNUSED ? &dst_op : &src_op); } else { m68k_disasm(inst, disasm_buf); - printf("%X: %s\ninstruction %d not yet implemented\n", inst->address, disasm_buf, inst->op); - exit(1); + fatal_error("%X: %s\ninstruction %d not yet implemented\n", inst->address, disasm_buf, inst->op); } } diff -r 062a2199daf6 -r 0b692b5d154b m68k_core_x86.c --- a/m68k_core_x86.c Sun Jul 26 13:08:22 2015 -0700 +++ b/m68k_core_x86.c Sun Jul 26 13:25:31 2015 -0700 @@ -9,6 +9,7 @@ #include "68kinst.h" #include "mem.h" #include "backend.h" +#include "util.h" #include #include #include @@ -507,8 +508,7 @@ return; default: m68k_disasm(inst, disasm_buf); - printf("%X: %s\naddress mode %d not implemented (%s)\n", inst->address, disasm_buf, op->addr_mode, dst ? "dst" : "src"); - exit(1); + fatal_error("%X: %s\naddress mode %d not implemented (%s)\n", inst->address, disasm_buf, op->addr_mode, dst ? "dst" : "src"); } if (!dst && inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) { if (ea->mode == MODE_REG_DIRECT) { @@ -684,8 +684,7 @@ break; default: m68k_disasm(inst, disasm_buf); - printf("%X: %s\naddress mode %d not implemented (move dst)\n", inst->address, disasm_buf, inst->dst.addr_mode); - exit(1); + fatal_error("%X: %s\naddress mode %d not implemented (move dst)\n", inst->address, disasm_buf, inst->dst.addr_mode); } if (inst->dst.addr_mode != MODE_AREG) { diff -r 062a2199daf6 -r 0b692b5d154b menu.s68 --- a/menu.s68 Sun Jul 26 13:08:22 2015 -0700 +++ b/menu.s68 Sun Jul 26 13:25:31 2015 -0700 @@ -196,7 +196,7 @@ move.w d1, (a0) addq #1, d2 move.l d2, d1 - ;add.w d1, d1 + ;switch to other plane and.w #$FFFE, d1 swap d1 eor.l #$20000000, d3 @@ -205,7 +205,9 @@ bra .loop .newline moveq #0, d2 + ;switch back to plane A and.l #$DFFFFFFF, d3 + ;skip to next row add.l #$00800000, d3 move.l d3, (a1) bra .loop diff -r 062a2199daf6 -r 0b692b5d154b render.h --- a/render.h Sun Jul 26 13:08:22 2015 -0700 +++ b/render.h Sun Jul 26 13:25:31 2015 -0700 @@ -50,7 +50,9 @@ int render_joystick_num_hats(int joystick); int render_num_joysticks(); void process_events(); - +void render_errorbox(char *title, char *message); +void render_warnbox(char *title, char *message); +void render_infobox(char *title, char *message); #endif //RENDER_H_ diff -r 062a2199daf6 -r 0b692b5d154b render_sdl.c --- a/render_sdl.c Sun Jul 26 13:08:22 2015 -0700 +++ b/render_sdl.c Sun Jul 26 13:25:31 2015 -0700 @@ -220,15 +220,14 @@ #ifdef DISABLE_OPENGL SDL_DestroyTexture(main_texture); #endif - SDL_Quit(); } void render_init(int width, int height, char * title, uint32_t fps, uint8_t fullscreen) { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) { - fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); - exit(1); + fatal_error("Unable to init SDL: %s\n", SDL_GetError()); } + atexit(SDL_Quit); printf("width: %d, height: %d\n", width, height); uint32_t flags = 0; @@ -255,15 +254,12 @@ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); main_window = SDL_CreateWindow(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, flags); if (!main_window) { - fprintf(stderr, "Unable to create SDL window: %s\n", SDL_GetError()); - SDL_Quit(); - exit(1); + fatal_error("Unable to create SDL window: %s\n", SDL_GetError()); } main_context = SDL_GL_CreateContext(main_window); GLenum res = glewInit(); if (res != GLEW_OK) { fprintf(stderr, "Initialization of GLEW failed with code %d\n", res); - SDL_DestroyWindow(main_window); } if (GLEW_VERSION_2_0) { @@ -361,9 +357,7 @@ desired.userdata = NULL; if (SDL_OpenAudio(&desired, &actual) < 0) { - fprintf(stderr, "Unable to open SDL audio: %s\n", SDL_GetError()); - SDL_Quit(); - exit(1); + fatal_error("Unable to open SDL audio: %s\n", SDL_GetError()); } buffer_samples = actual.samples; sample_rate = actual.freq; @@ -640,4 +634,18 @@ return sample_rate; } +void render_errorbox(char *title, char *message) +{ + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, message, NULL); +} +void render_warnbox(char *title, char *message) +{ + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, title, message, NULL); +} + +void render_infobox(char *title, char *message) +{ + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, title, message, NULL); +} + diff -r 062a2199daf6 -r 0b692b5d154b romdb.c --- a/romdb.c Sun Jul 26 13:08:22 2015 -0700 +++ b/romdb.c Sun Jul 26 13:25:31 2015 -0700 @@ -317,8 +317,7 @@ genesis_context *gen = ((m68k_context *)context)->system; eeprom_map *map = find_eeprom_map(address, gen); if (!map) { - fprintf(stderr, "Could not find EEPROM map for address %X\n", address); - exit(1); + fatal_error("Could not find EEPROM map for address %X\n", address); } if (map->scl_mask) { set_scl(&gen->eeprom, (value & map->scl_mask) != 0); @@ -334,8 +333,7 @@ genesis_context *gen = ((m68k_context *)context)->system; eeprom_map *map = find_eeprom_map(address, gen); if (!map) { - fprintf(stderr, "Could not find EEPROM map for address %X\n", address); - exit(1); + fatal_error("Could not find EEPROM map for address %X\n", address); } uint16_t expanded, mask; @@ -360,8 +358,7 @@ genesis_context *gen = ((m68k_context *)context)->system; eeprom_map *map = find_eeprom_map(address, gen); if (!map) { - fprintf(stderr, "Could not find EEPROM map for address %X\n", address); - exit(1); + fatal_error("Could not find EEPROM map for address %X\n", address); } uint16_t ret = 0; if (map->sda_read_bit < 16) { @@ -375,8 +372,7 @@ genesis_context *gen = ((m68k_context *)context)->system; eeprom_map *map = find_eeprom_map(address, gen); if (!map) { - fprintf(stderr, "Could not find EEPROM map for address %X\n", address); - exit(1); + fatal_error("Could not find EEPROM map for address %X\n", address); } uint8_t bit = address & 1 ? map->sda_read_bit : map->sda_read_bit - 8; uint8_t ret = 0; @@ -390,14 +386,13 @@ { char *exe_dir = get_exe_dir(); if (!exe_dir) { - fputs("Failed to find executable path\n", stderr); - exit(1); + fatal_error("Failed to find executable path\n"); } char *path = alloc_concat(exe_dir, "/rom.db"); tern_node *db = parse_config_file(path); free(path); if (!db) { - fputs("Failed to load ROM DB\n", stderr); + fatal_error("Failed to load ROM DB\n"); } return db; } @@ -615,13 +610,11 @@ if (!state->info->save_size) { char * size = tern_find_path(state->root, "SRAM\0size\0").ptrval; if (!size) { - fprintf(stderr, "ROM DB map entry %d with address %s has device type SRAM, but the SRAM size is not defined\n", state->index, key); - exit(1); + fatal_error("ROM DB map entry %d with address %s has device type SRAM, but the SRAM size is not defined\n", state->index, key); } state->info->save_size = atoi(size); if (!state->info->save_size) { - fprintf(stderr, "SRAM size %s is invalid\n", size); - exit(1); + fatal_error("SRAM size %s is invalid\n", size); } state->info->save_mask = nearest_pow2(state->info->save_size)-1; state->info->save_buffer = malloc(state->info->save_size); @@ -642,13 +635,11 @@ if (!state->info->save_size) { char * size = tern_find_path(state->root, "EEPROM\0size\0").ptrval; if (!size) { - fprintf(stderr, "ROM DB map entry %d with address %s has device type EEPROM, but the EEPROM size is not defined\n", state->index, key); - exit(1); + fatal_error("ROM DB map entry %d with address %s has device type EEPROM, but the EEPROM size is not defined\n", state->index, key); } state->info->save_size = atoi(size); if (!state->info->save_size) { - fprintf(stderr, "EEPROM size %s is invalid\n", size); - exit(1); + fatal_error("EEPROM size %s is invalid\n", size); } char *etype = tern_find_path(state->root, "EEPROM\0type\0").ptrval; if (!etype) { @@ -657,8 +648,7 @@ if (!strcmp(etype, "i2c")) { state->info->save_type = SAVE_I2C; } else { - fprintf(stderr, "EEPROM type %s is invalid\n", etype); - exit(1); + fatal_error("EEPROM type %s is invalid\n", etype); } state->info->save_buffer = malloc(state->info->save_size); memset(state->info->save_buffer, 0xFF, state->info->save_size); @@ -690,14 +680,12 @@ map_iter_state *state = data; tern_node *node = tern_get_node(val); if (!node) { - fprintf(stderr, "ROM DB map entry %d with address %s is not a node\n", state->index, key); - exit(1); + fatal_error("ROM DB map entry %d with address %s is not a node\n", state->index, key); } uint32_t start = strtol(key, NULL, 16); uint32_t end = strtol(tern_find_ptr_default(node, "last", "0"), NULL, 16); if (!end || end < start) { - fprintf(stderr, "'last' value is missing or invalid for ROM DB map entry %d with address %s\n", state->index, key); - exit(1); + fatal_error("'last' value is missing or invalid for ROM DB map entry %d with address %s\n", state->index, key); } char * dtype = tern_find_ptr_default(node, "device", "ROM"); uint32_t offset = strtol(tern_find_ptr_default(node, "offset", "0"), NULL, 16); @@ -769,8 +757,7 @@ map->write_16 = (write_16_fun)write_bank_reg_w; map->write_8 = (write_8_fun)write_bank_reg_b; } else { - fprintf(stderr, "Invalid device type for ROM DB map entry %d with address %s\n", state->index, key); - exit(1); + fatal_error("Invalid device type for ROM DB map entry %d with address %s\n", state->index, key); } state->index++; } diff -r 062a2199daf6 -r 0b692b5d154b stateview.c --- a/stateview.c Sun Jul 26 13:08:22 2015 -0700 +++ b/stateview.c Sun Jul 26 13:25:31 2015 -0700 @@ -7,6 +7,7 @@ #include #include "vdp.h" #include "render.h" +#include "util.h" #include "blastem.h" //not used, but referenced by the renderer since it handles input @@ -61,13 +62,11 @@ int main(int argc, char ** argv) { if (argc < 2) { - fprintf(stderr, "Usage: stateview FILENAME\n"); - exit(1); + fatal_error("Usage: stateview FILENAME\n"); } FILE * state_file = fopen(argv[1], "rb"); if (!state_file) { - fprintf(stderr, "Failed to open %s\n", argv[1]); - exit(1); + fatal_error("Failed to open %s\n", argv[1]); } config = load_config(argv[0]); int width = -1; diff -r 062a2199daf6 -r 0b692b5d154b termhelper.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/termhelper.c Sun Jul 26 13:25:31 2015 -0700 @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include +#include "terminal.h" + +char buf[4096]; + +void copy_data(int to, int from) +{ + ssize_t bytes = read(from, buf, sizeof(buf)); + while (bytes > 0) + { + ssize_t written = write(to, buf, bytes); + if (written == -1) { + exit(1); + } + bytes -= written; + } +} + +int main(int argc, char **argv) +{ + //these will block so order is important + int input_fd = open(INPUT_PATH, O_WRONLY); + int output_fd = open(OUTPUT_PATH, O_RDONLY); + fd_set read_fds; + FD_ZERO(&read_fds); + for (;;) + { + FD_SET(STDIN_FILENO, &read_fds); + FD_SET(output_fd, &read_fds); + select(output_fd+1, &read_fds, NULL, NULL, NULL); + + if (FD_ISSET(STDIN_FILENO, &read_fds)) { + copy_data(input_fd, STDIN_FILENO); + } + if (FD_ISSET(output_fd, &read_fds)) { + copy_data(STDOUT_FILENO, output_fd); + } + } + return 0; +} diff -r 062a2199daf6 -r 0b692b5d154b terminal.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/terminal.c Sun Jul 26 13:25:31 2015 -0700 @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include +#include +#include +#include "util.h" +#include "terminal.h" + +pid_t child; + +void cleanup_terminal() +{ + kill(child, SIGKILL); + unlink(INPUT_PATH); + unlink(OUTPUT_PATH); +} + +void init_terminal() +{ + static char init_done; + if (!init_done) { + if (!(isatty(STDIN_FILENO) && isatty(STDOUT_FILENO))) { +#ifndef __APPLE__ + //check to see if x-terminal-emulator exists, just use xterm if it doesn't + char *term = system("which x-terminal-emulator > /dev/null") ? "xterm" : "x-terminal-emulator"; +#endif + //get rid of FIFO's if they already exist + unlink(INPUT_PATH); + unlink(OUTPUT_PATH); + //create FIFOs for talking to helper process in terminal app + mkfifo(INPUT_PATH, 0666); + mkfifo(OUTPUT_PATH, 0666); + + //close existing file descriptors + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + + child = fork(); + if (child == -1) { + //error, oh well + warning("Failed to fork for terminal spawn"); + } else if (!child) { + //child process, exec our terminal emulator +#ifdef __APPLE__ + execlp("open", "open", "./termhelper", NULL); +#else + execlp(term, term, "-title", "BlastEm Debugger", "-e", "./termhelper", NULL); +#endif + } else { + //connect to the FIFOs, these will block so order is important + open(INPUT_PATH, O_RDONLY); + open(OUTPUT_PATH, O_WRONLY); + atexit(cleanup_terminal); + if (-1 == dup(STDOUT_FILENO)) { + fatal_error("failed to dup STDOUT to STDERR after terminal fork"); + } + } + } + + init_done = 1; + } +} diff -r 062a2199daf6 -r 0b692b5d154b terminal.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/terminal.h Sun Jul 26 13:25:31 2015 -0700 @@ -0,0 +1,9 @@ +#ifndef TERMINAL_H_ +#define TERMINAL_H_ + +void init_terminal(); + +#define INPUT_PATH "/tmp/blastem_input" +#define OUTPUT_PATH "/tmp/blastem_output" + +#endif //TERMINAL_H_ diff -r 062a2199daf6 -r 0b692b5d154b terminal_win.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/terminal_win.c Sun Jul 26 13:25:31 2015 -0700 @@ -0,0 +1,13 @@ +#include +#include + +void init_terminal() +{ + static init_done; + if (!init_done) { + AllocConsole(); + freopen("CONIN$", "r", stdin); + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + } +} diff -r 062a2199daf6 -r 0b692b5d154b tern.c --- a/tern.c Sun Jul 26 13:08:22 2015 -0700 +++ b/tern.c Sun Jul 26 13:25:31 2015 -0700 @@ -8,6 +8,7 @@ #include #include #include +#include "util.h" tern_node * tern_insert(tern_node * head, char * key, tern_val value) { @@ -190,8 +191,7 @@ } if (head->el) { if (pos == MAX_ITER_KEY) { - fputs("exceeded maximum key size", stderr); - exit(1); + fatal_error("tern_foreach_int: exceeded maximum key size"); } keybuf[pos] = head->el; tern_foreach_int(head->straight.next, fun, data, keybuf, pos+1); diff -r 062a2199daf6 -r 0b692b5d154b util.c --- a/util.c Sun Jul 26 13:08:22 2015 -0700 +++ b/util.c Sun Jul 26 13:25:31 2015 -0700 @@ -8,6 +8,9 @@ #include #include +#include "blastem.h" //for headless global +#include "render.h" //for render_errorbox + char * alloc_concat(char * first, char * second) { int flen = strlen(first); @@ -86,6 +89,91 @@ exe_str = str; } +void fatal_error(char *format, ...) +{ + va_list args; + va_start(args, format); + if (!headless) { + //take a guess at the final size + size_t size = strlen(format) * 2; + char *buf = malloc(size); + size_t actual = vsnprintf(buf, size, format, args); + if (actual >= size) { + actual++; + free(buf); + buf = malloc(actual); + va_end(args); + va_start(args, format); + vsnprintf(buf, actual, format, args); + } + fputs(buf, stderr); + render_errorbox("Fatal Error", buf); + free(buf); + } else { + vfprintf(stderr, format, args); + } + va_end(args); + exit(1); +} + +void warning(char *format, ...) +{ + va_list args; + va_start(args, format); +#ifndef _WIN32 + if (headless || (isatty(STDERR_FILENO) && isatty(STDIN_FILENO))) { + vfprintf(stderr, format, args); + } else { +#endif + size_t size = strlen(format) * 2; + char *buf = malloc(size); + size_t actual = vsnprintf(buf, size, format, args); + if (actual >= size) { + actual++; + free(buf); + buf = malloc(actual); + va_end(args); + va_start(args, format); + vsnprintf(buf, actual, format, args); + } + fputs(buf, stderr); + render_infobox("BlastEm Info", buf); + free(buf); +#ifndef _WIN32 + } +#endif + va_end(args); +} + +void info_message(char *format, ...) +{ + va_list args; + va_start(args, format); +#ifndef _WIN32 + if (headless || (isatty(STDOUT_FILENO) && isatty(STDIN_FILENO))) { + vprintf(format, args); + } else { +#endif + size_t size = strlen(format) * 2; + char *buf = malloc(size); + size_t actual = vsnprintf(buf, size, format, args); + if (actual >= size) { + actual++; + free(buf); + buf = malloc(actual); + va_end(args); + va_start(args, format); + vsnprintf(buf, actual, format, args); + } + fputs(buf, stdout); + render_infobox("BlastEm Info", buf); + free(buf); +#ifndef _WIN32 + } +#endif + va_end(args); +} + #ifdef _WIN32 #include #include diff -r 062a2199daf6 -r 0b692b5d154b util.h --- a/util.h Sun Jul 26 13:08:22 2015 -0700 +++ b/util.h Sun Jul 26 13:25:31 2015 -0700 @@ -25,5 +25,11 @@ char * get_home_dir(); //Returns the contents of a symlink in a newly allocated string char * readlink_alloc(char * path); +//Prints an error message to stderr and to a message box if not in headless mode and then exits +void fatal_error(char *format, ...); +//Prints an information message to stdout and to a message box if not in headless mode and not attached to a console +void info_message(char *format, ...); +//Prints an information message to stderr and to a message box if not in headless mode and not attached to a console +void warning(char *format, ...); #endif //UTIL_H_ diff -r 062a2199daf6 -r 0b692b5d154b vgmplay.c --- a/vgmplay.c Sun Jul 26 13:08:22 2015 -0700 +++ b/vgmplay.c Sun Jul 26 13:25:31 2015 -0700 @@ -7,6 +7,7 @@ #include "ym2612.h" #include "psg.h" #include "config.h" +#include "util.h" #include #include @@ -282,8 +283,7 @@ wait(&y_context, &p_context, ¤t_cycle, wait_time); } } else { - printf("unimplemented command: %X at offset %X\n", cmd, (unsigned int)(cur - data - 1)); - exit(1); + fatal_error("unimplemented command: %X at offset %X\n", cmd, (unsigned int)(cur - data - 1)); } } } diff -r 062a2199daf6 -r 0b692b5d154b z80_to_x86.c --- a/z80_to_x86.c Sun Jul 26 13:08:22 2015 -0700 +++ b/z80_to_x86.c Sun Jul 26 13:25:31 2015 -0700 @@ -7,6 +7,7 @@ #include "z80_to_x86.h" #include "gen_x86.h" #include "mem.h" +#include "util.h" #include #include #include @@ -256,8 +257,7 @@ ea->mode = MODE_UNUSED; break; default: - fprintf(stderr, "Unrecognized Z80 addressing mode %d\n", inst->addr_mode & 0x1F); - exit(1); + fatal_error("Unrecognized Z80 addressing mode %d\n", inst->addr_mode & 0x1F); } } @@ -1939,11 +1939,10 @@ default: { char disbuf[80]; z80_disasm(inst, disbuf, address); - fprintf(stderr, "unimplemented instruction: %s at %X\n", disbuf, address); FILE * f = fopen("zram.bin", "wb"); fwrite(context->mem_pointers[0], 1, 8 * 1024, f); fclose(f); - exit(1); + fatal_error("unimplemented Z80 instruction: %s at %X\nZ80 RAM has been saved to zram.bin for debugging", disbuf, address); } } } @@ -1952,8 +1951,7 @@ { if (!context->interp_code[opcode]) { if (opcode == 0xCB || (opcode >= 0xDD && (opcode & 0xF) == 0xD)) { - fprintf(stderr, "Encountered prefix byte %X at address %X. Z80 interpeter doesn't support those yet.", opcode, context->pc); - exit(1); + fatal_error("Encountered prefix byte %X at address %X. Z80 interpeter doesn't support those yet.", opcode, context->pc); } uint8_t codebuf[8]; memset(codebuf, 0, sizeof(codebuf)); @@ -1961,8 +1959,7 @@ z80inst inst; uint8_t * after = z80_decode(codebuf, &inst); if (after - codebuf > 1) { - fprintf(stderr, "Encountered multi-byte Z80 instruction at %X. Z80 interpeter doesn't support those yet.", context->pc); - exit(1); + fatal_error("Encountered multi-byte Z80 instruction at %X. Z80 interpeter doesn't support those yet.", context->pc); } z80_options * opts = context->options; @@ -2243,7 +2240,7 @@ if (opts->gen.deferred) { address = opts->gen.deferred->address; dprintf("defferred address: %X\n", address); - } + } } while (opts->gen.deferred); } @@ -2749,6 +2746,6 @@ opts->gen.code.last = native + 16; check_cycles_int(&opts->gen, address); opts->gen.code = tmp_code; -} + } }