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