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