Top secrets sources NedoPC pentevo

Rev

Rev 885 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

#include "std.h"
#include "emul.h"
#include "vars.h"
#include "zxusbnet.h"
#include <iphlpapi.h>

#define buf_size 8*1024

//#define dbgmod
#ifdef dbgmod
#define DPRINTF printf
#else
#define DPRINTF(pa,pb)
#endif // dbgmod

#define WRITE_REG_FUNC(f_n) void f_n(sInfoStruct * s, u_char d, u_char z)
#define READ_REG_FUNC(f_n) u_char f_n(sInfoStruct * s, u_char z)


enum class TCP_STATE{
        NONE, CLIENT_CONNECTED, LISTEN_CONNECTED, CLIENT, LISTEN, CLOSED
};

/************************************/
/* The bit of MR regsiter defintion */
/************************************/
#define MR_DBW             (1 << 15)            /**< Data bus width bit of MR. */
#define MR_MPF             (1 << 14)            /**< Mac layer pause frame bit of MR. */
#define MR_WDF(X)          ((X & 0x07) << 11)   /**< Write data fetch time bit of  MR. */
#define MR_RDH             (1 << 10)            /**< Read data hold time bit of MR. */
#define MR_FS              (1 << 8)             /**< FIFO swap bit of MR. */
#define MR_RST             (1 << 7)             /**< S/W reset bit of MR. */
#define MR_MT              (1 << 5)             /**< Memory test bit of MR. */
#define MR_PB              (1 << 4)             /**< Ping block bit of MR. */
#define MR_PPPoE           (1 << 3)             /**< PPPoE bit of MR. */
#define MR_DBS             (1 << 2)             /**< Data bus swap of MR. */
#define MR_IND             (1 << 0)             /**< Indirect mode bit of MR. */


/***************************************/
/* The bit of Sn_MR regsiter defintion */
/***************************************/
#define Sn_MR_ALIGN        (1 << 8)             /**< Alignment bit of Sn_MR. */
#define Sn_MR_MULTI        (1 << 7)             /**< Multicasting bit of Sn_MR. */
#define Sn_MR_MF           (1 << 6)             /**< MAC filter bit of Sn_MR. */
#define Sn_MR_IGMPv        (1 << 5)             /**< IGMP version bit of Sn_MR. */
#define Sn_MR_ND           (1 << 5)             /**< No delayed ack bit of Sn_MR. */
#define Sn_MR_CLOSE        0x00                 /**< Protocol bits of Sn_MR. */
#define Sn_MR_TCP          0x01                 /**< Protocol bits of Sn_MR. */
#define Sn_MR_UDP          0x02                 /**< Protocol bits of Sn_MR. */
#define Sn_MR_IPRAW        0x03                 /**< Protocol bits of Sn_MR. */
#define Sn_MR_MACRAW       0x04                 /**< Protocol bits of Sn_MR. */
#define Sn_MR_PPPoE        0x05                 /**< Protocol bits of Sn_MR. */

/******************************/
/* The values of CR defintion */
/******************************/
#define Sn_CR_OPEN         0x01                 /**< OPEN command value of Sn_CR. */
#define Sn_CR_LISTEN       0x02                 /**< LISTEN command value of Sn_CR. */
#define Sn_CR_CONNECT      0x04                 /**< CONNECT command value of Sn_CR. */
#define Sn_CR_DISCON       0x08                 /**< DISCONNECT command value of Sn_CR. */
#define Sn_CR_CLOSE        0x10                 /**< CLOSE command value of Sn_CR. */
#define Sn_CR_SEND         0x20                 /**< SEND command value of Sn_CR. */
#define Sn_CR_SEND_MAC     0x21                 /**< SEND_MAC command value of Sn_CR. */
#define Sn_CR_SEND_KEEP    0x22                 /**< SEND_KEEP command value of Sn_CR */
#define Sn_CR_RECV         0x40                 /**< RECV command value of Sn_CR */
#define Sn_CR_PCON         0x23                 /**< PCON command value of Sn_CR */
#define Sn_CR_PDISCON      0x24                 /**< PDISCON command value of Sn_CR */
#define Sn_CR_PCR          0x25                 /**< PCR command value of Sn_CR */
#define Sn_CR_PCN          0x26                 /**< PCN command value of Sn_CR */
#define Sn_CR_PCJ          0x27                 /**< PCJ command value of Sn_CR */

