DoujinStars
VUEngine
VUEngine

patreon


Link Cable support in VUEngine is complete!

After a lot of testing and painstaking trial and error, frustration at the documentation and at our own mistakes, we have been able to implement 100% reliable and efficient communications between two Virtual Boy systems, using hardware interrupts and without having to rely on artificial and unnecessarily long delays or on magical numbers.

When provided with a pointer to a BYTE array and a number of bytes to be transmitted, the CommunicationManager singleton class supports the transmission of data of any size in both synchronous and asynchronous modes, either bidirectionally or only in one direction.


Synchronous Mode

In synchronous mode, the execution of the program halts until all the data is transmitted. Each byte is transmitted one by one until all have been sent. Then, the program returns to the call point. To send or to receive data in synchronous mode, use the following:

CommunicationManager::sendData(BYTE* data, int numberOfBytes)
CommunicationManager::receiveData(BYTE* data, int numberOfBytes)


Asynchronous Mode

In asynchronous mode, the execution of the program continues while communications take place. In this mode, the program uses hardware interrupts to keep transmitting the rest of the data until all the remaining bytes are sent. Then, a user provided method is called back by the CommunicationManager. To send and receive data in this mode, an event listener method and a scope object are required:

CommunicationManager::sendDataAsync(BYTE* data, int numberOfBytes, EventListener eventListener, Object scope)
CommunicationManager::receiveDataAsync(int numberOfBytes, EventListener eventListener, Object scope)

The transmitted data can be retrieved only inside an event listener as follows:

BYTE* data = CommunicationManager::getData(CommunicationManager::getInstance());


Bidirectional Transmission

That is not all. Our communication class supports bidirectional transmission as well when both machines send and receive the same amount of data. To do so, either in synchronous or in asynchronous mode, use one of the following:

CommunicationManager::sendAndReceiveData(BYTE* sentData, BYTE* receivedData, int numberOfBytes);
CommunicationManager::sendAndReceiveDataAsync(BYTE* data, int numberOfBytes, EventListener eventListener, Object scope);


Some More Mumbo Jumbo

For those technically inclined, part of the trick for achieving reliable communications without hackish wait loops consists in using the CCRS's CC-Rd bit as a "opened/closed channel" signal between the two systems and only managing it in the remote one, making the master VB to always wait for the remote machine to open the channel and, finally, swapping the master / remote roles at the start of the communication interrupt.

Here is the link to the implementation:

https://bitbucket.org/jorgeche/vuengine/src/master/source/hardware/CommunicationManager.c 

That's it for the engine side of things. Now, we can finally start the work on synchronizing actual game logic... Phew!


More Creators