1 /* Pcsx - Pc Psx Emulator
2 * Copyright (C) 1999-2003 Pcsx Team
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses>.
18 #include "psxcommon.h"
23 // XXX: don't care but maybe fix it someday
24 #if defined(__GNUC__) && __GNUC__ >= 7
25 #pragma GCC diagnostic ignored "-Wrestrict"
29 PCSX Debug console protocol description, version 1.0
30 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
32 Commands number are formatted using %03X (yes)
33 Registers number are formatted using %02X.
34 Breakpoints numbers are formatted using %X
35 All other values are formatted using %08X, unless specified.
43 Sends a dumb message. Will be replied with a 200 reply, followed by the message.
47 Gets protocol version.
53 Gets GP register, or all, if no argument.
57 Gets COP0 register, or all, if no argument.
59 Gets COP2 control register, or all, if no argument.
61 Gets COP2 data register, or all, if no argument.
63 Disassemble current PC, or given PC.
65 Sets a GP register. Will return a 221 message.
67 Sets LO or HI register. Will return a 222 message.
69 Sets a COP0 register. Will return a 223 message.
71 Sets a COP2 control register. Will return a 224 message.
73 Sets a COP2 data register. Will return a 225 message.
75 Dumps a range of memory, of size bytes starting at addr.
77 Sets a range of memory, of size bytes starting at addr.
78 Will have to send immediately exactly size bytes afterward.
80 Starts/reset mapping execution flow, or stop it if number = 0
82 Starts/reset mapping read8 flow, or stop it if number = 0
84 Starts/reset mapping read16 flow, or stop it if number = 0
86 Starts/reset mapping read32 flow, or stop it if number = 0
88 Starts/reset mapping write8 flow, or stop it if number = 0
90 Starts/reset mapping write16 flow, or stop it if number = 0
92 Starts/reset mapping write32 flow, or stop it if number = 0
94 Breaks on map exec flow, or stop it if number = 0
96 Breaks on map read8 flow, or stop it if number = 0
98 Breaks on map read16 flow, or stop it if number = 0
100 Breaks on map read32 flow, or stop it if number = 0
102 Breaks on map write8 flow, or stop it if number = 0
104 Breaks on map write16 flow, or stop it if number = 0
106 Breaks on map write32 flow, or stop it if number = 0
108 Dumps the execution flow map in an IDC file
110 Execution flow control commands (3xx):
111 -------------------------------------
113 Get a list of the actual breakpoints. Will get '400' answers.
115 Deletes a breakpoint, or all, if no arguments.
117 Sets an exec breakpoint.
119 Sets a read breakpoint, 1 byte / 8 bits.
121 Sets a read breakpoint, 2 bytes / 16 bits, has to be on an even address.
123 Sets a read breakpoint, 4 bytes / 32 bits, address has to be 4-bytes aligned.
125 Sets a write breakpoint, 1 byte / 8 bits.
127 Sets a write breakpoint, 2 bytes / 16 bits, has to be on an even address.
129 Sets a write breakpoint, 4 bytes / 32 bits, address has to be 4-bytes aligned.
131 Pauses execution. Equivalents to a breakpoint.
135 Traces execution, 1 instruction by default. Formatted using %i
144 Spontaneous messages (0xx):
145 --------------------------
148 010 / 011 / 012 / 013 / 014 / 015 / 016
149 Execution hit mapping flow automatic breakpoint.
151 Execution hit breakpoint, PCSX is paused. Displays PC's value.
153 Basic commands acknowledge (2xx):
154 --------------------------------
156 Sends a dumb message.
158 Returns PCSX version.
160 Returns protocol version.
162 status = 0: running; = 1: paused; = 2: trace
164 Displays current PC value.
166 Displays one GP register value.
167 212 LO=<value> HI=<value>
168 Displays LO/HI registers.
170 Displays one COP0 register value.
172 Displays one COP2 control register value.
174 Displays one COP2 data register value.
176 Displays one line of disassembled code.
178 Displays one GP register value, ack for modification.
179 222 LO=<value> HI=<value>
180 Displays LO/HI registers, ack for modification.
182 Displays one COP0 register value, ack for modification.
184 Displays one COP2 control register value, ack for modification.
186 Displays one COP2 data register value, ack for modification.
188 Dumping memory. Will then raw outputs size bytes.
190 Memory set acknowledge.
191 250 / 251 / 252 / 253 / 254 / 255 / 256
192 Acknolwedge of 15x commands.
193 260 / 261 / 262 / 263 / 264 / 265 / 266
194 Acknolwedge of 16x commands.
196 Acknolwedge of 170 command.
198 Execution flow control commands acknowledge (4xx):
199 -------------------------------------------------
200 400 <number>@<address>-<type>
201 Displays a breakpoint, where 'type' can be of E, R1, R2, R4, W1, W2 or W4.
203 Breakpoint deleting acknowledge.
204 410, 420, 421, 422, 430, 431, 432 <number>
205 Breakpoint adding acknowledge. Returns the number of the added breakpoint.
217 Error messages (5xx):
220 Command not understood.
222 Invalid GPR register.
224 Invalid LO/HI register.
226 Invalid range or address.
228 Non existant breakpoint.
229 531, 532, 533 <message>
230 Invalid breakpoint address.
233 static int debugger_active = 0, paused = 0, trace = 0, reset = 0, resetting = 0;
234 static int mapping_e = 0, mapping_r8 = 0, mapping_r16 = 0, mapping_r32 = 0, mapping_w8 = 0, mapping_w16 = 0, mapping_w32 = 0;
235 static int breakmp_e = 0, breakmp_r8 = 0, breakmp_r16 = 0, breakmp_r32 = 0, breakmp_w8 = 0, breakmp_w16 = 0, breakmp_w32 = 0;
237 static void ProcessCommands();
239 static u8 *MemoryMap = NULL;
252 char *breakpoint_type_names[] = {
253 "E", "R1", "R2", "R4", "W1", "W2", "W4"
256 typedef struct breakpoint_s {
257 struct breakpoint_s *next, *prev;
262 static breakpoint_t *first = NULL;
264 int add_breakpoint(int type, u32 address) {
265 breakpoint_t *bp = (breakpoint_t *)malloc(sizeof(breakpoint_t));
268 bp->address = address;
271 bp->number = first->prev->number + 1;
273 bp->prev = first->prev;
286 void delete_breakpoint(breakpoint_t * bp) {
288 if (bp->next == bp) {
295 bp->next->prev = bp->prev;
296 bp->prev->next = bp->next;
301 breakpoint_t *next_breakpoint(breakpoint_t *bp) {
302 return bp->next != first ? bp->next : 0;
305 breakpoint_t *find_breakpoint(int number) {
308 for (p = first; p; p = next_breakpoint(p)) {
309 if (p->number == number)
316 void StartDebugger() {
320 MemoryMap = (u8 *)malloc(0x200000);
321 if (MemoryMap == NULL) {
322 SysMessage(_("Error allocating memory"));
326 if (StartServer() == -1) {
327 SysPrintf(_("Unable to start debug server.\n"));
331 SysPrintf(_("Debugger started.\n"));
335 void StopDebugger() {
336 if (debugger_active) {
338 SysPrintf(_("Debugger stopped.\n"));
341 if (MemoryMap != NULL) {
346 while (first != NULL) delete_breakpoint(first);
351 void PauseDebugger() {
356 void ResumeDebugger() {
362 if (!debugger_active || resetting)
371 reset = resetting = 0;
379 void MarkMap(u32 address, int mask) {
380 if ((address & 0xff000000) != 0x80000000) return;
381 MemoryMap[address & 0x001fffff] |= mask;
384 int IsMapMarked(u32 address, int mask) {
385 return (MemoryMap[address & 0x001fffff] & mask) != 0;
388 void ProcessDebug() {
389 if (!debugger_active || reset || resetting)
397 DebugCheckBP(psxRegs.pc, E);
400 MarkMap(psxRegs.pc, MAP_EXEC);
401 if ((psxRegs.code >> 26) == 3) {
402 MarkMap(_JumpTarget_, MAP_EXEC_JAL);
404 if (((psxRegs.code >> 26) == 0) && ((psxRegs.code & 0x3F) == 9)) {
405 MarkMap(_Rd_, MAP_EXEC_JAL);
415 static void ProcessCommands() {
416 int code, i, dumping;
418 char cmd[257], *arguments, *p, reply[10240], *save, *dump;
419 u32 reg, value, size, address;
424 if (ReadSocket(cmd, 256) > 0) {
426 if (strlen(cmd) <= 2) {
428 } else if (strlen(cmd) == 3) {
429 code = strtol(cmd, 0, 16);
430 } else if (!(isxdigit(cmd[0]) && isxdigit(cmd[1]) && isxdigit(cmd[2]) && (cmd[3] == 0x20))) {
432 } else if (sscanf(cmd, "%3X ", &code) != 1) {
437 code = strtol(cmd, &arguments, 16);
438 while (arguments && *arguments && *arguments == 0x20)
441 if (*arguments == '\0')
449 sprintf(reply, "200 %s\r\n", arguments == NULL ? "OK" : arguments);
452 sprintf(reply, "201 %s\r\n", PCSX_VERSION);
455 sprintf(reply, "202 1.0\r\n");
458 sprintf(reply, "203 %i\r\n", paused ? 1 : trace ? 2 : 0);
461 sprintf(reply, "210 PC=%08X\r\n", psxRegs.pc);
465 if (sscanf(arguments, "%02X", &code) != 1) {
466 sprintf(reply, "511 Malformed 111 command '%s'\r\n", cmd);
472 for (i = 0; i < 32; i++) {
473 sprintf(reply, "%s211 %02X=%08X\r\n", reply, i, psxRegs.GPR.r[i]);
476 if ((code >= 0) && (code < 32)) {
477 sprintf(reply, "211 %02X=%08X\r\n", code, psxRegs.GPR.r[code]);
479 sprintf(reply, "511 Invalid GPR register: %X\r\n", code);
484 sprintf(reply, "212 LO=%08X HI=%08X\r\n", psxRegs.GPR.n.lo, psxRegs.GPR.n.hi);
488 if (sscanf(arguments, "%02X", &code) != 1) {
489 sprintf(reply, "511 Malformed 113 command '%s'\r\n", cmd);
495 for (i = 0; i < 32; i++) {
496 sprintf(reply, "%s213 %02X=%08X\r\n", reply, i, psxRegs.CP0.r[i]);
499 if ((code >= 0) && (code < 32)) {
500 sprintf(reply, "213 %02X=%08X\r\n", code, psxRegs.CP0.r[code]);
502 sprintf(reply, "511 Invalid COP0 register: %X\r\n", code);
508 if (sscanf(arguments, "%02X", &code) != 1) {
509 sprintf(reply, "511 Malformed 114 command '%s'\r\n", cmd);
515 for (i = 0; i < 32; i++) {
516 sprintf(reply, "%s214 %02X=%08X\r\n", reply, i, psxRegs.CP2C.r[i]);
519 if ((code >= 0) && (code < 32)) {
520 sprintf(reply, "214 %02X=%08X\r\n", code, psxRegs.CP2C.r[code]);
522 sprintf(reply, "511 Invalid COP2C register: %X\r\n", code);
528 if (sscanf(arguments, "%02X", &code) != 1) {
529 sprintf(reply, "511 Malformed 111 command '%s'\r\n", cmd);
535 for (i = 0; i < 32; i++) {
536 sprintf(reply, "%s215 %02X=%08X\r\n", reply, i, psxRegs.CP2D.r[i]);
539 if ((code >= 0) && (code < 32)) {
540 sprintf(reply, "215 %02X=%08X\r\n", code, psxRegs.CP2D.r[code]);
542 sprintf(reply, "511 Invalid COP2D register: %X\r\n", code);
548 if (sscanf(arguments, "%08X", &code) != 1) {
549 sprintf(reply, "511 Malformed 119 command '%s'\r\n", cmd);
556 sprintf(reply, "219 %s\r\n", disR3000AF(psxMemRead32(code), code));
559 if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) {
560 sprintf(reply, "500 Malformed 121 command '%s'\r\n", arguments);
565 psxRegs.GPR.r[reg] = value;
566 sprintf(reply, "221 %02X=%08X\r\n", reg, value);
568 sprintf(reply, "512 Invalid GPR register: %02X\r\n", reg);
572 if (!arguments || strncmp(arguments, "HI=", 3) == 0) {
574 } else if (arguments && strncmp(arguments, "LO=", 3) == 0) {
578 sprintf(reply, "512 Invalid LO/HI register: '%s'\r\n", arguments);
582 if (sscanf(arguments + 3, "%08X", &value) != 1) {
583 sprintf(reply, "500 Malformed 122 command '%s'\r\n", arguments);
585 psxRegs.GPR.r[reg] = value;
586 sprintf(reply, "222 LO=%08X HI=%08X\r\n", psxRegs.GPR.n.lo, psxRegs.GPR.n.hi);
590 if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) {
591 sprintf(reply, "500 Malformed 123 command '%s'\r\n", arguments);
596 psxRegs.CP0.r[reg] = value;
597 sprintf(reply, "223 %02X=%08X\r\n", reg, value);
599 sprintf(reply, "512 Invalid COP0 register: %02X\r\n", reg);
603 if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) {
604 sprintf(reply, "500 Malformed 124 command '%s'\r\n", arguments);
609 psxRegs.CP2C.r[reg] = value;
610 sprintf(reply, "224 %02X=%08X\r\n", reg, value);
612 sprintf(reply, "512 Invalid COP2C register: %02X\r\n", reg);
616 if (!arguments || sscanf(arguments, "%02X=%08X", ®, &value) != 2) {
617 sprintf(reply, "500 Malformed 121 command '%s'\r\n", arguments);
622 psxRegs.CP2D.r[reg] = value;
623 sprintf(reply, "225 %02X=%08X\r\n", reg, value);
625 sprintf(reply, "512 Invalid COP2D register: %02X\r\n", reg);
629 if (!arguments || sscanf(arguments, "%08X@%08X", &size, &address) != 2) {
630 sprintf(reply, "500 Malformed 130 command '%s'\r\n", arguments);
634 if ((address >= 0x80000000) && ((address + size) <= 0x80200000)) {
635 sprintf(reply, "230 %08X@%08X\r\n", size, address);
636 dump = (char *) PSXM(address);
639 sprintf(reply, "513 Invalid address or range: '%s'\r\n", arguments);
643 if (!arguments || sscanf(arguments, "%08X@%08X", &size, &address) != 2) {
644 sprintf(reply, "500 Malformed 140 command '%s'\r\n", arguments);
648 if ((address >= 0x80000000) && ((address + size) <= 0x80200000)) {
649 sprintf(reply, "240 %08X@%08X\r\n", size, address);
650 RawReadSocket((char *)PSXM(address), size);
652 sprintf(reply, "514 Invalid address or range: '%s'\r\n", arguments);
658 if (sscanf(arguments, "%02X", &code) != 1) {
659 sprintf(reply, "500 Malformed 150 command '%s'\r\n", cmd);
665 for (i = 0; i < 0x00200000; i++) {
666 MemoryMap[i] &= ~MAP_EXEC;
667 MemoryMap[i] &= ~MAP_EXEC_JAL;
672 sprintf(reply, "250 Mapping of exec flow %s\r\n", code ? "started" : "stopped");
677 if (sscanf(arguments, "%02X", &code) != 1) {
678 sprintf(reply, "500 Malformed 151 command '%s'\r\n", cmd);
684 for (i = 0; i < 0x00200000; i++) {
685 MemoryMap[i] &= ~MAP_R8;
690 sprintf(reply, "251 Mapping of read8 flow %s\r\n", code ? "started" : "stopped");
695 if (sscanf(arguments, "%02X", &code) != 1) {
696 sprintf(reply, "500 Malformed 152 command '%s'\r\n", cmd);
702 for (i = 0; i < 0x00200000; i++) {
703 MemoryMap[i] &= ~MAP_R16;
708 sprintf(reply, "252 Mapping of read16 flow %s\r\n", code ? "started" : "stopped");
713 if (sscanf(arguments, "%02X", &code) != 1) {
714 sprintf(reply, "500 Malformed 153 command '%s'\r\n", cmd);
720 for (i = 0; i < 0x00200000; i++) {
721 MemoryMap[i] &= ~MAP_R32;
726 sprintf(reply, "253 Mapping of read32 flow %s\r\n", code ? "started" : "stopped");
731 if (sscanf(arguments, "%02X", &code) != 1) {
732 sprintf(reply, "500 Malformed 154 command '%s'\r\n", cmd);
738 for (i = 0; i < 0x00200000; i++) {
739 MemoryMap[i] &= ~MAP_W8;
744 sprintf(reply, "254 Mapping of write8 flow %s\r\n", code ? "started" : "stopped");
749 if (sscanf(arguments, "%02X", &code) != 1) {
750 sprintf(reply, "500 Malformed 155 command '%s'\r\n", cmd);
756 for (i = 0; i < 0x00200000; i++) {
757 MemoryMap[i] &= ~MAP_W16;
762 sprintf(reply, "255 Mapping of write16 flow %s\r\n", code ? "started" : "stopped");
767 if (sscanf(arguments, "%02X", &code) != 1) {
768 sprintf(reply, "500 Malformed 156 command '%s'\r\n", cmd);
774 for (i = 0; i < 0x00200000; i++) {
775 MemoryMap[i] &= ~MAP_W32;
780 sprintf(reply, "256 Mapping of write32 flow %s\r\n", code ? "started" : "stopped");
785 if (sscanf(arguments, "%02X", &code) != 1) {
786 sprintf(reply, "500 Malformed 160 command '%s'\r\n", cmd);
795 sprintf(reply, "260 Break on map of exec flow %s\r\n", code ? "started" : "stopped");
800 if (sscanf(arguments, "%02X", &code) != 1) {
801 sprintf(reply, "500 Malformed 161 command '%s'\r\n", cmd);
810 sprintf(reply, "261 Break on map of read8 flow %s\r\n", code ? "started" : "stopped");
815 if (sscanf(arguments, "%02X", &code) != 1) {
816 sprintf(reply, "500 Malformed 162 command '%s'\r\n", cmd);
825 sprintf(reply, "262 Break on map of read16 flow %s\r\n", code ? "started" : "stopped");
830 if (sscanf(arguments, "%02X", &code) != 1) {
831 sprintf(reply, "500 Malformed 163 command '%s'\r\n", cmd);
840 sprintf(reply, "263 Break on map of read32 flow %s\r\n", code ? "started" : "stopped");
845 if (sscanf(arguments, "%02X", &code) != 1) {
846 sprintf(reply, "500 Malformed 164 command '%s'\r\n", cmd);
855 sprintf(reply, "264 Break on map of write8 flow %s\r\n", code ? "started" : "stopped");
860 if (sscanf(arguments, "%02X", &code) != 1) {
861 sprintf(reply, "500 Malformed 165 command '%s'\r\n", cmd);
870 sprintf(reply, "265 Break on map of write16 flow %s\r\n", code ? "started" : "stopped");
875 if (sscanf(arguments, "%02X", &code) != 1) {
876 sprintf(reply, "500 Malformed 166 command '%s'\r\n", cmd);
885 sprintf(reply, "266 Break on map of write32 flow %s\r\n", code ? "started" : "stopped");
888 sfile = fopen("flow.idc", "wb");
889 fprintf(sfile, "#include <idc.idc>\r\n\r\n");
890 fprintf(sfile, "static main(void) {\r\n");
891 for (i = 0; i < 0x00200000; i++) {
892 if (IsMapMarked(i, MAP_EXEC_JAL)) {
893 fprintf(sfile, "\tMakeFunction(0X8%07X,BADADDR);\r\n", i);
896 fprintf(sfile, "}\r\n");
898 sfile = fopen("markcode.idc", "wb");
899 fprintf(sfile, "#include <idc.idc>\r\n\r\n");
900 fprintf(sfile, "static main(void) {\r\n");
901 for (i = 0; i < 0x00200000; i++) {
902 if (IsMapMarked(i, MAP_EXEC)) {
903 fprintf(sfile, "\tMakeCode(0X8%07X);\r\n", i);
906 fprintf(sfile, "}\r\n");
908 sprintf(reply, "270 flow.idc and markcode.idc dumped\r\n");
913 code = strtol(arguments, &p, 16);
915 if (p == arguments) {
918 for (bp = first; bp; bp = next_breakpoint(bp)) {
919 sprintf(reply, "%s400 %X@%08X-%s\r\n", reply, bp->number, bp->address, breakpoint_type_names[bp->type]);
922 sprintf(reply, "530 No breakpoint\r\n");
925 if ((bp = find_breakpoint(code))) {
926 sprintf(reply, "400 %X@%08X-%s\r\n", bp->number, bp->address, breakpoint_type_names[bp->type]);
928 sprintf(reply, "530 Invalid breakpoint number: %X\r\n", code);
935 code = strtol(arguments, &p, 16);
937 if (p == arguments) {
938 while (first != NULL) delete_breakpoint(first);
939 sprintf(reply, "401 All breakpoints deleted.\r\n");
941 if ((bp = find_breakpoint(code))) {
942 delete_breakpoint(bp);
943 sprintf(reply, "401 Breakpoint %X deleted.\r\n", code);
945 sprintf(reply, "530 Invalid breakpoint number: %X\r\n", code);
950 if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
951 sprintf(reply, "500 Malformed 310 command '%s'\r\n", arguments);
954 // if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) {
955 // sprintf(reply, "531 Invalid address %08X\r\n", address);
958 code = add_breakpoint(E, address);
959 sprintf(reply, "410 %X\r\n", code);
962 if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
963 sprintf(reply, "500 Malformed 320 command '%s'\r\n", arguments);
966 if ((address < 0x80000000) || (address >= 0x80200000)) {
967 sprintf(reply, "532 Invalid address %08X\r\n", address);
970 code = add_breakpoint(R1, address);
971 sprintf(reply, "420 %X\r\n", code);
974 if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
975 sprintf(reply, "500 Malformed 321 command '%s'\r\n", arguments);
978 if ((address & 1) || (address < 0x80000000) || (address >= 0x80200000)) {
979 sprintf(reply, "532 Invalid address %08X\r\n", address);
982 code = add_breakpoint(R2, address);
983 sprintf(reply, "421 %X\r\n", code);
986 if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
987 sprintf(reply, "500 Malformed 322 command '%s'\r\n", arguments);
990 if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) {
991 sprintf(reply, "532 Invalid address %08X\r\n", address);
994 code = add_breakpoint(R4, address);
995 sprintf(reply, "422 %X\r\n", code);
998 if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
999 sprintf(reply, "500 Malformed 330 command '%s'\r\n", arguments);
1002 if ((address < 0x80000000) || (address >= 0x80200000)) {
1003 sprintf(reply, "533 Invalid address %08X\r\n", address);
1006 code = add_breakpoint(W1, address);
1007 sprintf(reply, "430 %X\r\n", code);
1010 if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
1011 sprintf(reply, "500 Malformed 331 command '%s'\r\n", arguments);
1014 if ((address & 1) || (address < 0x80000000) || (address >= 0x80200000)) {
1015 sprintf(reply, "533 Invalid address %08X\r\n", address);
1018 code = add_breakpoint(W2, address);
1019 sprintf(reply, "431 %X\r\n", code);
1022 if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
1023 sprintf(reply, "500 Malformed 332 command '%s'\r\n", arguments);
1026 if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) {
1027 sprintf(reply, "533 Invalid address %08X\r\n", address);
1030 code = add_breakpoint(W4, address);
1031 sprintf(reply, "432 %X\r\n", code);
1035 sprintf(reply, "490 Paused\r\n");
1039 sprintf(reply, "491 Resumed\r\n");
1044 trace = strtol(arguments, &p, 10);
1046 if (p == arguments) {
1050 sprintf(reply, "495 Tracing\r\n");
1056 sprintf(reply, "498 Soft resetting\r\n");
1062 sprintf(reply, "499 Resetting\r\n");
1065 sprintf(reply, "500 Unknown command '%s'\r\n", cmd);
1068 WriteSocket(reply, strlen(reply));
1071 WriteSocket(dump, size);
1080 void DebugCheckBP(u32 address, enum breakpoint_types type) {
1084 if (!debugger_active || reset)
1086 for (bp = first; bp; bp = next_breakpoint(bp)) {
1087 if ((bp->type == type) && (bp->address == address)) {
1088 sprintf(reply, "030 %X@%08X\r\n", bp->number, psxRegs.pc);
1089 WriteSocket(reply, strlen(reply));
1094 if (breakmp_e && type == E) {
1095 if (!IsMapMarked(address, MAP_EXEC)) {
1096 sprintf(reply, "010 %08X@%08X\r\n", address, psxRegs.pc);
1097 WriteSocket(reply, strlen(reply));
1101 if (breakmp_r8 && type == R1) {
1102 if (!IsMapMarked(address, MAP_R8)) {
1103 sprintf(reply, "011 %08X@%08X\r\n", address, psxRegs.pc);
1104 WriteSocket(reply, strlen(reply));
1108 if (breakmp_r16 && type == R2) {
1109 if (!IsMapMarked(address, MAP_R16)) {
1110 sprintf(reply, "012 %08X@%08X\r\n", address, psxRegs.pc);
1111 WriteSocket(reply, strlen(reply));
1115 if (breakmp_r32 && type == R4) {
1116 if (!IsMapMarked(address, MAP_R32)) {
1117 sprintf(reply, "013 %08X@%08X\r\n", address, psxRegs.pc);
1118 WriteSocket(reply, strlen(reply));
1122 if (breakmp_w8 && type == W1) {
1123 if (!IsMapMarked(address, MAP_W8)) {
1124 sprintf(reply, "014 %08X@%08X\r\n", address, psxRegs.pc);
1125 WriteSocket(reply, strlen(reply));
1129 if (breakmp_w16 && type == W2) {
1130 if (!IsMapMarked(address, MAP_W16)) {
1131 sprintf(reply, "015 %08X@%08X\r\n", address, psxRegs.pc);
1132 WriteSocket(reply, strlen(reply));
1136 if (breakmp_w32 && type == W4) {
1137 if (!IsMapMarked(address, MAP_W32)) {
1138 sprintf(reply, "016 %08X@%08X\r\n", address, psxRegs.pc);
1139 WriteSocket(reply, strlen(reply));
1143 if (mapping_r8 && type == R1) MarkMap(address, MAP_R8);
1144 if (mapping_r16 && type == R2) MarkMap(address, MAP_R16);
1145 if (mapping_r32 && type == R4) MarkMap(address, MAP_R32);
1146 if (mapping_w8 && type == W1) MarkMap(address, MAP_W8);
1147 if (mapping_w16 && type == W2) MarkMap(address, MAP_W16);
1148 if (mapping_w32 && type == W4) MarkMap(address, MAP_W32);