Guest User

Link.CPP

a guest
Jan 24th, 2015
168
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.02 KB | None | 0 0
  1. #include "GBA.h"
  2. #include<stdio.h>
  3. #include<afxwin.h>
  4. #include "port.h"
  5. #include "Link.h"
  6. #include "win32/vba.h"
  7. #include "win32/MainWnd.h"
  8.  
  9. #define UPDATE_REG(address, value) WRITE16LE(((u16 *)&ioMem[address]),value)
  10. #define LINK_ID1FINISH 2
  11. #define LINK_ID2FINISH 4
  12. #define GBLINK_READY 8
  13.  
  14. int linktime = 0;
  15. u8 tspeed=3;
  16. u8 transfer=0;
  17. LINKDATA *linkmem=NULL;
  18. int linkid = 1;
  19. HANDLE linksync[4];
  20. extern int *extTicks;
  21. int savedlinktime=0;
  22. char inifile[] = "vba1.ini";
  23. HANDLE mmf=NULL;
  24. char linkevent[] = "VBA link event  ";
  25. static int i, j;
  26. int linktimeout = 500;
  27. int linklog = 0;
  28. FILE *jjj = NULL;
  29. LANLINKDATA lanlink;
  30.  
  31.  
  32. extern unsigned char *gbMemory;
  33. extern int gbInterrupt;
  34.  
  35. int trspeed1[4] = {34080, 8520, 5680, 2840};
  36. int trspeed2[4] = {65536, 16384, 10923, 5461};
  37. int trspeed2_5[4] = {72527, 18132, 12088, 6044};
  38. int trspeed3[4] = {99609, 24903, 16602, 8301};
  39. int trspeed3_5[4] = {106608, 26652, 17768, 8884};
  40. int trspeed4[4] = {133692, 33423, 22282, 11141};
  41. int gbtime = 1024;
  42.  
  43. DWORD WINAPI LanLinkThread(void *);
  44.  
  45. void StartLink(WORD value){
  46.     if(ioMem==NULL)
  47.         return;
  48.     if(!(READ16LE(&ioMem[0x134])&0x8000)){
  49.             switch(value & 0x3000){
  50.             case 0x2000: // Multiplayer
  51.                 if(value & 0x80){
  52.                     if(!linkid){  
  53.                         if(!transfer&&linkmem->numgbas>1){
  54.                             linkmem->linkflags &= !(LINK_ID1FINISH | LINK_ID2FINISH);
  55.                             ResetEvent(linksync[0]);
  56.                             linkmem->linkcmd[0] = ('M'<<8)+(value&3);
  57.                             linkmem->linkdata[0] = READ16LE(&ioMem[0x12a]);
  58.                             transfer = 1;
  59.                             if(linkmem->numtransfers!=0)
  60.                                 savedlinktime = linktime;
  61.                             else
  62.                                 savedlinktime = 0;
  63.                             linktime = 0;
  64.                             tspeed = value & 3;
  65.                             _asm{
  66.                                 mov eax, ioMem;
  67.                                 mov dword ptr [eax+0x120], 0xffffffff;
  68.                                 mov dword ptr [eax+0x124], 0xffffffff;
  69.                             }
  70.                         }
  71.                     } else {
  72.                         value &= 0xff7f;
  73.                         value |= (transfer!=0)<<7;
  74.                     }
  75.                 }
  76.                 value &= 0xffbb;
  77.                 value |= (linkid ? 0xc : 8);
  78.  
  79.                 UPDATE_REG(0x128, value);
  80.             break;
  81.            
  82.             case 0: // Normal 8-bit
  83.                 value |= 4;
  84.                 UPDATE_REG(0x128, value);
  85.                 if(linklog) fprintf(jjj, "Attempt to use 8-bit Normal mode %04x\n", value);
  86.                 break;
  87.  
  88.             case 0x1000: // Normal 32-bit
  89.                 value |= 4;
  90.                 UPDATE_REG(0x128, value);
  91.                 if(linklog) fprintf(jjj, "Attempt to use 32-bit Normal mode %04x %x%x\n", value, READ16LE(&ioMem[0x122]), READ16LE(&ioMem[0x120]));
  92.                 break;
  93.  
  94.             case 0x3000:    // UART
  95.                 if(linklog&&!linkid) fprintf(jjj, "Attempt to use UART mode %04x\n", value);
  96.                 UPDATE_REG(0x128, value);
  97.                 break;
  98.             }
  99.     }
  100. }
  101.  
  102. void StartGPLink(u16 value){
  103.     if(!value){
  104.         UPDATE_REG(0x134, 0);
  105.         return;
  106.     }
  107.     switch(value&0xC000){
  108.     case 0:
  109.     case 0x4000:
  110.         switch(READ16LE(&ioMem[0x128])&0x3000){
  111.         case 0x2000:
  112.             value = READ16LE(&ioMem[0x128]);
  113.             value &= 0xffbb;
  114.             value |= (linkid ? 0xc : 8);
  115.             UPDATE_REG(0x128, value);
  116.             return;
  117.             break;
  118.         }
  119.         break;
  120.     case 0x8000:
  121.         if(linklog)
  122.             if(value==0x8000)
  123.                 fprintf(jjj, "Circuit reset\n");
  124.             else
  125.                 fprintf(jjj, "Attempt to use General-purpose mode %04x\n", value);
  126.         UPDATE_REG(0x134, value);
  127.         break;
  128.     case 0xC000:
  129.         UPDATE_REG(0x134, value);
  130.         break;
  131.     }
  132.     return;
  133. }
  134.  
  135. void StartJOYLink(u16 value){
  136.     if(!value){
  137.         UPDATE_REG(0x140, 0);
  138.         return;
  139.     }
  140.     if(READ16LE(&ioMem[0x134])&0xC000==0xC000){
  141.         if(linklog) fprintf(jjj, "Attempt to use JOY-BUS mode %04x\n", value);
  142.     }
  143.     return;
  144. }
  145.  
  146. void LinkUpdate(void){
  147.     if(linkid){
  148.         savedlinktime = linkmem->lastlinktime;
  149.         if(linkid==1||(linkid==2&&(linkmem->linkflags&LINK_ID1FINISH))||(linkid==3&&(linkmem->linkflags&LINK_ID2FINISH))){
  150.             if(!transfer&&linktime>=savedlinktime&&linkmem->numtransfers){
  151.                 if(linkid==1){
  152.                     linkmem->linkdata[1] = READ16LE(&ioMem[0x12a]);
  153.                 }
  154.                 else
  155.                 if(linkid==2){
  156.                     linkmem->linkflags &= !LINK_ID1FINISH;
  157.                     linkmem->linkdata[2] = READ16LE(&ioMem[0x12a]);
  158.                 }
  159.                 else if(linkid==3){
  160.                     linkmem->linkflags &= !LINK_ID2FINISH;
  161.                     linkmem->linkdata[3] = READ16LE(&ioMem[0x12a]);
  162.                 }
  163.  
  164.                 if(linkmem->numtransfers!=1)
  165.                     linktime -= savedlinktime;
  166.                 else
  167.                     linktime = 0;
  168.  
  169.                 if(linkmem->numtransfers==1&&lanlink.active)
  170.                     linkmem->numtransfers = 2;
  171.  
  172.                 switch((linkmem->linkcmd[0])>>8){
  173.                 case 'M':
  174.                     tspeed = (linkmem->linkcmd[0]) & 3;
  175.                     transfer = 1;
  176.                     _asm{
  177.                         mov eax, ioMem;
  178.                         mov dword ptr [eax+0x120], 0xffffffff;
  179.                         mov dword ptr [eax+0x124], 0xffffffff;
  180.                         or byte ptr [eax+0x128], 0x80;
  181.                     }
  182.                     break;
  183.                 }
  184.             }
  185.         }
  186.     }
  187.    
  188.     if(!transfer) return;
  189.  
  190.     if(transfer == 1 && linktime >= trspeed1[tspeed]){
  191.         UPDATE_REG(0x120, linkmem->linkdata[0]);
  192.         transfer++;
  193.     }
  194.    
  195.     if(transfer == 2 && linktime >= trspeed2[tspeed]){
  196.         if(!linkid){
  197.             linkmem->numtransfers++;
  198.             if(linkmem->numtransfers==0)
  199.                 linkmem->numtransfers=2;
  200.             linkmem->lastlinktime=savedlinktime;
  201.                 SetEvent(linksync[1]);
  202.             WaitForSingleObject(linksync[0], linktimeout);
  203.             ResetEvent(linksync[0]);
  204.         }
  205.         if(linklog)
  206.             fprintf(jjj, "%04x %04x %04x %04x %10u\n",
  207.                 linkmem->linkdata[0], linkmem->linkdata[1], linkmem->linkdata[2], linkmem->linkdata[3], linkmem->lastlinktime);
  208.         UPDATE_REG(0x122, linkmem->linkdata[1]);
  209.         transfer++;
  210.     }
  211.  
  212.     if(transfer == 3 && linktime >= trspeed2_5[tspeed] && linkmem->numgbas==2){
  213.         if(linkid){
  214.             SetEvent(linksync[0]);
  215.             if(WaitForSingleObject(linksync[1], linktimeout)==WAIT_TIMEOUT){
  216.                 linkmem->numtransfers=0;
  217.             }
  218.             ResetEvent(linksync[1]);
  219.         }
  220.         transfer = 0;
  221.         linktime -= trspeed2_5[tspeed];
  222.         if((*(u16*)&ioMem[0x128]) & 0x4000){
  223.             IF |= 0x80;
  224.             UPDATE_REG(0x202, IF);
  225.         }
  226.         UPDATE_REG(0x128, (*(u16 *)&ioMem[0x128] & 0xff0f) | (linkid << 4));
  227.         linkmem->linkdata[linkid] = 0xffff;
  228.     }
  229.    
  230.     if(transfer == 3 && linktime >= trspeed3[tspeed]){
  231.         if(linkid==1){
  232.             linkmem->linkflags |= LINK_ID1FINISH;
  233.             if(linkmem->numtransfers!=1)
  234.                 SetEvent(linksync[2]);
  235.             if(WaitForSingleObject(linksync[1], linktimeout)==WAIT_TIMEOUT){
  236.                 linkmem->numtransfers=0;
  237.             }
  238.             ResetEvent(linksync[1]);
  239.         }
  240.         UPDATE_REG(0x124, linkmem->linkdata[2]);
  241.         transfer++;
  242.     }
  243.  
  244.     if(transfer == 4 && linktime >= trspeed3_5[tspeed] && linkmem->numgbas==3){
  245.         if(linkid==2){
  246.             SetEvent(linksync[0]);
  247.             if(WaitForSingleObject(linksync[2], linktimeout)==WAIT_TIMEOUT){
  248.                 linkmem->numtransfers=0;
  249.             }
  250.         ResetEvent(linksync[2]);
  251.         }
  252.         transfer = 0;
  253.         linktime -= trspeed3_5[tspeed];
  254.         if((*(u16*)&ioMem[0x128]) & 0x4000){
  255.             IF |= 0x80;
  256.             UPDATE_REG(0x202, IF);
  257.         }
  258.         UPDATE_REG(0x128, (*(u16 *)&ioMem[0x128] & 0xff0f) | (linkid << 4));
  259.         linkmem->linkdata[linkid] = 0xffff;
  260.     }
  261.  
  262.     if(transfer == 4 && linktime >= trspeed4[tspeed]){
  263.         if(linkid==2){
  264.             linkmem->linkflags |= LINK_ID2FINISH;
  265.             if(linkmem->numtransfers!=1)
  266.                 SetEvent(linksync[3]);
  267.             if(WaitForSingleObject(linksync[2], linktimeout)==WAIT_TIMEOUT){
  268.                 linkmem->numtransfers=0;
  269.             }
  270.             ResetEvent(linksync[2]);
  271.         }
  272.         UPDATE_REG(0x126, linkmem->linkdata[3]);
  273.         if(linkid==3){
  274.             SetEvent(linksync[0]);
  275.             if(WaitForSingleObject(linksync[3], linktimeout)==WAIT_TIMEOUT){
  276.                 linkmem->numtransfers=0;
  277.             }
  278.         ResetEvent(linksync[3]);
  279.         }
  280.         transfer = 0;
  281.         linktime -= trspeed4[tspeed];
  282.         if((*(u16*)&ioMem[0x128]) & 0x4000){
  283.             IF |= 0x80;
  284.             UPDATE_REG(0x202, IF);
  285.         }
  286.         UPDATE_REG(0x128, (*(u16 *)&ioMem[0x128] & 0xff0f) | (linkid << 4));
  287.         linkmem->linkdata[linkid] = 0xffff;
  288.     }
  289.  
  290. return;
  291. }
  292.  
  293. void gbLinkStart(u8 value){
  294. // Not in this version :-)
  295. }
  296.  
  297.  
  298. void gbLinkUpdate(void){
  299. }
  300.  
  301. int InitLink(void){
  302.     if(lanlink.active){
  303.         WSADATA wsadata;
  304.         WORD version;
  305.         if((linkmem=(LINKDATA*)malloc(sizeof(LINKDATA)))==NULL){
  306.             MessageBox(NULL, "Not enough memory.", "Error!", MB_OK);
  307.             return 0;
  308.         }
  309.         linkid = 0;
  310.         inifile[3]='1';
  311.         lanlink.linkthread = NULL;
  312.        
  313.         version=MAKEWORD(1,1);
  314.         if(WSAStartup(version, &wsadata)!=0){
  315.             WSACleanup();
  316.             return -1;
  317.         }
  318.        
  319.         if((lanlink.serversocket=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))==INVALID_SOCKET){
  320.             MessageBox(NULL, "Couldn't create socket.", "Error!", MB_OK);
  321.             WSACleanup();
  322.             return -1;
  323.         }
  324.  
  325.         for(i=0;i<4;i++){
  326.             if((linksync[i]=CreateEvent(NULL, true, false, NULL))==NULL){
  327.                 closesocket(lanlink.serversocket);
  328.                 WSACleanup();
  329.                 return -1;
  330.             }
  331.         }
  332.  
  333.         lanlink.numgbas = 1;
  334.     } else {
  335.  
  336.         if((mmf=CreateFileMapping((HANDLE)0xffffffff, NULL, PAGE_READWRITE, 0, sizeof(LINKDATA), "VBA link memory"))==NULL){     
  337.             MessageBox(NULL, "Error creating file mapping", "Error", MB_OK|MB_ICONEXCLAMATION);
  338.           return 0;
  339.       }
  340.        
  341.       if(GetLastError() == ERROR_ALREADY_EXISTS)
  342.           linkid = 1;
  343.         else
  344.           linkid = 0;
  345.          
  346.       if((linkmem=(LINKDATA *)MapViewOfFile(mmf, FILE_MAP_WRITE, 0, 0, sizeof(LINKDATA)))==NULL){
  347.           CloseHandle(mmf);
  348.           MessageBox(NULL, "Error mapping file", "Error", MB_OK|MB_ICONEXCLAMATION);
  349.           return 0;
  350.       }
  351.  
  352.       if(linkmem->linkflags&LINK_PARENTLOST)
  353.           linkid = 0;
  354.  
  355.         if(linkid==0){
  356.             inifile[3]='1';
  357.             if(linkmem->linkflags&LINK_PARENTLOST){
  358.                 linkmem->numgbas++;
  359.                 linkmem->linkflags &= !LINK_PARENTLOST;
  360.             }
  361.             else
  362.                 linkmem->numgbas=1;
  363.  
  364.             for(i=0;i<4;i++){
  365.                 linkevent[15]=(char)i+'1';
  366.                 if((linksync[i]=CreateEvent(NULL, true, false, linkevent))==NULL){
  367.                     UnmapViewOfFile(linkmem);
  368.                     CloseHandle(mmf);
  369.                     for(j=0;j<i;j++){
  370.                         CloseHandle(linksync[j]);
  371.                     }
  372.                     MessageBox(NULL, "Error opening event", "Error", MB_OK|MB_ICONEXCLAMATION);
  373.                     return 0;
  374.                 }
  375.             }
  376.         } else {
  377.             linkid=linkmem->numgbas;
  378.             linkmem->numgbas++;
  379.             linklog = 0;
  380.             if(linkmem->numgbas>4){
  381.                 linkmem->numgbas=4;
  382.                 MessageBox(NULL, "5 or more GBAs not supported.", "Error!", MB_OK|MB_ICONEXCLAMATION);
  383.                 UnmapViewOfFile(linkmem);
  384.                 CloseHandle(mmf);
  385.                 return 0;
  386.             }
  387.             inifile[3]=(char)linkmem->numgbas+'0';
  388.             for(i=0;i<4;i++){
  389.                 linkevent[15]=(char)i+'1';
  390.                 if((linksync[i]=OpenEvent(EVENT_ALL_ACCESS, false, linkevent))==NULL){
  391.                     CloseHandle(mmf);
  392.                     UnmapViewOfFile(linkmem);
  393.                     for(j=0;j<i;j++){
  394.                         CloseHandle(linksync[j]);
  395.                     }
  396.                     MessageBox(NULL, "Error opening event", "Error", MB_OK|MB_ICONEXCLAMATION);
  397.                     return 0;
  398.                 }
  399.             }
  400.         }
  401.     }  
  402.     linkmem->lastlinktime=0xffffffff;
  403.     linkmem->numtransfers=0;
  404.     linkmem->linkflags=0;
  405.     for(i=0;i<4;i++)
  406.         linkmem->linkdata[i] = 0xffff;
  407.  
  408.    
  409.  
  410. return 1;
  411. }
  412.  
  413. void CloseLanLink(void){
  414.     char buffer[8];
  415.     buffer[0] = 'S';
  416.     send(lanlink.serversocket, buffer, 8, 0);
  417.     closesocket(lanlink.serversocket);
  418.     free(linkmem);
  419.     WSACleanup();
  420.     for(i=0;i<4;i++)
  421.         CloseHandle(linksync[i]);
  422.     if(lanlink.linkthread!=NULL) CloseHandle(lanlink.linkthread);
  423.     if(linklog) fclose(jjj);
  424. }
  425.  
  426. void CloseLink(void){
  427.     if(lanlink.active){
  428.         CloseLanLink();
  429.         return;
  430.     }
  431.     linkmem->numgbas--;
  432.     if(!linkid&&linkmem->numgbas!=0)
  433.         linkmem->linkflags|=LINK_PARENTLOST;
  434.     CloseHandle(mmf);
  435.     UnmapViewOfFile(linkmem);
  436.  
  437.     for(i=0;i<4;i++){
  438.         if(linksync[i]!=NULL){
  439.             PulseEvent(linksync[i]);
  440.             CloseHandle(linksync[i]);
  441.         }
  442.     }
  443.     if(linklog&&!linkid) fclose(jjj);
  444. return;
  445. }
  446.  
  447. int LanConnect(void){
  448.     DWORD ehh;
  449.     LPHOSTENT hostentry;
  450.     SOCKADDR_IN serverinfo;
  451.     if(lanlink.linkthread!=NULL){
  452.         CloseHandle(lanlink.linkthread);
  453.         lanlink.linkthread = NULL;
  454.     }
  455.    
  456.     hostentry = gethostbyaddr((const char *)&lanlink.serveraddress, sizeof(IN_ADDR), AF_INET);
  457.     if(hostentry==NULL){
  458.         return WSAGetLastError();
  459.     }
  460.  
  461.     ZeroMemory(&serverinfo, sizeof(SOCKADDR_IN));
  462.     serverinfo.sin_family = AF_INET;
  463.     serverinfo.sin_port = htons(6477 + lanlink.numgbas);
  464.     serverinfo.sin_addr = *((LPIN_ADDR)*hostentry->h_addr_list);
  465.  
  466.     if(connect(lanlink.serversocket, (LPSOCKADDR)&serverinfo, sizeof(SOCKADDR))==SOCKET_ERROR){
  467.         return WSAGetLastError();
  468.     }
  469.  
  470.     ResetEvent(linksync[1]);
  471.     ResetEvent(linksync[0]);
  472.  
  473.     if((lanlink.linkthread=CreateThread(NULL, 0, LanLinkThread, NULL, 0, &ehh))==NULL){
  474.         return -1;
  475.     }
  476.    
  477.     return 0;
  478. }
  479.  
  480. DWORD WINAPI LanLinkThread(void *number){
  481.     SOCKET mysocket = lanlink.serversocket;
  482.     int numbytes = 0, howmuch, whatwait;
  483.     char *inbuffer, outbuffer[32], *oldbuffer;
  484.  
  485.     inbuffer = (char*)malloc(32);
  486.  
  487.     oldbuffer = inbuffer;
  488.    
  489.     while(numbytes<4){
  490.         numbytes += recv(mysocket, inbuffer+numbytes, 4, 0);
  491.     }
  492.  
  493.     numbytes = 0;
  494.    
  495.     MessageBox(NULL, "Connected.", "Link", MB_OK);
  496.    
  497.     linkid = inbuffer[0];
  498.  
  499.     linkmem->numgbas = lanlink.numgbas + 1;
  500.    
  501.     howmuch = (lanlink.numgbas)<<2;
  502.     if(linkid) howmuch += 4;
  503.  
  504.     if(linkid == lanlink.numgbas)
  505.         whatwait = 0;
  506.     else
  507.         whatwait = linkid + 1;
  508.  
  509.     linkmem->numtransfers = 0;
  510.  
  511.     if(!linkid) goto firstloop;
  512.    
  513.     while(true){
  514.        
  515.         numbytes = 0;
  516.  
  517.         while(numbytes<howmuch)
  518.             numbytes += recv(mysocket, inbuffer+numbytes, 32, 0);
  519.        
  520.         while(numbytes){
  521.             switch((inbuffer[0])&0x80){
  522.             case 0:
  523.                 switch(inbuffer[0]){
  524.                 case 'M':
  525.                     linkmem->linkdata[((inbuffer[1])&0xc0)>>6] = *((u16*)inbuffer+1);
  526.                     linkmem->linkcmd[0] = ntohs(*(u16*)inbuffer);
  527.                     if(linkid==2)
  528.                         linkmem->linkflags |= LINK_ID1FINISH;
  529.                     if(linkid==3){
  530.                         linkmem->linkflags |= LINK_ID1FINISH;
  531.                         linkmem->linkflags |= LINK_ID2FINISH;
  532.                     }
  533.                     break;
  534.                 case 'S':
  535.                     MessageBox(NULL, "Remote player disconnected.", "Link", MB_OK);
  536.                     linkmem->numgbas = 1;
  537.                     CloseHandle(lanlink.linkthread);
  538.                     lanlink.linkthread = NULL;
  539.                     ExitThread(0);
  540.                     break;
  541.                 default:
  542.                     MessageBox(NULL, "Unknown transfer mode", "Error!", MB_OK);
  543.                     break;
  544.                 }
  545.                 break;
  546.             case 0x80:
  547.                 inbuffer[0] &= 0x7f;
  548.                 linkmem->lastlinktime = ntohl(*(int*)inbuffer);
  549.                 break;
  550.             }
  551.             numbytes -= 4;
  552.             inbuffer += 4;
  553.         }
  554.        
  555.         inbuffer = oldbuffer;
  556.  
  557.         if(linkid&&(++linkmem->numtransfers)==0){
  558.             linkmem->numtransfers = 2;
  559.         }
  560.        
  561.         SetEvent(linksync[linkid]);
  562. firstloop:
  563.         WaitForSingleObject(linksync[whatwait], INFINITE);
  564.         ResetEvent(linksync[whatwait]);
  565.        
  566.         outbuffer[0] = (linkmem->linkcmd[0])>>8;
  567.         outbuffer[1] = tspeed | (linkid << 6);
  568.         *((u16*)outbuffer+1) = linkmem->linkdata[linkid];
  569.  
  570.         if(linkid){
  571.             send(mysocket, outbuffer, 4, 0);
  572.         }
  573.         else {
  574.             *((int*)outbuffer+1) = htonl(linkmem->lastlinktime);
  575.             outbuffer[4] |= 0x80;
  576.             send(mysocket, outbuffer, 8, 0);
  577.         }
  578.        
  579.     }
  580.     return 0;
  581. }
Advertisement
Add Comment
Please, Sign In to add comment