/**********************************/
/* The values of Sn_SSR defintion */
/**********************************/
#define SOCK_CLOSED        0x00                 /**< SOCKETn is released */
#define SOCK_ARP           0x01                 /**< ARP-request is transmitted in order to acquire destination hardware address. */
#define SOCK_INIT          0x13                 /**< SOCKETn is open as TCP mode. */
#define SOCK_LISTEN        0x14                 /**< SOCKETn operates as "TCP SERVER" and waits for connection-request (SYN packet) from "TCP CLIENT". */
#define SOCK_SYNSENT       0x15                 /**< Connect-request(SYN packet) is transmitted to "TCP SERVER". */
#define SOCK_SYNRECV       0x16                 /**< Connect-request(SYN packet) is received from "TCP CLIENT". */
#define SOCK_ESTABLISHED   0x17                 /**< TCP connection is established. */
#define SOCK_FIN_WAIT      0x18                 /**< SOCKETn is closing. */
#define SOCK_CLOSING       0x1A                 /**< SOCKETn is closing. */
#define SOCK_TIME_WAIT     0x1B                 /**< SOCKETn is closing. */
#define SOCK_CLOSE_WAIT    0x1C                 /**< Disconnect-request(FIN packet) is received from the peer. */
#define SOCK_LAST_ACK      0x1D                 /**< SOCKETn is closing. */
#define SOCK_UDP           0x22                 /**< SOCKETn is open as UDP mode. */
#define SOCK_IPRAW         0x32                 /**< SOCKETn is open as IPRAW mode. */
#define SOCK_MACRAW        0x42                 /**< SOCKET0 is open as MACRAW mode. */
#define SOCK_PPPoE         0x5F                 /**< SOCKET0 is open as PPPoE mode. */


union LONG_CHAR{
        u_long ul;
        u_char b[4];
};


static struct sInfoStruct
{
        SOCKET s; //socket
        sockaddr_in sa_in;
        u_char PORTR[2];
        WSAEVENT Event;
        u_char MR[2];
        u_char CR;
        TCP_STATE tcpState;
        u_long RX_RSR;
        u_char rx[buf_size + 8];
        u_char * rx_ptr;
        LONG_CHAR TX_WRSR;
        u_char tx[buf_size];
        u_char * tx_ptr;
        SOCKET list; //socket
        u_char PROTOR;
        u_char BINDED;
}soc[8];
//static char myIP[4];
static sockaddr_in sa_in;
static sockaddr_in r_sa_in;
//static u_long len_test;
static TIMEVAL select_timeout;
static u_char stat_regs[0x0100];
static u_char regs[sizeof(stat_regs)];
static int ns, iResult;
static u_char data;
//static char * s_ptr;
static fd_set fd_s;
//static fd_set fd_s1;
static u_long is_blocked = 0, non_blocked = 1;
WSADATA wsaData;

void soc_bind(sInfoStruct * s){
        ZeroMemory(&sa_in, sizeof(sa_in));
        sa_in.sin_family = AF_INET;
        //memcpy(&sa_in.sin_addr.S_un.S_addr, &stat_regs[0x0018], 4);
        char broadcast = '1';
        setsockopt(s->s,SOL_SOCKET,SO_BROADCAST,&broadcast,sizeof(broadcast));
        sa_in.sin_addr.s_addr = htonl(INADDR_ANY);;
        sa_in.sin_port = (s->PORTR[1] << 8) | s->PORTR[0];
        bind(s->s, (sockaddr *)&sa_in, sizeof(sa_in));
        s->BINDED = 1;
}

