view src/gba/remote.cpp @ 21:e0545ef33bb9

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