TI-89 / TI-92p / V200 Linking by GregD
Purpose of This Document:
There seems to be some confusion about linking and the 68k based calculators. This document examines the problem of creating a link between two calculators for the purpose of a multiplayer game.
Requirements:
To make full use of this paper, I recommend the latest version of TIGCC (http://tigcc.ticalc.org) My examples have been compiled and tested using TIGCC v0.94 Beta 19. Most of the linking code that is found on this webpage can also be found in a compile time library that I am developing for TIGCC called extralib. This code works with VTI virtual links, and between my TI-89 HW1, and TI-92 Plus HW2 calculators.
On The Number of Players:
When creating linking routines, one of the most common mistakes I see is trying to determine which player is number one, and which player is the second player. Often, it is not necessary to know to know which calculator is player one, and which is player two.
Take the game of Tetris. There is no need to know which player is the first player, and which is the second player. It can easily be assumed that the data received is from the other player, and handled as such. That is to say that each calculator acts as it is player #1, and stores the information coming from the other calculator as player #2. In this way, each calculator thinks it is player #1 and the other calculator is player #2. Notice that in a game of tetris, map position of the player does not need to be accounted for.
The CreateLink and CreateLink_ex routines have been giving me some trouble... they are based off of this routine which seems to work well (it is from the Insane Game of which I am the author.) For now, I recommend using this routine in place of the other routines. If you have any ideas on why the CreateLink and CreateLink_ex functions occasionally fail on real calculators (it works with vti virtual links), please email me
short CreateLink_ex2(void)
{
char s=LINK_PLAYER_ONE;
char r;
OSLinkOpen();
transmit(&s,1);
for(;;)
{
if(receive(&r,1))
{
if(r==LINK_PLAYER_ONE)
{
s=LINK_PLAYER_TWO;
transmit(&s,1);
return LINK_PLAYER_ONE; //player 1
}
else if(r==LINK_PLAYER_TWO)
{
return LINK_PLAYER_TWO; //player 2
}
else
{
s=LINK_PLAYER_ONE;
transmit(&s,1);
}
}
if(OSCheckBreak())
{
OSClearBreak();
break;
}
}
OSLinkClose();
return LINK_FAILURE; //LinkError
}
Creating The Initial Connection:
I am assuming that you want to establish a connection between two calculators, and that you are NOT concerned about giving each calculator a unique identifier (ie player1, player2).
enum { LINK_FAILURE, LINK_CREATE, LINK_CONNECTED, LINK_PLAYER_ONE, LINK_PLAYER_TWO };
short CreateLink(void)
{
UCHAR link; //the numerical value of link is not important
OSLinkOpen();
LIO_SendData(&link,1);
if(LIO_RecvData(&link,1,0))
{
OSLinkReset();
return LINK_FAILURE;
}
else
{
LIO_SendData(&link,1);
}
while(!LIO_RecvData(&link,1,10));//the delay is important!
return LINK_CONNECTED;
}
In order to understand this code, picture it running on two calculators. One calculator executes this code first, and ends up waiting for data. The second calculator executes the code, and sends the other calculator into the second LIO_SendData call. The second call to LIO_SendData signals that the two calculators are linked, and the program proceeds to the while loop. The while loop is important; one calculator will receive one extra byte which needs to be removed from the link queue. BUT, this byte may not be in the queue immediately, so we delay for a short time before assuming that the extra byte was not sent to the calculator executing the loop waiting for said byte.
If you need to determine which calculator is number one, and which is number two, a small modification to the above code helps:
short CreateLink_ex(void)
{
UCHAR link; //the numerical value of link is not important
BOOL player_one=FALSE;
OSLinkOpen();
LIO_SendData(&link,1);
if(LIO_RecvData(&link,1,0))
{
OSLinkReset();
return LINK_FAILURE;
}
else
{
LIO_SendData(&link,1);
}
while(!LIO_RecvData(&link,1,10))//the delay is important!
player_one=TRUE;
return player_one?LINK_PLAYER_ONE:LINK_PLAYER_TWO;
}
Most often, it is advantageous to determine which calculator is player one, and which is player two to provide a client server model. It is also helpful to use this approach when the two players need to start at a specific position on a map -- avoiding the problem of both players becomming located at the same map location.
Copyright © 2000 - by Greg D. All Rights Reserved.
|