void WizRecv(sInfoStruct * s){
        if (s->rx_ptr)return;
        int len=0;
        switch (s->MR[1]){
                case Sn_MR_TCP:
                        len = recv(s->s, (char*)&s->rx[2], buf_size, 0);
                        break;
                case Sn_MR_UDP:
                        if(s->BINDED == 0) soc_bind(s);
                        //ZeroMemory(&r_sa_in, sizeof(r_sa_in));
                        iResult = sizeof(r_sa_in);
                        len=recvfrom(s->s, (char*)&s->rx[8], buf_size, 0, (sockaddr *)&r_sa_in, &iResult);
                        break; 
                case Sn_MR_IPRAW:
                        if(s->BINDED == 0) soc_bind(s);
                        //ZeroMemory(&r_sa_in, sizeof(r_sa_in));
                        iResult = sizeof(r_sa_in);
                        len=recvfrom(s->s, (char*)&s->rx[6], buf_size, 0, (sockaddr *)&r_sa_in, &iResult);
                        //printf("res=%d, errno=%d\r\n",len,errno);
                        break; 
        }
        if(len>0)DPRINTF("Recv %d bytes\r\n", len);
        switch (len)
        {
        case -1:
                return;
        case 0:
                if (s->MR[1] == Sn_MR_TCP)
                        s->tcpState = TCP_STATE::CLOSED;
                return;
        default:
                break;
        }
        //unsigned char * p = s->rx;
        switch (s->MR[1]){
                case Sn_MR_TCP:
                        s->rx[0] = (len & 0xff00) >> 8;
                        s->rx[1] = len & 0x00ff;
                        s->RX_RSR = (len + 3) & 0x0001fffe;
                        break;
                case Sn_MR_UDP:
                        *((ULONG*)s->rx) = r_sa_in.sin_addr.S_un.S_addr;
                        *((u_short*)&s->rx[4]) = r_sa_in.sin_port;
                        s->rx[6] = (len & 0xff00) >> 8;
                        s->rx[7] = len & 0x00ff;
                        s->RX_RSR = (len + 9) & 0x0001fffe;
                        break; 
                case Sn_MR_IPRAW:
                        *((ULONG*)s->rx) = r_sa_in.sin_addr.S_un.S_addr;
                        s->rx[4] = (len & 0xff00) >> 8;
                        s->rx[5] = len & 0x00ff;
                        s->RX_RSR = (len + 7) & 0x0001fffe;
                        break; 
        }
        s->rx_ptr = s->rx;
}

READ_REG_FUNC(read_MR){ return s->MR[z]; }

READ_REG_FUNC(read_CR){
        if (!s->CR)return 0;
        if (s->s == INVALID_SOCKET)return s->CR;
        return 0;
}

READ_REG_FUNC(read_SSR){
        if (s->s == INVALID_SOCKET || s->tcpState == TCP_STATE::CLOSED)
                return SOCK_CLOSED;
        if (s->MR[1] == Sn_MR_TCP && s->tcpState == TCP_STATE::NONE){
                return SOCK_INIT;
        }
        FD_ZERO(&fd_s);
        FD_SET(s->s, &fd_s);
        iResult = select(0, NULL, NULL, &fd_s, &select_timeout);
        if (iResult == SOCKET_ERROR)
                return SOCK_CLOSED;
        if (s->tcpState == TCP_STATE::LISTEN){
                s->list = accept(s->s, (sockaddr *)&s->sa_in, &ns);
                if (s->list != (unsigned int)SOCKET_ERROR){
                        ioctlsocket(s->s, FIONBIO, &is_blocked);
                        closesocket(s->s);
                        s->s = s->list;
                        ioctlsocket(s->s, FIONBIO, &non_blocked);
                        bool bOptVal = true;
                        setsockopt(s->s, SOL_SOCKET, SO_KEEPALIVE, (char*)bOptVal, sizeof(bOptVal));
                        s->tcpState = TCP_STATE::LISTEN_CONNECTED;
                        return SOCK_ESTABLISHED;
                }
                return SOCK_LISTEN;
        }
        FD_ZERO(&fd_s);
        FD_SET(s->s, &fd_s);
        iResult = select(0, NULL, &fd_s, NULL, &select_timeout);
        if (iResult == SOCKET_ERROR)
                return SOCK_CLOSED;
        if (iResult == 0){
                switch (s->MR[1])
                {
                case Sn_MR_TCP:
                        switch (s->tcpState)
                        {
                        case TCP_STATE::LISTEN_CONNECTED:
                        case TCP_STATE::CLIENT_CONNECTED:
                                return SOCK_ESTABLISHED;
                        default:
                                FD_ZERO(&fd_s);
                                FD_SET(s->s, &fd_s);
                                iResult = select(0, NULL, NULL, &fd_s, &select_timeout);
                                if (iResult != 0){
                                        s->tcpState = TCP_STATE::CLOSED;
                                        return SOCK_CLOSED;
                                }
                                return SOCK_INIT;
                        }
                case Sn_MR_UDP:
                        return SOCK_UDP;
                case Sn_MR_IPRAW:
                        return SOCK_IPRAW;
                default:
                        return SOCK_CLOSED;
                }
        }
        else if (iResult > 0){
                FD_ZERO(&fd_s);
                FD_SET(s->s, &fd_s);
                iResult = select(0, NULL, NULL, &fd_s, &select_timeout);
                if (iResult != 0){
                        s->tcpState = TCP_STATE::CLOSED;
                        return SOCK_CLOSED;
                }
                switch (s->MR[1])
                {
                case Sn_MR_TCP:
                        switch (s->tcpState)
                        {
                        case TCP_STATE::LISTEN:
                                s->tcpState = TCP_STATE::LISTEN_CONNECTED;
                                return SOCK_ESTABLISHED;
                        case TCP_STATE::CLIENT:
                                s->tcpState = TCP_STATE::CLIENT_CONNECTED;
                                return SOCK_ESTABLISHED;
                        case TCP_STATE::CLOSED:
                                return SOCK_CLOSED;
                        }
                        WizRecv(s);
                        if (s->tcpState == TCP_STATE::CLOSED) return SOCK_CLOSED;
                        return SOCK_ESTABLISHED;
                case Sn_MR_UDP:
                        return SOCK_UDP;
                case Sn_MR_IPRAW:
                        return SOCK_IPRAW;
                default:
                        return SOCK_CLOSED;
                }
        }
        //ns = WSAGetLastError();
        return SOCK_CLOSED;
}

