gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Getting stuff onto the DS pronto

#166713 - Pete_Lockwood - Sun Feb 15, 2009 6:54 pm

So after switching the MicroSD out of my DSTT and into a card reader, copying the file across and moving the card back to the DSTT about three times I got bored.

I took a quick look around, because I figured I wasn't the only one that might be driven insane by this process, and sure enough there are a bunch of posts on the subject but lots dead links and inelegant solutions abound.

In the end I just cooked something up myself to pass the file through my wireless router - a couple of tiny applications, one on the PC side and one on the DS. Just drag-and-drop the file I want sent onto the PC application (or run it from a Makefile) and run up the receiver application on the DS.

Is anyone using anything much better that doesn't need me to configure the DS wireless and doesn't involve running a webserver or FTP server on the PC? If so, links plz?
_________________
It's not an illusion, it just looks like one.

#166792 - RickA - Wed Feb 18, 2009 8:46 am

I guess not. But I'd be more than interested in hearing details about how you did it.

#166796 - Pete_Lockwood - Wed Feb 18, 2009 11:45 am

OK.. This is the sender, which lives on the PC. Nothing fancy, nothing clever.

Code:

#include <winsock2.h>
#include <stdio.h>

#define DEFAULT_PORT 21
#define DEFAULT_BUFFER_SIZE 4096

int main(int argc, char* argv[])
{
   if(argc < 2)
      return 0;

   printf("Preparing to send %s\n", argv[1]);

   char Buffer[DEFAULT_BUFFER_SIZE + 1];

    WSAData wsd;

    if(WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
   {
        printf("Winsock not initialised!\n");
        return -1;
    }

    SOCKET ls = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ls == INVALID_SOCKET)
   {
        printf("Invalid socket!\n");
        return -1;
    }

    sockaddr_in service;
    memset(&service, 0, sizeof(service));
    service.sin_family = AF_INET;
    service.sin_addr.s_addr = INADDR_ANY;
   service.sin_port = htons(DEFAULT_PORT);

   if (bind(ls, (SOCKADDR*) &service, sizeof(service)) == SOCKET_ERROR)
   {
      printf("bind error!\n");
      return -1;
   }

   printf("Waiting for connection...\n");

   if (listen(ls, 1) == SOCKET_ERROR)
   {
      printf("listen() error!\n");
      return -1;
   }

   SOCKET as;

   while (1)
   {
      as = accept(ls, NULL, NULL);
      if (as == SOCKET_ERROR)
      {
         continue;
      }

      printf("Sending %s", argv[1]);

      int namelen = strlen(argv[1]) + 1;
      send(as, (char *)&namelen, 4, 0);
      send(as, argv[1], namelen, 0);

      FILE *inf;
      fopen_s(&inf, argv[1], "rb");

      fseek(inf, 0, SEEK_END);
      int totbytes = ftell(inf);
      send(as, (char *)&totbytes, 4, 0);
      fseek(inf, 0, SEEK_SET);

      int len, sent;
      char *pos;

      while(!feof(inf))
      {
         len = fread(Buffer, 1, DEFAULT_BUFFER_SIZE, inf);
         pos = Buffer;

         while(len)
         {
            sent = send(as, Buffer, len, 0);
            len -= sent;
            pos += sent;
         }
      }
      fclose(inf);
      break;
   }

   closesocket(as);
   closesocket(ls);
   WSACleanup();

   return 0;
}

_________________
It's not an illusion, it just looks like one.

#166797 - Pete_Lockwood - Wed Feb 18, 2009 11:46 am

This is the reciever, lives on the DS. There are a few #defines at the top, which provide the important info - and note I didn't bother dealing with WEP, although adding that shouldn't be a big deal.

Code:

#include <nds.h>
#include <stdio.h>
#include <string.h>
#include <dswifi9.h>

#include <sys/types.h>
#include <netinet/in.h>

#include <sys/socket.h>
#include <netdb.h>

#include <fat.h>

#define SERVER_ADDRESS "192.168.2.2"
#define PREFERRED_ROUTER "belkin54g"
#define DESTINATION_FOLDER "fat1:/games/"
#define BUFFER_SIZE 4096

void findAP(Wifi_AccessPoint *ap) {
   int selected = 0; 
   int i;
   int count = 0;

   Wifi_ScanMode();
   while(!(keysDown() & KEY_A)) {
      scanKeys();

      count = Wifi_GetNumAP();
      consoleClear();
      iprintf("Number of APs found: %d\n", count);

      for(i = 0; i < count; i++) {
         Wifi_GetAPData(i, ap);

          iprintf("%s %s Wep:%s Sig:%i\n",
             i == selected ? "*" : " ",
            ap->ssid,
             ap->flags & WFLAG_APDATA_WEP ? "Yes " : "No ",
             ap->rssi * 100 / 0xD0);

         if(!strcmp(ap->ssid,PREFERRED_ROUTER))
         {
            Wifi_GetAPData(i, ap);
            return;
         }
      }
      if(keysDown() & KEY_UP && selected >0 ) selected--;
      if(keysDown() & KEY_DOWN && selected < (count-1)) selected++;
      swiWaitForVBlank();
   }
   Wifi_GetAPData(selected, ap);
}

