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