READ_REG_FUNC(read_PORTR){
        return s->PORTR[z];
}

READ_REG_FUNC(read_DPORTR){
        if (z) return (s->sa_in.sin_port & 0xff00) >> 8;
        else return s->sa_in.sin_port & 0x00ff;
}

READ_REG_FUNC(read_ZERO){
        return 0;
}

READ_REG_FUNC(read_DIPR12){
        if (!z)
                return s->sa_in.sin_addr.S_un.S_un_b.s_b1;
        else
                return s->sa_in.sin_addr.S_un.S_un_b.s_b2;
}

READ_REG_FUNC(read_DIPR34){
        if (!z)
                return s->sa_in.sin_addr.S_un.S_un_b.s_b3;
        else
                return s->sa_in.sin_addr.S_un.S_un_b.s_b4;
}

READ_REG_FUNC(read_PROTOR){
        if (!z)
                return 0x00;
        else
                return s->PROTOR;
}

READ_REG_FUNC(read_TX_FSR32){
        if (z == 0) return 0;
        return ((sizeof(s->tx) - ((u_int)(s->tx_ptr - s->tx))) & 0x00010000) >> 16;
}

READ_REG_FUNC(read_TX_FSR10){
        if (z == 0) return ((sizeof(s->tx) - ((u_int)(s->tx_ptr - s->tx))) & 0x0000ff00) >> 8;
        return (sizeof(s->tx) - ((u_int)(s->tx_ptr - s->tx))) & 0x000000fF;
}

READ_REG_FUNC(read_RX_RSR32){
        if (s->s == INVALID_SOCKET)return 0;
        if (z == 0) return 0;
        WizRecv(s);
        return (u_char)((s->RX_RSR & 0x00010000) >> 16);
}

READ_REG_FUNC(read_RX_RSR10){
        if (s->s == INVALID_SOCKET)return 0;
        WizRecv(s);
        if (z == 0) return (s->RX_RSR & 0x0000ff00) >> 8;
        return s->RX_RSR & 0x000000fF;
}

READ_REG_FUNC(read_RX){
        if (s->RX_RSR == 0)return 0;
        data = *(s->rx_ptr + z);
        if (z == 0)return data;
        s->RX_RSR -= 2;
        if (s->RX_RSR == 0)
                s->rx_ptr = NULL;
        else
                s->rx_ptr += 2;
        return data;
}

