Genesis-Plus-GX/source/docs/io.htm
ekeeke31 217ca8de3f
2007-08-10 20:34:06 +00:00

933 lines
30 KiB
HTML

<html><head><title>Sega Genesis I/O Chip and Peripherals</title></head><body>
<h2>Sega Genesis I/O Chip and Peripherals</h2>
By Charles MacDonald<br>
<a href="http://cgfm2.emuviews.com/">http://cgfm2.emuviews.com</a>
<hr>
<h4>Contents</h4>
<ul>
<li><a href="#ovr">Overview</a>
</li><li><a href="#con">Connector details</a>
</li><li><a href="#cpu">CPU interface</a>
</li><li><a href="#reg">Register list</a>
</li><li><a href="#ver">Version register</a>
</li><li><a href="#dat">Data register</a>
</li><li><a href="#dir">Control register</a>
</li><li><a href="#scr">Serial control register</a>
</li><li><a href="#txd">TxData register</a>
</li><li><a href="#rxd">RxData register</a>
</li><li><a href="#ser">Using serial communication</a>
</li><li><a href="#per">Peripheral devices</a>
<ul>
<li><a href="#md2">2-button Mark-III gamepad</a>
</li><li><a href="#md3">3-button standard gamepad</a>
</li><li><a href="#md6">Fighting Pad 6B</a><i>(incomplete)</i>
</li><li><a href="#gun">Lightguns (Sega Menacer, Konami Justifier)</a><i>(incomplete)</i>
</li><li><a href="#eat">EA 4-Way Play</a>
</li><li><a href="#mul">Sega Team Player</a><i>(incomplete)</i>
</li><li><a href="#mmo">Sega Mega Mouse</a>
</li></ul>
</li><li><a href="#msc">Miscellaneous</a>
</li><li><a href="#dis">Disclaimer</a>
</li></ul>
<a name="ovr">
</a><h4><a name="ovr">Overview</a></h4>
<p>
<a name="ovr"> The I/O chip manages three 7-bit I/O ports. It also
provides an way for the CPU to read the state of several jumpers in the
system. Later versions of the Genesis hardware have the I/O chip
integrated into some of the other custom hardware, but they all
function identically.
</a></p>
<a name="con">
</a><h4><a name="con">Connector details</a></h4>
<p>
<a name="con"> Ports A and B are male DB-9 connectors, while port C is
female. In the Genesis 2 and 3, there is no physical connector for port
C, but it can still be programmed and will respond like any other port.
(as if no gamepad was connected) Here are the pin assignments:
</a></p>
<pre><a name="con"> Pin 1 : D0
Pin 2 : D1
Pin 3 : D2
Pin 4 : D3
Pin 5 : +5V
Pin 6 : TL
Pin 7 : TH
Pin 8 : Ground
Pin 9 : TR
</a></pre>
<a name="cpu">
</a><h4><a name="cpu">CPU interface</a></h4>
<p>
<a name="cpu"> The I/O chip is connected to the 68000 and Z80. When in
Mark-III compatibility mode, the I/O chip has a different set of
registers which mimic those of the SMS, which will not be discussed
here.
<br><br>
The I/O chip is mapped to $A10000-$A1001F in the 68000/VDP/Z80 banked address space.
It is normally read and written in byte units at odd addresses.
The chip gets /LWR only, so writing to even addresses has no effect.
Reading even addresses returns the same data you'd get from an odd address.
If a word-sized write is done, the LSB is sent to the I/O chip and the MSB is ignored.
Here are some examples to illustrate these points:
</a></p><pre><a name="cpu"> ; Does nothing, byte writes to even addresses are ignored
move.b #$40, $A10002
; Returns contents of version register, reading even addresses is the same as reading odd ones
move.b $A10000, d0
; Same as writing #$40 to $A10007, the MSB is ignored
move.w #$C040, $A10006
</a></pre>
<p></p>
<a name="reg">
</a><h4><a name="reg">Register list</a></h4>
<table bgcolor="#f0f0f0" border="0" cellpadding="4">
<tbody><tr bgcolor="#cccccc">
<td>Address</td>
<td>Description</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10001</td>
<td>Version</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10003</td>
<td>Port A data</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10005</td>
<td>Port B data</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10007</td>
<td>Port C data</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10009</td>
<td>Port A control</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A1000B</td>
<td>Port B control</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A1000D</td>
<td>Port C control</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A1000F</td>
<td>Port A TxData</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10011</td>
<td>Port A RxData</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10013</td>
<td>Port A serial control</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10015</td>
<td>Port B TxData</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10017</td>
<td>Port B RxData</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A10019</td>
<td>Port B serial control</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A1001B</td>
<td>Port C TxData</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A1001D</td>
<td>Port C RxData</td>
</tr>
<tr bgcolor="#dddddd">
<td>$A1001F</td>
<td>Port C serial control</td>
</tr>
</tbody></table>
<a name="ver">
</a><h4><a name="ver">Version register</a></h4>
<p>
<a name="ver"> The version register returns several types of
information, such as a hard-coded version number, settings of the
domestic/export and PAL/NTSC jumpers, and the state of a sense pin
which the Sega CD uses. </a></p><pre><a name="ver"> D7 : Console is 1= Export (USA, Europe, etc.) 0= Domestic (Japan)
D6 : Video type is 1= PAL, 0= NTSC
D5 : Sega CD unit is 1= not present, 0= connected.
D4 : Unused (always returns zero)
D3 : Bit 3 of version number
D2 : Bit 2 of version number
D1 : Bit 1 of version number
D0 : Bit 0 of version number
</a></pre>
<a name="ver"> Bit 5 is used by the Sega CD, returning '0' when it is attached and '1' when it is not.
<br><br>
The version number is zero for the original model Genesis and MegaDrive.
All later versions of the hardware are version 1, and have additional security hardware.
<br><br>
Bits 7,6 are used in country protection checks. Some early games used
them to display English or Japanese text, so the same game program could
be used in both regions. Here's a list of settings:
</a><p></p>
<table bgcolor="#f0f0f0" border="0" cellpadding="4">
<tbody><tr bgcolor="#cccccc">
<td>Bit 7</td>
<td>Bit 6</td>
<td>TV type</td>
<td>Region</td>
<td>Comments</td>
</tr>
<tr bgcolor="#dddddd">
<td>0</td>
<td>0</td>
<td>NTSC</td>
<td>Japan, Korea, Taiwan</td>
<td>262 lines, 60 FPS</td>
</tr>
<tr bgcolor="#dddddd">
<td>0</td>
<td>1</td>
<td>PAL</td>
<td>Japan</td>
<td>No hardware actually uses this setting</td>
</tr>
<tr bgcolor="#dddddd">
<td>1</td>
<td>0</td>
<td>NTSC</td>
<td>USA, Canada</td>
<td>262 lines, 60 FPS</td>
</tr>
<tr bgcolor="#dddddd">
<td>1</td>
<td>0</td>
<td>PAL-M</td>
<td>Brazil</td>
<td>262 lines, 60 FPS</td>
</tr>
<tr bgcolor="#dddddd">
<td>1</td>
<td>1</td>
<td>PAL</td>
<td>Europe, Hong Kong</td>
<td>313 lines, 50 FPS</td>
</tr>
</tbody></table>
<p>
<a name="ver"> Early games stored a region compatibility code in their
header at offset $0001F1. This value could be the ASCII text J, U, or E
for Japan, USA or Europe. During game initialization, bits 7,6 could be
sampled and compared to the region type stored in the header. If there
is a mismatch, many games will fill the screen with a single color lock
up intentionally, or sometimes display an error message. <br><br>
Later games have a slightly more complex code.
Here's the table Sega uses to determine valid codes to use:
</a></p>
<table bgcolor="#f0f0f0" border="0" cellpadding="4">
<tbody><tr bgcolor="#cccccc">
<td colspan="2">$A10001</td>
<td>&nbsp;</td>
<td rowspan="2">Main Sales Territories</td>
<td colspan="16">Hardware Enable Code (numbers from 0 to F below)</td>
</tr>
<tr bgcolor="#cccccc">
<td>Bit 7</td>
<td>Bit 6</td>
<td>Hardware Type</td>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
<td>A</td>
<td>B</td>
<td>C</td>
<td>D</td>
<td>E</td>
<td>F</td>
</tr>
<tr bgcolor="#dddddd">
<td>0</td>
<td>0</td>
<td>Japan, NTSC</td>
<td>Japan, S. Korea, Taiwan</td>
<td>X</td>
<td>O</td>
<td>X</td>
<td>O</td>
<td>X</td>
<td>O</td>
<td>X</td>
<td>O</td>
<td>X</td>
<td>O</td>
<td>X</td>
<td>O</td>
<td>X</td>
<td>O</td>
<td>X</td>
<td>O</td>
</tr>
<tr bgcolor="#dddddd">
<td>0</td>
<td>1</td>
<td>Japan, PAL</td>
<td>&nbsp;</td>
<td>X</td>
<td>X</td>
<td>O</td>
<td>O</td>
<td>X</td>
<td>X</td>
<td>O</td>
<td>O</td>
<td>X</td>
<td>X</td>
<td>O</td>
<td>O</td>
<td>X</td>
<td>X</td>
<td>O</td>
<td>O</td>
</tr>
<tr bgcolor="#dddddd">
<td>1</td>
<td>0</td>
<td>Overseas, NTSC</td>
<td>N. America, Brazil</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
</tr>
<tr bgcolor="#dddddd">
<td>1</td>
<td>1</td>
<td>Overseas, PAL</td>
<td>Europe, Hong Kong</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
</tr>
</tbody></table>
<p>
<a name="ver"> Common uses of the new code type are ASCII values '4' for N.America, 'A' for UK, and 'B' for UK and Japan.
</a></p>
<a name="dat">
</a><h4><a name="dat">Data register</a></h4>
<p>
<a name="dat"> Writing to the data register sets the logic level of
pins configured as outputs (0= 0V, 1= +5V), and does nothing to pins
configured as inputs. Reading from the data register returns the state
of each pin. Here's a list of which bits in the data register
correspond to pins on the I/O port.
</a></p><pre><a name="dat"> D7 : Unused. This bit will return any value written to it
D6 : TH pin
D5 : TR pin
D4 : TL pin
D3 : D3 pin
D2 : D2 pin
D1 : D1 pin
D0 : D0 pin
</a></pre>
<a name="dat"> If a pin is configured as an input, reading it returns
the true logic state of whatever the pin is connected to (e.g. 0 for
ground, 1 for +5V). If nothing is connected to it, the pin returns '1',
maybe due to internal pull-up resistors.
<br><br>
If a pin is configured as an output, reading it returns the last value written to this register.
</a><p></p>
<a name="dir">
</a><h4><a name="dir">Control register</a></h4>
<p>
<a name="dir"> The control register determines which pins are inputs and outputs.
</a></p><pre><a name="dir"> D7 : /HL output control (see description)
D6 : TH pin is 1=output, 0=input
D5 : TR pin is 1=output, 0=input
D4 : TL pin is 1=output, 0=input
D3 : D3 pin is 1=output, 0=input
D2 : D2 pin is 1=output, 0=input
D1 : D1 pin is 1=output, 0=input
D0 : D0 pin is 1=output, 0=input
</a></pre>
<a name="dir"> If bit 7 of this register is set, and TH is configured as an input,
then whenever external hardware makes high to low transition on TH
the I/O chip will strobe it's /HL output pin low. This pin connects to
the VDP, which can be set up to latch the HV counter and/or cause a level 2
interrupt upon /HL going low.
</a><p></p>
<a name="scr">
</a><h4><a name="scr">Serial control register</a></h4>
<p>
<a name="scr"> The serial control register defines how a port is used for serial
communications and provides status flags to indicate the current state
of sending or receiving data.
</a></p><pre><a name="scr"> D7 : Serial baud rate bit 1
D6 : Serial baud rate bit 0
D5 : TR pin functions as 1= serial input pin, 0= normal
D4 : TL pin functions as 1= serial output pin, 0= normal
D3 : 1= Make I/O chip strobe /HL low when a byte has been received, 0= Do nothing
D2 : 1= Error receiving current byte, 0= No error
D1 : 1= Rxd buffer is ready to read, 0= Rxd buffer isn't ready
D0 : 1= Txd buffer is full, 0= Can write to Txd buffer
</a></pre>
<a name="scr"> The available baud rates are:
</a><p></p>
<table bgcolor="#f0f0f0" border="0" cellpadding="4">
<tbody><tr bgcolor="#cccccc">
<td>D7</td>
<td>D6</td>
<td>Baud rate</td>
</tr>
<tr bgcolor="#dddddd">
<td>0</td>
<td>0</td>
<td>4800 bps</td>
</tr>
<tr bgcolor="#dddddd">
<td>0</td>
<td>1</td>
<td>2400 bps</td>
</tr>
<tr bgcolor="#dddddd">
<td>1</td>
<td>0</td>
<td>1200 bps</td>
</tr>
<tr bgcolor="#dddddd">
<td>1</td>
<td>1</td>
<td>300 bps</td>
</tr>
</tbody></table>
<p>
<a name="scr"> When doing serial communication, TL and/or TR can be used for sending
and receiving data. During this time the data and control registers
have no effect for whichever pin(s) are in serial mode. The rest of the
pins in the same port function normally.
<br><br> The intended use of bit 3 is to also have the VDP set up to
enable level 2 interrupts when /HL goes low. This way, when the I/O
chip receives a byte through the TR pin, if this bit is set then it
will strobe /HL low and cause an interrupt. So receiving data serially
can either be accomplished through manual polling or be interrupt
driven.
<br><br>
Bits 2-0 are read-only status flags, the rest of the bits in this register can be read and written.
</a></p>
<a name="txd">
</a><h4><a name="txd">TxData register</a></h4>
<p>
<a name="txd"> Writing a byte to this register will make the I/O chip
output the data serially through the TL pin, providing it was
configured for serial mode. You should poll bit 0 of the serial control
register until the bit returns 0 to ensure the previously written byte
has been sent and the TxData buffer is empty.
</a></p>
<a name="rxd">
</a><h4><a name="rxd">RxData register</a></h4>
<p>
<a name="rxd"> Reading from this register returns the last byte
received serially through the TR pin. You should check bits 3,2 of the
serial control register to ensure that the RxData input buffer is full
and that there were no errors in receiving the byte (which would then
be invalid).
</a></p>
<a name="ser">
</a><h4><a name="ser">Using serial communication</a></h4>
<p>
<a name="ser"> When in serial mode, the I/O ports output TTL-level
signals. You need something like a MAX232 line driver to convert these
to RS-232 compatible signals for interfacing with (for example) a PC.
<br><br> If you just want to do experiments on the serial ports
themselves, you can use a null modem cable with the TL/TR wires
switched around to connect port A to B. I used this for testing the
serial capabilities while writing this document. Be sure to disconnect
the +5V line as well.
</a></p>
<a name="per">
</a><h2><a name="per">Peripheral devices</a><hr></h2>
<ul>
<li><a href="#md2">2-button Mark-III gamepad</a>
</li><li><a href="#md3">3-button standard gamepad</a>
</li><li><a href="#md6">Fighting Pad 6B</a>
</li><li><a href="#gun">Lightguns (Sega Menacer, Konami Justifier)</a>
</li><li><a href="#eat">EA 4-Way Play</a>
</li><li><a href="#mul">Sega Team Player</a>
</li><li><a href="#mmo">Sega Mega Mouse</a>
</li></ul>
<a name="md2">
</a><h4><a name="md2">2-button Mark-III gamepad</a></h4>
<p>
<a name="md2"> This controller has a 4-way direction pad, and two buttons (2 and 1).
Here's a description of how the controller interfaces with an I/O port:
</a></p><pre><a name="md2"> D6 : (TH) Not used
D5 : (TR) Button 2
D4 : (TL) Button 1
D3 : (D3) D-pad Right
D2 : (D2) D-pad Left
D1 : (D1) D-pad Down
D0 : (D0) D-pad Up
</a></pre>
<a name="md2"> All buttons are active-low logic, so they return '0' when pressed and '1' when released.
</a><p></p>
<a name="md3">
</a><h4><a name="md3">3-button standard gamepad</a></h4>
<p>
<a name="md3"> This controller has a 4-way direction pad, and four buttons (Start, A, B, C).
It uses a multiplexer that selects 1 of 2 inputs using TH, and routes buttons Start or C to TR, and B or A to TL.
<br><br>
Here's a description of how the controller interfaces with an I/O port:
</a></p><pre><a name="md3"> When TH=0 When TH=1
D6 : (TH) 0 1
D5 : (TR) Start button Button C
D4 : (TL) Button A Button B
D3 : (D3) 0 D-pad Right
D2 : (D2) 0 D-pad Left
D1 : (D1) D-pad Down D-pad Down
D0 : (D0) D-pad Up D-pad Up
</a></pre>
<a name="md3"> All buttons are active-low logic, so they return '0' when pressed and '1' when released.
<br><br> You need a small delay between changing TH and reading the
button state back, as the multiplexer takes some time in switching
inputs. I've found about four NOPs provides a reasonable delay.
<br><br>
Here's some example code to read a 3-button gamepad:
</a><p></p>
<table bgcolor="#e0e0e0" width="70%"><tbody><tr><td><pre>; Returns D0 with the button states: 'SACBRLDU'
_read_joypad:
move.l d1, -(a7)
move.b #$40, $A10003
nop
nop
move.b $A10003, d0
andi.b #$3F, d0
move.b #$00, $A10003
nop
nop
move.b $A10003, d1
lsl.b #2, d1
andi.b #$C0, d1
or.b d1, d0
eori.b #$FF, d0
move.l (a7)+, d1
rts
</pre></td></tr></tbody></table>
<a name="md6">
</a><h4><a name="md6">Fighting Pad 6B</a></h4>
<p>
<a name="md6"> Information coming soon.
</a></p>
<a name="gun">
</a><h4><a name="gun">Lightguns (Sega Menacer, Konami Justifier)</a></h4>
<p>
<a name="gun"> Information coming soon.
</a></p>
<a name="eat">
</a><h4><a name="eat">EA 4-Way Play</a></h4>
<p>
<a name="eat"> The EA 4-Way Play plugs into ports A and B, and allows up to four standard Genesis controllers to be connected at once.
<br><br> I've determined how the multitap works by examining the
joystick reading code from NHL '95 and trying the same routine on a
new-style Sega Team Player in 'EXTRA' mode. That said, the actual EA
4-Way Play could have some differences that Sega's compatibility mode
doesn't take care of.
<br><br> To detect the multitap, set CTRL1 to 0x40, CTRL2 to 0x7F and
DATA2 to $7C. Reading the lower 2 bits of DATA1 will return zero if the
multitap is present. Usually these bits return 0x03 if there is no tap,
no controller, or the Sega Team Player isn't in EXTRA mode, but this
could be a behavior specific to the Team Player.
<br><br>
To read the pads, write 0x0C, 0x1C, 0x2C, or 0x3C to DATA2 to select the controller in port A, B, C, or D.
You can then use DATA1/CTRL1 to read the pad state just like polling a regular 3-button pad in port A.
<br><br>
Here's some example code to use the EA 4-Way Play:
</a></p>
<table bgcolor="#e0e0e0" width="70%"><tbody><tr><td><pre>; Returns D0 == 0 if the multitap is present, or D0 != 0 if it isn't
_detect_4wayplay:
move.b #$40, $A10009
nop
move.b #$7F, $A1000B
nop
move.b #$7C, $A10005
nop
moveq #0, d0
move.b $A10003, d0
andi.b #$03, d0
rts
; Returns the state of all four 3-button gamepads in D0
_read_4wayplay:
move.l d1-d3/a0, -(a7)
lea $A10000, a0
move.l #$0C1C2C3C, d2
moveq #$03, d3
poll: move.b d2, $05(a0)
nop
nop
move.b #$40, $03(a0)
nop
nop
move.b $A10003, d0
andi.b #$3F, d0
move.b #$00, $03(a0)
nop
nop
move.b $03(a0), d1
lsl.b #2, d1
andi.b #$C0, d1
or.b d1, d0
lsl.l #8, d0
lsr.l #8, d2
dbra d3, poll
eori.l #-1, d0
move.l (a7)+, d2-d3/a0
rts
</pre></td></tr></tbody></table>
<a name="mul">
</a><h4><a name="mul">Sega Team Player</a></h4>
<p>
<a name="mul"> The Team Player is a multitap device that allows four peripherals to be connected to the Genesis at one time.
It has a mode select switch with several settings:
</a></p><pre><a name="mul"> EXTRA - All four ports are enabled. This is the setting used by
EA 4-Way Play compatible games.
A - Routes the peripheral in port A to port A of the Genesis.
B - Routes the peripheral in port B to port A of the Genesis.
C - Routes the peripheral in port C to port A of the Genesis.
D - Routes the peripheral in port D to port A of the Genesis.
MULTI - All four ports are enabled. This is the setting used by
Team Player compatible games.
</a></pre>
<a name="mul"> Sega made two versions of the Team Player. The first one
was not compatible with the EA 4-Way Play and only had one cable to
connect it to port A. The second one added the "EXTRA" setting for EA
4-Way Play compatibility and provides a second cable to connect it to
port B as well. Both seem to function identically with the exception of
EXTRA mode.
<br><br>
I don't have any programming information for this device.
</a><p></p>
<a name="mmo">
</a><h4><a name="mmo">Sega Mega Mouse</a></h4>
<p>
<a name="mmo"> This is a three button mouse (left, middle, right) with an extra button
(Start) located near the thumb position. It uses a PIC16C54 microcontroller
which manages the buttons and position tracking.
<br><br>
The Sega Mega Mouse that is distributed in North America is incompatible with the European version of Populous 2.
The mouse functions normally but has Y axis inverted so up is down and vice-versa.
It may have been designed for the Japanese Mega Drive mouse, which is a <b>different</b> product with 2 buttons and unique physical appearance.
<br><br>
The protocol works as follows:
TH and TR are outputs which tell the microcontroller to stop or start a data transfer, and to acknowledge received data.
TL is an input which returns a busy flag for the microcontroller.
D3-D0 are inputs that return the data.
Here's a table showing the communication process:
</a></p>
<table bgcolor="#f0f0f0" border="0" cellpadding="4">
<tbody><tr bgcolor="#cccccc">
<td>Write</td>
<td>TH</td>
<td>TR</td>
<td>TL</td>
<td>D3</td>
<td>D2</td>
<td>D1</td>
<td>D0</td>
<td>Description</td>
</tr>
<tr bgcolor="#dddddd">
<td>$60</td>
<td bgcolor="#bbbbbb">1</td>
<td bgcolor="#bbbbbb">1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>Request data</td>
</tr>
<tr bgcolor="#dddddd">
<td>$20</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">1</td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>ID #0 ($0)</td>
</tr>
<tr bgcolor="#dddddd">
<td>$00</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>ID #1 ($B)</td>
</tr>
<tr bgcolor="#dddddd">
<td>$20</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>ID #2 ($F)</td>
</tr>
<tr bgcolor="#dddddd">
<td>$00</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">0</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>ID #3 ($F)</td>
</tr>
<tr bgcolor="#dddddd">
<td>$20</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">1</td>
<td>0</td>
<td>Y Over</td>
<td>X Over</td>
<td>Y Sign</td>
<td>X Sign</td>
<td>Axis sign and overflow</td>
</tr>
<tr bgcolor="#dddddd">
<td>$00</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">0</td>
<td>1</td>
<td>Start</td>
<td>Middle</td>
<td>Right</td>
<td>Left</td>
<td>Button state</td>
</tr>
<tr bgcolor="#dddddd">
<td>$20</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">1</td>
<td>0</td>
<td>X7</td>
<td>X6</td>
<td>X5</td>
<td>X4</td>
<td>X axis MSN</td>
</tr>
<tr bgcolor="#dddddd">
<td>$00</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">0</td>
<td>1</td>
<td>X3</td>
<td>X2</td>
<td>X1</td>
<td>X0</td>
<td>X axis LSN</td>
</tr>
<tr bgcolor="#dddddd">
<td>$20</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">1</td>
<td>0</td>
<td>Y7</td>
<td>Y6</td>
<td>Y5</td>
<td>Y4</td>
<td>Y axis MSN</td>
</tr>
<tr bgcolor="#dddddd">
<td>$00</td>
<td bgcolor="#bbbbbb">0</td>
<td bgcolor="#bbbbbb">0</td>
<td>1</td>
<td>Y3</td>
<td>Y2</td>
<td>Y1</td>
<td>Y0</td>
<td>Y axis LSN</td>
</tr>
</tbody></table>
<p>
<a name="mmo"> Write #$60 when you are done polling to stop the data
transfer. If you continue to poll the mouse after collecting all the
data by writing $20 / $00, the Y axis LSN will always be returned. Sega
advises polling beyond this point will make the mouse behave
abnormally. It's possible that the PIC code in some versions of the
Mega Mouse may have problems if the poll sequence is too long.
<br><br>
The X/Y overflow flags are supposed to be set if the mouse is moved over a distance greater than can be measured.
I can't get them to become set, maybe the mouse supports a fairly wide range of movement.
<br><br> You need a considerable delay between writing new values to
TH/TR. I think the intention is to poll TL until the microcontroller
returns 'not busy', but I can't get this to work reliably. Sega's mouse
reading code also has a timeout when checking TL which would indicate
it may get stuck in a certain state.
<br><br>
All buttons (start, left, middle, right) are active-high logic, so they return '1' when pressed and '0' when released.
</a></p>
<a name="msc">
</a><h4><a name="msc">Miscellaneous</a></h4>
<p>
<a name="msc"> After power-up, the default state of the I/O chip are as follows:
</a></p><pre><a name="msc"> $A10001 = $80 (Bits 7,6,5 depend on the domestic/export, PAL/NTSC jumpers and having a Sega CD or not)
$A10003 = $7F
$A10005 = $7F
$A10007 = $7F
$A10009 = $00
$A1000B = $00
$A1000D = $00
$A1000F = $FF
$A10011 = $00
$A10013 = $00
$A10015 = $FF
$A10017 = $00
$A10019 = $00
$A1001B = $FB
$A1001D = $00
$A1001F = $00
</a></pre>
<p></p>
<a name="dis">
</a><h4><a name="dis">Disclaimer</a></h4>
<pre><a name="dis"> If you use any information from this document, please credit me
(Charles MacDonald) and optionally provide a link to my webpage
(http://cgfm2.emuviews.com/) so interested parties can access it.
The credit text should be present in the accompanying documentation of
whatever project which used the information, or even in the program
itself (e.g. an about box)
Regarding distribution, you cannot put this document on another
website, nor link directly to it.
</a></pre>
<hr>
</body></html>