mirror of
https://github.com/libretro/blastem.git
synced 2026-11-07 10:15:58 -10:00
Spawn a terminal for the debugger when needed if we are not already attached to one
This commit is contained in:
1 parent
25fc1e88de
commit
bee8b42029
8 files changed
+175
-3
No files matched your search
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
+65
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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_
|
||||
Reference in new issue
Block a user