u_char(*regReadFunc[0x20])(sInfoStruct *, u_char) = {
        read_MR, read_CR, read_ZERO, read_ZERO, read_SSR, read_PORTR, read_ZERO, read_ZERO,
        read_ZERO, read_DPORTR, read_DIPR12, read_DIPR34, read_ZERO, read_PROTOR, read_ZERO, read_ZERO,
        read_ZERO, read_ZERO, read_TX_FSR32, read_TX_FSR10, read_RX_RSR32, read_RX_RSR10, read_ZERO, read_ZERO,
        read_RX, read_ZERO, read_ZERO, read_ZERO, read_ZERO, read_ZERO, read_ZERO, read_ZERO,
};
void WIZ_CLOSE_SOC(sInfoStruct * s){
        if (s->s != INVALID_SOCKET){
                ioctlsocket(s->s, FIONBIO, &is_blocked);
                iResult = closesocket(s->s);
                DPRINTF("closesocket = %x", iResult);
                s->s = INVALID_SOCKET;
                s->PROTOR = 0x00;
        }
}

void WizOpenSocket(sInfoStruct * s){
        bool bOptVal = true;
        DWORD tout = 3000;
        if (s->s != INVALID_SOCKET) return;
        s->RX_RSR = 0;
        memset(&s->sa_in.sin_addr,0x00,sizeof(s->sa_in.sin_addr));
        s->sa_in.sin_family = AF_INET;
        s->rx_ptr = NULL;
        s->tx_ptr = s->tx;
        s->tcpState = TCP_STATE::NONE;
        s->BINDED = 0;
        switch (s->MR[1])
        {
        case Sn_MR_TCP:
                s->s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
                setsockopt(s->s, SOL_SOCKET, SO_KEEPALIVE, (char*)&bOptVal, sizeof(bOptVal));
                DPRINTF("Opensocket %u ", s->s);
                break;
        case Sn_MR_UDP:
                s->s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
                break;
        case Sn_MR_IPRAW:
                setsockopt(s->s, SOL_SOCKET, SO_RCVTIMEO, (char*)&tout, sizeof(tout));
                s->s = socket(AF_INET, SOCK_RAW, s->PROTOR);
                break;
        default:
                s->s = INVALID_SOCKET;
                break;
        }
        if (s->s != INVALID_SOCKET){
                ioctlsocket(s->s, FIONBIO, &non_blocked);
                s->CR = 0;
        }
}

void WizConnect(sInfoStruct *s){
        if (s->MR[1] != Sn_MR_TCP || s->s == INVALID_SOCKET || s->tcpState != TCP_STATE::NONE) return;
        s->CR = 0;
        s->tcpState = TCP_STATE::CLIENT;
        connect(s->s, (SOCKADDR *)&s->sa_in, sizeof(s->sa_in));
}

void WisDisconnect(sInfoStruct *s){
        if (s->MR[1] != Sn_MR_TCP) return;
}

void WisListen(sInfoStruct *s){
        if (s->MR[1] != Sn_MR_TCP || s->s == INVALID_SOCKET || s->tcpState != TCP_STATE::NONE) return;
        s->tcpState = TCP_STATE::LISTEN;
        ZeroMemory(&sa_in, sizeof(sa_in));
        //s->list = s->s;
        sa_in.sin_family = AF_INET;
        sa_in.sin_addr.S_un.S_addr = 0;
        sa_in.sin_port = (s->PORTR[1] << 8) | s->PORTR[0];
        bind(s->s, (sockaddr *)&sa_in, sizeof(sa_in));
        s->BINDED = 1;
        listen(s->s, 1);
        ns = sizeof(s->sa_in);
}

void WizSend(sInfoStruct *s){
        if (s->s == INVALID_SOCKET)return;
        iResult = (int)(s->TX_WRSR.ul & 0x01ffff);
        if (s->MR[1] == Sn_MR_TCP && s->tcpState != TCP_STATE::NONE){
                send(s->s, (char*)s->tx, (int)(s->TX_WRSR.ul & 0x01ffff), 0);
                s->tx_ptr = s->tx;
                s->TX_WRSR.ul = 0;
                DPRINTF("Send %d bytes\r\n", iResult);
        }
        else if ((s->MR[1] == Sn_MR_UDP) || (s->MR[1] == Sn_MR_IPRAW)){
                if(s->BINDED == 0) soc_bind(s);
                sendto(s->s, (char*)s->tx, (int)(s->TX_WRSR.ul & 0x01ffff), 0, (sockaddr *)&s->sa_in, sizeof(sa_in));
                s->tx_ptr = s->tx;
                s->TX_WRSR.ul = 0;
                DPRINTF("Send %d bytes\r\n", iResult);
        }
}

