diff --git a/Source/Core/Common/Src/IniFile.cpp b/Source/Core/Common/Src/IniFile.cpp index 244d06a161..325b87278a 100644 --- a/Source/Core/Common/Src/IniFile.cpp +++ b/Source/Core/Common/Src/IniFile.cpp @@ -119,6 +119,22 @@ void IniFile::Section::Set(const char* key, const float newValue, const float de Delete(key); } +void IniFile::Section::Set(const char* key, int newValue, int defaultValue) +{ + if (newValue != defaultValue) + Set(key, newValue); + else + Delete(key); +} + +void IniFile::Section::Set(const char* key, bool newValue, bool defaultValue) +{ + if (newValue != defaultValue) + Set(key, newValue); + else + Delete(key); +} + void IniFile::Section::Set(const char* key, const std::vector& newValues) { std::string temp; diff --git a/Source/Core/Common/Src/IniFile.h b/Source/Core/Common/Src/IniFile.h index 1b214edf86..05eff76cdd 100644 --- a/Source/Core/Common/Src/IniFile.h +++ b/Source/Core/Common/Src/IniFile.h @@ -56,9 +56,13 @@ public: void Set(const char* key, double newValue) { Set(key, StringFromFormat("%f", newValue).c_str()); } + + void Set(const char* key, int newValue, int defaultValue); void Set(const char* key, int newValue) { Set(key, StringFromInt(newValue).c_str()); } + + void Set(const char* key, bool newValue, bool defaultValue); void Set(const char* key, bool newValue) { Set(key, StringFromBool(newValue).c_str()); } diff --git a/Source/Core/InputCommon/Src/UDPWiimote.cpp b/Source/Core/InputCommon/Src/UDPWiimote.cpp index fc3b8603e7..467ea44745 100644 --- a/Source/Core/InputCommon/Src/UDPWiimote.cpp +++ b/Source/Core/InputCommon/Src/UDPWiimote.cpp @@ -18,7 +18,6 @@ #else -#include #include #include #include @@ -38,7 +37,9 @@ #endif #include "Thread.h" +#include "Timer.h" #include +#include #include #include @@ -46,8 +47,9 @@ struct UDPWiimote::_d { Common::Thread * thread; std::list sockfds; - Common::CriticalSection termLock,mutex; + Common::CriticalSection termLock,mutex,nameMutex; volatile bool exit; + sock_t bipv4_fd,bipv6_fd; }; int UDPWiimote::noinst=0; @@ -55,7 +57,6 @@ int UDPWiimote::noinst=0; void _UDPWiiThread(void* arg) { ((UDPWiimote*)arg)->mainThread(); - //NOTICE_LOG(WIIMOTE,"UDPWii thread stopped"); } THREAD_RETURN UDPWiiThread(void* arg) @@ -64,11 +65,20 @@ THREAD_RETURN UDPWiiThread(void* arg) return 0; } -UDPWiimote::UDPWiimote(const char *_port) : - port(_port), +UDPWiimote::UDPWiimote(const char *_port, const char * name, int _index) : + port(_port), displayName(name), d(new _d) ,x(0),y(0),z(0),naX(0),naY(0),naZ(0),nunX(0),nunY(0), - pointerX(-0.1),pointerY(-0.1),nunMask(0),mask(0),time(0) + pointerX(-0.1),pointerY(-0.1),nunMask(0),mask(0),index(_index), int_port(atoi(_port)) { + + static bool sranded=false; + if (!sranded) + { + srand(time(0)); + sranded=true; + } + bcastMagic=rand() & 0xFFFF; + #ifdef _WIN32 u_long iMode = 1; #endif @@ -87,13 +97,18 @@ UDPWiimote::UDPWiimote(const char *_port) : #endif noinst++; - //PanicAlert("UDPWii instantiated"); memset(&hints, 0, sizeof hints); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_PASSIVE; // use my IP + if (!int_port){ + cleanup; + err=-1; + return; + } + if ((rv = getaddrinfo(NULL, _port, &hints, &servinfo)) != 0) { cleanup; err=-1; @@ -106,14 +121,10 @@ UDPWiimote::UDPWiimote(const char *_port) : if ((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == BAD_SOCK) { continue; } - if (bind(sock, p->ai_addr, p->ai_addrlen) == -1) { close(sock); continue; } - - - //NOTICE_LOG(WIIMOTE,"UDPWii new listening sock"); d->sockfds.push_back(sock); } @@ -126,7 +137,8 @@ UDPWiimote::UDPWiimote(const char *_port) : freeaddrinfo(servinfo); err=0; d->exit=false; -// NOTICE_LOG(WIIMOTE,"UDPWii thread starting"); + initBroadcastIPv4(); + initBroadcastIPv6(); d->termLock.Enter(); d->thread = new Common::Thread(UDPWiiThread,this); d->termLock.Leave(); @@ -136,12 +148,12 @@ UDPWiimote::UDPWiimote(const char *_port) : void UDPWiimote::mainThread() { d->termLock.Enter(); -// NOTICE_LOG(WIIMOTE,"UDPWii thread started"); + Common::Timer time; fd_set fds; struct timeval timeout; - timeout.tv_sec=1; - timeout.tv_usec=500000; - //Common::Thread * thisthr= d->thread; + timeout.tv_sec=0; + timeout.tv_usec=0; + time.Update(); do { int maxfd=0; @@ -154,12 +166,28 @@ void UDPWiimote::mainThread() maxfd=(*i)+1; #endif } - d->termLock.Leave(); - if (d->exit) return; + + u64 tleft=timeout.tv_sec*1000+timeout.tv_usec/1000; + u64 telapsed=time.GetTimeDifference(); + time.Update(); + if (tleft<=telapsed) + { + timeout.tv_sec=1; + timeout.tv_usec=500000; + broadcastPresence(); + } else { + tleft-=telapsed; + timeout.tv_sec=tleft/1000; + timeout.tv_usec=(tleft%1000)*1000; + } + + d->termLock.Leave(); //VERY hacky. don't like it + if (d->exit) return; int rt=select(maxfd,&fds,NULL,NULL,&timeout); if (d->exit) return; d->termLock.Enter(); if (d->exit) return; + if (rt) { for (std::list::iterator i=d->sockfds.begin(); i!=d->sockfds.end(); i++) @@ -171,7 +199,9 @@ void UDPWiimote::mainThread() size_t addr_len; struct sockaddr_storage their_addr; addr_len = sizeof their_addr; - if ((size = recvfrom(fd, (dataz)bf, size , 0,(struct sockaddr *)&their_addr, (socklen_t*)&addr_len)) == -1) + if ((size = recvfrom(fd, + (dataz)bf, + size , 0,(struct sockaddr *)&their_addr, (socklen_t*)&addr_len)) == -1) { ERROR_LOG(WIIMOTE,"UDPWii Packet error"); } @@ -187,12 +217,9 @@ void UDPWiimote::mainThread() d->mutex.Leave(); } } - } else { - broadcastPresence(); } } while (!(d->exit)); d->termLock.Leave(); - //delete thisthr; } UDPWiimote::~UDPWiimote() @@ -203,9 +230,10 @@ UDPWiimote::~UDPWiimote() d->termLock.Leave(); for (std::list::iterator i=d->sockfds.begin(); i!=d->sockfds.end(); i++) close(*i); + close(d->bipv4_fd); + close(d->bipv6_fd); cleanup; delete d; - //PanicAlert("UDPWii destructed"); } #define ACCEL_FLAG (1<<0) @@ -219,11 +247,11 @@ int UDPWiimote::pharsePacket(u8 * bf, size_t size) if (size<3) return -1; if (bf[0]!=0xde) return -1; - if (bf[1]==0) - time=0; - if (bf[1]bipv4_fd=socket(AF_INET, SOCK_DGRAM, 0); + if (d->bipv4_fd == BAD_SOCK) + { + WARN_LOG(WIIMOTE,"socket() failed"); + return; + } + + int broad=1; + if (setsockopt(d->bipv4_fd,SOL_SOCKET,SO_BROADCAST, &broad, sizeof broad) == -1) + { + WARN_LOG(WIIMOTE,"setsockopt(SO_BROADCAST) failed"); + return; + } +} + +void UDPWiimote::broadcastIPv4(const void * data, size_t size) +{ + + struct sockaddr_in their_addr; + their_addr.sin_family = AF_INET; + their_addr.sin_port = htons(4431); + their_addr.sin_addr.s_addr = INADDR_BROADCAST; + memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero); + + int num; + if ((num=sendto(d->bipv4_fd,(const dataz)data,size,0,(struct sockaddr *) &their_addr, sizeof their_addr)) == -1) + { + WARN_LOG(WIIMOTE,"sendto() failed"); + return; + } +} + +void UDPWiimote::initBroadcastIPv6() +{ + //TODO: IPv6 support +} + +void UDPWiimote::broadcastIPv6(const void * data, size_t size) +{ + //TODO: IPv6 support +} + void UDPWiimote::broadcastPresence() { -// NOTICE_LOG(WIIMOTE,"UDPWii broadcasting presence"); + size_t slen; + u8 bf[512]; + bf[0]=0xdf; //magic number + *((u16*)(&(bf[1])))=htons(bcastMagic); //unique per-wiimote 16-bit ID + bf[3]=(u8)index; //wiimote index + *((u16*)(&(bf[4])))=htons(int_port); //port + d->nameMutex.Enter(); + slen=displayName.size(); + if (slen>=256) + slen=255; + bf[6]=(u8)slen; //display name size (max 255) + memcpy(&(bf[7]),displayName.c_str(),slen); //display name + d->nameMutex.Leave(); + broadcastIPv4(bf,7+slen); + broadcastIPv6(bf,7+slen); } void UDPWiimote::getAccel(float &_x, float &_y, float &_z) @@ -281,7 +367,6 @@ void UDPWiimote::getAccel(float &_x, float &_y, float &_z) _y=(float)y; _z=(float)z; d->mutex.Leave(); - //NOTICE_LOG(WIIMOTE,"%lf %lf %lf",_x, _y, _z); } u32 UDPWiimote::getButtons() @@ -324,3 +409,11 @@ const char * UDPWiimote::getPort() { return port.c_str(); } + + +void UDPWiimote::changeName(const char * name) +{ + d->nameMutex.Enter(); + displayName=name; + d->nameMutex.Leave(); +} diff --git a/Source/Core/InputCommon/Src/UDPWiimote.h b/Source/Core/InputCommon/Src/UDPWiimote.h index 69cb57c06c..c1c39b2887 100644 --- a/Source/Core/InputCommon/Src/UDPWiimote.h +++ b/Source/Core/InputCommon/Src/UDPWiimote.h @@ -22,7 +22,7 @@ class UDPWiimote { public: - UDPWiimote(const char * port); + UDPWiimote(const char * port, const char * name, int index); virtual ~UDPWiimote(); void getAccel(float &x, float &y, float &z); u32 getButtons(); @@ -31,8 +31,9 @@ public: void getNunchuckAccel(float &x, float &y, float &z); int getErrNo() {return err;}; const char * getPort(); + void changeName(const char * name); private: - std::string port; + std::string port,displayName; int pharsePacket(u8 * data, size_t size); void mainThread(); struct _d; //using pimpl because Winsock2.h doesen't have include guards -_- @@ -43,10 +44,16 @@ private: double pointerX,pointerY; u8 nunMask; u32 mask; + u16 bcastMagic; int err; + int index; + int int_port; static int noinst; friend void _UDPWiiThread(void* arg); void broadcastPresence(); - u8 time; + void broadcastIPv4(const void * data, size_t size); + void broadcastIPv6(const void * data, size_t size); + void initBroadcastIPv4(); + void initBroadcastIPv6(); }; #endif diff --git a/Source/Core/InputCommon/Src/UDPWrapper.cpp b/Source/Core/InputCommon/Src/UDPWrapper.cpp index 20ae3ade19..6003119a92 100644 --- a/Source/Core/InputCommon/Src/UDPWrapper.cpp +++ b/Source/Core/InputCommon/Src/UDPWrapper.cpp @@ -69,7 +69,7 @@ void UDPWrapper::Refresh() if (strcmp(inst->getPort(),port.c_str())) { delete inst; - inst= new UDPWiimote(port.c_str()); + inst= new UDPWiimote(port.c_str(),"Dolphin-Emu",index); //TODO: Changeable display name } return; } @@ -81,7 +81,7 @@ void UDPWrapper::Refresh() return; } //else - inst= new UDPWiimote(port.c_str()); + inst= new UDPWiimote(port.c_str(),"Dolphin-Emu",index); } UDPWrapper::~UDPWrapper()