diff options
| author | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2009-10-09 10:00:15 +0000 |
|---|---|---|
| committer | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2009-10-09 10:00:15 +0000 |
| commit | c053578923c3367a442f2a850ccdd5380489c544 (patch) | |
| tree | d3088cce35230b8b8fa73faed5626e5bafac95a6 /libpcsxcore | |
| parent | 9c12bf58c89d134f30c5ff07b3b2606999d335df (diff) | |
| download | pcsxr-c053578923c3367a442f2a850ccdd5380489c544.tar.gz | |
git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@31468 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'libpcsxcore')
| -rw-r--r-- | libpcsxcore/Makefile.am | 5 | ||||
| -rw-r--r-- | libpcsxcore/Makefile.in | 44 | ||||
| -rw-r--r-- | libpcsxcore/debug.c | 1144 | ||||
| -rw-r--r-- | libpcsxcore/debug.h | 25 | ||||
| -rw-r--r-- | libpcsxcore/psxcommon.h | 2 | ||||
| -rw-r--r-- | libpcsxcore/psxcounters.c | 1 | ||||
| -rw-r--r-- | libpcsxcore/psxinterpreter.c | 55 | ||||
| -rw-r--r-- | libpcsxcore/psxmem.c | 14 | ||||
| -rw-r--r-- | libpcsxcore/r3000a.c | 6 | ||||
| -rw-r--r-- | libpcsxcore/r3000a.h | 1 | ||||
| -rw-r--r-- | libpcsxcore/socket.c | 254 | ||||
| -rw-r--r-- | libpcsxcore/socket.h | 36 |
12 files changed, 1517 insertions, 70 deletions
diff --git a/libpcsxcore/Makefile.am b/libpcsxcore/Makefile.am index cda48978..5704ec5e 100644 --- a/libpcsxcore/Makefile.am +++ b/libpcsxcore/Makefile.am @@ -23,6 +23,7 @@ libpcsxcore_a_SOURCES = \ $(top_builddir)/libpcsxcore/psxhle.c \ $(top_builddir)/libpcsxcore/cdrom.h \ $(top_builddir)/libpcsxcore/coff.h \ + $(top_builddir)/libpcsxcore/debug.c \ $(top_builddir)/libpcsxcore/debug.h \ $(top_builddir)/libpcsxcore/decode_xa.h \ $(top_builddir)/libpcsxcore/gte.h \ @@ -44,7 +45,9 @@ libpcsxcore_a_SOURCES = \ $(top_builddir)/libpcsxcore/cdriso.c \ $(top_builddir)/libpcsxcore/cdriso.h \ $(top_builddir)/libpcsxcore/cheat.c \ - $(top_builddir)/libpcsxcore/cheat.h + $(top_builddir)/libpcsxcore/cheat.h \ + $(top_builddir)/libpcsxcore/socket.c \ + $(top_builddir)/libpcsxcore/socket.h if ARCH_X86_64 libpcsxcore_a_SOURCES += \ diff --git a/libpcsxcore/Makefile.in b/libpcsxcore/Makefile.in index 8483f7b8..87d9fc77 100644 --- a/libpcsxcore/Makefile.in +++ b/libpcsxcore/Makefile.in @@ -88,6 +88,7 @@ am__libpcsxcore_a_SOURCES_DIST = \ $(top_builddir)/libpcsxcore/psxhle.c \ $(top_builddir)/libpcsxcore/cdrom.h \ $(top_builddir)/libpcsxcore/coff.h \ + $(top_builddir)/libpcsxcore/debug.c \ $(top_builddir)/libpcsxcore/debug.h \ $(top_builddir)/libpcsxcore/decode_xa.h \ $(top_builddir)/libpcsxcore/gte.h \ @@ -110,6 +111,8 @@ am__libpcsxcore_a_SOURCES_DIST = \ $(top_builddir)/libpcsxcore/cdriso.h \ $(top_builddir)/libpcsxcore/cheat.c \ $(top_builddir)/libpcsxcore/cheat.h \ + $(top_builddir)/libpcsxcore/socket.c \ + $(top_builddir)/libpcsxcore/socket.h \ $(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c \ $(top_builddir)/libpcsxcore/ix86_64/ix86-64.c \ $(top_builddir)/libpcsxcore/ix86_64/ix86_cpudetect.c \ @@ -137,9 +140,9 @@ am_libpcsxcore_a_OBJECTS = psxbios.$(OBJEXT) cdrom.$(OBJEXT) \ spu.$(OBJEXT) sio.$(OBJEXT) psxhw.$(OBJEXT) mdec.$(OBJEXT) \ psxmem.$(OBJEXT) misc.$(OBJEXT) plugins.$(OBJEXT) \ decode_xa.$(OBJEXT) r3000a.$(OBJEXT) psxinterpreter.$(OBJEXT) \ - gte.$(OBJEXT) psxhle.$(OBJEXT) cdriso.$(OBJEXT) \ - cheat.$(OBJEXT) $(am__objects_1) $(am__objects_2) \ - $(am__objects_3) + gte.$(OBJEXT) psxhle.$(OBJEXT) debug.$(OBJEXT) \ + cdriso.$(OBJEXT) cheat.$(OBJEXT) socket.$(OBJEXT) \ + $(am__objects_1) $(am__objects_2) $(am__objects_3) libpcsxcore_a_OBJECTS = $(am_libpcsxcore_a_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include depcomp = $(SHELL) $(top_srcdir)/depcomp @@ -330,6 +333,7 @@ libpcsxcore_a_SOURCES = $(top_builddir)/libpcsxcore/psxbios.c \ $(top_builddir)/libpcsxcore/psxhle.c \ $(top_builddir)/libpcsxcore/cdrom.h \ $(top_builddir)/libpcsxcore/coff.h \ + $(top_builddir)/libpcsxcore/debug.c \ $(top_builddir)/libpcsxcore/debug.h \ $(top_builddir)/libpcsxcore/decode_xa.h \ $(top_builddir)/libpcsxcore/gte.h \ @@ -351,7 +355,9 @@ libpcsxcore_a_SOURCES = $(top_builddir)/libpcsxcore/psxbios.c \ $(top_builddir)/libpcsxcore/cdriso.c \ $(top_builddir)/libpcsxcore/cdriso.h \ $(top_builddir)/libpcsxcore/cheat.c \ - $(top_builddir)/libpcsxcore/cheat.h $(am__append_1) \ + $(top_builddir)/libpcsxcore/cheat.h \ + $(top_builddir)/libpcsxcore/socket.c \ + $(top_builddir)/libpcsxcore/socket.h $(am__append_1) \ $(am__append_2) $(am__append_3) @ARCH_PPC_TRUE@libpcsxcore_a_CCASFLAGS = -x assembler-with-cpp -mregnames all: all-am @@ -404,6 +410,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdriso.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cheat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decode_xa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/disr3000a.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gte.Po@am__quote@ @@ -431,6 +438,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/r3000a.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reguse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spu.Po@am__quote@ .c.o: @@ -692,6 +700,20 @@ psxhle.obj: $(top_builddir)/libpcsxcore/psxhle.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o psxhle.obj `if test -f '$(top_builddir)/libpcsxcore/psxhle.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/psxhle.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/psxhle.c'; fi` +debug.o: $(top_builddir)/libpcsxcore/debug.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT debug.o -MD -MP -MF $(DEPDIR)/debug.Tpo -c -o debug.o `test -f '$(top_builddir)/libpcsxcore/debug.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/debug.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/debug.Tpo $(DEPDIR)/debug.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/debug.c' object='debug.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o debug.o `test -f '$(top_builddir)/libpcsxcore/debug.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/debug.c + +debug.obj: $(top_builddir)/libpcsxcore/debug.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT debug.obj -MD -MP -MF $(DEPDIR)/debug.Tpo -c -o debug.obj `if test -f '$(top_builddir)/libpcsxcore/debug.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/debug.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/debug.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/debug.Tpo $(DEPDIR)/debug.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/debug.c' object='debug.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o debug.obj `if test -f '$(top_builddir)/libpcsxcore/debug.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/debug.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/debug.c'; fi` + cdriso.o: $(top_builddir)/libpcsxcore/cdriso.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdriso.o -MD -MP -MF $(DEPDIR)/cdriso.Tpo -c -o cdriso.o `test -f '$(top_builddir)/libpcsxcore/cdriso.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/cdriso.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/cdriso.Tpo $(DEPDIR)/cdriso.Po @@ -720,6 +742,20 @@ cheat.obj: $(top_builddir)/libpcsxcore/cheat.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cheat.obj `if test -f '$(top_builddir)/libpcsxcore/cheat.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/cheat.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/cheat.c'; fi` +socket.o: $(top_builddir)/libpcsxcore/socket.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT socket.o -MD -MP -MF $(DEPDIR)/socket.Tpo -c -o socket.o `test -f '$(top_builddir)/libpcsxcore/socket.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/socket.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/socket.Tpo $(DEPDIR)/socket.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/socket.c' object='socket.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o socket.o `test -f '$(top_builddir)/libpcsxcore/socket.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/socket.c + +socket.obj: $(top_builddir)/libpcsxcore/socket.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT socket.obj -MD -MP -MF $(DEPDIR)/socket.Tpo -c -o socket.obj `if test -f '$(top_builddir)/libpcsxcore/socket.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/socket.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/socket.c'; fi` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/socket.Tpo $(DEPDIR)/socket.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$(top_builddir)/libpcsxcore/socket.c' object='socket.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o socket.obj `if test -f '$(top_builddir)/libpcsxcore/socket.c'; then $(CYGPATH_W) '$(top_builddir)/libpcsxcore/socket.c'; else $(CYGPATH_W) '$(srcdir)/$(top_builddir)/libpcsxcore/socket.c'; fi` + iR3000A-64.o: $(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iR3000A-64.o -MD -MP -MF $(DEPDIR)/iR3000A-64.Tpo -c -o iR3000A-64.o `test -f '$(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c' || echo '$(srcdir)/'`$(top_builddir)/libpcsxcore/ix86_64/iR3000A-64.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/iR3000A-64.Tpo $(DEPDIR)/iR3000A-64.Po diff --git a/libpcsxcore/debug.c b/libpcsxcore/debug.c new file mode 100644 index 00000000..b5c02b1e --- /dev/null +++ b/libpcsxcore/debug.c @@ -0,0 +1,1144 @@ +/* Pcsx - Pc Psx Emulator + * Copyright (C) 1999-2003 Pcsx Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses>. + */ + +#include "psxcommon.h" +#include "r3000a.h" +#include "debug.h" +#include "socket.h" + +/* +PCSX Debug console protocol description, version 1.0 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Commands number are formatted using %03X (yes) +Registers number are formatted using %02X. +Breakpoints numbers are formatted using %X +All other values are formatted using %08X, unless specified. + + +Client inputs: +~~~~~~~~~~~~~ +Basic commands (1xx): +-------------------- +100 <message> + Sends a dumb message. Will be replied with a 200 reply, followed by the message. +101 + Gets PCSX version. +102 + Gets protocol version. +103 + Gets status +110 + Gets PC. +111 [reg] + Gets GP register, or all, if no argument. +112 + Gets LO/HI registers. +113 [reg] + Gets COP0 register, or all, if no argument. +114 [reg] + Gets COP2 control register, or all, if no argument. +115 [reg] + Gets COP2 data register, or all, if no argument. +119 [pc] + Disassemble current PC, or given PC. +121 <reg>=<value> + Sets a GP register. Will return a 221 message. +122 <LO|HI>=<value> + Sets LO or HI register. Will return a 222 message. +123 <reg>=<value> + Sets a COP0 register. Will return a 223 message. +124 <reg>=<value> + Sets a COP2 control register. Will return a 224 message. +125 <reg>=<value> + Sets a COP2 data register. Will return a 225 message. +130 <size>@<addr> + Dumps a range of memory, of size bytes starting at addr. +140 <size>@<addr> + Sets a range of memory, of size bytes starting at addr. + Will have to send immediately exactly size bytes afterward. +150 [number] + Starts/reset mapping execution flow, or stop it if number = 0 +151 [number] + Starts/reset mapping read8 flow, or stop it if number = 0 +152 [number] + Starts/reset mapping read16 flow, or stop it if number = 0 +153 [number] + Starts/reset mapping read32 flow, or stop it if number = 0 +154 [number] + Starts/reset mapping write8 flow, or stop it if number = 0 +155 [number] + Starts/reset mapping write16 flow, or stop it if number = 0 +156 [number] + Starts/reset mapping write32 flow, or stop it if number = 0 +160 [number] + Breaks on map exec flow, or stop it if number = 0 +161 [number] + Breaks on map read8 flow, or stop it if number = 0 +162 [number] + Breaks on map read16 flow, or stop it if number = 0 +163 [number] + Breaks on map read32 flow, or stop it if number = 0 +164 [number] + Breaks on map write8 flow, or stop it if number = 0 +165 [number] + Breaks on map write16 flow, or stop it if number = 0 +166 [number] + Breaks on map write32 flow, or stop it if number = 0 +170 + Dumps the execution flow map in an IDC file + +Execution flow control commands (3xx): +------------------------------------- +300 [number] + Get a list of the actual breakpoints. Will get '400' answers. +301 [number] + Deletes a breakpoint, or all, if no arguments. +310 <address> + Sets an exec breakpoint. +320 <address> + Sets a read breakpoint, 1 byte / 8 bits. +321 <address> + Sets a read breakpoint, 2 bytes / 16 bits, has to be on an even address. +322 <address> + Sets a read breakpoint, 4 bytes / 32 bits, address has to be 4-bytes aligned. +330 <address> + Sets a write breakpoint, 1 byte / 8 bits. +331 <address> + Sets a write breakpoint, 2 bytes / 16 bits, has to be on an even address. +332 <address> + Sets a write breakpoint, 4 bytes / 32 bits, address has to be 4-bytes aligned. +390 + Pauses execution. Equivalents to a breakpoint. +391 + Restarts execution. +395 [number] + Traces execution, 1 instruction by default. Formatted using %i +398 + Soft (quick) resets. +399 + Resets. + + +Server outputs: +~~~~~~~~~~~~~~ +Spontaneous messages (0xx): +-------------------------- +000 <message> + Greeting banner. +010 / 011 / 012 / 013 / 014 / 015 / 016 + Execution hit mapping flow automatic breakpoint. +030 <number>@<PC> + Execution hit breakpoint, PCSX is paused. Displays PC's value. + +Basic commands acknowledge (2xx): +-------------------------------- +200 <message> + Sends a dumb message. +201 <message> + Returns PCSX version. +202 <message> + Returns protocol version. +203 <status> + status = 0: running; = 1: paused; = 2: trace +210 PC=<value> + Displays current PC value. +211 <reg>=<value> + Displays one GP register value. +212 LO=<value> HI=<value> + Displays LO/HI registers. +213 <reg>=<value> + Displays one COP0 register value. +214 <reg>=<value> + Displays one COP2 control register value. +215 <reg>=<value> + Displays one COP2 data register value. +219 <message> + Displays one line of disassembled code. +221 <reg>=<value> + Displays one GP register value, ack for modification. +222 LO=<value> HI=<value> + Displays LO/HI registers, ack for modification. +223 <reg>=<value> + Displays one COP0 register value, ack for modification. +224 <reg>=<value> + Displays one COP2 control register value, ack for modification. +225 <reg>=<value> + Displays one COP2 data register value, ack for modification. +230 <size>@<addr> + Dumping memory. Will then raw outputs size bytes. +240 <size>@<addr> + Memory set acknowledge. +250 / 251 / 252 / 253 / 254 / 255 / 256 + Acknolwedge of 15x commands. +260 / 261 / 262 / 263 / 264 / 265 / 266 + Acknolwedge of 16x commands. +270 + Acknolwedge of 170 command. + +Execution flow control commands acknowledge (4xx): +------------------------------------------------- +400 <number>@<address>-<type> + Displays a breakpoint, where 'type' can be of E, R1, R2, R4, W1, W2 or W4. +401 <message> + Breakpoint deleting acknowledge. +410, 420, 421, 422, 430, 431, 432 <number> + Breakpoint adding acknowledge. Returns the number of the added breakpoint. +490 <message> + Pausing. +491 <message> + Resuming. +495 <message> + Tracing. +498 <message> + Soft resetting. +499 <message> + Resetting. + +Error messages (5xx): +-------------------- +500 <message> + Command not understood. +511 <message> + Invalid GPR register. +512 <message> + Invalid LO/HI register. +513, 514 <message> + Invalid range or address. +530 <message> + Non existant breakpoint. +531, 532, 533 <message> + Invalid breakpoint address. +*/ + +static int debugger_active = 0, paused = 0, trace = 0, reset = 0, resetting = 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 void ProcessCommands(); + +static u8 *MemoryMap = NULL; + +enum { + MAP_EXEC = 1, + MAP_R8 = 2, + MAP_R16 = 4, + MAP_R32 = 8, + MAP_W8 = 16, + MAP_W16 = 32, + MAP_W32 = 64, + MAP_EXEC_JAL = 128, +}; + +char *breakpoint_type_names[] = { + "E", "R1", "R2", "R4", "W1", "W2", "W4" +}; + +typedef struct breakpoint_s { + struct breakpoint_s *next, *prev; + int number, type; + u32 address; +} breakpoint_t; + +static breakpoint_t *first = NULL; + +int add_breakpoint(int type, u32 address) { + breakpoint_t *bp = (breakpoint_t *)malloc(sizeof(breakpoint_t)); + + bp->type = type; + bp->address = address; + + if (first) { + bp->number = first->prev->number + 1; + bp->next = first; + bp->prev = first->prev; + first->prev = bp; + bp->prev->next = bp; + } else { + first = bp; + bp->number = 1; + bp->next = bp; + bp->prev = bp; + } + + return bp->number; +} + +void delete_breakpoint(breakpoint_t * bp) { + if (bp == first) { + if (bp->next == bp) { + first = NULL; + } else { + first = bp->next; + } + } + + bp->next->prev = bp->prev; + bp->prev->next = bp->next; + + free(bp); +} + +breakpoint_t *next_breakpoint(breakpoint_t *bp) { + return bp->next != first ? bp->next : 0; +} + +breakpoint_t *find_breakpoint(int number) { + breakpoint_t *p; + + for (p = first; p; p = next_breakpoint(p)) { + if (p->number == number) + return p; + } + + return 0; +} + +void StartDebugger() { + if (debugger_active) + return; + + MemoryMap = (u8 *)malloc(0x200000); + if (MemoryMap == NULL) { + SysMessage(_("Error allocating memory")); + return; + } + + if (StartServer() == -1) { + SysPrintf(_("Unable to start debug server.\n")); + return; + } + + SysPrintf(_("Debugger started.\n")); + debugger_active = 1; +} + +void StopDebugger() { + if (!debugger_active) { + StopServer(); + SysPrintf(_("Debugger stopped.\n")); + } + if (MemoryMap != NULL) { + free(MemoryMap); + MemoryMap = NULL; + } + + while (first != NULL) delete_breakpoint(first); + + debugger_active = 0; +} + +void PauseDebugger() { + trace = 0; + paused = 1; +} + +void ResumeDebugger() { + trace = 0; + paused = 0; +} + +void DebugVSync() { + if (!debugger_active || resetting) + return; + + if (reset) { + resetting = 1; + CheckCdrom(); + SysReset(); + if (reset == 2) + LoadCdrom(); + reset = resetting = 0; + return; + } + + GetClient(); + ProcessCommands(); +} + +void MarkMap(u32 address, int mask) { + if ((address & 0xff000000) != 0x80000000) return; + MemoryMap[address & 0x001fffff] |= mask; +} + +int IsMapMarked(u32 address, int mask) { + return (MemoryMap[address & 0x001fffff] & mask) != 0; +} + +void ProcessDebug() { + if (!debugger_active || reset || resetting) + return; + if (trace) { + if (!(--trace)) { + paused = 1; + } + } + if (!paused) { + DebugCheckBP(psxRegs.pc, E); + } + if (mapping_e) { + MarkMap(psxRegs.pc, MAP_EXEC); + if ((psxRegs.code >> 26) == 3) { + MarkMap(_JumpTarget_, MAP_EXEC_JAL); + } + if (((psxRegs.code >> 26) == 0) && ((psxRegs.code && 0x3F) == 9)) { + MarkMap(_Rd_, MAP_EXEC_JAL); + } + } + while (paused) { + GetClient(); + ProcessCommands(); + GPU_updateLace(); + SysUpdate(); + } +} + +static void ProcessCommands() { + int code, i, dumping; + FILE *sfile; + char cmd[257], *arguments, *p, reply[10240], sname[L_tmpnam], *save, *dump; + u32 reg, value, size, address; + breakpoint_t *bp; + + if (!HasClient()) + return; + if (ReadSocket(cmd, 256) > 0) { + arguments = 0; + if (strlen(cmd) <= 2) { + code = 0; + } else if (strlen(cmd) == 3) { + code = strtol(cmd, 0, 16); + } else if (!(isxdigit(cmd[0]) && isxdigit(cmd[1]) && isxdigit(cmd[2]) && (cmd[3] == 0x20))) { + code = 0; + } else if (sscanf(cmd, "%3X ", &code) != 1) { + code = 0; + } else { + arguments = cmd + 4; + } + code = strtol(cmd, &arguments, 16); + while (arguments && *arguments && *arguments == 0x20) + arguments++; + + if (!*arguments) + arguments = 0; + + dumping = 0; + save = 0; + + switch (code) { + case 0x100: + sprintf(reply, "200 %s\r\n", arguments); + break; + case 0x101: + sprintf(reply, "201 %s\r\n", PACKAGE_VERSION); + break; + case 0x102: + sprintf(reply, "202 1.0\r\n"); + break; + case 0x103: + sprintf(reply, "203 %i\r\n", paused ? 1 : trace ? 2 : 0); + break; + case 0x110: + sprintf(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); + break; + } + } + if (!arguments) { + reply[0] = 0; + for (i = 0; i < 32; i++) { + sprintf(reply, "%s211 %02X=%08X\r\n", reply, i, psxRegs.GPR.r[i]); + } + } else { + if ((code >= 0) && (code < 32)) { + sprintf(reply, "211 %02X=%08X\r\n", code, psxRegs.GPR.r[code]); + } else { + sprintf(reply, "511 Invalid GPR register: %X\r\n", code); + } + } + break; + case 0x112: + sprintf(reply, "212 LO=%08X HI=%08X\r\n", psxRegs.GPR.r[33], psxRegs.GPR.r[34]); + break; + case 0x113: + if (arguments) { + if (sscanf(arguments, "%02X", &code) != 1) { + sprintf(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=%08X\r\n", reply, i, psxRegs.CP0.r[i]); + } + } else { + if ((code >= 0) && (code < 32)) { + sprintf(reply, "213 %02X=%08X\r\n", code, psxRegs.CP0.r[code]); + } else { + sprintf(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); + break; + } + } + if (!arguments) { + reply[0] = 0; + for (i = 0; i < 32; i++) { + sprintf(reply, "%s214 %02X=%08X\r\n", reply, i, psxRegs.CP2C.r[i]); + } + } else { + if ((code >= 0) && (code < 32)) { + sprintf(reply, "214 %02X=%08X\r\n", code, psxRegs.CP2C.r[code]); + } else { + sprintf(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); + break; + } + } + if (!arguments) { + reply[0] = 0; + for (i = 0; i < 32; i++) { + sprintf(reply, "%s215 %02X=%08X\r\n", reply, i, psxRegs.CP2D.r[i]); + } + } else { + if ((code >= 0) && (code < 32)) { + sprintf(reply, "215 %02X=%08X\r\n", code, psxRegs.CP2D.r[code]); + } else { + sprintf(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); + break; + } + } + if (!arguments) + code = psxRegs.pc; + + sprintf(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); + break; + } + + if (reg < 32) { + psxRegs.GPR.r[reg] = value; + sprintf(reply, "221 %02X=%08X\r\n", reg, value); + } else { + sprintf(reply, "512 Invalid GPR register: %02X\r\n", reg); + } + break; + case 0x122: + if (!arguments || strncmp(arguments, "HI=", 3) == 0) { + reg = 34; + } else if (arguments && strncmp(arguments, "LO=", 3) == 0) { + reg = 33; + } else { + arguments[2] = 0; + sprintf(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); + } else { + psxRegs.GPR.r[reg] = value; + sprintf(reply, "222 LO=%08X HI=%08X\r\n", psxRegs.GPR.r[33], psxRegs.GPR.r[34]); + } + break; + case 0x123: + if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) { + sprintf(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); + } else { + sprintf(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); + break; + } + + if (reg < 32) { + psxRegs.CP2C.r[reg] = value; + sprintf(reply, "224 %02X=%08X\r\n", reg, value); + } else { + sprintf(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); + break; + } + + if (reg < 32) { + psxRegs.CP2D.r[reg] = value; + sprintf(reply, "225 %02X=%08X\r\n", reg, value); + } else { + sprintf(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); + break; + } + + if ((address >= 0x80000000) && ((address + size) <= 0x80200000)) { + sprintf(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); + } + break; + case 0x140: + if (!arguments || sscanf(arguments, "%08X@%08X", &size, &address) != 2) { + sprintf(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); + } else { + sprintf(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); + break; + } + } + if (code) { + mapping_e = 1; + for (i = 0; i < 0x00200000; i++) { + MemoryMap[i] &= ~MAP_EXEC; + MemoryMap[i] &= ~MAP_EXEC_JAL; + } + } else { + mapping_e = 0; + } + sprintf(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); + break; + } + } + if (code) { + mapping_r8 = 1; + for (i = 0; i < 0x00200000; i++) { + MemoryMap[i] &= ~MAP_R8; + } + } else { + mapping_r8 = 0; + } + sprintf(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); + break; + } + } + if (code) { + mapping_r16 = 1; + for (i = 0; i < 0x00200000; i++) { + MemoryMap[i] &= ~MAP_R16; + } + } else { + mapping_r16 = 0; + } + sprintf(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); + break; + } + } + if (code) { + mapping_r32 = 1; + for (i = 0; i < 0x00200000; i++) { + MemoryMap[i] &= ~MAP_R32; + } + } else { + mapping_r32 = 0; + } + sprintf(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); + break; + } + } + if (code) { + mapping_w8 = 1; + for (i = 0; i < 0x00200000; i++) { + MemoryMap[i] &= ~MAP_W8; + } + } else { + mapping_w8 = 0; + } + sprintf(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); + break; + } + } + if (code) { + mapping_w16 = 1; + for (i = 0; i < 0x00200000; i++) { + MemoryMap[i] &= ~MAP_W16; + } + } else { + mapping_w16 = 0; + } + sprintf(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); + break; + } + } + if (code) { + mapping_w32 = 1; + for (i = 0; i < 0x00200000; i++) { + MemoryMap[i] &= ~MAP_W32; + } + } else { + mapping_w32 = 0; + } + sprintf(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); + break; + } + } + if (code) { + breakmp_e = 1; + } else { + breakmp_e = 0; + } + sprintf(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); + break; + } + } + if (code) { + breakmp_r8 = 1; + } else { + breakmp_r8 = 0; + } + sprintf(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); + break; + } + } + if (code) { + breakmp_r16 = 1; + } else { + breakmp_r16 = 0; + } + sprintf(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); + break; + } + } + if (code) { + breakmp_r32 = 1; + } else { + breakmp_r32 = 0; + } + sprintf(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); + break; + } + } + if (code) { + breakmp_w8 = 1; + } else { + breakmp_w8 = 0; + } + sprintf(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); + break; + } + } + if (code) { + breakmp_w16 = 1; + } else { + breakmp_w16 = 0; + } + sprintf(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); + break; + } + } + if (code) { + breakmp_w32 = 1; + } else { + breakmp_w32 = 0; + } + sprintf(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 <idc.idc>\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); + sfile = fopen("markcode.idc", "wb"); + fprintf(sfile, "#include <idc.idc>\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); + sprintf(reply, "270 flow.idc and markcode.idc dumped\r\n"); + break; + case 0x300: + p = arguments; + if (arguments) { + code = strtol(arguments, &p, 16); + } + 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]); + } + } else { + sprintf(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]); + } else { + sprintf(reply, "530 Invalid breakpoint number: %X\r\n", code); + } + } + break; + case 0x301: + p = arguments; + if (arguments) { + code = strtol(arguments, &p, 16); + } + if (p == arguments) { + while (first != NULL) delete_breakpoint(first); + sprintf(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); + } else { + sprintf(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); + break; + } +// if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) { +// sprintf(reply, "531 Invalid address %08X\r\n", address); +// break; +// } + code = add_breakpoint(E, address); + sprintf(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); + break; + } + if ((address < 0x80000000) || (address >= 0x80200000)) { + sprintf(reply, "532 Invalid address %08X\r\n", address); + break; + } + code = add_breakpoint(R1, address); + sprintf(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); + break; + } + if ((address & 1) || (address < 0x80000000) || (address >= 0x80200000)) { + sprintf(reply, "532 Invalid address %08X\r\n", address); + break; + } + code = add_breakpoint(R2, address); + sprintf(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); + break; + } + if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) { + sprintf(reply, "532 Invalid address %08X\r\n", address); + break; + } + code = add_breakpoint(R4, address); + sprintf(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); + break; + } + if ((address < 0x80000000) || (address >= 0x80200000)) { + sprintf(reply, "533 Invalid address %08X\r\n", address); + break; + } + code = add_breakpoint(W1, address); + sprintf(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); + break; + } + if ((address & 1) || (address < 0x80000000) || (address >= 0x80200000)) { + sprintf(reply, "533 Invalid address %08X\r\n", address); + break; + } + code = add_breakpoint(W2, address); + sprintf(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); + break; + } + if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) { + sprintf(reply, "533 Invalid address %08X\r\n", address); + break; + } + code = add_breakpoint(W4, address); + sprintf(reply, "432 %X\r\n", code); + break; + case 0x390: + paused = 1; + sprintf(reply, "490 Paused\r\n"); + break; + case 0x391: + paused = 0; + sprintf(reply, "491 Resumed\r\n"); + break; + case 0x395: + p = arguments; + if (arguments) { + trace = strtol(arguments, &p, 10); + } + if (p == arguments) { + trace = 1; + } + paused = 0; + sprintf(reply, "495 Tracing\r\n"); + break; + case 0x398: + paused = 0; + trace = 0; + reset = 2; + sprintf(reply, "498 Soft resetting\r\n"); + break; + case 0x399: + paused = 0; + trace = 0; + reset = 1; + sprintf(reply, "499 Resetting\r\n"); + break; + default: + sprintf(reply, "500 Unknown command '%s'\r\n", cmd); + break; + } + WriteSocket(reply, strlen(reply)); + + if (dumping) { + WriteSocket(dump, size); + } + + if (save) { + free(save); + } + } +} + +void DebugCheckBP(u32 address, enum breakpoint_types type) { + breakpoint_t *bp; + char reply[512]; + + 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)); + paused = 1; + return; + } + } + if (breakmp_e && type == E) { + if (!IsMapMarked(address, MAP_EXEC)) { + sprintf(reply, "010 %08X@%08X\r\n", address, psxRegs.pc); + WriteSocket(reply, strlen(reply)); + paused = 1; + } + } + if (breakmp_r8 && type == R1) { + if (!IsMapMarked(address, MAP_R8)) { + sprintf(reply, "011 %08X@%08X\r\n", address, psxRegs.pc); + WriteSocket(reply, strlen(reply)); + paused = 1; + } + } + if (breakmp_r16 && type == R2) { + if (!IsMapMarked(address, MAP_R16)) { + sprintf(reply, "012 %08X@%08X\r\n", address, psxRegs.pc); + WriteSocket(reply, strlen(reply)); + paused = 1; + } + } + if (breakmp_r32 && type == R4) { + if (!IsMapMarked(address, MAP_R32)) { + sprintf(reply, "013 %08X@%08X\r\n", address, psxRegs.pc); + WriteSocket(reply, strlen(reply)); + paused = 1; + } + } + if (breakmp_w8 && type == W1) { + if (!IsMapMarked(address, MAP_W8)) { + sprintf(reply, "014 %08X@%08X\r\n", address, psxRegs.pc); + WriteSocket(reply, strlen(reply)); + paused = 1; + } + } + if (breakmp_w16 && type == W2) { + if (!IsMapMarked(address, MAP_W16)) { + sprintf(reply, "015 %08X@%08X\r\n", address, psxRegs.pc); + WriteSocket(reply, strlen(reply)); + paused = 1; + } + } + if (breakmp_w32 && type == W4) { + if (!IsMapMarked(address, MAP_W32)) { + sprintf(reply, "016 %08X@%08X\r\n", address, psxRegs.pc); + WriteSocket(reply, strlen(reply)); + paused = 1; + } + } + if (mapping_r8 && type == R1) MarkMap(address, MAP_R8); + if (mapping_r16 && type == R2) MarkMap(address, MAP_R16); + if (mapping_r32 && type == R4) MarkMap(address, MAP_R32); + if (mapping_w8 && type == W1) MarkMap(address, MAP_W8); + if (mapping_w16 && type == W2) MarkMap(address, MAP_W16); + if (mapping_w32 && type == W4) MarkMap(address, MAP_W32); + } diff --git a/libpcsxcore/debug.h b/libpcsxcore/debug.h index d61f2ba0..84aa8492 100644 --- a/libpcsxcore/debug.h +++ b/libpcsxcore/debug.h @@ -18,20 +18,35 @@ * 51 Franklin Steet, Fifth Floor, Boston, MA 02111-1307 USA. * ***************************************************************************/ -/* -* Specficies which logs should be activated. -* Ryan TODO: These should ALL be definable with configure flags. -*/ - #ifndef __DEBUG_H__ #define __DEBUG_H__ +enum breakpoint_types { + E, R1, R2, R4, W1, W2, W4 +}; + +void StartDebugger(); +void StopDebugger(); + +void DebugVSync(); +void ProcessDebug(); + +void DebugCheckBP(u32 address, enum breakpoint_types type); + +void PauseDebugger(); +void ResumeDebugger(); + extern char *disRNameCP0[]; char* disR3000AF(u32 code, u32 pc); FILE *emuLog; +/* + * Specficies which logs should be activated. + * Ryan TODO: These should ALL be definable with configure flags. + */ + //#define GTE_DUMP #ifdef GTE_DUMP diff --git a/libpcsxcore/psxcommon.h b/libpcsxcore/psxcommon.h index c3f21ffe..1ccf73fc 100644 --- a/libpcsxcore/psxcommon.h +++ b/libpcsxcore/psxcommon.h @@ -107,7 +107,7 @@ typedef struct { long Cdda; long HLE; long Cpu; - long Dbg; + long Debug; long PsxOut; long SpuIrq; long RCntFix; diff --git a/libpcsxcore/psxcounters.c b/libpcsxcore/psxcounters.c index 0daf3cb8..ef61f9e0 100644 --- a/libpcsxcore/psxcounters.c +++ b/libpcsxcore/psxcounters.c @@ -159,6 +159,7 @@ void psxRcntUpdate() { } psxRcntSet(); + DebugVSync(); } void psxRcntWcount(u32 index, u32 value) { diff --git a/libpcsxcore/psxinterpreter.c b/libpcsxcore/psxinterpreter.c index 2eabc16e..ff5d41b1 100644 --- a/libpcsxcore/psxinterpreter.c +++ b/libpcsxcore/psxinterpreter.c @@ -26,8 +26,6 @@ #include "r3000a.h" #include "gte.h" #include "psxhle.h" -/*FIXME*/ -#include "../gui/hdebug.h" static int branch = 0; static int branch2 = 0; @@ -42,7 +40,6 @@ static u32 branchPC; #endif inline void execI(); -inline void execIDbg(); // Subsets void (*psxBSC[64])(); @@ -773,21 +770,11 @@ static void intExecute() { execI(); } -static void intExecuteDbg() { - for (;;) - execIDbg(); -} - static void intExecuteBlock() { branch2 = 0; while (!branch2) execI(); } -static void intExecuteBlockDbg() { - branch2 = 0; - while (!branch2) execIDbg(); -} - static void intClear(u32 Addr, u32 Size) { } @@ -801,43 +788,14 @@ inline void execI() { debugI(); + if (Config.Debug) ProcessDebug(); + psxRegs.pc += 4; psxRegs.cycle++; psxBSC[psxRegs.code >> 26](); } -/* debugger version */ -inline void execIDbg() { - u32 *code = (u32 *)PSXM(psxRegs.pc); - psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code)); - - // dump opcode when LOG_CPU is enabled - debugI(); - - // normal execution - if (!hdb_pause) { - psxRegs.pc += 4; - psxRegs.cycle++; - psxBSC[psxRegs.code >> 26](); - } - - // trace one instruction - if(hdb_pause == 2) { - psxRegs.pc += 4; - psxRegs.cycle++; - psxBSC[psxRegs.code >> 26](); - hdb_pause = 1; - } - - // wait for breakpoint - if(hdb_pause == 3) { - psxRegs.pc+= 4; psxRegs.cycle++; - psxBSC[psxRegs.code >> 26](); - if(psxRegs.pc == hdb_break) hdb_pause = 1; - } -} - R3000Acpu psxInt = { intInit, intReset, @@ -846,12 +804,3 @@ R3000Acpu psxInt = { intClear, intShutdown }; - -R3000Acpu psxIntDbg = { - intInit, - intReset, - intExecuteDbg, - intExecuteBlockDbg, - intClear, - intShutdown -}; diff --git a/libpcsxcore/psxmem.c b/libpcsxcore/psxmem.c index 8dfc00e6..86ccc121 100644 --- a/libpcsxcore/psxmem.c +++ b/libpcsxcore/psxmem.c @@ -141,6 +141,8 @@ u8 psxMemRead8(u32 mem) { } else { p = (char *)(psxMemRLUT[t]); if (p != NULL) { + if (Config.Debug) + DebugCheckBP((mem & 0xffffff) | 0x80000000, R1); return *(u8 *)(p + (mem & 0xffff)); } else { #ifdef PSXMEM_LOG @@ -164,6 +166,8 @@ u16 psxMemRead16(u32 mem) { } else { p = (char *)(psxMemRLUT[t]); if (p != NULL) { + if (Config.Debug) + DebugCheckBP((mem & 0xffffff) | 0x80000000, R2); return SWAPu16(*(u16 *)(p + (mem & 0xffff))); } else { #ifdef PSXMEM_LOG @@ -187,6 +191,8 @@ u32 psxMemRead32(u32 mem) { } else { p = (char *)(psxMemRLUT[t]); if (p != NULL) { + if (Config.Debug) + DebugCheckBP((mem & 0xffffff) | 0x80000000, R4); return SWAPu32(*(u32 *)(p + (mem & 0xffff))); } else { #ifdef PSXMEM_LOG @@ -210,7 +216,9 @@ void psxMemWrite8(u32 mem, u8 value) { } else { p = (char *)(psxMemWLUT[t]); if (p != NULL) { - *(u8 *)(p + (mem & 0xffff)) = value; + if (Config.Debug) + DebugCheckBP((mem & 0xffffff) | 0x80000000, W1); + *(u8 *)(p + (mem & 0xffff)) = value; #ifdef PSXREC psxCpu->Clear((mem & (~3)), 1); #endif @@ -235,6 +243,8 @@ void psxMemWrite16(u32 mem, u16 value) { } else { p = (char *)(psxMemWLUT[t]); if (p != NULL) { + if (Config.Debug) + DebugCheckBP((mem & 0xffffff) | 0x80000000, W2); *(u16 *)(p + (mem & 0xffff)) = SWAPu16(value); #ifdef PSXREC psxCpu->Clear((mem & (~1)), 1); @@ -261,6 +271,8 @@ void psxMemWrite32(u32 mem, u32 value) { } else { p = (char *)(psxMemWLUT[t]); if (p != NULL) { + if (Config.Debug) + DebugCheckBP((mem & 0xffffff) | 0x80000000, W4); *(u32 *)(p + (mem & 0xffff)) = SWAPu32(value); #ifdef PSXREC psxCpu->Clear(mem, 1); diff --git a/libpcsxcore/r3000a.c b/libpcsxcore/r3000a.c index 6f45a1bb..72d52f37 100644 --- a/libpcsxcore/r3000a.c +++ b/libpcsxcore/r3000a.c @@ -35,12 +35,10 @@ int psxInit() { #ifdef PSXREC if (Config.Cpu) { - if (Config.Dbg) psxCpu = &psxIntDbg; - else psxCpu = &psxInt; + psxCpu = &psxInt; } else psxCpu = &psxRec; #else - if (Config.Dbg) psxCpu = &psxIntDbg; - else psxCpu = &psxInt; + psxCpu = &psxInt; #endif Log = 0; diff --git a/libpcsxcore/r3000a.h b/libpcsxcore/r3000a.h index 56c965fc..aed6ce84 100644 --- a/libpcsxcore/r3000a.h +++ b/libpcsxcore/r3000a.h @@ -37,7 +37,6 @@ typedef struct { R3000Acpu *psxCpu; extern R3000Acpu psxInt; -extern R3000Acpu psxIntDbg; #if (defined(__x86_64__) || defined(__i386__) || defined(__sh__) || defined(__ppc__)) && !defined(NOPSXREC) extern R3000Acpu psxRec; #define PSXREC diff --git a/libpcsxcore/socket.c b/libpcsxcore/socket.c new file mode 100644 index 00000000..5d0cd9f5 --- /dev/null +++ b/libpcsxcore/socket.c @@ -0,0 +1,254 @@ +/* Pcsx - Pc Psx Emulator + * Copyright (C) 1999-2003 Pcsx Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses>. + */ + +#include <stdio.h> +#ifdef _WIN32 +#include <winsock2.h> +#else +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <fcntl.h> +#endif +#include <stdlib.h> + +#include "psxcommon.h" +#include "socket.h" + +static int server_socket = 0; +static int client_socket = 0; + +static char tbuf[513]; +static int ptr = 0; + +#define PORT_NUMBER 12345 + +int StartServer() { + struct hostent * localhostent; + struct in_addr localhostaddr; + struct sockaddr_in localsocketaddr; + +#ifdef _WIN32 + WSADATA wsaData; + + if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) + return -1; +#endif + + server_socket = socket(AF_INET, SOCK_STREAM, 0); + +#ifdef _WIN32 + if (server_socket == INVALID_SOCKET) + return -1; +#else + if (server_socket == -1) + return -1; +#endif + + SetsNonblock(); + + memset((void *)&localhostaddr, 0, sizeof(localhostaddr)); + memset(&localsocketaddr, 0, sizeof(struct sockaddr_in)); + +#ifdef _WIN32 + localhostaddr.S_un.S_addr = htonl(INADDR_ANY); +#else + localhostaddr.s_addr = htonl(INADDR_ANY); +#endif + localsocketaddr.sin_family = AF_INET; + localsocketaddr.sin_addr = localhostaddr; + localsocketaddr.sin_port = htons(PORT_NUMBER); + + if (bind(server_socket, (struct sockaddr *) &localsocketaddr, sizeof(localsocketaddr)) < 0) + return -1; + + if (listen(server_socket, 1) != 0) + return -1; + + return 0; +} + +void StopServer() { +#ifdef _WIN32 + shutdown(server_socket, SD_BOTH); + closesocket(server_socket); + WSACleanup(); +#else + shutdown(server_socket, SHUT_RDWR); + close(server_socket); +#endif +} + +void GetClient() { + int new_socket; + char hello[256]; + + new_socket = accept(server_socket, 0, 0); + +#ifdef _WIN32 + if (new_socket == INVALID_SOCKET) + return; +#else + if (new_socket == -1) + return; +#endif + if (client_socket) + CloseClient(); + client_socket = new_socket; + +#ifndef _WIN32 + { + int flags; + flags = fcntl(client_socket, F_GETFL, 0); + fcntl(client_socket, F_SETFL, flags | O_NONBLOCK); + } +#endif + + sprintf(hello, "000 PCSX Version %s - Debug console\r\n", PACKAGE_VERSION); + WriteSocket(hello, strlen(hello)); + ptr = 0; +} + +void CloseClient() { + if (client_socket) { +#ifdef _WIN32 + shutdown(client_socket, SD_BOTH); + closesocket(client_socket); +#else + shutdown(client_socket, SHUT_RDWR); + close(client_socket); +#endif + client_socket = 0; + } +} + +int HasClient() { + return client_socket ? 1 : 0; +} + +int ReadSocket(char * buffer, int len) { + int r; + char * endl; + + if (!client_socket) + return -1; + + r = recv(client_socket, tbuf + ptr, 512 - ptr, 0); + + if (r == 0) { + client_socket = 0; + if (!ptr) + return 0; + } +#ifdef _WIN32 + if (r == SOCKET_ERROR) +#else + if (r == -1) +#endif + { + if (ptr == 0) + return -1; + r = 0; + } + ptr += r; + tbuf[ptr] = 0; + + endl = strstr(tbuf, "\r\n"); + + if (endl) { + r = endl - tbuf; + strncpy(buffer, tbuf, r); + + r += 2; + memmove(tbuf, tbuf + r, 512 - r); + ptr -= r; + memset(tbuf + r, 0, 512 - r); + r -= 2; + + } else { + r = 0; + } + + buffer[r] = 0; + + return r; +} + +int RawReadSocket(char * buffer, int len) { + int r; + int mlen = len < ptr ? len : ptr; + + if (!client_socket) + return -1; + + if (ptr) { + memcpy(buffer, tbuf, mlen); + ptr -= mlen; + memmove(tbuf, tbuf + mlen, 512 - mlen); + } + + if (len - mlen) + r = recv(client_socket, buffer + mlen, len - mlen, 0); + + if (r == 0) { + client_socket = 0; + if (!ptr) + return 0; + } +#ifdef _WIN32 + if (r == SOCKET_ERROR) +#else + if (r == -1) +#endif + { + if (ptr == 0) + return -1; + r = 0; + } + + r += mlen; + + return r; +} + +void WriteSocket(char * buffer, int len) { + if (!client_socket) + return; + + send(client_socket, buffer, len, 0); +} + +void SetsBlock() { +#ifdef _WIN32 + u_long b = 0; + ioctlsocket(server_socket, FIONBIO, &b); +#else + int flags = fcntl(server_socket, F_GETFL, 0); + fcntl(server_socket, F_SETFL, flags & ~O_NONBLOCK); +#endif +} + +void SetsNonblock() { +#ifdef _WIN32 + u_long b = 1; + ioctlsocket(server_socket, FIONBIO, &b); +#else + int flags = fcntl(server_socket, F_GETFL, 0); + fcntl(server_socket, F_SETFL, flags | O_NONBLOCK); +#endif +} diff --git a/libpcsxcore/socket.h b/libpcsxcore/socket.h new file mode 100644 index 00000000..bb0a978d --- /dev/null +++ b/libpcsxcore/socket.h @@ -0,0 +1,36 @@ +/* Pcsx - Pc Psx Emulator + * Copyright (C) 1999-2003 Pcsx Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses>. + */ + +#ifndef __SOCKET_H__ +#define __SOCKET_H__ + +int StartServer(); +void StopServer(); + +void GetClient(); +void CloseClient(); + +int HasClient(); + +int ReadSocket(char * buffer, int len); +int RawReadSocket(char * buffer, int len); +void WriteSocket(char * buffer, int len); + +void SetsBlock(); +void SetsNonblock(); + +#endif |
