mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-11-13 22:35:10 +01:00
933 lines
30 KiB
HTML
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> </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> </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>
|