spu: some misc refactoring/cleanup
[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
23/*
24PCSX Debug console protocol description, version 1.0
25~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26
27Commands number are formatted using %03X (yes)
28Registers number are formatted using %02X.
29Breakpoints numbers are formatted using %X
30All other values are formatted using %08X, unless specified.
31
32
33Client inputs:
34~~~~~~~~~~~~~
35Basic commands (1xx):
36--------------------
37100 <message>
38 Sends a dumb message. Will be replied with a 200 reply, followed by the message.
39101
40 Gets PCSX version.
41102
42 Gets protocol version.
43103
44 Gets status
45110
46 Gets PC.
47111 [reg]
48 Gets GP register, or all, if no argument.
49112
50 Gets LO/HI registers.
51113 [reg]
52 Gets COP0 register, or all, if no argument.
53114 [reg]
54 Gets COP2 control register, or all, if no argument.
55115 [reg]
56 Gets COP2 data register, or all, if no argument.
57119 [pc]
58 Disassemble current PC, or given PC.
59121 <reg>=<value>
60 Sets a GP register. Will return a 221 message.
61122 <LO|HI>=<value>
62 Sets LO or HI register. Will return a 222 message.
63123 <reg>=<value>
64 Sets a COP0 register. Will return a 223 message.
65124 <reg>=<value>
66 Sets a COP2 control register. Will return a 224 message.
67125 <reg>=<value>
68 Sets a COP2 data register. Will return a 225 message.
69130 <size>@<addr>
70 Dumps a range of memory, of size bytes starting at addr.
71140 <size>@<addr>
72 Sets a range of memory, of size bytes starting at addr.
73 Will have to send immediately exactly size bytes afterward.
74150 [number]
75 Starts/reset mapping execution flow, or stop it if number = 0
76151 [number]
77 Starts/reset mapping read8 flow, or stop it if number = 0
78152 [number]
79 Starts/reset mapping read16 flow, or stop it if number = 0
80153 [number]
81 Starts/reset mapping read32 flow, or stop it if number = 0
82154 [number]
83 Starts/reset mapping write8 flow, or stop it if number = 0
84155 [number]
85 Starts/reset mapping write16 flow, or stop it if number = 0
86156 [number]
87 Starts/reset mapping write32 flow, or stop it if number = 0
88160 [number]
89 Breaks on map exec flow, or stop it if number = 0
90161 [number]
91 Breaks on map read8 flow, or stop it if number = 0
92162 [number]
93 Breaks on map read16 flow, or stop it if number = 0
94163 [number]
95 Breaks on map read32 flow, or stop it if number = 0
96164 [number]
97 Breaks on map write8 flow, or stop it if number = 0
98165 [number]
99 Breaks on map write16 flow, or stop it if number = 0
100166 [number]
101 Breaks on map write32 flow, or stop it if number = 0
102170
103 Dumps the execution flow map in an IDC file
104
105Execution flow control commands (3xx):
106-------------------------------------
107300 [number]
108 Get a list of the actual breakpoints. Will get '400' answers.
109301 [number]
110 Deletes a breakpoint, or all, if no arguments.
111310 <address>
112 Sets an exec breakpoint.
113320 <address>
114 Sets a read breakpoint, 1 byte / 8 bits.
115321 <address>
116 Sets a read breakpoint, 2 bytes / 16 bits, has to be on an even address.
117322 <address>
118 Sets a read breakpoint, 4 bytes / 32 bits, address has to be 4-bytes aligned.
119330 <address>
120 Sets a write breakpoint, 1 byte / 8 bits.
121331 <address>
122 Sets a write breakpoint, 2 bytes / 16 bits, has to be on an even address.
123332 <address>
124 Sets a write breakpoint, 4 bytes / 32 bits, address has to be 4-bytes aligned.
125390
126 Pauses execution. Equivalents to a breakpoint.
127391
128 Restarts execution.
129395 [number]
130 Traces execution, 1 instruction by default. Formatted using %i
131398
132 Soft (quick) resets.
133399
134 Resets.
135
136
137Server outputs:
138~~~~~~~~~~~~~~
139Spontaneous messages (0xx):
140--------------------------
141000 <message>
142 Greeting banner.
143010 / 011 / 012 / 013 / 014 / 015 / 016
144 Execution hit mapping flow automatic breakpoint.
145030 <number>@<PC>
146 Execution hit breakpoint, PCSX is paused. Displays PC's value.
147
148Basic commands acknowledge (2xx):
149--------------------------------
150200 <message>
151 Sends a dumb message.
152201 <message>
153 Returns PCSX version.
154202 <message>
155 Returns protocol version.
156203 <status>
157 status = 0: running; = 1: paused; = 2: trace
158210 PC=<value>
159 Displays current PC value.
160211 <reg>=<value>
161 Displays one GP register value.
162212 LO=<value> HI=<value>
163 Displays LO/HI registers.
164213 <reg>=<value>
165 Displays one COP0 register value.
166214 <reg>=<value>
167 Displays one COP2 control register value.
168215 <reg>=<value>
169 Displays one COP2 data register value.
170219 <message>
171 Displays one line of disassembled code.
172221 <reg>=<value>
173 Displays one GP register value, ack for modification.
174222 LO=<value> HI=<value>
175 Displays LO/HI registers, ack for modification.
176223 <reg>=<value>
177 Displays one COP0 register value, ack for modification.
178224 <reg>=<value>
179 Displays one COP2 control register value, ack for modification.
180225 <reg>=<value>
181 Displays one COP2 data register value, ack for modification.
182230 <size>@<addr>
183 Dumping memory. Will then raw outputs size bytes.
184240 <size>@<addr>
185 Memory set acknowledge.
186250 / 251 / 252 / 253 / 254 / 255 / 256
187 Acknolwedge of 15x commands.
188260 / 261 / 262 / 263 / 264 / 265 / 266
189 Acknolwedge of 16x commands.
190270
191 Acknolwedge of 170 command.
192
193Execution flow control commands acknowledge (4xx):
194-------------------------------------------------
195400 <number>@<address>-<type>
196 Displays a breakpoint, where 'type' can be of E, R1, R2, R4, W1, W2 or W4.
197401 <message>
198 Breakpoint deleting acknowledge.
199410, 420, 421, 422, 430, 431, 432 <number>
200 Breakpoint adding acknowledge. Returns the number of the added breakpoint.
201490 <message>
202 Pausing.
203491 <message>
204 Resuming.
205495 <message>
206 Tracing.
207498 <message>
208 Soft resetting.
209499 <message>
210 Resetting.
211
212Error messages (5xx):
213--------------------
214500 <message>
215 Command not understood.
216511 <message>
217 Invalid GPR register.
218512 <message>
219 Invalid LO/HI register.
220513, 514 <message>
221 Invalid range or address.
222530 <message>
223 Non existant breakpoint.
224531, 532, 533 <message>
225 Invalid breakpoint address.
226*/
227
228static int debugger_active = 0, paused = 0, trace = 0, reset = 0, resetting = 0;
229static int mapping_e = 0, mapping_r8 = 0, mapping_r16 = 0, mapping_r32 = 0, mapping_w8 = 0, mapping_w16 = 0, mapping_w32 = 0;
230static int breakmp_e = 0, breakmp_r8 = 0, breakmp_r16 = 0, breakmp_r32 = 0, breakmp_w8 = 0, breakmp_w16 = 0, breakmp_w32 = 0;
231
232static void ProcessCommands();
233
234static u8 *MemoryMap = NULL;
235
236enum {
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
247char *breakpoint_type_names[] = {
248 "E", "R1", "R2", "R4", "W1", "W2", "W4"
249};
250
251typedef struct breakpoint_s {
252 struct breakpoint_s *next, *prev;
253 int number, type;
254 u32 address;
255} breakpoint_t;
256
257static breakpoint_t *first = NULL;
258
259int 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
281void 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
296breakpoint_t *next_breakpoint(breakpoint_t *bp) {
297 return bp->next != first ? bp->next : 0;
298}
299
300breakpoint_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
311void 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
330void 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
346void PauseDebugger() {
347 trace = 0;
348 paused = 1;
349}
350
351void ResumeDebugger() {
352 trace = 0;
353 paused = 0;
354}
355
356void 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
374void MarkMap(u32 address, int mask) {
375 if ((address & 0xff000000) != 0x80000000) return;
376 MemoryMap[address & 0x001fffff] |= mask;
377}
378
379int IsMapMarked(u32 address, int mask) {
380 return (MemoryMap[address & 0x001fffff] & mask) != 0;
381}
382
383void 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
411static 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
1076void 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 }