EA multitap
Called "4 Way Play", this is Electronic Arts' take on a multitap on the Mega Drive. Originally supported mostly by their games but eventually by other later games (along with Sega's own multitap). This is the easiest of the two to use, albeit only supports controllers and it takes up both ports (so it can't be used with anything else at the same time).
The protocol here is also supported by some Sega multitaps by configuring them into EXTRA mode.
Setting up the multitap
The EA multitap uses up both I/O ports: the first port is used to read the controllers, while the second port is used to select which controller to read. The ports should be configured as follows:
IoCtrl1
should be$40
IoCtrl2
should be$7F
IoData1
should be$40
Writing to the second port (IoData2
) makes different data
show up in the first port (IoData1
), so let's define the
different values the multitap knows about:
EAMULTI_1P: equ $0C ; Controller #1
EAMULTI_2P: equ $1C ; Controller #2
EAMULTI_3P: equ $2C ; Controller #3
EAMULTI_4P: equ $3C ; Controller #4
EAMULTI_ID: equ $7C ; Multitap ID
Probably the best way to check if the multitap is there (after the above
has been setup to try it) is by doing something like this (you should
burn a few cycles after each write to give it time to work, e.g. three
or four NOP
will probably do):
- Write
EAMULTI_1P
toIoData2
- Read from
IoData1
- Write
EAMULTI_ID
toIoData2
- Read from
IoData1
Then look at bits 1-0 from each read: if they were 00
in
the second read but something else in the first, chances are there's
an EA multitap connected.
Remember to keep the Z80 out of the way while accessing I/O ports.
; Prevent the Z80 from touching
; the 68000 bus while we're busy
; with the I/O ports
FastPauseZ80
; Set up ports to check for
; EA multitap
move.b #$40, (IoCtrl1)
move.b #$7F, (IoCtrl2)
move.b #$40, (IoData1)
; Read from controller #1
move.b #EAMULTI_1P, (IoData2)
nop
nop
moveq #%0000011, d0
and.b (IoData1), d0
; Read from multitap ID
move.b #EAMULTI_ID, (IoData2)
nop
nop
moveq #%0000011, d1
and.b (IoData1), d1
; We can let the Z80 run now
ResumeZ80
; Check if both are valid
tst.b d0
beq @NotEA
tst.b d1
bne @NotEA
; EA multitap present...
Reading the controllers
The EA multitap is a glorified multiplexer. TH (bit 6) is shared among all controllers, while port 2 is used to pick which controller is being read from bits 5-0 in port 1.
So, go check how to read a controller normally
(3-button or 6-button), except that instead of writing to the port and
reading back from it, you do it this way (waiting a handful of NOP
or so after every write to IoData2
as earlier):
- Write
$40
/$00
toIoData1
- Write
EAMULTI_1P
toIoData2
- Read back from
IoData1
(reads controller 1) - Write
EAMULTI_2P
toIoData2
- Read back from
IoData1
(reads controller 2) - Write
EAMULTI_3P
toIoData2
- Read back from
IoData1
(reads controller 3) - Write
EAMULTI_4P
toIoData2
- Read back from
IoData1
(reads controller 4)
Maybe the easiest way is to blindly take all the reads and put them into a buffer, then read the values off the buffer to figure out what the controller is (toggling a 3-button controller too often won't hurt).
ReadEa:
lea (IoData1), a0
lea (IoData2), a1
lea (EaBuffer), a2
; Keep the Z80 out of the way
; while we touch the I/O ports
FastPauseZ80
; Read all the controller values
; (see below for how many times)
moveq #@NUM_STEPS-1, d0
moveq #$40, d1
@Loop:
; Toggle select line
move.b d1, (a0)
; Read controller #1
move.b #EAMULTI_1P, (a1)
nop
nop
nop
move.b (a0), (a2)+
; Read controller #2
move.b #EAMULTI_2P, (a1)
nop
nop
nop
move.b (a0), (a2)+
; Read controller #3
move.b #EAMULTI_3P, (a1)
nop
nop
nop
move.b (a0), (a2)+
; Read controller #4
move.b #EAMULTI_4P, (a1)
nop
nop
nop
move.b (a0), (a2)+
; Onto next value
; Clever trick here: d1 will swap
; between $40 and $00 (remember
; we used moveq earlier!)
swap d1
dbf d0, @Loop
; Z80 can run again now
ResumeZ80
; We're done
rts
; The number of times to loop
; Use 2 if you only need 3-button pads
; Use 7 if you want 6-button pads too
; Buffer size will be @NUM_STEPS*4
@NUM_STEPS: equ 7
Peripheral ID in ROM header
Multitap support in the ROM header is specified by adding "4
"
in the devices field (the one at
$000190
). Since it doesn't specify which multitap
is supported, it's a good idea to consider supporting the Sega multitap as
well.
Support for the extra buttons in the 6-button controller ("6
")
should also be specified if supported. On the other hand, if the game
simply ignores them, you shouldn't add it.