void readdata(int my_socket, char *filename, int totbytes)
{
    fd_set readfd;
    struct timeval stTime;
    stTime.tv_sec = 2;
    stTime.tv_usec = 0;
   int iRet;
   int recvd_len;
    char incoming_buffer[BUFFER_SIZE];

   fatInitDefault();
   iprintf("Writing %s", filename);
   FILE *outf = fopen(filename, "wb");

   while( totbytes )
    {
      swiWaitForVBlank();

      FD_ZERO( &readfd );
      FD_SET( my_socket, &readfd );
        iRet = select( my_socket + 1, &readfd, NULL, NULL, &stTime );
        if( iRet > 0 )
        {
            recvd_len = recv( my_socket, incoming_buffer, sizeof(incoming_buffer), 0 );
         iprintf(".");
            if( recvd_len > 0 )
            {
            fwrite(incoming_buffer, 1, recvd_len, outf);
            totbytes -= recvd_len;
         }
        }
        else if( iRet == 0 )
        {
         iprintf("\nTimed out!\n");
            break;
        }
        else
        {
            iprintf( "\nError!!\n" );
            break;
        }
    }
   fclose(outf);
   iprintf("\nDone\n");
}

int main(void) {
   Wifi_AccessPoint ap;

   int status = ASSOCSTATUS_DISCONNECTED;
   int oldStatus;

   consoleDemoInit();
   Wifi_InitDefault(false);
   findAP(&ap);
   consoleClear();
   iprintf("Connecting to %s\n", ap.ssid);

   //use dhcp
   Wifi_SetIP(0,0,0,0,0);   
   Wifi_ConnectAP(&ap, WEPMODE_NONE, 0, 0);

   while(status != ASSOCSTATUS_ASSOCIATED && status != ASSOCSTATUS_CANNOTCONNECT) {
      oldStatus = status;
      status = Wifi_AssocStatus();
      if(oldStatus != status)
         iprintf("\n%s", ASSOCSTATUS_STRINGS[status]);
      else
         iprintf(".");
      swiWaitForVBlank();
   }

    struct sockaddr_in sain;
    sain.sin_family = AF_INET;
    sain.sin_port = htons(21);
    sain.sin_addr.s_addr = inet_addr( SERVER_ADDRESS );
   
    // Create TCP socket
    int my_socket = socket( AF_INET, SOCK_STREAM, 0 );
    connect( my_socket,(struct sockaddr *)&sain, sizeof(sain) );
    iprintf("\n\nConnected\n");

   int namelen;
   swiWaitForVBlank();
   recv( my_socket, &namelen, 4, 0 );

   char filename[namelen];
   swiWaitForVBlank();
   recv( my_socket, filename, namelen, 0 );

   int totbytes;
   swiWaitForVBlank();
   recv( my_socket, &totbytes, 4, 0 );

   iprintf("Receiving %d bytes from %s\n", totbytes, filename);

   char *pos = filename + namelen;
   while(pos > filename)
   {
      if(*pos == '\\')
      {
         pos++;
         break;
      }
      pos--;
   }
   char outfilename[1024];
   sprintf(outfilename, "%s%s", DESTINATION_FOLDER, pos);

   readdata(my_socket, outfilename, totbytes);
   return 0;
}

_________________
It's not an illusion, it just looks like one.

#166798 - Pete_Lockwood - Wed Feb 18, 2009 11:50 am

So you just run both up, in no particular order, and the file will be transferred across to the SD card. If you send something like "c:\my stuff\mything.nds" it does a simple strip to work out that the filename is mything.nds and places that in the directory controlled by the #define in the receiver.

Clearly it would be easy to extend this to be more flexible, broadcast from the DS to find the sender app without knowing the IP address, have the sender specify the destination folder etc. but I don't need any of that.
_________________
It's not an illusion, it just looks like one.

#168196 - silent_code - Tue Apr 14, 2009 3:29 pm

Thanks. :^D
_________________
July 5th 08: "Volumetric Shadow Demo" 1.6.0 (final) source released
June 5th 08: "Zombie NDS" WIP released!
It's all on my page, just click WWW below.

#168197 - azaydius - Tue Apr 14, 2009 3:42 pm

What kind of transfer speeds are you getting with this?
_________________
fileNinja - https://sourceforge.net/projects/fileninja/

#168199 - samel - Tue Apr 14, 2009 5:28 pm

You can just try mine

http://donotjava.netsons.org/?page_id=34

and if you have some comments/improvements we can collaborate to make only one tool together.

#168202 - Pete_Lockwood - Wed Apr 15, 2009 12:18 am

azaydius wrote:
What kind of transfer speeds are you getting with this?


Dunno exactly. I've since killed my default arm7 binary and wifi library and I'm too lazy to download them again at the moment to compile in something that'll give me a proper measurement.

Doing a very simple estimate based on filesize and seconds elapsed it's something a shade over 50 kilobytes per second. You could remove the swiWaitForVBlank in the main reader loop and probably squeeze some more out of it.


samel wrote:
You can just try mine
and if you have some comments/improvements we can collaborate to make only one tool together.


I didn't set out to compete, I just couldn't find anything simple so I spent 20 minutes and made my own. I have no plans to do anything more on my solution so by all means improve away.
_________________
It's not an illusion, it just looks like one.