1 // Copyright (c) 2012- PPSSPP Project.
2
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
6
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
11
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
14
15 // Official git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18 #if __linux__ || __APPLE__
19 #include <unistd.h>
20 #include <sys/types.h>
21 #include <sys/mman.h>
22 #include <fcntl.h>
23 #endif
24
25 #include "Common/Net/Resolve.h"
26 #include "Common/Data/Text/Parsers.h"
27
28 #include "Common/Serialize/Serializer.h"
29 #include "Common/Serialize/SerializeFuncs.h"
30 #include "Common/Serialize/SerializeMap.h"
31 #include "Core/HLE/HLE.h"
32 #include "Core/HLE/FunctionWrappers.h"
33 #include "Core/HLE/sceKernelMemory.h"
34 #include "Core/MIPS/MIPS.h"
35 #include "Core/Config.h"
36 #include "Core/MemMapHelpers.h"
37 #include "Core/Util/PortManager.h"
38
39 #include "sceKernel.h"
40 #include "sceKernelThread.h"
41 #include "sceKernelMutex.h"
42 #include "sceUtility.h"
43
44 #include "Core/HLE/proAdhoc.h"
45 #include "Core/HLE/sceNetAdhoc.h"
46 #include "Core/HLE/sceNet.h"
47 #include "Core/HLE/sceNp.h"
48 #include "Core/Reporting.h"
49 #include "Core/Instance.h"
50
51 #if PPSSPP_PLATFORM(SWITCH) && !defined(INADDR_NONE)
52 // Missing toolchain define
53 #define INADDR_NONE 0xFFFFFFFF
54 #endif
55
56 static bool netInited;
57 bool netInetInited;
58
59 u32 netDropRate = 0;
60 u32 netDropDuration = 0;
61 u32 netPoolAddr = 0;
62 u32 netThread1Addr = 0;
63 u32 netThread2Addr = 0;
64
65 static struct SceNetMallocStat netMallocStat;
66
67 static std::map<int, ApctlHandler> apctlHandlers;
68
69 SceNetApctlInfoInternal netApctlInfo;
70
71 bool netApctlInited;
72 u32 netApctlState;
73 u32 apctlThreadHackAddr = 0;
74 u32_le apctlThreadCode[3];
75 SceUID apctlThreadID = 0;
76 int apctlStateEvent = -1;
77 int actionAfterApctlMipsCall;
78 std::recursive_mutex apctlEvtMtx;
79 std::deque<ApctlArgs> apctlEvents;
80
81 u32 Net_Term();
82 int NetApctl_Term();
83 void NetApctl_InitInfo();
84
DoState(PointerWrap & p)85 void AfterApctlMipsCall::DoState(PointerWrap & p) {
86 auto s = p.Section("AfterApctlMipsCall", 1, 1);
87 if (!s)
88 return;
89 // Just in case there are "s" corruption in the future where s.ver is a negative number
90 if (s >= 1) {
91 Do(p, handlerID);
92 Do(p, oldState);
93 Do(p, newState);
94 Do(p, event);
95 Do(p, error);
96 Do(p, argsAddr);
97 } else {
98 handlerID = -1;
99 oldState = 0;
100 newState = 0;
101 event = 0;
102 error = 0;
103 argsAddr = 0;
104 }
105 }
106
run(MipsCall & call)107 void AfterApctlMipsCall::run(MipsCall& call) {
108 u32 v0 = currentMIPS->r[MIPS_REG_V0];
109 DEBUG_LOG(SCENET, "AfterApctlMipsCall::run [ID=%i][OldState=%d][NewState=%d][Event=%d][Error=%d][ArgsPtr=%08x] [cbId: %u][retV0: %08x]", handlerID, oldState, newState, event, error, argsAddr, call.cbId, v0);
110 //call.setReturnValue(v0);
111 }
112
SetData(int HandlerID,int OldState,int NewState,int Event,int Error,u32_le ArgsAddr)113 void AfterApctlMipsCall::SetData(int HandlerID, int OldState, int NewState, int Event, int Error, u32_le ArgsAddr) {
114 handlerID = HandlerID;
115 oldState = OldState;
116 newState = NewState;
117 event = Event;
118 error = Error;
119 argsAddr = ArgsAddr;
120 }
121
InitLocalhostIP()122 void InitLocalhostIP() {
123 // The entire 127.*.*.* is reserved for loopback.
124 uint32_t localIP = 0x7F000001 + PPSSPP_ID - 1;
125
126 g_localhostIP.in.sin_family = AF_INET;
127 g_localhostIP.in.sin_addr.s_addr = htonl(localIP);
128 g_localhostIP.in.sin_port = 0;
129
130 std::string serverStr = StripSpaces(g_Config.proAdhocServer);
131 isLocalServer = (!strcasecmp(serverStr.c_str(), "localhost") || serverStr.find("127.") == 0);
132 }
133
__ApctlState(u64 userdata,int cyclesLate)134 static void __ApctlState(u64 userdata, int cyclesLate) {
135 SceUID threadID = userdata >> 32;
136 int uid = (int)(userdata & 0xFFFFFFFF);
137 int event = uid - 1;
138
139 s64 result = 0;
140 u32 error = 0;
141
142 SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_NET, error);
143 if (waitID == 0 || error != 0) {
144 WARN_LOG(SCENET, "sceNetApctl State WaitID(%i) on Thread(%i) already woken up? (error: %08x)", uid, threadID, error);
145 return;
146 }
147
148 u32 waitVal = __KernelGetWaitValue(threadID, error);
149 if (error == 0) {
150 netApctlState = waitVal;
151 }
152
153 __KernelResumeThreadFromWait(threadID, result);
154 DEBUG_LOG(SCENET, "Returning (WaitID: %d, error: %08x) Result (%08x) of sceNetApctl - Event: %d, State: %d", waitID, error, (int)result, event, netApctlState);
155 }
156
157 // Used to change Apctl State after a delay and before executing callback mipscall (since we don't have beforeAction)
ScheduleApctlState(int event,int newState,int usec,const char * reason)158 int ScheduleApctlState(int event, int newState, int usec, const char* reason) {
159 int uid = event + 1;
160
161 u64 param = ((u64)__KernelGetCurThread()) << 32 | uid;
162 CoreTiming::ScheduleEvent(usToCycles(usec), apctlStateEvent, param);
163 __KernelWaitCurThread(WAITTYPE_NET, uid, newState, 0, false, reason);
164
165 return 0;
166 }
167
__NetApctlInit()168 void __NetApctlInit() {
169 netApctlInited = false;
170 netApctlState = PSP_NET_APCTL_STATE_DISCONNECTED;
171 apctlStateEvent = CoreTiming::RegisterEvent("__ApctlState", __ApctlState);
172 apctlHandlers.clear();
173 apctlEvents.clear();
174 memset(&netApctlInfo, 0, sizeof(netApctlInfo));
175 }
176
__ResetInitNetLib()177 static void __ResetInitNetLib() {
178 netInited = false;
179 netInetInited = false;
180
181 memset(&netMallocStat, 0, sizeof(netMallocStat));
182 memset(¶meter, 0, sizeof(parameter));
183 }
184
__NetCallbackInit()185 void __NetCallbackInit() {
186 // Init Network Callbacks
187 dummyThreadHackAddr = __CreateHLELoop(dummyThreadCode, "sceNetAdhoc", "__NetTriggerCallbacks", "dummythreadhack");
188 matchingThreadHackAddr = __CreateHLELoop(matchingThreadCode, "sceNetAdhocMatching", "__NetMatchingCallbacks", "matchingThreadHack");
189 apctlThreadHackAddr = __CreateHLELoop(apctlThreadCode, "sceNetApctl", "__NetApctlCallbacks", "apctlThreadHack");
190
191 // Newer one should be placed last to prevent callbacks going to the wrong after action after loading from old save state
192 actionAfterMatchingMipsCall = __KernelRegisterActionType(AfterMatchingMipsCall::Create);
193 actionAfterAdhocMipsCall = __KernelRegisterActionType(AfterAdhocMipsCall::Create);
194 actionAfterApctlMipsCall = __KernelRegisterActionType(AfterApctlMipsCall::Create);
195 }
196
__NetInit()197 void __NetInit() {
198 // Windows: Assuming WSAStartup already called beforehand
199 portOffset = g_Config.iPortOffset;
200 isOriPort = g_Config.bEnableUPnP && g_Config.bUPnPUseOriginalPort;
201 minSocketTimeoutUS = g_Config.iMinTimeout * 1000UL;
202
203 // Init Default AdhocServer struct
204 g_adhocServerIP.in.sin_family = AF_INET;
205 g_adhocServerIP.in.sin_port = htons(SERVER_PORT); //27312 // Maybe read this from config too
206 g_adhocServerIP.in.sin_addr.s_addr = INADDR_NONE;
207
208 dummyPeekBuf64k = (char*)malloc(dummyPeekBuf64kSize);
209 InitLocalhostIP();
210
211 SceNetEtherAddr mac;
212 getLocalMac(&mac);
213 INFO_LOG(SCENET, "LocalHost IP will be %s [%s]", ip2str(g_localhostIP.in.sin_addr).c_str(), mac2str(&mac).c_str());
214
215 // TODO: May be we should initialize & cleanup somewhere else than here for PortManager to be used as general purpose for whatever port forwarding PPSSPP needed
216 __UPnPInit();
217
218 __ResetInitNetLib();
219 __NetApctlInit();
220 __NetCallbackInit();
221 }
222
__NetApctlShutdown()223 void __NetApctlShutdown() {
224 if (apctlThreadHackAddr) {
225 kernelMemory.Free(apctlThreadHackAddr);
226 apctlThreadHackAddr = 0;
227 }
228 apctlHandlers.clear();
229 apctlEvents.clear();
230 }
231
__NetShutdown()232 void __NetShutdown() {
233 // Network Cleanup
234 Net_Term();
235
236 __NetApctlShutdown();
237 __ResetInitNetLib();
238
239 // Since PortManager supposed to be general purpose for whatever port forwarding PPSSPP needed, may be we shouldn't clear & restore ports in here? it will be cleared and restored by PortManager's destructor when exiting PPSSPP anyway
240 __UPnPShutdown();
241
242 free(dummyPeekBuf64k);
243 }
244
__UpdateApctlHandlers(u32 oldState,u32 newState,u32 flag,u32 error)245 static void __UpdateApctlHandlers(u32 oldState, u32 newState, u32 flag, u32 error) {
246 std::lock_guard<std::recursive_mutex> apctlGuard(apctlEvtMtx);
247 apctlEvents.push_back({ oldState, newState, flag, error });
248 }
249
250 // Make sure MIPS calls have been fully executed before the next notifyApctlHandlers
notifyApctlHandlers(int oldState,int newState,int flag,int error)251 void notifyApctlHandlers(int oldState, int newState, int flag, int error) {
252 __UpdateApctlHandlers(oldState, newState, flag, error);
253 }
254
netValidateLoopMemory()255 void netValidateLoopMemory() {
256 // Allocate Memory if it wasn't valid/allocated after loaded from old SaveState
257 if (!apctlThreadHackAddr || (apctlThreadHackAddr && strcmp("apctlThreadHack", kernelMemory.GetBlockTag(apctlThreadHackAddr)) != 0)) {
258 u32 blockSize = sizeof(apctlThreadCode);
259 apctlThreadHackAddr = kernelMemory.Alloc(blockSize, false, "apctlThreadHack");
260 if (apctlThreadHackAddr) Memory::Memcpy(apctlThreadHackAddr, apctlThreadCode, sizeof(apctlThreadCode));
261 }
262 }
263
264 // This feels like a dubious proposition, mostly...
__NetDoState(PointerWrap & p)265 void __NetDoState(PointerWrap &p) {
266 auto s = p.Section("sceNet", 1, 5);
267 if (!s)
268 return;
269
270 auto cur_netInited = netInited;
271 auto cur_netInetInited = netInetInited;
272 auto cur_netApctlInited = netApctlInited;
273
274 Do(p, netInited);
275 Do(p, netInetInited);
276 Do(p, netApctlInited);
277 Do(p, apctlHandlers);
278 Do(p, netMallocStat);
279 if (s < 2) {
280 netDropRate = 0;
281 netDropDuration = 0;
282 } else {
283 Do(p, netDropRate);
284 Do(p, netDropDuration);
285 }
286 if (s < 3) {
287 netPoolAddr = 0;
288 netThread1Addr = 0;
289 netThread2Addr = 0;
290 } else {
291 Do(p, netPoolAddr);
292 Do(p, netThread1Addr);
293 Do(p, netThread2Addr);
294 }
295 if (s >= 4) {
296 Do(p, netApctlState);
297 Do(p, netApctlInfo);
298 Do(p, actionAfterApctlMipsCall);
299 if (actionAfterApctlMipsCall != -1) {
300 __KernelRestoreActionType(actionAfterApctlMipsCall, AfterApctlMipsCall::Create);
301 }
302 Do(p, apctlThreadHackAddr);
303 Do(p, apctlThreadID);
304 }
305 else {
306 actionAfterApctlMipsCall = -1;
307 apctlThreadHackAddr = 0;
308 apctlThreadID = 0;
309 }
310 if (s >= 5) {
311 Do(p, apctlStateEvent);
312 } else {
313 apctlStateEvent = -1;
314 }
315 CoreTiming::RestoreRegisterEvent(apctlStateEvent, "__ApctlState", __ApctlState);
316
317 if (p.mode == p.MODE_READ) {
318 // Let's not change "Inited" value when Loading SaveState in the middle of multiplayer to prevent memory & port leaks
319 netApctlInited = cur_netApctlInited;
320 netInetInited = cur_netInetInited;
321 netInited = cur_netInited;
322
323 // Discard leftover events
324 apctlEvents.clear();
325 }
326 }
327
num2hex(I w,size_t hex_len)328 template <typename I> std::string num2hex(I w, size_t hex_len) {
329 static const char* digits = "0123456789ABCDEF";
330 std::string rc(hex_len, '0');
331 for (size_t i = 0, j = (hex_len - 1) * 4; i < hex_len; ++i, j -= 4)
332 rc[i] = digits[(w >> j) & 0x0f];
333 return rc;
334 }
335
error2str(u32 errorCode)336 std::string error2str(u32 errorCode) {
337 std::string str = "";
338 if (((errorCode >> 31) & 1) != 0)
339 str += "ERROR ";
340 if (((errorCode >> 30) & 1) != 0)
341 str += "CRITICAL ";
342 switch ((errorCode >> 16) & 0xfff) {
343 case 0x41:
344 str += "NET ";
345 break;
346 default:
347 str += "UNK"+num2hex(u16((errorCode >> 16) & 0xfff), 3)+" ";
348 }
349 switch ((errorCode >> 8) & 0xff) {
350 case 0x00:
351 str += "COMMON ";
352 break;
353 case 0x01:
354 str += "CORE ";
355 break;
356 case 0x02:
357 str += "INET ";
358 break;
359 case 0x03:
360 str += "POECLIENT ";
361 break;
362 case 0x04:
363 str += "RESOLVER ";
364 break;
365 case 0x05:
366 str += "DHCP ";
367 break;
368 case 0x06:
369 str += "ADHOC_AUTH ";
370 break;
371 case 0x07:
372 str += "ADHOC ";
373 break;
374 case 0x08:
375 str += "ADHOC_MATCHING ";
376 break;
377 case 0x09:
378 str += "NETCNF ";
379 break;
380 case 0x0a:
381 str += "APCTL ";
382 break;
383 case 0x0b:
384 str += "ADHOCCTL ";
385 break;
386 case 0x0c:
387 str += "UNKNOWN1 ";
388 break;
389 case 0x0d:
390 str += "WLAN ";
391 break;
392 case 0x0e:
393 str += "EAPOL ";
394 break;
395 case 0x0f:
396 str += "8021x ";
397 break;
398 case 0x10:
399 str += "WPA ";
400 break;
401 case 0x11:
402 str += "UNKNOWN2 ";
403 break;
404 case 0x12:
405 str += "TRANSFER ";
406 break;
407 case 0x13:
408 str += "ADHOC_DISCOVER ";
409 break;
410 case 0x14:
411 str += "ADHOC_DIALOG ";
412 break;
413 case 0x15:
414 str += "WISPR ";
415 break;
416 default:
417 str += "UNKNOWN"+num2hex(u8((errorCode >> 8) & 0xff))+" ";
418 }
419 str += num2hex(u8(errorCode & 0xff));
420 return str;
421 }
422
__NetApctlCallbacks()423 void __NetApctlCallbacks()
424 {
425 std::lock_guard<std::recursive_mutex> apctlGuard(apctlEvtMtx);
426 hleSkipDeadbeef();
427 int delayus = 10000;
428
429 // We are temporarily borrowing APctl thread for NpAuth callbacks for testing to simulate authentication
430 if (!npAuthEvents.empty())
431 {
432 auto args = npAuthEvents.front();
433 auto& id = args.data[0];
434 auto& result = args.data[1];
435 auto& argAddr = args.data[2];
436 npAuthEvents.pop_front();
437
438 delayus = (adhocEventDelay + adhocExtraDelay);
439
440 int handlerID = id - 1;
441 for (std::map<int, NpAuthHandler>::iterator it = npAuthHandlers.begin(); it != npAuthHandlers.end(); ++it) {
442 if (it->first == handlerID) {
443 DEBUG_LOG(SCENET, "NpAuthCallback [HandlerID=%i][RequestID=%d][Result=%d][ArgsPtr=%08x]", it->first, id, result, it->second.argument);
444 // TODO: Update result / args.data[1] with the actual ticket length (or error code?)
445 hleEnqueueCall(it->second.entryPoint, 3, args.data);
446 }
447 }
448 }
449
450 // How AP works probably like this: Game use sceNetApctl function -> sceNetApctl let the hardware know and do their's thing and have a new State -> Let the game know the resulting State through Event on their handler
451 if (!apctlEvents.empty())
452 {
453 auto args = apctlEvents.front();
454 auto& oldState = args.data[0];
455 auto& newState = args.data[1];
456 auto& event = args.data[2];
457 auto& error = args.data[3];
458 apctlEvents.pop_front();
459
460 // Adjust delay according to current event.
461 if (event == PSP_NET_APCTL_EVENT_CONNECT_REQUEST || event == PSP_NET_APCTL_EVENT_GET_IP || event == PSP_NET_APCTL_EVENT_SCAN_REQUEST)
462 delayus = adhocEventDelay;
463 else
464 delayus = adhocEventPollDelay;
465
466 // Do we need to change the oldState? even if there was error?
467 //if (error == 0)
468 // oldState = netApctlState;
469
470 // Need to make sure netApctlState is updated before calling the callback's mipscall so the game can GetState()/GetInfo() within their handler's subroutine and make use the new State/Info
471 // Should we update NewState & Error accordingly to Event before executing the mipscall ? sceNetApctl* functions might want to set the error value tho, so we probably should leave it untouched, right?
472 //error = 0;
473 switch (event) {
474 case PSP_NET_APCTL_EVENT_CONNECT_REQUEST:
475 newState = PSP_NET_APCTL_STATE_JOINING; // Should we set the State to PSP_NET_APCTL_STATE_DISCONNECTED if there was error?
476 if (error == 0)
477 apctlEvents.push_front({ newState, newState, PSP_NET_APCTL_EVENT_ESTABLISHED, 0 }); // Should we use PSP_NET_APCTL_EVENT_EAP_AUTH if securityType is not NONE?
478 break;
479
480 case PSP_NET_APCTL_EVENT_ESTABLISHED:
481 newState = PSP_NET_APCTL_STATE_GETTING_IP;
482 if (error == 0)
483 apctlEvents.push_front({ newState, newState, PSP_NET_APCTL_EVENT_GET_IP, 0 });
484 break;
485
486 case PSP_NET_APCTL_EVENT_GET_IP:
487 newState = PSP_NET_APCTL_STATE_GOT_IP;
488 NetApctl_InitInfo();
489 break;
490
491 case PSP_NET_APCTL_EVENT_DISCONNECT_REQUEST:
492 newState = PSP_NET_APCTL_STATE_DISCONNECTED;
493 break;
494
495 case PSP_NET_APCTL_EVENT_SCAN_REQUEST:
496 newState = PSP_NET_APCTL_STATE_SCANNING;
497 if (error == 0)
498 apctlEvents.push_front({ newState, newState, PSP_NET_APCTL_EVENT_SCAN_COMPLETE, 0 });
499 break;
500
501 case PSP_NET_APCTL_EVENT_SCAN_COMPLETE:
502 newState = PSP_NET_APCTL_STATE_DISCONNECTED;
503 if (error == 0)
504 apctlEvents.push_front({ newState, newState, PSP_NET_APCTL_EVENT_SCAN_STOP, 0 });
505 break;
506
507 case PSP_NET_APCTL_EVENT_SCAN_STOP:
508 newState = PSP_NET_APCTL_STATE_DISCONNECTED;
509 break;
510
511 case PSP_NET_APCTL_EVENT_EAP_AUTH: // Is this suppose to happen between JOINING and ESTABLISHED ?
512 newState = PSP_NET_APCTL_STATE_EAP_AUTH;
513 if (error == 0)
514 apctlEvents.push_front({ newState, newState, PSP_NET_APCTL_EVENT_KEY_EXCHANGE, 0 }); // not sure if KEY_EXCHANGE is the next step after AUTH or not tho
515 break;
516
517 case PSP_NET_APCTL_EVENT_KEY_EXCHANGE: // Is this suppose to happen between JOINING and ESTABLISHED ?
518 newState = PSP_NET_APCTL_STATE_KEY_EXCHANGE;
519 if (error == 0)
520 apctlEvents.push_front({ newState, newState, PSP_NET_APCTL_EVENT_ESTABLISHED, 0 });
521 break;
522
523 case PSP_NET_APCTL_EVENT_RECONNECT:
524 newState = PSP_NET_APCTL_STATE_DISCONNECTED;
525 if (error == 0)
526 apctlEvents.push_front({ newState, newState, PSP_NET_APCTL_EVENT_CONNECT_REQUEST, 0 });
527 break;
528 }
529 // Do we need to change the newState? even if there were error?
530 //if (error != 0)
531 // newState = netApctlState;
532
533 // Since 0 is a valid index to types_ we use -1 to detects if it was loaded from an old save state
534 if (actionAfterApctlMipsCall < 0) {
535 actionAfterApctlMipsCall = __KernelRegisterActionType(AfterApctlMipsCall::Create);
536 }
537
538 // Run mipscall. Should we skipped executing the mipscall if oldState == newState?
539 for (std::map<int, ApctlHandler>::iterator it = apctlHandlers.begin(); it != apctlHandlers.end(); ++it) {
540 DEBUG_LOG(SCENET, "ApctlCallback [ID=%i][OldState=%d][NewState=%d][Event=%d][Error=%08x][ArgsPtr=%08x]", it->first, oldState, newState, event, error, it->second.argument);
541 args.data[4] = it->second.argument;
542 AfterApctlMipsCall* after = (AfterApctlMipsCall*)__KernelCreateAction(actionAfterApctlMipsCall);
543 after->SetData(it->first, oldState, newState, event, error, it->second.argument);
544 hleEnqueueCall(it->second.entryPoint, 5, args.data, after);
545 }
546 // Similar to Adhocctl, new State might need to be set after delayed, right before executing the mipscall (ie. simulated beforeAction)
547 ScheduleApctlState(event, newState, delayus, "apctl callback state");
548 return;
549 }
550
551 // Must be delayed long enough whenever there is a pending callback to make sure previous callback & it's afterAction are fully executed
552 sceKernelDelayThread(delayus);
553 }
554
AllocUser(u32 size,bool fromTop,const char * name)555 static inline u32 AllocUser(u32 size, bool fromTop, const char *name) {
556 u32 addr = userMemory.Alloc(size, fromTop, name);
557 if (addr == -1)
558 return 0;
559 return addr;
560 }
561
FreeUser(u32 & addr)562 static inline void FreeUser(u32 &addr) {
563 if (addr != 0)
564 userMemory.Free(addr);
565 addr = 0;
566 }
567
Net_Term()568 u32 Net_Term() {
569 // May also need to Terminate netAdhocctl and netAdhoc to free some resources & threads, since the game (ie. GTA:VCS, Wipeout Pulse, etc) might not called them before calling sceNetTerm and causing them to behave strangely on the next sceNetInit & sceNetAdhocInit
570 NetAdhocctl_Term();
571 NetAdhoc_Term();
572
573 // TODO: Not implemented yet
574 NetApctl_Term();
575 //NetInet_Term();
576
577 // Library is initialized
578 if (netInited) {
579 // Delete Adhoc Sockets
580 deleteAllAdhocSockets();
581
582 // Delete GameMode Buffer
583 //deleteAllGMB();
584
585 // Terminate Internet Library
586 //sceNetInetTerm();
587
588 // Unload Internet Modules (Just keep it in memory... unloading crashes?!)
589 // if (_manage_modules != 0) sceUtilityUnloadModule(PSP_MODULE_NET_INET);
590 // Library shutdown
591 }
592
593 FreeUser(netPoolAddr);
594 FreeUser(netThread1Addr);
595 FreeUser(netThread2Addr);
596 netInited = false;
597
598 return 0;
599 }
600
sceNetTerm()601 static u32 sceNetTerm() {
602 WARN_LOG(SCENET, "sceNetTerm() at %08x", currentMIPS->pc);
603 int retval = Net_Term();
604
605 // Give time to make sure everything are cleaned up
606 hleEatMicro(adhocDefaultDelay);
607 return retval;
608 }
609
610 /*
611 Parameters:
612 poolsize - Memory pool size (appears to be for the whole of the networking library).
613 calloutprio - Priority of the SceNetCallout thread.
614 calloutstack - Stack size of the SceNetCallout thread (defaults to 4096 on non 1.5 firmware regardless of what value is passed).
615 netintrprio - Priority of the SceNetNetintr thread.
616 netintrstack - Stack size of the SceNetNetintr thread (defaults to 4096 on non 1.5 firmware regardless of what value is passed).
617 */
sceNetInit(u32 poolSize,u32 calloutPri,u32 calloutStack,u32 netinitPri,u32 netinitStack)618 static int sceNetInit(u32 poolSize, u32 calloutPri, u32 calloutStack, u32 netinitPri, u32 netinitStack) {
619 // TODO: Create Network Threads using given priority & stack
620 // TODO: The correct behavior is actually to allocate more and leak the other threads/pool.
621 // But we reset here for historic reasons (GTA:VCS potentially triggers this.)
622 if (netInited)
623 Net_Term(); // This cleanup attempt might not worked when SaveState were loaded in the middle of multiplayer game and re-entering multiplayer, thus causing memory leaks & wasting binded ports. May be we shouldn't save/load "Inited" vars on SaveState?
624
625 if (poolSize == 0) {
626 return hleLogError(SCENET, SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE, "invalid pool size");
627 } else if (calloutPri < 0x08 || calloutPri > 0x77) {
628 return hleLogError(SCENET, SCE_KERNEL_ERROR_ILLEGAL_PRIORITY, "invalid callout thread priority");
629 } else if (netinitPri < 0x08 || netinitPri > 0x77) {
630 return hleLogError(SCENET, SCE_KERNEL_ERROR_ILLEGAL_PRIORITY, "invalid init thread priority");
631 }
632
633 // TODO: Should also start the threads, probably? For now, let's just allocate.
634 // TODO: Respect the stack size if firmware set to 1.50?
635 u32 stackSize = 4096;
636 netThread1Addr = AllocUser(stackSize, true, "netstack1");
637 if (netThread1Addr == 0) {
638 return hleLogError(SCENET, SCE_KERNEL_ERROR_NO_MEMORY, "unable to allocate thread");
639 }
640 netThread2Addr = AllocUser(stackSize, true, "netstack2");
641 if (netThread2Addr == 0) {
642 FreeUser(netThread1Addr);
643 return hleLogError(SCENET, SCE_KERNEL_ERROR_NO_MEMORY, "unable to allocate thread");
644 }
645
646 netPoolAddr = AllocUser(poolSize, false, "netpool");
647 if (netPoolAddr == 0) {
648 FreeUser(netThread1Addr);
649 FreeUser(netThread2Addr);
650 return hleLogError(SCENET, SCE_KERNEL_ERROR_NO_MEMORY, "unable to allocate pool");
651 }
652
653 WARN_LOG(SCENET, "sceNetInit(poolsize=%d, calloutpri=%i, calloutstack=%d, netintrpri=%i, netintrstack=%d) at %08x", poolSize, calloutPri, calloutStack, netinitPri, netinitStack, currentMIPS->pc);
654
655 netMallocStat.pool = poolSize - 0x20; // On Vantage Master Portable this is slightly (32 bytes) smaller than the poolSize arg when tested with JPCSP + prx files
656 netMallocStat.maximum = 0x4050; // Dummy maximum foot print
657 netMallocStat.free = netMallocStat.pool; // Dummy free size, we should set this high enough to prevent any issue (ie. Vantage Master Portable), this is probably the only field being checked by games?
658
659 // Clear Socket Translator Memory
660 memset(&adhocSockets, 0, sizeof(adhocSockets));
661
662 netInited = true;
663 return hleLogSuccessI(SCENET, 0);
664 }
665
666 // Free(delete) thread info / data.
667 // Normal usage: sceKernelDeleteThread followed by sceNetFreeThreadInfo with the same threadID as argument
sceNetFreeThreadinfo(SceUID thid)668 static int sceNetFreeThreadinfo(SceUID thid) {
669 ERROR_LOG(SCENET, "UNIMPL sceNetFreeThreadinfo(%i)", thid);
670
671 return 0;
672 }
673
674 // Abort a thread.
sceNetThreadAbort(SceUID thid)675 static int sceNetThreadAbort(SceUID thid) {
676 ERROR_LOG(SCENET, "UNIMPL sceNetThreadAbort(%i)", thid);
677
678 return 0;
679 }
680
sceWlanGetEtherAddr(u32 addrAddr)681 static u32 sceWlanGetEtherAddr(u32 addrAddr) {
682 if (!Memory::IsValidRange(addrAddr, 6)) {
683 // More correctly, it should crash.
684 return hleLogError(SCENET, SCE_KERNEL_ERROR_ILLEGAL_ADDR, "illegal address");
685 }
686
687 u8 *addr = Memory::GetPointer(addrAddr);
688 if (PPSSPP_ID > 1) {
689 Memory::Memset(addrAddr, PPSSPP_ID, 6);
690 // Making sure the 1st 2-bits on the 1st byte of OUI are zero to prevent issue with some games (ie. Gran Turismo)
691 addr[0] &= 0xfc;
692 } else {
693 // Read MAC Address from config
694 if (!ParseMacAddress(g_Config.sMACAddress.c_str(), addr)) {
695 ERROR_LOG(SCENET, "Error parsing mac address %s", g_Config.sMACAddress.c_str());
696 Memory::Memset(addrAddr, 0, 6);
697 }
698 }
699 NotifyMemInfo(MemBlockFlags::WRITE, addrAddr, 6, "WlanEtherAddr");
700
701 return hleLogSuccessI(SCENET, hleDelayResult(0, "get ether mac", 200));
702 }
703
sceNetGetLocalEtherAddr(u32 addrAddr)704 static u32 sceNetGetLocalEtherAddr(u32 addrAddr) {
705 // FIXME: Return 0x80410180 (pspnet[_core] error code?) before successful attempt to Create/Connect/Join a Group? (ie. adhocctlCurrentMode == ADHOCCTL_MODE_NONE)
706 if (adhocctlCurrentMode == ADHOCCTL_MODE_NONE)
707 return hleLogDebug(SCENET, 0x80410180, "address not available?");
708
709 return sceWlanGetEtherAddr(addrAddr);
710 }
711
sceWlanDevIsPowerOn()712 static u32 sceWlanDevIsPowerOn() {
713 return hleLogSuccessVerboseI(SCENET, g_Config.bEnableWlan ? 1 : 0);
714 }
715
sceWlanGetSwitchState()716 static u32 sceWlanGetSwitchState() {
717 return hleLogSuccessVerboseI(SCENET, g_Config.bEnableWlan ? 1 : 0);
718 }
719
720 // Probably a void function, but often returns a useful value.
sceNetEtherNtostr(u32 macPtr,u32 bufferPtr)721 static void sceNetEtherNtostr(u32 macPtr, u32 bufferPtr) {
722 DEBUG_LOG(SCENET, "sceNetEtherNtostr(%08x, %08x) at %08x", macPtr, bufferPtr, currentMIPS->pc);
723
724 if (Memory::IsValidAddress(bufferPtr) && Memory::IsValidAddress(macPtr)) {
725 char *buffer = (char *)Memory::GetPointer(bufferPtr);
726 const u8 *mac = Memory::GetPointer(macPtr);
727
728 // MAC address is always 6 bytes / 48 bits.
729 sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x",
730 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
731
732 VERBOSE_LOG(SCENET, "sceNetEtherNtostr - [%s]", buffer);
733 }
734 }
735
hex_to_digit(int c)736 static int hex_to_digit(int c) {
737 if (c >= '0' && c <= '9')
738 return c - '0';
739 if (c >= 'a' && c <= 'f')
740 return c - 'a' + 10;
741 if (c >= 'A' && c <= 'F')
742 return c - 'A' + 10;
743 return -1;
744 }
745
746 // Probably a void function, but sometimes returns a useful-ish value.
sceNetEtherStrton(u32 bufferPtr,u32 macPtr)747 static void sceNetEtherStrton(u32 bufferPtr, u32 macPtr) {
748 DEBUG_LOG(SCENET, "sceNetEtherStrton(%08x, %08x)", bufferPtr, macPtr);
749
750 if (Memory::IsValidAddress(bufferPtr) && Memory::IsValidAddress(macPtr)) {
751 const char *buffer = (char *)Memory::GetPointer(bufferPtr);
752 u8 *mac = Memory::GetPointer(macPtr);
753
754 // MAC address is always 6 pairs of hex digits.
755 // TODO: Funny stuff happens if it's too short.
756 u8 value = 0;
757 for (int i = 0; i < 6 && *buffer != 0; ++i) {
758 value = 0;
759
760 int c = hex_to_digit(*buffer++);
761 if (c != -1) {
762 value |= c << 4;
763 }
764 c = hex_to_digit(*buffer++);
765 if (c != -1) {
766 value |= c;
767 }
768
769 *mac++ = value;
770
771 // Skip a single character in between.
772 // TODO: Strange behavior on the PSP, let's just null check.
773 if (*buffer++ == 0) {
774 break;
775 }
776 }
777
778 VERBOSE_LOG(SCENET, "sceNetEtherStrton - [%s]", mac2str((SceNetEtherAddr*)Memory::GetPointer(macPtr)).c_str());
779 // Seems to maybe kinda return the last value. Probably returns void.
780 //return value;
781 }
782 }
783
784
785 // Write static data since we don't actually manage any memory for sceNet* yet.
sceNetGetMallocStat(u32 statPtr)786 static int sceNetGetMallocStat(u32 statPtr) {
787 VERBOSE_LOG(SCENET, "UNTESTED sceNetGetMallocStat(%x) at %08x", statPtr, currentMIPS->pc);
788 if(Memory::IsValidAddress(statPtr))
789 Memory::WriteStruct(statPtr, &netMallocStat);
790 else
791 ERROR_LOG(SCENET, "UNTESTED sceNetGetMallocStat(%x): tried to request invalid address!", statPtr);
792
793 return 0;
794 }
795
sceNetInetInit()796 static int sceNetInetInit() {
797 ERROR_LOG(SCENET, "UNIMPL sceNetInetInit()");
798 if (netInetInited) return ERROR_NET_INET_ALREADY_INITIALIZED;
799 netInetInited = true;
800
801 return 0;
802 }
803
sceNetInetTerm()804 int sceNetInetTerm() {
805 ERROR_LOG(SCENET, "UNIMPL sceNetInetTerm()");
806 netInetInited = false;
807
808 return 0;
809 }
810
NetApctl_InitInfo()811 void NetApctl_InitInfo() {
812 memset(&netApctlInfo, 0, sizeof(netApctlInfo));
813 // Set dummy/fake values, these probably not suppose to have valid info before connected to an AP, right?
814 std::string APname = "Wifi"; // fake AP/hotspot
815 truncate_cpy(netApctlInfo.name, sizeof(netApctlInfo.name), APname.c_str());
816 truncate_cpy(netApctlInfo.ssid, sizeof(netApctlInfo.ssid), APname.c_str());
817 memcpy(netApctlInfo.bssid, "\1\1\2\2\3\3", sizeof(netApctlInfo.bssid)); // fake AP's mac address
818 netApctlInfo.ssidLength = static_cast<unsigned int>(APname.length());
819 netApctlInfo.strength = 99;
820 netApctlInfo.channel = g_Config.iWlanAdhocChannel;
821 if (netApctlInfo.channel == PSP_SYSTEMPARAM_ADHOC_CHANNEL_AUTOMATIC) netApctlInfo.channel = defaultWlanChannel;
822 // Get Local IP Address
823 sockaddr_in sockAddr;
824 getLocalIp(&sockAddr); // This will be valid IP, we probably not suppose to have a valid IP before connected to any AP, right?
825 char ipstr[INET_ADDRSTRLEN] = "127.0.0.1"; // Patapon 3 seems to try to get current IP using ApctlGetInfo() right after ApctlInit(), what kind of IP should we use as default before ApctlConnect()? it shouldn't be a valid IP, right?
826 inet_ntop(AF_INET, &sockAddr.sin_addr, ipstr, sizeof(ipstr));
827 truncate_cpy(netApctlInfo.ip, sizeof(netApctlInfo.ip), ipstr);
828 // Change the last number to 1 to indicate a common dns server/internet gateway
829 ((u8*)&sockAddr.sin_addr.s_addr)[3] = 1;
830 inet_ntop(AF_INET, &sockAddr.sin_addr, ipstr, sizeof(ipstr));
831 truncate_cpy(netApctlInfo.gateway, sizeof(netApctlInfo.gateway), ipstr);
832 truncate_cpy(netApctlInfo.primaryDns, sizeof(netApctlInfo.primaryDns), ipstr);
833 truncate_cpy(netApctlInfo.secondaryDns, sizeof(netApctlInfo.secondaryDns), "8.8.8.8");
834 truncate_cpy(netApctlInfo.subNetMask, sizeof(netApctlInfo.subNetMask), "255.255.255.0");
835 }
836
sceNetApctlInit(int stackSize,int initPriority)837 static int sceNetApctlInit(int stackSize, int initPriority) {
838 WARN_LOG(SCENET, "UNTESTED %s(%i, %i)", __FUNCTION__, stackSize, initPriority);
839 if (netApctlInited)
840 return ERROR_NET_APCTL_ALREADY_INITIALIZED;
841
842 apctlEvents.clear();
843 netApctlState = PSP_NET_APCTL_STATE_DISCONNECTED;
844
845 // Set default value before connected to an AP
846 memset(&netApctlInfo, 0, sizeof(netApctlInfo)); // NetApctl_InitInfo();
847 std::string APname = "Wifi"; // fake AP/hotspot
848 truncate_cpy(netApctlInfo.name, sizeof(netApctlInfo.name), APname.c_str());
849 truncate_cpy(netApctlInfo.ssid, sizeof(netApctlInfo.ssid), APname.c_str());
850 memcpy(netApctlInfo.bssid, "\1\1\2\2\3\3", sizeof(netApctlInfo.bssid)); // fake AP's mac address
851 netApctlInfo.ssidLength = static_cast<unsigned int>(APname.length());
852 truncate_cpy(netApctlInfo.ip, sizeof(netApctlInfo.ip), "0.0.0.0");
853 truncate_cpy(netApctlInfo.gateway, sizeof(netApctlInfo.gateway), "0.0.0.0");
854 truncate_cpy(netApctlInfo.primaryDns, sizeof(netApctlInfo.primaryDns), "0.0.0.0");
855 truncate_cpy(netApctlInfo.secondaryDns, sizeof(netApctlInfo.secondaryDns), "0.0.0.0");
856 truncate_cpy(netApctlInfo.subNetMask, sizeof(netApctlInfo.subNetMask), "0.0.0.0");
857
858 // Create APctl fake-Thread
859 netValidateLoopMemory();
860 apctlThreadID = __KernelCreateThread("ApctlThread", __KernelGetCurThreadModuleId(), apctlThreadHackAddr, initPriority, stackSize, PSP_THREAD_ATTR_USER, 0, true);
861 if (apctlThreadID > 0) {
862 __KernelStartThread(apctlThreadID, 0, 0);
863 }
864
865 netApctlInited = true;
866
867 return 0;
868 }
869
NetApctl_Term()870 int NetApctl_Term() {
871 // Cleanup Apctl resources
872 // Delete fake PSP Thread
873 if (apctlThreadID != 0) {
874 __KernelStopThread(apctlThreadID, SCE_KERNEL_ERROR_THREAD_TERMINATED, "ApctlThread stopped");
875 __KernelDeleteThread(apctlThreadID, SCE_KERNEL_ERROR_THREAD_TERMINATED, "ApctlThread deleted");
876 apctlThreadID = 0;
877 }
878
879 netApctlInited = false;
880 netApctlState = PSP_NET_APCTL_STATE_DISCONNECTED;
881
882 return 0;
883 }
884
sceNetApctlTerm()885 int sceNetApctlTerm() {
886 WARN_LOG(SCENET, "UNTESTED %s()", __FUNCTION__);
887 return NetApctl_Term();
888 }
889
sceNetApctlGetInfo(int code,u32 pInfoAddr)890 static int sceNetApctlGetInfo(int code, u32 pInfoAddr) {
891 WARN_LOG(SCENET, "UNTESTED %s(%i, %08x)", __FUNCTION__, code, pInfoAddr);
892
893 if (!netApctlInited)
894 return hleLogError(SCENET, ERROR_NET_APCTL_NOT_IN_BSS, "apctl not in bss"); // Only have valid info after joining an AP and got an IP, right?
895
896 if (!Memory::IsValidAddress(pInfoAddr))
897 return hleLogError(SCENET, -1, "apctl invalid arg");
898
899 u8* info = Memory::GetPointer(pInfoAddr); // FIXME: Points to a union instead of a struct thus each field have the same address
900
901 switch (code) {
902 case PSP_NET_APCTL_INFO_PROFILE_NAME:
903 Memory::WriteStruct(pInfoAddr, &netApctlInfo.name);
904 DEBUG_LOG(SCENET, "ApctlInfo - ProfileName: %s", netApctlInfo.name);
905 break;
906 case PSP_NET_APCTL_INFO_BSSID:
907 Memory::WriteStruct(pInfoAddr, &netApctlInfo.bssid);
908 DEBUG_LOG(SCENET, "ApctlInfo - BSSID: %s", mac2str((SceNetEtherAddr*)&netApctlInfo.bssid).c_str());
909 break;
910 case PSP_NET_APCTL_INFO_SSID:
911 Memory::WriteStruct(pInfoAddr, &netApctlInfo.ssid);
912 DEBUG_LOG(SCENET, "ApctlInfo - SSID: %s", netApctlInfo.ssid);
913 break;
914 case PSP_NET_APCTL_INFO_SSID_LENGTH:
915 Memory::WriteStruct(pInfoAddr, &netApctlInfo.ssidLength);
916 break;
917 case PSP_NET_APCTL_INFO_SECURITY_TYPE:
918 Memory::WriteStruct(pInfoAddr, &netApctlInfo.securityType);
919 break;
920 case PSP_NET_APCTL_INFO_STRENGTH:
921 Memory::WriteStruct(pInfoAddr, &netApctlInfo.strength);
922 break;
923 case PSP_NET_APCTL_INFO_CHANNEL:
924 Memory::WriteStruct(pInfoAddr, &netApctlInfo.channel);
925 break;
926 case PSP_NET_APCTL_INFO_POWER_SAVE:
927 Memory::WriteStruct(pInfoAddr, &netApctlInfo.powerSave);
928 break;
929 case PSP_NET_APCTL_INFO_IP:
930 Memory::WriteStruct(pInfoAddr, &netApctlInfo.ip);
931 DEBUG_LOG(SCENET, "ApctlInfo - IP: %s", netApctlInfo.ip);
932 break;
933 case PSP_NET_APCTL_INFO_SUBNETMASK:
934 Memory::WriteStruct(pInfoAddr, &netApctlInfo.subNetMask);
935 DEBUG_LOG(SCENET, "ApctlInfo - SubNet Mask: %s", netApctlInfo.subNetMask);
936 break;
937 case PSP_NET_APCTL_INFO_GATEWAY:
938 Memory::WriteStruct(pInfoAddr, &netApctlInfo.gateway);
939 DEBUG_LOG(SCENET, "ApctlInfo - Gateway IP: %s", netApctlInfo.gateway);
940 break;
941 case PSP_NET_APCTL_INFO_PRIMDNS:
942 Memory::WriteStruct(pInfoAddr, &netApctlInfo.primaryDns);
943 DEBUG_LOG(SCENET, "ApctlInfo - Primary DNS: %s", netApctlInfo.primaryDns);
944 break;
945 case PSP_NET_APCTL_INFO_SECDNS:
946 Memory::WriteStruct(pInfoAddr, &netApctlInfo.secondaryDns);
947 DEBUG_LOG(SCENET, "ApctlInfo - Secondary DNS: %s", netApctlInfo.secondaryDns);
948 break;
949 case PSP_NET_APCTL_INFO_USE_PROXY:
950 Memory::WriteStruct(pInfoAddr, &netApctlInfo.useProxy);
951 break;
952 case PSP_NET_APCTL_INFO_PROXY_URL:
953 Memory::WriteStruct(pInfoAddr, &netApctlInfo.proxyUrl);
954 DEBUG_LOG(SCENET, "ApctlInfo - Proxy URL: %s", netApctlInfo.proxyUrl);
955 break;
956 case PSP_NET_APCTL_INFO_PROXY_PORT:
957 Memory::WriteStruct(pInfoAddr, &netApctlInfo.proxyPort);
958 break;
959 case PSP_NET_APCTL_INFO_8021_EAP_TYPE:
960 Memory::WriteStruct(pInfoAddr, &netApctlInfo.eapType);
961 break;
962 case PSP_NET_APCTL_INFO_START_BROWSER:
963 Memory::WriteStruct(pInfoAddr, &netApctlInfo.startBrowser);
964 break;
965 case PSP_NET_APCTL_INFO_WIFISP:
966 Memory::WriteStruct(pInfoAddr, &netApctlInfo.wifisp);
967 break;
968 default:
969 return hleLogError(SCENET, ERROR_NET_APCTL_INVALID_CODE, "apctl invalid code");
970 }
971
972 return hleLogSuccessI(SCENET, 0);
973 }
974
NetApctl_AddHandler(u32 handlerPtr,u32 handlerArg)975 int NetApctl_AddHandler(u32 handlerPtr, u32 handlerArg) {
976 bool foundHandler = false;
977 u32 retval = 0;
978 struct ApctlHandler handler;
979 memset(&handler, 0, sizeof(handler));
980
981 while (apctlHandlers.find(retval) != apctlHandlers.end())
982 ++retval;
983
984 handler.entryPoint = handlerPtr;
985 handler.argument = handlerArg;
986
987 for (std::map<int, ApctlHandler>::iterator it = apctlHandlers.begin(); it != apctlHandlers.end(); it++) {
988 if (it->second.entryPoint == handlerPtr) {
989 foundHandler = true;
990 break;
991 }
992 }
993
994 if (!foundHandler && Memory::IsValidAddress(handlerPtr)) {
995 if (apctlHandlers.size() >= MAX_APCTL_HANDLERS) {
996 ERROR_LOG(SCENET, "Failed to Add handler(%x, %x): Too many handlers", handlerPtr, handlerArg);
997 retval = ERROR_NET_ADHOCCTL_TOO_MANY_HANDLERS; // TODO: What's the proper error code for Apctl's TOO_MANY_HANDLERS?
998 return retval;
999 }
1000 apctlHandlers[retval] = handler;
1001 WARN_LOG(SCENET, "Added Apctl handler(%x, %x): %d", handlerPtr, handlerArg, retval);
1002 }
1003 else {
1004 ERROR_LOG(SCENET, "Existing Apctl handler(%x, %x)", handlerPtr, handlerArg);
1005 }
1006
1007 // The id to return is the number of handlers currently registered
1008 return retval;
1009 }
1010
1011 // TODO: How many handlers can the PSP actually have for Apctl?
1012 // TODO: Should we allow the same handler to be added more than once?
sceNetApctlAddHandler(u32 handlerPtr,u32 handlerArg)1013 static u32 sceNetApctlAddHandler(u32 handlerPtr, u32 handlerArg) {
1014 INFO_LOG(SCENET, "%s(%08x, %08x)", __FUNCTION__, handlerPtr, handlerArg);
1015 return NetApctl_AddHandler(handlerPtr, handlerArg);
1016 }
1017
NetApctl_DelHandler(u32 handlerID)1018 int NetApctl_DelHandler(u32 handlerID) {
1019 if (apctlHandlers.find(handlerID) != apctlHandlers.end()) {
1020 apctlHandlers.erase(handlerID);
1021 WARN_LOG(SCENET, "Deleted Apctl handler: %d", handlerID);
1022 }
1023 else {
1024 ERROR_LOG(SCENET, "Invalid Apctl handler: %d", handlerID);
1025 }
1026 return 0;
1027 }
1028
sceNetApctlDelHandler(u32 handlerID)1029 static int sceNetApctlDelHandler(u32 handlerID) {
1030 INFO_LOG(SCENET, "%s(%d)", __FUNCTION__, handlerID);
1031 return NetApctl_DelHandler(handlerID);
1032 }
1033
sceNetInetInetAton(const char * hostname,u32 addrPtr)1034 static int sceNetInetInetAton(const char *hostname, u32 addrPtr) {
1035 ERROR_LOG(SCENET, "UNIMPL sceNetInetInetAton(%s, %08x)", hostname, addrPtr);
1036 return -1;
1037 }
1038
sceNetInetPoll(void * fds,u32 nfds,int timeout)1039 int sceNetInetPoll(void *fds, u32 nfds, int timeout) { // timeout in miliseconds
1040 DEBUG_LOG(SCENET, "UNTESTED sceNetInetPoll(%p, %d, %i) at %08x", fds, nfds, timeout, currentMIPS->pc);
1041 int retval = -1;
1042 SceNetInetPollfd *fdarray = (SceNetInetPollfd *)fds; // SceNetInetPollfd/pollfd, sceNetInetPoll() have similarity to BSD poll() but pollfd have different size on 64bit
1043 //#ifdef _WIN32
1044 //WSAPoll only available for Vista or newer, so we'll use an alternative way for XP since Windows doesn't have poll function like *NIX
1045 if (nfds > FD_SETSIZE) return -1;
1046 fd_set readfds, writefds, exceptfds;
1047 FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds);
1048 for (int i = 0; i < (s32)nfds; i++) {
1049 if (fdarray[i].events & (INET_POLLRDNORM)) FD_SET(fdarray[i].fd, &readfds); // (POLLRDNORM | POLLIN)
1050 if (fdarray[i].events & (INET_POLLWRNORM)) FD_SET(fdarray[i].fd, &writefds); // (POLLWRNORM | POLLOUT)
1051 //if (fdarray[i].events & (ADHOC_EV_ALERT)) // (POLLRDBAND | POLLPRI) // POLLERR
1052 FD_SET(fdarray[i].fd, &exceptfds);
1053 fdarray[i].revents = 0;
1054 }
1055 timeval tmout;
1056 tmout.tv_sec = timeout / 1000; // seconds
1057 tmout.tv_usec = (timeout % 1000) * 1000; // microseconds
1058 retval = select(nfds, &readfds, &writefds, &exceptfds, &tmout);
1059 if (retval < 0) return -1;
1060 retval = 0;
1061 for (int i = 0; i < (s32)nfds; i++) {
1062 if (FD_ISSET(fdarray[i].fd, &readfds)) fdarray[i].revents |= INET_POLLRDNORM; //POLLIN
1063 if (FD_ISSET(fdarray[i].fd, &writefds)) fdarray[i].revents |= INET_POLLWRNORM; //POLLOUT
1064 fdarray[i].revents &= fdarray[i].events;
1065 if (FD_ISSET(fdarray[i].fd, &exceptfds)) fdarray[i].revents |= ADHOC_EV_ALERT; // POLLPRI; // POLLERR; // can be raised on revents regardless of events bitmask?
1066 if (fdarray[i].revents) retval++;
1067 }
1068 //#else
1069 /*
1070 // Doesn't work properly yet
1071 pollfd *fdtmp = (pollfd *)malloc(sizeof(pollfd) * nfds);
1072 // Note: sizeof(pollfd) = 16bytes in 64bit and 8bytes in 32bit, while sizeof(SceNetInetPollfd) is always 8bytes
1073 for (int i = 0; i < (s32)nfds; i++) {
1074 fdtmp[i].fd = fdarray[i].fd;
1075 fdtmp[i].events = 0;
1076 if (fdarray[i].events & INET_POLLRDNORM) fdtmp[i].events |= (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI);
1077 if (fdarray[i].events & INET_POLLWRNORM) fdtmp[i].events |= (POLLOUT | POLLWRNORM | POLLWRBAND);
1078 fdtmp[i].revents = 0;
1079 fdarray[i].revents = 0;
1080 }
1081 retval = poll(fdtmp, (nfds_t)nfds, timeout); //retval = WSAPoll(fdarray, nfds, timeout);
1082 for (int i = 0; i < (s32)nfds; i++) {
1083 if (fdtmp[i].revents & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) fdarray[i].revents |= INET_POLLRDNORM;
1084 if (fdtmp[i].revents & (POLLOUT | POLLWRNORM | POLLWRBAND)) fdarray[i].revents |= INET_POLLWRNORM;
1085 fdarray[i].revents &= fdarray[i].events;
1086 if (fdtmp[i].revents & POLLERR) fdarray[i].revents |= POLLERR; //INET_POLLERR // can be raised on revents regardless of events bitmask?
1087 }
1088 free(fdtmp);
1089 */
1090 //#endif
1091 return retval;
1092 }
1093
sceNetInetRecv(int socket,u32 bufPtr,u32 bufLen,u32 flags)1094 static int sceNetInetRecv(int socket, u32 bufPtr, u32 bufLen, u32 flags) {
1095 ERROR_LOG(SCENET, "UNIMPL sceNetInetRecv(%i, %08x, %i, %08x)", socket, bufPtr, bufLen, flags);
1096 return -1;
1097 }
1098
sceNetInetSend(int socket,u32 bufPtr,u32 bufLen,u32 flags)1099 static int sceNetInetSend(int socket, u32 bufPtr, u32 bufLen, u32 flags) {
1100 ERROR_LOG(SCENET, "UNIMPL sceNetInetSend(%i, %08x, %i, %08x)", socket, bufPtr, bufLen, flags);
1101 return -1;
1102 }
1103
sceNetInetGetErrno()1104 static int sceNetInetGetErrno() {
1105 ERROR_LOG(SCENET, "UNTESTED sceNetInetGetErrno()");
1106 int error = errno;
1107 switch (error) {
1108 case ETIMEDOUT:
1109 return INET_ETIMEDOUT;
1110 case EISCONN:
1111 return INET_EISCONN;
1112 case EINPROGRESS:
1113 return INET_EINPROGRESS;
1114 //case EAGAIN:
1115 // return INET_EAGAIN;
1116 }
1117 return error; //-1;
1118 }
1119
sceNetInetSocket(int domain,int type,int protocol)1120 static int sceNetInetSocket(int domain, int type, int protocol) {
1121 ERROR_LOG(SCENET, "UNIMPL sceNetInetSocket(%i, %i, %i)", domain, type, protocol);
1122 return -1;
1123 }
1124
sceNetInetSetsockopt(int socket,int level,int optname,u32 optvalPtr,int optlen)1125 static int sceNetInetSetsockopt(int socket, int level, int optname, u32 optvalPtr, int optlen) {
1126 ERROR_LOG(SCENET, "UNIMPL sceNetInetSetsockopt(%i, %i, %i, %08x, %i)", socket, level, optname, optvalPtr, optlen);
1127 return -1;
1128 }
1129
sceNetInetConnect(int socket,u32 sockAddrInternetPtr,int addressLength)1130 static int sceNetInetConnect(int socket, u32 sockAddrInternetPtr, int addressLength) {
1131 ERROR_LOG(SCENET, "UNIMPL sceNetInetConnect(%i, %08x, %i)", socket, sockAddrInternetPtr, addressLength);
1132 return -1;
1133 }
1134
sceNetApctlConnect(int connIndex)1135 int sceNetApctlConnect(int connIndex) {
1136 WARN_LOG(SCENET, "UNTESTED %s(%i)", __FUNCTION__, connIndex);
1137 // Is this connIndex is the index to the scanning's result data or sceNetApctlGetBSSDescIDListUser result?
1138 __UpdateApctlHandlers(0, 0, PSP_NET_APCTL_EVENT_CONNECT_REQUEST, 0);
1139 //hleDelayResult(0, "give time to init/cleanup", adhocEventDelayMS * 1000);
1140 return 0;
1141 }
1142
sceNetApctlDisconnect()1143 static int sceNetApctlDisconnect() {
1144 ERROR_LOG(SCENET, "UNIMPL %s()", __FUNCTION__);
1145 // Like its 'sister' function sceNetAdhocctlDisconnect, we need to alert Apctl handlers that a disconnect took place
1146 // or else games like Phantasy Star Portable 2 will hang at certain points (e.g. returning to the main menu after trying to connect to PSN).
1147
1148 __UpdateApctlHandlers(0, 0, PSP_NET_APCTL_EVENT_DISCONNECT_REQUEST, 0);
1149 return 0;
1150 }
1151
NetApctl_GetState()1152 int NetApctl_GetState() {
1153 return netApctlState;
1154 }
1155
sceNetApctlGetState(u32 pStateAddr)1156 static int sceNetApctlGetState(u32 pStateAddr) {
1157 //if (!netApctlInited) return hleLogError(SCENET, ERROR_NET_APCTL_NOT_IN_BSS, "apctl not in bss");
1158
1159 // Valid Arguments
1160 if (Memory::IsValidAddress(pStateAddr)) {
1161 // Return Thread Status
1162 Memory::Write_U32(NetApctl_GetState(), pStateAddr);
1163 // Return Success
1164 return hleLogSuccessI(SCENET, 0);
1165 }
1166
1167 return hleLogError(SCENET, -1, "apctl invalid arg"); // 0x8002013A or ERROR_NET_WLAN_INVALID_ARG ?
1168 }
1169
NetApctl_ScanUser()1170 int NetApctl_ScanUser() {
1171 // Scan probably only works when not in connected state, right?
1172 if (netApctlState != PSP_NET_APCTL_STATE_DISCONNECTED)
1173 return hleLogError(SCENET, ERROR_NET_APCTL_NOT_DISCONNECTED, "apctl not disconnected");
1174
1175 __UpdateApctlHandlers(0, 0, PSP_NET_APCTL_EVENT_SCAN_REQUEST, 0);
1176 return 0;
1177 }
1178
sceNetApctlScanUser()1179 static int sceNetApctlScanUser() {
1180 ERROR_LOG(SCENET, "UNIMPL %s()", __FUNCTION__);
1181 return NetApctl_ScanUser();
1182 }
1183
NetApctl_GetBSSDescIDListUser(u32 sizeAddr,u32 bufAddr)1184 int NetApctl_GetBSSDescIDListUser(u32 sizeAddr, u32 bufAddr) {
1185 const int userInfoSize = 8; // 8 bytes per entry (next address + entry id)
1186 // Faking 4 entries, games like MGS:PW Recruit will need to have a different AP for each entry
1187 int entries = 4;
1188 if (!Memory::IsValidAddress(sizeAddr) || !Memory::IsValidAddress(bufAddr))
1189 return hleLogError(SCENET, -1, "apctl invalid arg"); // 0x8002013A or ERROR_NET_WLAN_INVALID_ARG ?
1190
1191 int size = Memory::Read_U32(sizeAddr);
1192 // Return size required
1193 Memory::Write_U32(entries * userInfoSize, sizeAddr);
1194
1195 if (bufAddr != 0 && Memory::IsValidAddress(sizeAddr)) {
1196 int offset = 0;
1197 for (int i = 0; i < entries; i++) {
1198 // Check if enough space available to write the next structure
1199 if (offset + userInfoSize > size) {
1200 break;
1201 }
1202
1203 DEBUG_LOG(SCENET, "%s writing ID#%d to %08x", __FUNCTION__, i, bufAddr + offset);
1204
1205 // Pointer to next Network structure in list
1206 Memory::Write_U32((i + 1) * userInfoSize + bufAddr, bufAddr + offset);
1207 offset += 4;
1208
1209 // Entry ID
1210 Memory::Write_U32(i, bufAddr + offset);
1211 offset += 4;
1212 }
1213 // Fix the last Pointer
1214 if (offset > 0)
1215 Memory::Write_U32(0, bufAddr + offset - userInfoSize);
1216 }
1217
1218 return 0;
1219 }
1220
sceNetApctlGetBSSDescIDListUser(u32 sizeAddr,u32 bufAddr)1221 static int sceNetApctlGetBSSDescIDListUser(u32 sizeAddr, u32 bufAddr) {
1222 WARN_LOG(SCENET, "UNTESTED %s(%08x, %08x)", __FUNCTION__, sizeAddr, bufAddr);
1223 return NetApctl_GetBSSDescIDListUser(sizeAddr, bufAddr);
1224 }
1225
NetApctl_GetBSSDescEntryUser(int entryId,int infoId,u32 resultAddr)1226 int NetApctl_GetBSSDescEntryUser(int entryId, int infoId, u32 resultAddr) {
1227 if (!Memory::IsValidAddress(resultAddr))
1228 return hleLogError(SCENET, -1, "apctl invalid arg"); // 0x8002013A or ERROR_NET_WLAN_INVALID_ARG ?
1229
1230 // Generate an SSID name
1231 char dummySSID[APCTL_SSID_MAXLEN] = "WifiAP0";
1232 dummySSID[6] += static_cast<char>(entryId);
1233
1234 switch (infoId) {
1235 case PSP_NET_APCTL_DESC_IBSS: // IBSS, 6 bytes
1236 if (entryId == 0)
1237 Memory::WriteStruct(resultAddr, &netApctlInfo.bssid);
1238 else {
1239 // Generate a BSSID/MAC address
1240 char dummyMAC[ETHER_ADDR_LEN];
1241 memset(dummyMAC, entryId, sizeof(dummyMAC));
1242 // Making sure the 1st 2-bits on the 1st byte of OUI are zero to prevent issue with some games (ie. Gran Turismo)
1243 dummyMAC[0] &= 0xfc;
1244 Memory::WriteStruct(resultAddr, &dummyMAC);
1245 }
1246 break;
1247 case PSP_NET_APCTL_DESC_SSID_NAME:
1248 // Return 32 bytes
1249 if (entryId == 0)
1250 Memory::WriteStruct(resultAddr, &netApctlInfo.ssid);
1251 else {
1252 Memory::WriteStruct(resultAddr, &dummySSID);
1253 }
1254 break;
1255 case PSP_NET_APCTL_DESC_SSID_NAME_LENGTH:
1256 // Return one 32-bit value
1257 if (entryId == 0)
1258 Memory::WriteStruct(resultAddr, &netApctlInfo.ssidLength);
1259 else {
1260 // Calculate the SSID length
1261 Memory::Write_U32((u32)strlen(dummySSID), resultAddr);
1262 }
1263 break;
1264 case PSP_NET_APCTL_DESC_CHANNEL:
1265 // FIXME: Return one 1 byte value or may be 32-bit if this is not a channel?
1266 if (entryId == 0)
1267 Memory::WriteStruct(resultAddr, &netApctlInfo.channel);
1268 else {
1269 // Generate channel for testing purposes, not even sure whether this is channel or not, MGS:PW seems to treat the data as u8
1270 Memory::Write_U8(entryId, resultAddr);
1271 }
1272 break;
1273 case PSP_NET_APCTL_DESC_SIGNAL_STRENGTH:
1274 // Return 1 byte
1275 if (entryId == 0)
1276 Memory::WriteStruct(resultAddr, &netApctlInfo.strength);
1277 else {
1278 // Randomize signal strength between 1%~99% since games like MGS:PW are using signal strength to determine the strength of the recruit
1279 Memory::Write_U8((int)(((float)rand() / (float)RAND_MAX) * 99.0 + 1.0), resultAddr);
1280 }
1281 break;
1282 case PSP_NET_APCTL_DESC_SECURITY:
1283 // Return one 32-bit value
1284 Memory::WriteStruct(resultAddr, &netApctlInfo.securityType);
1285 break;
1286 default:
1287 return hleLogError(SCENET, ERROR_NET_APCTL_INVALID_CODE, "unknown info id");
1288 }
1289
1290 return 0;
1291 }
1292
sceNetApctlGetBSSDescEntryUser(int entryId,int infoId,u32 resultAddr)1293 static int sceNetApctlGetBSSDescEntryUser(int entryId, int infoId, u32 resultAddr) {
1294 WARN_LOG(SCENET, "UNTESTED %s(%i, %i, %08x)", __FUNCTION__, entryId, infoId, resultAddr);
1295 return NetApctl_GetBSSDescEntryUser(entryId, infoId, resultAddr);
1296 }
1297
sceNetApctlScanSSID2()1298 static int sceNetApctlScanSSID2() {
1299 WARN_LOG(SCENET, "UNTESTED %s() at %08x", __FUNCTION__, currentMIPS->pc);
1300 return NetApctl_ScanUser();
1301 }
1302
1303 /**************
1304 * Arg1 = output buffer size being filled? (initially the same with Arg3 ?)
1305 * Arg2 = output buffer? (linked list where the 1st 32-bit is the next address? followed by entry Id? ie. 8-bytes per entry?)
1306 * Arg3 = max buffer size? (ie. 0x100 ?)
1307 * Arg4 = input flag? (initially 0/1 ?)
1308 ***************/
sceNetApctlGetBSSDescIDList2(u32 Arg1,u32 Arg2,u32 Arg3,u32 Arg4)1309 static int sceNetApctlGetBSSDescIDList2(u32 Arg1, u32 Arg2, u32 Arg3, u32 Arg4) {
1310 WARN_LOG(SCENET, "UNTESTED %s(%08x, %08x, %08x, %08x) at %08x", __FUNCTION__, Arg1, Arg2, Arg3, Arg4, currentMIPS->pc);
1311 return NetApctl_GetBSSDescIDListUser(Arg1, Arg2);
1312 }
1313
1314 /**************
1315 * Arg1 = a value returned from sceNetApctlGetBSSDescIDList2 ? entryId?
1316 * Arg2 = input field type within the entry desc (ie. PSP_NET_APCTL_DESC_SSID_NAME ?)
1317 * Arg3 = output buffer for retrieved entry data? (max size = 32 bytes? ie. APCTL_SSID_MAXLEN ? or similar to SceNetApctlInfoInternal union ?)
1318 ***************/
sceNetApctlGetBSSDescEntry2(int entryId,int infoId,u32 resultAddr)1319 static int sceNetApctlGetBSSDescEntry2(int entryId, int infoId, u32 resultAddr) {
1320 WARN_LOG(SCENET, "UNTESTED %s(%i, %i, %08x) at %08x", __FUNCTION__, entryId, infoId, resultAddr, currentMIPS->pc);
1321 return NetApctl_GetBSSDescEntryUser(entryId, infoId, resultAddr);
1322 }
1323
sceNetResolverInit()1324 static int sceNetResolverInit()
1325 {
1326 ERROR_LOG(SCENET, "UNIMPL %s()", __FUNCTION__);
1327 return 0;
1328 }
1329
sceNetApctlAddInternalHandler(u32 handlerPtr,u32 handlerArg)1330 static int sceNetApctlAddInternalHandler(u32 handlerPtr, u32 handlerArg) {
1331 ERROR_LOG(SCENET, "UNIMPL %s(%08x, %08x)", __FUNCTION__, handlerPtr, handlerArg);
1332 // This seems to be a 2nd kind of handler
1333 return NetApctl_AddHandler(handlerPtr, handlerArg);
1334 }
1335
sceNetApctlDelInternalHandler(u32 handlerID)1336 static int sceNetApctlDelInternalHandler(u32 handlerID) {
1337 ERROR_LOG(SCENET, "UNIMPL %s(%i)", __FUNCTION__, handlerID);
1338 // This seems to be a 2nd kind of handler
1339 return NetApctl_DelHandler(handlerID);
1340 }
1341
sceNetApctl_A7BB73DF(u32 handlerPtr,u32 handlerArg)1342 static int sceNetApctl_A7BB73DF(u32 handlerPtr, u32 handlerArg) {
1343 ERROR_LOG(SCENET, "UNIMPL %s(%08x, %08x)", __FUNCTION__, handlerPtr, handlerArg);
1344 // This seems to be a 3rd kind of handler
1345 return sceNetApctlAddHandler(handlerPtr, handlerArg);
1346 }
1347
sceNetApctl_6F5D2981(u32 handlerID)1348 static int sceNetApctl_6F5D2981(u32 handlerID) {
1349 ERROR_LOG(SCENET, "UNIMPL %s(%i)", __FUNCTION__, handlerID);
1350 // This seems to be a 3rd kind of handler
1351 return sceNetApctlDelHandler(handlerID);
1352 }
1353
sceNetApctl_lib2_69745F0A(int handlerId)1354 static int sceNetApctl_lib2_69745F0A(int handlerId) {
1355 return hleLogError(SCENET, 0, "unimplemented");
1356 }
1357
sceNetApctl_lib2_4C19731F(int code,u32 pInfoAddr)1358 static int sceNetApctl_lib2_4C19731F(int code, u32 pInfoAddr) {
1359 ERROR_LOG(SCENET, "UNIMPL %s(%i, %08x)", __FUNCTION__, code, pInfoAddr);
1360 return sceNetApctlGetInfo(code, pInfoAddr);
1361 }
1362
sceNetApctlScan()1363 static int sceNetApctlScan() {
1364 ERROR_LOG(SCENET, "UNIMPL %s()", __FUNCTION__);
1365 return NetApctl_ScanUser();
1366 }
1367
sceNetApctlGetBSSDescIDList(u32 sizeAddr,u32 bufAddr)1368 static int sceNetApctlGetBSSDescIDList(u32 sizeAddr, u32 bufAddr) {
1369 ERROR_LOG(SCENET, "UNIMPL %s(%08x, %08x)", __FUNCTION__, sizeAddr, bufAddr);
1370 return sceNetApctlGetBSSDescIDListUser(sizeAddr, bufAddr);
1371 }
1372
sceNetApctlGetBSSDescEntry(int entryId,int infoId,u32 resultAddr)1373 static int sceNetApctlGetBSSDescEntry(int entryId, int infoId, u32 resultAddr) {
1374 ERROR_LOG(SCENET, "UNIMPL %s(%i, %i, %08x)", __FUNCTION__, entryId, infoId, resultAddr);
1375 return sceNetApctlGetBSSDescEntryUser(entryId, infoId, resultAddr);
1376 }
1377
sceNetApctl_lib2_C20A144C(int connIndex,u32 ps3MacAddressPtr)1378 static int sceNetApctl_lib2_C20A144C(int connIndex, u32 ps3MacAddressPtr) {
1379 ERROR_LOG(SCENET, "UNIMPL %s(%i, %08x)", __FUNCTION__, connIndex, ps3MacAddressPtr);
1380 return sceNetApctlConnect(connIndex);
1381 }
1382
1383
sceNetUpnpInit(int unknown1,int unknown2)1384 static int sceNetUpnpInit(int unknown1,int unknown2)
1385 {
1386 ERROR_LOG_REPORT_ONCE(sceNetUpnpInit, SCENET, "UNIMPLsceNetUpnpInit %d,%d",unknown1,unknown2);
1387 return 0;
1388 }
1389
sceNetUpnpStart()1390 static int sceNetUpnpStart()
1391 {
1392 ERROR_LOG(SCENET, "UNIMPLsceNetUpnpStart");
1393 return 0;
1394 }
1395
sceNetUpnpStop()1396 static int sceNetUpnpStop()
1397 {
1398 ERROR_LOG(SCENET, "UNIMPLsceNetUpnpStop");
1399 return 0;
1400 }
1401
sceNetUpnpTerm()1402 static int sceNetUpnpTerm()
1403 {
1404 ERROR_LOG(SCENET, "UNIMPLsceNetUpnpTerm");
1405 return 0;
1406 }
1407
sceNetUpnpGetNatInfo()1408 static int sceNetUpnpGetNatInfo()
1409 {
1410 ERROR_LOG(SCENET, "UNIMPLsceNetUpnpGetNatInfo");
1411 return 0;
1412 }
1413
sceNetGetDropRate(u32 dropRateAddr,u32 dropDurationAddr)1414 static int sceNetGetDropRate(u32 dropRateAddr, u32 dropDurationAddr)
1415 {
1416 Memory::Write_U32(netDropRate, dropRateAddr);
1417 Memory::Write_U32(netDropDuration, dropDurationAddr);
1418 return hleLogSuccessInfoI(SCENET, 0);
1419 }
1420
sceNetSetDropRate(u32 dropRate,u32 dropDuration)1421 static int sceNetSetDropRate(u32 dropRate, u32 dropDuration)
1422 {
1423 netDropRate = dropRate;
1424 netDropDuration = dropDuration;
1425 return hleLogSuccessInfoI(SCENET, 0);
1426 }
1427
1428 const HLEFunction sceNet[] = {
1429 {0X39AF39A6, &WrapI_UUUUU<sceNetInit>, "sceNetInit", 'i', "xxxxx"},
1430 {0X281928A9, &WrapU_V<sceNetTerm>, "sceNetTerm", 'x', "" },
1431 {0X89360950, &WrapV_UU<sceNetEtherNtostr>, "sceNetEtherNtostr", 'v', "xx" },
1432 {0XD27961C9, &WrapV_UU<sceNetEtherStrton>, "sceNetEtherStrton", 'v', "xx" },
1433 {0X0BF0A3AE, &WrapU_U<sceNetGetLocalEtherAddr>, "sceNetGetLocalEtherAddr", 'x', "x" },
1434 {0X50647530, &WrapI_I<sceNetFreeThreadinfo>, "sceNetFreeThreadinfo", 'i', "i" },
1435 {0XCC393E48, &WrapI_U<sceNetGetMallocStat>, "sceNetGetMallocStat", 'i', "x" },
1436 {0XAD6844C6, &WrapI_I<sceNetThreadAbort>, "sceNetThreadAbort", 'i', "i" },
1437 };
1438
1439 const HLEFunction sceNetResolver[] = {
1440 {0X224C5F44, nullptr, "sceNetResolverStartNtoA", '?', "" },
1441 {0X244172AF, nullptr, "sceNetResolverCreate", '?', "" },
1442 {0X94523E09, nullptr, "sceNetResolverDelete", '?', "" },
1443 {0XF3370E61, &WrapI_V<sceNetResolverInit>, "sceNetResolverInit", 'i', "" },
1444 {0X808F6063, nullptr, "sceNetResolverStop", '?', "" },
1445 {0X6138194A, nullptr, "sceNetResolverTerm", '?', "" },
1446 {0X629E2FB7, nullptr, "sceNetResolverStartAtoN", '?', "" },
1447 {0X14C17EF9, nullptr, "sceNetResolverStartNtoAAsync", '?', "" },
1448 {0XAAC09184, nullptr, "sceNetResolverStartAtoNAsync", '?', "" },
1449 {0X12748EB9, nullptr, "sceNetResolverWaitAsync", '?', "" },
1450 {0X4EE99358, nullptr, "sceNetResolverPollAsync", '?', "" },
1451 };
1452
1453 const HLEFunction sceNetInet[] = {
1454 {0X17943399, &WrapI_V<sceNetInetInit>, "sceNetInetInit", 'i', "" },
1455 {0X4CFE4E56, nullptr, "sceNetInetShutdown", '?', "" },
1456 {0XA9ED66B9, &WrapI_V<sceNetInetTerm>, "sceNetInetTerm", 'i', "" },
1457 {0X8B7B220F, &WrapI_III<sceNetInetSocket>, "sceNetInetSocket", 'i', "iii" },
1458 {0X2FE71FE7, &WrapI_IIIUI<sceNetInetSetsockopt>, "sceNetInetSetsockopt", 'i', "iiixi"},
1459 {0X4A114C7C, nullptr, "sceNetInetGetsockopt", '?', "" },
1460 {0X410B34AA, &WrapI_IUI<sceNetInetConnect>, "sceNetInetConnect", 'i', "ixi" },
1461 {0X805502DD, nullptr, "sceNetInetCloseWithRST", '?', "" },
1462 {0XD10A1A7A, nullptr, "sceNetInetListen", '?', "" },
1463 {0XDB094E1B, nullptr, "sceNetInetAccept", '?', "" },
1464 {0XFAABB1DD, &WrapI_VUI<sceNetInetPoll>, "sceNetInetPoll", 'i', "pxi" },
1465 {0X5BE8D595, nullptr, "sceNetInetSelect", '?', "" },
1466 {0X8D7284EA, nullptr, "sceNetInetClose", '?', "" },
1467 {0XCDA85C99, &WrapI_IUUU<sceNetInetRecv>, "sceNetInetRecv", 'i', "ixxx" },
1468 {0XC91142E4, nullptr, "sceNetInetRecvfrom", '?', "" },
1469 {0XEECE61D2, nullptr, "sceNetInetRecvmsg", '?', "" },
1470 {0X7AA671BC, &WrapI_IUUU<sceNetInetSend>, "sceNetInetSend", 'i', "ixxx" },
1471 {0X05038FC7, nullptr, "sceNetInetSendto", '?', "" },
1472 {0X774E36F4, nullptr, "sceNetInetSendmsg", '?', "" },
1473 {0XFBABE411, &WrapI_V<sceNetInetGetErrno>, "sceNetInetGetErrno", 'i', "" },
1474 {0X1A33F9AE, nullptr, "sceNetInetBind", '?', "" },
1475 {0XB75D5B0A, nullptr, "sceNetInetInetAddr", '?', "" },
1476 {0X1BDF5D13, &WrapI_CU<sceNetInetInetAton>, "sceNetInetInetAton", 'i', "sx" },
1477 {0XD0792666, nullptr, "sceNetInetInetNtop", '?', "" },
1478 {0XE30B8C19, nullptr, "sceNetInetInetPton", '?', "" },
1479 {0X8CA3A97E, nullptr, "sceNetInetGetPspError", '?', "" },
1480 {0XE247B6D6, nullptr, "sceNetInetGetpeername", '?', "" },
1481 {0X162E6FD5, nullptr, "sceNetInetGetsockname", '?', "" },
1482 {0X80A21ABD, nullptr, "sceNetInetSocketAbort", '?', "" },
1483 {0X39B0C7D3, nullptr, "sceNetInetGetUdpcbstat", '?', "" },
1484 {0XB3888AD4, nullptr, "sceNetInetGetTcpcbstat", '?', "" },
1485 };
1486
1487 const HLEFunction sceNetApctl[] = {
1488 {0XCFB957C6, &WrapI_I<sceNetApctlConnect>, "sceNetApctlConnect", 'i', "i" },
1489 {0X24FE91A1, &WrapI_V<sceNetApctlDisconnect>, "sceNetApctlDisconnect", 'i', "" },
1490 {0X5DEAC81B, &WrapI_U<sceNetApctlGetState>, "sceNetApctlGetState", 'i', "x" },
1491 {0X8ABADD51, &WrapU_UU<sceNetApctlAddHandler>, "sceNetApctlAddHandler", 'x', "xx" },
1492 {0XE2F91F9B, &WrapI_II<sceNetApctlInit>, "sceNetApctlInit", 'i', "ii" },
1493 {0X5963991B, &WrapI_U<sceNetApctlDelHandler>, "sceNetApctlDelHandler", 'i', "x" },
1494 {0XB3EDD0EC, &WrapI_V<sceNetApctlTerm>, "sceNetApctlTerm", 'i', "" },
1495 {0X2BEFDF23, &WrapI_IU<sceNetApctlGetInfo>, "sceNetApctlGetInfo", 'i', "ix" },
1496 {0XA3E77E13, &WrapI_V<sceNetApctlScanSSID2>, "sceNetApctlScanSSID2", 'i', "" },
1497 {0XE9B2E5E6, &WrapI_V<sceNetApctlScanUser>, "sceNetApctlScanUser", 'i', "" },
1498 {0XF25A5006, &WrapI_UUUU<sceNetApctlGetBSSDescIDList2>, "sceNetApctlGetBSSDescIDList2", 'i', "xxxx" },
1499 {0X2935C45B, &WrapI_IIU<sceNetApctlGetBSSDescEntry2>, "sceNetApctlGetBSSDescEntry2", 'i', "iix" },
1500 {0X04776994, &WrapI_IIU<sceNetApctlGetBSSDescEntryUser>, "sceNetApctlGetBSSDescEntryUser", 'i', "iix" },
1501 {0X6BDDCB8C, &WrapI_UU<sceNetApctlGetBSSDescIDListUser>, "sceNetApctlGetBSSDescIDListUser", 'i', "xx" },
1502 {0X7CFAB990, &WrapI_UU<sceNetApctlAddInternalHandler>, "sceNetApctlAddInternalHandler", 'i', "xx" },
1503 {0XE11BAFAB, &WrapI_U<sceNetApctlDelInternalHandler>, "sceNetApctlDelInternalHandler", 'i', "x" },
1504 {0XA7BB73DF, &WrapI_UU<sceNetApctl_A7BB73DF>, "sceNetApctl_A7BB73DF", 'i', "xx" },
1505 {0X6F5D2981, &WrapI_U<sceNetApctl_6F5D2981>, "sceNetApctl_6F5D2981", 'i', "x" },
1506 {0X69745F0A, &WrapI_I<sceNetApctl_lib2_69745F0A>, "sceNetApctl_lib2_69745F0A", 'i', "i" },
1507 {0X4C19731F, &WrapI_IU<sceNetApctl_lib2_4C19731F>, "sceNetApctl_lib2_4C19731F", 'i', "ix" },
1508 {0XB3CF6849, &WrapI_V<sceNetApctlScan>, "sceNetApctlScan", 'i', "" },
1509 {0X0C7FFA5C, &WrapI_UU<sceNetApctlGetBSSDescIDList>, "sceNetApctlGetBSSDescIDList", 'i', "xx" },
1510 {0X96BEB231, &WrapI_IIU<sceNetApctlGetBSSDescEntry>, "sceNetApctlGetBSSDescEntry", 'i', "iix" },
1511 {0XC20A144C, &WrapI_IU<sceNetApctl_lib2_C20A144C>, "sceNetApctl_lib2_C20A144C", 'i', "ix" },
1512 // Fake function for PPSSPP's use.
1513 {0X756E6F10, &WrapV_V<__NetApctlCallbacks>, "__NetApctlCallbacks", 'v', "" },
1514 };
1515
1516 const HLEFunction sceWlanDrv[] = {
1517 {0XD7763699, &WrapU_V<sceWlanGetSwitchState>, "sceWlanGetSwitchState", 'x', "" },
1518 {0X0C622081, &WrapU_U<sceWlanGetEtherAddr>, "sceWlanGetEtherAddr", 'x', "x" },
1519 {0X93440B11, &WrapU_V<sceWlanDevIsPowerOn>, "sceWlanDevIsPowerOn", 'x', "" },
1520 };
1521
1522 // see http://www.kingx.de/forum/showthread.php?tid=35164
1523 const HLEFunction sceNetUpnp[] = {
1524 {0X27045362, &WrapI_V<sceNetUpnpGetNatInfo>, "sceNetUpnpGetNatInfo", 'i', "" },
1525 {0X3432B2E5, &WrapI_V<sceNetUpnpStart>, "sceNetUpnpStart", 'i', "" },
1526 {0X3E32ED9E, &WrapI_V<sceNetUpnpStop>, "sceNetUpnpStop", 'i', "" },
1527 {0X540491EF, &WrapI_V<sceNetUpnpTerm>, "sceNetUpnpTerm", 'i', "" },
1528 {0XE24220B5, &WrapI_II<sceNetUpnpInit>, "sceNetUpnpInit", 'i', "ii" },
1529 };
1530
1531 const HLEFunction sceNetIfhandle[] = {
1532 {0xC80181A2, &WrapI_UU<sceNetGetDropRate>, "sceNetGetDropRate", 'i', "pp" },
1533 {0xFD8585E1, &WrapI_UU<sceNetSetDropRate>, "sceNetSetDropRate", 'i', "ii" },
1534 };
1535
Register_sceNet()1536 void Register_sceNet() {
1537 RegisterModule("sceNet", ARRAY_SIZE(sceNet), sceNet);
1538 RegisterModule("sceNetResolver", ARRAY_SIZE(sceNetResolver), sceNetResolver);
1539 RegisterModule("sceNetInet", ARRAY_SIZE(sceNetInet), sceNetInet);
1540 RegisterModule("sceNetApctl", ARRAY_SIZE(sceNetApctl), sceNetApctl);
1541 }
1542
Register_sceWlanDrv()1543 void Register_sceWlanDrv() {
1544 RegisterModule("sceWlanDrv", ARRAY_SIZE(sceWlanDrv), sceWlanDrv);
1545 }
1546
Register_sceNetUpnp()1547 void Register_sceNetUpnp() {
1548 RegisterModule("sceNetUpnp", ARRAY_SIZE(sceNetUpnp), sceNetUpnp);
1549 }
1550
Register_sceNetIfhandle()1551 void Register_sceNetIfhandle() {
1552 RegisterModule("sceNetIfhandle", ARRAY_SIZE(sceNetIfhandle), sceNetIfhandle);
1553 }
1554