cdrom: change pause timing again
[pcsx_rearmed.git] / libpcsxcore / debug.c
1 /*  Pcsx - Pc Psx Emulator
2  *  Copyright (C) 1999-2003  Pcsx Team
3  *
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.
8  *
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.
13  *
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>.
16  */
17
18 #include "psxcommon.h"
19 #include "r3000a.h"
20 #include "debug.h"
21 #include "socket.h"
22
23 // XXX: don't care but maybe fix it someday
24 #if defined(__GNUC__) && __GNUC__ >= 7
25 #pragma GCC diagnostic ignored "-Wrestrict"
26 #endif
27
28 /*
29 PCSX Debug console protocol description, version 1.0
30 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
31
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.
36
37
38 Client inputs:
39 ~~~~~~~~~~~~~
40 Basic commands (1xx):
41 --------------------
42 100 <message>
43     Sends a dumb message. Will be replied with a 200 reply, followed by the message.
44 101
45     Gets PCSX version.
46 102
47     Gets protocol version.
48 103
49     Gets status
50 110
51     Gets PC.
52 111 [reg]
53     Gets GP register, or all, if no argument.
54 112
55     Gets LO/HI registers.
56 113 [reg]
57     Gets COP0 register, or all, if no argument.
58 114 [reg]
59     Gets COP2 control register, or all, if no argument.
60 115 [reg]
61     Gets COP2 data register, or all, if no argument.
62 119 [pc]
63     Disassemble current PC, or given PC.
64 121 <reg>=<value>
65     Sets a GP register. Will return a 221 message.
66 122 <LO|HI>=<value>
67     Sets LO or HI register. Will return a 222 message.
68 123 <reg>=<value>
69     Sets a COP0 register. Will return a 223 message.
70 124 <reg>=<value>
71     Sets a COP2 control register. Will return a 224 message.
72 125 <reg>=<value>
73     Sets a COP2 data register. Will return a 225 message.
74 130 <size>@<addr>
75     Dumps a range of memory, of size bytes starting at addr.
76 140 <size>@<addr>
77     Sets a range of memory, of size bytes starting at addr.
78     Will have to send immediately exactly size bytes afterward.
79 150 [number]
80     Starts/reset mapping execution flow, or stop it if number = 0
81 151 [number]
82     Starts/reset mapping read8 flow, or stop it if number = 0
83 152 [number]
84     Starts/reset mapping read16 flow, or stop it if number = 0
85 153 [number]
86     Starts/reset mapping read32 flow, or stop it if number = 0
87 154 [number]
88     Starts/reset mapping write8 flow, or stop it if number = 0
89 155 [number]
90     Starts/reset mapping write16 flow, or stop it if number = 0
91 156 [number]
92     Starts/reset mapping write32 flow, or stop it if number = 0
93 160 [number]
94     Breaks on map exec flow, or stop it if number = 0
95 161 [number]
96     Breaks on map read8 flow, or stop it if number = 0
97 162 [number]
98     Breaks on map read16 flow, or stop it if number = 0
99 163 [number]
100     Breaks on map read32 flow, or stop it if number = 0
101 164 [number]
102     Breaks on map write8 flow, or stop it if number = 0
103 165 [number]
104     Breaks on map write16 flow, or stop it if number = 0
105 166 [number]
106     Breaks on map write32 flow, or stop it if number = 0
107 170
108     Dumps the execution flow map in an IDC file
109
110 Execution flow control commands (3xx):
111 -------------------------------------
112 300 [number]
113     Get a list of the actual breakpoints. Will get '400' answers.
114 301 [number]
115     Deletes a breakpoint, or all, if no arguments.
116 310 <address>
117     Sets an exec breakpoint.
118 320 <address>
119     Sets a read breakpoint, 1 byte / 8 bits.
120 321 <address>
121     Sets a read breakpoint, 2 bytes / 16 bits, has to be on an even address.
122 322 <address>
123     Sets a read breakpoint, 4 bytes / 32 bits, address has to be 4-bytes aligned.
124 330 <address>
125     Sets a write breakpoint, 1 byte / 8 bits.
126 331 <address>
127     Sets a write breakpoint, 2 bytes / 16 bits, has to be on an even address.
128 332 <address>
129     Sets a write breakpoint, 4 bytes / 32 bits, address has to be 4-bytes aligned.
130 390
131     Pauses execution. Equivalents to a breakpoint.
132 391
133     Restarts execution.
134 395 [number]
135     Traces execution, 1 instruction by default. Formatted using %i
136 398
137     Soft (quick) resets.
138 399
139     Resets.
140     
141
142 Server outputs:
143 ~~~~~~~~~~~~~~
144 Spontaneous messages (0xx):
145 --------------------------
146 000 <message>
147     Greeting banner.
148 010 / 011 / 012 / 013 / 014 / 015 / 016
149     Execution hit mapping flow automatic breakpoint.
150 030 <number>@<PC>
151     Execution hit breakpoint, PCSX is paused. Displays PC's value.
152
153 Basic commands acknowledge (2xx):
154 --------------------------------
155 200 <message>
156     Sends a dumb message.
157 201 <message>
158     Returns PCSX version.
159 202 <message>
160     Returns protocol version.
161 203 <status>
162     status = 0: running; = 1: paused; = 2: trace
163 210 PC=<value>
164     Displays current PC value.
165 211 <reg>=<value>
166     Displays one GP register value.
167 212 LO=<value> HI=<value>
168     Displays LO/HI registers.
169 213 <reg>=<value>
170     Displays one COP0 register value.
171 214 <reg>=<value>
172     Displays one COP2 control register value.
173 215 <reg>=<value>
174     Displays one COP2 data register value.
175 219 <message>
176     Displays one line of disassembled code.
177 221 <reg>=<value>
178     Displays one GP register value, ack for modification.
179 222 LO=<value> HI=<value>
180     Displays LO/HI registers, ack for modification.
181 223 <reg>=<value>
182     Displays one COP0 register value, ack for modification.
183 224 <reg>=<value>
184     Displays one COP2 control register value, ack for modification.
185 225 <reg>=<value>
186     Displays one COP2 data register value, ack for modification.
187 230 <size>@<addr>
188     Dumping memory. Will then raw outputs size bytes.
189 240 <size>@<addr>
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.
195 270
196     Acknolwedge of 170 command.
197
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.
202 401 <message>
203     Breakpoint deleting acknowledge.
204 410, 420, 421, 422, 430, 431, 432 <number>
205     Breakpoint adding acknowledge. Returns the number of the added breakpoint.
206 490 <message>
207     Pausing.
208 491 <message>
209     Resuming.
210 495 <message>
211     Tracing.
212 498 <message>
213     Soft resetting.
214 499 <message>
215     Resetting.
216
217 Error messages (5xx):
218 --------------------
219 500 <message>
220     Command not understood.
221 511 <message>
222     Invalid GPR register.
223 512 <message>
224     Invalid LO/HI register.
225 513, 514 <message>
226     Invalid range or address.
227 530 <message>
228     Non existant breakpoint.
229 531, 532, 533 <message>
230     Invalid breakpoint address.
231 */
232
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;
236
237 static void ProcessCommands();
238
239 static u8 *MemoryMap = NULL;
240
241 enum {
242     MAP_EXEC = 1,
243     MAP_R8 = 2,
244     MAP_R16 = 4,
245     MAP_R32 = 8,
246     MAP_W8 = 16,
247     MAP_W16 = 32,
248     MAP_W32 = 64,
249     MAP_EXEC_JAL = 128,
250 };
251
252 char *breakpoint_type_names[] = {
253     "E", "R1", "R2", "R4", "W1", "W2", "W4"
254 };
255
256 typedef struct breakpoint_s {
257     struct breakpoint_s *next, *prev;
258     int number, type;
259     u32 address;
260 } breakpoint_t;
261
262 static breakpoint_t *first = NULL;
263
264 int add_breakpoint(int type, u32 address) {
265     breakpoint_t *bp = (breakpoint_t *)malloc(sizeof(breakpoint_t));
266
267     bp->type = type;
268     bp->address = address;
269
270     if (first) {
271         bp->number = first->prev->number + 1;
272         bp->next = first;
273         bp->prev = first->prev;
274         first->prev = bp;
275         bp->prev->next = bp;
276     } else {
277         first = bp;
278         bp->number = 1;
279         bp->next = bp;
280         bp->prev = bp;
281     }
282
283     return bp->number;
284 }
285
286 void delete_breakpoint(breakpoint_t * bp) {
287     if (bp == first) {
288         if (bp->next == bp) {
289             first = NULL;
290         } else {
291             first = bp->next;
292         }
293     }
294
295     bp->next->prev = bp->prev;
296     bp->prev->next = bp->next;
297
298     free(bp);
299 }
300
301 breakpoint_t *next_breakpoint(breakpoint_t *bp) {
302     return bp->next != first ? bp->next : 0;
303 }
304
305 breakpoint_t *find_breakpoint(int number) {
306     breakpoint_t *p;
307
308     for (p = first; p; p = next_breakpoint(p)) {
309         if (p->number == number)
310             return p;
311     }
312
313     return 0;
314 }
315
316 void StartDebugger() {
317     if (debugger_active)
318         return;
319
320     MemoryMap = (u8 *)malloc(0x200000);
321     if (MemoryMap == NULL) {
322         SysMessage(_("Error allocating memory"));
323         return;
324     }
325
326     if (StartServer() == -1) {
327         SysPrintf(_("Unable to start debug server.\n"));
328         return;
329     }
330
331     SysPrintf(_("Debugger started.\n"));
332     debugger_active = 1;
333 }
334
335 void StopDebugger() {
336     if (debugger_active) {
337         StopServer();
338         SysPrintf(_("Debugger stopped.\n"));
339     }
340
341     if (MemoryMap != NULL) {
342         free(MemoryMap);
343         MemoryMap = NULL;
344     }
345
346     while (first != NULL) delete_breakpoint(first);
347
348     debugger_active = 0;
349 }
350
351 void PauseDebugger() {
352     trace = 0;
353     paused = 1;
354 }
355
356 void ResumeDebugger() {
357     trace = 0;
358     paused = 0;
359 }
360
361 void DebugVSync() {
362     if (!debugger_active || resetting)
363         return;
364
365     if (reset) {
366         resetting = 1;
367         CheckCdrom();
368         SysReset();
369         if (reset == 2)
370             LoadCdrom();
371         reset = resetting = 0;
372         return;
373     }
374
375     GetClient();
376     ProcessCommands();
377 }
378
379 void MarkMap(u32 address, int mask) {
380     if ((address & 0xff000000) != 0x80000000) return;
381     MemoryMap[address & 0x001fffff] |= mask;
382 }
383
384 int IsMapMarked(u32 address, int mask) {
385     return (MemoryMap[address & 0x001fffff] & mask) != 0;
386 }
387
388 void ProcessDebug() {
389     if (!debugger_active || reset || resetting)
390         return;
391     if (trace) {
392         if (!(--trace)) {
393             paused = 1;
394         }
395     }
396     if (!paused) {
397         DebugCheckBP(psxRegs.pc, E);
398     }
399     if (mapping_e) {
400         MarkMap(psxRegs.pc, MAP_EXEC);
401         if ((psxRegs.code >> 26) == 3) {
402             MarkMap(_JumpTarget_, MAP_EXEC_JAL);
403         }
404         if (((psxRegs.code >> 26) == 0) && ((psxRegs.code & 0x3F) == 9)) {
405             MarkMap(_Rd_, MAP_EXEC_JAL);
406         }
407     }
408     while (paused) {
409         GetClient();
410         ProcessCommands();
411         GPU_updateLace();
412     }
413 }
414
415 static void ProcessCommands() {
416     int code, i, dumping;
417     FILE *sfile;
418     char cmd[257], *arguments, *p, reply[10240], *save, *dump;
419     u32 reg, value, size, address;
420     breakpoint_t *bp;
421
422     if (!HasClient())
423         return;
424     if (ReadSocket(cmd, 256) > 0) {
425         arguments = NULL;
426         if (strlen(cmd) <= 2) {
427             code = 0;
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))) {
431             code = 0;
432         } else if (sscanf(cmd, "%3X ", &code) != 1) {
433             code = 0;
434         } else {
435             arguments = cmd + 4;
436         }
437         code = strtol(cmd, &arguments, 16);
438         while (arguments && *arguments && *arguments == 0x20)
439             arguments++;
440
441         if (*arguments == '\0')
442             arguments = NULL;
443
444         dumping = 0;
445         save = NULL;
446
447         switch (code) {
448         case 0x100:
449             sprintf(reply, "200 %s\r\n", arguments == NULL ? "OK" : arguments);
450             break;
451         case 0x101:
452             sprintf(reply, "201 %s\r\n", PCSX_VERSION);
453             break;
454         case 0x102:
455             sprintf(reply, "202 1.0\r\n");
456             break;
457         case 0x103:
458             sprintf(reply, "203 %i\r\n", paused ? 1 : trace ? 2 : 0);
459             break;
460         case 0x110:
461             sprintf(reply, "210 PC=%08X\r\n", psxRegs.pc);
462             break;
463         case 0x111:
464             if (arguments) {
465                 if (sscanf(arguments, "%02X", &code) != 1) {
466                     sprintf(reply, "511 Malformed 111 command '%s'\r\n", cmd);
467                     break;
468                 }
469             }
470             if (!arguments) {
471                 reply[0] = 0;
472                 for (i = 0; i < 32; i++) {
473                     sprintf(reply, "%s211 %02X=%08X\r\n", reply, i, psxRegs.GPR.r[i]);
474                 }
475             } else {
476                 if ((code >= 0) && (code < 32)) {
477                     sprintf(reply, "211 %02X=%08X\r\n", code, psxRegs.GPR.r[code]);
478                 } else {
479                     sprintf(reply, "511 Invalid GPR register: %X\r\n", code);
480                 }
481             }
482             break;
483         case 0x112:
484             sprintf(reply, "212 LO=%08X HI=%08X\r\n", psxRegs.GPR.n.lo, psxRegs.GPR.n.hi);
485             break;
486         case 0x113:
487             if (arguments) {
488                 if (sscanf(arguments, "%02X", &code) != 1) {
489                     sprintf(reply, "511 Malformed 113 command '%s'\r\n", cmd);
490                     break;
491                 }
492             }
493             if (!arguments) {
494                 reply[0] = 0;
495                 for (i = 0; i < 32; i++) {
496                     sprintf(reply, "%s213 %02X=%08X\r\n", reply, i, psxRegs.CP0.r[i]);
497                 }
498             } else {
499                 if ((code >= 0) && (code < 32)) {
500                     sprintf(reply, "213 %02X=%08X\r\n", code, psxRegs.CP0.r[code]);
501                 } else {
502                     sprintf(reply, "511 Invalid COP0 register: %X\r\n", code);
503                 }
504             }
505             break;
506         case 0x114:
507             if (arguments) {
508                 if (sscanf(arguments, "%02X", &code) != 1) {
509                     sprintf(reply, "511 Malformed 114 command '%s'\r\n", cmd);
510                     break;
511                 }
512             }
513             if (!arguments) {
514                 reply[0] = 0;
515                 for (i = 0; i < 32; i++) {
516                     sprintf(reply, "%s214 %02X=%08X\r\n", reply, i, psxRegs.CP2C.r[i]);
517                 }
518             } else {
519                 if ((code >= 0) && (code < 32)) {
520                     sprintf(reply, "214 %02X=%08X\r\n", code, psxRegs.CP2C.r[code]);
521                 } else {
522                     sprintf(reply, "511 Invalid COP2C register: %X\r\n", code);
523                 }
524             }
525             break;
526         case 0x115:
527             if (arguments) {
528                 if (sscanf(arguments, "%02X", &code) != 1) {
529                     sprintf(reply, "511 Malformed 111 command '%s'\r\n", cmd);
530                     break;
531                 }
532             }
533             if (!arguments) {
534                 reply[0] = 0;
535                 for (i = 0; i < 32; i++) {
536                     sprintf(reply, "%s215 %02X=%08X\r\n", reply, i, psxRegs.CP2D.r[i]);
537                 }
538             } else {
539                 if ((code >= 0) && (code < 32)) {
540                     sprintf(reply, "215 %02X=%08X\r\n", code, psxRegs.CP2D.r[code]);
541                 } else {
542                     sprintf(reply, "511 Invalid COP2D register: %X\r\n", code);
543                 }
544             }
545             break;
546         case 0x119:
547             if (arguments) {
548                 if (sscanf(arguments, "%08X", &code) != 1) {
549                     sprintf(reply, "511 Malformed 119 command '%s'\r\n", cmd);
550                     break;
551                 }
552             }
553             if (!arguments)
554                 code = psxRegs.pc;
555
556             sprintf(reply, "219 %s\r\n", disR3000AF(psxMemRead32(code), code));
557             break;
558         case 0x121:
559             if (!arguments || sscanf(arguments, "%02X=%08X", &reg, &value) != 2) {
560                 sprintf(reply, "500 Malformed 121 command '%s'\r\n", arguments);
561                 break;
562             }
563
564             if (reg < 32) {
565                 psxRegs.GPR.r[reg] = value;
566                 sprintf(reply, "221 %02X=%08X\r\n", reg, value);
567             } else {
568                 sprintf(reply, "512 Invalid GPR register: %02X\r\n", reg);
569             }
570             break;
571         case 0x122:
572             if (!arguments || strncmp(arguments, "HI=", 3) == 0) {
573                 reg = 33;
574             } else if (arguments && strncmp(arguments, "LO=", 3) == 0) {
575                 reg = 32;
576             } else {
577                 arguments[2] = 0;
578                 sprintf(reply, "512 Invalid LO/HI register: '%s'\r\n", arguments);
579                 break;
580             }
581
582             if (sscanf(arguments + 3, "%08X", &value) != 1) {
583                 sprintf(reply, "500 Malformed 122 command '%s'\r\n", arguments);
584             } else {
585                 psxRegs.GPR.r[reg] = value;
586                 sprintf(reply, "222 LO=%08X HI=%08X\r\n", psxRegs.GPR.n.lo, psxRegs.GPR.n.hi);
587             }
588             break;
589         case 0x123:
590             if (!arguments || sscanf(arguments, "%02X=%08X", &reg, &value) != 2) {
591                 sprintf(reply, "500 Malformed 123 command '%s'\r\n", arguments);
592                 break;
593             }
594
595             if (reg < 32) {
596                 psxRegs.CP0.r[reg] = value;
597                 sprintf(reply, "223 %02X=%08X\r\n", reg, value);
598             } else {
599                 sprintf(reply, "512 Invalid COP0 register: %02X\r\n", reg);
600             }
601             break;
602         case 0x124:
603             if (!arguments || sscanf(arguments, "%02X=%08X", &reg, &value) != 2) {
604                 sprintf(reply, "500 Malformed 124 command '%s'\r\n", arguments);
605                 break;
606             }
607
608             if (reg < 32) {
609                 psxRegs.CP2C.r[reg] = value;
610                 sprintf(reply, "224 %02X=%08X\r\n", reg, value);
611             } else {
612                 sprintf(reply, "512 Invalid COP2C register: %02X\r\n", reg);
613             }
614             break;
615         case 0x125:
616             if (!arguments || sscanf(arguments, "%02X=%08X", &reg, &value) != 2) {
617                 sprintf(reply, "500 Malformed 121 command '%s'\r\n", arguments);
618                 break;
619             }
620
621             if (reg < 32) {
622                 psxRegs.CP2D.r[reg] = value;
623                 sprintf(reply, "225 %02X=%08X\r\n", reg, value);
624             } else {
625                 sprintf(reply, "512 Invalid COP2D register: %02X\r\n", reg);
626             }
627             break;
628         case 0x130:
629             if (!arguments || sscanf(arguments, "%08X@%08X", &size, &address) != 2) {
630                 sprintf(reply, "500 Malformed 130 command '%s'\r\n", arguments);
631                 break;
632             }
633
634             if ((address >= 0x80000000) && ((address + size) <= 0x80200000)) {
635                 sprintf(reply, "230 %08X@%08X\r\n", size, address);
636                 dump = (char *) PSXM(address);
637                 dumping = 1;
638             } else {
639                 sprintf(reply, "513 Invalid address or range: '%s'\r\n", arguments);
640             }
641             break;
642         case 0x140:
643             if (!arguments || sscanf(arguments, "%08X@%08X", &size, &address) != 2) {
644                 sprintf(reply, "500 Malformed 140 command '%s'\r\n", arguments);
645                 break;
646             }
647
648             if ((address >= 0x80000000) && ((address + size) <= 0x80200000)) {
649                 sprintf(reply, "240 %08X@%08X\r\n", size, address);
650                 RawReadSocket((char *)PSXM(address), size);
651             } else {
652                 sprintf(reply, "514 Invalid address or range: '%s'\r\n", arguments);
653             }
654             break;
655         case 0x150:
656             code = 1;
657             if (arguments) {
658                 if (sscanf(arguments, "%02X", &code) != 1) {
659                     sprintf(reply, "500 Malformed 150 command '%s'\r\n", cmd);
660                     break;
661                 }
662             }
663             if (code) {
664                 mapping_e = 1;
665                 for (i = 0; i < 0x00200000; i++) {
666                     MemoryMap[i] &= ~MAP_EXEC;
667                     MemoryMap[i] &= ~MAP_EXEC_JAL;
668                 }
669             } else {
670                 mapping_e = 0;
671             }
672             sprintf(reply, "250 Mapping of exec flow %s\r\n", code ? "started" : "stopped");
673             break;
674         case 0x151:
675             code = 1;
676             if (arguments) {
677                 if (sscanf(arguments, "%02X", &code) != 1) {
678                     sprintf(reply, "500 Malformed 151 command '%s'\r\n", cmd);
679                     break;
680                 }
681             }
682             if (code) {
683                 mapping_r8 = 1;
684                 for (i = 0; i < 0x00200000; i++) {
685                     MemoryMap[i] &= ~MAP_R8;
686                 }
687             } else {
688                 mapping_r8 = 0;
689             }
690             sprintf(reply, "251 Mapping of read8 flow %s\r\n", code ? "started" : "stopped");
691             break;
692         case 0x152:
693             code = 1;
694             if (arguments) {
695                 if (sscanf(arguments, "%02X", &code) != 1) {
696                     sprintf(reply, "500 Malformed 152 command '%s'\r\n", cmd);
697                     break;
698                 }
699             }
700             if (code) {
701                 mapping_r16 = 1;
702                 for (i = 0; i < 0x00200000; i++) {
703                     MemoryMap[i] &= ~MAP_R16;
704                 }
705             } else {
706                 mapping_r16 = 0;
707             }
708             sprintf(reply, "252 Mapping of read16 flow %s\r\n", code ? "started" : "stopped");
709             break;
710         case 0x153:
711             code = 1;
712             if (arguments) {
713                 if (sscanf(arguments, "%02X", &code) != 1) {
714                     sprintf(reply, "500 Malformed 153 command '%s'\r\n", cmd);
715                     break;
716                 }
717             }
718             if (code) {
719                 mapping_r32 = 1;
720                 for (i = 0; i < 0x00200000; i++) {
721                     MemoryMap[i] &= ~MAP_R32;
722                 }
723             } else {
724                 mapping_r32 = 0;
725             }
726             sprintf(reply, "253 Mapping of read32 flow %s\r\n", code ? "started" : "stopped");
727             break;
728         case 0x154:
729             code = 1;
730             if (arguments) {
731                 if (sscanf(arguments, "%02X", &code) != 1) {
732                     sprintf(reply, "500 Malformed 154 command '%s'\r\n", cmd);
733                     break;
734                 }
735             }
736             if (code) {
737                 mapping_w8 = 1;
738                 for (i = 0; i < 0x00200000; i++) {
739                     MemoryMap[i] &= ~MAP_W8;
740                 }
741             } else {
742                 mapping_w8 = 0;
743             }
744             sprintf(reply, "254 Mapping of write8 flow %s\r\n", code ? "started" : "stopped");
745             break;
746         case 0x155:
747             code = 1;
748             if (arguments) {
749                 if (sscanf(arguments, "%02X", &code) != 1) {
750                     sprintf(reply, "500 Malformed 155 command '%s'\r\n", cmd);
751                     break;
752                 }
753             }
754             if (code) {
755                 mapping_w16 = 1;
756                 for (i = 0; i < 0x00200000; i++) {
757                     MemoryMap[i] &= ~MAP_W16;
758                 }
759             } else {
760                 mapping_w16 = 0;
761             }
762             sprintf(reply, "255 Mapping of write16 flow %s\r\n", code ? "started" : "stopped");
763             break;
764         case 0x156:
765             code = 1;
766             if (arguments) {
767                 if (sscanf(arguments, "%02X", &code) != 1) {
768                     sprintf(reply, "500 Malformed 156 command '%s'\r\n", cmd);
769                     break;
770                 }
771             }
772             if (code) {
773                 mapping_w32 = 1;
774                 for (i = 0; i < 0x00200000; i++) {
775                     MemoryMap[i] &= ~MAP_W32;
776                 }
777             } else {
778                 mapping_w32 = 0;
779             }
780             sprintf(reply, "256 Mapping of write32 flow %s\r\n", code ? "started" : "stopped");
781             break;
782         case 0x160:
783             code = 1;
784             if (arguments) {
785                 if (sscanf(arguments, "%02X", &code) != 1) {
786                     sprintf(reply, "500 Malformed 160 command '%s'\r\n", cmd);
787                     break;
788                 }
789             }
790             if (code) {
791                 breakmp_e = 1;
792             } else {
793                 breakmp_e = 0;
794             }
795             sprintf(reply, "260 Break on map of exec flow %s\r\n", code ? "started" : "stopped");
796             break;
797         case 0x161:
798             code = 1;
799             if (arguments) {
800                 if (sscanf(arguments, "%02X", &code) != 1) {
801                     sprintf(reply, "500 Malformed 161 command '%s'\r\n", cmd);
802                     break;
803                 }
804             }
805             if (code) {
806                 breakmp_r8 = 1;
807             } else {
808                 breakmp_r8 = 0;
809             }
810             sprintf(reply, "261 Break on map of read8 flow %s\r\n", code ? "started" : "stopped");
811             break;
812         case 0x162:
813             code = 1;
814             if (arguments) {
815                 if (sscanf(arguments, "%02X", &code) != 1) {
816                     sprintf(reply, "500 Malformed 162 command '%s'\r\n", cmd);
817                     break;
818                 }
819             }
820             if (code) {
821                 breakmp_r16 = 1;
822             } else {
823                 breakmp_r16 = 0;
824             }
825             sprintf(reply, "262 Break on map of read16 flow %s\r\n", code ? "started" : "stopped");
826             break;
827         case 0x163:
828             code = 1;
829             if (arguments) {
830                 if (sscanf(arguments, "%02X", &code) != 1) {
831                     sprintf(reply, "500 Malformed 163 command '%s'\r\n", cmd);
832                     break;
833                 }
834             }
835             if (code) {
836                 breakmp_r32 = 1;
837             } else {
838                 breakmp_r32 = 0;
839             }
840             sprintf(reply, "263 Break on map of read32 flow %s\r\n", code ? "started" : "stopped");
841             break;
842         case 0x164:
843             code = 1;
844             if (arguments) {
845                 if (sscanf(arguments, "%02X", &code) != 1) {
846                     sprintf(reply, "500 Malformed 164 command '%s'\r\n", cmd);
847                     break;
848                 }
849             }
850             if (code) {
851                 breakmp_w8 = 1;
852             } else {
853                 breakmp_w8 = 0;
854             }
855             sprintf(reply, "264 Break on map of write8 flow %s\r\n", code ? "started" : "stopped");
856             break;
857         case 0x165:
858             code = 1;
859             if (arguments) {
860                 if (sscanf(arguments, "%02X", &code) != 1) {
861                     sprintf(reply, "500 Malformed 165 command '%s'\r\n", cmd);
862                     break;
863                 }
864             }
865             if (code) {
866                 breakmp_w16 = 1;
867             } else {
868                 breakmp_w16 = 0;
869             }
870             sprintf(reply, "265 Break on map of write16 flow %s\r\n", code ? "started" : "stopped");
871             break;
872         case 0x166:
873             code = 1;
874             if (arguments) {
875                 if (sscanf(arguments, "%02X", &code) != 1) {
876                     sprintf(reply, "500 Malformed 166 command '%s'\r\n", cmd);
877                     break;
878                 }
879             }
880             if (code) {
881                 breakmp_w32 = 1;
882             } else {
883                 breakmp_w32 = 0;
884             }
885             sprintf(reply, "266 Break on map of write32 flow %s\r\n", code ? "started" : "stopped");
886             break;
887         case 0x170:
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);
894                 }
895             }
896             fprintf(sfile, "}\r\n");
897             fclose(sfile);
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);
904                 }
905             }
906             fprintf(sfile, "}\r\n");
907             fclose(sfile);
908             sprintf(reply, "270 flow.idc and markcode.idc dumped\r\n");
909             break;
910         case 0x300:
911             p = arguments;
912             if (arguments) {
913                 code = strtol(arguments, &p, 16);
914             }
915             if (p == arguments) {
916                 if (first) {
917                     reply[0] = 0;
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]);
920                     }
921                 } else {
922                     sprintf(reply, "530 No breakpoint\r\n");
923                 }
924             } else {
925                 if ((bp = find_breakpoint(code))) {
926                     sprintf(reply, "400 %X@%08X-%s\r\n", bp->number, bp->address, breakpoint_type_names[bp->type]);
927                 } else {
928                     sprintf(reply, "530 Invalid breakpoint number: %X\r\n", code);
929                 }
930             }
931             break;
932         case 0x301:
933             p = arguments;
934             if (arguments) {
935                 code = strtol(arguments, &p, 16);
936             }
937             if (p == arguments) {
938                 while (first != NULL) delete_breakpoint(first);
939                 sprintf(reply, "401 All breakpoints deleted.\r\n");
940             } else {
941                 if ((bp = find_breakpoint(code))) {
942                     delete_breakpoint(bp);
943                     sprintf(reply, "401 Breakpoint %X deleted.\r\n", code);
944                 } else {
945                     sprintf(reply, "530 Invalid breakpoint number: %X\r\n", code);
946                 }
947             }
948             break;
949         case 0x310:
950             if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
951                 sprintf(reply, "500 Malformed 310 command '%s'\r\n", arguments);
952                 break;
953             }
954 //            if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) {
955 //                sprintf(reply, "531 Invalid address %08X\r\n", address);
956 //                break;
957 //            }
958             code = add_breakpoint(E, address);
959             sprintf(reply, "410 %X\r\n", code);
960             break;
961         case 0x320:
962             if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
963                 sprintf(reply, "500 Malformed 320 command '%s'\r\n", arguments);
964                 break;
965             }
966             if ((address < 0x80000000) || (address >= 0x80200000)) {
967                 sprintf(reply, "532 Invalid address %08X\r\n", address);
968                 break;
969             }
970             code = add_breakpoint(R1, address);
971             sprintf(reply, "420 %X\r\n", code);
972             break;
973         case 0x321:
974             if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
975                 sprintf(reply, "500 Malformed 321 command '%s'\r\n", arguments);
976                 break;
977             }
978             if ((address & 1) || (address < 0x80000000) || (address >= 0x80200000)) {
979                 sprintf(reply, "532 Invalid address %08X\r\n", address);
980                 break;
981             }
982             code = add_breakpoint(R2, address);
983             sprintf(reply, "421 %X\r\n", code);
984             break;
985         case 0x322:
986             if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
987                 sprintf(reply, "500 Malformed 322 command '%s'\r\n", arguments);
988                 break;
989             }
990             if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) {
991                 sprintf(reply, "532 Invalid address %08X\r\n", address);
992                 break;
993             }
994             code = add_breakpoint(R4, address);
995             sprintf(reply, "422 %X\r\n", code);
996             break;
997         case 0x330:
998             if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
999                 sprintf(reply, "500 Malformed 330 command '%s'\r\n", arguments);
1000                 break;
1001             }
1002             if ((address < 0x80000000) || (address >= 0x80200000)) {
1003                 sprintf(reply, "533 Invalid address %08X\r\n", address);
1004                 break;
1005             }
1006             code = add_breakpoint(W1, address);
1007             sprintf(reply, "430 %X\r\n", code);
1008             break;
1009         case 0x331:
1010             if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
1011                 sprintf(reply, "500 Malformed 331 command '%s'\r\n", arguments);
1012                 break;
1013             }
1014             if ((address & 1) || (address < 0x80000000) || (address >= 0x80200000)) {
1015                 sprintf(reply, "533 Invalid address %08X\r\n", address);
1016                 break;
1017             }
1018             code = add_breakpoint(W2, address);
1019             sprintf(reply, "431 %X\r\n", code);
1020             break;
1021         case 0x332:
1022             if (!arguments || sscanf(arguments, "%08X", &address) != 1) {
1023                 sprintf(reply, "500 Malformed 332 command '%s'\r\n", arguments);
1024                 break;
1025             }
1026             if ((address & 3) || (address < 0x80000000) || (address >= 0x80200000)) {
1027                 sprintf(reply, "533 Invalid address %08X\r\n", address);
1028                 break;
1029             }
1030             code = add_breakpoint(W4, address);
1031             sprintf(reply, "432 %X\r\n", code);
1032             break;
1033         case 0x390:
1034             paused = 1;
1035             sprintf(reply, "490 Paused\r\n");
1036             break;
1037         case 0x391:
1038             paused = 0;
1039             sprintf(reply, "491 Resumed\r\n");
1040             break;
1041         case 0x395:
1042             p = arguments;
1043             if (arguments) {
1044                 trace = strtol(arguments, &p, 10);
1045             }
1046             if (p == arguments) {
1047                 trace = 1;
1048             }
1049             paused = 0;
1050             sprintf(reply, "495 Tracing\r\n");
1051             break;
1052         case 0x398:
1053             paused = 0;
1054             trace = 0;
1055             reset = 2;
1056             sprintf(reply, "498 Soft resetting\r\n");
1057             break;
1058         case 0x399:
1059             paused = 0;
1060             trace = 0;
1061             reset = 1;
1062             sprintf(reply, "499 Resetting\r\n");
1063             break;
1064         default:
1065             sprintf(reply, "500 Unknown command '%s'\r\n", cmd);
1066             break;
1067         }
1068         WriteSocket(reply, strlen(reply));
1069
1070         if (dumping) {
1071             WriteSocket(dump, size);
1072         }
1073
1074         if (save) {
1075             free(save);
1076         }
1077     }
1078 }
1079
1080 void DebugCheckBP(u32 address, enum breakpoint_types type) {
1081     breakpoint_t *bp;
1082     char reply[512];
1083
1084     if (!debugger_active || reset)
1085         return;
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));
1090             paused = 1;
1091             return;
1092         }
1093     }
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));
1098             paused = 1;
1099         }
1100     }
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));
1105             paused = 1;
1106         }
1107     }
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));
1112             paused = 1;
1113         }
1114     }
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));
1119             paused = 1;
1120         }
1121     }
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));
1126             paused = 1;
1127         }
1128     }
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));
1133             paused = 1;
1134         }
1135     }
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));
1140             paused = 1;
1141         }
1142     }
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);
1149  }