changeset 794:792be135d3af

Spawn a terminal for the debugger when needed if we are not already attached to one
author Michael Pavone <pavone@retrodev.com>
date Sun, 26 Jul 2015 01:11:04 -0700
parents 9aff36a172b2
children 0b692b5d154b
files Makefile debug.c termhelper.c terminal.c terminal.h terminal_win.c util.c util.h
diffstat 8 files changed, 175 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Sun Jul 26 01:09:05 2015 -0700
+++ b/Makefile	Sun Jul 26 01:11:04 2015 -0700
@@ -5,6 +5,7 @@
 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 @@
 else
 
 MEM:=mem.o
+TERMINAL:=terminal.o
 BLASTEM:=blastem
 
 ifeq ($(OS),Darwin)
@@ -99,7 +101,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
@@ -119,9 +121,12 @@
 
 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 @@
 	vasmz80_mot -Fbin -spaces -o $@ $<
 
 clean :
-	rm -rf dis trans stateview test_x86 gen_fib *.o
+	rm -rf $(ALL) trans ztestrun ztestgen *.o
--- a/debug.c	Sun Jul 26 01:09:05 2015 -0700
+++ b/debug.c	Sun Jul 26 01:11:04 2015 -0700
@@ -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 @@
 	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 @@
 	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;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/termhelper.c	Sun Jul 26 01:11:04 2015 -0700
@@ -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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/terminal.c	Sun Jul 26 01:11:04 2015 -0700
@@ -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;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/terminal.h	Sun Jul 26 01:11:04 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_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/terminal_win.c	Sun Jul 26 01:11:04 2015 -0700
@@ -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);
+	}
+}
--- a/util.c	Sun Jul 26 01:09:05 2015 -0700
+++ b/util.c	Sun Jul 26 01:11:04 2015 -0700
@@ -116,6 +116,35 @@
 	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;
--- a/util.h	Sun Jul 26 01:09:05 2015 -0700
+++ b/util.h	Sun Jul 26 01:11:04 2015 -0700
@@ -29,5 +29,7 @@
 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_