The ugBASIC language is equipped with primitives capable of communicating
with an external server, called DOJO, which is a system for creating virtual
"game rooms" online. This guide contains information and tutorials to make the best use
of this feature, as well as a description of the DOJO protocol
Preparation
Services
Message Ports
In order to use the DOJO protocol features, it is necessary to connect the retrocomputer to a server that implements the protocol. The ugBASIC language provides several servers that can be used, and the procedure to link to it is different, depending on the target.
All coco and coco3
emulators support the Becker port.
To enable this port on XRoar, you need to use the -cart-becker
command line option. Moreover, you
need to give a specific TCP port and address to use. On that address a server that implements the DOJO protocol
should listen for TCP/IP connections from the machine the emulator runs on. They make that connection
every time it starts.
In this example, we use the ugBASIC's server:
xroar -machine coco -cart-becker -becker-ip dojo.ugbasic.iwashere.eu -becker-port 50666 dojo_example_01.bin
xroar -machine coco3p -cart-becker -becker-ip dojo.ugbasic.iwashere.eu -becker-port 50666 dojo_example_01.bin
All c64 emulators support the
RS-232 port by using the ACIA1 chipset. In order to test the operation on a PC,
you need a modem connected to the RS-232 port or its emulation. Emulators
allow you to connect the RS-232 port to a TCP port, and then communicate with a
"server" that acts as a modem (unless there is a modem integrated into the
emulator). From empirical tests carried out on current software, there are
some problems (or actual "bugs") that prevent the correct operation of some
of these configurations "out of the box".
At the moment the following configuration has been successfully tested:
vice
- VICE 3.8 emulator, recompiled a specific fix (click to show), Windows binaries available here (20 MB):
--- a/src/rs232drv/rsuser.c
+++ b/src/rs232drv/rsuser.c
@@ -243,10 +243,10 @@ static int set_up_device(int val, void *param)
rsuser_device = val;
- if (fd >= 0) {
- rs232drv_close(fd);
- fd = rs232drv_open(rsuser_device);
- }
+ // if (fd >= 0) {
+ // rs232drv_close(fd);
+ // fd = rs232drv_open(rsuser_device);
+ // }
return 0;
}
@@ -457,9 +457,9 @@ static void rsuser_setup(void)
clk_start_tx = 0;
clk_start_bit = 0;
dsr_cnt = 0;
- if (fd < 0 && rsuser_enabled) {
- fd = rs232drv_open(rsuser_device);
- }
+ // if (fd < 0 && rsuser_enabled) {
+ // fd = rs232drv_open(rsuser_device);
+ // }
alarm_set(rsuser_alarm, maincpu_clk + char_clk_ticks / 10);
}
tcpser
- IP232 modem, recompiled under cygwin with a specific fix (click to show), Windows binaries available here (130 KB).
--- a/src/bridge.c
+++ b/src/bridge.c
@@ +236,7 -236,6 @@
} else {
LOG(LOG_INFO, "Link has gone down");
writePipe(cfg->wp[0][1], MSG_LE_DOWN);
+ new_status = -1;
}
}
tcpser -v 25233 -p 6400 -s 1200
x64sc -default -acia1 -rsdev1 "127.0.0.1:25233" -rsdev1baud "1200" -rsuserbaud "1200" -userportdevice "2" -myaciadev "0"
tcpser
must be restarted each time the emulator is closed
after connected to the DOJO server.
The DOJO protocol provides a set of commands that are implemented as statements and functions on ugBASIC, and serve to model a set of services:
If you choose to use this mode, you have access to a direct two-way
communication channel to the DOJO server. This type of connection can
be useful if you want to interact directly with the protocol elements.
In this case, the available instructions are as follows:
= PING()
- return TRUE
if the connection is alive;= RECEIVE()
- receive a byte from the communication
channel, and it will wait indefinitely until the next byte arrives;SEND
- send a byte into the communication
channel, and it will wait indefinitely until sent;= READY()
- return TRUE
if a byte to receive is present.In this mode, a mechanism for managing ports and messages is set up above the communication channel, which are elements of asynchronous communication between programs. They are very useful for allowing the management of multiplayer games. The instructions that are available in this mode are:
= PING()
- return TRUE
if the connection is alive;= LOGIN(...)
- it allows the client to be identified at the server;= SUCCESS(...)
- it allows to understand if the last command was successfully executed;= CREATE PORT(...)
- it allows to create a (receiving) port;= FIND PORT(...)
- it allows to find out a (sending) port;PUT MESSAGE ...
- it allows to send a message to a port;= PEEK MESSAGE(...)
- it allows to check if a message is available;= GET MESSAGE(...)
- it allows to retrieve any available message;DESTROY PORT
- it allows to destroy the receiving port;
= LOGIN( username, password )
LOGIN
function return a sessionId
, To
be used on other commands / functions. To verify that the operation has taken place, the SUCCESS()
function must be used. If SUCCESS(...)
returns a TRUE
result, then the login process was successful; if it returns a FALSE
result,
then the process must be considered failed for some reason (the username may
have already been used, or the credentials are incorrect, and so on).
CREATE PORT(...)
function, whose
syntax is as follows:= CREATE PORT( sessionId, application )
sessionId
parameter is the same one that returned the call to
LOGIN(...)
, and identifies the working session at that moment.
The application
parameter represents, instead, the name of the
application or functionality to which you want to associate this message port.
= FIND PORT(...)
function.port = FIND PORT( sessionId, username, application )
sessionId
). To get it, you need to identify
yourself, and you can do that with the procedure explained in the previous
chapter. Secondly, you need to know the identifier of the user who
owns that mailbox (username
). Finally, it is essential to know
the name of the application on whose behalf we are looking for the mailbox
(application
).application
identifier
(or, if we want, an application functionality identifier). The consequence is that the
DOJO protocol indirectly creates communication networks whose nodes belong to the same
application. This is the basis for sharing servers by programs that are also very different
from each other.
To put a message we can use the PUT MESSAGE
statement, with the
following syntax:
PUT MESSAGE portId, message
This is a statement, not a function. It follows
that we cannot know if the statement was successful. This does not really represent
a limitation, for the simple fact that the statement will always be successful: if
the program on the other side of the port is not available, for some reason, the
message will be preserved by the DOJO server, and it will be delivered at the
first available moment.
Once you have created a port and sent a message, you may wait for a
message to arrive to you. As explained in the previous chapters,
the port is accessible to anyone who knows its identifier (perhaps
because they have searched for it). Therefore, many messages may
arrive or none at all. The program that wants to wait for the
arrival can use the PEEK MESSAGE
command. The syntax is as follows:
= PEEK MESSAGE( portId )
If it returns FALSE
, it means that the message port is empty; on
the contrary, if it returns TRUE
, it is possible to fetch the message
using the GET MESSAGE
command. The syntax is:
= GET MESSAGE( portId )
If you have found a problem, if you think there is a bug or, more
simply, you would like something to be improved, write a topic on the official forum, or open an issue on GitHub.
Thank you!