07-28-2026, 03:58 AM
Tixu (the ngpcraft guy or gal) has been helping me with this - my single byte copy might actually be faster, but his is definitely more robust
https://codeberg.org/ahchay/FRUITYVINES.ngp
Two includes, and one change to use ngpc.h and it works like a charm - two lines to init:
link_state isn't needed it to avoid unnessecary screen refreshes when updating the status graphics
Then the actual meat of the transfer is
And that's kind of it - you have to limit the buffer size to a miserly 8 bytes - hence I copy my playfield over one line at a time. I could probably compress that a bit and do it fewer chunks, but it's fine for puzzle games...
If you want to have some kind of onscreen indicator of the link status, you just query ngpc_linkkit_state()
The game itself needs a bit more finesse - as far as link mode goes though, it should probably wait for the second player to join before starting to play, and should also quit if the link is interrupted or whatever
https://codeberg.org/ahchay/FRUITYVINES.ngp
Two includes, and one change to use ngpc.h and it works like a charm - two lines to init:
Code:
ngpc_linkkit_init();
link_state=ngpc_linkkit_state();link_state isn't needed it to avoid unnessecary screen refreshes when updating the status graphics
Then the actual meat of the transfer is
Code:
// Setup an 8 byte transfer buffer
// This one contains the row number to update and the 5 individual tile ID's for my puzzle game
myBuffer[0]=cur_LinkRow;
for(iLoopX=0;iLoopX<5;iLoopX++)
{
myBuffer[1+iLoopX]=Board[cur_LinkRow][iLoopX].TileNo;
}
// Just resets the current row indicator so that it loops from 0-9
cur_LinkRow++;
if(cur_LinkRow>9) cur_LinkRow=0;
ngpc_linkkit_stage(myBuffer); // stages the send
ngpc_linkkit_update(); // sends and receives data
if (ngpc_linkkit_fresh()) // Checks that the link is active
{
u8 TargetRow;
ngpc_linkkit_peek(TheirBuffer); // Retrieves the data into gRx[]
// Copy the buffer from the "other" machine into the game structures
TargetRow=TheirBuffer[0];
PrintDecimal(SCR_BACK_PLANE,PAL_TEXT,0,1,TargetRow,2);
for(iLoopX=0;iLoopX<5;iLoopX++)
{
OpponentBoard[TargetRow][iLoopX].TileNo=TheirBuffer[1+iLoopX];
}
}And that's kind of it - you have to limit the buffer size to a miserly 8 bytes - hence I copy my playfield over one line at a time. I could probably compress that a bit and do it fewer chunks, but it's fine for puzzle games...
If you want to have some kind of onscreen indicator of the link status, you just query ngpc_linkkit_state()
Code:
if(link_state!=ngpc_linkkit_state())
{
link_state=ngpc_linkkit_state();
switch (ngpc_linkkit_state()) // Check link status
{
case LINKKIT_CONNECTING:
//PrintString(SCR_BACK_PLANE,PAL_TEXT, 0, 0, "LOOKING FOR PLAYER 2");
PaintTile(SCR_BACK_PLANE,384+LINK_HOST,PAL_LINK_HOST,7,0,2,2);
PaintTile(SCR_BACK_PLANE,384+LINK_CABLE,PAL_LINK_CABLE,9,0,2,2);
PaintTile(SCR_BACK_PLANE,384+LINK_CLIENT_DISCONNECTED,PAL_LINK_HOST,11,0,2,2);
break;
case LINKKIT_READY:
//PrintString(SCR_BACK_PLANE,PAL_TEXT, 0, 0, ngpc_linkkit_role() == LINKKIT_ROLE_HOST ? "CONNECTED - HOST " : "CONNECTED - GUEST ");
PaintTile(SCR_BACK_PLANE,384+LINK_HOST,PAL_LINK_HOST,7,0,2,2);
PaintTile(SCR_BACK_PLANE,384+LINK_GOOD,PAL_LINK_GOOD,9,0,2,2);
PaintTile(SCR_BACK_PLANE,384+LINK_CLIENT,PAL_LINK_HOST,11,0,2,2);
break;
case LINKKIT_LOST:
//PrintString(SCR_BACK_PLANE,PAL_TEXT, 0, 0, "LINK LOST - RETRYING");
PaintTile(SCR_BACK_PLANE,384+LINK_HOST,PAL_LINK_HOST,7,0,2,2);
PaintTile(SCR_BACK_PLANE,384+LINK_RETRY,PAL_LINK_QUESTION,9,0,2,2);
PaintTile(SCR_BACK_PLANE,384+LINK_CLIENT,PAL_LINK_HOST,11,0,2,2);
break;
case LINKKIT_MISMATCH:
//PrintString(SCR_BACK_PLANE,PAL_TEXT, 0, 0, "OTHER CART DIFFERS ");
break;
default:
//PrintString(SCR_BACK_PLANE,PAL_TEXT, 0, 0, "NO LINK ");
PaintTile(SCR_BACK_PLANE,384+LINK_HOST,PAL_LINK_HOST,7,0,2,2);
PaintTile(SCR_BACK_PLANE,384+LINK_BAD,PAL_LINK_BAD,9,0,2,2);
PaintTile(SCR_BACK_PLANE,384+LINK_CLIENT,PAL_LINK_HOST,11,0,2,2);
break;
}The game itself needs a bit more finesse - as far as link mode goes though, it should probably wait for the second player to join before starting to play, and should also quit if the link is interrupted or whatever

