mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-15 15:30:29 +02:00
Merge branch 'adhoc-support' of https://github.com/Kyhel/ppsspp into Kyhel-adhoc-support
hrydgard here: I switched to our implementation of thread.h and removed the "Windows7SDK" things for now. Conflicts: Core/Core.vcxproj.filters
This commit is contained in:
commit
c499be9769
14 files changed
+3338
-368
No files matched your search
@@ -873,6 +873,8 @@ add_library(${CoreLibName} ${CoreLinkType}
|
||||
Core/HLE/sceNet.h
|
||||
Core/HLE/sceNetAdhoc.cpp
|
||||
Core/HLE/sceNetAdhoc.h
|
||||
Core/HLE/proAdhoc.h
|
||||
Core/HLE/proAdhoc.cpp
|
||||
Core/HLE/sceOpenPSID.cpp
|
||||
Core/HLE/sceOpenPSID.h
|
||||
Core/HLE/sceP3da.cpp
|
||||
|
||||
@@ -297,6 +297,8 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
|
||||
|
||||
IniFile::Section *pspConfig = iniFile.GetOrCreateSection("SystemParam");
|
||||
pspConfig->Get("NickName", &sNickName, "PPSSPP");
|
||||
pspConfig->Get("proAdhocServer", &proAdhocServer, "localhost");
|
||||
pspConfig->Get("MacAddress", &localMacAddress, "01:02:03:04:05:06");
|
||||
pspConfig->Get("Language", &iLanguage, PSP_SYSTEMPARAM_LANGUAGE_ENGLISH);
|
||||
pspConfig->Get("TimeFormat", &iTimeFormat, PSP_SYSTEMPARAM_TIME_FORMAT_24HR);
|
||||
pspConfig->Get("DateFormat", &iDateFormat, PSP_SYSTEMPARAM_DATE_FORMAT_YYYYMMDD);
|
||||
@@ -521,6 +523,8 @@ void Config::Save() {
|
||||
|
||||
IniFile::Section *pspConfig = iniFile.GetOrCreateSection("SystemParam");
|
||||
pspConfig->Set("NickName", sNickName.c_str());
|
||||
pspConfig->Set("proAdhocServer", proAdhocServer.c_str());
|
||||
pspConfig->Set("MacAddress", localMacAddress.c_str());
|
||||
pspConfig->Set("Language", iLanguage);
|
||||
pspConfig->Set("TimeFormat", iTimeFormat);
|
||||
pspConfig->Set("DateFormat", iDateFormat);
|
||||
|
||||
@@ -203,6 +203,8 @@ public:
|
||||
|
||||
// SystemParam
|
||||
std::string sNickName;
|
||||
std::string proAdhocServer;
|
||||
std::string localMacAddress;
|
||||
int iLanguage;
|
||||
int iTimeFormat;
|
||||
int iDateFormat;
|
||||
|
||||
@@ -195,6 +195,7 @@
|
||||
<ClCompile Include="HDRemaster.cpp" />
|
||||
<ClCompile Include="HLE\HLE.cpp" />
|
||||
<ClCompile Include="HLE\HLETables.cpp" />
|
||||
<ClCompile Include="HLE\proAdhoc.cpp" />
|
||||
<ClCompile Include="HLE\sceAtrac.cpp" />
|
||||
<ClCompile Include="HLE\sceAudio.cpp" />
|
||||
<ClCompile Include="HLE\sceAudiocodec.cpp" />
|
||||
@@ -451,6 +452,7 @@
|
||||
<ClInclude Include="HLE\HLE.h" />
|
||||
<ClInclude Include="HLE\HLETables.h" />
|
||||
<ClInclude Include="HLE\KernelWaitHelpers.h" />
|
||||
<ClInclude Include="HLE\proAdhoc.h" />
|
||||
<ClInclude Include="HLE\sceAtrac.h" />
|
||||
<ClInclude Include="HLE\sceAudio.h" />
|
||||
<ClInclude Include="HLE\sceAudiocodec.h" />
|
||||
|
||||
@@ -499,6 +499,9 @@
|
||||
<ClCompile Include="Debugger\DisassemblyManager.cpp">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HLE\proAdhoc.cpp">
|
||||
<Filter>HLE\Libraries</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ELF\ElfReader.h">
|
||||
@@ -924,6 +927,9 @@
|
||||
<ClInclude Include="Debugger\DisassemblyManager.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HLE\proAdhoc.h">
|
||||
<Filter>HLE\Libraries</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
@@ -931,4 +937,4 @@
|
||||
<None Include="..\android\jni\Android.mk" />
|
||||
<None Include="GameLogNotes.txt" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -18,6 +18,11 @@
|
||||
#include "PSPNetconfDialog.h"
|
||||
#include "ChunkFile.h"
|
||||
#include "../Core/MemMap.h"
|
||||
#include "../Core/HLE/sceNetAdhoc.h"
|
||||
|
||||
#define NETCONF_CONNECT_ADHOC 2
|
||||
#define NETCONF_CREATE_ADHOC 4
|
||||
#define NETCONF_JOIN_ADHOC 5
|
||||
|
||||
PSPNetconfDialog::PSPNetconfDialog() {
|
||||
}
|
||||
@@ -40,6 +45,19 @@ int PSPNetconfDialog::Init(u32 paramAddr) {
|
||||
}
|
||||
|
||||
int PSPNetconfDialog::Update(int animSpeed) {
|
||||
if(request.netAction == NETCONF_CONNECT_ADHOC ||
|
||||
request.netAction == NETCONF_CREATE_ADHOC ||
|
||||
request.netAction == NETCONF_JOIN_ADHOC){
|
||||
if(request.NetconfData != NULL){
|
||||
Shutdown(true);
|
||||
if(sceNetAdhocctlCreate(request.NetconfData->groupName) == 0)
|
||||
{
|
||||
status = SCE_UTILITY_STATUS_FINISHED;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -58,4 +76,4 @@ void PSPNetconfDialog::DoState(PointerWrap &p) {
|
||||
return;
|
||||
|
||||
p.Do(request);
|
||||
}
|
||||
}
|
||||
@@ -46,4 +46,4 @@ public:
|
||||
|
||||
private:
|
||||
SceUtilityNetconfParam request;
|
||||
};
|
||||
};
|
||||
@@ -806,3 +806,13 @@ template <int func(int, const char *, int)> void WrapI_ICI() {
|
||||
int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2));
|
||||
RETURN(retval);
|
||||
}
|
||||
|
||||
template<int func(int, void *, void *, void *, void *, u32, int)> void WrapI_IVVVVUI(){
|
||||
u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1)), Memory::GetPointer(PARAM(2)), Memory::GetPointer(PARAM(3)), Memory::GetPointer(PARAM(4)), PARAM(5), PARAM(6) );
|
||||
RETURN(retval);
|
||||
}
|
||||
|
||||
template<int func(int, const char *, u32, void *, int, int, int)> void WrapI_ICUVIII(){
|
||||
u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), Memory::GetPointer(PARAM(3)), PARAM(4), PARAM(5), PARAM(6));
|
||||
RETURN(retval);
|
||||
}
|
||||
@@ -0,0 +1,708 @@
|
||||
#include "proAdhoc.h"
|
||||
|
||||
uint32_t fakePoolSize = 0;
|
||||
SceNetAdhocMatchingContext * contexts = NULL;
|
||||
int one = 1;
|
||||
bool friendFinderRunning = false;
|
||||
SceNetAdhocctlPeerInfo * friends = NULL;
|
||||
SceNetAdhocctlScanInfo * networks = NULL;
|
||||
int eventHandlerUpdate = -1;
|
||||
int threadStatus = ADHOCCTL_STATE_DISCONNECTED;
|
||||
|
||||
int metasocket;
|
||||
SceNetAdhocctlParameter parameter;
|
||||
std::thread friendFinderThread;
|
||||
recursive_mutex peerlock;
|
||||
SceNetAdhocPdpStat * pdp[255];
|
||||
SceNetAdhocPtpStat * ptp[255];
|
||||
|
||||
int isLocalMAC(const SceNetEtherAddr * addr) {
|
||||
SceNetEtherAddr saddr;
|
||||
getLocalMac(&saddr);
|
||||
|
||||
// Compare MAC Addresses
|
||||
int match = memcmp((const void *)addr, (const void *)&saddr, ETHER_ADDR_LEN);
|
||||
|
||||
// Return Result
|
||||
return (match == 0);
|
||||
}
|
||||
|
||||
int isPDPPortInUse(uint16_t port) {
|
||||
// Iterate Elements
|
||||
int i = 0; for(; i < 255; i++) if(pdp[i] != NULL && pdp[i]->lport == port) return 1;
|
||||
|
||||
// Unused Port
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isPTPPortInUse(uint16_t port) {
|
||||
// Iterate Sockets
|
||||
int i = 0; for(; i < 255; i++) if(ptp[i] != NULL && ptp[i]->lport == port) return 1;
|
||||
|
||||
// Unused Port
|
||||
return 0;
|
||||
}
|
||||
|
||||
void addFriend(SceNetAdhocctlConnectPacketS2C * packet) {
|
||||
// Allocate Structure
|
||||
SceNetAdhocctlPeerInfo * peer = (SceNetAdhocctlPeerInfo *)malloc(sizeof(SceNetAdhocctlPeerInfo));
|
||||
// Allocated Structure
|
||||
if(peer != NULL) {
|
||||
// Clear Memory
|
||||
memset(peer, 0, sizeof(SceNetAdhocctlPeerInfo));
|
||||
|
||||
// Link to existing Peers
|
||||
peer->next = friends;
|
||||
|
||||
// Save Nickname
|
||||
peer->nickname = packet->name;
|
||||
|
||||
// Save MAC Address
|
||||
peer->mac_addr = packet->mac;
|
||||
|
||||
// Save IP Address
|
||||
peer->ip_addr = packet->ip;
|
||||
|
||||
// Multithreading Lock
|
||||
peerlock.lock();
|
||||
|
||||
// Link into Peerlist
|
||||
friends = peer;
|
||||
|
||||
// Multithreading Unlock
|
||||
peerlock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void changeBlockingMode(int fd, int nonblocking) {
|
||||
unsigned long on = 1;
|
||||
unsigned long off = 0;
|
||||
#ifdef _MSC_VER
|
||||
if(nonblocking){
|
||||
// Change to Non-Blocking Mode
|
||||
ioctlsocket(fd,FIONBIO,&on);
|
||||
}else {
|
||||
// Change to Blocking Mode
|
||||
ioctlsocket(fd, FIONBIO, &off);
|
||||
}
|
||||
#else
|
||||
if(nonblocking == 1) fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||
else {
|
||||
// Get Flags
|
||||
int flags = fcntl(fd, F_GETFL);
|
||||
// Remove Non-Blocking Flag
|
||||
fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int countAvailableNetworks(void) {
|
||||
// Network Count
|
||||
int count = 0;
|
||||
|
||||
// Group Reference
|
||||
SceNetAdhocctlScanInfo * group = networks;
|
||||
|
||||
// Count Groups
|
||||
for(; group != NULL; group = group->next) count++;
|
||||
|
||||
// Return Network Count
|
||||
return count;
|
||||
}
|
||||
|
||||
void deleteAllPDP(void) {
|
||||
// Iterate Element
|
||||
int i = 0; for(; i < 255; i++) {
|
||||
// Active Socket
|
||||
if(pdp[i] != NULL) {
|
||||
// Close Socket
|
||||
closesocket(pdp[i]->id);
|
||||
|
||||
// Free Memory
|
||||
free(pdp[i]);
|
||||
|
||||
// Delete Reference
|
||||
pdp[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deleteAllPTP(void) {
|
||||
// Iterate Element
|
||||
int i = 0; for(; i < 255; i++) {
|
||||
// Active Socket
|
||||
if(ptp[i] != NULL) {
|
||||
// Close Socket
|
||||
closesocket(ptp[i]->id);
|
||||
|
||||
// Free Memory
|
||||
free(ptp[i]);
|
||||
|
||||
// Delete Reference
|
||||
ptp[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deleteFriendByIP(uint32_t ip) {
|
||||
// Previous Peer Reference
|
||||
SceNetAdhocctlPeerInfo * prev = NULL;
|
||||
|
||||
// Peer Pointer
|
||||
SceNetAdhocctlPeerInfo * peer = friends;
|
||||
|
||||
// Iterate Peers
|
||||
for(; peer != NULL; peer = peer->next) {
|
||||
// Found Peer
|
||||
if(peer->ip_addr == ip) {
|
||||
// Multithreading Lock
|
||||
peerlock.lock();
|
||||
|
||||
// Unlink Left (Beginning)
|
||||
if(prev == NULL)friends = peer->next;
|
||||
|
||||
// Unlink Left (Other)
|
||||
else prev->next = peer->next;
|
||||
|
||||
// Multithreading Unlock
|
||||
peerlock.unlock();
|
||||
|
||||
// Free Memory
|
||||
free(peer);
|
||||
|
||||
// Stop Search
|
||||
break;
|
||||
}
|
||||
|
||||
// Set Previous Reference
|
||||
prev = peer;
|
||||
}
|
||||
}
|
||||
|
||||
int findFreeMatchingID(void) {
|
||||
// Minimum Matching ID
|
||||
int min = 1;
|
||||
|
||||
// Maximum Matching ID
|
||||
int max = 0;
|
||||
|
||||
// Find highest Matching ID
|
||||
SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) {
|
||||
// New Maximum
|
||||
if(max < item->id) max = item->id;
|
||||
}
|
||||
|
||||
// Find unoccupied ID
|
||||
int i = min; for(; i < max; i++) {
|
||||
// Found unoccupied ID
|
||||
if(findMatchingContext(i) == NULL) return i;
|
||||
}
|
||||
|
||||
// Append at virtual end
|
||||
return max + 1;
|
||||
}
|
||||
|
||||
SceNetAdhocMatchingContext * findMatchingContext(int id) {
|
||||
// Iterate Matching Context List
|
||||
SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) { // Found Matching ID
|
||||
if(item->id == id) return item;
|
||||
}
|
||||
|
||||
// Context not found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void freeFriendsRecursive(SceNetAdhocctlPeerInfo * node) {
|
||||
// End of List
|
||||
if(node == NULL) return;
|
||||
|
||||
// Increase Recursion Depth
|
||||
freeFriendsRecursive(node->next);
|
||||
|
||||
// Free Memory
|
||||
free(node);
|
||||
}
|
||||
|
||||
int friendFinder(){
|
||||
// Receive Buffer
|
||||
int rxpos = 0;
|
||||
uint8_t rx[1024];
|
||||
|
||||
// Chat Packet
|
||||
SceNetAdhocctlChatPacketC2S chat;
|
||||
chat.base.opcode = OPCODE_CHAT;
|
||||
|
||||
// Last Ping Time
|
||||
uint64_t lastping = 0;
|
||||
|
||||
// Last Time Reception got updated
|
||||
uint64_t lastreceptionupdate = 0;
|
||||
|
||||
uint64_t now;
|
||||
|
||||
// Finder Loop
|
||||
while(friendFinderRunning) {
|
||||
// Acquire Network Lock
|
||||
//_acquireNetworkLock();
|
||||
|
||||
// Ping Server
|
||||
now = real_time_now()*1000.0;
|
||||
if(now - lastping >= 100) {
|
||||
// Update Ping Time
|
||||
lastping = now;
|
||||
|
||||
// Prepare Packet
|
||||
uint8_t opcode = OPCODE_PING;
|
||||
|
||||
// Send Ping to Server
|
||||
send(metasocket, (const char *)&opcode, 1,0);
|
||||
}
|
||||
|
||||
// Send Chat Messages
|
||||
//while(popFromOutbox(chat.message))
|
||||
//{
|
||||
// // Send Chat to Server
|
||||
// sceNetInetSend(metasocket, (const char *)&chat, sizeof(chat), 0);
|
||||
//}
|
||||
|
||||
// Wait for Incoming Data
|
||||
int received = recv(metasocket, (char *)(rx + rxpos), sizeof(rx) - rxpos,0);
|
||||
|
||||
// Free Network Lock
|
||||
//_freeNetworkLock();
|
||||
|
||||
// Received Data
|
||||
if(received > 0) {
|
||||
// Fix Position
|
||||
rxpos += received;
|
||||
|
||||
// Log Incoming Traffic
|
||||
//printf("Received %d Bytes of Data from Server\n", received);
|
||||
INFO_LOG(SCENET, "Received %d Bytes of Data from Adhoc Server", received);
|
||||
}
|
||||
|
||||
// Handle Packets
|
||||
if(rxpos > 0) {
|
||||
// BSSID Packet
|
||||
if(rx[0] == OPCODE_CONNECT_BSSID) {
|
||||
// Enough Data available
|
||||
if(rxpos >= sizeof(SceNetAdhocctlConnectBSSIDPacketS2C)) {
|
||||
// Cast Packet
|
||||
SceNetAdhocctlConnectBSSIDPacketS2C * packet = (SceNetAdhocctlConnectBSSIDPacketS2C *)rx;
|
||||
// Update BSSID
|
||||
parameter.bssid.mac_addr = packet->mac;
|
||||
// Change State
|
||||
threadStatus = ADHOCCTL_STATE_CONNECTED;
|
||||
// Notify Event Handlers
|
||||
CoreTiming::ScheduleEvent_Threadsafe_Immediate(eventHandlerUpdate, join32(ADHOCCTL_EVENT_CONNECT, 0));
|
||||
|
||||
// Move RX Buffer
|
||||
memmove(rx, rx + sizeof(SceNetAdhocctlConnectBSSIDPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlConnectBSSIDPacketS2C));
|
||||
|
||||
// Fix RX Buffer Length
|
||||
rxpos -= sizeof(SceNetAdhocctlConnectBSSIDPacketS2C);
|
||||
}
|
||||
}
|
||||
|
||||
// Chat Packet
|
||||
else if(rx[0] == OPCODE_CHAT) {
|
||||
// Enough Data available
|
||||
if(rxpos >= sizeof(SceNetAdhocctlChatPacketS2C)) {
|
||||
// Cast Packet
|
||||
SceNetAdhocctlChatPacketS2C * packet = (SceNetAdhocctlChatPacketS2C *)rx;
|
||||
|
||||
// Fix for Idiots that try to troll the "ME" Nametag
|
||||
#ifdef _MSC_VER
|
||||
if(stricmp((char *)packet->name.data, "ME") == 0) strcpy((char *)packet->name.data, "NOT ME");
|
||||
#else
|
||||
if(strcasecmp((char *)packet->name.data, "ME") == 0) strcpy((char *)packet->name.data, "NOT ME");
|
||||
#endif
|
||||
|
||||
// Add Incoming Chat to HUD
|
||||
//printf("Receive chat message %s", packet->base.message);
|
||||
|
||||
// Move RX Buffer
|
||||
memmove(rx, rx + sizeof(SceNetAdhocctlChatPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlChatPacketS2C));
|
||||
|
||||
// Fix RX Buffer Length
|
||||
rxpos -= sizeof(SceNetAdhocctlChatPacketS2C);
|
||||
}
|
||||
}
|
||||
|
||||
// Connect Packet
|
||||
else if(rx[0] == OPCODE_CONNECT) {
|
||||
// Enough Data available
|
||||
if(rxpos >= sizeof(SceNetAdhocctlConnectPacketS2C)) {
|
||||
// Log Incoming Peer
|
||||
INFO_LOG(SCENET,"Incoming Peer Data...");
|
||||
|
||||
// Cast Packet
|
||||
SceNetAdhocctlConnectPacketS2C * packet = (SceNetAdhocctlConnectPacketS2C *)rx;
|
||||
|
||||
// Add User
|
||||
addFriend(packet);
|
||||
|
||||
// Update HUD User Count
|
||||
#ifdef LOCALHOST_AS_PEER
|
||||
setUserCount(getActivePeerCount());
|
||||
#else
|
||||
// setUserCount(getActivePeerCount()+1);
|
||||
#endif
|
||||
|
||||
// Move RX Buffer
|
||||
memmove(rx, rx + sizeof(SceNetAdhocctlConnectPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlConnectPacketS2C));
|
||||
|
||||
// Fix RX Buffer Length
|
||||
rxpos -= sizeof(SceNetAdhocctlConnectPacketS2C);
|
||||
}
|
||||
}
|
||||
|
||||
// Disconnect Packet
|
||||
else if(rx[0] == OPCODE_DISCONNECT) {
|
||||
// Enough Data available
|
||||
if(rxpos >= sizeof(SceNetAdhocctlDisconnectPacketS2C)) {
|
||||
// Log Incoming Peer Delete Request
|
||||
INFO_LOG(SCENET,"FriendFinder: Incoming Peer Data Delete Request...");
|
||||
|
||||
// Cast Packet
|
||||
SceNetAdhocctlDisconnectPacketS2C * packet = (SceNetAdhocctlDisconnectPacketS2C *)rx;
|
||||
|
||||
// Delete User by IP
|
||||
deleteFriendByIP(packet->ip);
|
||||
|
||||
// Update HUD User Count
|
||||
#ifdef LOCALHOST_AS_PEER
|
||||
setUserCount(_getActivePeerCount());
|
||||
#else
|
||||
//setUserCount(_getActivePeerCount()+1);
|
||||
#endif
|
||||
|
||||
// Move RX Buffer
|
||||
memmove(rx, rx + sizeof(SceNetAdhocctlDisconnectPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlDisconnectPacketS2C));
|
||||
|
||||
// Fix RX Buffer Length
|
||||
rxpos -= sizeof(SceNetAdhocctlDisconnectPacketS2C);
|
||||
}
|
||||
}
|
||||
|
||||
// Scan Packet
|
||||
else if(rx[0] == OPCODE_SCAN) {
|
||||
// Enough Data available
|
||||
if(rxpos >= sizeof(SceNetAdhocctlScanPacketS2C)) {
|
||||
// Log Incoming Network Information
|
||||
INFO_LOG(SCENET,"Incoming Group Information...");
|
||||
// Cast Packet
|
||||
SceNetAdhocctlScanPacketS2C * packet = (SceNetAdhocctlScanPacketS2C *)rx;
|
||||
|
||||
// Allocate Structure Data
|
||||
SceNetAdhocctlScanInfo * group = (SceNetAdhocctlScanInfo *)malloc(sizeof(SceNetAdhocctlScanInfo));
|
||||
|
||||
// Allocated Structure Data
|
||||
if(group != NULL)
|
||||
{
|
||||
// Clear Memory
|
||||
memset(group, 0, sizeof(SceNetAdhocctlScanInfo));
|
||||
|
||||
// Link to existing Groups
|
||||
group->next = networks;
|
||||
|
||||
// Copy Group Name
|
||||
group->group_name = packet->group;
|
||||
|
||||
// Set Group Host
|
||||
group->bssid.mac_addr = packet->mac;
|
||||
|
||||
// Link into Group List
|
||||
networks = group;
|
||||
}
|
||||
|
||||
// Move RX Buffer
|
||||
memmove(rx, rx + sizeof(SceNetAdhocctlScanPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlScanPacketS2C));
|
||||
|
||||
// Fix RX Buffer Length
|
||||
rxpos -= sizeof(SceNetAdhocctlScanPacketS2C);
|
||||
}
|
||||
}
|
||||
|
||||
// Scan Complete Packet
|
||||
else if(rx[0] == OPCODE_SCAN_COMPLETE) {
|
||||
// Log Scan Completion
|
||||
INFO_LOG(SCENET,"FriendFinder: Incoming Scan complete response...");
|
||||
|
||||
// Change State
|
||||
threadStatus = ADHOCCTL_STATE_DISCONNECTED;
|
||||
|
||||
// Notify Event Handlers
|
||||
CoreTiming::ScheduleEvent_Threadsafe_Immediate(eventHandlerUpdate,join32(ADHOCCTL_EVENT_SCAN, 0));
|
||||
//int i = 0; for(; i < ADHOCCTL_MAX_HANDLER; i++)
|
||||
//{
|
||||
// // Active Handler
|
||||
// if(_event_handler[i] != NULL) _event_handler[i](ADHOCCTL_EVENT_SCAN, 0, _event_args[i]);
|
||||
//}
|
||||
|
||||
// Move RX Buffer
|
||||
memmove(rx, rx + 1, sizeof(rx) - 1);
|
||||
|
||||
// Fix RX Buffer Length
|
||||
rxpos -= 1;
|
||||
}
|
||||
}
|
||||
// Original value was 10 ms, I think 100 is just fine
|
||||
sleep_ms(100);
|
||||
}
|
||||
|
||||
// Log Shutdown
|
||||
INFO_LOG(SCENET, "FriendFinder: End of Friend Finder Thread");
|
||||
|
||||
// Return Success
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getActivePeerCount(void) {
|
||||
// Counter
|
||||
int count = 0;
|
||||
|
||||
// #ifdef LOCALHOST_AS_PEER
|
||||
// // Increase for Localhost
|
||||
// count++;
|
||||
// #endif
|
||||
|
||||
// Peer Reference
|
||||
SceNetAdhocctlPeerInfo * peer = friends;
|
||||
|
||||
// Iterate Peers
|
||||
for(; peer != NULL; peer = peer->next) {
|
||||
// Increase Counter
|
||||
count++;
|
||||
}
|
||||
|
||||
// Return Result
|
||||
return count;
|
||||
}
|
||||
|
||||
int getLocalIp(sockaddr_in * SocketAddress){
|
||||
#ifdef _MSC_VER
|
||||
// Get local host name
|
||||
char szHostName[128] = "";
|
||||
|
||||
if(::gethostname(szHostName, sizeof(szHostName))) {
|
||||
// Error handling
|
||||
}
|
||||
// Get local IP addresses
|
||||
struct hostent *pHost = 0;
|
||||
pHost = ::gethostbyname(szHostName);
|
||||
if(pHost) {
|
||||
memcpy(&SocketAddress->sin_addr, pHost->h_addr_list[0], pHost->h_length);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
#else
|
||||
SocketAddress->sin_addr.s_addr = inet_addr("192.168.12.1");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void getLocalMac(SceNetEtherAddr * addr){
|
||||
//MAC Adress from config
|
||||
uint8_t mac[ETHER_ADDR_LEN];
|
||||
sscanf(g_Config.localMacAddress.c_str(), "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",&mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
|
||||
memcpy(addr,mac,ETHER_ADDR_LEN);
|
||||
}
|
||||
|
||||
int getPTPSocketCount(void) {
|
||||
// Socket Counter
|
||||
int counter = 0;
|
||||
|
||||
// Count Sockets
|
||||
int i = 0; for(; i < 255; i++) if(ptp[i] != NULL) counter++;
|
||||
|
||||
// Return Socket Count
|
||||
return counter;
|
||||
}
|
||||
|
||||
int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
|
||||
int iResult = 0;
|
||||
#ifdef _MSC_VER
|
||||
WSADATA data;
|
||||
iResult = WSAStartup(MAKEWORD(2,2),&data);
|
||||
if(iResult != NOERROR){
|
||||
ERROR_LOG(SCENET, "Wsa failed");
|
||||
return iResult;
|
||||
}
|
||||
#endif
|
||||
metasocket = INVALID_SOCKET;
|
||||
metasocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
|
||||
if(metasocket == INVALID_SOCKET){
|
||||
ERROR_LOG(SCENET,"invalid socket");
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
struct sockaddr_in server_addr;
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_port = htons(27312); // Maybe read this from config too
|
||||
|
||||
// Resolve dns
|
||||
addrinfo * resultAddr;
|
||||
addrinfo * ptr;
|
||||
in_addr serverIp;
|
||||
iResult = getaddrinfo(g_Config.proAdhocServer.c_str(),0,NULL,&resultAddr);
|
||||
if(iResult != 0){
|
||||
ERROR_LOG(SCENET, "Dns error\n");
|
||||
return iResult;
|
||||
}
|
||||
for(ptr = resultAddr; ptr != NULL; ptr = ptr->ai_next){
|
||||
switch(ptr->ai_family){
|
||||
case AF_INET:
|
||||
serverIp = ((sockaddr_in *)ptr->ai_addr)->sin_addr;
|
||||
}
|
||||
}
|
||||
server_addr.sin_addr = serverIp; iResult = connect(metasocket,(sockaddr *)&server_addr,sizeof(server_addr));
|
||||
if(iResult == SOCKET_ERROR){
|
||||
ERROR_LOG(SCENET,"Socket error");
|
||||
return iResult;
|
||||
}
|
||||
memset(¶meter,0,sizeof(parameter));
|
||||
strcpy((char *)¶meter.nickname.data, g_Config.sNickName.c_str());
|
||||
parameter.channel = 1; // Fake Channel 1
|
||||
|
||||
// Prepare Login Packet
|
||||
getLocalMac(¶meter.bssid.mac_addr);
|
||||
SceNetAdhocctlLoginPacketC2S packet;
|
||||
packet.base.opcode = OPCODE_LOGIN;
|
||||
SceNetEtherAddr addres;
|
||||
getLocalMac(&addres);
|
||||
packet.mac = addres;
|
||||
strcpy((char *)packet.name.data, g_Config.sNickName.c_str());
|
||||
memcpy(packet.game.data, adhoc_id->data, ADHOCCTL_ADHOCID_LEN);
|
||||
int sent = send(metasocket, (char*)&packet, sizeof(packet), 0);
|
||||
changeBlockingMode(metasocket,1); // Change to non-blocking
|
||||
if(sent > 0){
|
||||
return 0;
|
||||
}else{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int isBroadcastMAC(const SceNetEtherAddr * addr) {
|
||||
// Broadcast MAC
|
||||
if(memcmp(addr->data, "\xFF\xFF\xFF\xFF\xFF\xFF", ETHER_ADDR_LEN) == 0) return 1;
|
||||
// Normal MAC
|
||||
return 0;
|
||||
}
|
||||
|
||||
int resolveIP(uint32_t ip, SceNetEtherAddr * mac) {
|
||||
sockaddr_in addr;
|
||||
getLocalIp(&addr);
|
||||
uint32 localIp = addr.sin_addr.s_addr;
|
||||
|
||||
if(ip == localIp){
|
||||
getLocalMac(mac);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Multithreading Lock
|
||||
peerlock.lock();
|
||||
|
||||
// Peer Reference
|
||||
SceNetAdhocctlPeerInfo * peer = friends;
|
||||
|
||||
// Iterate Peers
|
||||
for(; peer != NULL; peer = peer->next) {
|
||||
// Found Matching Peer
|
||||
if(peer->ip_addr == ip) {
|
||||
// Copy Data
|
||||
*mac = peer->mac_addr;
|
||||
|
||||
// Multithreading Unlock
|
||||
peerlock.unlock();
|
||||
|
||||
// Return Success
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Multithreading Unlock
|
||||
peerlock.unlock();
|
||||
|
||||
// Peer not found
|
||||
return -1;
|
||||
}
|
||||
|
||||
int resolveMAC(SceNetEtherAddr * mac, uint32_t * ip) {
|
||||
// Get Local MAC Address
|
||||
SceNetEtherAddr localMac;
|
||||
getLocalMac(&localMac);
|
||||
// Local MAC Requested
|
||||
if(memcmp(&localMac, mac, sizeof(SceNetEtherAddr)) == 0) {
|
||||
// Get Local IP Address
|
||||
sockaddr_in sockAddr;
|
||||
getLocalIp(&sockAddr);
|
||||
*ip = sockAddr.sin_addr.s_addr;
|
||||
return 0; // return succes
|
||||
}
|
||||
|
||||
// Multithreading Lock
|
||||
peerlock.lock();
|
||||
|
||||
// Peer Reference
|
||||
SceNetAdhocctlPeerInfo * peer = friends;
|
||||
|
||||
// Iterate Peers
|
||||
for(; peer != NULL; peer = peer->next) {
|
||||
// Found Matching Peer
|
||||
if(memcmp(&peer->mac_addr, mac, sizeof(SceNetEtherAddr)) == 0) {
|
||||
// Copy Data
|
||||
*ip = peer->ip_addr;
|
||||
|
||||
// Multithreading Unlock
|
||||
peerlock.unlock();
|
||||
|
||||
// Return Success
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Multithreading Unlock
|
||||
peerlock.unlock();
|
||||
|
||||
// Peer not found
|
||||
return -1;
|
||||
}
|
||||
|
||||
int validNetworkName(const SceNetAdhocctlGroupName * group_name) {
|
||||
// Result
|
||||
int valid = 1;
|
||||
|
||||
// Name given
|
||||
if(group_name != NULL) {
|
||||
// Iterate Name Characters
|
||||
int i = 0; for(; i < ADHOCCTL_GROUPNAME_LEN && valid; i++) {
|
||||
// End of Name
|
||||
if(group_name->data[i] == 0) break;
|
||||
|
||||
// Not a digit
|
||||
if(group_name->data[i] < '0' || group_name->data[i] > '9') {
|
||||
// Not 'A' to 'Z'
|
||||
if(group_name->data[i] < 'A' || group_name->data[i] > 'Z') {
|
||||
// Not 'a' to 'z'
|
||||
if(group_name->data[i] < 'a' || group_name->data[i] > 'z') {
|
||||
// Invalid Name
|
||||
valid = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return Result
|
||||
return valid;
|
||||
}
|
||||
|
||||
u64 join32(u32 num1, u32 num2){
|
||||
return (u64)num2 << 32 | num1;
|
||||
}
|
||||
|
||||
void split64(u64 num, int buff[]){
|
||||
int num1 = (int)(num&firstMask);
|
||||
int num2 = (int)((num&secondMask)>>32);
|
||||
buff[0] = num1;
|
||||
buff[1] = num2;
|
||||
}
|
||||
@@ -0,0 +1,598 @@
|
||||
#pragma once
|
||||
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "../Config.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "../CoreTiming.h"
|
||||
#include "Core/HLE/sceNetAdhoc.h"
|
||||
#include "native/base/timeutil.h"
|
||||
#include "native/base/mutex.h"
|
||||
#include "native/thread/thread.h"
|
||||
|
||||
#include "sceKernel.h"
|
||||
#include "sceKernelThread.h"
|
||||
#include "sceKernelMutex.h"
|
||||
#include "sceUtility.h"
|
||||
#include "net/resolve.h"
|
||||
|
||||
/*
|
||||
#ifdef _MSC_VER
|
||||
#include <thread.h>
|
||||
#else
|
||||
#include <thread>
|
||||
#endif
|
||||
*/
|
||||
|
||||
// Net stuff
|
||||
#ifdef _MSC_VER
|
||||
#include <WS2tcpip.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#define PACK
|
||||
#define errno WSAGetLastError()
|
||||
#define EAGAIN WSAEWOULDBLOCK
|
||||
#define EINPROGRESS WSAEWOULDBLOCK
|
||||
#define EISCONN WSAEISCONN
|
||||
#else
|
||||
#define INVALID_SOCKET -1
|
||||
#define SOCKET_ERROR -1
|
||||
#define closesocket close
|
||||
#define PACK __attribute__((packed))
|
||||
#endif
|
||||
|
||||
// psp strutcs and definitions
|
||||
#define ADHOCCTL_MODE_ADHOC 0
|
||||
#define ADHOCCTL_MODE_GAMEMODE 1
|
||||
|
||||
// Event Types for Event Handler
|
||||
#define ADHOCCTL_EVENT_CONNECT 1
|
||||
#define ADHOCCTL_EVENT_DISCONNECT 2
|
||||
#define ADHOCCTL_EVENT_SCAN 3
|
||||
|
||||
// Internal Thread States
|
||||
#define ADHOCCTL_STATE_DISCONNECTED 0
|
||||
#define ADHOCCTL_STATE_CONNECTED 1
|
||||
#define ADHOCCTL_STATE_SCANNING 2
|
||||
#define ADHOCCTL_STATE_GAMEMODE 3
|
||||
|
||||
// Kernel Utility Netconf Adhoc Types
|
||||
#define UTILITY_NETCONF_TYPE_CONNECT_ADHOC 2
|
||||
#define UTILITY_NETCONF_TYPE_CREATE_ADHOC 4
|
||||
#define UTILITY_NETCONF_TYPE_JOIN_ADHOC 5
|
||||
|
||||
// Kernel Utility States
|
||||
#define UTILITY_NETCONF_STATUS_NONE 0
|
||||
#define UTILITY_NETCONF_STATUS_INITIALIZE 1
|
||||
#define UTILITY_NETCONF_STATUS_RUNNING 2
|
||||
#define UTILITY_NETCONF_STATUS_FINISHED 3
|
||||
#define UTILITY_NETCONF_STATUS_SHUTDOWN 4
|
||||
|
||||
// PTP Connection States
|
||||
#define PTP_STATE_CLOSED 0
|
||||
#define PTP_STATE_LISTEN 1
|
||||
#define PTP_STATE_ESTABLISHED 4
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#endif
|
||||
// Ethernet Address
|
||||
#define ETHER_ADDR_LEN 6
|
||||
typedef struct SceNetEtherAddr {
|
||||
uint8_t data[ETHER_ADDR_LEN];
|
||||
} PACK SceNetEtherAddr;
|
||||
|
||||
|
||||
// Adhoc Virtual Network Name
|
||||
#define ADHOCCTL_GROUPNAME_LEN 8
|
||||
typedef struct SceNetAdhocctlGroupName {
|
||||
uint8_t data[ADHOCCTL_GROUPNAME_LEN];
|
||||
} PACK SceNetAdhocctlGroupName;
|
||||
|
||||
// Virtual Network Host Information
|
||||
typedef struct SceNetAdhocctlBSSId {
|
||||
SceNetEtherAddr mac_addr;
|
||||
uint8_t padding[2];
|
||||
} PACK SceNetAdhocctlBSSId;
|
||||
|
||||
// Virtual Network Information
|
||||
typedef struct SceNetAdhocctlScanInfo {
|
||||
struct SceNetAdhocctlScanInfo * next;
|
||||
s32_le channel;
|
||||
SceNetAdhocctlGroupName group_name;
|
||||
SceNetAdhocctlBSSId bssid;
|
||||
s32_le mode;
|
||||
} PACK SceNetAdhocctlScanInfo;
|
||||
|
||||
// Player Nickname
|
||||
#define ADHOCCTL_NICKNAME_LEN 128
|
||||
typedef struct SceNetAdhocctlNickname {
|
||||
uint8_t data[ADHOCCTL_NICKNAME_LEN];
|
||||
} PACK SceNetAdhocctlNickname;
|
||||
|
||||
// Active Virtual Network Information
|
||||
typedef struct SceNetAdhocctlParameter {
|
||||
s32_le channel;
|
||||
SceNetAdhocctlGroupName group_name;
|
||||
SceNetAdhocctlBSSId bssid;
|
||||
SceNetAdhocctlNickname nickname;
|
||||
} PACK SceNetAdhocctlParameter;
|
||||
|
||||
// Peer Information
|
||||
typedef struct SceNetAdhocctlPeerInfo {
|
||||
SceNetAdhocctlPeerInfo * next;
|
||||
SceNetAdhocctlNickname nickname;
|
||||
SceNetEtherAddr mac_addr;
|
||||
u32_le ip_addr;
|
||||
uint8_t padding[2];
|
||||
u64_le last_recv;
|
||||
} PACK SceNetAdhocctlPeerInfo;
|
||||
|
||||
// Peer Information with u32 pointers
|
||||
typedef struct SceNetAdhocctlPeerInfoEmu {
|
||||
u32_le next; // Changed the pointer to u32
|
||||
SceNetAdhocctlNickname nickname;
|
||||
SceNetEtherAddr mac_addr;
|
||||
u32_le ip_addr;
|
||||
u32 padding; // Changed the pointer to u32
|
||||
u64_le last_recv;
|
||||
} SceNetAdhocctlPeerInfoEmu;
|
||||
|
||||
// Game Mode Peer List
|
||||
#define ADHOCCTL_GAMEMODE_MAX_MEMBERS 16
|
||||
typedef struct SceNetAdhocctlGameModeInfo {
|
||||
s32_le num;
|
||||
SceNetEtherAddr member[ADHOCCTL_GAMEMODE_MAX_MEMBERS];
|
||||
} PACK SceNetAdhocctlGameModeInfo;
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
// Adhoc ID (Game Product Key)
|
||||
#define ADHOCCTL_ADHOCID_LEN 9
|
||||
typedef struct SceNetAdhocctlAdhocId {
|
||||
s32_le type;
|
||||
uint8_t data[ADHOCCTL_ADHOCID_LEN];
|
||||
uint8_t padding[3];
|
||||
} SceNetAdhocctlAdhocId;
|
||||
|
||||
// Socket Polling Event Listener
|
||||
struct SceNetAdhocPollSd {
|
||||
s32_le id;
|
||||
s32_le events;
|
||||
s32_le revents;
|
||||
};
|
||||
|
||||
// PDP Socket Status
|
||||
struct SceNetAdhocPdpStat {
|
||||
struct SceNetAdhocPdpStat * next;
|
||||
s32_le id;
|
||||
SceNetEtherAddr laddr;
|
||||
u16_le lport;
|
||||
u32_le rcv_sb_cc;
|
||||
};
|
||||
|
||||
// PTP Socket Status
|
||||
struct SceNetAdhocPtpStat {
|
||||
u32_le next; // Changed the pointer to u32
|
||||
s32_le id;
|
||||
SceNetEtherAddr laddr;
|
||||
SceNetEtherAddr paddr;
|
||||
u16_le lport;
|
||||
u16_le pport;
|
||||
u32_le snd_sb_cc;
|
||||
u32_le rcv_sb_cc;
|
||||
s32_le state;
|
||||
};
|
||||
|
||||
// Gamemode Optional Peer Buffer Data
|
||||
struct SceNetAdhocGameModeOptData {
|
||||
u32_le size;
|
||||
u32_le flag;
|
||||
u64_le last_recv;
|
||||
};
|
||||
|
||||
// Gamemode Buffer Status
|
||||
struct SceNetAdhocGameModeBufferStat {
|
||||
struct SceNetAdhocGameModeBufferStat * next;
|
||||
s32_le id;
|
||||
void * ptr;
|
||||
u32_le size;
|
||||
u32_le master;
|
||||
SceNetAdhocGameModeOptData opt;
|
||||
};
|
||||
|
||||
|
||||
// Internal Matching Peer Information
|
||||
typedef struct SceNetAdhocMatchingMemberInternal {
|
||||
// Next Peer
|
||||
struct SceNetAdhocMatchingMemberInternal * next;
|
||||
|
||||
// MAC Address
|
||||
SceNetEtherAddr mac;
|
||||
|
||||
// State Variable
|
||||
s32_le state;
|
||||
|
||||
// Send in Progress
|
||||
s32_le sending;
|
||||
|
||||
// Last Heartbeat
|
||||
u64_le lastping;
|
||||
} SceNetAdhocMatchingMemberInternal;
|
||||
|
||||
|
||||
// Matching handler
|
||||
struct SceNetAdhocMatchingHandlerArgs {
|
||||
s32_le id;
|
||||
s32_le event;
|
||||
SceNetEtherAddr * peer;
|
||||
s32_le optlen;
|
||||
void * opt;
|
||||
};
|
||||
|
||||
struct SceNetAdhocMatchingHandler {
|
||||
u32_le entryPoint;
|
||||
};
|
||||
|
||||
// Thread Message Stack Item
|
||||
typedef struct ThreadMessage {
|
||||
// Next Thread Message
|
||||
struct ThreadMessage * next;
|
||||
|
||||
// Stack Event Opcode
|
||||
u32_le opcode;
|
||||
|
||||
// Target MAC Address
|
||||
SceNetEtherAddr mac;
|
||||
|
||||
// Optional Data Length
|
||||
s32_le optlen;
|
||||
} ThreadMessage;
|
||||
|
||||
// Established Peer
|
||||
|
||||
// Context Information
|
||||
typedef struct SceNetAdhocMatchingContext {
|
||||
// Next Context
|
||||
struct SceNetAdhocMatchingContext * next;
|
||||
|
||||
// Externally Visible ID
|
||||
s32_le id;
|
||||
|
||||
// Matching Mode (HOST, CLIENT, P2P)
|
||||
s32_le mode;
|
||||
|
||||
// Running Flag (1 = running, 0 = created)
|
||||
s32_le running;
|
||||
|
||||
// Maximum Number of Peers (for HOST, P2P)
|
||||
s32_le maxpeers;
|
||||
|
||||
// Local MAC Address
|
||||
SceNetEtherAddr mac;
|
||||
|
||||
// Peer List for Connectees
|
||||
SceNetAdhocMatchingMemberInternal * peerlist;
|
||||
|
||||
// Local PDP Port
|
||||
u16_le port;
|
||||
|
||||
// Local PDP Socket
|
||||
s32_le socket;
|
||||
|
||||
// Receive Buffer Length
|
||||
s32_le rxbuflen;
|
||||
|
||||
// Receive Buffer
|
||||
uint8_t * rxbuf;
|
||||
|
||||
// Hello Broadcast Interval (Microseconds)
|
||||
u32_le hello_int;
|
||||
|
||||
// Keep-Alive Broadcast Interval (Microseconds)
|
||||
u32_le keepalive_int;
|
||||
|
||||
// Resend Interval (Microseconds)
|
||||
u32_le resend_int;
|
||||
|
||||
// Resend-Counter
|
||||
s32_le resendcounter;
|
||||
|
||||
// Keep-Alive Counter
|
||||
s32_le keepalivecounter;
|
||||
|
||||
// Event Handler
|
||||
SceNetAdhocMatchingHandler handler;
|
||||
|
||||
// Hello Data Length
|
||||
u32_le hellolen;
|
||||
|
||||
// Hello Data
|
||||
void * hello;
|
||||
|
||||
// Event Caller Thread
|
||||
s32_le event_thid;
|
||||
|
||||
// IO Handler Thread
|
||||
s32_le input_thid;
|
||||
|
||||
// Event Caller Thread Message Stack
|
||||
s32_le event_stack_lock;
|
||||
ThreadMessage * event_stack;
|
||||
|
||||
// IO Handler Thread Message Stack
|
||||
s32_le input_stack_lock;
|
||||
ThreadMessage * input_stack;
|
||||
} SceNetAdhocMatchingContext;
|
||||
|
||||
// End of psp definitions
|
||||
|
||||
#define OPCODE_PING 0
|
||||
#define OPCODE_LOGIN 1
|
||||
#define OPCODE_CONNECT 2
|
||||
#define OPCODE_DISCONNECT 3
|
||||
#define OPCODE_SCAN 4
|
||||
#define OPCODE_SCAN_COMPLETE 5
|
||||
#define OPCODE_CONNECT_BSSID 6
|
||||
#define OPCODE_CHAT 7
|
||||
|
||||
// PSP Product Code
|
||||
#define PRODUCT_CODE_LENGTH 9
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push,1)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
// Game Product Code (ex. ULUS12345)
|
||||
char data[PRODUCT_CODE_LENGTH];
|
||||
} PACK SceNetAdhocctlProductCode;
|
||||
|
||||
// Basic Packet
|
||||
typedef struct {
|
||||
uint8_t opcode;
|
||||
} PACK SceNetAdhocctlPacketBase;
|
||||
|
||||
// C2S Login Packet
|
||||
typedef struct {
|
||||
SceNetAdhocctlPacketBase base;
|
||||
SceNetEtherAddr mac;
|
||||
SceNetAdhocctlNickname name;
|
||||
SceNetAdhocctlProductCode game;
|
||||
} PACK SceNetAdhocctlLoginPacketC2S;
|
||||
|
||||
// C2S Connect Packet
|
||||
typedef struct {
|
||||
SceNetAdhocctlPacketBase base;
|
||||
SceNetAdhocctlGroupName group;
|
||||
} PACK SceNetAdhocctlConnectPacketC2S;
|
||||
|
||||
// C2S Chat Packet
|
||||
typedef struct {
|
||||
SceNetAdhocctlPacketBase base;
|
||||
char message[64];
|
||||
} PACK SceNetAdhocctlChatPacketC2S;
|
||||
|
||||
// S2C Connect Packet
|
||||
typedef struct {
|
||||
SceNetAdhocctlPacketBase base;
|
||||
SceNetAdhocctlNickname name;
|
||||
SceNetEtherAddr mac;
|
||||
uint32_t ip;
|
||||
} PACK SceNetAdhocctlConnectPacketS2C;
|
||||
|
||||
// S2C Disconnect Packet
|
||||
typedef struct {
|
||||
SceNetAdhocctlPacketBase base;
|
||||
uint32_t ip;
|
||||
} PACK SceNetAdhocctlDisconnectPacketS2C;
|
||||
|
||||
// S2C Scan Packet
|
||||
typedef struct {
|
||||
SceNetAdhocctlPacketBase base;
|
||||
SceNetAdhocctlGroupName group;
|
||||
SceNetEtherAddr mac;
|
||||
} PACK SceNetAdhocctlScanPacketS2C;
|
||||
|
||||
// S2C Connect BSSID Packet
|
||||
typedef struct {
|
||||
SceNetAdhocctlPacketBase base;
|
||||
SceNetEtherAddr mac;
|
||||
} PACK SceNetAdhocctlConnectBSSIDPacketS2C;
|
||||
|
||||
// S2C Chat Packet
|
||||
typedef struct {
|
||||
SceNetAdhocctlChatPacketC2S base;
|
||||
SceNetAdhocctlNickname name;
|
||||
} PACK SceNetAdhocctlChatPacketS2C;
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
// Aux vars
|
||||
extern int metasocket;
|
||||
extern SceNetAdhocctlParameter parameter;
|
||||
extern std::thread friendFinderThread;
|
||||
extern recursive_mutex peerlock;
|
||||
extern SceNetAdhocPdpStat * pdp[255];
|
||||
extern SceNetAdhocPtpStat * ptp[255];
|
||||
|
||||
extern uint32_t fakePoolSize;
|
||||
extern SceNetAdhocMatchingContext * contexts;
|
||||
extern int one;
|
||||
extern bool friendFinderRunning;
|
||||
extern SceNetAdhocctlPeerInfo * friends;
|
||||
extern SceNetAdhocctlScanInfo * networks;
|
||||
extern int eventHandlerUpdate;
|
||||
extern int threadStatus;
|
||||
// End of Aux vars
|
||||
|
||||
/**
|
||||
* Local MAC Check
|
||||
* @param saddr To-be-checked MAC Address
|
||||
* @return 1 if valid or... 0
|
||||
*/
|
||||
int isLocalMAC(const SceNetEtherAddr * addr);
|
||||
|
||||
/**
|
||||
* PDP Port Check
|
||||
* @param port To-be-checked Port
|
||||
* @return 1 if in use or... 0
|
||||
*/
|
||||
int isPDPPortInUse(uint16_t port);
|
||||
|
||||
/**
|
||||
* Check whether PTP Port is in use or not
|
||||
* @param port To-be-checked Port Number
|
||||
* @return 1 if in use or... 0
|
||||
*/
|
||||
int isPTPPortInUse(uint16_t port);
|
||||
|
||||
/**
|
||||
* Add Friend to Local List
|
||||
* @param packet Friend Information
|
||||
*/
|
||||
void addFriend(SceNetAdhocctlConnectPacketS2C * packet);
|
||||
|
||||
/**
|
||||
* Changes the Blocking Mode of the socket
|
||||
* @param fd File Descriptor of the socket
|
||||
* @param nonblocking 1 to set to nonblock and 0 to set blocking
|
||||
*/
|
||||
void changeBlockingMode(int fd, int nonblocking);
|
||||
|
||||
/**
|
||||
* Count Virtual Networks by analyzing the Friend List
|
||||
* @return Number of Virtual Networks
|
||||
*/
|
||||
int countAvailableNetworks();
|
||||
|
||||
/**
|
||||
* Closes & Deletes all PDP Sockets
|
||||
*/
|
||||
void deleteAllPDP(void);
|
||||
|
||||
/**
|
||||
* Closes & Deletes all PTP sockets
|
||||
*/
|
||||
void deleteAllPTP(void);
|
||||
|
||||
/**
|
||||
* Delete Friend from Local List
|
||||
* @param ip Friend IP
|
||||
*/
|
||||
void deleteFriendByIP(uint32_t ip);
|
||||
|
||||
/**
|
||||
* Find Free Matching ID
|
||||
* @return First unoccupied Matching ID
|
||||
*/
|
||||
int findFreeMatchingID(void);
|
||||
|
||||
/**
|
||||
* Find Internal Matching Context for Matching ID
|
||||
* @param id Matching ID
|
||||
* @return Matching Context Pointer or... NULL
|
||||
*/
|
||||
SceNetAdhocMatchingContext * findMatchingContext(int id);
|
||||
|
||||
/**
|
||||
* Recursive Memory Freeing-Helper for Friend-Structures
|
||||
* @param node Current Node in List
|
||||
*/
|
||||
void freeFriendsRecursive(SceNetAdhocctlPeerInfo * node);
|
||||
|
||||
/**
|
||||
* Friend Finder Thread (Receives Peer Information)
|
||||
* @param args Length of argp in Bytes (Unused)
|
||||
* @param argp Argument (Unused)
|
||||
* @return Unused Value - Return 0
|
||||
*/
|
||||
int friendFinder();
|
||||
|
||||
/**
|
||||
* Return Number of active Peers in the same Network as the Local Player
|
||||
* @return Number of active Peers
|
||||
*/
|
||||
int getActivePeerCount(void);
|
||||
|
||||
/**
|
||||
* Returns the locall Ip of this machine, TODO: Implement the linux version
|
||||
* @param SocketAddres OUT: local ip
|
||||
*/
|
||||
int getLocalIp(sockaddr_in * SocketAddress);
|
||||
|
||||
/**
|
||||
* Joins two 32 bits number into a 64 bit one
|
||||
* @param num1: first number
|
||||
* @param num2: second number
|
||||
* @return Single 64 bit number
|
||||
*/
|
||||
#define firstMask 0x00000000FFFFFFFF
|
||||
#define secondMask 0xFFFFFFFF00000000
|
||||
u64 join32(u32 num1, u32 num2);
|
||||
|
||||
/**
|
||||
* Splits a 64 bit number into two 32 bit ones
|
||||
* @param num: The number to be split
|
||||
* @param buf OUT: Array containing the split numbers
|
||||
*/
|
||||
void split64(u64 num, int buff[]);
|
||||
|
||||
/**
|
||||
* Returns the local mac, TODO: Read from Config file
|
||||
* @param addr OUT: Local Mac
|
||||
*/
|
||||
void getLocalMac(SceNetEtherAddr * addr);
|
||||
|
||||
/**
|
||||
* PTP Socket Counter
|
||||
* @return Number of internal PTP Sockets
|
||||
*/
|
||||
int getPTPSocketCount(void);
|
||||
|
||||
/**
|
||||
* Initialize Networking Components for Adhocctl Emulator
|
||||
* @param adhoc_id Game Product Code
|
||||
* @param server_ip Server IP
|
||||
* @return 0 on success or... -1
|
||||
*/
|
||||
int initNetwork(SceNetAdhocctlAdhocId *adhocid);
|
||||
|
||||
/**
|
||||
* Broadcast MAC Check
|
||||
* @param addr To-be-checked MAC Address
|
||||
* @return 1 if Broadcast MAC or... 0
|
||||
*/
|
||||
int isBroadcastMAC(const SceNetEtherAddr * addr);
|
||||
|
||||
/**
|
||||
* Resolve IP to MAC
|
||||
* @param ip Peer IP Address
|
||||
* @param mac OUT: Peer MAC
|
||||
* @return 0 on success or... ADHOC_NO_ENTRY
|
||||
*/
|
||||
int resolveIP(uint32_t ip, SceNetEtherAddr * mac);
|
||||
|
||||
/**
|
||||
* Resolve MAC to IP
|
||||
* @param mac Peer MAC Address
|
||||
* @param ip OUT: Peer IP
|
||||
* @return 0 on success or... ADHOC_NO_ENTRY
|
||||
*/
|
||||
int resolveMAC(SceNetEtherAddr * mac, uint32_t * ip);
|
||||
|
||||
/**
|
||||
* Check whether Network Name contains only valid symbols
|
||||
* @param group_name To-be-checked Network Name
|
||||
* @return 1 if valid or... 0
|
||||
*/
|
||||
int validNetworkName(const SceNetAdhocctlGroupName * groupname);
|
||||
+12
-5
@@ -18,6 +18,7 @@
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "HLE.h"
|
||||
#include "../MIPS/MIPS.h"
|
||||
#include "../Config.h"
|
||||
|
||||
#include "sceKernel.h"
|
||||
#include "sceKernelThread.h"
|
||||
@@ -130,22 +131,28 @@ u32 sceNetTerm() {
|
||||
}
|
||||
|
||||
u32 sceWlanGetEtherAddr(u32 addrAddr) {
|
||||
static const u8 fakeEtherAddr[6] = { 1, 2, 3, 4, 5, 6 };
|
||||
//MAC Adress from config
|
||||
uint8_t mac[6];
|
||||
sscanf(g_Config.localMacAddress.c_str(), "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",&mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
|
||||
DEBUG_LOG(SCENET, "sceWlanGetEtherAddr(%08x)", addrAddr);
|
||||
for (int i = 0; i < 6; i++)
|
||||
Memory::Write_U8(fakeEtherAddr[i], addrAddr + i);
|
||||
Memory::Write_U8(mac[i], addrAddr + i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceNetGetLocalEtherAddr(u32 addrAddr) {
|
||||
return sceWlanGetEtherAddr(addrAddr);
|
||||
}
|
||||
|
||||
u32 sceWlanDevIsPowerOn() {
|
||||
DEBUG_LOG(SCENET, "UNTESTED 0=sceWlanDevIsPowerOn()");
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
u32 sceWlanGetSwitchState() {
|
||||
DEBUG_LOG(SCENET, "UNTESTED sceWlanGetSwitchState()");
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Probably a void function, but often returns a useful value.
|
||||
@@ -348,7 +355,7 @@ const HLEFunction sceNet[] = {
|
||||
{0x281928A9, WrapU_V<sceNetTerm>, "sceNetTerm"},
|
||||
{0x89360950, WrapI_UU<sceNetEtherNtostr>, "sceNetEtherNtostr"},
|
||||
{0xd27961c9, WrapI_UU<sceNetEtherStrton>, "sceNetEtherStrton"},
|
||||
{0x0bf0a3ae, 0, "sceNetGetLocalEtherAddr"},
|
||||
{0x0bf0a3ae, WrapU_U<sceNetGetLocalEtherAddr>, "sceNetGetLocalEtherAddr"},
|
||||
{0x50647530, 0, "sceNetFreeThreadinfo"},
|
||||
{0xcc393e48, WrapI_U<sceNetGetMallocStat>, "sceNetGetMallocStat"},
|
||||
{0xad6844c6, 0, "sceNetThreadAbort"},
|
||||
|
||||
+1944
-360
File diff suppressed because it is too large.
Load diff
@@ -24,3 +24,6 @@ void Register_sceNetAdhoc();
|
||||
void __NetAdhocInit();
|
||||
void __NetAdhocShutdown();
|
||||
void __NetAdhocDoState(PointerWrap &p);
|
||||
|
||||
// I have to call this from netdialog
|
||||
int sceNetAdhocctlCreate(const char * groupName);
|
||||
@@ -1,3 +1,29 @@
|
||||
ADHOC SUPPORT
|
||||
=============
|
||||
This is based on coldbird code: http://code.google.com/p/aemu/ All Credit goes
|
||||
to him!
|
||||
|
||||
Status
|
||||
------
|
||||
Code is a complete mess and it's not fully functional yet, I still need to implement
|
||||
some functions and add a upnp lib(really important for people with routers).
|
||||
|
||||
I did test it with some games(emulator <-> real psp with the server running locally)
|
||||
and it's looking good:
|
||||
* Worms Open Warfare: Ran just fine, I was able to play a whole match without problems
|
||||
* Monster Hunter Freedom Unite: Runs fine too. Gathering Hall and embarking on quests Works
|
||||
* Dissidia Duodecim 012: Doesn't work. It requires some functions that I haven't implemented
|
||||
yet. Also, it uses a port < 1000 and thats reserved for admin apps on linux, running the emu
|
||||
as sudo "solves" it, but it's far from ideal.
|
||||
* Pacman World Rally: Works too.
|
||||
|
||||
Update (Kyhel) :
|
||||
---------------
|
||||
* Now compiles on both Mac OSX and Windows. For more details on how to play and build
|
||||
go to see there http://forums.ppsspp.org/showthread.php?tid=3595&pid=59241#pid59241
|
||||
* Got it tested windows <-> mac osx <-> psp, it works
|
||||
* Monster Hunter 3rd HD works too, as well as God Eater Burst.
|
||||
|
||||
PPSSPP - a fast and portable PSP emulator
|
||||
=========================================
|
||||
|
||||
|
||||
Reference in new issue
Block a user