XBAND, Mega Net 2, and Mega Drive Keyboards

Ask anything your want about Megadrive/Genesis programming.

Moderator: BigEvilCorporation

GeoffLedak
Interested
Posts: 16
Joined: Thu Jan 05, 2017 10:14 pm

Re: XBAND, Mega Net 2, and Mega Drive Keyboards

Post by GeoffLedak » Sun Jan 29, 2017 8:52 am

Sik wrote:And yeah I had gone over the keyboard code long ago, it relies on an adapter to connect an AT keyboard to the console:

Code: Select all

REQUIREMENTS:

   - TH and TR are always output
   - TL is always input
   - Other bits depend on action

HANDSHAKE:

   - Set TH and TR high ($60)
   - Wait a bit (two NOPs)
   - Read bits 3-0 (should be %0011)
   
   - Set TH low, TR high ($20)
   - Read bits 3-0 (should become %1100)
   - Keep reading if still not %1100
   
   - Set TH and TR low ($00)
   - Wait until TL goes low
   - Read bits 3-0 (should be %0110)

READING:

   - Do handshake
   - Make bits 3-0 input lines
   
   - Set TH low, TR high ($20)
   - Wait until TL goes high
   - Read bits 3-0 (count)
   
   - Do this "count" times:
      - Set TH low and TR ($00)
      - Wait until TL goes low
      - Read bits 3-0 (high nibble of byte)
      
      - Set TH low, TR high ($20)
      - Wait until TL goes high
      - Read bits 3-0 (low nibble of byte)
   - (loop end)
   
   - Set TH and TR high ($60)
   
WRITING:

   - Do handshake
   - Make bits 3-0 output lines
   
   - Set bits 3-0 to %0000
   - Set TH low, TR high ($20)
   - Wait until TL goes high
   
   - Set bits 3-0 to %0001 (2)
   - Set TH and TR low ($00)
   - Wait until TL goes low
   
   - Set bits 3-0 to %0000
   - Set TH low, TR high ($20)
   - Wait until TL goes high
   
   - Set bits 3-0 to %0000
   - Set TH and TR low ($00)
   - Wait until TL goes low
   
   - Set bits 3-0 to high nibble of byte to write
   - Set TH low, TR high ($20)
   - Wait until TL goes high
   
   - Set bits 3-0 to low nibble of byte to write
   - Set TH and TR low ($00)
   - Wait until TL goes low
   
   - Make bits 3-0 input lines (or set them to %1111?)
   - Set TH and TR high ($60)

ABORT:

   - Set TH high, TR low ($40)
   - Wait a while
   - Set TH and TR high ($60)

NOTES:

   - Keyboard seems to use the same scancodes and commands as AT keyboards
   - Command $FF (no arguments) initializes the keyboard
   - Command $ED (one byte arg.) sets the keyboard leds
I'm curious where you got those values that you pass to the Genesis during what you refer to as the handshake (%0011, %1100, and %0110). Shouldn't there be 4 nibbles instead of 3? The FindESKeyboard() function reads a total of 4 nibbles and then checks if they are equal to a variable called 'kbID'. The value of kbID is assigned using the REFGLOBAL( controls, keyboardID ) function which isn't included in the leaked source code.

GeoffLedak
Interested
Posts: 16
Joined: Thu Jan 05, 2017 10:14 pm

Re: XBAND, Mega Net 2, and Mega Drive Keyboards

Post by GeoffLedak » Mon Jan 30, 2017 12:06 am

I think I just found what I was looking for.

/Database/DBConstants.h contains this:

/* Hardware Keyboard ID */
kESKeyboardID = 0x030C0609,

GeoffLedak
Interested
Posts: 16
Joined: Thu Jan 05, 2017 10:14 pm

Re: XBAND, Mega Net 2, and Mega Drive Keyboards

Post by GeoffLedak » Mon Jan 30, 2017 8:59 am

