Latest compatible version of Classicube from the original GitHub repository (https://github.com/ClassiCube/ClassiCube) that can be compiled on Classicube for PowerMac PPC running Mac OS X 10.4.

This commit is contained in:
Andrei Alexandru
2025-12-17 13:17:57 +02:00
commit c71492f846
1248 changed files with 422858 additions and 0 deletions

View File

@@ -0,0 +1,453 @@
/*
* Copyright (c) 2021 Max Thomas
* This file is part of DSiWifi and is distributed under the MIT license.
* See dsiwifi_license.txt for terms of use.
*/
#include "wifi_host.h"
#include <nds.h>
#include "lwip/err.h"
#include "lwip/inet.h"
#include "lwip/lwip_init.h"
#include "lwip/tcp.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/dhcp.h"
#include "lwip/timeouts.h"
#include "lwip/etharp.h"
#include "lwip/netif/ethernet.h"
#include "lwip/sys.h"
#include "lwip/netbiosns.h"
#include "lwip/tcpip.h"
#include "dsiwifi9.h"
#include "dsiwifi_cmds.h"
static u8 device_mac[6];
static u8 ap_mac[6];
static bool host_bInitted = false;
static bool host_bLwipInitted = false;
static bool host_bNeedsDHCPRenew = false;
static int ip_data_buf_idx = 0;
#define DATA_BUF_RINGS (6)
#define DATA_IN_BUF_RINGS (6)
#define DATA_BUF_LEN (0x600)
#define IF_MTU_SIZE (0x570)
static u8 __attribute((aligned(16))) ip_data_buf[DATA_BUF_LEN*DATA_BUF_RINGS];
static u8 __attribute((aligned(16))) ip_data_in_buf[DATA_BUF_LEN*DATA_IN_BUF_RINGS];
// LWIP state
static struct netif ath_netif = {0};
static ip_addr_t ath_myip_addr = {0};
static ip_addr_t gw_addr = {0}, netmask = {0};
void ath_lwip_tick();
err_t ath_link_output(struct netif *netif, struct pbuf *p);
static int idk_hack = 0;
void data_init_bufs()
{
for (int i = 0; i < DATA_BUF_RINGS; i++)
{
void* dst = memUncached(ip_data_buf + (DATA_BUF_LEN * i));
*(vu32*)dst = 0xF00FF00F;
}
for (int i = 0; i < DATA_IN_BUF_RINGS; i++)
{
void* dst = memUncached(ip_data_in_buf + (DATA_BUF_LEN * i));
*(vu32*)dst = 0xF00FF00F;
}
}
void* data_next_buf()
{
#if 0
//for (int j = 0; j < 1000000; j++)
//while (1)
for (int j = 0; j < 100; j++)
{
for (int i = 0; i < DATA_BUF_RINGS; i++)
{
void* dst = memUncached(ip_data_buf + (DATA_BUF_LEN * i));
if (*(vu32*)dst == 0xF00FF00F)
{
//wifi_printf("ret %u\n", i);
return dst;
}
}
//wifi_printf("arm9 loop...\n");
}
//return memUncached(ip_data_buf);
return NULL;
#endif
#if 1
void* ret = memUncached(ip_data_buf + (DATA_BUF_LEN * ip_data_buf_idx));
//wifi_printf("ret %u\n", ip_data_buf_idx);
ip_data_buf_idx = (ip_data_buf_idx + 1) % DATA_BUF_RINGS;
//memset(ret, 0, DATA_BUF_LEN);
return ret;
#endif
}
static void wifi_print_mac(const char* prefix, const u8* mac)
{
if (prefix) {
wifi_printlnf("%s %02x:%02x:%02x:%02x:%02x:%02x", prefix, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
else {
wifi_printlnf("%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
}
//
// LwIP
//
err_t data_send_link(void* ip_data, u32 ip_data_len)
{
if (!ip_data_len) return ERR_OK;
if (ip_data_len > DATA_BUF_LEN)
ip_data_len = DATA_BUF_LEN;
void* dst = data_next_buf();
if (!dst)
return ERR_MEM;
memcpy(dst, ip_data, ip_data_len);
//wifi_printf("send pkt size %d\n", ip_data_len - 0x40);
Wifi_FifoMsg msg;
msg.cmd = WIFI_IPCCMD_SENDPKT;
msg.pkt_data = dst;
msg.pkt_len = ip_data_len;
fifoSendDatamsg(FIFO_DSWIFI, sizeof(msg), (u8*)&msg);
/*for(int i = 0; i < 0x10000; i++)
{
asm("nop");
}*/
//while (*(vu32*)dst != 0xF00FF00F);
return ERR_OK;
}
err_t ath_init_fn(struct netif *netif)
{
ath_netif.output = etharp_output;
ath_netif.linkoutput = ath_link_output;
ath_netif.mtu = IF_MTU_SIZE;
ath_netif.name[0] = 'w';
ath_netif.name[1] = 'l';
ath_netif.hwaddr_len = 6;
ath_netif.hostname = "WhoNeedTheyPzy8";
memcpy(ath_netif.hwaddr, device_mac, 6);
ath_netif.flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6 | NETIF_FLAG_LINK_UP;
return ERR_OK;
}
err_t ath_link_output(struct netif *netif, struct pbuf *p)
{
// TODO pbuf_coalesce?
//wifi_printlnf("link output %x", p->len);
//hexdump(p->payload, 0x20);
return data_send_link(p->payload, p->len);
}
void ath_lwip_tick()
{
sys_check_timeouts();
tcpip_thread_poll_one();
}
void data_send_to_lwip(void* data, u32 len)
{
if (len > DATA_BUF_LEN-6)
len = DATA_BUF_LEN-6;
struct pbuf *p = pbuf_alloc(PBUF_IP, len, PBUF_POOL);
// TODO error check?
if (!p) {
*(vu32*)(data - 6) = 0xF00FF00F;
return;
}
if (len > p->len)
len = p->len;
memcpy(p->payload, data, len);
*(vu32*)(data - 6) = 0xF00FF00F;
//wifi_printlnf("link in 0x%x bytes", len);
if (ath_netif.input(p, &ath_netif) != ERR_OK) {
pbuf_free(p);
}
// ~Hopefully get a fast ACK by doing this
//int lock = enterCriticalSection();
//ath_lwip_tick();
//leaveCriticalSection(lock);
//wifi_printlnf("link in done");
//ath_lwip_tick();
}
//
// FIFO
//
static void wifi_host_get_mac()
{
Wifi_FifoMsg msg;
msg.cmd = WIFI_IPCCMD_GET_DEVICE_MAC;
fifoSendDatamsg(FIFO_DSWIFI, sizeof(msg), (u8*)&msg);
}
static void wifi_host_get_ap_mac()
{
Wifi_FifoMsg msg;
msg.cmd = WIFI_IPCCMD_GET_AP_MAC;
fifoSendDatamsg(FIFO_DSWIFI, sizeof(msg), (u8*)&msg);
}
static void wifi_host_init_bufs(void)
{
data_init_bufs();
Wifi_FifoMsg msg;
msg.cmd = WIFI_IPCCMD_INITBUFS;
msg.pkt_data = memUncached(ip_data_in_buf);
msg.pkt_len = sizeof(ip_data_in_buf);
fifoSendDatamsg(FIFO_DSWIFI, sizeof(msg), (u8*)&msg);
}
static void wifi_host_init_iop(void)
{
Wifi_FifoMsg msg;
msg.cmd = WIFI_IPCCMD_INIT_IOP;
fifoSendDatamsg(FIFO_DSWIFI, sizeof(msg), (u8*)&msg);
}
static void wifi_host_lwip_init()
{
// If this is just the AP renewing keys, don't redo lwip init.
if (host_bLwipInitted) {
if (host_bNeedsDHCPRenew)
{
if (DSiWifi_pfnReconnectHandler)
DSiWifi_pfnReconnectHandler();
dhcp_start(&ath_netif);
host_bNeedsDHCPRenew = false;
}
return;
}
// Initialize LwIP
ath_myip_addr.addr = IPADDR_NONE;
gw_addr.addr = IPADDR_NONE;
netmask.addr = IPADDR_NONE;
lwip_init();
if (netif_add(&ath_netif, &ath_myip_addr, &netmask, &gw_addr, NULL /* priv state */,
ath_init_fn, ethernet_input) == NULL) {
wifi_printlnf("wifi_host_lwip_init: netif_add failed");
return;
}
netif_set_default(&ath_netif);
netif_set_up(&ath_netif);
netif_set_link_up(&ath_netif);
netbiosns_set_name(ath_netif.hostname);
netbiosns_init();
dhcp_start(&ath_netif);
if (DSiWifi_pfnConnectHandler)
DSiWifi_pfnConnectHandler();
host_bLwipInitted = true;
host_bNeedsDHCPRenew = false;
}
static void wifi_host_handleMsg(int len, void* user_data)
{
Wifi_FifoMsgExt msg;
if (len < 4)
{
wifi_printf("Bad msg len %x\n", len);
return;
}
fifoGetDatamsg(FIFO_DSWIFI, len, (u8*)&msg);
u32 cmd = msg.cmd;
if (cmd == WIFI_IPCINT_READY)
{
wifi_host_get_mac();
wifi_host_get_ap_mac();
wifi_host_init_bufs();
host_bInitted = true;
}
else if (cmd == WIFI_IPCINT_CONNECT)
{
wifi_printf("Connecting to AP\n");
host_bNeedsDHCPRenew = true;
}
else if (cmd == WIFI_IPCINT_DEVICE_MAC)
{
memcpy(device_mac, msg.mac_addr, 6);
wifi_print_mac("Dev", device_mac);
}
else if (cmd == WIFI_IPCINT_AP_MAC)
{
memcpy(ap_mac, msg.mac_addr, 6);
wifi_print_mac("AP", ap_mac);
wifi_host_lwip_init();
}
else if (cmd == WIFI_IPCINT_PKTDATA)
{
void* data = memUncached(msg.pkt_data);
u32 len = msg.pkt_len;
data_send_to_lwip(data, len);
}
else if (cmd == WIFI_IPCINT_PKTSENT)
{
void* data = msg.pkt_data;
u32 len = msg.pkt_len;
*(vu32*)data = 0xF00FF00F;
}
else if (cmd == WIFI_IPCINT_DBGLOG)
{
wifi_printf("%s", msg.log_str);
}
else
{
wifi_printf("val %x\n", cmd);
}
}
extern void sys_now_inc(u32 amt);
u32 wifi_host_get_ipaddr(void)
{
return ath_netif.ip_addr.addr;
}
int wifi_host_get_status(void)
{
if (host_bLwipInitted)
{
if (wifi_host_get_ipaddr() != 0xFFFFFFFF)
return ASSOCSTATUS_ASSOCIATED;
return ASSOCSTATUS_ACQUIRINGDHCP;
}
return ASSOCSTATUS_SEARCHING;
}
void wifi_host_tick_display()
{
static int counter = 100000;
if (counter++ > 2*1000)
{
u32 addr = ath_netif.ip_addr.addr;
u8 addr_bytes[4];
memcpy(addr_bytes, &addr, 4);
//wifi_printf("\x1b[s\x1b[0;0HCur IP: \x1b[36m%u.%u.%u.%u \x1b[u\x1b[37m", addr_bytes[0], addr_bytes[1], addr_bytes[2], addr_bytes[3]);
//font_draw_string(0,0, WHITE, tmp);
//data_send_ip(broadcast_all, device_mac, NULL, 0);
counter = 0;
}
}
void wifi_host_tick()
{
static int inc_cnt = 0;
if (inc_cnt++ == 1) {
sys_now_inc(1);
inc_cnt = 0;
}
// For debugging weird hangs
static int sec_cnt = 0;
//static int sec_num = 0;
if (sec_cnt++ == 1000) {
//wifi_printf("tick %u\n", sec_num++);
sec_cnt = 0;
// Sometimes DHCP can have some trouble enumerating.
// Since we *really* need an IP address, just keep prodding every so often
// if we don't get one quickly.
if (host_bLwipInitted && ath_netif.ip_addr.addr == 0xFFFFFFFF || ath_netif.ip_addr.addr == 0x0)
{
if (DSiWifi_pfnReconnectHandler)
DSiWifi_pfnReconnectHandler();
dhcp_start(&ath_netif);
host_bNeedsDHCPRenew = false;
}
}
if (host_bLwipInitted)
{
ath_lwip_tick();
wifi_host_tick_display();
}
}
void wifi_host_init()
{
wifi_printf("wifi_host_init\n");
// 100ms timer
timerStart(3, ClockDivider_1024, TIMER_FREQ_1024(1000), wifi_host_tick);
// Enable FIFO handlers
fifoSetDatamsgHandler(FIFO_DSWIFI, wifi_host_handleMsg, 0);
wifi_host_init_iop();
wifi_printf("did init iop\n");
}