cdrom: change pause timing again
[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();
ef79bbde
P
412 }
413}
414
415static 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:
7a8d521f 452 sprintf(reply, "201 %s\r\n", PCSX_VERSION);
ef79bbde
P
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
1080void 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 }