I've been continuing work on my project of trying to use an Arduino Uno to simulate the xband keyboard. I bought an xband modem on ebay and I have some pins from the Arduino connected to a DB9 connector which is plugged into the Genesis. So far it's been quite an enlightening learning project (I've never done much with hardware and the concept of creating an empty do{ } while loop while waiting for pins to change was completely foreign to me).

After looking through the rom source code some more and reading about how the Sega Team Player adapter works, I've extrapolated the following:

- Specific types of communication between the Genesis and the keyboard are broken up into different types of transactions.
- TH is held low throughout the duration of a transaction.
- A transaction that communicates with the keyboard can be one of the three following types: Find, Write (to the keyboard, which includes 'almost' a complete Find transaction at the beginning), or Read (from the keyboard, which includes a complete Find transaction at the beginning).

The Genesis performs a Find transaction once every 2 seconds (see the _ControllerVBL and FindESKeyboard functions in controls.c)
A Find transaction consists of the following:
- When TH and TR are high, the keyboard should be broadcasting the first nibble of what the rom source code refers to as an identifying ID (%0011).
- The Genesis reads this nibble and then sets TH low to begin a transaction. (TH is held low for the rest of the transaction).
- The keyboard responds with the 2nd nibble of the identifying ID (%1100).
- The Genesis reads this nibble and then sets TR low, the keyboard responds with the 3rd nibble of the identifying ID (%0110), and the keyboard sets TL low.
- The Genesis reads this nibble and sets TR high, the keyboard responds with the 4th nibble of the identifying ID (%1001), and the keyboard sets TL high.
= The Genesis reads this nibble, and then aborts the transaction by setting TH high).
- The Genesis checks to see if the 4 nibbles it received match the kbID variable (kbID == 0x030C0609 per /Database/DBConstants.h) (note that each nibble is stored in a separate byte. The upper nibble of each byte is zero, and the lower nibble contains the value sent by the keyboard). 0x030C0609 = %0000 0011 0000 1100 0000 0110 0000 1001
- If kbID == 0x030C0609 the FindESKeyboard function returns true, otherwise it returns false.


A Read transaction (handled by the function ReadESKeyboard in controls.c) begins with everything described above, except the Genesis doesn't abort the transaction by setting TH high. After it confirms that kbID == 0x030C0609, it continues with the transaction.

The rest of the transaction consists of a common pattern (see the function GetHandshakeNibblePort2 in controls.c):

- The Genesis sets TR low. The keyboard will write a nibble of data to the data pins, and then set TL low to indicate that the data is ready to be read.
- The Genesis reads the data, and if it wants another nibble, it will set TR high. The keyboard will write another nibble of data to the data pins, and then set TL high to indicate that the data is ready to be read.
- The Genesis reads the data, and if it wants another nibble, it will set TR low. The keyboard will write another nibble of data to the data pins, and then set TL low to indicate that the data is ready to be read.
- The Genesis reads the data, and if it wants another nibble, it will set TR high. The keyboard will...

During this period, the keyboard will first send a nibble which indicates the total number of bytes it's about to send. Next it should send a data type byte (2 nibbles). If sending keycode data, both of these nibbles should have a value of zero (#define kESKeycodeData 0 in controls.c)

Next, the keyboard should send AT style scancodes. For instance, if the letter 'a' was pressed, the keyboard should send the byte 1C. If the letter 'a' was released, the keyboard should send two bytes, F0 followed by 1C (AT scancodes available here).

Note: Total number of bytes should include the data type byte


When I wrote above that a Write transaction includes 'almost' a complete Find transaction, I was referring to this:

FindESKeyboard:

Code: Select all

...
readScan++;							

hshkState = 0;										// start flipping TR
*readScan++ = GetHandshakeNibblePort2(&hshkState);	// 3rd nybble = local ID
*readScan = GetHandshakeNibblePort2(&hshkState);	// 4th nybble = local ID

*reg |= kTH;										// abort the transaction
	
for ( timeout = 0; timeout != 50; timeout++ );		// spin a bit

*reg = kTH + kTR;									// make sure we leave with TH & TR hi
	
if ( *(ULong *) readBuf == kbID )					// found a good Eric Smith Keyboard
	return ( true );
else
	return ( false );
...
ReadESKeyboard:

Code: Select all

...
readScan++;							
	
hshkState = 0;											// start flipping TR
*readScan++ = GetHandshakeNibblePort2(&hshkState);		// 3rd nybble = local ID
*readScan++ = GetHandshakeNibblePort2(&hshkState);		// 4th nybble = local ID

