update README
[rofl0r-VisualBoyAdvance.git] / src / remote.c
blob9ff800545544fdf294c2c1c129b65d060e14d407
1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
2 // Copyright (C) 1999-2003 Forgotten
3 // Copyright (C) 2004 Forgotten and the VBA development team
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2, or(at your option)
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
23 #ifndef _WIN32
24 # include <unistd.h>
25 # include <sys/socket.h>
26 # include <netdb.h>
27 # include <netinet/in.h>
28 # include <arpa/inet.h>
29 # define SOCKET int
30 #else // _WIN32
31 # include <winsock.h>
32 # include <io.h>
33 # define socklen_t int
34 # define close closesocket
35 # define read _read
36 # define write _write
37 #endif // _WIN32
39 #include "GBA.h"
41 extern bool debugger;
42 extern void CPUUpdateCPSR();
43 #ifdef SDL
44 extern void (*dbgMain)();
45 extern void (*dbgSignal)(int,int);
46 extern void debuggerMain();
47 extern void debuggerSignal(int,int);
48 #endif
50 int remotePort = 55555;
51 int remoteSignal = 5;
52 SOCKET remoteSocket = -1;
53 SOCKET remoteListenSocket = -1;
54 bool remoteConnected = false;
55 bool remoteResumed = false;
57 int (*remoteSendFnc)(char *, int) = NULL;
58 int (*remoteRecvFnc)(char *, int) = NULL;
59 bool (*remoteInitFnc)() = NULL;
60 void (*remoteCleanUpFnc)() = NULL;
62 #ifndef SDL
63 void remoteSetSockets(SOCKET l, SOCKET r)
65 remoteSocket = r;
66 remoteListenSocket = l;
68 #endif
70 int remoteTcpSend(char *data, int len)
72 return send(remoteSocket, data, len, 0);
75 int remoteTcpRecv(char *data, int len)
77 return recv(remoteSocket, data, len, 0);
80 bool remoteTcpInit()
82 if(remoteSocket == -1) {
83 #ifdef _WIN32
84 WSADATA wsaData;
85 int error = WSAStartup(MAKEWORD(1,1),&wsaData);
86 #endif // _WIN32
87 SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
89 remoteListenSocket = s;
91 if(s < 0) {
92 fprintf(stderr,"Error opening socket\n");
93 exit(-1);
95 int tmp = 1;
96 setsockopt (s, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp, sizeof (tmp));
98 // char hostname[256];
99 // gethostname(hostname, 256);
101 // hostent *ent = gethostbyname(hostname);
102 // unsigned long a = *((unsigned long *)ent->h_addr);
104 struct sockaddr_in addr;
105 addr.sin_family = AF_INET;
106 addr.sin_port = htons(remotePort);
107 addr.sin_addr.s_addr = htonl(0);
108 int count = 0;
109 while(count < 3) {
110 if(bind(s, (struct sockaddr *)&addr, sizeof(addr))) {
111 addr.sin_port = htons(ntohs(addr.sin_port)+1);
112 } else
113 break;
115 if(count == 3) {
116 fprintf(stderr,"Error binding \n");
117 exit(-1);
120 fprintf(stderr,"Listening for a connection at port %d\n",
121 ntohs(addr.sin_port));
123 if(listen(s, 1)) {
124 fprintf(stderr, "Error listening\n");
125 exit(-1);
127 socklen_t len = sizeof(addr);
129 #ifdef _WIN32
130 int flag = 0;
131 ioctlsocket(s, FIONBIO, (unsigned long *)&flag);
132 #endif // _WIN32
133 SOCKET s2 = accept(s, (struct sockaddr *)&addr, &len);
134 if(s2 > 0) {
135 fprintf(stderr, "Got a connection from %s %d\n",
136 inet_ntoa((struct in_addr)addr.sin_addr),
137 ntohs(addr.sin_port));
138 } else {
139 #ifdef _WIN32
140 int error = WSAGetLastError();
141 #endif // _WIN32
143 char dummy;
144 recv(s2, &dummy, 1, 0);
145 if(dummy != '+') {
146 fprintf(stderr, "ACK not received\n");
147 exit(-1);
149 remoteSocket = s2;
150 // close(s);
152 return true;
155 void remoteTcpCleanUp()
157 if(remoteSocket > 0) {
158 fprintf(stderr, "Closing remote socket\n");
159 close(remoteSocket);
160 remoteSocket = -1;
162 if(remoteListenSocket > 0) {
163 fprintf(stderr, "Closing listen socket\n");
164 close(remoteListenSocket);
165 remoteListenSocket = -1;
169 int remotePipeSend(char *data, int len)
171 int res = write(1, data, len);
172 return res;
175 int remotePipeRecv(char *data, int len)
177 int res = read(0, data, len);
178 return res;
181 bool remotePipeInit()
183 char dummy;
184 read(0, &dummy, 1);
185 if(dummy != '+') {
186 fprintf(stderr, "ACK not received\n");
187 exit(-1);
190 return true;
193 void remotePipeCleanUp()
197 void remoteSetPort(int port)
199 remotePort = port;
202 void remoteSetProtocol(int p)
204 if(p == 0) {
205 remoteSendFnc = remoteTcpSend;
206 remoteRecvFnc = remoteTcpRecv;
207 remoteInitFnc = remoteTcpInit;
208 remoteCleanUpFnc = remoteTcpCleanUp;
209 } else {
210 remoteSendFnc = remotePipeSend;
211 remoteRecvFnc = remotePipeRecv;
212 remoteInitFnc = remotePipeInit;
213 remoteCleanUpFnc = remotePipeCleanUp;
217 void remoteInit()
219 if(remoteInitFnc)
220 remoteInitFnc();
223 void remotePutPacket(char *packet)
225 char *hex = "0123456789abcdef";
226 char buffer[1024];
228 size_t count = strlen(packet);
230 unsigned char csum = 0;
232 char *p = buffer;
233 *p++ = '$';
235 for(size_t i = 0 ;i < count; i++) {
236 csum += packet[i];
237 *p++ = packet[i];
239 *p++ = '#';
240 *p++ = hex[csum>>4];
241 *p++ = hex[csum & 15];
242 *p++ = 0;
243 // printf("Sending %s\n", buffer);
244 remoteSendFnc(buffer, (int)count + 4);
246 char c = 0;
247 remoteRecvFnc(&c, 1);
249 if(c == '+')
250 printf("ACK\n");
251 else if(c=='-')
252 printf("NACK\n");
256 #define debuggerReadMemory(addr) \
257 (*(u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])
259 #define debuggerReadHalfWord(addr) \
260 (*(u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])
262 #define debuggerReadByte(addr) \
263 map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
265 #define debuggerWriteMemory(addr, value) \
266 *(u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] = (value)
268 #define debuggerWriteHalfWord(addr, value) \
269 *(u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] = (value)
271 #define debuggerWriteByte(addr, value) \
272 map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] = (value)
274 void remoteOutput(char *s, u32 addr)
276 char buffer[16384];
278 char *d = buffer;
279 *d++ = 'O';
281 if(s) {
282 char c = *s++;
283 while(c) {
284 sprintf(d, "%02x", c);
285 d += 2;
286 c = *s++;
288 } else {
289 char c= debuggerReadByte(addr);
290 addr++;
291 while(c) {
292 sprintf(d, "%02x", c);
293 d += 2;
294 c = debuggerReadByte(addr);
295 addr++;
298 remotePutPacket(buffer);
299 // fprintf(stderr, "Output sent %s\n", buffer);
302 void remoteSendSignal()
304 char buffer[1024];
305 sprintf(buffer, "S%02x", remoteSignal);
306 remotePutPacket(buffer);
309 void remoteSendStatus()
311 char buffer[1024];
312 sprintf(buffer, "T%02x", remoteSignal);
313 char *s = buffer;
314 s += 3;
315 for(int i = 0; i < 15; i++) {
316 u32 v = reg[i].I;
317 sprintf(s, "%02x:%02x%02x%02x%02x;",i,
318 (v & 255),
319 (v >> 8) & 255,
320 (v >> 16) & 255,
321 (v >> 24) & 255);
322 s += 12;
324 u32 v = armNextPC;
325 sprintf(s, "0f:%02x%02x%02x%02x;", (v & 255),
326 (v >> 8) & 255,
327 (v >> 16) & 255,
328 (v >> 24) & 255);
329 s += 12;
330 CPUUpdateCPSR();
331 v = reg[16].I;
332 sprintf(s, "19:%02x%02x%02x%02x;", (v & 255),
333 (v >> 8) & 255,
334 (v >> 16) & 255,
335 (v >> 24) & 255);
336 s += 12;
337 *s = 0;
338 // printf("Sending %s\n", buffer);
339 remotePutPacket(buffer);
342 void remoteBinaryWrite(char *p)
344 u32 address;
345 int count;
346 sscanf(p,"%x,%x:", &address, &count);
347 // printf("Binary write for %08x %d\n", address, count);
349 p = strchr(p, ':');
350 p++;
351 for(int i = 0; i < count; i++) {
352 u8 b = *p++;
353 switch(b) {
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;
365 // printf("ROM is %08x\n", debuggerReadMemory(0x8000254));
366 remotePutPacket("OK");
369 void remoteMemoryWrite(char *p)
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 u8 v = 0;
380 char c = *p++;
381 if(c <= '9')
382 v = (c - '0') << 4;
383 else
384 v = (c + 10 - 'a') << 4;
385 c = *p++;
386 if(c <= '9')
387 v += (c - '0');
388 else
389 v += (c + 10 - 'a');
390 debuggerWriteByte(address, v);
391 address++;
393 // printf("ROM is %08x\n", debuggerReadMemory(0x8000254));
394 remotePutPacket("OK");
397 void remoteMemoryRead(char *p)
399 u32 address;
400 int count;
401 sscanf(p,"%x,%x:", &address, &count);
402 // printf("Memory read for %08x %d\n", address, count);
404 char buffer[1024];
406 char *s = buffer;
407 for(int i = 0; i < count; i++) {
408 u8 b = debuggerReadByte(address);
409 sprintf(s, "%02x", b);
410 address++;
411 s += 2;
413 *s = 0;
414 remotePutPacket(buffer);
417 void remoteStepOverRange(char *p)
419 u32 address;
420 u32 final;
421 sscanf(p, "%x,%x", &address, &final);
423 remotePutPacket("OK");
425 remoteResumed = true;
426 do {
427 CPULoop(1);
428 if(debugger)
429 break;
430 } while(armNextPC >= address && armNextPC < final);
432 remoteResumed = false;
434 remoteSendStatus();
437 void remoteWriteWatch(char *p, bool active)
439 u32 address;
440 int count;
441 sscanf(p, ",%x,%x#", &address, &count);
443 fprintf(stderr, "Write watch for %08x %d\n", address, count);
445 if(address < 0x2000000 || address > 0x3007fff) {
446 remotePutPacket("E01");
447 return;
450 if(address > 0x203ffff && address < 0x3000000) {
451 remotePutPacket("E01");
452 return;
455 u32 final = address + count;
457 if(address < 0x2040000 && final > 0x2040000) {
458 remotePutPacket("E01");
459 return;
460 } else if(address < 0x3008000 && final > 0x3008000) {
461 remotePutPacket("E01");
462 return;
465 #ifdef BKPT_SUPPORT
466 for(int i = 0; i < count; i++) {
467 if((address >> 24) == 2)
468 freezeWorkRAM[address & 0x3ffff] = active;
469 else
470 freezeInternalRAM[address & 0x7fff] = active;
471 address++;
473 #endif
475 remotePutPacket("OK");
478 void remoteReadRegisters(char *p)
480 char buffer[1024];
482 char *s = buffer;
483 int i;
484 // regular registers
485 for(i = 0; i < 15; i++) {
486 u32 v = reg[i].I;
487 sprintf(s, "%02x%02x%02x%02x", v & 255, (v >> 8) & 255,
488 (v >> 16) & 255, (v >> 24) & 255);
489 s += 8;
491 // PC
492 u32 pc = armNextPC;
493 sprintf(s, "%02x%02x%02x%02x", pc & 255, (pc >> 8) & 255,
494 (pc >> 16) & 255, (pc >> 24) & 255);
495 s += 8;
497 // floating point registers (24-bit)
498 for(i = 0; i < 8; i++) {
499 sprintf(s, "000000000000000000000000");
500 s += 24;
503 // FP status register
504 sprintf(s, "00000000");
505 s += 8;
506 // CPSR
507 CPUUpdateCPSR();
508 u32 v = reg[16].I;
509 sprintf(s, "%02x%02x%02x%02x", v & 255, (v >> 8) & 255,
510 (v >> 16) & 255, (v >> 24) & 255);
511 s += 8;
512 *s = 0;
513 remotePutPacket(buffer);
516 void remoteWriteRegister(char *p)
518 int r;
520 sscanf(p, "%x=", &r);
522 p = strchr(p, '=');
523 p++;
525 char c = *p++;
527 u32 v = 0;
529 u8 data[4] = {0,0,0,0};
531 int i = 0;
533 while(c != '#') {
534 u8 b = 0;
535 if(c <= '9')
536 b = (c - '0') << 4;
537 else
538 b = (c + 10 - 'a') << 4;
539 c = *p++;
540 if(c <= '9')
541 b += (c - '0');
542 else
543 b += (c + 10 - 'a');
544 data[i++] = b;
545 c = *p++;
548 v = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
550 // printf("Write register %d=%08x\n", r, v);
551 reg[r].I = v;
552 if(r == 15) {
553 armNextPC = v;
554 if(armState)
555 reg[15].I = v + 4;
556 else
557 reg[15].I = v + 2;
559 remotePutPacket("OK");
562 extern int emulating;
564 void remoteStubMain()
566 if(!debugger)
567 return;
569 if(remoteResumed) {
570 remoteSendStatus();
571 remoteResumed = false;
574 while(1) {
575 char buffer[1024];
576 int res = remoteRecvFnc(buffer, 1024);
578 if(res == -1) {
579 fprintf(stderr, "GDB connection lost\n");
580 #ifdef SDL
581 dbgMain = debuggerMain;
582 dbgSignal = debuggerSignal;
583 #endif
584 debugger = false;
585 break;
588 // fprintf(stderr, "Received %s\n", buffer);
589 char *p = buffer;
590 char c = *p++;
591 char pp = '+';
592 remoteSendFnc(&pp, 1);
594 if(c != '$')
595 continue;
596 c= *p++;
597 switch(c) {
598 case '?':
599 remoteSendSignal();
600 break;
601 case 'D':
602 remotePutPacket("OK");
603 #ifdef SDL
604 dbgMain = debuggerMain;
605 dbgSignal = debuggerSignal;
606 #endif
607 remoteResumed = true;
608 debugger = false;
609 return;
610 case 'e':
611 remoteStepOverRange(p);
612 break;
613 case 'k':
614 remotePutPacket("OK");
615 #ifdef SDL
616 dbgMain = debuggerMain;
617 dbgSignal = debuggerSignal;
618 #endif
619 debugger = false;
620 emulating = false;
621 return;
622 case 'C':
623 remoteResumed = true;
624 debugger = false;
625 return;
626 case 'c':
627 remoteResumed = true;
628 debugger = false;
629 return;
630 case 's':
631 remoteResumed = true;
632 remoteSignal = 5;
633 CPULoop(1);
634 if(remoteResumed) {
635 remoteResumed = false;
636 remoteSendStatus();
638 break;
639 case 'g':
640 remoteReadRegisters(p);
641 break;
642 case 'P':
643 remoteWriteRegister(p);
644 break;
645 case 'M':
646 remoteMemoryWrite(p);
647 break;
648 case 'm':
649 remoteMemoryRead(p);
650 break;
651 case 'X':
652 remoteBinaryWrite(p);
653 break;
654 case 'H':
655 remotePutPacket("OK");
656 break;
657 case 'q':
658 remotePutPacket("");
659 break;
660 case 'Z':
661 if(*p++ == '2') {
662 remoteWriteWatch(p, true);
663 } else
664 remotePutPacket("");
665 break;
666 case 'z':
667 if(*p++ == '2') {
668 remoteWriteWatch(p, false);
669 } else
670 remotePutPacket("");
671 break;
672 default:
674 *(strchr(p, '#') + 3) = 0;
675 fprintf(stderr, "Unknown packet %s\n", --p);
676 remotePutPacket("");
678 break;
683 void remoteStubSignal(int sig, int number)
685 remoteSignal = sig;
686 remoteResumed = false;
687 remoteSendStatus();
688 debugger = true;
691 void remoteCleanUp()
693 if(remoteCleanUpFnc)
694 remoteCleanUpFnc();