mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-17 03:25:14 -04:00
PS2: Not really working networking
This commit is contained in:
parent
4b3e520ec3
commit
ae52ab9761
@ -4,7 +4,7 @@ CFILES := $(wildcard src/*.c)
|
||||
OBJS :=$(patsubst %.c, %.o, $(CFILES))
|
||||
|
||||
EE_BIN = ClassiCube-ps2.elf
|
||||
EE_OBJS = $(OBJS)
|
||||
EE_OBJS = $(OBJS) DEV9_irx.o NETMAN_irx.o SMAP_irx.o
|
||||
EE_LIBS = -lpatches -lpad -lpacket -ldma -lgraph -ldraw -lc
|
||||
EE_CFLAGS = -DPLAT_PS2
|
||||
|
||||
@ -12,6 +12,15 @@ all: $(EE_BIN)
|
||||
|
||||
clean:
|
||||
rm -f $(EE_BIN) $(EE_OBJS)
|
||||
|
||||
DEV9_irx.c: $(PS2SDK)/iop/irx/ps2dev9.irx
|
||||
bin2c $< DEV9_irx.c DEV9_irx
|
||||
|
||||
NETMAN_irx.c: $(PS2SDK)/iop/irx/netman.irx
|
||||
bin2c $< NETMAN_irx.c NETMAN_irx
|
||||
|
||||
SMAP_irx.c: $(PS2SDK)/iop/irx/smap.irx
|
||||
bin2c $< SMAP_irx.c SMAP_irx
|
||||
|
||||
include $(PS2SDK)/samples/Makefile.pref
|
||||
include $(PS2SDK)/samples/Makefile.eeglobal
|
||||
|
@ -197,7 +197,7 @@ cc_result File_Length(cc_file file, cc_uint32* len) {
|
||||
/*########################################################################################################################*
|
||||
*--------------------------------------------------------Threading--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
// !!! NOTE: Dreamcast uses cooperative multithreading (not preemptive multithreading) !!!
|
||||
// !!! NOTE: Dreamcast is configured to use preemptive multithreading !!!
|
||||
void Thread_Sleep(cc_uint32 milliseconds) {
|
||||
thd_sleep(milliseconds);
|
||||
}
|
||||
|
@ -29,13 +29,13 @@
|
||||
#include <loadfile.h>
|
||||
#include <iopcontrol.h>
|
||||
#include <sbv_patches.h>
|
||||
#include <netman.h>
|
||||
#include <ps2ip.h>
|
||||
#include "_PlatformConsole.h"
|
||||
|
||||
const cc_result ReturnCode_FileShareViolation = 1000000000; // not used
|
||||
const cc_result ReturnCode_FileNotFound = 0x80010006; // ENOENT;
|
||||
//const cc_result ReturnCode_SocketInProgess = 0x80010032; // EINPROGRESS
|
||||
//const cc_result ReturnCode_SocketWouldBlock = 0x80010001; // EWOULDBLOCK;
|
||||
const cc_result ReturnCode_DirectoryExists = 0x80010014; // EEXIST
|
||||
const cc_result ReturnCode_FileNotFound = ENOENT;
|
||||
const cc_result ReturnCode_DirectoryExists = EEXIST;
|
||||
|
||||
const cc_result ReturnCode_SocketInProgess = EINPROGRESS;
|
||||
const cc_result ReturnCode_SocketWouldBlock = EWOULDBLOCK;
|
||||
@ -337,41 +337,240 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) {
|
||||
/*########################################################################################################################*
|
||||
*-------------------------------------------------------Networking--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
// https://github.com/ps2dev/ps2sdk/blob/master/NETMAN.txt
|
||||
// https://github.com/ps2dev/ps2sdk/blob/master/ee/network/tcpip/samples/tcpip_dhcp/ps2ip.c
|
||||
extern unsigned char DEV9_irx[];
|
||||
extern unsigned int size_DEV9_irx;
|
||||
|
||||
extern unsigned char SMAP_irx[];
|
||||
extern unsigned int size_SMAP_irx;
|
||||
|
||||
extern unsigned char NETMAN_irx[];
|
||||
extern unsigned int size_NETMAN_irx;
|
||||
|
||||
static void ethStatusCheckCb(s32 alarm_id, u16 time, void *common) {
|
||||
int threadID = *(int*)common;
|
||||
iWakeupThread(threadID);
|
||||
}
|
||||
|
||||
static int WaitValidNetState(int (*checkingFunction)(void)) {
|
||||
// Wait for a valid network status
|
||||
int threadID = GetThreadId();
|
||||
|
||||
for (int retries = 0; checkingFunction() == 0; retries++)
|
||||
{
|
||||
// Sleep for 500ms
|
||||
SetAlarm(500 * 16, ðStatusCheckCb, &threadID);
|
||||
SleepThread();
|
||||
|
||||
if (retries >= 10) // 5s = 10 * 500ms
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ethGetNetIFLinkStatus(void) {
|
||||
return NetManIoctl(NETMAN_NETIF_IOCTL_GET_LINK_STATUS, NULL, 0, NULL, 0) == NETMAN_NETIF_ETH_LINK_STATE_UP;
|
||||
}
|
||||
|
||||
static int ethWaitValidNetIFLinkState(void) {
|
||||
return WaitValidNetState(ðGetNetIFLinkStatus);
|
||||
}
|
||||
|
||||
static int ethGetDHCPStatus(void) {
|
||||
t_ip_info ip_info;
|
||||
int result;
|
||||
if ((result = ps2ip_getconfig("sm0", &ip_info)) < 0) return result;
|
||||
|
||||
if (ip_info.dhcp_enabled) {
|
||||
return ip_info.dhcp_status == DHCP_STATE_BOUND || ip_info.dhcp_status == DHCP_STATE_OFF;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ethWaitValidDHCPState(void) {
|
||||
return WaitValidNetState(ðGetDHCPStatus);
|
||||
}
|
||||
|
||||
static int ethEnableDHCP(void) {
|
||||
t_ip_info ip_info;
|
||||
int result;
|
||||
// SMAP is registered as the "sm0" device to the TCP/IP stack.
|
||||
if ((result = ps2ip_getconfig("sm0", &ip_info)) < 0) return result;
|
||||
|
||||
if (!ip_info.dhcp_enabled) {
|
||||
ip_info.dhcp_enabled = 1;
|
||||
return ps2ip_setconfig(&ip_info);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SetupNetworking(void) {
|
||||
struct ip4_addr IP = { 0 }, NM = { 0 }, GW = { 0 };
|
||||
ps2ipInit(&IP, &NM, &GW);
|
||||
ethEnableDHCP();
|
||||
|
||||
Platform_LogConst("Waiting for net link connection...");
|
||||
if(ethWaitValidNetIFLinkState() != 0) {
|
||||
Platform_LogConst("Failed to establish net link");
|
||||
return;
|
||||
}
|
||||
|
||||
Platform_LogConst("Waiting for DHCP lease...");
|
||||
if (ethWaitValidDHCPState() != 0) {
|
||||
Platform_LogConst("Failed to acquire DHCP lease");
|
||||
return;
|
||||
}
|
||||
Platform_LogConst("Network setup done");
|
||||
}
|
||||
|
||||
static void InitNetworking(void) {
|
||||
//SifExecModuleBuffer(DEV9_irx, size_DEV9_irx, 0, NULL, NULL);
|
||||
//SifExecModuleBuffer(NETMAN_irx, size_NETMAN_irx, 0, NULL, NULL);
|
||||
//SifExecModuleBuffer(SMAP_irx, size_SMAP_irx, 0, NULL, NULL);
|
||||
//NetManInit();
|
||||
SifExecModuleBuffer(DEV9_irx, size_DEV9_irx, 0, NULL, NULL);
|
||||
SifExecModuleBuffer(NETMAN_irx, size_NETMAN_irx, 0, NULL, NULL);
|
||||
SifExecModuleBuffer(SMAP_irx, size_SMAP_irx, 0, NULL, NULL);
|
||||
NetManInit();
|
||||
}
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------Socket----------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
union SocketAddress {
|
||||
struct sockaddr raw;
|
||||
struct sockaddr_in v4;
|
||||
};
|
||||
|
||||
static int ParseHost(union SocketAddress* addr, const char* host) {
|
||||
struct addrinfo hints = { 0 };
|
||||
struct addrinfo* result;
|
||||
struct addrinfo* cur;
|
||||
int found = false;
|
||||
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
int res = getaddrinfo(host, NULL, &hints, &result);
|
||||
if (res == -NO_DATA) return SOCK_ERR_UNKNOWN_HOST;
|
||||
if (res) return res;
|
||||
|
||||
for (cur = result; cur; cur = cur->ai_next) {
|
||||
if (cur->ai_family != AF_INET) continue;
|
||||
found = true;
|
||||
|
||||
Mem_Copy(addr, cur->ai_addr, cur->ai_addrlen);
|
||||
break;
|
||||
}
|
||||
|
||||
freeaddrinfo(result);
|
||||
return found ? 0 : ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
static int ParseAddress(union SocketAddress* addr, const cc_string* address) {
|
||||
char str[NATIVE_STR_LEN];
|
||||
String_EncodeUtf8(str, address);
|
||||
|
||||
if (inet_aton(str, &addr->v4.sin_addr) > 0) return 0;
|
||||
return ParseHost(addr, str);
|
||||
}
|
||||
|
||||
int Socket_ValidAddress(const cc_string* address) {
|
||||
return false;
|
||||
union SocketAddress addr;
|
||||
return ParseAddress(&addr, address) == 0;
|
||||
}
|
||||
|
||||
static cc_result GetSocketError(cc_socket s) {
|
||||
socklen_t resultSize = sizeof(socklen_t);
|
||||
cc_result res = 0;
|
||||
getsockopt(s, SOL_SOCKET, SO_ERROR, &res, &resultSize);
|
||||
return res;
|
||||
}
|
||||
|
||||
cc_result Socket_Connect(cc_socket* s, const cc_string* address, int port, cc_bool nonblocking) {
|
||||
return ERR_NOT_SUPPORTED;
|
||||
union SocketAddress addr;
|
||||
int res;
|
||||
|
||||
*s = -1;
|
||||
if ((res = ParseAddress(&addr, address))) return res;
|
||||
|
||||
*s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (*s < 0) return *s;
|
||||
|
||||
if (nonblocking) {
|
||||
int blocking_raw = -1; // non-blocking mode
|
||||
//ioctlsocket(*s, FIONBIO, &blocking_raw); TODO doesn't work
|
||||
}
|
||||
|
||||
addr.v4.sin_family = AF_INET;
|
||||
addr.v4.sin_port = htons(port);
|
||||
|
||||
res = connect(*s, &addr.raw, sizeof(addr.v4));
|
||||
return res == -1 ? GetSocketError(*s) : 0;
|
||||
}
|
||||
|
||||
cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) {
|
||||
return ERR_NOT_SUPPORTED;
|
||||
Platform_Log1("PREPARE TO READ: %i", &count);
|
||||
int recvCount = recv(s, data, count, 0);
|
||||
Platform_Log1(" .. read %i", &recvCount);
|
||||
if (recvCount != -1) { *modified = recvCount; return 0; }
|
||||
|
||||
int ERR = GetSocketError(s);
|
||||
Platform_Log1("ERR: %i", &ERR);
|
||||
*modified = 0; return ERR;
|
||||
}
|
||||
|
||||
cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) {
|
||||
return ERR_NOT_SUPPORTED;
|
||||
Platform_Log1("PREPARE TO WRITE: %i", &count);
|
||||
int sentCount = send(s, data, count, 0);
|
||||
Platform_Log1(" .. wrote %i", &sentCount);
|
||||
if (sentCount != -1) { *modified = sentCount; return 0; }
|
||||
|
||||
int ERR = GetSocketError(s);
|
||||
Platform_Log1("ERR: %i", &ERR);
|
||||
*modified = 0; return ERR;
|
||||
}
|
||||
|
||||
void Socket_Close(cc_socket s) {
|
||||
shutdown(s, SHUT_RDWR);
|
||||
close(s);
|
||||
}
|
||||
|
||||
static cc_result Socket_Poll(cc_socket s, int mode, cc_bool* success) {
|
||||
fd_set read_set, write_set, error_set;
|
||||
struct timeval time = { 0 };
|
||||
int selectCount;
|
||||
|
||||
FD_ZERO(&read_set);
|
||||
FD_SET(s, &read_set);
|
||||
FD_ZERO(&write_set);
|
||||
FD_SET(s, &write_set);
|
||||
FD_ZERO(&error_set);
|
||||
FD_SET(s, &error_set);
|
||||
|
||||
selectCount = select(s + 1, &read_set, &write_set, &error_set, &time);
|
||||
|
||||
Platform_Log4("SELECT %i = %h / %h / %h", &selectCount, &read_set, &write_set, &error_set);
|
||||
if (selectCount == -1) { *success = false; return errno; }
|
||||
*success = FD_ISSET(s, &write_set) != 0; return 0;
|
||||
}
|
||||
|
||||
cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) {
|
||||
return ERR_NOT_SUPPORTED;
|
||||
Platform_LogConst("POLL READ");
|
||||
return Socket_Poll(s, SOCKET_POLL_READ, readable);
|
||||
}
|
||||
|
||||
static int tries;
|
||||
cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) {
|
||||
return ERR_NOT_SUPPORTED;
|
||||
cc_result res = Socket_Poll(s, SOCKET_POLL_WRITE, writable);
|
||||
Platform_Log1("POLL WRITE: %i", &res);
|
||||
if (res || *writable) return res;
|
||||
|
||||
// INPROGRESS error code returned if connect is still in progress
|
||||
res = GetSocketError(s);
|
||||
Platform_Log1("POLL FAIL: %i", &res);
|
||||
if (res == EINPROGRESS) res = 0;
|
||||
|
||||
if (tries++ > 20) { *writable = true; }
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@ -396,6 +595,7 @@ void Platform_Init(void) {
|
||||
sbv_patch_enable_lmb();
|
||||
|
||||
InitNetworking();
|
||||
SetupNetworking();
|
||||
// Create root directory
|
||||
Directory_Create(&String_Empty);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user