WRITE_REG_FUNC(write_DPORTR){
        if (z) s->sa_in.sin_port = ((s->sa_in.sin_port) & 0x00ff) | (d << 8);
        else s->sa_in.sin_port = ((s->sa_in.sin_port) & 0xff00) | d;
};

WRITE_REG_FUNC(write_MR){
        WIZ_CLOSE_SOC(s);
        s->MR[z] = d;
};

WRITE_REG_FUNC(write_CR){
        if (!z)return;
        DPRINTF("Write CR = %x\r\n", d);
        s->CR = d;
        switch (d)
        {
        case Sn_CR_CLOSE:
                WIZ_CLOSE_SOC(s);
                s->CR = 0;
                break;
        case Sn_CR_RECV:
                s->rx_ptr = NULL;
                s->RX_RSR = 0;
                s->CR = 0;
                break;
        case Sn_CR_SEND:
                WizSend(s);
                break;
        case Sn_CR_DISCON:
                if (s->s != INVALID_SOCKET){
                        WIZ_CLOSE_SOC(s);
                        //WizOpenSocket(s);
                        s->CR = 0;
                }
                break;
        case Sn_CR_OPEN:
                WizOpenSocket(s);
                break;
        case Sn_CR_LISTEN:
                WisListen(s);
                break;
        case Sn_CR_CONNECT:
                WizConnect(s);
                break;
        default:
                break;
        }
};

WRITE_REG_FUNC(write_PORTR){
        s->PORTR[z] = d;
};

WRITE_REG_FUNC(write_DIPR12){
        if (!z)s->sa_in.sin_addr.S_un.S_un_b.s_b1 = d;
        else s->sa_in.sin_addr.S_un.S_un_b.s_b2 = d;
}

WRITE_REG_FUNC(write_DIPR34){
        if (!z)s->sa_in.sin_addr.S_un.S_un_b.s_b3 = d;
        else s->sa_in.sin_addr.S_un.S_un_b.s_b4 = d;
}

WRITE_REG_FUNC(write_PROTOR){
        if (z)s->PROTOR = d;
}

WRITE_REG_FUNC(write_TX_WRSR32){
        s->TX_WRSR.b[3 - z] = d;
};

WRITE_REG_FUNC(write_TX_WRSR10){
        s->TX_WRSR.b[1 - z] = d;
};

WRITE_REG_FUNC(write_TX){
        *(s->tx_ptr + z) = d;
        if (z == 0)return;
        s->tx_ptr += 2;
};

WRITE_REG_FUNC(write_ZERO){};

void(*regWriteFunc[0x20])(sInfoStruct * s, u_char, u_char) = {
        write_MR, write_CR, write_ZERO, write_ZERO, write_ZERO, write_PORTR, write_ZERO, write_ZERO,
        write_ZERO, write_DPORTR, write_DIPR12, write_DIPR34, write_ZERO, write_PROTOR, write_ZERO, write_ZERO,
        write_TX_WRSR32, write_TX_WRSR10, write_ZERO, write_ZERO, write_ZERO, write_ZERO, write_ZERO, write_TX,
        write_ZERO, write_ZERO, write_ZERO, write_ZERO, write_ZERO, write_ZERO, write_ZERO, write_ZERO,
};

u_char Wiz5300_RegRead(unsigned int Addr)
{

        if(comp.wiznet.p82&0x08)Addr^=0x01;
        if (Addr >= 0x0200)
                return regReadFunc[(Addr & 0x3f) >> 1](&soc[(Addr >> 6) & 0x07], Addr & 0x01);
        if (Addr <= 0x00ff){
                return regs[Addr];
        }
        return 0;
}

void Wiz5300_RegWrite(unsigned int Addr, unsigned char Data)
{
        if(comp.wiznet.p82&0x08)Addr^=0x01;
        if (Addr >= 0x0200)
                regWriteFunc[(Addr & 0x3f) >> 1](&soc[(Addr >> 6) & 0x07], Data, Addr & 0x01);
        else if (Addr <= 0x00ff) {
                regs[Addr] = stat_regs[Addr];
        }
}

