Mercurial > vba-clojure
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 WIN326 # include <unistd.h>7 # include <sys/socket.h>8 # include <netdb.h>9 # ifdef HAVE_NETINET_IN_H10 # include <netinet/in.h>11 # endif // HAVE_NETINET_IN_H12 # ifdef HAVE_ARPA_INET_H13 # include <arpa/inet.h>14 # else // ! HAVE_ARPA_INET_H15 # define socklen_t int16 # endif // ! HAVE_ARPA_INET_H17 #else // WIN3218 # include "../win32/stdafx.h"19 # include <winsock.h>20 # include <io.h>21 # define socklen_t int22 # define close closesocket23 # define read _read24 # define write _write25 #endif // WIN3227 #include "GBA.h"28 #include "GBAGlobals.h"30 extern bool debugger;31 extern void CPUUpdateCPSR();32 #ifdef SDL33 extern void (*dbgMain)();34 extern void (*dbgSignal)(int, int);35 extern void debuggerMain();36 extern void debuggerSignal(int, int);37 #endif39 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 #endif60 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 WIN3275 WSADATA wsaData;76 int error = WSAStartup(MAKEWORD(1, 1), &wsaData);77 #endif // WIN3278 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 else108 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 WIN32127 int flag = 0;128 ioctlsocket(s, FIONBIO, (unsigned long *)&flag);129 #endif // WIN32131 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 else141 {142 #ifdef WIN32143 int error = WSAGetLastError();144 #endif // WIN32145 }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 else218 {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 else284 {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 else385 v = (c + 10 - 'a') << 4;386 c = *p++;387 if (c <= '9')388 v += (c - '0');389 else390 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 do429 {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 else479 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 registers493 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 // PC501 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 register514 sprintf(s, "00000000");515 s += 8;516 // CPSR517 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 else549 b = (c + 10 - 'a') << 4;550 c = *p++;551 if (c <= '9')552 b += (c - '0');553 else554 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 else569 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 SDL594 dbgMain = debuggerMain;595 dbgSignal = debuggerSignal;596 #endif597 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 SDL618 dbgMain = debuggerMain;619 dbgSignal = debuggerSignal;620 #endif621 remoteResumed = true;622 debugger = false;623 return;624 case 'e':625 remoteStepOverRange(p);626 break;627 case 'k':628 remotePutPacket("OK");629 #ifdef SDL630 dbgMain = debuggerMain;631 dbgSignal = debuggerSignal;632 #endif633 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 else681 remotePutPacket("");682 break;683 case 'z':684 if (*p++ == '2')685 {686 remoteWriteWatch(p, false);687 }688 else689 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 }