if ( *(ULong *) readBuf == kbID )						// found a good Eric Smith Keyboard
{
	len = GetHandshakeNibblePort2(&hshkState);			// 5th nybble = BYTE count, 0-15
	
	if (len)
...
WriteESKeyboard:

Code: Select all

...
readScan++;							
	
hshkState = 0;											// start flipping TR
*readScan++ = GetHandshakeNibblePort2(&hshkState);		// 3rd nybble = local ID


if ( (*(ULong *) readBuf & 0xFFFFFF00) == (kbID & 0xFFFFFF00) )		// found a good Eric Smith Keyboard?
{
	*reg &= 0xF0;										// ensure data lines are 0
	*(char *)kCtl2 |= kDataLines;						// 4 data lines are outputs now

	REFGLOBAL( controls, cmdTail )++;
	REFGLOBAL( controls, cmdTail ) &= kKeybdCmdStatusFifoMask;
	byteToSend = REFGLOBAL( controls, cmdBuf )[REFGLOBAL( controls, cmdTail )];

	PutHandshakeNibblePort2(&hshkState, 0);				// 4th nybble = 0 ==> I'm talking to him
	PutHandshakeNibblePort2(&hshkState, 2);				// 2 bytes follow; type & data
...

Notice that in the WriteESKeyboard function, the last nibble of the keyboard ID is ignored / not read.

Also regarding the WriteESKeyboard function, something I don't understand is how the keyboard knows that the Genesis is going to start sending information through the data lines and that it should begin treating them as inputs instead of outputs.


This project of trying to simulate the keyboard with an Arduino is proving to be quite difficult and I'm not sure if it's going to be possible. It's kind of a shot in the dark without having any debug information from the console / modem.

Here is what I've come up with so far for an Arduino sketch if anyone's interested. The sendScancodes() function is currently commented out everywhere and not being called.

The println() statements at the bottom of the identifyKeyboard() function are almost doing what I expect them to, but the results are inverted (here's a video). I was expecting "continuing with transaction" to be printed about 15 times a second, and "transaction aborted" to be printed every 2 seconds.

Just the fact that the timing I'm seeing with the println statements seems to match what is described at the top of _ControllerVBL is somewhat promising.

Code: Select all

void	_ControllerVBL( void )
{
register short	whichRead = 0;		// +1 read controls, -1 sample controller types
register long	newPhase;

	// to avoid sucking down too much CPU, we do a few things based on
	// a phase counter.  We read the controls 15 times per second (instead
	// of 60), and every two seconds, we replace a controller read with
	// a controller-type sample.  This allows the user to change controllers
	// and we'll figure it out.
	
	newPhase = REFGLOBAL( controls, samplePhase ) - 1;
	if (newPhase < 0)	{
...

GeoffLedak
Interested
Posts: 16
Joined: Thu Jan 05, 2017 10:14 pm

Re: XBAND, Mega Net 2, and Mega Drive Keyboards

Post by GeoffLedak » Fri Feb 03, 2017 3:15 pm

I just thought I'd add that the keyboard definitely made it out of the prototype stage and was available for sale back in the day. There's a guy in the XBAND facebook group who posted some pictures of his Genesis keyboard. I sent him a message asking some questions about it and he says that he ordered it directly from Catapult Entertainment back when the service was still up and running. Apparently the keyboards show up for sale on eBay from time to time.

MrTamk1s
Very interested
Posts: 75
Joined: Sun Jan 04, 2015 10:27 pm
Location: Pennsylvania
Contact:

Re: XBAND, Mega Net 2, and Mega Drive Keyboards

Post by MrTamk1s » Sat Feb 11, 2017 4:26 pm

Natsumi wrote:So, based on the knowledge I have atm, the plan of action is as follows:
*Compile this source code and compare it with available dumps of XBAND
After looking through the source, it doesn't appear to be complete. For instance, GameLib/controls.c imports a header file called "SegaOS.h" which doesn't appear to be included with the source release. I don't think you'll be able to compile your own complete ROM, but we should have everything we need regarding the keyboard in controls.c
You should double check the official XBAND source code. I don't think it has "SegaOS.h", but it has other pertinent info about the XBAND. It contains source code for both SNES and Genesis.
SGDK homebrew dev and Unity3D Indie dev.
Sega does what Nintendont!

GeoffLedak
Interested
Posts: 16
Joined: Thu Jan 05, 2017 10:14 pm

Re: XBAND, Mega Net 2, and Mega Drive Keyboards

Post by GeoffLedak » Mon Feb 20, 2017 5:03 am

The keyboard was advertised via XBAND news and was available to order by phone directly from Catapult Entertainment.

Image

Image

Image

Image

Image

Image

Image

Image

Post Reply