summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Pavone <pavone@retrodev.com>2015-07-26 01:11:04 -0700
committerMichael Pavone <pavone@retrodev.com>2015-07-26 01:11:04 -0700
commitbee8b42029900ca034675c54d98813a61ca4407a (patch)
treeee5d02129ed6f07607bb262b3960e99f3bc379e0
parent25fc1e88deea8253d9d4b8084485e176eb69abd0 (diff)
Spawn a terminal for the debugger when needed if we are not already attached to one
-rw-r--r--Makefile11
-rw-r--r--debug.c5
-rw-r--r--termhelper.c44
-rw-r--r--terminal.c65
-rw-r--r--terminal.h9
-rw-r--r--terminal_win.c13
-rw-r--r--util.c29
-rw-r--r--util.h2
8 files changed, 175 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index 40ffb72..b5b1be9 100644
--- a/Makefile
+++ b/Makefile
@@ -5,6 +5,7 @@ endif
ifeq ($(OS),Windows)
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"C:/MinGW/usr/include/SDL2" -DGLEW_STATIC
@@ -14,6 +15,7 @@ CPU:=i686
else
MEM:=mem.o
+TERMINAL:=terminal.o
BLASTEM:=blastem
ifeq ($(OS),Darwin)
@@ -99,7 +101,7 @@ Z80OBJS=z80inst.o z80_to_x86.o
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
@@ -119,9 +121,12 @@ endif
ifeq ($(OS),Windows)
MAINOBJS+= glew32s.lib
+ALL=$(BLASTEM)
+else
+ALL= dis zdis stateview vgmplay blastem termhelper
endif
-all : dis zdis stateview vgmplay blastem
+all : $(ALL)
$(BLASTEM) : $(MAINOBJS)
$(CC) -o $(BLASTEM) $(MAINOBJS) $(LDFLAGS)
@@ -188,4 +193,4 @@ vos_prog_info : vos_prog_info.o vos_program_module.o
vasmz80_mot -Fbin -spaces -o $@ $<
clean :
- rm -rf dis trans stateview test_x86 gen_fib *.o
+ rm -rf $(ALL) trans ztestrun ztestgen *.o
diff --git a/debug.c b/debug.c
index a70f790..5fedb73 100644
--- a/debug.c
+++ b/debug.c
@@ -8,6 +8,7 @@
#endif
#include "render.h"
#include "util.h"
+#include "terminal.h"
static bp_def * breakpoints = NULL;
static bp_def * zbreakpoints = NULL;
@@ -287,6 +288,7 @@ z80_context * zdebugger(z80_context * context, uint16_t address)
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) {
@@ -473,6 +475,9 @@ m68k_context * debugger(m68k_context * context, uint32_t address)
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;
diff --git a/termhelper.c b/termhelper.c
new file mode 100644
index 0000000..a5cf17c
--- /dev/null
+++ b/termhelper.c
@@ -0,0 +1,44 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#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 --git a/terminal.c b/terminal.c
new file mode 100644
index 0000000..0e952f2
--- /dev/null
+++ b/terminal.c
@@ -0,0 +1,65 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <signal.h>
+#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 --git a/terminal.h b/terminal.h
new file mode 100644
index 0000000..08986c2
--- /dev/null
+++ b/terminal.h
@@ -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 --git a/terminal_win.c b/terminal_win.c
new file mode 100644
index 0000000..120a086
--- /dev/null
+++ b/terminal_win.c
@@ -0,0 +1,13 @@
+#include <windows.h>
+#include <stdio.h>
+
+void init_terminal()
+{
+ static init_done;
+ if (!init_done) {
+ AllocConsole();
+ freopen("CONIN$", "r", stdin);
+ freopen("CONOUT$", "w", stdout);
+ freopen("CONOUT$", "w", stderr);
+ }
+}
diff --git a/util.c b/util.c
index 3ad290d..c0131b2 100644
--- a/util.c
+++ b/util.c
@@ -116,6 +116,35 @@ void fatal_error(char *format, ...)
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;
diff --git a/util.h b/util.h
index 537c97e..ffa3385 100644
--- a/util.h
+++ b/util.h
@@ -29,5 +29,7 @@ char * readlink_alloc(char * path);
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_