Mercurial > vba-clojure
view src/gba/remote.cpp @ 7:c0a590a394c3
ignore generated files
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:50:33 -0600 |
parents | f9f4f1b99eed |
children | ecd30c5e2f5a |
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 }124 socklen_t len = sizeof(addr);126 #ifdef WIN32127 int flag = 0;128 ioctlsocket(s, FIONBIO, (unsigned long *)&flag);129 #endif // WIN32130 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 else138 {139 #ifdef WIN32140 int error = WSAGetLastError();141 #endif // WIN32142 }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 }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 }172 int remotePipeSend(char *data, int len)173 {174 int res = write(1, data, len);175 return res;176 }178 int remotePipeRecv(char *data, int len)179 {180 int res = read(0, data, len);181 return res;182 }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 }194 return true;195 }197 void remotePipeCleanUp()198 {}200 void remoteSetPort(int port)201 {202 remotePort = port;203 }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 else215 {216 remoteSendFnc = remotePipeSend;217 remoteRecvFnc = remotePipeRecv;218 remoteInitFnc = remotePipeInit;219 remoteCleanUpFnc = remotePipeCleanUp;220 }221 }223 void remoteInit()224 {225 if (remoteInitFnc)226 remoteInitFnc();227 }229 void remotePutPacket(char *packet)230 {231 char *hex = "0123456789abcdef";232 char buffer[1024];234 int count = strlen(packet);236 unsigned char csum = 0;238 char *p = buffer;239 *p++ = '$';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);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 }263 void remoteOutput(char *s, u32 addr)264 {265 char buffer[16384];267 char *d = buffer;268 *d++ = 'O';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 else281 {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 }296 void remoteSendSignal()297 {298 char buffer[1024];299 sprintf(buffer, "S%02x", remoteSignal);300 remotePutPacket(buffer);301 }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 }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);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 }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);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 else382 v = (c + 10 - 'a') << 4;383 c = *p++;384 if (c <= '9')385 v += (c - '0');386 else387 v += (c + 10 - 'a');388 debuggerWriteByte(address, v);389 address++;390 }391 // printf("ROM is %08x\n", debuggerReadMemory(0x8000254));392 remotePutPacket("OK");393 }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);402 char buffer[1024];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 }416 void remoteStepOverRange(char *p)417 {418 u32 address;419 u32 final;420 sscanf(p, "%x,%x", &address, &final);422 remotePutPacket("OK");424 remoteResumed = true;425 do426 {427 CPULoop(1);428 if (debugger)429 break;430 }431 while (armNextPC >= address && armNextPC < final);433 remoteResumed = false;435 remoteSendStatus();436 }438 void remoteWriteWatch(char *p, bool active)439 {440 u32 address;441 int count;442 sscanf(p, ",%x,%x#", &address, &count);444 fprintf(stderr, "Write watch for %08x %d\n", address, count);446 if (address < 0x2000000 || address > 0x3007fff)447 {448 remotePutPacket("E01");449 return;450 }452 if (address > 0x203ffff && address < 0x3000000)453 {454 remotePutPacket("E01");455 return;456 }458 u32 final = address + count;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 }471 for (int i = 0; i < count; i++)472 {473 if ((address >> 24) == 2)474 freezeWorkRAM[address & 0x3ffff] = active;475 else476 freezeInternalRAM[address & 0x7fff] = active;477 address++;478 }480 remotePutPacket("OK");481 }483 void remoteReadRegisters(char *p)484 {485 char buffer[1024];487 char *s = buffer;488 int i;489 // regular registers490 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 // PC498 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;503 // floating point registers (24-bit)504 for (i = 0; i < 8; i++)505 {506 sprintf(s, "000000000000000000000000");507 s += 24;508 }510 // FP status register511 sprintf(s, "00000000");512 s += 8;513 // CPSR514 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 }523 void remoteWriteRegister(char *p)524 {525 int r;527 sscanf(p, "%x=", &r);529 p = strchr(p, '=');530 p++;532 char c = *p++;534 u32 v = 0;536 u8 data[4] = {0, 0, 0, 0};538 int i = 0;540 while (c != '#')541 {542 u8 b = 0;543 if (c <= '9')544 b = (c - '0') << 4;545 else546 b = (c + 10 - 'a') << 4;547 c = *p++;548 if (c <= '9')549 b += (c - '0');550 else551 b += (c + 10 - 'a');552 data[i++] = b;553 c = *p++;554 }556 v = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);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 else566 reg[15].I = v + 2;567 }568 remotePutPacket("OK");569 }571 void remoteStubMain()572 {573 if (!debugger)574 return;576 if (remoteResumed)577 {578 remoteSendStatus();579 remoteResumed = false;580 }582 while (true)583 {584 char buffer[1024];585 int res = remoteRecvFnc(buffer, 1024);587 if (res == -1)588 {589 fprintf(stderr, "GDB connection lost\n");590 #ifdef SDL591 dbgMain = debuggerMain;592 dbgSignal = debuggerSignal;593 #endif594 debugger = false;595 break;596 }598 // fprintf(stderr, "Received %s\n", buffer);599 char *p = buffer;600 char c = *p++;601 char pp = '+';602 remoteSendFnc(&pp, 1);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 SDL615 dbgMain = debuggerMain;616 dbgSignal = debuggerSignal;617 #endif618 remoteResumed = true;619 debugger = false;620 return;621 case 'e':622 remoteStepOverRange(p);623 break;624 case 'k':625 remotePutPacket("OK");626 #ifdef SDL627 dbgMain = debuggerMain;628 dbgSignal = debuggerSignal;629 #endif630 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 else678 remotePutPacket("");679 break;680 case 'z':681 if (*p++ == '2')682 {683 remoteWriteWatch(p, false);684 }685 else686 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 }699 void remoteStubSignal(int sig, int number)700 {701 remoteSignal = sig;702 remoteResumed = false;703 remoteSendStatus();704 debugger = true;705 }707 void remoteCleanUp()708 {709 if (remoteCleanUpFnc)710 remoteCleanUpFnc();711 }