Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How do I integrate the link cable into my projects?
#37
I've further abstracted the linkkit code to my own handshake routine, which I think handles the host/client detection better and also attempts to sync to the same "game" on the other side of the cable - this might be a bit clunky still, but it seems to be consistent from the couple of dozen tests I've run - I should probably make that counter a u16 as it wraps pretty quickly. For my purposes I don't really mind much - as long as the handshake consistently nominates one machine as the host and the other as the client.

Worked example in ahchay/HEADTOHEAD.ngp: Head to head classics for the NGPC - Codeberg.org

Code:
/*******************************************************************
* Set up the link to the other console
*
* The four Char* parameters here are the unique code for the game
* P-O-N-G for Pong, N-O-O-N for High Noon etc
*
********************************************************************/
u8 HeadToHeadHandshake(u8 Char1, u8 Char2, u8 Char3, u8 Char4)
{
    u8 myBuffer[8];
    u8 theirBuffer[8];
    bool ReadyHost;
    bool ReadyClient;
    u8 iLoop;
    u8 link_state;
    u8 ConnectionTime;
    u8 retval;

    ReadyHost=false;
    ReadyClient=false;

    ngpc_linkkit_init();
    link_state=ngpc_linkkit_state();

    //PrintString(SCR_FORE_PLANE,PAL_TEXT,0,0,"PLAYER   VS     LINK");
    //PrintString(SCR_FORE_PLANE,PAL_TEXT,8,0,"...");

    ConnectionTime=0;
    retval=ROLE_CLIENT;

    while((!ReadyHost)||(!ReadyClient))
    {
        // Send and receive the joystick state between the two machines
        u8 iLoop;

        if(!ReadyHost) ConnectionTime++;

        myBuffer[0]=LINK_HANDSHAKE;
        myBuffer[1]=Char1;
        myBuffer[2]=Char2;
        myBuffer[3]=Char3;
        myBuffer[4]=Char4;
        myBuffer[5]=ConnectionTime;
        myBuffer[6]=QRandom();
        myBuffer[7]=ReadyHost;
       
        ngpc_linkkit_stage(myBuffer); // stages the send
        ngpc_linkkit_update(); // sends and receives data
        if (ngpc_linkkit_fresh()) // Checks that the link is active
        {
            ReadyHost=true;
            ngpc_linkkit_peek(theirBuffer); // Retrieves the data into gRx[]
            //UnpackTheirs();
        }
        link_state=ngpc_linkkit_state();
        switch (link_state) // Check link status
        {
            case LINKKIT_CONNECTING:
                //PrintString(SCR_FORE_PLANE,PAL_TEXT,8,0,"...");
                break;
            case LINKKIT_READY:
                //PrintString(SCR_FORE_PLANE,PAL_TEXT,8,0,"OK!");
                break;
            case LINKKIT_LOST:
                //PrintString(SCR_FORE_PLANE,PAL_TEXT,8,0,"!!!");
                break;
            case LINKKIT_MISMATCH:
                //PrintString(SCR_FORE_PLANE,PAL_TEXT,8,0,"???");
                //PrintString(SCR_FORE_PLANE,PAL_TEXT, 0, 17, "OTHER CART DIFFERS  ");
                break;
            default:
                //PrintString(SCR_FORE_PLANE,PAL_TEXT,8,0,"***");
                ngpc_linkkit_init();
                break;
        }
       
        ReadyClient=true;
        switch(theirBuffer[0])
        {
            case LINK_HANDSHAKE:
                // other client in handshake mode (as they should be)
                // Check that their buffer contains the magic letters
                // for this game mode
                // Probably need to complain/abort if these differ
                ReadyClient=theirBuffer[7];
                if(ReadyClient)
                {
                    for(iLoop=0;iLoop<5;iLoop++)
                    {
                        if(theirBuffer[iLoop]!=myBuffer[iLoop])
                        {
                            ReadyClient=false;
                        }
                    }
                    if(ReadyClient)
                    {
                        if(ConnectionTime<theirBuffer[5])
                        {
                            retval=ROLE_HOST;
                        }
                        else if(ConnectionTime==theirBuffer[5]&&myBuffer[6]<theirBuffer[6])
                        {
                            retval=ROLE_HOST;
                        }
                    }
                }
                break;
            case LINK_GAME:
            case LINK_META:
                // other client is already in game - shouldn't happen, but
                // it can do
                // Just let it fall through - they may join the game late
                // but the sync routine should sort it out
                // At this point, we're assuming that the other client
                // is the same cartid. They shouldn't have got past the
                // handshake on their end if not
                // Players can force this by starting one game mode and then
                // quitting one console and rejoining in another.
                // That's on them though ;)
                break;
            default:
                // Nonsense or empty data
                ReadyClient=false;
                break;
        }
        // if(myBuffer[0]!=theirBuffer[0])
        // {
        //     ReadyClient=false;
        // }

        if(JOYPAD_OPTION)
        {
            return ROLE_ABORT;
        }

    }
    return retval;

}
Reply


Messages In This Thread
RE: How do I integrate the link cable into my projects? - by Ahchay - 08-07-2026, 07:04 PM

Forum Jump:


Users browsing this thread: 1 Guest(s)