diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..75dee188 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "dynstr/dynstr"] + path = dynstr/dynstr + url = https://github.com/XaviDCR92/dynstr +[submodule "gdbstub/gdbstub"] + path = gdbstub/gdbstub + url = https://github.com/XaviDCR92/gdbstub diff --git a/CMakeLists.txt b/CMakeLists.txt index c7f61cc3..2d597443 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,8 @@ add_definitions(-DPACKAGE_NAME="PCSXr") add_definitions(-DPACKAGE_STRING="PCSXr ${PCSXR_VERSION_MAJOR}.${PCSXR_VERSION_MINOR}.${PCSXR_VERSION_PATCH}") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -s") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s") +#uncomment for gdb server debugging +#add_definitions(-DDEBUG=1) include(CheckCCompilerFlag) include(GNUInstallDirs) @@ -51,6 +53,5 @@ add_subdirectory(libpcsxcore) add_subdirectory(gui) add_subdirectory(plugins) add_subdirectory(doc) - - - +add_subdirectory(dynstr) +add_subdirectory(gdbstub) diff --git a/cmake/FindGTK3.cmake b/cmake/FindGTK3.cmake index 049a276f..163d6c01 100644 --- a/cmake/FindGTK3.cmake +++ b/cmake/FindGTK3.cmake @@ -35,7 +35,8 @@ set(GTK3_DEPS GDK3 Pango Cairo - GDKPixbuf) + GDKPixbuf + Harfbuzz) if(PKG_CONFIG_FOUND) pkg_search_module(GTK3_PKG QUIET gtk+-3.0) diff --git a/cmake/FindHarfbuzz.cmake b/cmake/FindHarfbuzz.cmake new file mode 100644 index 00000000..f35598f0 --- /dev/null +++ b/cmake/FindHarfbuzz.cmake @@ -0,0 +1,58 @@ +find_package(PkgConfig) + +set(Harfbuzz_DEPS) + +if(PKG_CONFIG_FOUND) + pkg_search_module(Harfbuzz_PKG harfbuzz) +endif() + +find_library(Harfbuzz_LIBRARY harfbuzz HINTS ${Harfbuzz_PKG_LIBRARY_DIRS}) +set(Harfbuzz harfbuzz) + +if(Harfbuzz_LIBRARY) + add_library(${Harfbuzz} SHARED IMPORTED) + set_property(TARGET ${Harfbuzz} PROPERTY IMPORTED_LOCATION "${Harfbuzz_LIBRARY}") + set_property(TARGET ${Harfbuzz} PROPERTY INTERFACE_COMPILE_OPTIONS "${Harfbuzz_PKG_CFLAGS_OTHER}") + + set(Harfbuzz_INCLUDE_DIRS) + + find_path(Harfbuzz_INCLUDE_DIR "hb.h" + HINTS ${Harfbuzz_PKG_INCLUDE_DIRS}) + + if(Harfbuzz_INCLUDE_DIR) + file(STRINGS "${Harfbuzz_INCLUDE_DIR}/hb-version.h" HB_VERSION_MAJOR REGEX "^#define HB_VERSION_MAJOR +\\(?([0-9]+)\\)?$") + string(REGEX REPLACE "^#define HB_VERSION_MAJOR \\(?([0-9]+)\\)?$" "\\1" HB_VERSION_MAJOR "${HB_VERSION_MAJOR}") + file(STRINGS "${Harfbuzz_INCLUDE_DIR}/hb-version.h" HB_VERSION_MINOR REGEX "^#define HB_VERSION_MINOR +\\(?([0-9]+)\\)?$") + string(REGEX REPLACE "^#define HB_VERSION_MINOR \\(?([0-9]+)\\)?$" "\\1" HB_VERSION_MINOR "${HB_VERSION_MINOR}") + file(STRINGS "${Harfbuzz_INCLUDE_DIR}/hb-version.h" HB_VERSION_MICRO REGEX "^#define HB_VERSION_MICRO +\\(?([0-9]+)\\)?$") + string(REGEX REPLACE "^#define HB_VERSION_MICRO \\(?([0-9]+)\\)?$" "\\1" HB_VERSION_MICRO "${HB_VERSION_MICRO}") + set(Harfbuzz_VERSION "${HB_VERSION_MAJOR}.${HB_VERSION_MINOR}.${HB_VERSION_MICRO}") + unset(HB_VERSION_MAJOR) + unset(HB_VERSION_MINOR) + unset(HB_VERSION_MICRO) + + list(APPEND Harfbuzz_INCLUDE_DIRS ${Harfbuzz_INCLUDE_DIR}) + set_property(TARGET ${Harfbuzz} PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${Harfbuzz_INCLUDE_DIR}") + endif() +endif() + +set(Harfbuzz_DEPS_FOUND_VARS) +foreach(harfbuzz_dep ${Harfbuzz_DEPS}) + find_package(${harfbuzz_dep}) + + list(APPEND Harfbuzz_DEPS_FOUND_VARS "${harfbuzz_dep}_FOUND") + list(APPEND Harfbuzz_INCLUDE_DIRS ${${harfbuzz_dep}_INCLUDE_DIRS}) + + set_property (TARGET ${Harfbuzz} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "${${harfbuzz_dep}}") +endforeach(harfbuzz_dep) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Harfbuzz + REQUIRED_VARS + Harfbuzz_LIBRARY + Harfbuzz_INCLUDE_DIRS + ${Harfbuzz_DEPS_FOUND_VARS} + VERSION_VAR + Harfbuzz_VERSION) + +unset(Harfbuzz_DEPS_FOUND_VARS) diff --git a/dynstr/CMakeLists.txt b/dynstr/CMakeLists.txt new file mode 100644 index 00000000..38313dbc --- /dev/null +++ b/dynstr/CMakeLists.txt @@ -0,0 +1,5 @@ +message(STATUS "* Configuring dynstr") + +set(SRCS dynstr/dynstr.c) +include_directories(dynstr/include) +add_library(dynstr STATIC ${SRCS}) diff --git a/dynstr/dynstr b/dynstr/dynstr new file mode 160000 index 00000000..357d4f2c --- /dev/null +++ b/dynstr/dynstr @@ -0,0 +1 @@ +Subproject commit 357d4f2c0fc52ae7e5967f542161d59d09830e27 diff --git a/gdbstub/CMakeLists.txt b/gdbstub/CMakeLists.txt new file mode 100644 index 00000000..a3f0624a --- /dev/null +++ b/gdbstub/CMakeLists.txt @@ -0,0 +1,5 @@ +message(STATUS "* Configuring gdbstub") + +set(SRCS gdbstub/gdbstub.c gdbstub_sys.c) +include_directories(gdbstub .) +add_library(gdbstub STATIC ${SRCS}) diff --git a/gdbstub/gdbstub b/gdbstub/gdbstub new file mode 160000 index 00000000..1266e617 --- /dev/null +++ b/gdbstub/gdbstub @@ -0,0 +1 @@ +Subproject commit 1266e61757af01485f56b4e5bd3969fdaba9c356 diff --git a/gdbstub/gdbstub_sys.c b/gdbstub/gdbstub_sys.c new file mode 100644 index 00000000..bd966b29 --- /dev/null +++ b/gdbstub/gdbstub_sys.c @@ -0,0 +1,430 @@ +#include "gdbstub_sys.h" +#include "gdbstub.h" +#include "libpcsxcore/socket.h" +#include "libpcsxcore/r3000a.h" +#include +#include +#include + +#ifdef _POSIX_VERSION +#include +#include +#include +#include +#include +#include + +static pthread_t thread; +static mqd_t in_queue = -1, out_queue = -1; +#endif + +static int server_socket = -1, client_socket = -1; +static enum { + PAUSED, +} state; + +static void update_regs(struct dbg_state *const dbg_state) +{ + dbg_state->registers[DBG_CPU_MIPS_I_REG_ZERO] = 0; + dbg_state->registers[DBG_CPU_MIPS_I_REG_AT] = psxRegs.GPR.n.at; + + dbg_state->registers[DBG_CPU_MIPS_I_REG_V0] = psxRegs.GPR.n.v0; + dbg_state->registers[DBG_CPU_MIPS_I_REG_V1] = psxRegs.GPR.n.v1; + + dbg_state->registers[DBG_CPU_MIPS_I_REG_A0] = psxRegs.GPR.n.a0; + dbg_state->registers[DBG_CPU_MIPS_I_REG_A1] = psxRegs.GPR.n.a1; + dbg_state->registers[DBG_CPU_MIPS_I_REG_A2] = psxRegs.GPR.n.a2; + dbg_state->registers[DBG_CPU_MIPS_I_REG_A3] = psxRegs.GPR.n.a3; + + dbg_state->registers[DBG_CPU_MIPS_I_REG_T0] = psxRegs.GPR.n.t0; + dbg_state->registers[DBG_CPU_MIPS_I_REG_T1] = psxRegs.GPR.n.t1; + dbg_state->registers[DBG_CPU_MIPS_I_REG_T2] = psxRegs.GPR.n.t2; + dbg_state->registers[DBG_CPU_MIPS_I_REG_T3] = psxRegs.GPR.n.t3; + dbg_state->registers[DBG_CPU_MIPS_I_REG_T4] = psxRegs.GPR.n.t4; + dbg_state->registers[DBG_CPU_MIPS_I_REG_T5] = psxRegs.GPR.n.t5; + dbg_state->registers[DBG_CPU_MIPS_I_REG_T6] = psxRegs.GPR.n.t6; + dbg_state->registers[DBG_CPU_MIPS_I_REG_T7] = psxRegs.GPR.n.t7; + + dbg_state->registers[DBG_CPU_MIPS_I_REG_S0] = psxRegs.GPR.n.s0; + dbg_state->registers[DBG_CPU_MIPS_I_REG_S1] = psxRegs.GPR.n.s1; + dbg_state->registers[DBG_CPU_MIPS_I_REG_S2] = psxRegs.GPR.n.s2; + dbg_state->registers[DBG_CPU_MIPS_I_REG_S3] = psxRegs.GPR.n.s3; + dbg_state->registers[DBG_CPU_MIPS_I_REG_S4] = psxRegs.GPR.n.s4; + dbg_state->registers[DBG_CPU_MIPS_I_REG_S5] = psxRegs.GPR.n.s5; + dbg_state->registers[DBG_CPU_MIPS_I_REG_S6] = psxRegs.GPR.n.s6; + dbg_state->registers[DBG_CPU_MIPS_I_REG_S7] = psxRegs.GPR.n.s7; + + dbg_state->registers[DBG_CPU_MIPS_I_REG_T8] = psxRegs.GPR.n.t8; + dbg_state->registers[DBG_CPU_MIPS_I_REG_T9] = psxRegs.GPR.n.t9; + + dbg_state->registers[DBG_CPU_MIPS_I_REG_K0] = psxRegs.GPR.n.k0; + dbg_state->registers[DBG_CPU_MIPS_I_REG_K1] = psxRegs.GPR.n.k1; + + dbg_state->registers[DBG_CPU_MIPS_I_REG_GP] = psxRegs.GPR.n.gp; + dbg_state->registers[DBG_CPU_MIPS_I_REG_SP] = psxRegs.GPR.n.sp; + dbg_state->registers[DBG_CPU_MIPS_I_REG_S8] = psxRegs.GPR.n.s8; + dbg_state->registers[DBG_CPU_MIPS_I_REG_RA] = psxRegs.GPR.n.ra; + + dbg_state->registers[DBG_CPU_MIPS_I_REG_SR] = psxRegs.CP0.n.Status; + dbg_state->registers[DBG_CPU_MIPS_I_REG_LO] = psxRegs.GPR.r[32]; + dbg_state->registers[DBG_CPU_MIPS_I_REG_HI] = psxRegs.GPR.r[33]; + dbg_state->registers[DBG_CPU_MIPS_I_REG_BAD] = psxRegs.CP0.n.BadVAddr; + dbg_state->registers[DBG_CPU_MIPS_I_REG_CAUSE] = psxRegs.CP0.n.Cause; + dbg_state->registers[DBG_CPU_MIPS_I_REG_PC] = psxRegs.pc; +} + +static int exit_loop; + +int dbg_sys_getc(void) +{ + while (1) { + char packet; + size_t len = sizeof packet; + SetsBlock(client_socket); + { + const enum read_socket_err err = ReadSocket(client_socket, &packet, &len); + +#ifdef _POSIX_VERSION + if (exit_loop) + pthread_exit(NULL); +#endif + + switch (err) { + case READ_SOCKET_OK: + return packet; + + case READ_SOCKET_SHUTDOWN: { + struct msg msg; + + printf("gdb shutdown\n"); + client_socket = 0; + msg.type = MSG_TYPE_SHUTDOWN; + + if (mq_send(out_queue, (const char *)&msg, sizeof msg, 0)) + perror("dbg_sys_getc() mq_send()"); + return EOF; + } + + case READ_SOCKET_ERR_RECV: + SetsBlock(client_socket); + /* Fall through. */ + case READ_SOCKET_ERR_INVALID_ARG: + /* Fall through. */ + default: + break; + } + } + } +} + +int dbg_sys_putchar(int ch) +{ + WriteSocket(client_socket, (const char *)&ch, sizeof (char)); +} + +int dbg_sys_mem_readb(address addr, char *val) +{ + *val = psxMemRead8(addr); + return 0; +} + +int dbg_sys_mem_writeb(address addr, char val) +{ + psxMemWrite8(addr, val); + return 0; +} + +#ifdef _POSIX_VERSION +static int wait_hit_or_break(struct msg *msg) +{ + do { + int ret = mq_receive(in_queue, (char *)msg, sizeof *msg, 0); + + if (exit_loop) + return 1; + + if (ret < 0 && errno == EAGAIN) { + /* Breakpoint has not been hit yet, look for incoming messages from gdb. */ + SetsNonblock(client_socket); + + { + const int fd = in_queue > client_socket ? in_queue : client_socket; + fd_set set; + + FD_ZERO(&set); + FD_SET(in_queue, &set); + FD_SET(client_socket, &set); + + /* Warning: mqd_t are file descriptors in Linux and hence + * can be used with select(), but this is not portable. */ + if (select(fd + 1, &set, NULL, NULL, NULL) < 0) + { + perror("wait_hit_or_break: select"); + return EOF; + } + } + + char packet; + size_t len = sizeof packet; + const enum read_socket_err err = ReadSocket(client_socket, &packet, &len); + + switch (err) { + case READ_SOCKET_OK: + if (len && packet == 0x03) { + DEBUG_PRINT("received break\n"); + psxCpu->Halt(); + return wait_hit_or_break(msg); + } + + break; + + case READ_SOCKET_SHUTDOWN: + printf("gdb shutdown\n"); + client_socket = 0; + msg->type = MSG_TYPE_SHUTDOWN; + + if (mq_send(out_queue, (const char *)msg, sizeof *msg, 0)) + perror("wait_hit_or_break() mq_send()"); + + return EOF; + + case READ_SOCKET_ERR_INVALID_ARG: + /* Fall through. */ + case READ_SOCKET_ERR_RECV: + /* Fall through. */ + default: + break; + } + } + else { + switch (msg->type) { + case MSG_TYPE_BREAK: + return 1; + case MSG_TYPE_HIT: + return 0; + + default: + fprintf(stderr, "%s:%d:unexpected msg.type %d\n", + __func__, __LINE__, msg->type); + return EOF; + } + } + } while (1); + + return EOF; +} +#endif + +#ifdef _POSIX_VERSION +int dbg_sys_continue(void) +{ + struct msg msg; + + msg.type = MSG_TYPE_CONTINUE; + + if (mq_send(out_queue, (const char *)&msg, sizeof msg, 0)) { + perror("dbg_sys_continue(): mq_send()"); + return 1; + } + + return wait_hit_or_break(&msg); +} +#endif + +#ifdef _POSIX_VERSION +int dbg_sys_step(void) +{ + struct msg msg; + + msg.type = MSG_TYPE_STEP; + + if (mq_send(out_queue, (const char *)&msg, sizeof msg, 0)) { + perror("dbg_sys_step(): mq_send()"); + } + + return wait_hit_or_break(&msg); +} +#endif + +#ifdef _POSIX_VERSION +static int wait_ack(struct msg *msg) +{ + int ret; + + do { + if (exit_loop) + return 1; + + ret = mq_receive(in_queue, (char *)msg, sizeof *msg, 0); + } while (ret < 0 && errno == EAGAIN); + + if (msg->type != MSG_TYPE_ACK) { + fprintf(stderr, "wait_ack: unexpected msg.type %d\n", msg->type); + return 1; + } + + return 0; +} +#endif + +#ifdef _POSIX_VERSION +int dbg_sys_breakpoint(address addr) +{ + struct msg msg; + + msg.type = MSG_TYPE_BREAKPOINT; + msg.data.breakpoint.addr = addr; + + if (mq_send(out_queue, (const char *)&msg, sizeof msg, 0)) { + perror("dbg_sys_breakpoint(): mq_send()"); + } + + return wait_ack(&msg); +} +#endif + +#ifdef _POSIX_VERSION +int dbg_sys_del_breakpoint(address addr) +{ + struct msg msg; + + msg.type = MSG_TYPE_REMOVE_BREAKPOINT; + + if (mq_send(out_queue, (const char *)&msg, sizeof msg, 0)) { + perror("dbg_sys_del_breakpoint(): mq_send()"); + } + + return wait_ack(&msg); +} +#endif + +#ifdef _POSIX_VERSION +static int queue_create(void) +{ + struct mq_attr attr; + + attr.mq_msgsize = sizeof (struct msg); + attr.mq_flags = 0; + attr.mq_maxmsg = 4; + + mq_unlink("/pcsxrin"); + in_queue = mq_open("/pcsxrin", O_CREAT | O_RDWR | O_EXCL | O_NONBLOCK, 0600, &attr); + + mq_unlink("/pcsxrout"); + out_queue = mq_open("/pcsxrout", O_CREAT | O_RDWR | O_EXCL, 0600, &attr); + + if ((out_queue < 0) || (in_queue < 0)) { + perror("mq_open()"); + return 1; + } + + return 0; +} +#endif + +static void *loop(void *const args) +{ + struct dbg_state dbg_state = {0}; + + SetsBlock(server_socket); + + if ((client_socket = GetClient(server_socket, 1)) < 0) { + fprintf(stderr, "GetClient() failed\n"); + return NULL; + } + + SetsNonblock(client_socket); + + printf("Accepted gdb connection\n"); + + while (!exit_loop) { + update_regs(&dbg_state); + dbg_main(&dbg_state); + } + + return NULL; +} + +#ifdef _POSIX_VERSION +static void start_thread(void) +{ + if (pthread_create(&thread, NULL, loop, NULL)) + perror("could not start gdb server thread"); +} +#endif + +#ifdef _POSIX_VERSION +static void stop_thread(void) +{ + if (pthread_join(thread, NULL)) + perror("pthread_join()"); + + mq_unlink("/pcsxrin"); + mq_unlink("/pcsxrout"); +} +#endif + +#ifdef _POSIX_VERSION +void gdbstub_sys_recv(struct msg *msg) +{ + if (out_queue >= 0) + { + const ssize_t sz = mq_receive(out_queue, (char *)msg, sizeof *msg, 0); + + if (sz < 0) + perror("mq_receive"); + } +} +#endif + +#ifdef _POSIX_VERSION +void gdbstub_sys_send(const struct msg *msg) +{ + if (mq_send(in_queue, (const char *)msg, sizeof *msg, 0)) { + perror("dbg_sys_send(): mq_send()"); + } +} +#endif + +void dbg_stop(void) +{ + exit_loop = 1; + stop_thread(); + + if (client_socket > 0) { + StopServer(client_socket); + printf("Terminated active gdb connection\n"); + } + + if (server_socket > 0) { + StopServer(server_socket); + printf("Closed gdb server\n"); + } +} + +void dbg_start(void) +{ + if (server_socket >= 0) { + fprintf(stderr, "gdb server already started\n"); + return; + } + else { + const unsigned short port = 3333; + + server_socket = StartServer(port); + + if (server_socket >= 0) { + printf("GDB server started on port %hu.\n", port); + if (queue_create()) { + fprintf(stderr, "could not create gdb stub internal queues\n"); + Config.GdbServer = 0; + } + else + start_thread(); + } + else { + fprintf(stderr, "could not start GDB server\n"); + Config.GdbServer = 0; + } + } +} diff --git a/gdbstub/gdbstub_sys.h b/gdbstub/gdbstub_sys.h new file mode 100644 index 00000000..4d0fe3e9 --- /dev/null +++ b/gdbstub/gdbstub_sys.h @@ -0,0 +1,85 @@ +#ifndef GDBSTUB_SYS_H +#define GDBSTUB_SYS_H + +typedef unsigned int address; + +enum DBG_REGISTER { + DBG_CPU_MIPS_I_REG_ZERO, + DBG_CPU_MIPS_I_REG_AT, + DBG_CPU_MIPS_I_REG_V0, + DBG_CPU_MIPS_I_REG_V1, + DBG_CPU_MIPS_I_REG_A0, + DBG_CPU_MIPS_I_REG_A1, + DBG_CPU_MIPS_I_REG_A2, + DBG_CPU_MIPS_I_REG_A3, + DBG_CPU_MIPS_I_REG_T0, + DBG_CPU_MIPS_I_REG_T1, + DBG_CPU_MIPS_I_REG_T2, + DBG_CPU_MIPS_I_REG_T3, + DBG_CPU_MIPS_I_REG_T4, + DBG_CPU_MIPS_I_REG_T5, + DBG_CPU_MIPS_I_REG_T6, + DBG_CPU_MIPS_I_REG_T7, + DBG_CPU_MIPS_I_REG_S0, + DBG_CPU_MIPS_I_REG_S1, + DBG_CPU_MIPS_I_REG_S2, + DBG_CPU_MIPS_I_REG_S3, + DBG_CPU_MIPS_I_REG_S4, + DBG_CPU_MIPS_I_REG_S5, + DBG_CPU_MIPS_I_REG_S6, + DBG_CPU_MIPS_I_REG_S7, + DBG_CPU_MIPS_I_REG_T8, + DBG_CPU_MIPS_I_REG_T9, + DBG_CPU_MIPS_I_REG_K0, + DBG_CPU_MIPS_I_REG_K1, + DBG_CPU_MIPS_I_REG_GP, + DBG_CPU_MIPS_I_REG_SP, + DBG_CPU_MIPS_I_REG_S8, + DBG_CPU_MIPS_I_REG_RA, + DBG_CPU_MIPS_I_REG_SR, + DBG_CPU_MIPS_I_REG_LO, + DBG_CPU_MIPS_I_REG_HI, + DBG_CPU_MIPS_I_REG_BAD, + DBG_CPU_MIPS_I_REG_CAUSE, + DBG_CPU_MIPS_I_REG_PC, + + /* GDB requests 73, where 38 are the ones above and the rest + * are the floating-point registers. This way, unused registers + * are left to zero. */ + DBG_CPU_NUM_REGISTERS = 73 +}; + +typedef unsigned int reg; + +struct dbg_state { + int signum; + reg registers[DBG_CPU_NUM_REGISTERS]; +}; + +struct msg { + enum { + MSG_TYPE_CONTINUE, + MSG_TYPE_BREAKPOINT, + MSG_TYPE_STEP, + MSG_TYPE_ACK, + MSG_TYPE_REMOVE_BREAKPOINT, + MSG_TYPE_SHUTDOWN, + + /* Response frames. */ + MSG_TYPE_HIT, + MSG_TYPE_BREAK, + } type; + + union { + struct { + address addr; + } breakpoint; + } data; +}; + +void dbg_start(void); +void dbg_stop(void); +void gdbstub_sys_send(const struct msg *msg); +void gdbstub_sys_recv(struct msg *msg); + +#endif /* GDBSTUB_SYS_H */ diff --git a/gui/ConfDlg.c b/gui/ConfDlg.c index d55234f8..f41dd9ed 100644 --- a/gui/ConfDlg.c +++ b/gui/ConfDlg.c @@ -32,6 +32,7 @@ #include "ConfDlg.h" #include "../libpcsxcore/plugins.h" +#include "../gdbstub/gdbstub_sys.h" static void OnBiosPath_Changed(GtkWidget *wdg, gpointer data); static void OnConf_Clicked(GtkDialog *dialog, gint arg1, gpointer user_data); @@ -109,7 +110,7 @@ void ConfigurePlugins() { UpdatePluginsBIOS_UpdateGUI(builder); ConfDlg = GTK_WIDGET(gtk_builder_get_object(builder, "ConfDlg")); - + gtk_window_set_title(GTK_WINDOW(ConfDlg), _("Configure PCSXR")); gtk_widget_show (ConfDlg); @@ -219,7 +220,7 @@ void OnConf_Net() { } NetDlg = GTK_WIDGET(gtk_builder_get_object(builder, "NetDlg")); - + gtk_widget_show (NetDlg); FindNetPlugin(builder); @@ -791,7 +792,7 @@ static void FindNetPlugin() { char plugin[MAXPATHLEN],name[MAXPATHLEN]; NetConfS.plugins = 0; - NetConfS.glist = NULL; + NetConfS.glist = NULL; NetConfS.plugins += 2; strcpy(NetConfS.plist[NetConfS.plugins - 1], "Disabled"); @@ -894,7 +895,7 @@ void OnCpu_Clicked(GtkDialog *dialog, gint arg1, gpointer user_data) { // If nothing chosen, default to NTSC tmp = gtk_combo_box_get_active (GTK_COMBO_BOX (widget)); - if (tmp == -1) + if (tmp == -1) tmp = PSX_TYPE_NTSC; if (!strcmp("NTSC", psxtypes[tmp])) @@ -920,6 +921,7 @@ void OnCpu_Clicked(GtkDialog *dialog, gint arg1, gpointer user_data) { Config.Cdda = gtk_combo_box_get_active(GTK_COMBO_BOX(gtk_builder_get_object(builder, "GtkCombo_CDDA"))); Config.SlowBoot = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "GtkCheckButton_SlowBoot"))); Config.PsxAuto = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "GtkCheckButton_PsxAuto"))); + Config.GdbServer = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "GtkCheckButton_GdbServer"))); t = Config.Debug; Config.Debug = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "GtkCheckButton_Dbg"))); @@ -928,6 +930,9 @@ void OnCpu_Clicked(GtkDialog *dialog, gint arg1, gpointer user_data) { else StopDebugger(); } + if (Config.GdbServer) + dbg_start(); + t = Config.Cpu; Config.Cpu = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "GtkCheckButton_Cpu"))); if (t != Config.Cpu) { @@ -974,7 +979,7 @@ void OnConf_Cpu() { char buf[25]; builder = gtk_builder_new(); - + if (!gtk_builder_add_from_resource(builder, "/org/pcsxr/gui/pcsxr.ui", NULL)) { g_warning("Error: interface could not be loaded!"); return; diff --git a/gui/LnxMain.c b/gui/LnxMain.c index d6dd9316..daa54b90 100644 --- a/gui/LnxMain.c +++ b/gui/LnxMain.c @@ -32,6 +32,7 @@ #include #include #include "../libpcsxcore/sio.h" +#include "../gdbstub/gdbstub_sys.h" #include "Linux.h" #include "ConfDlg.h" @@ -320,6 +321,12 @@ int main(int argc, char *argv[]) { SetIsoFile(isofilename); runcd = RUN_CD; } + else if (!strcmp(argv[i], "-gdb")) { + /* Force configuration. */ + Config.Cpu = CPU_INTERPRETER; + Config.GdbServer = 1; + Config.Debug = 0; + } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")) { @@ -334,6 +341,7 @@ int main(int argc, char *argv[]) { "\t-psxout\t\tEnable PSX output\n" "\t-slowboot\tEnable BIOS Logo\n" "\t-load STATENUM\tLoads savestate STATENUM (1-9)\n" + "\t-gdb\t\tStarts GDB server on port 3333\n" "\t-h -help\tDisplay this message\n" "\tfile\t\tLoads file\n")); return 0; @@ -443,7 +451,7 @@ int main(int argc, char *argv[]) { } } } - + if (loadst==0) { loadst = UpdateMenuSlots() + 1; } @@ -490,9 +498,10 @@ int SysInit() { LoadMcds(Config.Mcd1, Config.Mcd2); /* TODO Do we need to have this here, or in the calling main() function?? */ - if (Config.Debug) { + if (Config.Debug) StartDebugger(); - } + else if (Config.GdbServer) + dbg_start(); return 0; } @@ -506,6 +515,7 @@ void SysClose() { ReleasePlugins(); StopDebugger(); + if (Config.GdbServer) dbg_stop(); if (emuLog != NULL) fclose(emuLog); } diff --git a/gui/data/pcsxr.ui b/gui/data/pcsxr.ui index 6f6a9b12..1426911b 100644 --- a/gui/data/pcsxr.ui +++ b/gui/data/pcsxr.ui @@ -1,5 +1,5 @@ - + @@ -10,6 +10,9 @@ dialog pcsxr image-missing + + + False @@ -32,9 +35,6 @@ - - - False @@ -43,6 +43,9 @@ True center-on-parent dialog + + + True @@ -217,9 +220,6 @@ closbutton1 - - - False @@ -228,6 +228,9 @@ True center-on-parent dialog + + + True @@ -916,9 +919,6 @@ btn_ConfClose - - - False @@ -928,6 +928,9 @@ 688 400 dialog + + + True @@ -1750,9 +1753,6 @@ McdClose - - - False @@ -1762,6 +1762,9 @@ True center-on-parent dialog + + + True @@ -2032,9 +2035,6 @@ memview_close - - - False @@ -2044,6 +2044,9 @@ center-on-parent dialog + + + True @@ -2191,9 +2194,6 @@ closebutton2 - - - @@ -2219,6 +2219,9 @@ True center-on-parent dialog + + + False @@ -2454,9 +2457,6 @@ PgxpDlg_close - - - 0.5 @@ -2638,6 +2638,9 @@ False pcsxr-icon.png + + + True @@ -3444,9 +3447,6 @@ - - - @@ -3536,6 +3536,9 @@ True center-on-parent dialog + + + True @@ -4055,9 +4058,6 @@ closebutton - - - @@ -4083,6 +4083,9 @@ True center-on-parent dialog + + + True @@ -4143,8 +4146,8 @@ True - 0 - 2 + 1 + 1 @@ -4158,7 +4161,7 @@ 0 - 3 + 1 @@ -4171,8 +4174,8 @@ True - 0 - 1 + 1 + 0 @@ -4200,7 +4203,7 @@ 0 - 5 + 2 @@ -4214,7 +4217,7 @@ 0 - 7 + 3 @@ -4227,8 +4230,8 @@ True - 0 - 6 + 1 + 2 @@ -4241,8 +4244,8 @@ True - 0 - 8 + 1 + 3 @@ -4255,8 +4258,8 @@ True - 0 - 9 + 1 + 6 @@ -4269,8 +4272,8 @@ True - 0 - 10 + 1 + 4 @@ -4284,7 +4287,7 @@ 0 - 11 + 5 @@ -4297,8 +4300,8 @@ True - 0 - 12 + 1 + 5 @@ -4312,11 +4315,22 @@ 0 - 13 + 6 - + + Enable GDB server + True + True + False + True + True + + + 0 + 4 + @@ -4810,8 +4824,5 @@ closebutton1 - - - diff --git a/libpcsxcore/CMakeLists.txt b/libpcsxcore/CMakeLists.txt index b8caef4c..0be1e4ac 100644 --- a/libpcsxcore/CMakeLists.txt +++ b/libpcsxcore/CMakeLists.txt @@ -6,6 +6,8 @@ set_property(CACHE DYNAREC PROPERTY STRINGS auto x86_64 x86 ppc no) option(ENABLE_CCDDA "Enables compressed CDDA support." OFF) option(USE_LIBARCHIVE "Enables compressed data-tracks support." OFF) +include_directories(../dynstr/dynstr/include) + if (ENABLE_CCDDA) find_package(FFMPEG REQUIRED) include_directories(${FFMPEG_INCLUDE_DIRS}) @@ -114,4 +116,4 @@ endif() set(SRCS ${SRCS} ${DYNAREC_SRC}) add_library(pcsxcore STATIC ${SRCS}) -target_link_libraries(pcsxcore ${FFMPEG_LIBRARIES} ${LibArchive_LIBRARIES} ${LIBS}) +target_link_libraries(pcsxcore dynstr gdbstub ${FFMPEG_LIBRARIES} ${LibArchive_LIBRARIES} ${LIBS}) diff --git a/libpcsxcore/debug.c b/libpcsxcore/debug.c index a4e9ab35..ecc9edc7 100644 --- a/libpcsxcore/debug.c +++ b/libpcsxcore/debug.c @@ -19,6 +19,8 @@ #include "r3000a.h" #include "debug.h" #include "socket.h" +#include +#include /* PCSXR Debug console protocol description, version 1.0 @@ -134,7 +136,7 @@ Execution flow control commands (3xx): Soft (quick) resets. 399 Resets. - + Server outputs: ~~~~~~~~~~~~~~ @@ -236,6 +238,9 @@ static int step_over = 0; static u32 step_over_addr = 0; static int mapping_e = 0, mapping_r8 = 0, mapping_r16 = 0, mapping_r32 = 0, mapping_w8 = 0, mapping_w16 = 0, mapping_w32 = 0; static int breakmp_e = 0, breakmp_r8 = 0, breakmp_r16 = 0, breakmp_r32 = 0, breakmp_w8 = 0, breakmp_w16 = 0, breakmp_w32 = 0; +static int server_socket, client_socket; +static char tbuf[513]; +static size_t ptr; static void ProcessCommands(); @@ -317,6 +322,11 @@ breakpoint_t *find_breakpoint(int number) { } void StartDebugger() { + enum + { + PORT_NUMBER = 12345 + }; + if (debugger_active) return; @@ -326,7 +336,9 @@ void StartDebugger() { return; } - if (StartServer() == -1) { + server_socket = StartServer(PORT_NUMBER); + + if (server_socket == -1) { SysPrintf("%s", _("Unable to start debug server.\n")); return; } @@ -337,7 +349,7 @@ void StartDebugger() { void StopDebugger() { if (debugger_active) { - StopServer(); + StopServer(server_socket); SysPrintf("%s", _("Debugger stopped.\n")); } @@ -361,6 +373,14 @@ void ResumeDebugger() { paused = 0; } +static void DebugHello(void) +{ + static const char hello[] = "000 PCSXR Version " PACKAGE_VERSION " - Debug console\r\n"; + + WriteSocket(client_socket, hello, sizeof hello); + ptr = 0; +} + void DebugVSync() { if (!debugger_active || resetting) return; @@ -375,7 +395,16 @@ void DebugVSync() { return; } - GetClient(); + if (client_socket < 1) + { + client_socket = GetClient(server_socket, 0); + + if (client_socket > 0) + { + DebugHello(); + } + } + ProcessCommands(); } @@ -398,33 +427,42 @@ void ProcessDebug() { } if (!paused) { if(trace && printpc) { - char reply[256]; - sprintf(reply, "219 %s\r\n", disR3000AF(psxMemRead32(psxRegs.pc), psxRegs.pc)); - WriteSocket(reply, strlen(reply)); + struct dynstr reply; + + dynstr_init(&reply); + dynstr_append(&reply, "219 %s\r\n", disR3000AF(psxMemRead32(psxRegs.pc), psxRegs.pc)); + WriteSocket(client_socket, reply.str, reply.len); + dynstr_free(&reply); } - + if(step_over) { if(psxRegs.pc == step_over_addr) { - char reply[256]; + struct dynstr reply; + + dynstr_init(&reply); step_over = 0; step_over_addr = 0; - sprintf(reply, "050 @%08X\r\n", psxRegs.pc); - WriteSocket(reply, strlen(reply)); + dynstr_append(&reply, "050 @%08X\r\n", psxRegs.pc); + WriteSocket(client_socket, reply.str, reply.len); + dynstr_free(&reply); paused = 1; } } - + if(run_to) { if(psxRegs.pc == run_to_addr) { - char reply[256]; + struct dynstr reply; + run_to = 0; run_to_addr = 0; - sprintf(reply, "040 @%08X\r\n", psxRegs.pc); - WriteSocket(reply, strlen(reply)); + dynstr_init(&reply); + dynstr_append(&reply, "040 @%08X\r\n", psxRegs.pc); + WriteSocket(client_socket, reply.str, reply.len); + dynstr_free(&reply); paused = 1; } } - + DebugCheckBP(psxRegs.pc, BE); } if (mapping_e) { @@ -437,7 +475,17 @@ void ProcessDebug() { } } while (paused) { - GetClient(); + + if (client_socket < 1) + { + client_socket = GetClient(server_socket, 0); + + if (client_socket > 0) + { + DebugHello(); + } + } + ProcessCommands(); GPU_updateLace(); SysUpdate(); @@ -446,14 +494,31 @@ void ProcessDebug() { static void ProcessCommands() { int code, i, dumping; - FILE *sfile; - char cmd[257], *arguments, *p, reply[10240], *save, *dump = NULL; + char cmd[348], *arguments, *p, *save, *dump = NULL; u32 reg, value, size = 0, address; breakpoint_t *bp; + size_t len = sizeof cmd; + struct dynstr reply; + + if (HasClient(client_socket)) + { + const enum read_socket_err err = ReadSocket(client_socket, cmd, &len); + + switch (err) + { + case READ_SOCKET_OK: + break; + + case READ_SOCKET_ERR_INVALID_ARG: + /* Fall through. */ + case READ_SOCKET_ERR_RECV: + /* Fall through. */ + case READ_SOCKET_SHUTDOWN: + /* Fall through. */ + default: + return; + } - if (!HasClient()) - return; - if (ReadSocket(cmd, 256) > 0) { arguments = NULL; if (strlen(cmd) <= 2) { code = 0; @@ -475,129 +540,126 @@ static void ProcessCommands() { dumping = 0; save = NULL; + dynstr_init(&reply); switch (code) { case 0x100: - sprintf(reply, "200 %s\r\n", arguments == NULL ? "OK" : arguments); + dynstr_append(&reply, "200 %s\r\n", arguments == NULL ? "OK" : arguments); break; case 0x101: - sprintf(reply, "201 %s\r\n", PACKAGE_VERSION); + dynstr_append(&reply, "201 %s\r\n", PACKAGE_VERSION); break; case 0x102: - sprintf(reply, "202 1.0\r\n"); + dynstr_append(&reply, "202 1.0\r\n"); break; case 0x103: - sprintf(reply, "203 %i\r\n", paused ? 1 : trace ? 2 : 0); + dynstr_append(&reply, "203 %i\r\n", paused ? 1 : trace ? 2 : 0); break; case 0x110: - sprintf(reply, "210 PC=%08X\r\n", psxRegs.pc); + dynstr_append(&reply, "210 PC=%08X\r\n", psxRegs.pc); break; case 0x111: if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "511 Malformed 111 command '%s'\r\n", cmd); + dynstr_append(&reply, "511 Malformed 111 command '%s'\r\n", cmd); break; } } if (!arguments) { - reply[0] = 0; for (i = 0; i < 32; i++) { - sprintf(reply, "%s211 %02X(%2.2s)=%08X\r\n", reply, i, disRNameGPR[i], psxRegs.GPR.r[i]); + dynstr_append(&reply, "211 %02X(%2.2s)=%08X\r\n", reply, i, disRNameGPR[i], psxRegs.GPR.r[i]); } } else { if ((code >= 0) && (code < 32)) { - sprintf(reply, "211 %02X(%2.2s)=%08X\r\n", code, disRNameGPR[code], psxRegs.GPR.r[code]); + dynstr_append(&reply, "211 %02X(%2.2s)=%08X\r\n", code, disRNameGPR[code], psxRegs.GPR.r[code]); } else { - sprintf(reply, "511 Invalid GPR register: %X\r\n", code); + dynstr_append(&reply, "511 Invalid GPR register: %X\r\n", code); } } break; case 0x112: - sprintf(reply, "212 LO=%08X HI=%08X\r\n", psxRegs.GPR.n.lo, psxRegs.GPR.n.hi); + dynstr_append(&reply, "212 LO=%08X HI=%08X\r\n", psxRegs.GPR.n.lo, psxRegs.GPR.n.hi); break; case 0x113: if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "511 Malformed 113 command '%s'\r\n", cmd); + dynstr_append(&reply, "511 Malformed 113 command '%s'\r\n", cmd); break; } } if (!arguments) { - reply[0] = 0; for (i = 0; i < 32; i++) { - sprintf(reply, "%s213 %02X(%8.8s)=%08X\r\n", reply, i, disRNameCP0[i], psxRegs.CP0.r[i]); + dynstr_append(&reply, "213 %02X(%8.8s)=%08X\r\n", i, disRNameCP0[i], psxRegs.CP0.r[i]); } } else { if ((code >= 0) && (code < 32)) { - sprintf(reply, "213 %02X(%8.8s)=%08X\r\n", code, disRNameCP0[code], psxRegs.CP0.r[code]); + dynstr_append(&reply, "213 %02X(%8.8s)=%08X\r\n", code, disRNameCP0[code], psxRegs.CP0.r[code]); } else { - sprintf(reply, "511 Invalid COP0 register: %X\r\n", code); + dynstr_append(&reply, "511 Invalid COP0 register: %X\r\n", code); } } break; case 0x114: if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "511 Malformed 114 command '%s'\r\n", cmd); + dynstr_append(&reply, "511 Malformed 114 command '%s'\r\n", cmd); break; } } if (!arguments) { - reply[0] = 0; for (i = 0; i < 32; i++) { - sprintf(reply, "%s214 %02X(%6.6s)=%08X\r\n", reply, i, disRNameCP2C[i], psxRegs.CP2C.r[i]); + dynstr_append(&reply, "214 %02X(%6.6s)=%08X\r\n", i, disRNameCP2C[i], psxRegs.CP2C.r[i]); } } else { if ((code >= 0) && (code < 32)) { - sprintf(reply, "214 %02X(%6.6s)=%08X\r\n", code, disRNameCP2C[code], psxRegs.CP2C.r[code]); + dynstr_append(&reply, "214 %02X(%6.6s)=%08X\r\n", code, disRNameCP2C[code], psxRegs.CP2C.r[code]); } else { - sprintf(reply, "511 Invalid COP2C register: %X\r\n", code); + dynstr_append(&reply, "511 Invalid COP2C register: %X\r\n", code); } } break; case 0x115: if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "511 Malformed 111 command '%s'\r\n", cmd); + dynstr_append(&reply, "511 Malformed 111 command '%s'\r\n", cmd); break; } } if (!arguments) { - reply[0] = 0; for (i = 0; i < 32; i++) { - sprintf(reply, "%s215 %02X(%4.4s)=%08X\r\n", reply, i, disRNameCP2D[i], psxRegs.CP2D.r[i]); + dynstr_append(&reply, "215 %02X(%4.4s)=%08X\r\n", i, disRNameCP2D[i], psxRegs.CP2D.r[i]); } } else { if ((code >= 0) && (code < 32)) { - sprintf(reply, "215 %02X(%4.4s)=%08X\r\n", code, disRNameCP2D[code], psxRegs.CP2D.r[code]); + dynstr_append(&reply, "215 %02X(%4.4s)=%08X\r\n", code, disRNameCP2D[code], psxRegs.CP2D.r[code]); } else { - sprintf(reply, "511 Invalid COP2D register: %X\r\n", code); + dynstr_append(&reply, "511 Invalid COP2D register: %X\r\n", code); } } break; case 0x119: if (arguments) { if (sscanf(arguments, "%08X", &code) != 1) { - sprintf(reply, "511 Malformed 119 command '%s'\r\n", cmd); + dynstr_append(&reply, "511 Malformed 119 command '%s'\r\n", cmd); break; } } if (!arguments) code = psxRegs.pc; - sprintf(reply, "219 %s\r\n", disR3000AF(psxMemRead32(code), code)); + dynstr_append(&reply, "219 %s\r\n", disR3000AF(psxMemRead32(code), code)); break; case 0x121: if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) { - sprintf(reply, "500 Malformed 121 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 121 command '%s'\r\n", arguments); break; } if (reg < 32) { psxRegs.GPR.r[reg] = value; - sprintf(reply, "221 %02X=%08X\r\n", reg, value); + dynstr_append(&reply, "221 %02X=%08X\r\n", reg, value); } else { - sprintf(reply, "512 Invalid GPR register: %02X\r\n", reg); + dynstr_append(&reply, "512 Invalid GPR register: %02X\r\n", reg); } break; case 0x122: @@ -607,88 +669,88 @@ static void ProcessCommands() { reg = 32; } else { arguments[2] = 0; - sprintf(reply, "512 Invalid LO/HI register: '%s'\r\n", arguments); + dynstr_append(&reply, "512 Invalid LO/HI register: '%s'\r\n", arguments); break; } if (sscanf(arguments + 3, "%08X", &value) != 1) { - sprintf(reply, "500 Malformed 122 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 122 command '%s'\r\n", arguments); } else { psxRegs.GPR.r[reg] = value; - sprintf(reply, "222 LO=%08X HI=%08X\r\n", psxRegs.GPR.n.lo, psxRegs.GPR.n.hi); + dynstr_append(&reply, "222 LO=%08X HI=%08X\r\n", psxRegs.GPR.n.lo, psxRegs.GPR.n.hi); } break; case 0x123: if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) { - sprintf(reply, "500 Malformed 123 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 123 command '%s'\r\n", arguments); break; } if (reg < 32) { psxRegs.CP0.r[reg] = value; - sprintf(reply, "223 %02X=%08X\r\n", reg, value); + dynstr_append(&reply, "223 %02X=%08X\r\n", reg, value); } else { - sprintf(reply, "512 Invalid COP0 register: %02X\r\n", reg); + dynstr_append(&reply, "512 Invalid COP0 register: %02X\r\n", reg); } break; case 0x124: if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) { - sprintf(reply, "500 Malformed 124 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 124 command '%s'\r\n", arguments); break; } if (reg < 32) { psxRegs.CP2C.r[reg] = value; - sprintf(reply, "224 %02X=%08X\r\n", reg, value); + dynstr_append(&reply, "224 %02X=%08X\r\n", reg, value); } else { - sprintf(reply, "512 Invalid COP2C register: %02X\r\n", reg); + dynstr_append(&reply, "512 Invalid COP2C register: %02X\r\n", reg); } break; case 0x125: if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) { - sprintf(reply, "500 Malformed 121 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 121 command '%s'\r\n", arguments); break; } if (reg < 32) { psxRegs.CP2D.r[reg] = value; - sprintf(reply, "225 %02X=%08X\r\n", reg, value); + dynstr_append(&reply, "225 %02X=%08X\r\n", reg, value); } else { - sprintf(reply, "512 Invalid COP2D register: %02X\r\n", reg); + dynstr_append(&reply, "512 Invalid COP2D register: %02X\r\n", reg); } break; case 0x130: if (!arguments || sscanf(arguments, "%08X@%08X", &size, &address) != 2) { - sprintf(reply, "500 Malformed 130 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 130 command '%s'\r\n", arguments); break; } if ((address >= 0x80000000) && ((address + size) <= 0x80200000)) { - sprintf(reply, "230 %08X@%08X\r\n", size, address); + dynstr_append(&reply, "230 %08X@%08X\r\n", size, address); dump = (char *) PSXM(address); dumping = 1; } else { - sprintf(reply, "513 Invalid address or range: '%s'\r\n", arguments); + dynstr_append(&reply, "513 Invalid address or range: '%s'\r\n", arguments); } break; case 0x140: if (!arguments || sscanf(arguments, "%08X@%08X", &size, &address) != 2) { - sprintf(reply, "500 Malformed 140 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 140 command '%s'\r\n", arguments); break; } if ((address >= 0x80000000) && ((address + size) <= 0x80200000)) { - sprintf(reply, "240 %08X@%08X\r\n", size, address); - RawReadSocket((char *)PSXM(address), size); + dynstr_append(&reply, "240 %08X@%08X\r\n", size, address); + RawReadSocket(client_socket, (char *)PSXM(address), size); } else { - sprintf(reply, "514 Invalid address or range: '%s'\r\n", arguments); + dynstr_append(&reply, "514 Invalid address or range: '%s'\r\n", arguments); } break; case 0x150: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 150 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 150 command '%s'\r\n", cmd); break; } } @@ -701,13 +763,13 @@ static void ProcessCommands() { } else { mapping_e = 0; } - sprintf(reply, "250 Mapping of exec flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "250 Mapping of exec flow %s\r\n", code ? "started" : "stopped"); break; case 0x151: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 151 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 151 command '%s'\r\n", cmd); break; } } @@ -719,13 +781,13 @@ static void ProcessCommands() { } else { mapping_r8 = 0; } - sprintf(reply, "251 Mapping of read8 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "251 Mapping of read8 flow %s\r\n", code ? "started" : "stopped"); break; case 0x152: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 152 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 152 command '%s'\r\n", cmd); break; } } @@ -737,13 +799,13 @@ static void ProcessCommands() { } else { mapping_r16 = 0; } - sprintf(reply, "252 Mapping of read16 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "252 Mapping of read16 flow %s\r\n", code ? "started" : "stopped"); break; case 0x153: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 153 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 153 command '%s'\r\n", cmd); break; } } @@ -755,13 +817,13 @@ static void ProcessCommands() { } else { mapping_r32 = 0; } - sprintf(reply, "253 Mapping of read32 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "253 Mapping of read32 flow %s\r\n", code ? "started" : "stopped"); break; case 0x154: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 154 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 154 command '%s'\r\n", cmd); break; } } @@ -773,13 +835,13 @@ static void ProcessCommands() { } else { mapping_w8 = 0; } - sprintf(reply, "254 Mapping of write8 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "254 Mapping of write8 flow %s\r\n", code ? "started" : "stopped"); break; case 0x155: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 155 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 155 command '%s'\r\n", cmd); break; } } @@ -791,13 +853,13 @@ static void ProcessCommands() { } else { mapping_w16 = 0; } - sprintf(reply, "255 Mapping of write16 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "255 Mapping of write16 flow %s\r\n", code ? "started" : "stopped"); break; case 0x156: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 156 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 156 command '%s'\r\n", cmd); break; } } @@ -809,13 +871,13 @@ static void ProcessCommands() { } else { mapping_w32 = 0; } - sprintf(reply, "256 Mapping of write32 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "256 Mapping of write32 flow %s\r\n", code ? "started" : "stopped"); break; case 0x160: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 160 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 160 command '%s'\r\n", cmd); break; } } @@ -824,13 +886,13 @@ static void ProcessCommands() { } else { breakmp_e = 0; } - sprintf(reply, "260 Break on map of exec flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "260 Break on map of exec flow %s\r\n", code ? "started" : "stopped"); break; case 0x161: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 161 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 161 command '%s'\r\n", cmd); break; } } @@ -839,13 +901,13 @@ static void ProcessCommands() { } else { breakmp_r8 = 0; } - sprintf(reply, "261 Break on map of read8 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "261 Break on map of read8 flow %s\r\n", code ? "started" : "stopped"); break; case 0x162: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 162 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 162 command '%s'\r\n", cmd); break; } } @@ -854,13 +916,13 @@ static void ProcessCommands() { } else { breakmp_r16 = 0; } - sprintf(reply, "262 Break on map of read16 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "262 Break on map of read16 flow %s\r\n", code ? "started" : "stopped"); break; case 0x163: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 163 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 163 command '%s'\r\n", cmd); break; } } @@ -869,13 +931,13 @@ static void ProcessCommands() { } else { breakmp_r32 = 0; } - sprintf(reply, "263 Break on map of read32 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "263 Break on map of read32 flow %s\r\n", code ? "started" : "stopped"); break; case 0x164: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 164 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 164 command '%s'\r\n", cmd); break; } } @@ -884,13 +946,13 @@ static void ProcessCommands() { } else { breakmp_w8 = 0; } - sprintf(reply, "264 Break on map of write8 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "264 Break on map of write8 flow %s\r\n", code ? "started" : "stopped"); break; case 0x165: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 165 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 165 command '%s'\r\n", cmd); break; } } @@ -899,13 +961,13 @@ static void ProcessCommands() { } else { breakmp_w16 = 0; } - sprintf(reply, "265 Break on map of write16 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "265 Break on map of write16 flow %s\r\n", code ? "started" : "stopped"); break; case 0x166: code = 1; if (arguments) { if (sscanf(arguments, "%02X", &code) != 1) { - sprintf(reply, "500 Malformed 166 command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Malformed 166 command '%s'\r\n", cmd); break; } } @@ -914,30 +976,37 @@ static void ProcessCommands() { } else { breakmp_w32 = 0; } - sprintf(reply, "266 Break on map of write32 flow %s\r\n", code ? "started" : "stopped"); + dynstr_append(&reply, "266 Break on map of write32 flow %s\r\n", code ? "started" : "stopped"); break; case 0x170: - sfile = fopen("flow.idc", "wb"); - fprintf(sfile, "#include \r\n\r\n"); - fprintf(sfile, "static main(void) {\r\n"); - for (i = 0; i < 0x00200000; i++) { - if (IsMapMarked(i, MAP_EXEC_JAL)) { - fprintf(sfile, "\tMakeFunction(0X8%07X,BADADDR);\r\n", i); + { + { + FILE *const sfile = fopen("flow.idc", "wb"); + fprintf(sfile, "#include \r\n\r\n"); + fprintf(sfile, "static main(void) {\r\n"); + for (i = 0; i < 0x00200000; i++) { + if (IsMapMarked(i, MAP_EXEC_JAL)) { + fprintf(sfile, "\tMakeFunction(0X8%07X,BADADDR);\r\n", i); + } } + fprintf(sfile, "}\r\n"); + fclose(sfile); } - fprintf(sfile, "}\r\n"); - fclose(sfile); - sfile = fopen("markcode.idc", "wb"); - fprintf(sfile, "#include \r\n\r\n"); - fprintf(sfile, "static main(void) {\r\n"); - for (i = 0; i < 0x00200000; i++) { - if (IsMapMarked(i, MAP_EXEC)) { - fprintf(sfile, "\tMakeCode(0X8%07X);\r\n", i); + + { + FILE *const sfile = fopen("markcode.idc", "wb"); + fprintf(sfile, "#include \r\n\r\n"); + fprintf(sfile, "static main(void) {\r\n"); + for (i = 0; i < 0x00200000; i++) { + if (IsMapMarked(i, MAP_EXEC)) { + fprintf(sfile, "\tMakeCode(0X8%07X);\r\n", i); + } } + fprintf(sfile, "}\r\n"); + fclose(sfile); + dynstr_append(&reply, "270 flow.idc and markcode.idc dumped\r\n"); } - fprintf(sfile, "}\r\n"); - fclose(sfile); - sprintf(reply, "270 flow.idc and markcode.idc dumped\r\n"); + } break; case 0x300: p = arguments; @@ -946,18 +1015,17 @@ static void ProcessCommands() { } if (p == arguments) { if (first) { - reply[0] = 0; for (bp = first; bp; bp = next_breakpoint(bp)) { - sprintf(reply, "%s400 %X@%08X-%s\r\n", reply, bp->number, bp->address, breakpoint_type_names[bp->type]); + dynstr_append(&reply, "%s400 %X@%08X-%s\r\n", bp->number, bp->address, breakpoint_type_names[bp->type]); } } else { - sprintf(reply, "530 No breakpoint\r\n"); + dynstr_append(&reply, "530 No breakpoint\r\n"); } } else { if ((bp = find_breakpoint(code))) { - sprintf(reply, "400 %X@%08X-%s\r\n", bp->number, bp->address, breakpoint_type_names[bp->type]); + dynstr_append(&reply, "400 %X@%08X-%s\r\n", bp->number, bp->address, breakpoint_type_names[bp->type]); } else { - sprintf(reply, "530 Invalid breakpoint number: %X\r\n", code); + dynstr_append(&reply, "530 Invalid breakpoint number: %X\r\n", code); } } break; @@ -968,107 +1036,107 @@ static void ProcessCommands() { } if (p == arguments) { while (first != NULL) delete_breakpoint(first); - sprintf(reply, "401 All breakpoints deleted.\r\n"); + dynstr_append(&reply, "401 All breakpoints deleted.\r\n"); } else { if ((bp = find_breakpoint(code))) { delete_breakpoint(bp); - sprintf(reply, "401 Breakpoint %X deleted.\r\n", code); + dynstr_append(&reply, "401 Breakpoint %X deleted.\r\n", code); } else { - sprintf(reply, "530 Invalid breakpoint number: %X\r\n", code); + dynstr_append(&reply, "530 Invalid breakpoint number: %X\r\n", code); } } break; case 0x310: if (!arguments || sscanf(arguments, "%08X", &address) != 1) { - sprintf(reply, "500 Malformed 310 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 310 command '%s'\r\n", arguments); break; } -// if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) { -// sprintf(reply, "531 Invalid address %08X\r\n", address); -// break; -// } + // if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) { + // dynstr_append(&reply, "531 Invalid address %08X\r\n", address); + // break; + // } code = add_breakpoint(BE, address); - sprintf(reply, "410 %X\r\n", code); + dynstr_append(&reply, "410 %X\r\n", code); break; case 0x320: if (!arguments || sscanf(arguments, "%08X", &address) != 1) { - sprintf(reply, "500 Malformed 320 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 320 command '%s'\r\n", arguments); break; } if ((address < 0x80000000) || (address >= 0x80200000)) { - sprintf(reply, "532 Invalid address %08X\r\n", address); + dynstr_append(&reply, "532 Invalid address %08X\r\n", address); break; } code = add_breakpoint(BR1, address); - sprintf(reply, "420 %X\r\n", code); + dynstr_append(&reply, "420 %X\r\n", code); break; case 0x321: if (!arguments || sscanf(arguments, "%08X", &address) != 1) { - sprintf(reply, "500 Malformed 321 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 321 command '%s'\r\n", arguments); break; } if ((address & 1) || (address < 0x80000000) || (address >= 0x80200000)) { - sprintf(reply, "532 Invalid address %08X\r\n", address); + dynstr_append(&reply, "532 Invalid address %08X\r\n", address); break; } code = add_breakpoint(BR2, address); - sprintf(reply, "421 %X\r\n", code); + dynstr_append(&reply, "421 %X\r\n", code); break; case 0x322: if (!arguments || sscanf(arguments, "%08X", &address) != 1) { - sprintf(reply, "500 Malformed 322 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 322 command '%s'\r\n", arguments); break; } if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) { - sprintf(reply, "532 Invalid address %08X\r\n", address); + dynstr_append(&reply, "532 Invalid address %08X\r\n", address); break; } code = add_breakpoint(BR4, address); - sprintf(reply, "422 %X\r\n", code); + dynstr_append(&reply, "422 %X\r\n", code); break; case 0x330: if (!arguments || sscanf(arguments, "%08X", &address) != 1) { - sprintf(reply, "500 Malformed 330 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 330 command '%s'\r\n", arguments); break; } if ((address < 0x80000000) || (address >= 0x80200000)) { - sprintf(reply, "533 Invalid address %08X\r\n", address); + dynstr_append(&reply, "533 Invalid address %08X\r\n", address); break; } code = add_breakpoint(BW1, address); - sprintf(reply, "430 %X\r\n", code); + dynstr_append(&reply, "430 %X\r\n", code); break; case 0x331: if (!arguments || sscanf(arguments, "%08X", &address) != 1) { - sprintf(reply, "500 Malformed 331 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 331 command '%s'\r\n", arguments); break; } if ((address & 1) || (address < 0x80000000) || (address >= 0x80200000)) { - sprintf(reply, "533 Invalid address %08X\r\n", address); + dynstr_append(&reply, "533 Invalid address %08X\r\n", address); break; } code = add_breakpoint(BW2, address); - sprintf(reply, "431 %X\r\n", code); + dynstr_append(&reply, "431 %X\r\n", code); break; case 0x332: if (!arguments || sscanf(arguments, "%08X", &address) != 1) { - sprintf(reply, "500 Malformed 332 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 332 command '%s'\r\n", arguments); break; } if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) { - sprintf(reply, "533 Invalid address %08X\r\n", address); + dynstr_append(&reply, "533 Invalid address %08X\r\n", address); break; } code = add_breakpoint(BW4, address); - sprintf(reply, "432 %X\r\n", code); + dynstr_append(&reply, "432 %X\r\n", code); break; case 0x390: paused = 1; - sprintf(reply, "490 Paused\r\n"); + dynstr_append(&reply, "490 Paused\r\n"); break; case 0x391: paused = 0; - sprintf(reply, "491 Resumed\r\n"); + dynstr_append(&reply, "491 Resumed\r\n"); break; case 0x395: p = arguments; @@ -1079,7 +1147,7 @@ static void ProcessCommands() { trace = 1; } paused = 0; - sprintf(reply, "495 Tracing\r\n"); + dynstr_append(&reply, "495 Tracing\r\n"); break; case 0x396: p = arguments; @@ -1089,19 +1157,19 @@ static void ProcessCommands() { if (p == arguments) { printpc = !printpc; } - sprintf(reply, "496 Printing %s\r\n", printpc ? "enabled" : "disabled"); + dynstr_append(&reply, "496 Printing %s\r\n", printpc ? "enabled" : "disabled"); break; case 0x398: paused = 0; trace = 0; reset = 2; - sprintf(reply, "498 Soft resetting\r\n"); + dynstr_append(&reply, "498 Soft resetting\r\n"); break; case 0x399: paused = 0; trace = 0; reset = 1; - sprintf(reply, "499 Resetting\r\n"); + dynstr_append(&reply, "499 Resetting\r\n"); break; case 0x3A0: // run to @@ -1112,10 +1180,10 @@ static void ProcessCommands() { paused = 0; } if (p == arguments) { - sprintf(reply, "500 Malformed 3A0 command '%s'\r\n", arguments); + dynstr_append(&reply, "500 Malformed 3A0 command '%s'\r\n", arguments); break; } - sprintf(reply, "4A0 run to addr %08X\r\n", run_to_addr); + dynstr_append(&reply, "4A0 run to addr %08X\r\n", run_to_addr); break; case 0x3A1: // step over (jal) @@ -1125,8 +1193,8 @@ static void ProcessCommands() { step_over = 1; step_over_addr = psxRegs.pc + 8; paused = 0; - - sprintf(reply, "4A1 step over addr %08X\r\n", psxRegs.pc); + + dynstr_append(&reply, "4A1 step over addr %08X\r\n", psxRegs.pc); } else { trace = 1; @@ -1135,13 +1203,14 @@ static void ProcessCommands() { } break; default: - sprintf(reply, "500 Unknown command '%s'\r\n", cmd); + dynstr_append(&reply, "500 Unknown command '%s'\r\n", cmd); break; } - WriteSocket(reply, strlen(reply)); + WriteSocket(client_socket, reply.str, reply.len); + dynstr_free(&reply); if (dumping) { - WriteSocket(dump, size); + WriteSocket(client_socket, dump, size); } if (save) { @@ -1156,11 +1225,11 @@ void DebugCheckBP(u32 address, enum breakpoint_types type) { if (!debugger_active || reset) return; - + for (bp = first; bp; bp = next_breakpoint(bp)) { if ((bp->type == type) && (bp->address == address)) { sprintf(reply, "030 %X@%08X\r\n", bp->number, psxRegs.pc); - WriteSocket(reply, strlen(reply)); + WriteSocket(client_socket, reply, strlen(reply)); paused = 1; return; } @@ -1168,49 +1237,49 @@ void DebugCheckBP(u32 address, enum breakpoint_types type) { if (breakmp_e && type == BE) { if (!IsMapMarked(address, MAP_EXEC)) { sprintf(reply, "010 %08X@%08X\r\n", address, psxRegs.pc); - WriteSocket(reply, strlen(reply)); + WriteSocket(client_socket, reply, strlen(reply)); paused = 1; } } if (breakmp_r8 && type == BR1) { if (!IsMapMarked(address, MAP_R8)) { sprintf(reply, "011 %08X@%08X\r\n", address, psxRegs.pc); - WriteSocket(reply, strlen(reply)); + WriteSocket(client_socket, reply, strlen(reply)); paused = 1; } } if (breakmp_r16 && type == BR2) { if (!IsMapMarked(address, MAP_R16)) { sprintf(reply, "012 %08X@%08X\r\n", address, psxRegs.pc); - WriteSocket(reply, strlen(reply)); + WriteSocket(client_socket, reply, strlen(reply)); paused = 1; } } if (breakmp_r32 && type == BR4) { if (!IsMapMarked(address, MAP_R32)) { sprintf(reply, "013 %08X@%08X\r\n", address, psxRegs.pc); - WriteSocket(reply, strlen(reply)); + WriteSocket(client_socket, reply, strlen(reply)); paused = 1; } } if (breakmp_w8 && type == BW1) { if (!IsMapMarked(address, MAP_W8)) { sprintf(reply, "014 %08X@%08X\r\n", address, psxRegs.pc); - WriteSocket(reply, strlen(reply)); + WriteSocket(client_socket, reply, strlen(reply)); paused = 1; } } if (breakmp_w16 && type == BW2) { if (!IsMapMarked(address, MAP_W16)) { sprintf(reply, "015 %08X@%08X\r\n", address, psxRegs.pc); - WriteSocket(reply, strlen(reply)); + WriteSocket(client_socket, reply, strlen(reply)); paused = 1; } } if (breakmp_w32 && type == BW4) { if (!IsMapMarked(address, MAP_W32)) { sprintf(reply, "016 %08X@%08X\r\n", address, psxRegs.pc); - WriteSocket(reply, strlen(reply)); + WriteSocket(client_socket, reply, strlen(reply)); paused = 1; } } diff --git a/libpcsxcore/debug.h b/libpcsxcore/debug.h index f54c4883..4ca2e5ec 100644 --- a/libpcsxcore/debug.h +++ b/libpcsxcore/debug.h @@ -46,7 +46,7 @@ extern char *disRNameCP0[]; char* disR3000AF(u32 code, u32 pc); -/* +/* * Specficies which logs should be activated. */ diff --git a/libpcsxcore/pgxp_cpu.c b/libpcsxcore/pgxp_cpu.c index 2b36da57..7f84f9a2 100644 --- a/libpcsxcore/pgxp_cpu.c +++ b/libpcsxcore/pgxp_cpu.c @@ -14,12 +14,12 @@ PGXP_value* CPU_reg = CPU_reg_mem; PGXP_value* CP0_reg = CP0_reg_mem; // Instruction register decoding -#define op(_instr) (_instr >> 26) // The op part of the instruction register -#define func(_instr) ((_instr) & 0x3F) // The funct part of the instruction register +#define op(_instr) (_instr >> 26) // The op part of the instruction register +#define func(_instr) ((_instr) & 0x3F) // The funct part of the instruction register #define sa(_instr) ((_instr >> 6) & 0x1F) // The sa part of the instruction register -#define rd(_instr) ((_instr >> 11) & 0x1F) // The rd part of the instruction register -#define rt(_instr) ((_instr >> 16) & 0x1F) // The rt part of the instruction register -#define rs(_instr) ((_instr >> 21) & 0x1F) // The rs part of the instruction register +#define rd(_instr) ((_instr >> 11) & 0x1F) // The rd part of the instruction register +#define rt(_instr) ((_instr >> 16) & 0x1F) // The rt part of the instruction register +#define rs(_instr) ((_instr >> 21) & 0x1F) // The rs part of the instruction register #define imm(_instr) (_instr & 0xFFFF) // The immediate part of the instruction register void PGXP_InitCPU() @@ -31,7 +31,7 @@ void PGXP_InitCPU() // invalidate register (invalid 8 bit read) void InvalidLoad(u32 addr, u32 code, u32 value) { - u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register + u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register PGXP_value* pD = NULL; PGXP_value p; @@ -60,7 +60,7 @@ void InvalidLoad(u32 addr, u32 code, u32 value) // invalidate memory address (invalid 8 bit write) void InvalidStore(u32 addr, u32 code, u32 value) { - u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register + u32 reg = ((code >> 16) & 0x1F); // The rt part of the instruction register PGXP_value* pD = NULL; PGXP_value p; @@ -86,7 +86,7 @@ void PGXP_CPU_ADDI(u32 instr, u32 rtVal, u32 rsVal) // Rt = Rs + Imm (signed) psx_value tempImm; PGXP_value ret; - + Validate(&CPU_reg[rs(instr)], rsVal); ret = CPU_reg[rs(instr)]; tempImm.d = imm(instr); @@ -674,11 +674,11 @@ void PGXP_CPU_SLL(u32 instr, u32 rdVal, u32 rtVal) PGXP_value ret; u32 sh = sa(instr); Validate(&CPU_reg[rt(instr)], rtVal); - + ret = CPU_reg[rt(instr)]; // TODO: Shift flags -#if 1 +#if 1 double x = f16Unsign(CPU_reg[rt(instr)].x); double y = f16Unsign(CPU_reg[rt(instr)].y); if (sh >= 32) @@ -797,7 +797,7 @@ void PGXP_CPU_SRL(u32 instr, u32 rdVal, u32 rtVal) else if ((valt.w.h & mask) == 0) x = x; else - x += y * (1 << (16 - sh));//f16Overflow(y); + x += y * (1 << (16 - sh));//f16Overflow(y); y = y / (1 << sh); x = f16Sign(x); @@ -882,7 +882,7 @@ void PGXP_CPU_SRA(u32 instr, u32 rdVal, u32 rtVal) else { x = x / (1 << sh); - + // check for potential sign extension in overflow psx_value valt; valt.d = rtVal; @@ -892,7 +892,7 @@ void PGXP_CPU_SRA(u32 instr, u32 rdVal, u32 rtVal) else if ((valt.w.h & mask) == 0) x = x; else - x += y * (1 << (16 - sh));//f16Overflow(y); + x += y * (1 << (16 - sh));//f16Overflow(y); y = y / (1 << sh); x = f16Sign(x); @@ -1076,7 +1076,7 @@ void PGXP_CPU_SRLV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal) else { x = x / (1 << sh); - + // check for potential sign extension in overflow psx_value valt; valt.d = rtVal; @@ -1086,7 +1086,7 @@ void PGXP_CPU_SRLV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal) else if ((valt.w.h & mask) == 0) x = x; else - x += y * (1 << (16 - sh));//f16Overflow(y); + x += y * (1 << (16 - sh));//f16Overflow(y); y = y / (1 << sh); x = f16Sign(x); @@ -1173,7 +1173,7 @@ void PGXP_CPU_SRAV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal) else { x = x / (1 << sh); - + // check for potential sign extension in overflow psx_value valt; valt.d = rtVal; @@ -1183,7 +1183,7 @@ void PGXP_CPU_SRAV(u32 instr, u32 rdVal, u32 rtVal, u32 rsVal) else if ((valt.w.h & mask) == 0) x = x; else - x += y * (1 << (16 - sh));//f16Overflow(y); + x += y * (1 << (16 - sh));//f16Overflow(y); y = y / (1 << sh); x = f16Sign(x); @@ -1402,4 +1402,4 @@ void PGXP_CP0_CTC0(u32 instr, u32 rdVal, u32 rtVal) } void PGXP_CP0_RFE(u32 instr) -{} \ No newline at end of file +{} diff --git a/libpcsxcore/ppf.c b/libpcsxcore/ppf.c index 3d2f9f30..a5d0eca8 100644 --- a/libpcsxcore/ppf.c +++ b/libpcsxcore/ppf.c @@ -23,6 +23,7 @@ #include "psxcommon.h" #include "ppf.h" #include "cdrom.h" +#include typedef struct tagPPF_DATA { s32 addr; @@ -184,7 +185,7 @@ void BuildPPFCache() { char method, undo = 0, blockcheck = 0; int dizlen = 0, dizyn; unsigned char ppfmem[512]; - char szPPF[MAXPATHLEN]; + struct dynstr szPPF; int count, seekpos, pos; u32 anz; // use 32-bit to avoid stupid overflows s32 ladr, off, anx; @@ -207,9 +208,10 @@ void BuildPPFCache() { buffer[10] = CdromId[8]; buffer[11] = '\0'; - sprintf(szPPF, "%s/%s", Config.PatchesDir, buffer); - - ppffile = fopen(szPPF, "rb"); + dynstr_init(&szPPF); + dynstr_append(&szPPF, "%s/%s", Config.PatchesDir, buffer); + ppffile = fopen(szPPF.str, "rb"); + dynstr_free(&szPPF); if (ppffile == NULL) return; memset(buffer, 0, 5); @@ -297,7 +299,7 @@ void BuildPPFCache() { } // now do the data reading - do { + do { fseek(ppffile, seekpos, SEEK_SET); fread(&pos, 4, 1, ppffile); pos = SWAP32(pos); @@ -305,7 +307,7 @@ void BuildPPFCache() { if (method == 2) fread(buffer, 4, 1, ppffile); // skip 4 bytes on ppf3 (no int64 support here) anz = fgetc(ppffile); - fread(ppfmem, anz, 1, ppffile); + fread(ppfmem, anz, 1, ppffile); ladr = pos / CD_FRAMESIZE_RAW; off = pos % CD_FRAMESIZE_RAW; @@ -391,8 +393,8 @@ boolean CheckSBI(const u8 *time) { // both BCD format for (lcv = 0; lcv < sbicount; lcv++) { - if (time[0] == sbitime[lcv][0] && - time[1] == sbitime[lcv][1] && + if (time[0] == sbitime[lcv][0] && + time[1] == sbitime[lcv][1] && time[2] == sbitime[lcv][2]) return TRUE; } diff --git a/libpcsxcore/psxcommon.h b/libpcsxcore/psxcommon.h index f2fba819..c6deaa9f 100644 --- a/libpcsxcore/psxcommon.h +++ b/libpcsxcore/psxcommon.h @@ -17,8 +17,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ -/* -* This file contains common definitions and includes for all parts of the +/* +* This file contains common definitions and includes for all parts of the * emulator core. */ @@ -172,6 +172,7 @@ typedef struct { boolean PGXP_Cache; boolean PGXP_Texture; u32 PGXP_Mode; + boolean GdbServer; #ifdef _WIN32 char Lang[256]; #endif diff --git a/libpcsxcore/psxcounters.c b/libpcsxcore/psxcounters.c index a6d7e10e..9203d62d 100644 --- a/libpcsxcore/psxcounters.c +++ b/libpcsxcore/psxcounters.c @@ -323,7 +323,7 @@ void psxRcntUpdate() } } - DebugVSync(); + if (Config.Debug) DebugVSync(); } /******************************************************************************/ diff --git a/libpcsxcore/psxinterpreter.c b/libpcsxcore/psxinterpreter.c index a4f38e6d..0ea4b1bf 100644 --- a/libpcsxcore/psxinterpreter.c +++ b/libpcsxcore/psxinterpreter.c @@ -28,6 +28,7 @@ #include "pgxp_debug.h" #include "pgxp_cpu.h" #include "pgxp_gte.h" +#include "../gdbstub/gdbstub_sys.h" static int branch = 0; static int branch2 = 0; @@ -152,12 +153,12 @@ static void delayReadWrite(int reg, u32 bpc) { psxBranchTest(); } -// this defines shall be used with the tmp +// this defines shall be used with the tmp // of the next func (instead of _Funct_...) -#define _tFunct_ ((tmp ) & 0x3F) // The funct part of the instruction register -#define _tRd_ ((tmp >> 11) & 0x1F) // The rd part of the instruction register -#define _tRt_ ((tmp >> 16) & 0x1F) // The rt part of the instruction register -#define _tRs_ ((tmp >> 21) & 0x1F) // The rs part of the instruction register +#define _tFunct_ ((tmp ) & 0x3F) // The funct part of the instruction register +#define _tRd_ ((tmp >> 11) & 0x1F) // The rd part of the instruction register +#define _tRt_ ((tmp >> 16) & 0x1F) // The rt part of the instruction register +#define _tRs_ ((tmp >> 21) & 0x1F) // The rs part of the instruction register #define _tSa_ ((tmp >> 6) & 0x1F) // The sa part of the instruction register int psxTestLoadDelay(int reg, u32 tmp) { @@ -184,7 +185,7 @@ int psxTestLoadDelay(int reg, u32 tmp) { // SYSCALL/BREAK just a break; case 0x20: case 0x21: case 0x22: case 0x23: - case 0x24: case 0x25: case 0x26: case 0x27: + case 0x24: case 0x25: case 0x26: case 0x27: case 0x2a: case 0x2b: // ADD/ADDU... case 0x04: case 0x06: case 0x07: // SLLV... if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) return 1; else @@ -271,7 +272,7 @@ int psxTestLoadDelay(int reg, u32 tmp) { case 0x12: // COP2 switch (_tFunct_) { - case 0x00: + case 0x00: switch (_tRs_) { case 0x00: // MFC2 if (_tRt_ == reg) return 3; @@ -654,8 +655,10 @@ void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs * Special purpose instructions * * Format: OP * *********************************************************/ +static void process_gdb(int); void psxBREAK() { // Break exception - psx rom doens't handles this + if (Config.GdbServer) process_gdb(1); } void psxSYSCALL() { @@ -721,9 +724,9 @@ void psxLB() { if (_Rt_) { - _i32(_rRt_) = (signed char)psxMemRead8(_oB_); + _i32(_rRt_) = (signed char)psxMemRead8(_oB_); } else { - psxMemRead8(_oB_); + psxMemRead8(_oB_); } } @@ -743,7 +746,7 @@ void psxLBU() { if (_Rt_) { _u32(_rRt_) = psxMemRead8(_oB_); } else { - psxMemRead8(_oB_); + psxMemRead8(_oB_); } } @@ -828,7 +831,7 @@ void psxLWL() { if (!_Rt_) return; - _u32(_rRt_) = ( _u32(_rRt_) & LWL_MASK[shift]) | + _u32(_rRt_) = ( _u32(_rRt_) & LWL_MASK[shift]) | ( mem << LWL_SHIFT[shift]); /* @@ -850,7 +853,7 @@ void psxLWR() { u32 mem = psxMemRead32(addr & ~3); - + // load delay = 1 latency if( branch == 0 ) { @@ -864,7 +867,7 @@ void psxLWR() { if (!_Rt_) return; - _u32(_rRt_) = ( _u32(_rRt_) & LWR_MASK[shift]) | + _u32(_rRt_) = ( _u32(_rRt_) & LWR_MASK[shift]) | ( mem >> LWR_SHIFT[shift]); /* @@ -940,7 +943,7 @@ void psxMFC0() if (!_Rt_) return; - + _i32(_rRt_) = (int)_rFs_; } @@ -958,7 +961,7 @@ void psxCFC0() if (!_Rt_) return; - + _i32(_rRt_) = (int)_rFs_; } @@ -1031,7 +1034,7 @@ void psxCFC2() * Unknow instruction (would generate an exception) * * Format: ? * *********************************************************/ -void psxNULL() { +void psxNULL() { #ifdef PSXCPU_LOG PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code); #endif @@ -1071,9 +1074,9 @@ void (*psxBSC[64])() = { psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL, - psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL, + psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL, psxNULL , psxNULL , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, - psxNULL , psxNULL , gteSWC2, psxHLE , psxNULL, psxNULL, psxNULL, psxNULL + psxNULL , psxNULL , gteSWC2, psxHLE , psxNULL, psxNULL, psxNULL, psxNULL }; @@ -1108,7 +1111,7 @@ void (*psxCP2[64])() = { gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10 psxNULL , psxNULL , psxNULL , gteNCCS, gteCC , psxNULL , gteNCS , psxNULL, // 18 gteNCT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20 - gteSQR , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28 + gteSQR , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28 gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30 psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF , gteGPL , gteNCCT // 38 }; @@ -1181,8 +1184,14 @@ static void intReset() { psxRegs.ICache_valid = FALSE; } +static int halt; + +static void intHalt() { + halt = 1; +} + static void intExecute() { - for (;;) + for (;;) execI(); } @@ -1197,14 +1206,87 @@ static void intClear(u32 Addr, u32 Size) { static void intShutdown() { } +static void process_gdb(int found_break) { + static int shutdown; + static u32 tgt_addr; + static int step, must_continue; + struct msg msg; + +start: + + if (shutdown) + return; + + if (found_break) { + msg.type = MSG_TYPE_BREAK; + gdbstub_sys_send(&msg); + must_continue = 0; + step = 0; + halt = 0; + } + else if (halt || step || (must_continue && tgt_addr && tgt_addr == psxRegs.pc)) { + msg.type = MSG_TYPE_HIT; +#if DEBUG == 1 + printf("hit address 0x%08X\n", psxRegs.pc); +#endif + gdbstub_sys_send(&msg); + must_continue = 0; + step = 0; + halt = 0; + } + + if (!must_continue) { + gdbstub_sys_recv(&msg); + + switch (msg.type) { + case MSG_TYPE_CONTINUE: + must_continue = 1; + break; + + case MSG_TYPE_STEP: + step = 1; + break; + + case MSG_TYPE_REMOVE_BREAKPOINT: { + struct msg out; + + tgt_addr = 0; + out.type = MSG_TYPE_ACK; + + gdbstub_sys_send(&out); + goto start; + } + + case MSG_TYPE_BREAKPOINT: { + struct msg out; + + tgt_addr = msg.data.breakpoint.addr; + out.type = MSG_TYPE_ACK; + + gdbstub_sys_send(&out); + goto start; + } + + case MSG_TYPE_SHUTDOWN: + shutdown = 1; + break; + + default: + fprintf(stderr, "unknown msg.type %d\n", msg.type); + break; + } + } +} + // interpreter execution -static inline void execI() { +static inline void execI() { u32 *code = Read_ICache(psxRegs.pc, FALSE); psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code)); debugI(); - if (Config.Debug) ProcessDebug(); + if (Config.GdbServer) process_gdb(0); + else if (Config.Debug) ProcessDebug(); psxRegs.pc += 4; psxRegs.cycle += BIAS; @@ -1219,5 +1301,6 @@ R3000Acpu psxInt = { intExecuteBlock, intClear, intShutdown, - intSetPGXPMode + intSetPGXPMode, + intHalt }; diff --git a/libpcsxcore/r3000a.h b/libpcsxcore/r3000a.h index b0616256..1592a020 100644 --- a/libpcsxcore/r3000a.h +++ b/libpcsxcore/r3000a.h @@ -37,6 +37,7 @@ typedef struct { void (*Clear)(u32 Addr, u32 Size); void (*Shutdown)(); void (*SetPGXPMode)(u32 pgxpMode); + void (*Halt)(); /* stops CPU */ } R3000Acpu; extern R3000Acpu *psxCpu; @@ -291,11 +292,11 @@ static inline u32 *Read_ICache(u32 pc, boolean isolate) { /**** R3000A Instruction Macros ****/ #define _PC_ psxRegs.pc // The next PC to be executed -#define _fOp_(code) ((code >> 26) ) // The opcode part of the instruction register -#define _fFunct_(code) ((code ) & 0x3F) // The funct part of the instruction register -#define _fRd_(code) ((code >> 11) & 0x1F) // The rd part of the instruction register -#define _fRt_(code) ((code >> 16) & 0x1F) // The rt part of the instruction register -#define _fRs_(code) ((code >> 21) & 0x1F) // The rs part of the instruction register +#define _fOp_(code) ((code >> 26) ) // The opcode part of the instruction register +#define _fFunct_(code) ((code ) & 0x3F) // The funct part of the instruction register +#define _fRd_(code) ((code >> 11) & 0x1F) // The rd part of the instruction register +#define _fRt_(code) ((code >> 16) & 0x1F) // The rt part of the instruction register +#define _fRs_(code) ((code >> 21) & 0x1F) // The rs part of the instruction register #define _fSa_(code) ((code >> 6) & 0x1F) // The sa part of the instruction register #define _fIm_(code) ((u16)code) // The immediate part of the instruction register #define _fTarget_(code) (code & 0x03ffffff) // The target part of the instruction register diff --git a/libpcsxcore/socket.c b/libpcsxcore/socket.c index f0b19853..77ed7a49 100644 --- a/libpcsxcore/socket.c +++ b/libpcsxcore/socket.c @@ -21,6 +21,7 @@ #include "psxcommon.h" #include "socket.h" +#include "config.h" #ifndef _WIN32 #include @@ -31,17 +32,10 @@ #include #endif -static int server_socket = 0; -static int client_socket = 0; - -static char tbuf[513]; -static int ptr = 0; - -#define PORT_NUMBER 12345 - -int StartServer() { +int StartServer(unsigned short port) { struct in_addr localhostaddr; struct sockaddr_in localsocketaddr; + int ret; #ifdef _WIN32 WSADATA wsaData; @@ -50,17 +44,17 @@ int StartServer() { return -1; #endif - server_socket = socket(AF_INET, SOCK_STREAM, 0); + ret = socket(AF_INET, SOCK_STREAM, 0); #ifdef _WIN32 - if (server_socket == INVALID_SOCKET) + if (ret == INVALID_SOCKET) return -1; #else - if (server_socket == -1) - return -1; + if (ret == -1) + return ret; #endif - SetsNonblock(); + SetsNonblock(ret); memset((void *)&localhostaddr, 0, sizeof(localhostaddr)); memset(&localsocketaddr, 0, sizeof(struct sockaddr_in)); @@ -72,59 +66,55 @@ int StartServer() { #endif localsocketaddr.sin_family = AF_INET; localsocketaddr.sin_addr = localhostaddr; - localsocketaddr.sin_port = htons(PORT_NUMBER); + localsocketaddr.sin_port = htons(port); - if (bind(server_socket, (struct sockaddr *) &localsocketaddr, sizeof(localsocketaddr)) < 0) + if (bind(ret, (const struct sockaddr *) &localsocketaddr, sizeof(localsocketaddr)) < 0) { + perror("gdbserver bind() failed"); return -1; + } - if (listen(server_socket, 1) != 0) + if (listen(ret, 1)) { + perror("gdbserver listen() failed"); return -1; + } - return 0; + return ret; } -void StopServer() { +void StopServer(int s_socket) { #ifdef _WIN32 - shutdown(server_socket, SD_BOTH); - closesocket(server_socket); + shutdown(s_socket, SD_BOTH); + closesocket(s_socket); WSACleanup(); #else - shutdown(server_socket, SHUT_RDWR); - close(server_socket); + shutdown(s_socket, SHUT_RDWR); + close(s_socket); #endif } -void GetClient() { - int new_socket; - char hello[256]; +int GetClient(int s_socket, int blocking) { + int new_socket = accept(s_socket, NULL, NULL); - new_socket = accept(server_socket, 0, 0); - #ifdef _WIN32 if (new_socket == INVALID_SOCKET) - return; + return -1; #else if (new_socket == -1) - return; + return -1; #endif - if (client_socket) - CloseClient(); - client_socket = new_socket; #ifndef _WIN32 + if (!blocking) { int flags; - flags = fcntl(client_socket, F_GETFL, 0); - fcntl(client_socket, F_SETFL, flags | O_NONBLOCK); + flags = fcntl(new_socket, F_GETFL, 0); + fcntl(new_socket, F_SETFL, flags | O_NONBLOCK); + return new_socket; } #endif - - sprintf(hello, "000 PCSXR Version %s - Debug console\r\n", PACKAGE_VERSION); - WriteSocket(hello, strlen(hello)); - ptr = 0; } -void CloseClient() { +void CloseClient(int client_socket) { if (client_socket) { #ifdef _WIN32 shutdown(client_socket, SD_BOTH); @@ -133,28 +123,69 @@ void CloseClient() { shutdown(client_socket, SHUT_RDWR); close(client_socket); #endif - client_socket = 0; } } -int HasClient() { - return client_socket ? 1 : 0; +int HasClient(int client_socket) { + return client_socket > 0; } -int ReadSocket(char * buffer, int len) { - int r; - char * endl; +#ifdef _WIN32 - if (!client_socket) - return -1; +static enum read_socket_err ReadSocketOS(SOCKET client_socket, char *buf, size_t *const len) +{ + const int res = recv(client_socket, buf, len, 0); - r = recv(client_socket, tbuf + ptr, 512 - ptr, 0); + switch (res) + { + case SOCKET_ERROR: + return READ_SOCKET_ERR_RECV; - if (r == 0) { - client_socket = 0; - if (!ptr) - return 0; + case 0: + return READ_SOCKET_SHUTDOWN; + + default: + *len = res; + + break; } + + return READ_SOCKET_OK; +} + +#elif defined(_POSIX_VERSION) + +static enum read_socket_err ReadSocketOS(int client_socket, char *buf, size_t *const len) +{ + const ssize_t res = recv(client_socket, buf, *len, 0); + + switch (res) + { + case -1: + return READ_SOCKET_ERR_RECV; + + case 0: + return READ_SOCKET_SHUTDOWN; + + default: + *len = res; + break; + } + + return READ_SOCKET_OK; +} + +#endif /* _WIN32 */ + +enum read_socket_err ReadSocket(int client_socket, char *buf, size_t *const len) { + char * endl; + + if (client_socket < 0 || !buf || !len || !*len) + return READ_SOCKET_ERR_INVALID_ARG; + + return ReadSocketOS(client_socket, buf, len); + +#if 0 #ifdef _WIN32 if (r == SOCKET_ERROR) #else @@ -185,11 +216,11 @@ int ReadSocket(char * buffer, int len) { } buffer[r] = 0; - - return r; +#endif } -int RawReadSocket(char * buffer, int len) { +int RawReadSocket(int client_socket, char *buf, size_t len) { +#if 0 int r = 0; int mlen = len < ptr ? len : ptr; @@ -206,7 +237,6 @@ int RawReadSocket(char * buffer, int len) { r = recv(client_socket, buffer + mlen, len - mlen, 0); if (r == 0) { - client_socket = 0; if (!ptr) return 0; } @@ -224,31 +254,37 @@ int RawReadSocket(char * buffer, int len) { r += mlen; return r; +#else +#warning please check + return ReadSocket(client_socket, buf, &len); +#endif } -void WriteSocket(char * buffer, int len) { - if (!client_socket) +void WriteSocket(int client_socket, const void *buffer, size_t len) { + if (client_socket <= 0) return; - send(client_socket, buffer, len, 0); + if (send(client_socket, buffer, len, 0) == -1) { + perror("send():"); + } } -void SetsBlock() { +void SetsBlock(int s_socket) { #ifdef _WIN32 u_long b = 0; - ioctlsocket(server_socket, FIONBIO, &b); + ioctlsocket(s_socket, FIONBIO, &b); #else - int flags = fcntl(server_socket, F_GETFL, 0); - fcntl(server_socket, F_SETFL, flags & ~O_NONBLOCK); + int flags = fcntl(s_socket, F_GETFL, 0); + fcntl(s_socket, F_SETFL, flags & ~O_NONBLOCK); #endif } -void SetsNonblock() { +void SetsNonblock(int s_socket) { #ifdef _WIN32 u_long b = 1; - ioctlsocket(server_socket, FIONBIO, &b); + ioctlsocket(s_socket, FIONBIO, &b); #else - int flags = fcntl(server_socket, F_GETFL, 0); - fcntl(server_socket, F_SETFL, flags | O_NONBLOCK); + int flags = fcntl(s_socket, F_GETFL, 0); + fcntl(s_socket, F_SETFL, flags | O_NONBLOCK); #endif } diff --git a/libpcsxcore/socket.h b/libpcsxcore/socket.h index 7ee0deb4..852c76a4 100644 --- a/libpcsxcore/socket.h +++ b/libpcsxcore/socket.h @@ -22,20 +22,30 @@ extern "C" { #endif -int StartServer(); -void StopServer(); +#include -void GetClient(); -void CloseClient(); +enum read_socket_err +{ + READ_SOCKET_OK, + READ_SOCKET_ERR_INVALID_ARG, + READ_SOCKET_ERR_RECV, + READ_SOCKET_SHUTDOWN +}; -int HasClient(); +int StartServer(unsigned short port); +void StopServer(int s_socket); -int ReadSocket(char * buffer, int len); -int RawReadSocket(char * buffer, int len); -void WriteSocket(char * buffer, int len); +int GetClient(int s_socket, int blocking); +void CloseClient(int client_socket); -void SetsBlock(); -void SetsNonblock(); +int HasClient(int client_socket); + +enum read_socket_err ReadSocket(int client_socket, char *buffer, size_t *len); +int RawReadSocket(int client_socket, char *buffer, size_t len); +void WriteSocket(int client_socket, const void *buffer, size_t len); + +void SetsBlock(int s_socket); +void SetsNonblock(int s_socket); #ifdef __cplusplus } diff --git a/plugins/peopsxgl/CMakeLists.txt b/plugins/peopsxgl/CMakeLists.txt index 907009ce..e4621b6d 100644 --- a/plugins/peopsxgl/CMakeLists.txt +++ b/plugins/peopsxgl/CMakeLists.txt @@ -18,6 +18,7 @@ set(GTK_LIBRARIES ${GTK3_LIBRARY} ${GDK3_LIBRARY} ${GDKPixbuf_LIBRARY} ${Pango_L find_package(X11 REQUIRED) +set(OpenGL_GL_PREFERENCE LEGACY) find_package(OpenGL REQUIRED) if(NOT OPENGL_FOUND) message(FATAL_ERROR "GL library not found") diff --git a/plugins/peopsxgl/pgxp_gpu.c b/plugins/peopsxgl/pgxp_gpu.c index 184c7452..afb6cf31 100644 --- a/plugins/peopsxgl/pgxp_gpu.c +++ b/plugins/peopsxgl/pgxp_gpu.c @@ -160,7 +160,7 @@ void CALLBACK GPUpgxpCacheVertex(short sx, short sy, const unsigned char* _pVert if ((fabsf(pOldVertex->x - pNewVertex->x) > 0.1f) || (fabsf(pOldVertex->y - pNewVertex->y) > 0.1f) || (fabsf(pOldVertex->z - pNewVertex->z) > 0.1f)) - { + { pOldVertex->mFlags = 5; return; } @@ -390,6 +390,11 @@ int PGXP_GetVertices(unsigned int* addr, void* pOutput, int xOffs, int yOffs) // calculate offset to actual data int offset = 0; + + /* Dirty hack */ + if (!pDMABlock) + return 0; + while ((pDMABlock[offset] != *addr) && (offset < blockSize)) { unsigned char command = (unsigned char)((pDMABlock[offset] >> 24) & 0xff); @@ -455,7 +460,7 @@ int PGXP_GetVertices(unsigned int* addr, void* pOutput, int xOffs, int yOffs) } // Log incorrect vertices - //if (PGXP_tDebug && + //if (PGXP_tDebug && // (fabs((float)pPrimData[stride * i * 2] - primStart[stride * i].x) > debug_tolerance) || // (fabs((float)pPrimData[(stride * i * 2) + 1] - primStart[stride * i].y) > debug_tolerance)) // __Log("GPPV: v:%x (%d, %d) pgxp(%f, %f)|\n", (currentAddr + offset + 1 + (i * stride)) * 4, pPrimData[stride * i * 2], pPrimData[(stride * i * 2) + 1], primStart[stride * i].x, primStart[stride * i].y); @@ -527,7 +532,7 @@ enum PGXP_vDebugMode vDEBUG_MAX, vDEBUG_TEXCOORD, - vDEBUG_ID, + vDEBUG_ID, }; const char red[4] = { 255, 0, 0, 255 }; @@ -569,7 +574,7 @@ void ColourFromRange(float val, float min, float max, GLubyte alpha, int wrap) if (wrap) val = fmod(val, 1); - if (0 <= val && val<= 1.f / 8.f) + if (0 <= val && val<= 1.f / 8.f) { r = 0; g = 0; @@ -672,7 +677,7 @@ void PGXP_colour(OGLVertex* vertex, GLubyte alpha, int prim, int isTextured, int glColor4ubv(vertex->c.col); break; } - + break; case vDEBUG_TEXTURE: // Texture only @@ -830,4 +835,4 @@ int PGXP_DrawDebugQuad(OGLVertex* vertex1, OGLVertex* vertex2, OGLVertex* vertex int PGXP_DrawDebugTriQuad(OGLVertex* vertex1, OGLVertex* vertex2, OGLVertex* vertex3, OGLVertex* vertex4, int colourMode, int isTextured) { return DrawDebugPrim(DRAW_TRIQUAD, vertex1, vertex2, vertex3, vertex4, colourMode, isTextured); -} \ No newline at end of file +} diff --git a/win32/gui/WndMain.c b/win32/gui/WndMain.c index 67e29ef3..5602f41a 100644 --- a/win32/gui/WndMain.c +++ b/win32/gui/WndMain.c @@ -225,6 +225,12 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine return 0; } + else if (strcmp(arg, "-gdb") == 0) { + /* Force configuration. */ + Config.Cpu = CPU_INTERPRETER; + Config.GdbServer = 1; + dbg_start(); + } } if (SysInit() == -1) return 1; @@ -261,10 +267,10 @@ void RestoreWindow() { AccBreak = 1; DestroyWindow(gApp.hWnd); CreateMainWindow(SW_SHOWNORMAL); - + if(Config.HideCursor) ShowCursor(TRUE); - + //SetCursor(LoadCursor(gApp.hInstance, IDC_ARROW)); //ShowCursor(TRUE); @@ -279,7 +285,7 @@ void ResetMenuSlots() { GetStateFilename(str, i); if (CheckState(str) == -1) EnableMenuItem(gApp.hMenu, ID_FILE_STATES_LOAD_SLOT1+i, MF_GRAYED); - else + else EnableMenuItem(gApp.hMenu, ID_FILE_STATES_LOAD_SLOT1+i, MF_ENABLED); } } @@ -382,7 +388,7 @@ void OnStates_LoadOther() { Running = 1; psxCpu->Execute(); } -} +} void OnStates_SaveOther() { OPENFILENAME ofn; @@ -428,7 +434,7 @@ void OnStates_SaveOther() { Running = 1; psxCpu->Execute(); } -} +} LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { char File[256]; @@ -475,7 +481,7 @@ LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { SysMessage(_("The CD does not appear to be a valid Playstation CD")); return TRUE; } - + // Auto-detect: region first, then rcnt reset SysReset(); @@ -532,7 +538,7 @@ LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { // Auto-detect: region first, then rcnt reset SysReset(); - + if (LoadCdrom() == -1) { ClosePlugins(); RestoreWindow(); @@ -559,7 +565,7 @@ LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { // Auto-detect: region first, then rcnt reset SysReset(); - + Load(File); Running = 1; psxCpu->Execute(); @@ -604,7 +610,7 @@ LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { // Auto-detect: region first, then rcnt reset SysReset(); - + if (LoadCdrom() == -1) { fprintf(stderr, _("Could not load CD-ROM!")); ClosePlugins(); @@ -634,7 +640,7 @@ LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { // Auto-detect: region first, then rcnt reset SysReset(); - + LoadCdrom(); if(Config.HideCursor) ShowCursor(FALSE); @@ -820,48 +826,48 @@ void CreateListView(int idc) { int GetRGB() { HDC scrDC, memDC; - HBITMAP oldBmp = NULL; + HBITMAP oldBmp = NULL; HBITMAP curBmp = NULL; COLORREF oldColor; COLORREF curColor = RGB(255,255,255); int i, R, G, B; R = G = B = 1; - + scrDC = CreateDC("DISPLAY", NULL, NULL, NULL); - memDC = CreateCompatibleDC(NULL); - curBmp = CreateCompatibleBitmap(scrDC, 1, 1); + memDC = CreateCompatibleDC(NULL); + curBmp = CreateCompatibleBitmap(scrDC, 1, 1); oldBmp = (HBITMAP)SelectObject(memDC, curBmp); - + for (i = 255; i >= 0; --i) { oldColor = curColor; curColor = SetPixel(memDC, 0, 0, RGB(i, i, i)); - - if (GetRValue(curColor) < GetRValue(oldColor)) ++R; + + if (GetRValue(curColor) < GetRValue(oldColor)) ++R; if (GetGValue(curColor) < GetGValue(oldColor)) ++G; if (GetBValue(curColor) < GetBValue(oldColor)) ++B; } - + DeleteObject(oldBmp); DeleteObject(curBmp); DeleteDC(scrDC); DeleteDC(memDC); - + return (R * G * B); } - + HICON GetIcon(short *icon) { ICONINFO iInfo; HDC hDC; char mask[16*16]; int x, y, c, Depth; - + hDC = CreateIC("DISPLAY",NULL,NULL,NULL); Depth=GetDeviceCaps(hDC, BITSPIXEL); DeleteDC(hDC); - + if (Depth == 16) { - if (GetRGB() == (32 * 32 * 32)) + if (GetRGB() == (32 * 32 * 32)) Depth = 15; } @@ -869,8 +875,8 @@ HICON GetIcon(short *icon) { for (x=0; x<16; x++) { c = icon[y*16+x]; if (Depth == 15 || Depth == 32) - c = ((c&0x001f) << 10) | - ((c&0x7c00) >> 10) | + c = ((c&0x001f) << 10) | + ((c&0x7c00) >> 10) | ((c&0x03e0) ); else c = ((c&0x001f) << 11) | @@ -879,20 +885,20 @@ HICON GetIcon(short *icon) { icon[y*16+x] = c; } - } + } iInfo.fIcon = TRUE; memset(mask, 0, 16*16); iInfo.hbmMask = CreateBitmap(16, 16, 1, 1, mask); - iInfo.hbmColor = CreateBitmap(16, 16, 1, 16, icon); - + iInfo.hbmColor = CreateBitmap(16, 16, 1, 16, icon); + return CreateIconIndirect(&iInfo); } HICON hICON[2][3][15]; -int aIover[2]; +int aIover[2]; int ani[2]; - + void LoadMcdItems(int mcd, int idc) { HWND List = GetDlgItem(mcdDlg, idc); LV_ITEM item; @@ -900,37 +906,37 @@ void LoadMcdItems(int mcd, int idc) { int i, j; HICON hIcon; McdBlock *Info; - + aIover[mcd-1]=0; ani[mcd-1]=0; - + ListView_DeleteAllItems(List); for (i=0; i<15; i++) { - + item.mask = LVIF_TEXT | LVIF_IMAGE; item.iItem = i; item.iImage = i; item.pszText = LPSTR_TEXTCALLBACK; item.iSubItem = 0; - + IconC[mcd-1][i] = 0; Info = &Blocks[mcd-1][i]; - + if ((Info->Flags & 0xF) == 1 && Info->IconCount != 0) { - hIcon = GetIcon(Info->Icon); - + hIcon = GetIcon(Info->Icon); + if (Info->IconCount > 1) { for(j = 0; j < 3; j++) hICON[mcd-1][j][i]=hIcon; } } else { - hIcon = eICON; + hIcon = eICON; } - + ImageList_ReplaceIcon(iml, -1, hIcon); ListView_InsertItem(List, &item); - } + } } void UpdateMcdItems(int mcd, int idc) { @@ -940,38 +946,38 @@ void UpdateMcdItems(int mcd, int idc) { int i, j; McdBlock *Info; HICON hIcon; - + aIover[mcd-1]=0; ani[mcd-1]=0; - - for (i=0; i<15; i++) { - + + for (i=0; i<15; i++) { + item.mask = LVIF_TEXT | LVIF_IMAGE; item.iItem = i; item.iImage = i; item.pszText = LPSTR_TEXTCALLBACK; item.iSubItem = 0; - - IconC[mcd-1][i] = 0; + + IconC[mcd-1][i] = 0; Info = &Blocks[mcd-1][i]; - + if ((Info->Flags & 0xF) == 1 && Info->IconCount != 0) { - hIcon = GetIcon(Info->Icon); - - if (Info->IconCount > 1) { + hIcon = GetIcon(Info->Icon); + + if (Info->IconCount > 1) { for(j = 0; j < 3; j++) hICON[mcd-1][j][i]=hIcon; } - } else { - hIcon = eICON; + } else { + hIcon = eICON; } - + ImageList_ReplaceIcon(iml, i, hIcon); ListView_SetItem(List, &item); - } + } ListView_Update(List, -1); } - + void McdListGetDispInfo(int mcd, int idc, LPNMHDR pnmh) { LV_DISPINFO *lpdi = (LV_DISPINFO *)pnmh; McdBlock *Info; @@ -1050,22 +1056,22 @@ void UpdateMcdIcon(int mcd, int idc) { HIMAGELIST iml = Iiml[mcd-1]; int i; McdBlock *Info; - int *count; - + int *count; + if(!aIover[mcd-1]) { - ani[mcd-1]++; - + ani[mcd-1]++; + for (i=0; i<15; i++) { Info = &Blocks[mcd-1][i]; count = &IconC[mcd-1][i]; - + if ((Info->Flags & 0xF) != 1) continue; if (Info->IconCount <= 1) continue; - + if (*count < Info->IconCount) { (*count)++; aIover[mcd-1]=0; - + if(ani[mcd-1] <= (Info->IconCount-1)) // last frame and below... hICON[mcd-1][ani[mcd-1]][i] = GetIcon(&Info->Icon[(*count)*16*16]); } else { @@ -1073,14 +1079,14 @@ void UpdateMcdIcon(int mcd, int idc) { } } - } else { - + } else { + if (ani[mcd-1] > 1) ani[mcd-1] = 0; // 1st frame else ani[mcd-1]++; // 2nd, 3rd frame - + for(i=0;i<15;i++) { Info = &Blocks[mcd-1][i]; - + if (((Info->Flags & 0xF) == 1) && (Info->IconCount > 1)) ImageList_ReplaceIcon(iml, i, hICON[mcd-1][ani[mcd-1]][i]); } @@ -1116,7 +1122,7 @@ BOOL CALLBACK ConfigureMcdsDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lPa Button_SetText(GetDlgItem(hW, IDC_PASTE), _("Paste")); Button_SetText(GetDlgItem(hW, IDC_DELETE1), _("<- Un/Delete")); Button_SetText(GetDlgItem(hW, IDC_DELETE2), _("Un/Delete ->")); - + Static_SetText(GetDlgItem(hW, IDC_FRAMEMCD1), _("Memory Card 1")); Static_SetText(GetDlgItem(hW, IDC_FRAMEMCD2), _("Memory Card 2")); @@ -1143,10 +1149,10 @@ BOOL CALLBACK ConfigureMcdsDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lPa CreateListView(IDC_LIST1); CreateListView(IDC_LIST2); - + Iiml[0] = ImageList_Create(16, 16, ILC_COLOR16, 0, 0); Iiml[1] = ImageList_Create(16, 16, ILC_COLOR16, 0, 0); - + ListView_SetImageList(GetDlgItem(mcdDlg, IDC_LIST1), Iiml[0], LVSIL_SMALL); ListView_SetImageList(GetDlgItem(mcdDlg, IDC_LIST2), Iiml[1], LVSIL_SMALL); @@ -1274,18 +1280,18 @@ BOOL CALLBACK ConfigureMcdsDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lPa return TRUE; - case IDC_MCDSEL1: - Open_Mcd_Proc(hW, 1); + case IDC_MCDSEL1: + Open_Mcd_Proc(hW, 1); return TRUE; - case IDC_MCDSEL2: - Open_Mcd_Proc(hW, 2); + case IDC_MCDSEL2: + Open_Mcd_Proc(hW, 2); return TRUE; - case IDC_RELOAD1: + case IDC_RELOAD1: Edit_GetText(GetDlgItem(hW,IDC_MCD1), str, 256); LoadMcd(1, str); UpdateMcdDlg(); return TRUE; - case IDC_RELOAD2: + case IDC_RELOAD2: Edit_GetText(GetDlgItem(hW,IDC_MCD2), str, 256); LoadMcd(2, str); UpdateMcdDlg(); @@ -1340,12 +1346,12 @@ BOOL CALLBACK ConfigureMcdsDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lPa } -BOOL CALLBACK ConfigurePGXPDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) +BOOL CALLBACK ConfigurePGXPDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) { long tmp; RECT rect; - switch (uMsg) + switch (uMsg) { case WM_INITDIALOG: SetWindowText(hW, _("PGXP Config")); @@ -1374,7 +1380,7 @@ BOOL CALLBACK ConfigurePGXPDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lPa Static_SetText(GetDlgItem(hW, IDC_PGXP_MODETEXT), _("Error: Uknown mode")); } - case WM_COMMAND: + case WM_COMMAND: switch (LOWORD(wParam)) { case IDCANCEL: @@ -1423,7 +1429,7 @@ BOOL CALLBACK ConfigurePGXPDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lPa return TRUE; } } - + return FALSE; } @@ -1506,7 +1512,7 @@ BOOL CALLBACK ConfigureCpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lPar if (Config.OverClock) EnableWindow(GetDlgItem(hW, IDC_PSXCLOCK), TRUE); - else + else EnableWindow(GetDlgItem(hW, IDC_PSXCLOCK), FALSE); break; @@ -1569,6 +1575,10 @@ BOOL CALLBACK ConfigureCpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lPar else StopDebugger(); } + if (Config.GdbServer) { + dbg_start(); + } + SaveConfig(); EndDialog(hW,TRUE); @@ -1619,7 +1629,7 @@ void Open_Mcd_Proc(HWND hW, int mcd) { memset(&szFilter, 0, sizeof(szFilter)); strcpy(szFilter, _("Psx Mcd Format (*.mcr;*.mc;*.mem;*.vgs;*.mcd;*.gme;*.ddf)")); - str = szFilter + strlen(szFilter) + 1; + str = szFilter + strlen(szFilter) + 1; strcpy(str, "*.mcr;*.mcd;*.mem;*.gme;*.mc;*.ddf"); str+= strlen(str) + 1; @@ -1725,7 +1735,7 @@ int Open_Iso_Proc(char *file) { ofn.hwndOwner = gApp.hWnd; strcpy(szFilter, _("Psx Isos (*.iso;*.mdf;*.img;*.bin;*.cue;*.pbp;*.cbn)")); - str = szFilter + strlen(szFilter) + 1; + str = szFilter + strlen(szFilter) + 1; strcpy(str, "*.iso;*.mdf;*.img;*.bin;*.cue;*.pbp;*.cbn"); str += strlen(str) + 1; @@ -1942,15 +1952,15 @@ void InitLanguages() { } char *GetLanguageNext() { - if (lFind == INVALID_HANDLE_VALUE) + if (lFind == INVALID_HANDLE_VALUE) return NULL; for (;;) { if (lFirst == 0) { if (FindNextFile(lFind, &lFindData) == FALSE) return NULL; - } - else + } + else lFirst = 0; if (!strcmp(lFindData.cFileName, ".") || @@ -1992,6 +2002,7 @@ int SysInit() { LoadMcds(Config.Mcd1, Config.Mcd2); if (Config.Debug) StartDebugger(); + else if (Config.GdbServer) dbg_start(); return 0; } @@ -2005,6 +2016,7 @@ void SysClose() { ReleasePlugins(); StopDebugger(); + if (Config.GdbServer) dbg_stop(); if (Config.PsxOut) CloseConsole();