void getNetProperties(void){
        char ac[80];
        gethostname(ac, sizeof(ac));
        struct hostent *phe = gethostbyname(ac);
        if (phe)memcpy(&stat_regs[0x0018], phe->h_addr_list[0], 4);
        if (*((ULONG32*)(&stat_regs[0x0018])) == 0)return;

        PIP_ADAPTER_INFO pAdapterInfo, pAdapter = NULL;
        DWORD dwRetVal = 0;
        //unsigned int i;
        //struct tm newtime;
        //errno_t error;
        ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
        pAdapterInfo = (IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO));
        // if (pAdapterInfo==NULL) ...return
        if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW){
                free(pAdapterInfo);
                pAdapterInfo = (IP_ADAPTER_INFO*)malloc(ulOutBufLen);
                // if (pAdapterInfo==NULL) ...return
        }
        if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR){
                pAdapter = pAdapterInfo;
                while (pAdapter)
                {
                        if (pAdapter->IpAddressList.Context != *((DWORD32*)(&stat_regs[0x0018]))){
                                pAdapter = pAdapter->Next;
                                continue;
                        }
                        printf("Network adapter: %s \r\n",pAdapter->Description);
                        *((ULONG32*)(&stat_regs[0x0014])) = inet_addr(pAdapter->IpAddressList.IpMask.String);
                        *((ULONG32*)(&stat_regs[0x0010])) = inet_addr(pAdapter->GatewayList.IpAddress.String);
                        memcpy(&stat_regs[0x008], pAdapter->Address, 8);
                        break;
                }
        }
        else
        {
                //print error, no return
        }
        if (pAdapterInfo){
                free(pAdapterInfo);
        }
}

int Wiz5300_Init(void)
{
        ZeroMemory(stat_regs, sizeof(stat_regs));
        memset(&stat_regs[0x20], 0x08, 16);
        stat_regs[0x00] = 0x38;
        stat_regs[0xfe] = 0x53;
        stat_regs[0x31] = 0xff;
        memcpy(regs, stat_regs, sizeof(stat_regs));

        ZeroMemory(soc, sizeof(soc));
        WSAStartup(MAKEWORD(2, 2), &wsaData);
        for (int i = 0; i < 8; i++){
                soc[i].s = INVALID_SOCKET;
                soc[i].sa_in.sin_family = AF_INET;
                soc[i].list = INVALID_SOCKET;
                soc[i].PROTOR = 0x00;
        }
        select_timeout.tv_sec = 0;
        select_timeout.tv_usec = 0;
        getNetProperties();
        //DPRINTF("wiz init\r\n");
        return 0;
}

int Wiz5300_Close(void)
{
        for (int i = 0; i < 8; i++) {
                if (soc[i].s != INVALID_SOCKET){
                        ioctlsocket(soc[i].s, FIONBIO, &is_blocked);
                        closesocket(soc[i].s);
                }
        }
        WSACleanup(); //Clean up Winsock
        return 0;
}


void pXXAB_Write(unsigned port, unsigned char val){
        if((!(port&0x8000))&&(comp.wiznet.p82&0x10)){
                Wiz5300_RegWrite(((comp.wiznet.p81&0x0f)<<6)|
                        ((port&0x3f00)>>8),val);
                return;
        }
        if(port==0x83ab){
                if((comp.wiznet.p83&0x10)^(val&0x10)){
                        if(val&0x10){Wiz5300_Init();}
                        else {Wiz5300_Close();}
                }
                comp.wiznet.p83=val;
               
        }else if(port==0x82ab){
                comp.wiznet.p82=val;
        }else if(port==0x81ab){
                comp.wiznet.p81=val;
                return;
        }
        comp.wiznet.memEna=conf.wiznet && (comp.wiznet.p82 & 0x04)
                && (comp.wiznet.p83 & 0x10) && (!(comp.wiznet.p82 & 0x10));
        return;
}

unsigned char pXXAB_Read(unsigned port){
        if((!(port&0x8000))&&(comp.wiznet.p82&0x10)){
                return Wiz5300_RegRead(((comp.wiznet.p81&0x0f)<<6)|
                        ((port&0x3f00)>>8));
               
        }
                if(port==0x83ab){
                        return comp.wiznet.p83;
                }else if(port==0x82ab){
                        return comp.wiznet.p82;
                }else if(port==0x81ab){
                        return comp.wiznet.p81;
                }else if(port&0x8000){return 0xFF;}

                return 0xff;
}