view src/gba/remote.cpp @ 93:4c60ebca1a9d

added function to get all the GB's memory.
author Robert McIntyre <rlm@mit.edu>
date Sun, 11 Mar 2012 20:16:09 -0500
parents 8870086b716c
children
line wrap: on
line source
1 #include <cstdlib>
2 #include <cstdio>
3 #include <cstring>
4 #include <config.h>
6 #ifndef WIN32
7 # include <unistd.h>
8 # include <sys/socket.h>
9 # include <netdb.h>
10 # ifdef HAVE_NETINET_IN_H
11 # include <netinet/in.h>
12 # endif // HAVE_NETINET_IN_H
13 # ifdef HAVE_ARPA_INET_H
14 # include <arpa/inet.h>
15 # else // ! HAVE_ARPA_INET_H
16 # define socklen_t int
17 # endif // ! HAVE_ARPA_INET_H
18 #else // WIN32
19 # include "../win32/stdafx.h"
20 # include <winsock.h>
21 # include <io.h>
22 # define socklen_t int
23 # define close closesocket
24 # define read _read
25 # define write _write
26 #endif // WIN32
28 #include "GBA.h"
29 #include "GBAGlobals.h"
31 extern bool debugger;
32 extern void CPUUpdateCPSR();
33 #ifdef SDL
34 extern void (*dbgMain)();
35 extern void (*dbgSignal)(int, int);
36 extern void debuggerMain();
37 extern void debuggerSignal(int, int);
38 #endif
40 int remotePort = 55555;
41 int remoteSignal = 5;
42 int remoteSocket = -1;
43 int remoteListenSocket = -1;
44 bool remoteConnected = false;
45 bool remoteResumed = false;
47 int (*remoteSendFnc)(char *, int) = NULL;
48 int (*remoteRecvFnc)(char *, int) = NULL;
49 bool (*remoteInitFnc)() = NULL;
50 void (*remoteCleanUpFnc)() = NULL;
52 #if (defined WIN32 && !defined SDL)
53 void remoteSetSockets(SOCKET l, SOCKET r)
54 {
55 remoteSocket = r;
56 remoteListenSocket = l;
57 }
59 #endif
61 int remoteTcpSend(char *data, int len)
62 {
63 return send(remoteSocket, data, len, 0);
64 }
66 int remoteTcpRecv(char *data, int len)
67 {
68 return recv(remoteSocket, data, len, 0);
69 }
71 bool remoteTcpInit()
72 {
73 if (remoteSocket == -1)
74 {
75 #ifdef WIN32
76 WSADATA wsaData;
77 int error = WSAStartup(MAKEWORD(1, 1), &wsaData);
78 #endif // WIN32
79 int s = socket(PF_INET, SOCK_STREAM, 0);
81 remoteListenSocket = s;
83 if (s < 0)
84 {
85 fprintf(stderr, "Error opening socket\n");
86 exit(-1);
87 }
88 int tmp = 1;
89 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp, sizeof(tmp));
91 // char hostname[256];
92 // gethostname(hostname, 256);
94 // hostent *ent = gethostbyname(hostname);
95 // unsigned long a = *((unsigned long *)ent->h_addr);
97 sockaddr_in addr;
98 addr.sin_family = AF_INET;
99 addr.sin_port = htons(remotePort);
100 addr.sin_addr.s_addr = htonl(0);
101 int count = 0;
102 while (count < 3)
103 {
104 if (bind(s, (sockaddr *)&addr, sizeof(addr)))
105 {
106 addr.sin_port = htons(ntohs(addr.sin_port)+1);
107 }
108 else
109 break;
110 }
111 if (count == 3)
112 {
113 fprintf(stderr, "Error binding \n");
114 exit(-1);
115 }
117 fprintf(stderr, "Listening for a connection at port %d\n",
118 ntohs(addr.sin_port));
120 if (listen(s, 1))
121 {
122 fprintf(stderr, "Error listening\n");
123 exit(-1);
124 }
125 socklen_t len = sizeof(addr);
127 #ifdef WIN32
128 int flag = 0;
129 ioctlsocket(s, FIONBIO, (unsigned long *)&flag);
130 #endif // WIN32
131 int s2 = accept(s, (sockaddr *)&addr, &len);
132 if (s2 > 0)
133 {
134 fprintf(stderr, "Got a connection from %s %d\n",
135 inet_ntoa((in_addr)addr.sin_addr),
136 ntohs(addr.sin_port));
137 }
138 else
139 {
140 #ifdef WIN32
141 int error = WSAGetLastError();
142 #endif // WIN32
143 }
144 char dummy;
145 recv(s2, &dummy, 1, 0);
146 if (dummy != '+')
147 {
148 fprintf(stderr, "ACK not received\n");
149 exit(-1);
150 }
151 remoteSocket = s2;
152 // close(s);
153 }
154 return true;
155 }
157 void remoteTcpCleanUp()
158 {
159 if (remoteSocket > 0)
160 {
161 fprintf(stderr, "Closing remote socket\n");
162 close(remoteSocket);
163 remoteSocket = -1;
164 }
165 if (remoteListenSocket > 0)
166 {
167 fprintf(stderr, "Closing listen socket\n");
168 close(remoteListenSocket);
169 remoteListenSocket = -1;
170 }
171 }
173 int remotePipeSend(char *data, int len)
174 {
175 int res = write(1, data, len);
176 return res;
177 }
179 int remotePipeRecv(char *data, int len)
180 {
181 int res = read(0, data, len);
182 return res;
183 }
185 bool remotePipeInit()
186 {
187 char dummy;
188 read(0, &dummy, 1);
189 if (dummy != '+')
190 {
191 fprintf(stderr, "ACK not received\n");
192 exit(-1);
193 }
195 return true;
196 }
198 void remotePipeCleanUp()
199 {}
201 void remoteSetPort(int port)
202 {
203 remotePort = port;
204 }
206 void remoteSetProtocol(int p)
207 {
208 if (p == 0)
209 {
210 remoteSendFnc = remoteTcpSend;
211 remoteRecvFnc = remoteTcpRecv;
212 remoteInitFnc = remoteTcpInit;
213 remoteCleanUpFnc = remoteTcpCleanUp;
214 }
215 else
216 {
217 remoteSendFnc = remotePipeSend;
218 remoteRecvFnc = remotePipeRecv;
219 remoteInitFnc = remotePipeInit;
220 remoteCleanUpFnc = remotePipeCleanUp;
221 }
222 }
224 void remoteInit()
225 {
226 if (remoteInitFnc)
227 remoteInitFnc();
228 }
230 void remotePutPacket(char *packet)
231 {
232 char *hex = "0123456789abcdef";
233 char buffer[1024];
235 int count = strlen(packet);
237 unsigned char csum = 0;
239 char *p = buffer;
240 *p++ = '$';
242 for (int i = 0; i < count; i++)
243 {
244 csum += packet[i];
245 *p++ = packet[i];
246 }
247 *p++ = '#';
248 *p++ = hex[csum>>4];
249 *p++ = hex[csum & 15];
250 *p++ = 0;
251 // printf("Sending %s\n", buffer);
252 remoteSendFnc(buffer, count + 4);
254 char c = 0;
255 remoteRecvFnc(&c, 1);
256 /*
257 if(c == '+')
258 printf("ACK\n");
259 else if(c=='-')
260 printf("NACK\n");
261 */
262 }
264 void remoteOutput(char *s, u32 addr)
265 {
266 char buffer[16384];
268 char *d = buffer;
269 *d++ = 'O';
271 if (s)
272 {
273 char c = *s++;
274 while (c)
275 {
276 sprintf(d, "%02x", c);
277 d += 2;
278 c = *s++;
279 }
280 }
281 else
282 {
283 char c = debuggerReadByte(addr);
284 addr++;
285 while (c)
286 {
287 sprintf(d, "%02x", c);
288 d += 2;
289 c = debuggerReadByte(addr);
290 addr++;
291 }
292 }
293 remotePutPacket(buffer);
294 // fprintf(stderr, "Output sent %s\n", buffer);
295 }
297 void remoteSendSignal()
298 {
299 char buffer[1024];
300 sprintf(buffer, "S%02x", remoteSignal);
301 remotePutPacket(buffer);
302 }
304 void remoteSendStatus()
305 {
306 char buffer[1024];
307 sprintf(buffer, "T%02x", remoteSignal);
308 char *s = buffer;
309 s += 3;
310 for (int i = 0; i < 15; i++)
311 {
312 u32 v = reg[i].I;
313 sprintf(s, "%02x:%02x%02x%02x%02x;", i,
314 (v & 255),
315 (v >> 8) & 255,
316 (v >> 16) & 255,
317 (v >> 24) & 255);
318 s += 12;
319 }
320 u32 v = armNextPC;
321 sprintf(s, "0f:%02x%02x%02x%02x;", (v & 255),
322 (v >> 8) & 255,
323 (v >> 16) & 255,
324 (v >> 24) & 255);
325 s += 12;
326 CPUUpdateCPSR();
327 v = reg[16].I;
328 sprintf(s, "19:%02x%02x%02x%02x;", (v & 255),
329 (v >> 8) & 255,
330 (v >> 16) & 255,
331 (v >> 24) & 255);
332 s += 12;
333 *s = 0;
334 // printf("Sending %s\n", buffer);
335 remotePutPacket(buffer);
336 }
338 void remoteBinaryWrite(char *p)
339 {
340 u32 address;
341 int count;
342 sscanf(p, "%x,%x:", &address, &count);
343 // printf("Binary write for %08x %d\n", address, count);
345 p = strchr(p, ':');
346 p++;
347 for (int i = 0; i < count; i++)
348 {
349 u8 b = *p++;
350 switch (b)
351 {
352 case 0x7d:
353 b = *p++;
354 debuggerWriteByte(address, (b^0x20));
355 address++;
356 break;
357 default:
358 debuggerWriteByte(address, b);
359 address++;
360 break;
361 }
362 }
363 // printf("ROM is %08x\n", debuggerReadMemory(0x8000254));
364 remotePutPacket("OK");
365 }
367 void remoteMemoryWrite(char *p)
368 {
369 u32 address;
370 int count;
371 sscanf(p, "%x,%x:", &address, &count);
372 // printf("Memory write for %08x %d\n", address, count);
374 p = strchr(p, ':');
375 p++;
376 for (int i = 0; i < count; i++)
377 {
378 u8 v = 0;
379 char c = *p++;
380 if (c <= '9')
381 v = (c - '0') << 4;
382 else
383 v = (c + 10 - 'a') << 4;
384 c = *p++;
385 if (c <= '9')
386 v += (c - '0');
387 else
388 v += (c + 10 - 'a');
389 debuggerWriteByte(address, v);
390 address++;
391 }
392 // printf("ROM is %08x\n", debuggerReadMemory(0x8000254));
393 remotePutPacket("OK");
394 }
396 void remoteMemoryRead(char *p)
397 {
398 u32 address;
399 int count;
400 sscanf(p, "%x,%x:", &address, &count);
401 // printf("Memory read for %08x %d\n", address, count);
403 char buffer[1024];
405 char *s = buffer;
406 for (int i = 0; i < count; i++)
407 {
408 u8 b = debuggerReadByte(address);
409 sprintf(s, "%02x", b);
410 address++;
411 s += 2;
412 }
413 *s = 0;
414 remotePutPacket(buffer);
415 }
417 void remoteStepOverRange(char *p)
418 {
419 u32 address;
420 u32 final;
421 sscanf(p, "%x,%x", &address, &final);
423 remotePutPacket("OK");
425 remoteResumed = true;
426 do
427 {
428 CPULoop(1);
429 if (debugger)
430 break;
431 }
432 while (armNextPC >= address && armNextPC < final);
434 remoteResumed = false;
436 remoteSendStatus();
437 }
439 void remoteWriteWatch(char *p, bool active)
440 {
441 u32 address;
442 int count;
443 sscanf(p, ",%x,%x#", &address, &count);
445 fprintf(stderr, "Write watch for %08x %d\n", address, count);
447 if (address < 0x2000000 || address > 0x3007fff)
448 {
449 remotePutPacket("E01");
450 return;
451 }
453 if (address > 0x203ffff && address < 0x3000000)
454 {
455 remotePutPacket("E01");
456 return;
457 }
459 u32 final = address + count;
461 if (address < 0x2040000 && final > 0x2040000)
462 {
463 remotePutPacket("E01");
464 return;
465 }
466 else if (address < 0x3008000 && final > 0x3008000)
467 {
468 remotePutPacket("E01");
469 return;
470 }
472 for (int i = 0; i < count; i++)
473 {
474 if ((address >> 24) == 2)
475 freezeWorkRAM[address & 0x3ffff] = active;
476 else
477 freezeInternalRAM[address & 0x7fff] = active;
478 address++;
479 }
481 remotePutPacket("OK");
482 }
484 void remoteReadRegisters(char *p)
485 {
486 char buffer[1024];
488 char *s = buffer;
489 int i;
490 // regular registers
491 for (i = 0; i < 15; i++)
492 {
493 u32 v = reg[i].I;
494 sprintf(s, "%02x%02x%02x%02x", v & 255, (v >> 8) & 255,
495 (v >> 16) & 255, (v >> 24) & 255);
496 s += 8;
497 }
498 // PC
499 u32 pc = armNextPC;
500 sprintf(s, "%02x%02x%02x%02x", pc & 255, (pc >> 8) & 255,
501 (pc >> 16) & 255, (pc >> 24) & 255);
502 s += 8;
504 // floating point registers (24-bit)
505 for (i = 0; i < 8; i++)
506 {
507 sprintf(s, "000000000000000000000000");
508 s += 24;
509 }
511 // FP status register
512 sprintf(s, "00000000");
513 s += 8;
514 // CPSR
515 CPUUpdateCPSR();
516 u32 v = reg[16].I;
517 sprintf(s, "%02x%02x%02x%02x", v & 255, (v >> 8) & 255,
518 (v >> 16) & 255, (v >> 24) & 255);
519 s += 8;
520 *s = 0;
521 remotePutPacket(buffer);
522 }
524 void remoteWriteRegister(char *p)
525 {
526 int r;
528 sscanf(p, "%x=", &r);
530 p = strchr(p, '=');
531 p++;
533 char c = *p++;
535 u32 v = 0;
537 u8 data[4] = {0, 0, 0, 0};
539 int i = 0;
541 while (c != '#')
542 {
543 u8 b = 0;
544 if (c <= '9')
545 b = (c - '0') << 4;
546 else
547 b = (c + 10 - 'a') << 4;
548 c = *p++;
549 if (c <= '9')
550 b += (c - '0');
551 else
552 b += (c + 10 - 'a');
553 data[i++] = b;
554 c = *p++;
555 }
557 v = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
559 // printf("Write register %d=%08x\n", r, v);
560 reg[r].I = v;
561 if (r == 15)
562 {
563 armNextPC = v;
564 if (armState)
565 reg[15].I = v + 4;
566 else
567 reg[15].I = v + 2;
568 }
569 remotePutPacket("OK");
570 }
572 void remoteStubMain()
573 {
574 if (!debugger)
575 return;
577 if (remoteResumed)
578 {
579 remoteSendStatus();
580 remoteResumed = false;
581 }
583 while (true)
584 {
585 char buffer[1024];
586 int res = remoteRecvFnc(buffer, 1024);
588 if (res == -1)
589 {
590 fprintf(stderr, "GDB connection lost\n");
591 #ifdef SDL
592 dbgMain = debuggerMain;
593 dbgSignal = debuggerSignal;
594 #endif
595 debugger = false;
596 break;
597 }
599 // fprintf(stderr, "Received %s\n", buffer);
600 char *p = buffer;
601 char c = *p++;
602 char pp = '+';
603 remoteSendFnc(&pp, 1);
605 if (c != '$')
606 continue;
607 c = *p++;
608 switch (c)
609 {
610 case '?':
611 remoteSendSignal();
612 break;
613 case 'D':
614 remotePutPacket("OK");
615 #ifdef SDL
616 dbgMain = debuggerMain;
617 dbgSignal = debuggerSignal;
618 #endif
619 remoteResumed = true;
620 debugger = false;
621 return;
622 case 'e':
623 remoteStepOverRange(p);
624 break;
625 case 'k':
626 remotePutPacket("OK");
627 #ifdef SDL
628 dbgMain = debuggerMain;
629 dbgSignal = debuggerSignal;
630 #endif
631 debugger = false;
632 emulating = false;
633 return;
634 case 'C':
635 remoteResumed = true;
636 debugger = false;
637 return;
638 case 'c':
639 remoteResumed = true;
640 debugger = false;
641 return;
642 case 's':
643 remoteResumed = true;
644 remoteSignal = 5;
645 CPULoop(1);
646 if (remoteResumed)
647 {
648 remoteResumed = false;
649 remoteSendStatus();
650 }
651 break;
652 case 'g':
653 remoteReadRegisters(p);
654 break;
655 case 'P':
656 remoteWriteRegister(p);
657 break;
658 case 'M':
659 remoteMemoryWrite(p);
660 break;
661 case 'm':
662 remoteMemoryRead(p);
663 break;
664 case 'X':
665 remoteBinaryWrite(p);
666 break;
667 case 'H':
668 remotePutPacket("OK");
669 break;
670 case 'q':
671 remotePutPacket("");
672 break;
673 case 'Z':
674 if (*p++ == '2')
675 {
676 remoteWriteWatch(p, true);
677 }
678 else
679 remotePutPacket("");
680 break;
681 case 'z':
682 if (*p++ == '2')
683 {
684 remoteWriteWatch(p, false);
685 }
686 else
687 remotePutPacket("");
688 break;
689 default:
690 {
691 *(strchr(p, '#') + 3) = 0;
692 fprintf(stderr, "Unknown packet %s\n", --p);
693 remotePutPacket("");
694 break;
695 }
696 }
697 }
698 }
700 void remoteStubSignal(int sig, int number)
701 {
702 remoteSignal = sig;
703 remoteResumed = false;
704 remoteSendStatus();
705 debugger = true;
706 }
708 void remoteCleanUp()
709 {
710 if (remoteCleanUpFnc)
711 remoteCleanUpFnc();
712 }